diff --git a/drivers/net/wireless/marvell/mwifiex/11h.c b/drivers/net/wireless/marvell/mwifiex/11h.c
index 43dccd5b0291f98fcf184822d8a50374c142fc9c..d29e7dfe51fc478eae54afc5f2c7f09a79f249f8 100644
--- a/drivers/net/wireless/marvell/mwifiex/11h.c
+++ b/drivers/net/wireless/marvell/mwifiex/11h.c
@@ -266,7 +266,7 @@ int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv,
 		mwifiex_dbg(priv->adapter, ERROR,
 			    "Failed to stop CAC in FW\n");
 	cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef,
-			     GFP_KERNEL);
+			     0, GFP_KERNEL);
 	mwifiex_dbg(priv->adapter, MSG, "regdomain: %d\n",
 		    rdr_event->reg_domain);
 	mwifiex_dbg(priv->adapter, MSG, "radar detection type: %d\n",
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index a80516fd65c8c12f658346be54fee320b5c513b7..7bdb1ca7a6286cf85fa8800dd6ef3e4673001535 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -2333,6 +2333,12 @@ enum ieee80211_sa_query_action {
 #define WLAN_OUI_TYPE_MICROSOFT_WMM	2
 #define WLAN_OUI_TYPE_MICROSOFT_WPS	4
 
+#define WLAN_OUI_BROADCOM 			0x00904c /* Broadcom (Epigram) */
+#define WLAN_VENDOR_VHT_TYPE		0x04
+#define WLAN_VENDOR_VHT_SUBTYPE		0x08
+#define WLAN_VENDOR_VHT_SUBTYPE2	0x00
+#define WLAN_VENDOR_VHT_SUBTYPE3	0x18
+
 /*
  * WMM/802.11e Tspec Element
  */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 66167138120a2d2108e88ec23e5184ac55ed37a1..fbd0923aff8e26d2def1279813ba2798c59d735d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -769,6 +769,7 @@ struct cfg80211_csa_settings {
 	bool radar_required;
 	bool block_tx;
 	u8 count;
+	u8 sb_dfs_bw; /* from enum nl80211_sb_dfs_bw */
 };
 
 /**
@@ -825,6 +826,10 @@ enum station_parameters_apply_mask {
  * @opmode_notif: operating mode field from Operating Mode Notification
  * @opmode_notif_used: information if operating mode field is used
  * @support_p2p_ps: information if station supports P2P PS mechanism
+ * @resp: last association response frame
+ *	(or NULL for no change)
+ * @resp_len: length of last association response
+ * @rssi: received signal strength indicator
  */
 struct station_parameters {
 	const u8 *supported_rates;
@@ -852,6 +857,9 @@ struct station_parameters {
 	u8 opmode_notif;
 	bool opmode_notif_used;
 	int support_p2p_ps;
+	u8 *resp;
+	size_t resp_len;
+	u32 rssi;
 };
 
 /**
@@ -1071,6 +1079,7 @@ struct cfg80211_tid_stats {
  * @nonpeer_pm: non-peer mesh STA power save mode
  * @expected_throughput: expected throughput in kbps (including 802.11 headers)
  *	towards this station.
+ * @max_rssi: maximum received signal strength indicator
  * @rx_beacon: number of beacons received from this peer
  * @rx_beacon_signal_avg: signal strength average (in dBm) for beacons received
  *	from this peer
@@ -1116,6 +1125,7 @@ struct station_info {
 	enum nl80211_mesh_power_mode nonpeer_pm;
 
 	u32 expected_throughput;
+	u32 max_rssi;
 
 	u64 rx_beacon;
 	u64 rx_duration;
@@ -1814,6 +1824,7 @@ enum cfg80211_assoc_req_flags {
  * @ht_capa_mask:  The bits of ht_capa which are to be used.
  * @vht_capa: VHT capability override
  * @vht_capa_mask: VHT capability mask indicating which fields to use
+ * @vendor_wds: use WDS vendor specific capabilities
  */
 struct cfg80211_assoc_request {
 	struct cfg80211_bss *bss;
@@ -1825,6 +1836,7 @@ struct cfg80211_assoc_request {
 	struct ieee80211_ht_cap ht_capa;
 	struct ieee80211_ht_cap ht_capa_mask;
 	struct ieee80211_vht_cap vht_capa, vht_capa_mask;
+	int vendor_wds;
 };
 
 /**
@@ -3056,6 +3068,7 @@ enum wiphy_flags {
 	WIPHY_FLAG_SUPPORTS_5_10_MHZ		= BIT(22),
 	WIPHY_FLAG_HAS_CHANNEL_SWITCH		= BIT(23),
 	WIPHY_FLAG_HAS_STATIC_WEP		= BIT(24),
+	WIPHY_FLAG_DISABLE_11D_HINT			= BIT(31),
 };
 
 /**
@@ -3819,6 +3832,9 @@ struct wireless_dev {
 
 	u32 owner_nlportid;
 
+	u8 *vendor_events_filter;
+	u8 vendor_events_filter_len;
+
 #ifdef CONFIG_CFG80211_WEXT
 	/* wext data */
 	struct {
@@ -5153,6 +5169,9 @@ void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
 			  enum nl80211_connect_failed_reason reason,
 			  gfp_t gfp);
 
+int cfg80211_rx_vendor_specific_mgmt(struct wireless_dev *wdev, int freq,
+		      const u8 *buf, size_t len, gfp_t gfp);
+
 /**
  * cfg80211_rx_mgmt - notification of received, unprocessed management frame
  * @wdev: wireless device receiving the frame
@@ -5243,12 +5262,13 @@ void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp);
  * cfg80211_radar_event - radar detection event
  * @wiphy: the wiphy
  * @chandef: chandef for the current channel
+ * @radar_bit_map: Bit map of channels, on which radar was detected
  * @gfp: context flags
  *
  * This function is called when a radar is detected on the current chanenl.
  */
-void cfg80211_radar_event(struct wiphy *wiphy,
-			  struct cfg80211_chan_def *chandef, gfp_t gfp);
+void cfg80211_radar_event(struct wiphy *wiphy, struct cfg80211_chan_def *chandef,
+			  u8 radar_bit_map, gfp_t gfp);
 
 /**
  * cfg80211_cac_event - Channel availability check (CAC) event
@@ -5596,6 +5616,9 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
  * by .crit_proto_start() has expired.
  */
 void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp);
+void cfg80211_set_dfs_state_bit_map(struct wiphy *wiphy,
+				    struct cfg80211_chan_def *chandef,
+				    u8 radar_bit_map, enum nl80211_dfs_state dfs_state);
 
 /**
  * ieee80211_get_num_supported_channels - get number of channels device has
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 2c7d876e2a1ae522e8df3c2b9b59291790b33087..3deba85dde3779a365bd6d523091afae5075bfaa 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1489,6 +1489,50 @@ struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev);
  */
 struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif);
 
+/**
+ * net_device_to_ieee80211_vif - return a vif from net_device
+ * @dev: the net_device to get the vif for
+ *
+ * This can be used by mac80211 drivers which needs to manipulate data
+ * path with tier own implementation of net_device_ops.
+ */
+struct ieee80211_vif *net_device_to_ieee80211_vif(struct net_device *dev);
+
+/**
+ * get_net_device_ops_from_wdev - extract the net_device from wdev
+ * @wdev: the wdev to get the net_device for
+ */
+const struct net_device_ops *get_net_device_ops_from_wdev(
+		struct wireless_dev *wdev);
+
+/**
+ * set_net_device_ops_from_wdev - replace the net_device to a wdev
+ * @wdev: the wdev to set the net_device for
+ */
+void set_net_device_ops_in_wdev(struct wireless_dev *wdev,
+		const struct net_device_ops *ops);
+
+/**
+ * copy_net_device_ops_from_wdev - clone a net_device_ops from wdev
+ * @wdev: the wdev to get the net_device_ops for
+ * @ops: the net_device_ops object to clone the ops to
+ */
+void copy_net_device_ops_from_wdev(struct wireless_dev *wdev,
+		struct net_device_ops *ops);
+
+/**
+ * ieee80211_vif_to_name - return the vif name
+ * @vif: the vif to get the wdev for
+ *
+ * This can be used by mac80211 drivers with direct cfg80211 APIs
+ * (like the vendor commands) that needs to get the name for a vif.
+ *
+ * Note that this function may return %NULL if the given wdev isn't
+ * associated with a vif that the driver knows about (e.g. monitor
+ * or AP_VLAN interfaces.)
+ */
+const char *ieee80211_vif_to_name(struct ieee80211_vif *vif);
+
 /**
  * enum ieee80211_key_flags - key flags
  *
@@ -1751,6 +1795,8 @@ struct ieee80211_sta_rates {
  * @tdls_initiator: indicates the STA is an initiator of the TDLS link. Only
  *	valid if the STA is a TDLS peer in the first place.
  * @mfp: indicates whether the STA uses management frame protection or not.
+ * @vendor_wds: indicates whether the STA supports
+ *	wds vendor specific capabilities.
  * @max_amsdu_subframes: indicates the maximal number of MSDUs in a single
  *	A-MSDU. Taken from the Extended Capabilities element. 0 means
  *	unlimited.
@@ -1784,6 +1830,7 @@ struct ieee80211_sta {
 	bool tdls;
 	bool tdls_initiator;
 	bool mfp;
+	int vendor_wds;
 	u8 max_amsdu_subframes;
 	u16 max_amsdu_len;
 	bool support_p2p_ps;
@@ -3640,6 +3687,9 @@ struct ieee80211_ops {
 	void (*reconfig_complete)(struct ieee80211_hw *hw,
 				  enum ieee80211_reconfig_type reconfig_type);
 
+	int (*get_connection_alive)(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif);
+
 #if IS_ENABLED(CONFIG_IPV6)
 	void (*ipv6_addr_change)(struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
@@ -5740,6 +5790,15 @@ int ieee80211_reserve_tid(struct ieee80211_sta *sta, u8 tid);
  */
 void ieee80211_unreserve_tid(struct ieee80211_sta *sta, u8 tid);
 
+/**
+ * ieee80211_drv_start_sw_scan - allow driver to fallback to sw scan from hw
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ *
+ * Note: This function must be called from hw_scan callback only.
+ *
+ */
+void ieee80211_drv_start_sw_scan(struct ieee80211_hw *hw);
+
 /**
  * ieee80211_tx_dequeue - dequeue a packet from a software tx queue
  *
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index d3cbe48b286d8cffd598305eb3164aa55ba0998e..b10f1243c3b7ed11d0088eec31b1d9b533d2c558 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1936,6 +1936,10 @@ enum nl80211_commands {
  *	attribute.
  * @NL80211_ATTR_NAN_MATCH: used to report a match. This is a nested attribute.
  *	See &enum nl80211_nan_match_attributes.
+ * @NL80211_ATTR_VENDOR_WDS: used to enable the wds vendor specific capability
+ * @NL80211_ATTR_STA_RSSI: Received signal strength indication (u32)
+ * @NL80211_ATTR_RADAR_BIT_MAP: Bit map of channel where radar was detected
+ * @NL80211_ATTR_SB_DFS_BW: Sub Band DFS new operation bandwidth
  *
  * @NL80211_ATTR_BSSID: The BSSID of the AP. Note that %NL80211_ATTR_MAC is also
  *	used in various commands/events for specifying the BSSID.
@@ -2341,6 +2345,11 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_BSSID,
 
+	NL80211_ATTR_VENDOR_WDS,
+	NL80211_ATTR_STA_RSSI,
+	NL80211_ATTR_RADAR_BIT_MAP,
+	NL80211_ATTR_SB_DFS_BW,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2698,6 +2707,7 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_TID_STATS,
 	NL80211_STA_INFO_RX_DURATION,
 	NL80211_STA_INFO_PAD,
+	NL80211_STA_INFO_MAX_RSSI,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
@@ -5128,4 +5138,12 @@ enum nl80211_nan_match_attributes {
 	NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1
 };
 
+enum nl80211_sb_dfs_bw {
+	NL80211_SB_DFS_BW_NORMAL,
+	NL80211_SB_DFS_BW_20,
+	NL80211_SB_DFS_BW_40,
+	NL80211_SB_DFS_BW_80,
+	NL80211_SB_DFS_BW_FULL,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 07001b6d36cc3771ccc1e75f1cf8f76b23013ec2..5e27811a409b5cb58f3435d9b60ec90c530a9b44 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -622,8 +622,10 @@ void sta_set_rate_info_tx(struct sta_info *sta,
 
 		sband = sta->local->hw.wiphy->bands[
 				ieee80211_get_sdata_band(sta->sdata)];
-		brate = sband->bitrates[rate->idx].bitrate;
-		rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
+		if (sband) {
+			brate = sband->bitrates[rate->idx].bitrate;
+			rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
+		}
 	}
 	if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
 		rinfo->bw = RATE_INFO_BW_40;
@@ -2017,6 +2019,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
 				struct bss_parameters *params)
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_supported_band *sband;
 	enum nl80211_band band;
 	u32 changed = 0;
 
@@ -2024,6 +2027,9 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
 		return -ENOENT;
 
 	band = ieee80211_get_sdata_band(sdata);
+	sband = wiphy->bands[band];
+	if (!sband)
+		return -EINVAL;
 
 	if (params->use_cts_prot >= 0) {
 		sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index e75cbf6ecc26e4ec7bde777c385e001c0e49e371..fb37e0a0ffef219c61bb45bc7743d423ea4d827e 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -1567,7 +1567,8 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
 
 	lockdep_assert_held(&local->mtx);
 
-	WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
+	if (local->use_chanctx)
+		WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
 
 	mutex_lock(&local->chanctx_mtx);
 
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 09f77e4a8a79d78f5722a85470bfa0862671e43e..3be8346ef51e18a252861078cf627d491098830b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -972,6 +972,20 @@ drv_reconfig_complete(struct ieee80211_local *local,
 	trace_drv_return_void(local);
 }
 
+static inline int drv_get_connection_alive(struct ieee80211_local *local,
+			      struct ieee80211_sub_if_data *sdata)
+{
+	int ret;
+
+	check_sdata_in_driver(sdata);
+
+	ret = local->ops->get_connection_alive(&local->hw, &sdata->vif);
+
+	trace_drv_return_int(local, ret);
+
+	return ret;
+}
+
 static inline void
 drv_set_default_unicast_key(struct ieee80211_local *local,
 			    struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 62d13eabe17f6b917306f893465a324884060348..4a092c1ea6e1b59dcbe1c2edbbe41d8449121c3a 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -776,7 +776,7 @@ static void ieee80211_ibss_csa_mark_radar(struct ieee80211_sub_if_data *sdata)
 					    NL80211_IFTYPE_ADHOC);
 	if (err > 0)
 		cfg80211_radar_event(sdata->local->hw.wiphy, &ifibss->chandef,
-				     GFP_ATOMIC);
+				     0, GFP_ATOMIC);
 }
 
 static bool
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 34c2add2c455978936c5379218620d41269a43a6..e76d95b21efd596f26afbdd79ecad9bd35fd5a48 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -125,6 +125,9 @@ struct ieee80211_bss {
 
 	/* Keep track of what bits of information we have valid info for. */
 	u8 valid_data;
+
+	const u8 *vendor_vht;
+	u8 vendor_vht_len;
 };
 
 /**
@@ -145,6 +148,7 @@ enum ieee80211_bss_corrupt_data_flags {
  * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE
  * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE
  * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE
+ * @IEEE80211_BSS_VALID_VENDOR_VHT: vendor VHT was gathered from non-corrupt IE
  *
  * These are bss flags that are attached to a bss in the
  * @valid_data field of &struct ieee80211_bss.  They show which parts
@@ -154,7 +158,8 @@ enum ieee80211_bss_corrupt_data_flags {
 enum ieee80211_bss_valid_data_flags {
 	IEEE80211_BSS_VALID_WMM			= BIT(1),
 	IEEE80211_BSS_VALID_RATES		= BIT(2),
-	IEEE80211_BSS_VALID_ERP			= BIT(3)
+	IEEE80211_BSS_VALID_ERP			= BIT(3),
+	IEEE80211_BSS_VALID_VENDOR_VHT	= BIT(4)
 };
 
 typedef unsigned __bitwise__ ieee80211_tx_result;
@@ -398,6 +403,9 @@ struct ieee80211_mgd_assoc_data {
 
 	struct ieee80211_vht_cap ap_vht_cap;
 
+	const u8 *vendor_vht;
+	u8 vendor_vht_len;
+
 	size_t ie_len;
 	u8 ie[];
 };
@@ -525,6 +533,8 @@ struct ieee80211_if_managed {
 	struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */
 	struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */
 
+	int vendor_wds;
+
 	/* TDLS support */
 	u8 tdls_peer[ETH_ALEN] __aligned(2);
 	struct delayed_work tdls_peer_del_work;
@@ -1430,6 +1440,8 @@ struct ieee80211_csa_ie {
 struct ieee802_11_elems {
 	const u8 *ie_start;
 	size_t total_len;
+	u8 *vendor_events_filter;
+	u8 vendor_events_filter_len;
 
 	/* pointers to IEs */
 	const struct ieee80211_tdls_lnkie *lnk_id;
@@ -1467,6 +1479,8 @@ struct ieee802_11_elems {
 	const u8 *opmode_notif;
 	const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
 	const struct ieee80211_mesh_chansw_params_ie *mesh_chansw_params_ie;
+	const u8 *vendor_vht;
+	const u8 *vendor_ie_to_notify;
 
 	/* length of them, respectively */
 	u8 ext_capab_len;
@@ -1484,6 +1498,8 @@ struct ieee802_11_elems {
 	u8 prep_len;
 	u8 perr_len;
 	u8 country_elem_len;
+	u8 vendor_vht_len;
+	u8 vendor_ie_to_notify_len;
 
 	/* whether a parse error occurred while retrieving these elements */
 	bool parse_error;
@@ -1890,12 +1906,13 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
 
 u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
 			       struct ieee802_11_elems *elems,
+				   u8 *vendor_events_filter, u8 vendor_events_filter_len,
 			       u64 filter, u32 crc);
 static inline void ieee802_11_parse_elems(const u8 *start, size_t len,
 					  bool action,
 					  struct ieee802_11_elems *elems)
 {
-	ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
+	ieee802_11_parse_elems_crc(start, len, action, elems, NULL, 0, 0, 0);
 }
 
 
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index edd6f2945f694f1fc6103caad0b04856a9cd5875..ae29fc390b8aa1db14beaeb39fb2d641af4f408e 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -619,9 +619,6 @@ int ieee80211_key_link(struct ieee80211_key *key,
 
 	pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
 	idx = key->conf.keyidx;
-	key->local = sdata->local;
-	key->sdata = sdata;
-	key->sta = sta;
 
 	mutex_lock(&sdata->local->key_mtx);
 
@@ -632,6 +629,21 @@ int ieee80211_key_link(struct ieee80211_key *key,
 	else
 		old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
 
+	/*
+	 * Silently accept key re-installation without really installing the
+	 * new version of the key to avoid nonce reuse or replay issues.
+	 */
+	if (old_key && key->conf.keylen == old_key->conf.keylen &&
+		!memcmp(key->conf.key, old_key->conf.key, key->conf.keylen)) {
+		ieee80211_key_free_unused(key);
+		ret = 0;
+		goto out;
+	}
+
+	key->local = sdata->local;
+	key->sdata = sdata;
+	key->sta = sta;
+
 	increment_tailroom_need_count(sdata);
 
 	ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
@@ -647,6 +659,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
 		ret = 0;
 	}
 
+out:
 	mutex_unlock(&sdata->local->key_mtx);
 
 	return ret;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1118c61f835dde97b801531163f22ede2177592d..ce1b13e37b0563d2086e69937b5cae61939eafa9 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -868,6 +868,20 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
 		pos = ieee80211_add_wmm_info_ie(skb_put(skb, 9), qos_info);
 	}
 
+	if (assoc_data->vendor_vht && sband->vht_cap.vht_supported) {
+		struct ieee80211_vht_cap *ap_vht_cap =
+				(struct ieee80211_vht_cap *) (assoc_data->vendor_vht + 7);
+		pos = skb_put(skb, 7);
+		*pos++ = WLAN_EID_VENDOR_SPECIFIC;
+		*pos++ = 5 + 2 + sizeof(struct ieee80211_vht_cap);
+		*pos++ = 0x00; /* Broadcom (Epigram) (00:90:4C) */
+		*pos++ = 0x90;
+		*pos++ = 0x4C;
+		*pos++ = WLAN_VENDOR_VHT_TYPE;
+		*pos++ = WLAN_VENDOR_VHT_SUBTYPE;
+		ieee80211_add_vht_ie(sdata, skb, sband, ap_vht_cap);
+	}
+
 	/* add any remaining custom (i.e. vendor specific here) IEs */
 	if (assoc_data->ie_len) {
 		noffset = assoc_data->ie_len;
@@ -1022,6 +1036,10 @@ static void ieee80211_chswitch_work(struct work_struct *work)
 	/* XXX: shouldn't really modify cfg80211-owned data! */
 	ifmgd->associated->channel = sdata->csa_chandef.chan;
 
+	if(ieee80211_vif_use_channel(sdata, &sdata->csa_chandef,
+					IEEE80211_CHANCTX_SHARED))
+		sdata_info(sdata, "driver channel switch failed\n");
+
 	ifmgd->csa_waiting_bcn = true;
 
 	ieee80211_sta_reset_beacon_monitor(sdata);
@@ -2276,6 +2294,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
 				   bool beacon)
 {
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+	struct ieee80211_local *local = sdata->local;
 	bool already = false;
 
 	if (!ieee80211_sdata_running(sdata))
@@ -2299,6 +2318,16 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
 				     beacon_loss_count);
 
 		ieee80211_cqm_beacon_loss_notify(&sdata->vif, GFP_KERNEL);
+	} else {
+		if (local->ops->get_connection_alive) {
+			if (drv_get_connection_alive(local, sdata)) {
+				mod_timer(&ifmgd->conn_mon_timer,
+						round_jiffies_up(jiffies +
+								IEEE80211_CONNECTION_IDLE_TIME));
+				mutex_unlock(&sdata->local->mtx);
+				goto out;
+			}
+		}
 	}
 
 	/*
@@ -2995,6 +3024,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 	}
 
 	sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)];
+	if (!sband) {
+		mutex_unlock(&sdata->local->sta_mtx);
+		ret = false;
+		goto out;
+	}
 
 	/* Set up internal HT/VHT capabilities */
 	if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT))
@@ -3005,6 +3039,12 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 		ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
 						    elems.vht_cap_elem, sta);
 
+	if (elems.vendor_vht) {
+		struct ieee80211_vht_cap *vht_cap_ie =
+				(struct ieee80211_vht_cap *) (elems.vendor_vht + 7);
+		ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, vht_cap_ie, sta);
+	}
+
 	/*
 	 * Some APs, e.g. Netgear WNDR3700, report invalid HT operation data
 	 * in their association response, so ignore that data for our own
@@ -3037,6 +3077,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 	}
 
 	sta->sta.wme = elems.wmm_param && local->hw.queues >= IEEE80211_NUM_ACS;
+	sta->sta.vendor_wds = ifmgd->vendor_wds;
 
 	err = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
 	if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
@@ -3246,11 +3287,16 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
 	if (baselen > len)
 		return;
 
-	ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
-			       false, &elems);
+	ieee802_11_parse_elems_crc(mgmt->u.probe_resp.variable, len - baselen,
+			       false, &elems, sdata->wdev.vendor_events_filter,
+				   sdata->wdev.vendor_events_filter_len, 0, 0);
 
 	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
 
+	if (elems.vendor_ie_to_notify)
+		cfg80211_rx_vendor_specific_mgmt(&sdata->wdev, rx_status->freq,
+				(const u8 *)mgmt, len, GFP_ATOMIC);
+
 	if (ifmgd->associated &&
 	    ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
 		ieee80211_reset_ap_probe(sdata);
@@ -3306,6 +3352,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 	if (baselen > len)
 		return;
 
+	ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
+			len - baselen, false, &elems, sdata->wdev.vendor_events_filter,
+			   sdata->wdev.vendor_events_filter_len, 0, 0);
+
+	if (elems.vendor_ie_to_notify)
+		 cfg80211_rx_vendor_specific_mgmt(&sdata->wdev, rx_status->freq,
+			(const u8 *)mgmt, len, GFP_ATOMIC);
+
 	rcu_read_lock();
 	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
 	if (!chanctx_conf) {
@@ -3322,8 +3376,6 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 
 	if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
 	    ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
-		ieee802_11_parse_elems(mgmt->u.beacon.variable,
-				       len - baselen, false, &elems);
 
 		ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
 		if (elems.tim && !elems.parse_error) {
@@ -3434,7 +3486,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
 	ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
 	ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
 					  len - baselen, false, &elems,
-					  care_about_ies, ncrc);
+					  NULL, 0, care_about_ies, ncrc);
 
 	if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) &&
 	    ieee80211_check_tim(elems.tim, elems.tim_len, ifmgd->aid)) {
@@ -4708,6 +4760,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 	assoc_data->capability = req->bss->capability;
 	assoc_data->supp_rates = bss->supp_rates;
 	assoc_data->supp_rates_len = bss->supp_rates_len;
+	assoc_data->vendor_vht = bss->vendor_vht;
+	assoc_data->vendor_vht_len = bss->vendor_vht_len;
 
 	rcu_read_lock();
 	ht_ie = ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION);
@@ -4749,6 +4803,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 		ifmgd->flags &= ~IEEE80211_STA_MFP_ENABLED;
 	}
 
+	ifmgd->vendor_wds = req->vendor_wds;
+
 	if (req->flags & ASSOC_REQ_USE_RRM)
 		ifmgd->flags |= IEEE80211_STA_ENABLE_RRM;
 	else
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 23d8ac8292796714df893e32072e44edb3617ca0..9558f0595101fc295eca4c31c7462eb35ffebf9b 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -171,6 +171,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
 			bss->valid_data |= IEEE80211_BSS_VALID_WMM;
 	}
 
+	if (elems->vendor_vht && (!elems->parse_error ||
+			!(bss->valid_data & IEEE80211_BSS_VALID_VENDOR_VHT))) {
+		bss->vendor_vht = elems->vendor_vht;
+		bss->vendor_vht_len = elems->vendor_vht_len;
+		if (!elems->parse_error)
+			bss->valid_data |= IEEE80211_BSS_VALID_VENDOR_VHT;
+	}
+
 	if (beacon) {
 		struct ieee80211_supported_band *sband =
 			local->hw.wiphy->bands[rx_status->band];
@@ -474,6 +482,17 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local,
 	return 0;
 }
 
+void ieee80211_drv_start_sw_scan(struct ieee80211_hw *hw)
+{
+	struct ieee80211_local *local = hw_to_local(hw);
+	test_and_clear_bit(SCAN_HW_SCANNING, &local->scanning);
+	__set_bit(SCAN_SW_SCANNING, &local->scanning);
+	/* TODO: check remain on channel (scan for current channel requested) */
+
+	ieee80211_start_sw_scan(local, local->scan_sdata);
+}
+EXPORT_SYMBOL(ieee80211_drv_start_sw_scan);
+
 static bool ieee80211_can_scan(struct ieee80211_local *local,
 			       struct ieee80211_sub_if_data *sdata)
 {
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 545c79a42a779b949fe4cd62afee7e36685d358c..9677223bd7d2d88ff70f80a2282ef1ed48500695 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -723,6 +723,72 @@ struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif)
 }
 EXPORT_SYMBOL_GPL(ieee80211_vif_to_wdev);
 
+struct ieee80211_vif *net_device_to_ieee80211_vif(struct net_device *dev)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	if (!dev)
+		return NULL;
+
+	sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	return &sdata->vif;
+}
+EXPORT_SYMBOL_GPL(net_device_to_ieee80211_vif);
+
+const struct net_device_ops *get_net_device_ops_from_wdev(
+		struct wireless_dev *wdev)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	if (!wdev)
+		return NULL;
+	sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+	return sdata->dev->netdev_ops;
+}
+EXPORT_SYMBOL_GPL(get_net_device_ops_from_wdev);
+
+void set_net_device_ops_in_wdev(struct wireless_dev *wdev,
+		const struct net_device_ops *ops)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	if (!wdev || !ops)
+		return;
+	sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+	sdata->dev->netdev_ops = ops;
+}
+EXPORT_SYMBOL_GPL(set_net_device_ops_in_wdev);
+
+void copy_net_device_ops_from_wdev(struct wireless_dev *wdev,
+		struct net_device_ops *ops)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	if (!wdev || !ops)
+		return;
+	sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+	if (!sdata->dev->netdev_ops)
+		return;
+	memcpy(ops, sdata->dev->netdev_ops, sizeof(struct net_device_ops));
+}
+EXPORT_SYMBOL_GPL(copy_net_device_ops_from_wdev);
+
+const char *ieee80211_vif_to_name(struct ieee80211_vif *vif)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	if (!vif)
+		return NULL;
+
+	sdata = vif_to_sdata(vif);
+
+	if (!sdata)
+		return NULL;
+
+	return (const char *)sdata->name;
+}
+EXPORT_SYMBOL_GPL(ieee80211_vif_to_name);
+
 /*
  * Nothing should have been stuffed into the workqueue during
  * the suspend->resume cycle. Since we can't check each caller
@@ -766,8 +832,63 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_queue_delayed_work);
 
+static u32 ieee802_11_parse_vendor_specific(const u8 *pos, u8 elen,
+		struct ieee802_11_elems *elems, bool calc_crc, u32 crc)
+{
+	if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && pos[2] == 0xf2) {
+		/* Microsoft OUI (00:50:F2) */
+
+		if (calc_crc)
+			crc = crc32_be(crc, pos - 2, elen + 2);
+
+		if (elen >= 5 && pos[3] == 2) {
+			/* OUI Type 2 - WMM IE */
+			if (pos[4] == 0) {
+				elems->wmm_info = pos;
+				elems->wmm_info_len = elen;
+			} else if (pos[4] == 1) {
+				elems->wmm_param = pos;
+				elems->wmm_param_len = elen;
+			}
+		}
+	}
+
+	if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x90 && pos[2] == 0x4c) {
+		/* Broadcom (Epigram) (00:90:4C) */
+
+		if (calc_crc)
+			crc = crc32_be(crc, pos - 2, elen + 2);
+
+		if (elen >= 5 && pos[3] == WLAN_VENDOR_VHT_TYPE) {
+			if ((pos[4] == WLAN_VENDOR_VHT_SUBTYPE  ||
+			     pos[4] == WLAN_VENDOR_VHT_SUBTYPE2 ||
+			     pos[4] == WLAN_VENDOR_VHT_SUBTYPE3)) {
+				elems->vendor_vht = pos;
+				elems->vendor_vht_len = elen;
+			}
+		}
+	}
+
+	if (elen >= 4 && elems->vendor_events_filter && elems->vendor_events_filter_len >= 3) {
+		int i = 0, found = 1;
+		for (i = 0; i < elems->vendor_events_filter_len; i++) {
+			if (pos[i] != elems->vendor_events_filter[i]) {
+				found = 0;
+				break;
+			}
+		}
+		if (found) {
+			elems->vendor_ie_to_notify = pos;
+			elems->vendor_ie_to_notify_len = elen;
+		}
+	}
+
+	return crc;
+}
+
 u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
 			       struct ieee802_11_elems *elems,
+				   u8 *vendor_events_filter, u8 vendor_events_filter_len,
 			       u64 filter, u32 crc)
 {
 	size_t left = len;
@@ -780,6 +901,8 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
 	memset(elems, 0, sizeof(*elems));
 	elems->ie_start = start;
 	elems->total_len = len;
+	elems->vendor_events_filter = vendor_events_filter;
+	elems->vendor_events_filter_len = vendor_events_filter_len;
 
 	while (left >= 2) {
 		u8 id, elen;
@@ -891,24 +1014,8 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
 			elems->challenge_len = elen;
 			break;
 		case WLAN_EID_VENDOR_SPECIFIC:
-			if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
-			    pos[2] == 0xf2) {
-				/* Microsoft OUI (00:50:F2) */
-
-				if (calc_crc)
-					crc = crc32_be(crc, pos - 2, elen + 2);
-
-				if (elen >= 5 && pos[3] == 2) {
-					/* OUI Type 2 - WMM IE */
-					if (pos[4] == 0) {
-						elems->wmm_info = pos;
-						elems->wmm_info_len = elen;
-					} else if (pos[4] == 1) {
-						elems->wmm_param = pos;
-						elems->wmm_param_len = elen;
-					}
-				}
-			}
+			crc = ieee802_11_parse_vendor_specific(pos, elen, elems,
+					calc_crc, crc);
 			break;
 		case WLAN_EID_RSN:
 			elems->rsn = pos;
@@ -1456,7 +1563,8 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
 		break;
 	}
 
-	if (sband->vht_cap.vht_supported && have_80mhz) {
+	/* Don't add VHT capab. in 2GHZ, even if we support it */
+	if (sband->vht_cap.vht_supported && have_80mhz && band != NL80211_BAND_2GHZ) {
 		if (end - pos < 2 + sizeof(struct ieee80211_vht_cap))
 			goto out_err;
 		pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap,
@@ -2837,7 +2945,7 @@ void ieee80211_dfs_radar_detected_work(struct work_struct *work)
 		/* XXX: multi-channel is not supported yet */
 		WARN_ON(1);
 	else
-		cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
+		cfg80211_radar_event(local->hw.wiphy, &chandef, 0, GFP_KERNEL);
 }
 
 void ieee80211_radar_detected(struct ieee80211_hw *hw)
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 4ea786eae1ab363bef0376bab2bb2bc989718e3f..05a0fc645a30588ee0e3f01b0b2b1b300ab47bdc 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -181,7 +181,7 @@ config CFG80211_WEXT
 	  extensions with cfg80211-based drivers.
 
 config CFG80211_WEXT_EXPORT
-	bool
+	bool "Export cfg80211's wext compatibility symbols"
 	depends on CFG80211
 	help
 	  Drivers should select this option if they require cfg80211's
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 5497d022fadabf17512c0f4c0b77ce50cce345dc..0f4043565dca35f3285c94a457e0f5cda18539c8 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -150,7 +150,7 @@ static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
 	}
 }
 
-static int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
+int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c)
 {
 	int width;
 
@@ -251,6 +251,8 @@ static void cfg80211_set_chans_dfs_state(struct wiphy *wiphy, u32 center_freq,
 		if (!c || !(c->flags & IEEE80211_CHAN_RADAR))
 			continue;
 
+		printk(KERN_DEBUG "Setting the DFS state of channel %hu to 0x%02x\n",
+		       c->hw_value, dfs_state);
 		c->dfs_state = dfs_state;
 		c->dfs_state_entered = jiffies;
 	}
@@ -277,6 +279,7 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy,
 	cfg80211_set_chans_dfs_state(wiphy, chandef->center_freq2,
 				     width, dfs_state);
 }
+EXPORT_SYMBOL(cfg80211_set_dfs_state);
 
 static u32 cfg80211_get_start_freq(u32 center_freq,
 				   u32 bandwidth)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 8201e6d7449e969182152fcc2641a7e0247b7770..d19fbe678339184c3241b8240105775cd87ea311 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -39,6 +39,7 @@ MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
 
 /* RCU-protected (and RTNL for writers) */
 LIST_HEAD(cfg80211_rdev_list);
+EXPORT_SYMBOL(cfg80211_rdev_list);
 int cfg80211_rdev_list_generation;
 
 /* for debugfs */
@@ -431,6 +432,8 @@ use_default_name:
 		dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
 	}
 
+	rdev->scan_expire_time = IEEE80211_SCAN_RESULT_EXPIRE;
+
 	INIT_LIST_HEAD(&rdev->wiphy.wdev_list);
 	INIT_LIST_HEAD(&rdev->beacon_registrations);
 	spin_lock_init(&rdev->beacon_registrations_lock);
@@ -529,9 +532,9 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
 				CFG80211_MAX_NUM_DIFFERENT_CHANNELS))
 			return -EINVAL;
 
-		/* DFS only works on one channel. */
+		/* Two different channels allowed by WLAN driver during CSA */
 		if (WARN_ON(c->radar_detect_widths &&
-			    (c->num_different_channels > 1)))
+			    (c->num_different_channels > 2)))
 			return -EINVAL;
 
 		if (WARN_ON(!c->n_limits))
@@ -957,6 +960,12 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
 }
 EXPORT_SYMBOL(cfg80211_unregister_wdev);
 
+struct workqueue_struct *cfg80211_get_cfg80211_wq(void)
+{
+	return cfg80211_wq;
+}
+EXPORT_SYMBOL(cfg80211_get_cfg80211_wq);
+
 static const struct device_type wiphy_type = {
 	.name	= "wlan",
 };
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 5f5867f90fed5e61992baf06fbf330333889a390..5bd0ae19eb7280efde4e22cc1034f77c52aedb85 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -18,6 +18,7 @@
 
 
 #define WIPHY_IDX_INVALID	-1
+#define IEEE80211_SCAN_RESULT_EXPIRE	(30 * HZ)
 
 struct cfg80211_registered_device {
 	const struct cfg80211_ops *ops;
@@ -75,6 +76,7 @@ struct cfg80211_registered_device {
 	struct cfg80211_scan_request *scan_req; /* protected by RTNL */
 	struct sk_buff *scan_msg;
 	struct cfg80211_sched_scan_request __rcu *sched_scan_req;
+	u32 scan_expire_time;
 	unsigned long suspend_at;
 	struct work_struct scan_done_wk;
 	struct work_struct sched_scan_results_wk;
@@ -493,6 +495,8 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
 void cfg80211_stop_nan(struct cfg80211_registered_device *rdev,
 		       struct wireless_dev *wdev);
 
+int cfg80211_chandef_get_width(const struct cfg80211_chan_def *c);
+
 #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
 
 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 76775a2b421db31c33a323f4a671f470099051db..c48e158c6ceca0cdcb7788ee45c803d2d7b3a127 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -505,6 +505,13 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
 	nreg->frame_type = cpu_to_le16(frame_type);
 	nreg->wdev = wdev;
 	list_add(&nreg->list, &wdev->mgmt_registrations);
+
+	if (frame_type == IEEE80211_STYPE_PROBE_RESP ||
+		frame_type == IEEE80211_STYPE_BEACON) {
+		wdev->vendor_events_filter = nreg->match;
+		wdev->vendor_events_filter_len = nreg->match_len;
+	}
+
 	spin_unlock_bh(&wdev->mgmt_registrations_lock);
 
 	/* process all unregistrations to avoid driver confusion */
@@ -762,7 +769,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
 
 				nl80211_radar_notify(rdev, &chandef,
 						     NL80211_RADAR_NOP_FINISHED,
-						     NULL, GFP_ATOMIC);
+						     NULL, 0, GFP_ATOMIC);
 				continue;
 			}
 
@@ -782,26 +789,72 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
 }
 
 
+static void cfg80211_set_chans_dfs_state_bit_map (struct wiphy *wiphy, u32 center_freq,
+						  u32 bandwidth, u8 radar_bit_map, u8 *bit_idx,
+						  enum nl80211_dfs_state dfs_state)
+{
+	struct ieee80211_channel *c;
+	u32 freq;
+
+	for (freq = center_freq - bandwidth/2 + 10;
+	     freq <= center_freq + bandwidth/2 - 10;
+	     freq += 20) {
+		if (radar_bit_map & (1 << *bit_idx)) {
+			c = ieee80211_get_channel(wiphy, freq);
+			if (!c || !(c->flags & IEEE80211_CHAN_RADAR)) {
+				*bit_idx++;
+				continue;
+			}
+
+			c->dfs_state = dfs_state;
+			c->dfs_state_entered = jiffies;
+		}
+		(*bit_idx)++;
+	}
+}
+
+void cfg80211_set_dfs_state_bit_map (struct wiphy *wiphy, struct cfg80211_chan_def *chandef,
+				     u8 radar_bit_map, enum nl80211_dfs_state dfs_state)
+{
+	u8 bit_idx = 0;
+	u32 center_freq, bandwidth;
+
+	center_freq = chandef->center_freq1;
+	bandwidth   = cfg80211_chandef_get_width(chandef);
+
+	cfg80211_set_chans_dfs_state_bit_map(wiphy, center_freq, bandwidth,
+					     radar_bit_map, &bit_idx, dfs_state);
+
+	if (NL80211_CHAN_WIDTH_80P80 != bandwidth)
+		return;
+
+	center_freq = chandef->center_freq2;
+	cfg80211_set_chans_dfs_state_bit_map(wiphy, center_freq, bandwidth,
+					     radar_bit_map, &bit_idx, dfs_state);
+}
+EXPORT_SYMBOL(cfg80211_set_dfs_state_bit_map);
+
+
 void cfg80211_radar_event(struct wiphy *wiphy,
 			  struct cfg80211_chan_def *chandef,
-			  gfp_t gfp)
+			  u8 radar_bit_map, gfp_t gfp)
 {
 	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
 	unsigned long timeout;
 
 	trace_cfg80211_radar_event(wiphy, chandef);
 
-	/* only set the chandef supplied channel to unavailable, in
-	 * case the radar is detected on only one of multiple channels
-	 * spanned by the chandef.
-	 */
-	cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE);
+	if (radar_bit_map)
+		cfg80211_set_dfs_state_bit_map(wiphy, chandef, radar_bit_map,
+					       NL80211_DFS_UNAVAILABLE);
+	else
+		cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE);
 
 	timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_NOP_TIME_MS);
 	queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk,
 			   timeout);
 
-	nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp);
+	nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, radar_bit_map, gfp);
 }
 EXPORT_SYMBOL(cfg80211_radar_event);
 
@@ -837,6 +890,23 @@ void cfg80211_cac_event(struct net_device *netdev,
 	}
 	wdev->cac_started = false;
 
-	nl80211_radar_notify(rdev, chandef, event, netdev, gfp);
+	nl80211_radar_notify(rdev, chandef, event, netdev, 0, gfp);
 }
 EXPORT_SYMBOL(cfg80211_cac_event);
+
+int cfg80211_rx_vendor_specific_mgmt(struct wireless_dev *wdev, int freq,
+		      const u8 *buf, size_t len, gfp_t gfp)
+{
+	struct wiphy *wiphy = wdev->wiphy;
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+	struct cfg80211_mgmt_registration *reg;
+	int res = 0;
+
+	list_for_each_entry(reg, &wdev->mgmt_registrations, list) {
+		res = nl80211_send_mgmt(rdev, wdev, reg->nlportid, freq, 0, buf, len, 0, gfp);
+		break;
+	}
+
+	return res;
+}
+EXPORT_SYMBOL(cfg80211_rx_vendor_specific_mgmt);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c626f679e1c870204c62b0fa5a0d4661bfa06d32..a4d28e7ee71d8c549465f5e1c02eb77cc126addf 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -255,6 +255,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 	[NL80211_ATTR_BEACON_TAIL] = { .type = NLA_BINARY,
 				       .len = IEEE80211_MAX_DATA_LEN },
 	[NL80211_ATTR_STA_AID] = { .type = NLA_U16 },
+	[NL80211_ATTR_STA_RSSI] = { .type = NLA_U32 },
 	[NL80211_ATTR_STA_FLAGS] = { .type = NLA_NESTED },
 	[NL80211_ATTR_STA_LISTEN_INTERVAL] = { .type = NLA_U16 },
 	[NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
@@ -389,6 +390,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 	[NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
 	[NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
 				   .len = IEEE80211_QOS_MAP_LEN_MAX },
+	[NL80211_ATTR_VENDOR_WDS] = { .type = NLA_U32 },
 	[NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN },
 	[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
 	[NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
@@ -4206,6 +4208,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
 
 	PUT_SINFO(CONNECTED_TIME, connected_time, u32);
 	PUT_SINFO(INACTIVE_TIME, inactive_time, u32);
+	PUT_SINFO(MAX_RSSI, max_rssi, u32);
 
 	if (sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES) |
 			     BIT(NL80211_STA_INFO_RX_BYTES64)) &&
@@ -4883,6 +4886,9 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 	    !info->attrs[NL80211_ATTR_PEER_AID])
 		return -EINVAL;
 
+	if (!info->attrs[NL80211_ATTR_STA_RSSI])
+		return -EINVAL;
+
 	mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
 	params.supported_rates =
 		nla_data(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]);
@@ -4891,6 +4897,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 	params.listen_interval =
 		nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
 
+	if (info->attrs[NL80211_ATTR_FRAME]) {
+		params.resp = nla_data(info->attrs[NL80211_ATTR_FRAME]);
+		params.resp_len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
+	}
+
 	if (info->attrs[NL80211_ATTR_STA_SUPPORT_P2P_PS]) {
 		u8 tmp;
 
@@ -4915,6 +4926,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 	if (!params.aid || params.aid > IEEE80211_MAX_AID)
 		return -EINVAL;
 
+	params.rssi = nla_get_u32(info->attrs[NL80211_ATTR_STA_RSSI]);
+
 	if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) {
 		params.capability =
 			nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]);
@@ -7217,33 +7230,51 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
 	unsigned int cac_time_ms;
 	int err;
 
+	printk(KERN_INFO "Starting radar detection\n");
+
 	dfs_region = reg_get_dfs_region(wdev->wiphy);
-	if (dfs_region == NL80211_DFS_UNSET)
+	if (dfs_region == NL80211_DFS_UNSET) {
+		printk(KERN_ERR "DFS master region not specified\n");
 		return -EINVAL;
+	}
 
 	err = nl80211_parse_chandef(rdev, info, &chandef);
-	if (err)
+	if (err) {
+		printk(KERN_ERR "Could not parse the channel definition\n");
 		return err;
+	}
 
-	if (netif_carrier_ok(dev))
+	if (netif_carrier_ok(dev)) {
+		printk(KERN_ERR "Carrier isn't present on device\n");
 		return -EBUSY;
+	}
 
-	if (wdev->cac_started)
+	if (wdev->cac_started) {
+		printk(KERN_ERR "CAC already started\n");
 		return -EBUSY;
+	}
 
 	err = cfg80211_chandef_dfs_required(wdev->wiphy, &chandef,
 					    wdev->iftype);
-	if (err < 0)
+	if (err < 0) {
+		printk(KERN_ERR "Error looking for DFS-required channels\n");
 		return err;
+	}
 
-	if (err == 0)
+	if (err == 0) {
+		printk(KERN_ERR "No DFS-required channels found\n");
 		return -EINVAL;
+	}
 
-	if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef))
+	if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef)) {
+		printk(KERN_ERR "Channels are not all in DFS_USABLE state\n");
 		return -EINVAL;
+	}
 
-	if (!rdev->ops->start_radar_detection)
+	if (!rdev->ops->start_radar_detection) {
+		printk(KERN_ERR "Device does not support radar detection\n");
 		return -EOPNOTSUPP;
+	}
 
 	cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
 	if (WARN_ON(!cac_time_ms))
@@ -7255,7 +7286,10 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
 		wdev->cac_started = true;
 		wdev->cac_start_time = jiffies;
 		wdev->cac_time_ms = cac_time_ms;
+	} else {
+		printk(KERN_ERR "Start radar detection in device failed\n");
 	}
+
 	return err;
 }
 
@@ -7394,6 +7428,12 @@ skip_beacons:
 	if (err)
 		return err;
 
+	if (info->attrs[NL80211_ATTR_SB_DFS_BW])
+		params.sb_dfs_bw = nla_get_u8(info->attrs[NL80211_ATTR_SB_DFS_BW]);
+
+	if (NL80211_SB_DFS_BW_FULL == params.sb_dfs_bw)
+		cfg80211_set_dfs_state(&rdev->wiphy, &params.chandef, NL80211_DFS_AVAILABLE);
+
 	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
 					   wdev->iftype))
 		return -EINVAL;
@@ -7970,6 +8010,10 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
 			return -EINVAL;
 	}
 
+	if (info->attrs[NL80211_ATTR_VENDOR_WDS]) {
+		req.vendor_wds = nla_get_u32(info->attrs[NL80211_ATTR_VENDOR_WDS]);
+	}
+
 	if (info->attrs[NL80211_ATTR_PREV_BSSID])
 		req.prev_bssid = nla_data(info->attrs[NL80211_ATTR_PREV_BSSID]);
 
@@ -14041,7 +14085,8 @@ void
 nl80211_radar_notify(struct cfg80211_registered_device *rdev,
 		     const struct cfg80211_chan_def *chandef,
 		     enum nl80211_radar_event event,
-		     struct net_device *netdev, gfp_t gfp)
+		     struct net_device *netdev,
+		     u8 radar_bit_map, gfp_t gfp)
 {
 	struct sk_buff *msg;
 	void *hdr;
@@ -14075,6 +14120,12 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
 	if (nl80211_send_chandef(msg, chandef))
 		goto nla_put_failure;
 
+	if (radar_bit_map) {
+		if (NL80211_RADAR_DETECTED == event &&
+		    nla_put_u8(msg, NL80211_ATTR_RADAR_BIT_MAP, radar_bit_map))
+			goto nla_put_failure;
+	}
+
 	genlmsg_end(msg, hdr);
 
 	genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
@@ -14085,6 +14136,7 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev,
 	genlmsg_cancel(msg, hdr);
 	nlmsg_free(msg);
 }
+EXPORT_SYMBOL(nl80211_radar_notify);
 
 void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
 			   u64 cookie, bool acked, gfp_t gfp)
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 7e3821d7fcc5eb185359d3b9c45bd3d526fd36c2..a858b164d77d208360aeef7a87c1d3ac8f41cf41 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -91,7 +91,8 @@ void
 nl80211_radar_notify(struct cfg80211_registered_device *rdev,
 		     const struct cfg80211_chan_def *chandef,
 		     enum nl80211_radar_event event,
-		     struct net_device *netdev, gfp_t gfp);
+		     struct net_device *netdev,
+		     u8 radar_bit_map, gfp_t gfp);
 
 void nl80211_send_ap_stopped(struct wireless_dev *wdev);
 
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 5dbac37497386fffb23de9bf5fe384891f874eca..acd45975f153c5bd8380ede67b1fdc115b060146 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -109,6 +109,7 @@ static struct platform_device *reg_pdev;
  * (protected by RTNL, can be read under RCU)
  */
 const struct ieee80211_regdomain __rcu *cfg80211_regdomain;
+EXPORT_SYMBOL(cfg80211_regdomain);
 
 /*
  * Number of devices that registered to the core
@@ -1857,8 +1858,9 @@ __reg_process_hint_user(struct regulatory_request *user_request)
 	if (reg_request_cell_base(lr))
 		return REG_REQ_IGNORE;
 
+	/* Don't do intersection between mac80211 and cfg80211 regdom */
 	if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)
-		return REG_REQ_INTERSECT;
+		return REG_REQ_OK;
 	/*
 	 * If the user knows better the user should set the regdom
 	 * to their country before the IE is picked up
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 35ad69fd08383a2a8392170d2a580fc4549276d7..89aa8fa61e7c8e4228c17f2e52bf19d1631e9c03 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -70,8 +70,6 @@ module_param(bss_entries_limit, int, 0644);
 MODULE_PARM_DESC(bss_entries_limit,
                  "limit to number of scan BSS entries (per wiphy, default 1000)");
 
-#define IEEE80211_SCAN_RESULT_EXPIRE	(30 * HZ)
-
 static void bss_free(struct cfg80211_internal_bss *bss)
 {
 	struct cfg80211_bss_ies *ies;
@@ -400,7 +398,7 @@ void cfg80211_bss_age(struct cfg80211_registered_device *rdev,
 
 void cfg80211_bss_expire(struct cfg80211_registered_device *rdev)
 {
-	__cfg80211_bss_expire(rdev, jiffies - IEEE80211_SCAN_RESULT_EXPIRE);
+	__cfg80211_bss_expire(rdev, jiffies - rdev->scan_expire_time);
 }
 
 const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len,
@@ -661,7 +659,7 @@ struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy,
 		if (!is_valid_ether_addr(bss->pub.bssid))
 			continue;
 		/* Don't get expired BSS structs */
-		if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
+		if (time_after(now, bss->ts + rdev->scan_expire_time) &&
 		    !atomic_read(&bss->hold))
 			continue;
 		if (is_bss(&bss->pub, bssid, ssid, ssid_len)) {
@@ -1231,6 +1229,22 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
 }
 EXPORT_SYMBOL(cfg80211_unlink_bss);
 
+void cfg80211_set_scan_expire_time(struct wiphy *wiphy, unsigned long time)
+{
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+
+	rdev->scan_expire_time = time;
+}
+EXPORT_SYMBOL(cfg80211_set_scan_expire_time);
+
+u32 cfg80211_get_scan_expire_time(struct wiphy *wiphy)
+{
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+
+	return rdev->scan_expire_time;
+}
+EXPORT_SYMBOL(cfg80211_get_scan_expire_time);
+
 #ifdef CONFIG_CFG80211_WEXT
 static struct cfg80211_registered_device *
 cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 35cc1de85dcc53ea18817a5a23a4745718277910..ece8a0ab7b1a9d8de99f68d9476912abe8e9060c 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -761,8 +761,9 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
 	 * - country_ie + 2, the start of the country ie data, and
 	 * - and country_ie[1] which is the IE length
 	 */
-	regulatory_hint_country_ie(wdev->wiphy, bss->channel->band,
-				   country_ie + 2, country_ie[1]);
+	if (!(wdev->wiphy->flags & WIPHY_FLAG_DISABLE_11D_HINT))
+		regulatory_hint_country_ie(wdev->wiphy, bss->channel->band,
+						country_ie + 2, country_ie[1]);
 	kfree(country_ie);
 }
 
diff --git a/net/wireless/util.c b/net/wireless/util.c
index c921c2eed15d4fe9ee2025b5ed49180d9a8ed38d..ea5724f2b52820932677d42088f03c48303b0dca 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1637,20 +1637,29 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
 			}
 		}
 
-		if (radar_detect != (c->radar_detect_widths & radar_detect))
+		if (radar_detect != (c->radar_detect_widths & radar_detect)) {
+			printk(KERN_DEBUG "combination %u, radar detect_widths 0x%02x",
+			       i, c->radar_detect_widths);
 			goto cont;
+		}
 
 		if (radar_detect && c->radar_detect_regions &&
-		    !(c->radar_detect_regions & BIT(region)))
+		    !(c->radar_detect_regions & BIT(region))) {
+			printk(KERN_DEBUG "radar_detect_regions 0x%x, region %d)",
+			       c->radar_detect_regions, region);
 			goto cont;
+		}
 
 		/* Finally check that all iftypes that we're currently
 		 * using are actually part of this combination. If they
 		 * aren't then we can't use this combination and have
 		 * to continue to the next.
 		 */
-		if ((all_iftypes & used_iftypes) != used_iftypes)
+		if ((all_iftypes & used_iftypes) != used_iftypes) {
+			printk(KERN_DEBUG "all_iftypes 0x%02x, used_iftypes 0x%02x",
+			       all_iftypes, used_iftypes);
 			goto cont;
+		}
 
 		/* This combination covered all interface types and
 		 * supported the requested numbers, so we're good.
@@ -1685,8 +1694,10 @@ int cfg80211_check_combinations(struct wiphy *wiphy,
 					 cfg80211_iter_sum_ifcombs, &num);
 	if (err)
 		return err;
-	if (num == 0)
+	if (num == 0) {
+		printk(KERN_ERR "No suitable interface combination found\n");
 		return -EBUSY;
+	}
 
 	return 0;
 }