diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index c959f15..2fd4af8 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -260,9 +260,10 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type)
 	return -EOPNOTSUPP;
 }
 
-int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
+int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
 		       struct station_info *sinfo)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_notify_req_cmd cmd = {
 		.cid = cid,
 		.interval_usec = 0,
@@ -274,17 +275,17 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
 	struct wil_net_stats *stats = &wil->sta[cid].stats;
 	int rc;
 
-	rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, &cmd, sizeof(cmd),
 		      WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20);
 	if (rc)
 		return rc;
 
-	wil_dbg_wmi(wil, "Link status for CID %d: {\n"
+	wil_dbg_wmi(wil, "Link status for CID %d MID %d: {\n"
 		    "  MCS %d TSF 0x%016llx\n"
 		    "  BF status 0x%08x RSSI %d SQI %d%%\n"
 		    "  Tx Tpt %d goodput %d Rx goodput %d\n"
 		    "  Sectors(rx:tx) my %d:%d peer %d:%d\n""}\n",
-		    cid, le16_to_cpu(reply.evt.bf_mcs),
+		    cid, vif->mid, le16_to_cpu(reply.evt.bf_mcs),
 		    le64_to_cpu(reply.evt.tsf), reply.evt.status,
 		    reply.evt.rssi,
 		    reply.evt.sqi,
@@ -333,30 +334,34 @@ static int wil_cfg80211_get_station(struct wiphy *wiphy,
 				    struct net_device *ndev,
 				    const u8 *mac, struct station_info *sinfo)
 {
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 	int rc;
 
-	int cid = wil_find_cid(wil, mac);
+	int cid = wil_find_cid(wil, vif->mid, mac);
 
-	wil_dbg_misc(wil, "get_station: %pM CID %d\n", mac, cid);
+	wil_dbg_misc(wil, "get_station: %pM CID %d MID %d\n", mac, cid,
+		     vif->mid);
 	if (cid < 0)
 		return cid;
 
-	rc = wil_cid_fill_sinfo(wil, cid, sinfo);
+	rc = wil_cid_fill_sinfo(vif, cid, sinfo);
 
 	return rc;
 }
 
 /*
- * Find @idx-th active STA for station dump.
+ * Find @idx-th active STA for specific MID for station dump.
  */
-static int wil_find_cid_by_idx(struct wil6210_priv *wil, int idx)
+static int wil_find_cid_by_idx(struct wil6210_priv *wil, u8 mid, int idx)
 {
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
 		if (wil->sta[i].status == wil_sta_unused)
 			continue;
+		if (wil->sta[i].mid != mid)
+			continue;
 		if (idx == 0)
 			return i;
 		idx--;
@@ -369,17 +374,19 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy,
 				     struct net_device *dev, int idx,
 				     u8 *mac, struct station_info *sinfo)
 {
+	struct wil6210_vif *vif = ndev_to_vif(dev);
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 	int rc;
-	int cid = wil_find_cid_by_idx(wil, idx);
+	int cid = wil_find_cid_by_idx(wil, vif->mid, idx);
 
 	if (cid < 0)
 		return -ENOENT;
 
 	ether_addr_copy(mac, wil->sta[cid].addr);
-	wil_dbg_misc(wil, "dump_station: %pM CID %d\n", mac, cid);
+	wil_dbg_misc(wil, "dump_station: %pM CID %d MID %d\n", mac, cid,
+		     vif->mid);
 
-	rc = wil_cid_fill_sinfo(wil, cid, sinfo);
+	rc = wil_cid_fill_sinfo(vif, cid, sinfo);
 
 	return rc;
 }
@@ -390,7 +397,7 @@ static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy,
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 
 	wil_dbg_misc(wil, "start_p2p_device: entered\n");
-	wil->p2p.p2p_dev_started = 1;
+	wil->p2p_dev_started = 1;
 	return 0;
 }
 
@@ -398,16 +405,15 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
 					 struct wireless_dev *wdev)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-	struct wil_p2p_info *p2p = &wil->p2p;
 
-	if (!p2p->p2p_dev_started)
+	if (!wil->p2p_dev_started)
 		return;
 
 	wil_dbg_misc(wil, "stop_p2p_device: entered\n");
 	mutex_lock(&wil->mutex);
 	mutex_lock(&wil->p2p_wdev_mutex);
 	wil_p2p_stop_radio_operations(wil);
-	p2p->p2p_dev_started = 0;
+	wil->p2p_dev_started = 0;
 	mutex_unlock(&wil->p2p_wdev_mutex);
 	mutex_unlock(&wil->mutex);
 }
@@ -419,7 +425,7 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy,
 		       struct vif_params *params)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	struct wil6210_vif *vif;
 	struct wireless_dev *p2p_wdev;
 
@@ -474,12 +480,13 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy,
 				     struct vif_params *params)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-	struct wireless_dev *wdev = wil_to_wdev(wil);
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
+	struct wireless_dev *wdev = vif_to_wdev(vif);
 	int rc;
 
 	wil_dbg_misc(wil, "change_iface: type=%d\n", type);
 
-	if (netif_running(wil_to_ndev(wil)) && !wil_is_recovery_blocked(wil)) {
+	if (netif_running(ndev) && !wil_is_recovery_blocked(wil)) {
 		wil_dbg_misc(wil, "interface is up. resetting...\n");
 		mutex_lock(&wil->mutex);
 		__wil_down(wil);
@@ -514,6 +521,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 	struct wireless_dev *wdev = request->wdev;
+	struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
 	struct {
 		struct wmi_start_scan_cmd cmd;
 		u16 chnl[4];
@@ -542,7 +550,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
 	mutex_lock(&wil->mutex);
 
 	mutex_lock(&wil->p2p_wdev_mutex);
-	if (wil->scan_request || wil->p2p.discovery_started) {
+	if (vif->scan_request || vif->p2p.discovery_started) {
 		wil_err(wil, "Already scanning\n");
 		mutex_unlock(&wil->p2p_wdev_mutex);
 		rc = -EAGAIN;
@@ -551,25 +559,28 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
 	mutex_unlock(&wil->p2p_wdev_mutex);
 
 	if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
-		if (!wil->p2p.p2p_dev_started) {
+		if (!wil->p2p_dev_started) {
 			wil_err(wil, "P2P search requested on stopped P2P device\n");
 			rc = -EIO;
 			goto out;
 		}
 		/* social scan on P2P_DEVICE is handled as p2p search */
 		if (wil_p2p_is_social_scan(request)) {
-			wil->scan_request = request;
-			wil->radio_wdev = wdev;
-			rc = wil_p2p_search(wil, request);
+			vif->scan_request = request;
+			if (vif->mid == 0)
+				wil->radio_wdev = wdev;
+			rc = wil_p2p_search(vif, request);
 			if (rc) {
-				wil->radio_wdev = wil_to_wdev(wil);
-				wil->scan_request = NULL;
+				if (vif->mid == 0)
+					wil->radio_wdev =
+						wil->main_ndev->ieee80211_ptr;
+				vif->scan_request = NULL;
 			}
 			goto out;
 		}
 	}
 
-	(void)wil_p2p_stop_discovery(wil);
+	(void)wil_p2p_stop_discovery(vif);
 
 	wil_dbg_misc(wil, "Start scan_request 0x%p\n", request);
 	wil_dbg_misc(wil, "SSID count: %d", request->n_ssids);
@@ -582,18 +593,18 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
 	}
 
 	if (request->n_ssids)
-		rc = wmi_set_ssid(wil, request->ssids[0].ssid_len,
+		rc = wmi_set_ssid(vif, request->ssids[0].ssid_len,
 				  request->ssids[0].ssid);
 	else
-		rc = wmi_set_ssid(wil, 0, NULL);
+		rc = wmi_set_ssid(vif, 0, NULL);
 
 	if (rc) {
 		wil_err(wil, "set SSID for scan request failed: %d\n", rc);
 		goto out;
 	}
 
-	wil->scan_request = request;
-	mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO);
+	vif->scan_request = request;
+	mod_timer(&vif->scan_timer, jiffies + WIL6210_SCAN_TO);
 
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.cmd.scan_type = WMI_ACTIVE_SCAN;
@@ -620,7 +631,8 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
 	else
 		wil_dbg_misc(wil, "Scan has no IE's\n");
 
-	rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie);
+	rc = wmi_set_ie(vif, WMI_FRAME_PROBE_REQ,
+			request->ie_len, request->ie);
 	if (rc)
 		goto out_restore;
 
@@ -629,15 +641,18 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
 		wil_dbg_misc(wil, "active scan with discovery_mode=1\n");
 	}
 
-	wil->radio_wdev = wdev;
-	rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
-			cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
+	if (vif->mid == 0)
+		wil->radio_wdev = wdev;
+	rc = wmi_send(wil, WMI_START_SCAN_CMDID, vif->mid,
+		      &cmd, sizeof(cmd.cmd) +
+		      cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
 
 out_restore:
 	if (rc) {
-		del_timer_sync(&wil->scan_timer);
-		wil->radio_wdev = wil_to_wdev(wil);
-		wil->scan_request = NULL;
+		del_timer_sync(&vif->scan_timer);
+		if (vif->mid == 0)
+			wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
+		vif->scan_request = NULL;
 	}
 out:
 	mutex_unlock(&wil->mutex);
@@ -648,24 +663,25 @@ static void wil_cfg80211_abort_scan(struct wiphy *wiphy,
 				    struct wireless_dev *wdev)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
 
 	wil_dbg_misc(wil, "wdev=0x%p iftype=%d\n", wdev, wdev->iftype);
 
 	mutex_lock(&wil->mutex);
 	mutex_lock(&wil->p2p_wdev_mutex);
 
-	if (!wil->scan_request)
+	if (!vif->scan_request)
 		goto out;
 
-	if (wdev != wil->scan_request->wdev) {
+	if (wdev != vif->scan_request->wdev) {
 		wil_dbg_misc(wil, "abort scan was called on the wrong iface\n");
 		goto out;
 	}
 
-	if (wil->radio_wdev == wil->p2p_wdev)
+	if (wdev == wil->p2p_wdev && wil->radio_wdev == wil->p2p_wdev)
 		wil_p2p_stop_radio_operations(wil);
 	else
-		wil_abort_scan(wil, true);
+		wil_abort_scan(vif, true);
 
 out:
 	mutex_unlock(&wil->p2p_wdev_mutex);
@@ -719,6 +735,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
 				struct cfg80211_connect_params *sme)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
 	struct cfg80211_bss *bss;
 	struct wmi_connect_cmd conn;
 	const u8 *ssid_eid;
@@ -727,7 +744,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
 	int rc = 0;
 	enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS;
 
-	wil_dbg_misc(wil, "connect\n");
+	wil_dbg_misc(wil, "connect, mid=%d\n", vif->mid);
 	wil_print_connect_params(wil, sme);
 
 	if (test_bit(wil_status_fwconnecting, wil->status) ||
@@ -762,18 +779,18 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
 		rc = -ENOENT;
 		goto out;
 	}
-	wil->privacy = sme->privacy;
-	wil->pbss = sme->pbss;
+	vif->privacy = sme->privacy;
+	vif->pbss = sme->pbss;
 
-	if (wil->privacy) {
+	if (vif->privacy) {
 		/* For secure assoc, remove old keys */
-		rc = wmi_del_cipher_key(wil, 0, bss->bssid,
+		rc = wmi_del_cipher_key(vif, 0, bss->bssid,
 					WMI_KEY_USE_PAIRWISE);
 		if (rc) {
 			wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(PTK) failed\n");
 			goto out;
 		}
-		rc = wmi_del_cipher_key(wil, 0, bss->bssid,
+		rc = wmi_del_cipher_key(vif, 0, bss->bssid,
 					WMI_KEY_USE_RX_GROUP);
 		if (rc) {
 			wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD(GTK) failed\n");
@@ -785,7 +802,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
 	 * elements. Send it also in case it's empty, to erase previously set
 	 * ies in FW.
 	 */
-	rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie);
+	rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie);
 	if (rc)
 		goto out;
 
@@ -803,7 +820,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
 			bss->capability);
 		goto out;
 	}
-	if (wil->privacy) {
+	if (vif->privacy) {
 		if (rsn_eid) { /* regular secure connection */
 			conn.dot11_auth_mode = WMI_AUTH11_SHARED;
 			conn.auth_mode = WMI_AUTH_WPA2_PSK;
@@ -837,13 +854,13 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
 
 	set_bit(wil_status_fwconnecting, wil->status);
 
-	rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn));
+	rc = wmi_send(wil, WMI_CONNECT_CMDID, vif->mid, &conn, sizeof(conn));
 	if (rc == 0) {
 		netif_carrier_on(ndev);
 		wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
-		wil->bss = bss;
+		vif->bss = bss;
 		/* Connect can take lots of time */
-		mod_timer(&wil->connect_timer,
+		mod_timer(&vif->connect_timer,
 			  jiffies + msecs_to_jiffies(5000));
 	} else {
 		clear_bit(wil_status_fwconnecting, wil->status);
@@ -861,8 +878,10 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy,
 {
 	int rc;
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
 
-	wil_dbg_misc(wil, "disconnect: reason=%d\n", reason_code);
+	wil_dbg_misc(wil, "disconnect: reason=%d, mid=%d\n",
+		     reason_code, vif->mid);
 
 	if (!(test_bit(wil_status_fwconnecting, wil->status) ||
 	      test_bit(wil_status_fwconnected, wil->status))) {
@@ -870,8 +889,8 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy,
 		return 0;
 	}
 
-	wil->locally_generated_disc = true;
-	rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
+	vif->locally_generated_disc = true;
+	rc = wmi_call(wil, WMI_DISCONNECT_CMDID, vif->mid, NULL, 0,
 		      WMI_DISCONNECT_EVENTID, NULL, 0,
 		      WIL6210_DISCONNECT_TO_MS);
 	if (rc)
@@ -907,6 +926,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 	const u8 *buf = params->buf;
 	size_t len = params->len, total;
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
 	int rc;
 	bool tx_status = false;
 	struct ieee80211_mgmt *mgmt_frame = (void *)buf;
@@ -923,7 +943,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 	 * different from currently "listened" channel and fail if it is.
 	 */
 
-	wil_dbg_misc(wil, "mgmt_tx\n");
+	wil_dbg_misc(wil, "mgmt_tx mid %d\n", vif->mid);
 	wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf,
 			  len, true);
 
@@ -944,7 +964,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 	cmd->len = cpu_to_le16(len);
 	memcpy(cmd->payload, buf, len);
 
-	rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, cmd, total,
+	rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, vif->mid, cmd, total,
 		      WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000);
 	if (rc == 0)
 		tx_status = !evt.evt.status;
@@ -966,10 +986,10 @@ static int wil_cfg80211_set_channel(struct wiphy *wiphy,
 	return 0;
 }
 
-static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
+static enum wmi_key_usage wil_detect_key_usage(struct wireless_dev *wdev,
 					       bool pairwise)
 {
-	struct wireless_dev *wdev = wil_to_wdev(wil);
+	struct wil6210_priv *wil = wdev_to_wil(wdev);
 	enum wmi_key_usage rc;
 
 	if (pairwise) {
@@ -997,7 +1017,7 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
 }
 
 static struct wil_sta_info *
-wil_find_sta_by_key_usage(struct wil6210_priv *wil,
+wil_find_sta_by_key_usage(struct wil6210_priv *wil, u8 mid,
 			  enum wmi_key_usage key_usage, const u8 *mac_addr)
 {
 	int cid = -EINVAL;
@@ -1007,9 +1027,9 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
 
 	/* supplicant provides Rx group key in STA mode with NULL MAC address */
 	if (mac_addr)
-		cid = wil_find_cid(wil, mac_addr);
+		cid = wil_find_cid(wil, mid, mac_addr);
 	else if (key_usage == WMI_KEY_USE_RX_GROUP)
-		cid = wil_find_cid_by_idx(wil, 0);
+		cid = wil_find_cid_by_idx(wil, mid, 0);
 	if (cid < 0) {
 		wil_err(wil, "No CID for %pM %s\n", mac_addr,
 			key_usage_str[key_usage]);
@@ -1086,9 +1106,12 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy,
 				struct key_params *params)
 {
 	int rc;
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-	enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
-	struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage,
+	struct wireless_dev *wdev = vif_to_wdev(vif);
+	enum wmi_key_usage key_usage = wil_detect_key_usage(wdev, pairwise);
+	struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, vif->mid,
+							    key_usage,
 							    mac_addr);
 
 	if (!params) {
@@ -1118,7 +1141,7 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy,
 		return -EINVAL;
 	}
 
-	rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
+	rc = wmi_add_cipher_key(vif, key_index, mac_addr, params->key_len,
 				params->key, key_usage);
 	if (!rc)
 		wil_set_crypto_rx(key_index, key_usage, cs, params);
@@ -1131,9 +1154,12 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy,
 				u8 key_index, bool pairwise,
 				const u8 *mac_addr)
 {
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
-	enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
-	struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage,
+	struct wireless_dev *wdev = vif_to_wdev(vif);
+	enum wmi_key_usage key_usage = wil_detect_key_usage(wdev, pairwise);
+	struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, vif->mid,
+							    key_usage,
 							    mac_addr);
 
 	wil_dbg_misc(wil, "del_key: %pM %s[%d]\n", mac_addr,
@@ -1146,7 +1172,7 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy,
 	if (!IS_ERR_OR_NULL(cs))
 		wil_del_rx_key(key_index, key_usage, cs);
 
-	return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage);
+	return wmi_del_cipher_key(vif, key_index, mac_addr, key_usage);
 }
 
 /* Need to be present or wiphy_new() will WARN */
@@ -1183,10 +1209,11 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy,
 					u64 cookie)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
 
 	wil_dbg_misc(wil, "cancel_remain_on_channel\n");
 
-	return wil_p2p_cancel_listen(wil, cookie);
+	return wil_p2p_cancel_listen(vif, cookie);
 }
 
 /**
@@ -1279,11 +1306,10 @@ static void wil_print_bcon_data(struct cfg80211_beacon_data *b)
 }
 
 /* internal functions for device reset and starting AP */
-static int _wil_cfg80211_set_ies(struct wiphy *wiphy,
+static int _wil_cfg80211_set_ies(struct wil6210_vif *vif,
 				 struct cfg80211_beacon_data *bcon)
 {
 	int rc;
-	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 	u16 len = 0, proberesp_len = 0;
 	u8 *ies = NULL, *proberesp = NULL;
 
@@ -1304,20 +1330,21 @@ static int _wil_cfg80211_set_ies(struct wiphy *wiphy,
 	if (rc)
 		goto out;
 
-	rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, len, ies);
+	rc = wmi_set_ie(vif, WMI_FRAME_PROBE_RESP, len, ies);
 	if (rc)
 		goto out;
 
 	if (bcon->assocresp_ies)
-		rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP,
+		rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_RESP,
 				bcon->assocresp_ies_len, bcon->assocresp_ies);
 	else
-		rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, len, ies);
+		rc = wmi_set_ie(vif, WMI_FRAME_ASSOC_RESP, len, ies);
 #if 0 /* to use beacon IE's, remove this #if 0 */
 	if (rc)
 		goto out;
 
-	rc = wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->tail_len, bcon->tail);
+	rc = wmi_set_ie(vif, WMI_FRAME_BEACON,
+			bcon->tail_len, bcon->tail);
 #endif
 out:
 	kfree(ies);
@@ -1332,6 +1359,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
 				  u8 hidden_ssid, u32 pbss)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
 	int rc;
 	struct wireless_dev *wdev = ndev->ieee80211_ptr;
 	u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
@@ -1340,7 +1368,7 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
 	if (pbss)
 		wmi_nettype = WMI_NETTYPE_P2P;
 
-	wil_dbg_misc(wil, "start_ap: is_go=%d\n", is_go);
+	wil_dbg_misc(wil, "start_ap: mid=%d, is_go=%d\n", vif->mid, is_go);
 	if (is_go && !pbss) {
 		wil_err(wil, "P2P GO must be in PBSS\n");
 		return -ENOTSUPP;
@@ -1355,34 +1383,34 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy,
 	if (rc)
 		goto out;
 
-	rc = wmi_set_ssid(wil, ssid_len, ssid);
+	rc = wmi_set_ssid(vif, ssid_len, ssid);
 	if (rc)
 		goto out;
 
-	rc = _wil_cfg80211_set_ies(wiphy, bcon);
+	rc = _wil_cfg80211_set_ies(vif, bcon);
 	if (rc)
 		goto out;
 
-	wil->privacy = privacy;
-	wil->channel = chan;
-	wil->hidden_ssid = hidden_ssid;
-	wil->pbss = pbss;
+	vif->privacy = privacy;
+	vif->channel = chan;
+	vif->hidden_ssid = hidden_ssid;
+	vif->pbss = pbss;
 
 	netif_carrier_on(ndev);
 	wil6210_bus_request(wil, WIL_MAX_BUS_REQUEST_KBPS);
 
-	rc = wmi_pcp_start(wil, bi, wmi_nettype, chan, hidden_ssid, is_go);
+	rc = wmi_pcp_start(vif, bi, wmi_nettype, chan, hidden_ssid, is_go);
 	if (rc)
 		goto err_pcp_start;
 
-	rc = wil_bcast_init(wil);
+	rc = wil_bcast_init(vif);
 	if (rc)
 		goto err_bcast;
 
 	goto out; /* success */
 
 err_bcast:
-	wmi_pcp_stop(wil);
+	wmi_pcp_stop(vif);
 err_pcp_start:
 	netif_carrier_off(ndev);
 	wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
@@ -1396,10 +1424,11 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
 				      struct cfg80211_beacon_data *bcon)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
 	int rc;
 	u32 privacy = 0;
 
-	wil_dbg_misc(wil, "change_beacon\n");
+	wil_dbg_misc(wil, "change_beacon, mid=%d\n", vif->mid);
 	wil_print_bcon_data(bcon);
 
 	if (bcon->tail &&
@@ -1408,20 +1437,20 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy,
 		privacy = 1;
 
 	/* in case privacy has changed, need to restart the AP */
-	if (wil->privacy != privacy) {
+	if (vif->privacy != privacy) {
 		struct wireless_dev *wdev = ndev->ieee80211_ptr;
 
 		wil_dbg_misc(wil, "privacy changed %d=>%d. Restarting AP\n",
-			     wil->privacy, privacy);
+			     vif->privacy, privacy);
 
 		rc = _wil_cfg80211_start_ap(wiphy, ndev, wdev->ssid,
 					    wdev->ssid_len, privacy,
 					    wdev->beacon_interval,
-					    wil->channel, bcon,
-					    wil->hidden_ssid,
-					    wil->pbss);
+					    vif->channel, bcon,
+					    vif->hidden_ssid,
+					    vif->pbss);
 	} else {
-		rc = _wil_cfg80211_set_ies(wiphy, bcon);
+		rc = _wil_cfg80211_set_ies(vif, bcon);
 	}
 
 	return rc;
@@ -1488,6 +1517,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
 				struct net_device *ndev)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
 
 	wil_dbg_misc(wil, "stop_ap\n");
 
@@ -1499,7 +1529,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
 
 	mutex_lock(&wil->mutex);
 
-	wmi_pcp_stop(wil);
+	wmi_pcp_stop(vif);
 
 	__wil_down(wil);
 
@@ -1513,9 +1543,11 @@ static int wil_cfg80211_add_station(struct wiphy *wiphy,
 				    const u8 *mac,
 				    struct station_parameters *params)
 {
+	struct wil6210_vif *vif = ndev_to_vif(dev);
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 
-	wil_dbg_misc(wil, "add station %pM aid %d\n", mac, params->aid);
+	wil_dbg_misc(wil, "add station %pM aid %d mid %d\n",
+		     mac, params->aid, vif->mid);
 
 	if (!disable_ap_sme) {
 		wil_err(wil, "not supported with AP SME enabled\n");
@@ -1527,20 +1559,21 @@ static int wil_cfg80211_add_station(struct wiphy *wiphy,
 		return -EINVAL;
 	}
 
-	return wmi_new_sta(wil, mac, params->aid);
+	return wmi_new_sta(vif, mac, params->aid);
 }
 
 static int wil_cfg80211_del_station(struct wiphy *wiphy,
 				    struct net_device *dev,
 				    struct station_del_parameters *params)
 {
+	struct wil6210_vif *vif = ndev_to_vif(dev);
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 
-	wil_dbg_misc(wil, "del_station: %pM, reason=%d\n", params->mac,
-		     params->reason_code);
+	wil_dbg_misc(wil, "del_station: %pM, reason=%d mid=%d\n",
+		     params->mac, params->reason_code, vif->mid);
 
 	mutex_lock(&wil->mutex);
-	wil6210_disconnect(wil, params->mac, params->reason_code, false);
+	wil6210_disconnect(vif, params->mac, params->reason_code, false);
 	mutex_unlock(&wil->mutex);
 
 	return 0;
@@ -1551,13 +1584,15 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy,
 				       const u8 *mac,
 				       struct station_parameters *params)
 {
+	struct wil6210_vif *vif = ndev_to_vif(dev);
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
 	int authorize;
 	int cid, i;
 	struct vring_tx_data *txdata = NULL;
 
-	wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x\n", mac,
-		     params->sta_flags_mask, params->sta_flags_set);
+	wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x mid %d\n",
+		     mac, params->sta_flags_mask, params->sta_flags_set,
+		     vif->mid);
 
 	if (!disable_ap_sme) {
 		wil_dbg_misc(wil, "not supported with AP SME enabled\n");
@@ -1567,7 +1602,7 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy,
 	if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
 		return 0;
 
-	cid = wil_find_cid(wil, mac);
+	cid = wil_find_cid(wil, vif->mid, mac);
 	if (cid < 0) {
 		wil_err(wil, "station not found\n");
 		return -ENOLINK;
@@ -1594,9 +1629,10 @@ static int wil_cfg80211_change_station(struct wiphy *wiphy,
 
 /* probe_client handling */
 static void wil_probe_client_handle(struct wil6210_priv *wil,
+				    struct wil6210_vif *vif,
 				    struct wil_probe_client_req *req)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = vif_to_ndev(vif);
 	struct wil_sta_info *sta = &wil->sta[req->cid];
 	/* assume STA is alive if it is still connected,
 	 * else FW will disconnect it
@@ -1607,51 +1643,53 @@ static void wil_probe_client_handle(struct wil6210_priv *wil,
 			      0, false, GFP_KERNEL);
 }
 
-static struct list_head *next_probe_client(struct wil6210_priv *wil)
+static struct list_head *next_probe_client(struct wil6210_vif *vif)
 {
 	struct list_head *ret = NULL;
 
-	mutex_lock(&wil->probe_client_mutex);
+	mutex_lock(&vif->probe_client_mutex);
 
-	if (!list_empty(&wil->probe_client_pending)) {
-		ret = wil->probe_client_pending.next;
+	if (!list_empty(&vif->probe_client_pending)) {
+		ret = vif->probe_client_pending.next;
 		list_del(ret);
 	}
 
-	mutex_unlock(&wil->probe_client_mutex);
+	mutex_unlock(&vif->probe_client_mutex);
 
 	return ret;
 }
 
 void wil_probe_client_worker(struct work_struct *work)
 {
-	struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
-						probe_client_worker);
+	struct wil6210_vif *vif = container_of(work, struct wil6210_vif,
+					       probe_client_worker);
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wil_probe_client_req *req;
 	struct list_head *lh;
 
-	while ((lh = next_probe_client(wil)) != NULL) {
+	while ((lh = next_probe_client(vif)) != NULL) {
 		req = list_entry(lh, struct wil_probe_client_req, list);
 
-		wil_probe_client_handle(wil, req);
+		wil_probe_client_handle(wil, vif, req);
 		kfree(req);
 	}
 }
 
-void wil_probe_client_flush(struct wil6210_priv *wil)
+void wil_probe_client_flush(struct wil6210_vif *vif)
 {
 	struct wil_probe_client_req *req, *t;
+	struct wil6210_priv *wil = vif_to_wil(vif);
 
 	wil_dbg_misc(wil, "probe_client_flush\n");
 
-	mutex_lock(&wil->probe_client_mutex);
+	mutex_lock(&vif->probe_client_mutex);
 
-	list_for_each_entry_safe(req, t, &wil->probe_client_pending, list) {
+	list_for_each_entry_safe(req, t, &vif->probe_client_pending, list) {
 		list_del(&req->list);
 		kfree(req);
 	}
 
-	mutex_unlock(&wil->probe_client_mutex);
+	mutex_unlock(&vif->probe_client_mutex);
 }
 
 static int wil_cfg80211_probe_client(struct wiphy *wiphy,
@@ -1659,10 +1697,12 @@ static int wil_cfg80211_probe_client(struct wiphy *wiphy,
 				     const u8 *peer, u64 *cookie)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = ndev_to_vif(dev);
 	struct wil_probe_client_req *req;
-	int cid = wil_find_cid(wil, peer);
+	int cid = wil_find_cid(wil, vif->mid, peer);
 
-	wil_dbg_misc(wil, "probe_client: %pM => CID %d\n", peer, cid);
+	wil_dbg_misc(wil, "probe_client: %pM => CID %d MID %d\n",
+		     peer, cid, vif->mid);
 
 	if (cid < 0)
 		return -ENOLINK;
@@ -1674,12 +1714,12 @@ static int wil_cfg80211_probe_client(struct wiphy *wiphy,
 	req->cid = cid;
 	req->cookie = cid;
 
-	mutex_lock(&wil->probe_client_mutex);
-	list_add_tail(&req->list, &wil->probe_client_pending);
-	mutex_unlock(&wil->probe_client_mutex);
+	mutex_lock(&vif->probe_client_mutex);
+	list_add_tail(&req->list, &vif->probe_client_pending);
+	mutex_unlock(&vif->probe_client_mutex);
 
 	*cookie = req->cookie;
-	queue_work(wil->wq_service, &wil->probe_client_worker);
+	queue_work(wil->wq_service, &vif->probe_client_worker);
 	return 0;
 }
 
@@ -1688,11 +1728,12 @@ static int wil_cfg80211_change_bss(struct wiphy *wiphy,
 				   struct bss_parameters *params)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = ndev_to_vif(dev);
 
 	if (params->ap_isolate >= 0) {
-		wil_dbg_misc(wil, "change_bss: ap_isolate %d => %d\n",
-			     wil->ap_isolate, params->ap_isolate);
-		wil->ap_isolate = params->ap_isolate;
+		wil_dbg_misc(wil, "change_bss: ap_isolate MID %d, %d => %d\n",
+			     vif->mid, vif->ap_isolate, params->ap_isolate);
+		vif->ap_isolate = params->ap_isolate;
 	}
 
 	return 0;
@@ -1738,7 +1779,7 @@ static int wil_cfg80211_suspend(struct wiphy *wiphy,
 	mutex_lock(&wil->mutex);
 	mutex_lock(&wil->p2p_wdev_mutex);
 	wil_p2p_stop_radio_operations(wil);
-	wil_abort_scan(wil, true);
+	wil_abort_scan(ndev_to_vif(wil->main_ndev), true);
 	mutex_unlock(&wil->p2p_wdev_mutex);
 	mutex_unlock(&wil->mutex);
 
@@ -1761,8 +1802,12 @@ static int wil_cfg80211_resume(struct wiphy *wiphy)
 			      struct cfg80211_sched_scan_request *request)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = ndev_to_vif(dev);
 	int i, rc;
 
+	if (vif->mid != 0)
+		return -EOPNOTSUPP;
+
 	wil_dbg_misc(wil,
 		     "sched scan start: n_ssids %d, ie_len %zu, flags 0x%x\n",
 		     request->n_ssids, request->ie_len, request->flags);
@@ -1796,7 +1841,8 @@ static int wil_cfg80211_resume(struct wiphy *wiphy)
 			     i, sp->interval, sp->iterations);
 	}
 
-	rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie);
+	rc = wmi_set_ie(vif, WMI_FRAME_PROBE_REQ,
+			request->ie_len, request->ie);
 	if (rc)
 		return rc;
 	return wmi_start_sched_scan(wil, request);
@@ -1807,8 +1853,12 @@ static int wil_cfg80211_resume(struct wiphy *wiphy)
 			     u64 reqid)
 {
 	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wil6210_vif *vif = ndev_to_vif(dev);
 	int rc;
 
+	if (vif->mid != 0)
+		return -EOPNOTSUPP;
+
 	rc = wmi_stop_sched_scan(wil);
 	/* device would return error if it thinks PNO is already stopped.
 	 * ignore the return code so user space and driver gets back in-sync
@@ -2015,11 +2065,11 @@ void wil_p2p_wdev_free(struct wil6210_priv *wil)
 	mutex_lock(&wil->p2p_wdev_mutex);
 	p2p_wdev = wil->p2p_wdev;
 	wil->p2p_wdev = NULL;
-	wil->radio_wdev = wil_to_wdev(wil);
+	wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
 	mutex_unlock(&wil->p2p_wdev_mutex);
 	if (p2p_wdev) {
 		cfg80211_unregister_wdev(p2p_wdev);
-		vif = wdev_to_vif(p2p_wdev);
+		vif = wdev_to_vif(wil, p2p_wdev);
 		kfree(vif);
 	}
 }
@@ -2045,6 +2095,7 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy,
 				 const void *data, int data_len)
 {
 	struct wil6210_priv *wil = wdev_to_wil(wdev);
+	struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
 	int rc;
 	struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
 	u16 sector_index;
@@ -2101,8 +2152,8 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy,
 	cmd.sector_type = sector_type;
 	cmd.rf_modules_vec = rf_modules_vec & 0xFF;
 	memset(&reply, 0, sizeof(reply));
-	rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd),
-		      WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID,
+	rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, vif->mid,
+		      &cmd, sizeof(cmd), WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID,
 		      &reply, sizeof(reply),
 		      500);
 	if (rc)
@@ -2164,6 +2215,7 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy,
 				 const void *data, int data_len)
 {
 	struct wil6210_priv *wil = wdev_to_wil(wdev);
+	struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
 	int rc, tmp;
 	struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
 	struct nlattr *tb2[QCA_ATTR_DMG_RF_SECTOR_CFG_MAX + 1];
@@ -2258,8 +2310,8 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy,
 
 	cmd.rf_modules_vec = rf_modules_vec & 0xFF;
 	memset(&reply, 0, sizeof(reply));
-	rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, &cmd, sizeof(cmd),
-		      WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID,
+	rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, vif->mid,
+		      &cmd, sizeof(cmd), WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID,
 		      &reply, sizeof(reply),
 		      500);
 	if (rc)
@@ -2272,6 +2324,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy,
 				      const void *data, int data_len)
 {
 	struct wil6210_priv *wil = wdev_to_wil(wdev);
+	struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
 	int rc;
 	struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
 	u8 sector_type, mac_addr[ETH_ALEN];
@@ -2305,7 +2358,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy,
 
 	if (tb[QCA_ATTR_MAC_ADDR]) {
 		ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR]));
-		cid = wil_find_cid(wil, mac_addr);
+		cid = wil_find_cid(wil, vif->mid, mac_addr);
 		if (cid < 0) {
 			wil_err(wil, "invalid MAC address %pM\n", mac_addr);
 			return -ENOENT;
@@ -2321,7 +2374,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy,
 	cmd.cid = (u8)cid;
 	cmd.sector_type = sector_type;
 	memset(&reply, 0, sizeof(reply));
-	rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID,
+	rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID, vif->mid,
 		      &cmd, sizeof(cmd),
 		      WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID,
 		      &reply, sizeof(reply),
@@ -2354,7 +2407,7 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy,
 }
 
 static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil,
-					  u16 sector_index,
+					  u8 mid, u16 sector_index,
 					  u8 sector_type, u8 cid)
 {
 	struct wmi_set_selected_rf_sector_index_cmd cmd;
@@ -2369,7 +2422,7 @@ static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil,
 	cmd.sector_type = sector_type;
 	cmd.cid = (u8)cid;
 	memset(&reply, 0, sizeof(reply));
-	rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID,
+	rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID, mid,
 		      &cmd, sizeof(cmd),
 		      WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID,
 		      &reply, sizeof(reply),
@@ -2384,6 +2437,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy,
 				      const void *data, int data_len)
 {
 	struct wil6210_priv *wil = wdev_to_wil(wdev);
+	struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
 	int rc;
 	struct nlattr *tb[QCA_ATTR_DMG_RF_SECTOR_MAX + 1];
 	u16 sector_index;
@@ -2423,7 +2477,7 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy,
 	if (tb[QCA_ATTR_MAC_ADDR]) {
 		ether_addr_copy(mac_addr, nla_data(tb[QCA_ATTR_MAC_ADDR]));
 		if (!is_broadcast_ether_addr(mac_addr)) {
-			cid = wil_find_cid(wil, mac_addr);
+			cid = wil_find_cid(wil, vif->mid, mac_addr);
 			if (cid < 0) {
 				wil_err(wil, "invalid MAC address %pM\n",
 					mac_addr);
@@ -2445,17 +2499,20 @@ static int wil_rf_sector_set_selected(struct wiphy *wiphy,
 	}
 
 	if (cid >= 0) {
-		rc = wil_rf_sector_wmi_set_selected(wil, sector_index,
+		rc = wil_rf_sector_wmi_set_selected(wil, vif->mid, sector_index,
 						    sector_type, cid);
 	} else {
 		/* unlock all cids */
 		rc = wil_rf_sector_wmi_set_selected(
-			wil, WMI_INVALID_RF_SECTOR_INDEX, sector_type,
-			WIL_CID_ALL);
+			wil, vif->mid, WMI_INVALID_RF_SECTOR_INDEX,
+			sector_type, WIL_CID_ALL);
 		if (rc == -EINVAL) {
 			for (i = 0; i < WIL6210_MAX_CID; i++) {
+				if (wil->sta[i].mid != vif->mid)
+					continue;
 				rc = wil_rf_sector_wmi_set_selected(
-					wil, WMI_INVALID_RF_SECTOR_INDEX,
+					wil, vif->mid,
+					WMI_INVALID_RF_SECTOR_INDEX,
 					sector_type, i);
 				/* the FW will silently ignore and return
 				 * success for unused cid, so abort the loop
diff --git a/drivers/net/wireless/ath/wil6210/debug.c b/drivers/net/wireless/ath/wil6210/debug.c
index 217a459..a9befb9 100644
--- a/drivers/net/wireless/ath/wil6210/debug.c
+++ b/drivers/net/wireless/ath/wil6210/debug.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013,2016 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -25,7 +26,7 @@ void __wil_err(struct wil6210_priv *wil, const char *fmt, ...)
 	va_start(args, fmt);
 	vaf.fmt = fmt;
 	vaf.va = &args;
-	netdev_err(wil_to_ndev(wil), "%pV", &vaf);
+	netdev_err(wil->main_ndev, "%pV", &vaf);
 	trace_wil6210_log_err(&vaf);
 	va_end(args);
 }
@@ -41,7 +42,7 @@ void __wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...)
 	va_start(args, fmt);
 	vaf.fmt = fmt;
 	vaf.va = &args;
-	netdev_err(wil_to_ndev(wil), "%pV", &vaf);
+	netdev_err(wil->main_ndev, "%pV", &vaf);
 	trace_wil6210_log_err(&vaf);
 	va_end(args);
 }
@@ -57,7 +58,7 @@ void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...)
 	va_start(args, fmt);
 	vaf.fmt = fmt;
 	vaf.va = &args;
-	netdev_dbg(wil_to_ndev(wil), "%pV", &vaf);
+	netdev_dbg(wil->main_ndev, "%pV", &vaf);
 	trace_wil6210_log_dbg(&vaf);
 	va_end(args);
 }
@@ -70,7 +71,7 @@ void __wil_info(struct wil6210_priv *wil, const char *fmt, ...)
 	va_start(args, fmt);
 	vaf.fmt = fmt;
 	vaf.va = &args;
-	netdev_info(wil_to_ndev(wil), "%pV", &vaf);
+	netdev_info(wil->main_ndev, "%pV", &vaf);
 	trace_wil6210_log_info(&vaf);
 	va_end(args);
 }
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 4a48882..636da5e 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -621,7 +622,7 @@ static ssize_t wil_write_file_reset(struct file *file, const char __user *buf,
 				    size_t len, loff_t *ppos)
 {
 	struct wil6210_priv *wil = file->private_data;
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 
 	/**
 	 * BUG:
@@ -716,27 +717,44 @@ static ssize_t wil_write_back(struct file *file, const char __user *buf,
 	if (rc < 2)
 		return -EINVAL;
 
-	if (0 == strcmp(cmd, "add")) {
-		if (rc < 3) {
-			wil_err(wil, "BACK: add require at least 2 params\n");
+	if ((strcmp(cmd, "add") == 0) ||
+	    (strcmp(cmd, "del_tx") == 0)) {
+		struct vring_tx_data *txdata;
+
+		if (p1 < 0 || p1 >= WIL6210_MAX_TX_RINGS) {
+			wil_err(wil, "BACK: invalid ring id %d\n", p1);
 			return -EINVAL;
 		}
-		if (rc < 4)
-			p3 = 0;
-		wmi_addba(wil, p1, p2, p3);
-	} else if (0 == strcmp(cmd, "del_tx")) {
-		if (rc < 3)
-			p2 = WLAN_REASON_QSTA_LEAVE_QBSS;
-		wmi_delba_tx(wil, p1, p2);
-	} else if (0 == strcmp(cmd, "del_rx")) {
+		txdata = &wil->vring_tx_data[p1];
+		if (strcmp(cmd, "add") == 0) {
+			if (rc < 3) {
+				wil_err(wil, "BACK: add require at least 2 params\n");
+				return -EINVAL;
+			}
+			if (rc < 4)
+				p3 = 0;
+			wmi_addba(wil, txdata->mid, p1, p2, p3);
+		} else {
+			if (rc < 3)
+				p2 = WLAN_REASON_QSTA_LEAVE_QBSS;
+			wmi_delba_tx(wil, txdata->mid, p1, p2);
+		}
+	} else if (strcmp(cmd, "del_rx") == 0) {
+		struct wil_sta_info *sta;
+
 		if (rc < 3) {
 			wil_err(wil,
 				"BACK: del_rx require at least 2 params\n");
 			return -EINVAL;
 		}
+		if (p1 < 0 || p1 >= WIL6210_MAX_CID) {
+			wil_err(wil, "BACK: invalid CID %d\n", p1);
+			return -EINVAL;
+		}
 		if (rc < 4)
 			p3 = WLAN_REASON_QSTA_LEAVE_QBSS;
-		wmi_delba_rx(wil, mk_cidxtid(p1, p2), p3);
+		sta = &wil->sta[p1];
+		wmi_delba_rx(wil, sta->mid, mk_cidxtid(p1, p2), p3);
 	} else {
 		wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd);
 		return -EINVAL;
@@ -855,7 +873,7 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
 {
 	struct wil6210_priv *wil = file->private_data;
 	struct wiphy *wiphy = wil_to_wiphy(wil);
-	struct wireless_dev *wdev = wil_to_wdev(wil);
+	struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
 	struct cfg80211_mgmt_tx_params params;
 	int rc;
 	void *frame;
@@ -890,6 +908,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
 				  size_t len, loff_t *ppos)
 {
 	struct wil6210_priv *wil = file->private_data;
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	struct wmi_cmd_hdr *wmi;
 	void *cmd;
 	int cmdlen = len - sizeof(struct wmi_cmd_hdr);
@@ -912,7 +931,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf,
 	cmd = (cmdlen > 0) ? &wmi[1] : NULL;
 	cmdid = le16_to_cpu(wmi->command_id);
 
-	rc1 = wmi_send(wil, cmdid, cmd, cmdlen);
+	rc1 = wmi_send(wil, cmdid, vif->mid, cmd, cmdlen);
 	kfree(wmi);
 
 	wil_info(wil, "0x%04x[%d] -> %d\n", cmdid, cmdlen, rc1);
@@ -1050,6 +1069,7 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data)
 	int rc;
 	int i;
 	struct wil6210_priv *wil = s->private;
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	struct wmi_notify_req_cmd cmd = {
 		.interval_usec = 0,
 	};
@@ -1062,7 +1082,8 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data)
 		u32 status;
 
 		cmd.cid = i;
-		rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd),
+		rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid,
+			      &cmd, sizeof(cmd),
 			      WMI_NOTIFY_REQ_DONE_EVENTID, &reply,
 			      sizeof(reply), 20);
 		/* if reply is all-0, ignore this CID */
@@ -1155,7 +1176,7 @@ static int wil_temp_seq_open(struct inode *inode, struct file *file)
 static int wil_freq_debugfs_show(struct seq_file *s, void *data)
 {
 	struct wil6210_priv *wil = s->private;
-	struct wireless_dev *wdev = wil_to_wdev(wil);
+	struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
 	u16 freq = wdev->chandef.chan ? wdev->chandef.chan->center_freq : 0;
 
 	seq_printf(s, "Freq = %d\n", freq);
@@ -1180,6 +1201,7 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data)
 {
 	struct wil6210_priv *wil = s->private;
 	struct station_info sinfo;
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int i, rc;
 
 	for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
@@ -1200,7 +1222,7 @@ static int wil_link_debugfs_show(struct seq_file *s, void *data)
 		seq_printf(s, "[%d] %pM %s\n", i, p->addr, status);
 
 		if (p->status == wil_sta_connected) {
-			rc = wil_cid_fill_sinfo(wil, i, &sinfo);
+			rc = wil_cid_fill_sinfo(vif, i, &sinfo);
 			if (rc)
 				return rc;
 
@@ -1229,7 +1251,7 @@ static int wil_link_seq_open(struct inode *inode, struct file *file)
 static int wil_info_debugfs_show(struct seq_file *s, void *data)
 {
 	struct wil6210_priv *wil = s->private;
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	int is_ac = power_supply_is_system_supplied();
 	int rx = atomic_xchg(&wil->isr_count_rx, 0);
 	int tx = atomic_xchg(&wil->isr_count_tx, 0);
@@ -1773,11 +1795,9 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil,
 
 /* fields in struct wil6210_priv */
 static const struct dbg_off dbg_wil_off[] = {
-	WIL_FIELD(privacy,	0444,		doff_u32),
 	WIL_FIELD(status[0],	0644,	doff_ulong),
 	WIL_FIELD(hw_version,	0444,	doff_x32),
 	WIL_FIELD(recovery_count, 0444,	doff_u32),
-	WIL_FIELD(ap_isolate,	0444,	doff_u32),
 	WIL_FIELD(discovery_mode, 0644,	doff_u8),
 	WIL_FIELD(chip_revision, 0444,	doff_u8),
 	WIL_FIELD(abft_len, 0644,		doff_u8),
diff --git a/drivers/net/wireless/ath/wil6210/ethtool.c b/drivers/net/wireless/ath/wil6210/ethtool.c
index 66200f6..e7ff41e 100644
--- a/drivers/net/wireless/ath/wil6210/ethtool.c
+++ b/drivers/net/wireless/ath/wil6210/ethtool.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014,2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -74,12 +75,13 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev,
 				       struct ethtool_coalesce *cp)
 {
 	struct wil6210_priv *wil = ndev_to_wil(ndev);
+	struct wireless_dev *wdev = ndev->ieee80211_ptr;
 	int ret;
 
 	wil_dbg_misc(wil, "ethtoolops_set_coalesce: rx %d usec, tx %d usec\n",
 		     cp->rx_coalesce_usecs, cp->tx_coalesce_usecs);
 
-	if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+	if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
 		wil_dbg_misc(wil, "No IRQ coalescing in monitor mode\n");
 		return -EINVAL;
 	}
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index 1835187..ef8f9a7 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -188,12 +188,14 @@ void wil_unmask_irq(struct wil6210_priv *wil)
 
 void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
 {
+	struct wireless_dev *wdev = wil->main_ndev->ieee80211_ptr;
+
 	wil_dbg_irq(wil, "configure_interrupt_moderation\n");
 
 	/* disable interrupt moderation for monitor
 	 * to get better timestamp precision
 	 */
-	if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR)
+	if (wdev->iftype == NL80211_IFTYPE_MONITOR)
 		return;
 
 	/* Disable and clear tx counter before (re)configuration */
@@ -340,7 +342,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
 
 static void wil_notify_fw_error(struct wil6210_priv *wil)
 {
-	struct device *dev = &wil_to_ndev(wil)->dev;
+	struct device *dev = &wil->main_ndev->dev;
 	char *envp[3] = {
 		[0] = "SOURCE=wil6210",
 		[1] = "EVENT=FW_ERROR",
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 04c8651..b151f1c 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -160,24 +160,25 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
 	}
 }
 
-static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
+static void wil_disconnect_cid(struct wil6210_vif *vif, int cid,
 			       u16 reason_code, bool from_event)
 __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
 {
 	uint i;
-	struct net_device *ndev = wil_to_ndev(wil);
-	struct wireless_dev *wdev = wil->wdev;
+	struct wil6210_priv *wil = vif_to_wil(vif);
+	struct net_device *ndev = vif_to_ndev(vif);
+	struct wireless_dev *wdev = vif_to_wdev(vif);
 	struct wil_sta_info *sta = &wil->sta[cid];
 
 	might_sleep();
-	wil_dbg_misc(wil, "disconnect_cid: CID %d, status %d\n",
-		     cid, sta->status);
+	wil_dbg_misc(wil, "disconnect_cid: CID %d, MID %d, status %d\n",
+		     cid, sta->mid, sta->status);
 	/* inform upper/lower layers */
 	if (sta->status != wil_sta_unused) {
 		if (!from_event) {
 			bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ?
 						disable_ap_sme : false;
-			wmi_disconnect_sta(wil, sta->addr, reason_code,
+			wmi_disconnect_sta(vif, sta->addr, reason_code,
 					   true, del_sta);
 		}
 
@@ -191,6 +192,7 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
 			break;
 		}
 		sta->status = wil_sta_unused;
+		sta->mid = U8_MAX;
 	}
 	/* reorder buffers */
 	for (i = 0; i < WIL_STA_TID_NUM; i++) {
@@ -216,28 +218,33 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
 	memset(&sta->stats, 0, sizeof(sta->stats));
 }
 
-static bool wil_is_connected(struct wil6210_priv *wil)
+static bool wil_vif_is_connected(struct wil6210_priv *wil, u8 mid)
 {
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
-		if (wil->sta[i].status == wil_sta_connected)
+		if (wil->sta[i].mid == mid &&
+		    wil->sta[i].status == wil_sta_connected)
 			return true;
 	}
 
 	return false;
 }
 
-static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
+static void _wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid,
 				u16 reason_code, bool from_event)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int cid = -ENOENT;
-	struct net_device *ndev = wil_to_ndev(wil);
-	struct wireless_dev *wdev = wil->wdev;
+	struct net_device *ndev;
+	struct wireless_dev *wdev;
 
-	if (unlikely(!ndev))
+	if (unlikely(!vif))
 		return;
 
+	ndev = vif_to_ndev(vif);
+	wdev = vif_to_wdev(vif);
+
 	might_sleep();
 	wil_info(wil, "bssid=%pM, reason=%d, ev%s\n", bssid,
 		 reason_code, from_event ? "+" : "-");
@@ -254,22 +261,22 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
 	 */
 	if (bssid && !is_broadcast_ether_addr(bssid) &&
 	    !ether_addr_equal_unaligned(ndev->dev_addr, bssid)) {
-		cid = wil_find_cid(wil, bssid);
+		cid = wil_find_cid(wil, vif->mid, bssid);
 		wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n",
 			     bssid, cid, reason_code);
 		if (cid >= 0) /* disconnect 1 peer */
-			wil_disconnect_cid(wil, cid, reason_code, from_event);
+			wil_disconnect_cid(vif, cid, reason_code, from_event);
 	} else { /* all */
 		wil_dbg_misc(wil, "Disconnect all\n");
 		for (cid = 0; cid < WIL6210_MAX_CID; cid++)
-			wil_disconnect_cid(wil, cid, reason_code, from_event);
+			wil_disconnect_cid(vif, cid, reason_code, from_event);
 	}
 
 	/* link state */
 	switch (wdev->iftype) {
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_P2P_CLIENT:
-		wil_bcast_fini(wil);
+		wil_bcast_fini(vif);
 		wil_update_net_queues_bh(wil, NULL, true);
 		netif_carrier_off(ndev);
 		wil6210_bus_request(wil, WIL_DEFAULT_BUS_REQUEST_KBPS);
@@ -278,20 +285,20 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
 			clear_bit(wil_status_fwconnected, wil->status);
 			cfg80211_disconnected(ndev, reason_code,
 					      NULL, 0,
-					      wil->locally_generated_disc,
+					      vif->locally_generated_disc,
 					      GFP_KERNEL);
-			wil->locally_generated_disc = false;
+			vif->locally_generated_disc = false;
 		} else if (test_bit(wil_status_fwconnecting, wil->status)) {
 			cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
 						WLAN_STATUS_UNSPECIFIED_FAILURE,
 						GFP_KERNEL);
-			wil->bss = NULL;
+			vif->bss = NULL;
 		}
 		clear_bit(wil_status_fwconnecting, wil->status);
 		break;
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_P2P_GO:
-		if (!wil_is_connected(wil)) {
+		if (!wil_vif_is_connected(wil, vif->mid)) {
 			wil_update_net_queues_bh(wil, NULL, true);
 			clear_bit(wil_status_fwconnected, wil->status);
 		} else {
@@ -303,11 +310,12 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
 	}
 }
 
-static void wil_disconnect_worker(struct work_struct *work)
+void wil_disconnect_worker(struct work_struct *work)
 {
-	struct wil6210_priv *wil = container_of(work,
-			struct wil6210_priv, disconnect_worker);
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct wil6210_vif *vif = container_of(work,
+			struct wil6210_vif, disconnect_worker);
+	struct wil6210_priv *wil = vif_to_wil(vif);
+	struct net_device *ndev = vif_to_ndev(vif);
 	int rc;
 	struct {
 		struct wmi_cmd_hdr wmi;
@@ -322,7 +330,7 @@ static void wil_disconnect_worker(struct work_struct *work)
 		/* already disconnected */
 		return;
 
-	rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
+	rc = wmi_call(wil, WMI_DISCONNECT_CMDID, vif->mid, NULL, 0,
 		      WMI_DISCONNECT_EVENTID, &reply, sizeof(reply),
 		      WIL6210_DISCONNECT_TO_MS);
 	if (rc) {
@@ -337,30 +345,6 @@ static void wil_disconnect_worker(struct work_struct *work)
 	clear_bit(wil_status_fwconnecting, wil->status);
 }
 
-static void wil_connect_timer_fn(struct timer_list *t)
-{
-	struct wil6210_priv *wil = from_timer(wil, t, connect_timer);
-	bool q;
-
-	wil_err(wil, "Connect timeout detected, disconnect station\n");
-
-	/* reschedule to thread context - disconnect won't
-	 * run from atomic context.
-	 * queue on wmi_wq to prevent race with connect event.
-	 */
-	q = queue_work(wil->wmi_wq, &wil->disconnect_worker);
-	wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q);
-}
-
-static void wil_scan_timer_fn(struct timer_list *t)
-{
-	struct wil6210_priv *wil = from_timer(wil, t, scan_timer);
-
-	clear_bit(wil_status_fwready, wil->status);
-	wil_err(wil, "Scan timeout detected, start fw error recovery\n");
-	wil_fw_error_recovery(wil);
-}
-
 static int wil_wait_for_recovery(struct wil6210_priv *wil)
 {
 	if (wait_event_interruptible(wil->wq, wil->recovery_state !=
@@ -394,12 +378,12 @@ static void wil_fw_error_worker(struct work_struct *work)
 {
 	struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
 						fw_error_worker);
-	struct wireless_dev *wdev = wil->wdev;
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
+	struct wireless_dev *wdev = ndev->ieee80211_ptr;
 
 	wil_dbg_misc(wil, "fw error worker\n");
 
-	if (!(ndev->flags & IFF_UP)) {
+	if (!ndev || !(ndev->flags & IFF_UP)) {
 		wil_info(wil, "No recovery - interface is down\n");
 		return;
 	}
@@ -429,6 +413,10 @@ static void wil_fw_error_worker(struct work_struct *work)
 		return;
 
 	mutex_lock(&wil->mutex);
+	/* Needs adaptation for multiple VIFs
+	 * need to go over all VIFs and consider the appropriate
+	 * recovery.
+	 */
 	switch (wdev->iftype) {
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_P2P_CLIENT:
@@ -461,8 +449,9 @@ static int wil_find_free_vring(struct wil6210_priv *wil)
 	return -EINVAL;
 }
 
-int wil_tx_init(struct wil6210_priv *wil, int cid)
+int wil_tx_init(struct wil6210_vif *vif, int cid)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc = -EINVAL, ringid;
 
 	if (cid < 0) {
@@ -475,21 +464,22 @@ int wil_tx_init(struct wil6210_priv *wil, int cid)
 		goto out;
 	}
 
-	wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n",
-		    cid, ringid);
+	wil_dbg_wmi(wil, "Configure for connection CID %d MID %d vring %d\n",
+		    cid, vif->mid, ringid);
 
-	rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0);
+	rc = wil_vring_init_tx(vif, ringid, 1 << tx_ring_order, cid, 0);
 	if (rc)
-		wil_err(wil, "wil_vring_init_tx for CID %d vring %d failed\n",
-			cid, ringid);
+		wil_err(wil, "init TX for CID %d MID %d vring %d failed\n",
+			cid, vif->mid, ringid);
 
 out:
 	return rc;
 }
 
-int wil_bcast_init(struct wil6210_priv *wil)
+int wil_bcast_init(struct wil6210_vif *vif)
 {
-	int ri = wil->bcast_vring, rc;
+	struct wil6210_priv *wil = vif_to_wil(vif);
+	int ri = vif->bcast_vring, rc;
 
 	if ((ri >= 0) && wil->vring_tx[ri].va)
 		return 0;
@@ -498,22 +488,23 @@ int wil_bcast_init(struct wil6210_priv *wil)
 	if (ri < 0)
 		return ri;
 
-	wil->bcast_vring = ri;
-	rc = wil_vring_init_bcast(wil, ri, 1 << bcast_ring_order);
+	vif->bcast_vring = ri;
+	rc = wil_vring_init_bcast(vif, ri, 1 << bcast_ring_order);
 	if (rc)
-		wil->bcast_vring = -1;
+		vif->bcast_vring = -1;
 
 	return rc;
 }
 
-void wil_bcast_fini(struct wil6210_priv *wil)
+void wil_bcast_fini(struct wil6210_vif *vif)
 {
-	int ri = wil->bcast_vring;
+	struct wil6210_priv *wil = vif_to_wil(vif);
+	int ri = vif->bcast_vring;
 
 	if (ri < 0)
 		return;
 
-	wil->bcast_vring = -1;
+	vif->bcast_vring = -1;
 	wil_vring_fini_tx(wil, ri);
 }
 
@@ -524,15 +515,16 @@ int wil_priv_init(struct wil6210_priv *wil)
 	wil_dbg_misc(wil, "priv_init\n");
 
 	memset(wil->sta, 0, sizeof(wil->sta));
-	for (i = 0; i < WIL6210_MAX_CID; i++)
+	for (i = 0; i < WIL6210_MAX_CID; i++) {
 		spin_lock_init(&wil->sta[i].tid_rx_lock);
+		wil->sta[i].mid = U8_MAX;
+	}
 
 	for (i = 0; i < WIL6210_MAX_TX_RINGS; i++)
 		spin_lock_init(&wil->vring_tx_data[i].lock);
 
 	mutex_init(&wil->mutex);
 	mutex_init(&wil->wmi_mutex);
-	mutex_init(&wil->probe_client_mutex);
 	mutex_init(&wil->p2p_wdev_mutex);
 	mutex_init(&wil->halp.lock);
 
@@ -540,22 +532,12 @@ int wil_priv_init(struct wil6210_priv *wil)
 	init_completion(&wil->wmi_call);
 	init_completion(&wil->halp.comp);
 
-	wil->bcast_vring = -1;
-	timer_setup(&wil->connect_timer, wil_connect_timer_fn, 0);
-	timer_setup(&wil->scan_timer, wil_scan_timer_fn, 0);
-	timer_setup(&wil->p2p.discovery_timer, wil_p2p_discovery_timer_fn, 0);
-
-	INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
 	INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
 	INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker);
-	INIT_WORK(&wil->probe_client_worker, wil_probe_client_worker);
-	INIT_WORK(&wil->p2p.delayed_listen_work, wil_p2p_delayed_listen_work);
 
 	INIT_LIST_HEAD(&wil->pending_wmi_ev);
-	INIT_LIST_HEAD(&wil->probe_client_pending);
 	spin_lock_init(&wil->wmi_ev_lock);
 	spin_lock_init(&wil->net_queue_lock);
-	wil->net_queue_stopped = 1;
 	init_waitqueue_head(&wil->wq);
 
 	wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi");
@@ -582,6 +564,8 @@ int wil_priv_init(struct wil6210_priv *wil)
 	memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));
 	wil->vring_idle_trsh = 16;
 
+	wil->reply_mid = U8_MAX;
+
 	return 0;
 
 out_wmi_wq:
@@ -600,7 +584,7 @@ void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
 
 /**
  * wil6210_disconnect - disconnect one connection
- * @wil: driver context
+ * @vif: virtual interface context
  * @bssid: peer to disconnect, NULL to disconnect all
  * @reason_code: Reason code for the Disassociation frame
  * @from_event: whether is invoked from FW event handler
@@ -608,13 +592,15 @@ void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
  * Disconnect and release associated resources. If invoked not from the
  * FW event handler, issue WMI command(s) to trigger MAC disconnect.
  */
-void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
+void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid,
 			u16 reason_code, bool from_event)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
+
 	wil_dbg_misc(wil, "disconnect\n");
 
-	del_timer_sync(&wil->connect_timer);
-	_wil6210_disconnect(wil, bssid, reason_code, from_event);
+	del_timer_sync(&vif->connect_timer);
+	_wil6210_disconnect(vif, bssid, reason_code, from_event);
 }
 
 void wil_priv_deinit(struct wil6210_priv *wil)
@@ -622,18 +608,8 @@ void wil_priv_deinit(struct wil6210_priv *wil)
 	wil_dbg_misc(wil, "priv_deinit\n");
 
 	wil_set_recovery_state(wil, fw_recovery_idle);
-	del_timer_sync(&wil->scan_timer);
-	del_timer_sync(&wil->p2p.discovery_timer);
-	cancel_work_sync(&wil->disconnect_worker);
 	cancel_work_sync(&wil->fw_error_worker);
-	cancel_work_sync(&wil->p2p.discovery_expired_work);
-	cancel_work_sync(&wil->p2p.delayed_listen_work);
-	mutex_lock(&wil->mutex);
-	wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
-	mutex_unlock(&wil->mutex);
 	wmi_event_flush(wil);
-	wil_probe_client_flush(wil);
-	cancel_work_sync(&wil->probe_client_worker);
 	destroy_workqueue(wil->wq_service);
 	destroy_workqueue(wil->wmi_wq);
 }
@@ -943,7 +919,7 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
 
 static int wil_get_bl_info(struct wil6210_priv *wil)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	struct wiphy *wiphy = wil_to_wiphy(wil);
 	union {
 		struct bl_dedicated_registers_v0 bl0;
@@ -1035,7 +1011,7 @@ static void wil_bl_crash_info(struct wil6210_priv *wil, bool is_err)
 
 static int wil_get_otp_info(struct wil6210_priv *wil)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	struct wiphy *wiphy = wil_to_wiphy(wil);
 	u8 mac[8];
 
@@ -1069,8 +1045,9 @@ static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
 	return 0;
 }
 
-void wil_abort_scan(struct wil6210_priv *wil, bool sync)
+void wil_abort_scan(struct wil6210_vif *vif, bool sync)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 	struct cfg80211_scan_info info = {
 		.aborted = true,
@@ -1078,22 +1055,22 @@ void wil_abort_scan(struct wil6210_priv *wil, bool sync)
 
 	lockdep_assert_held(&wil->p2p_wdev_mutex);
 
-	if (!wil->scan_request)
+	if (!vif->scan_request)
 		return;
 
-	wil_dbg_misc(wil, "Abort scan_request 0x%p\n", wil->scan_request);
-	del_timer_sync(&wil->scan_timer);
+	wil_dbg_misc(wil, "Abort scan_request 0x%p\n", vif->scan_request);
+	del_timer_sync(&vif->scan_timer);
 	mutex_unlock(&wil->p2p_wdev_mutex);
-	rc = wmi_abort_scan(wil);
+	rc = wmi_abort_scan(vif);
 	if (!rc && sync)
-		wait_event_interruptible_timeout(wil->wq, !wil->scan_request,
+		wait_event_interruptible_timeout(wil->wq, !vif->scan_request,
 						 msecs_to_jiffies(
 						 WAIT_FOR_SCAN_ABORT_MS));
 
 	mutex_lock(&wil->p2p_wdev_mutex);
-	if (wil->scan_request) {
-		cfg80211_scan_done(wil->scan_request, &info);
-		wil->scan_request = NULL;
+	if (vif->scan_request) {
+		cfg80211_scan_done(vif->scan_request, &info);
+		vif->scan_request = NULL;
 	}
 }
 
@@ -1148,6 +1125,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
 	int rc;
 	unsigned long status_flags = BIT(wil_status_resetting);
 	int no_flash;
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 
 	wil_dbg_misc(wil, "reset\n");
 
@@ -1158,7 +1136,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
 		static const u8 mac[ETH_ALEN] = {
 			0x00, 0xde, 0xad, 0x12, 0x34, 0x56,
 		};
-		struct net_device *ndev = wil_to_ndev(wil);
+		struct net_device *ndev = wil->main_ndev;
 
 		ether_addr_copy(ndev->perm_addr, mac);
 		ether_addr_copy(ndev->dev_addr, ndev->perm_addr);
@@ -1196,15 +1174,15 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
 		goto out;
 	}
 
-	cancel_work_sync(&wil->disconnect_worker);
-	wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
-	wil_bcast_fini(wil);
+	cancel_work_sync(&vif->disconnect_worker);
+	wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
+	wil_bcast_fini(vif);
 
 	/* Disable device led before reset*/
 	wmi_led_cfg(wil, false);
 
 	mutex_lock(&wil->p2p_wdev_mutex);
-	wil_abort_scan(wil, false);
+	wil_abort_scan(vif, false);
 	mutex_unlock(&wil->p2p_wdev_mutex);
 
 	/* prevent NAPI from being scheduled and prevent wmi commands */
@@ -1276,7 +1254,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
 	}
 
 	/* init after reset */
-	wil->ap_isolate = 0;
+	vif->ap_isolate = 0;
 	reinit_completion(&wil->wmi_ready);
 	reinit_completion(&wil->wmi_call);
 	reinit_completion(&wil->halp.comp);
@@ -1337,8 +1315,8 @@ void wil_fw_error_recovery(struct wil6210_priv *wil)
 
 int __wil_up(struct wil6210_priv *wil)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
-	struct wireless_dev *wdev = wil->wdev;
+	struct net_device *ndev = wil->main_ndev;
+	struct wireless_dev *wdev = ndev->ieee80211_ptr;
 	int rc;
 
 	WARN_ON(!mutex_is_locked(&wil->mutex));
@@ -1422,7 +1400,7 @@ int __wil_down(struct wil6210_priv *wil)
 
 	mutex_lock(&wil->p2p_wdev_mutex);
 	wil_p2p_stop_radio_operations(wil);
-	wil_abort_scan(wil, false);
+	wil_abort_scan(ndev_to_vif(wil->main_ndev), false);
 	mutex_unlock(&wil->p2p_wdev_mutex);
 
 	return wil_reset(wil, false);
@@ -1442,13 +1420,14 @@ int wil_down(struct wil6210_priv *wil)
 	return rc;
 }
 
-int wil_find_cid(struct wil6210_priv *wil, const u8 *mac)
+int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac)
 {
 	int i;
 	int rc = -ENOENT;
 
 	for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
-		if ((wil->sta[i].status != wil_sta_unused) &&
+		if (wil->sta[i].mid == mid &&
+		    wil->sta[i].status != wil_sta_unused &&
 		    ether_addr_equal(wil->sta[i].addr, mac)) {
 			rc = i;
 			break;
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index 648f636..95570b8 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -122,6 +122,85 @@ static void wil_dev_setup(struct net_device *dev)
 	dev->tx_queue_len = WIL_TX_Q_LEN_DEFAULT;
 }
 
+static void wil_vif_deinit(struct wil6210_vif *vif)
+{
+	del_timer_sync(&vif->scan_timer);
+	del_timer_sync(&vif->p2p.discovery_timer);
+	cancel_work_sync(&vif->disconnect_worker);
+	cancel_work_sync(&vif->p2p.discovery_expired_work);
+	cancel_work_sync(&vif->p2p.delayed_listen_work);
+	wil_probe_client_flush(vif);
+	cancel_work_sync(&vif->probe_client_worker);
+}
+
+void wil_vif_free(struct wil6210_vif *vif)
+{
+	struct net_device *ndev = vif_to_ndev(vif);
+
+	wil_vif_deinit(vif);
+	free_netdev(ndev);
+}
+
+static void wil_ndev_destructor(struct net_device *ndev)
+{
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
+
+	wil_vif_deinit(vif);
+}
+
+static void wil_connect_timer_fn(struct timer_list *t)
+{
+	struct wil6210_vif *vif = from_timer(vif, t, connect_timer);
+	struct wil6210_priv *wil = vif_to_wil(vif);
+	bool q;
+
+	wil_err(wil, "Connect timeout detected, disconnect station\n");
+
+	/* reschedule to thread context - disconnect won't
+	 * run from atomic context.
+	 * queue on wmi_wq to prevent race with connect event.
+	 */
+	q = queue_work(wil->wmi_wq, &vif->disconnect_worker);
+	wil_dbg_wmi(wil, "queue_work of disconnect_worker -> %d\n", q);
+}
+
+static void wil_scan_timer_fn(struct timer_list *t)
+{
+	struct wil6210_vif *vif = from_timer(vif, t, scan_timer);
+	struct wil6210_priv *wil = vif_to_wil(vif);
+
+	clear_bit(wil_status_fwready, wil->status);
+	wil_err(wil, "Scan timeout detected, start fw error recovery\n");
+	wil_fw_error_recovery(wil);
+}
+
+static void wil_p2p_discovery_timer_fn(struct timer_list *t)
+{
+	struct wil6210_vif *vif = from_timer(vif, t, p2p.discovery_timer);
+	struct wil6210_priv *wil = vif_to_wil(vif);
+
+	wil_dbg_misc(wil, "p2p_discovery_timer_fn\n");
+
+	schedule_work(&vif->p2p.discovery_expired_work);
+}
+
+static void wil_vif_init(struct wil6210_vif *vif)
+{
+	vif->bcast_vring = -1;
+
+	mutex_init(&vif->probe_client_mutex);
+
+	timer_setup(&vif->connect_timer, wil_connect_timer_fn, 0);
+	timer_setup(&vif->scan_timer, wil_scan_timer_fn, 0);
+	timer_setup(&vif->p2p.discovery_timer, wil_p2p_discovery_timer_fn, 0);
+
+	INIT_WORK(&vif->probe_client_worker, wil_probe_client_worker);
+	INIT_WORK(&vif->disconnect_worker, wil_disconnect_worker);
+	INIT_WORK(&vif->p2p.delayed_listen_work, wil_p2p_delayed_listen_work);
+
+	INIT_LIST_HEAD(&vif->probe_client_pending);
+}
+
 struct wil6210_vif *
 wil_vif_alloc(struct wil6210_priv *wil, const char *name,
 	      unsigned char name_assign_type, enum nl80211_iftype iftype,
@@ -138,10 +217,12 @@ struct wil6210_vif *
 		return ERR_PTR(-ENOMEM);
 	}
 	if (mid == 0)
-		wil->ndev = ndev;
+		wil->main_ndev = ndev;
 	vif = ndev_to_vif(ndev);
+	vif->ndev = ndev;
 	vif->wil = wil;
 	vif->mid = mid;
+	wil_vif_init(vif);
 
 	wdev = &vif->wdev;
 	wdev->wiphy = wil->wiphy;
@@ -163,7 +244,6 @@ struct wil6210_vif *
 
 void *wil_if_alloc(struct device *dev)
 {
-	struct wireless_dev *wdev;
 	struct wil6210_priv *wil;
 	struct wil6210_vif *vif;
 	int rc = 0;
@@ -190,9 +270,7 @@ void *wil_if_alloc(struct device *dev)
 		goto out_priv;
 	}
 
-	wdev = &vif->wdev;
-	wil->wdev = wdev;
-	wil->radio_wdev = wdev;
+	wil->radio_wdev = vif_to_wdev(vif);
 
 	return wil;
 
@@ -207,7 +285,7 @@ void *wil_if_alloc(struct device *dev)
 
 void wil_if_free(struct wil6210_priv *wil)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 
 	wil_dbg_misc(wil, "if_free\n");
 
@@ -216,7 +294,8 @@ void wil_if_free(struct wil6210_priv *wil)
 
 	wil_priv_deinit(wil);
 
-	wil_to_ndev(wil) = NULL;
+	wil->main_ndev = NULL;
+	wil_ndev_destructor(ndev);
 	free_netdev(ndev);
 
 	wil_cfg80211_deinit(wil);
@@ -224,9 +303,8 @@ void wil_if_free(struct wil6210_priv *wil)
 
 int wil_if_add(struct wil6210_priv *wil)
 {
-	struct wireless_dev *wdev = wil_to_wdev(wil);
 	struct wiphy *wiphy = wil->wiphy;
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	int rc;
 
 	wil_dbg_misc(wil, "entered");
@@ -255,14 +333,14 @@ int wil_if_add(struct wil6210_priv *wil)
 	return 0;
 
 out_wiphy:
-	wiphy_unregister(wdev->wiphy);
+	wiphy_unregister(wiphy);
 	return rc;
 }
 
 void wil_if_remove(struct wil6210_priv *wil)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
-	struct wireless_dev *wdev = wil_to_wdev(wil);
+	struct net_device *ndev = wil->main_ndev;
+	struct wireless_dev *wdev = ndev->ieee80211_ptr;
 
 	wil_dbg_misc(wil, "if_remove\n");
 
diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c
index 7dbee2c..8b34f18 100644
--- a/drivers/net/wireless/ath/wil6210/p2p.c
+++ b/drivers/net/wireless/ath/wil6210/p2p.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -22,27 +23,28 @@
 #define P2P_SEARCH_DURATION_MS 500
 #define P2P_DEFAULT_BI 100
 
-static int wil_p2p_start_listen(struct wil6210_priv *wil)
+static int wil_p2p_start_listen(struct wil6210_vif *vif)
 {
-	struct wil_p2p_info *p2p = &wil->p2p;
+	struct wil6210_priv *wil = vif_to_wil(vif);
+	struct wil_p2p_info *p2p = &vif->p2p;
 	u8 channel = p2p->listen_chan.hw_value;
 	int rc;
 
 	lockdep_assert_held(&wil->mutex);
 
-	rc = wmi_p2p_cfg(wil, channel, P2P_DEFAULT_BI);
+	rc = wmi_p2p_cfg(vif, channel, P2P_DEFAULT_BI);
 	if (rc) {
 		wil_err(wil, "wmi_p2p_cfg failed\n");
 		goto out;
 	}
 
-	rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
+	rc = wmi_set_ssid(vif, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
 	if (rc) {
 		wil_err(wil, "wmi_set_ssid failed\n");
 		goto out_stop;
 	}
 
-	rc = wmi_start_listen(wil);
+	rc = wmi_start_listen(vif);
 	if (rc) {
 		wil_err(wil, "wmi_start_listen failed\n");
 		goto out_stop;
@@ -53,7 +55,7 @@ static int wil_p2p_start_listen(struct wil6210_priv *wil)
 		  jiffies + msecs_to_jiffies(p2p->listen_duration));
 out_stop:
 	if (rc)
-		wmi_stop_discovery(wil);
+		wmi_stop_discovery(vif);
 
 out:
 	return rc;
@@ -65,20 +67,12 @@ bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request)
 	       (request->channels[0]->hw_value == P2P_DMG_SOCIAL_CHANNEL);
 }
 
-void wil_p2p_discovery_timer_fn(struct timer_list *t)
-{
-	struct wil6210_priv *wil = from_timer(wil, t, p2p.discovery_timer);
-
-	wil_dbg_misc(wil, "p2p_discovery_timer_fn\n");
-
-	schedule_work(&wil->p2p.discovery_expired_work);
-}
-
-int wil_p2p_search(struct wil6210_priv *wil,
+int wil_p2p_search(struct wil6210_vif *vif,
 		   struct cfg80211_scan_request *request)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
-	struct wil_p2p_info *p2p = &wil->p2p;
+	struct wil_p2p_info *p2p = &vif->p2p;
 
 	wil_dbg_misc(wil, "p2p_search: channel %d\n", P2P_DMG_SOCIAL_CHANNEL);
 
@@ -90,20 +84,20 @@ int wil_p2p_search(struct wil6210_priv *wil,
 		goto out;
 	}
 
-	rc = wmi_p2p_cfg(wil, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI);
+	rc = wmi_p2p_cfg(vif, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI);
 	if (rc) {
 		wil_err(wil, "wmi_p2p_cfg failed\n");
 		goto out;
 	}
 
-	rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
+	rc = wmi_set_ssid(vif, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID);
 	if (rc) {
 		wil_err(wil, "wmi_set_ssid failed\n");
 		goto out_stop;
 	}
 
 	/* Set application IE to probe request and probe response */
-	rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ,
+	rc = wmi_set_ie(vif, WMI_FRAME_PROBE_REQ,
 			request->ie_len, request->ie);
 	if (rc) {
 		wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n");
@@ -113,14 +107,14 @@ int wil_p2p_search(struct wil6210_priv *wil,
 	/* supplicant doesn't provide Probe Response IEs. As a workaround -
 	 * re-use Probe Request IEs
 	 */
-	rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP,
+	rc = wmi_set_ie(vif, WMI_FRAME_PROBE_RESP,
 			request->ie_len, request->ie);
 	if (rc) {
 		wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n");
 		goto out_stop;
 	}
 
-	rc = wmi_start_search(wil);
+	rc = wmi_start_search(vif);
 	if (rc) {
 		wil_err(wil, "wmi_start_search failed\n");
 		goto out_stop;
@@ -133,7 +127,7 @@ int wil_p2p_search(struct wil6210_priv *wil,
 
 out_stop:
 	if (rc)
-		wmi_stop_discovery(wil);
+		wmi_stop_discovery(vif);
 
 out:
 	return rc;
@@ -143,7 +137,8 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
 		   unsigned int duration, struct ieee80211_channel *chan,
 		   u64 *cookie)
 {
-	struct wil_p2p_info *p2p = &wil->p2p;
+	struct wil6210_vif *vif = wdev_to_vif(wil, wdev);
+	struct wil_p2p_info *p2p = &vif->p2p;
 	int rc;
 
 	if (!chan)
@@ -164,7 +159,7 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
 	p2p->listen_duration = duration;
 
 	mutex_lock(&wil->p2p_wdev_mutex);
-	if (wil->scan_request) {
+	if (vif->scan_request) {
 		wil_dbg_misc(wil, "Delaying p2p listen until scan done\n");
 		p2p->pending_listen_wdev = wdev;
 		p2p->discovery_started = 1;
@@ -174,12 +169,13 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
 	}
 	mutex_unlock(&wil->p2p_wdev_mutex);
 
-	rc = wil_p2p_start_listen(wil);
+	rc = wil_p2p_start_listen(vif);
 	if (rc)
 		goto out;
 
 	p2p->discovery_started = 1;
-	wil->radio_wdev = wdev;
+	if (vif->mid == 0)
+		wil->radio_wdev = wdev;
 
 	cfg80211_ready_on_channel(wdev, *cookie, chan, duration,
 				  GFP_KERNEL);
@@ -189,9 +185,9 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
 	return rc;
 }
 
-u8 wil_p2p_stop_discovery(struct wil6210_priv *wil)
+u8 wil_p2p_stop_discovery(struct wil6210_vif *vif)
 {
-	struct wil_p2p_info *p2p = &wil->p2p;
+	struct wil_p2p_info *p2p = &vif->p2p;
 	u8 started = p2p->discovery_started;
 
 	if (p2p->discovery_started) {
@@ -200,7 +196,7 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil)
 			p2p->pending_listen_wdev = NULL;
 		} else {
 			del_timer_sync(&p2p->discovery_timer);
-			wmi_stop_discovery(wil);
+			wmi_stop_discovery(vif);
 		}
 		p2p->discovery_started = 0;
 	}
@@ -208,9 +204,10 @@ u8 wil_p2p_stop_discovery(struct wil6210_priv *wil)
 	return started;
 }
 
-int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie)
+int wil_p2p_cancel_listen(struct wil6210_vif *vif, u64 cookie)
 {
-	struct wil_p2p_info *p2p = &wil->p2p;
+	struct wil6210_priv *wil = vif_to_wil(vif);
+	struct wil_p2p_info *p2p = &vif->p2p;
 	u8 started;
 
 	mutex_lock(&wil->mutex);
@@ -222,7 +219,7 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie)
 		return -ENOENT;
 	}
 
-	started = wil_p2p_stop_discovery(wil);
+	started = wil_p2p_stop_discovery(vif);
 
 	mutex_unlock(&wil->mutex);
 
@@ -232,11 +229,12 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie)
 	}
 
 	mutex_lock(&wil->p2p_wdev_mutex);
-	cfg80211_remain_on_channel_expired(wil->radio_wdev,
+	cfg80211_remain_on_channel_expired(vif_to_radio_wdev(wil, vif),
 					   p2p->cookie,
 					   &p2p->listen_chan,
 					   GFP_KERNEL);
-	wil->radio_wdev = wil->wdev;
+	if (vif->mid == 0)
+		wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
 	mutex_unlock(&wil->p2p_wdev_mutex);
 	return 0;
 }
@@ -245,40 +243,43 @@ void wil_p2p_listen_expired(struct work_struct *work)
 {
 	struct wil_p2p_info *p2p = container_of(work,
 			struct wil_p2p_info, discovery_expired_work);
-	struct wil6210_priv *wil = container_of(p2p,
-			struct wil6210_priv, p2p);
+	struct wil6210_vif *vif = container_of(p2p,
+			struct wil6210_vif, p2p);
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	u8 started;
 
 	wil_dbg_misc(wil, "p2p_listen_expired\n");
 
 	mutex_lock(&wil->mutex);
-	started = wil_p2p_stop_discovery(wil);
+	started = wil_p2p_stop_discovery(vif);
 	mutex_unlock(&wil->mutex);
 
-	if (started) {
-		mutex_lock(&wil->p2p_wdev_mutex);
-		cfg80211_remain_on_channel_expired(wil->radio_wdev,
-						   p2p->cookie,
-						   &p2p->listen_chan,
-						   GFP_KERNEL);
-		wil->radio_wdev = wil->wdev;
-		mutex_unlock(&wil->p2p_wdev_mutex);
-	}
+	if (!started)
+		return;
 
+	mutex_lock(&wil->p2p_wdev_mutex);
+	cfg80211_remain_on_channel_expired(vif_to_radio_wdev(wil, vif),
+					   p2p->cookie,
+					   &p2p->listen_chan,
+					   GFP_KERNEL);
+	if (vif->mid == 0)
+		wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
+	mutex_unlock(&wil->p2p_wdev_mutex);
 }
 
 void wil_p2p_search_expired(struct work_struct *work)
 {
 	struct wil_p2p_info *p2p = container_of(work,
 			struct wil_p2p_info, discovery_expired_work);
-	struct wil6210_priv *wil = container_of(p2p,
-			struct wil6210_priv, p2p);
+	struct wil6210_vif *vif = container_of(p2p,
+			struct wil6210_vif, p2p);
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	u8 started;
 
 	wil_dbg_misc(wil, "p2p_search_expired\n");
 
 	mutex_lock(&wil->mutex);
-	started = wil_p2p_stop_discovery(wil);
+	started = wil_p2p_stop_discovery(vif);
 	mutex_unlock(&wil->mutex);
 
 	if (started) {
@@ -287,10 +288,12 @@ void wil_p2p_search_expired(struct work_struct *work)
 		};
 
 		mutex_lock(&wil->p2p_wdev_mutex);
-		if (wil->scan_request) {
-			cfg80211_scan_done(wil->scan_request, &info);
-			wil->scan_request = NULL;
-			wil->radio_wdev = wil->wdev;
+		if (vif->scan_request) {
+			cfg80211_scan_done(vif->scan_request, &info);
+			vif->scan_request = NULL;
+			if (vif->mid == 0)
+				wil->radio_wdev =
+					wil->main_ndev->ieee80211_ptr;
 		}
 		mutex_unlock(&wil->p2p_wdev_mutex);
 	}
@@ -300,8 +303,9 @@ void wil_p2p_delayed_listen_work(struct work_struct *work)
 {
 	struct wil_p2p_info *p2p = container_of(work,
 			struct wil_p2p_info, delayed_listen_work);
-	struct wil6210_priv *wil = container_of(p2p,
-			struct wil6210_priv, p2p);
+	struct wil6210_vif *vif = container_of(p2p,
+			struct wil6210_vif, p2p);
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 
 	mutex_lock(&wil->mutex);
@@ -311,14 +315,14 @@ void wil_p2p_delayed_listen_work(struct work_struct *work)
 		goto out;
 
 	mutex_lock(&wil->p2p_wdev_mutex);
-	if (wil->scan_request) {
+	if (vif->scan_request) {
 		/* another scan started, wait again... */
 		mutex_unlock(&wil->p2p_wdev_mutex);
 		goto out;
 	}
 	mutex_unlock(&wil->p2p_wdev_mutex);
 
-	rc = wil_p2p_start_listen(wil);
+	rc = wil_p2p_start_listen(vif);
 
 	mutex_lock(&wil->p2p_wdev_mutex);
 	if (rc) {
@@ -326,12 +330,14 @@ void wil_p2p_delayed_listen_work(struct work_struct *work)
 						   p2p->cookie,
 						   &p2p->listen_chan,
 						   GFP_KERNEL);
-		wil->radio_wdev = wil->wdev;
+		if (vif->mid == 0)
+			wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
 	} else {
 		cfg80211_ready_on_channel(p2p->pending_listen_wdev, p2p->cookie,
 					  &p2p->listen_chan,
 					  p2p->listen_duration, GFP_KERNEL);
-		wil->radio_wdev = p2p->pending_listen_wdev;
+		if (vif->mid == 0)
+			wil->radio_wdev = p2p->pending_listen_wdev;
 	}
 	p2p->pending_listen_wdev = NULL;
 	mutex_unlock(&wil->p2p_wdev_mutex);
@@ -342,7 +348,8 @@ void wil_p2p_delayed_listen_work(struct work_struct *work)
 
 void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)
 {
-	struct wil_p2p_info *p2p = &wil->p2p;
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
+	struct wil_p2p_info *p2p = &vif->p2p;
 	struct cfg80211_scan_info info = {
 		.aborted = true,
 	};
@@ -355,21 +362,21 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)
 
 	if (!p2p->discovery_started) {
 		/* Regular scan on the p2p device */
-		if (wil->scan_request &&
-		    wil->scan_request->wdev == wil->p2p_wdev)
-			wil_abort_scan(wil, true);
+		if (vif->scan_request &&
+		    vif->scan_request->wdev == wil->p2p_wdev)
+			wil_abort_scan(vif, true);
 		goto out;
 	}
 
 	/* Search or listen on p2p device */
 	mutex_unlock(&wil->p2p_wdev_mutex);
-	wil_p2p_stop_discovery(wil);
+	wil_p2p_stop_discovery(vif);
 	mutex_lock(&wil->p2p_wdev_mutex);
 
-	if (wil->scan_request) {
+	if (vif->scan_request) {
 		/* search */
-		cfg80211_scan_done(wil->scan_request, &info);
-		wil->scan_request = NULL;
+		cfg80211_scan_done(vif->scan_request, &info);
+		vif->scan_request = NULL;
 	} else {
 		/* listen */
 		cfg80211_remain_on_channel_expired(wil->radio_wdev,
@@ -379,5 +386,5 @@ void wil_p2p_stop_radio_operations(struct wil6210_priv *wil)
 	}
 
 out:
-	wil->radio_wdev = wil->wdev;
+	wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
 }
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index 809092a..a61ffd9 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -425,7 +425,7 @@ static int wil6210_suspend(struct device *dev, bool is_runtime)
 	int rc = 0;
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct wil6210_priv *wil = pci_get_drvdata(pdev);
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	bool keep_radio_on = ndev->flags & IFF_UP &&
 			     wil->keep_radio_on_during_sleep;
 
@@ -457,7 +457,7 @@ static int wil6210_resume(struct device *dev, bool is_runtime)
 	int rc = 0;
 	struct pci_dev *pdev = to_pci_dev(dev);
 	struct wil6210_priv *wil = pci_get_drvdata(pdev);
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	bool keep_radio_on = ndev->flags & IFF_UP &&
 			     wil->keep_radio_on_during_sleep;
 
diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c
index 0a96518..12f6d78 100644
--- a/drivers/net/wireless/ath/wil6210/pm.c
+++ b/drivers/net/wireless/ath/wil6210/pm.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014,2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -23,8 +24,8 @@
 int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime)
 {
 	int rc = 0;
-	struct wireless_dev *wdev = wil->wdev;
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
+	struct wireless_dev *wdev = ndev->ieee80211_ptr;
 	bool wmi_only = test_bit(WMI_FW_CAPABILITY_WMI_ONLY,
 				 wil->fw_capabilities);
 
@@ -258,7 +259,7 @@ static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
 static int wil_suspend_radio_off(struct wil6210_priv *wil)
 {
 	int rc = 0;
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 
 	wil_dbg_pm(wil, "suspend radio off\n");
 
@@ -306,7 +307,7 @@ static int wil_suspend_radio_off(struct wil6210_priv *wil)
 static int wil_resume_radio_off(struct wil6210_priv *wil)
 {
 	int rc = 0;
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 
 	wil_dbg_pm(wil, "Enabling PCIe IRQ\n");
 	wil_enable_irq(wil);
diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c
index 4ea27b0..c49f798 100644
--- a/drivers/net/wireless/ath/wil6210/pmc.c
+++ b/drivers/net/wireless/ath/wil6210/pmc.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2015,2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -53,6 +54,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
 	u32 i;
 	struct pmc_ctx *pmc = &wil->pmc;
 	struct device *dev = wil_to_dev(wil);
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	struct wmi_pmc_cmd pmc_cmd = {0};
 	int last_cmd_err = -ENOMEM;
 
@@ -186,6 +188,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
 	wil_dbg_misc(wil, "pmc_alloc: send WMI_PMC_CMD with ALLOCATE op\n");
 	pmc->last_cmd_status = wmi_send(wil,
 					WMI_PMC_CMDID,
+					vif->mid,
 					&pmc_cmd,
 					sizeof(pmc_cmd));
 	if (pmc->last_cmd_status) {
@@ -236,6 +239,7 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd)
 {
 	struct pmc_ctx *pmc = &wil->pmc;
 	struct device *dev = wil_to_dev(wil);
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	struct wmi_pmc_cmd pmc_cmd = {0};
 
 	mutex_lock(&pmc->lock);
@@ -254,8 +258,8 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd)
 		wil_dbg_misc(wil, "send WMI_PMC_CMD with RELEASE op\n");
 		pmc_cmd.op = WMI_PMC_RELEASE;
 		pmc->last_cmd_status =
-				wmi_send(wil, WMI_PMC_CMDID, &pmc_cmd,
-					 sizeof(pmc_cmd));
+				wmi_send(wil, WMI_PMC_CMDID, vif->mid,
+					 &pmc_cmd, sizeof(pmc_cmd));
 		if (pmc->last_cmd_status) {
 			wil_err(wil,
 				"WMI_PMC_CMD with RELEASE op failed, status %d",
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c
index a43cffc..c2140b3 100644
--- a/drivers/net/wireless/ath/wil6210/rx_reorder.c
+++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -44,7 +45,7 @@ static void wil_release_reorder_frame(struct wil6210_priv *wil,
 				      struct wil_tid_ampdu_rx *r,
 				      int index)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	struct sk_buff *skb = r->reorder_buf[index];
 
 	if (!skb)
@@ -93,7 +94,7 @@ static void wil_reorder_release(struct wil6210_priv *wil,
 void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb)
 __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	struct vring_rx_desc *d = wil_skb_rxdesc(skb);
 	int tid = wil_rxdesc_tid(d);
 	int cid = wil_rxdesc_cid(d);
@@ -292,8 +293,8 @@ static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize)
 }
 
 /* Block Ack - Rx side (recipient) */
-int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
-			 u8 dialog_token, __le16 ba_param_set,
+int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid,
+			 u8 cidxtid, u8 dialog_token, __le16 ba_param_set,
 			 __le16 ba_timeout, __le16 ba_seq_ctrl)
 __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
 {
@@ -354,7 +355,7 @@ int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
 		}
 	}
 
-	rc = wmi_addba_rx_resp(wil, cid, tid, dialog_token, status,
+	rc = wmi_addba_rx_resp(wil, mid, cid, tid, dialog_token, status,
 			       agg_amsdu, agg_wsize, agg_timeout);
 	if (rc || (status != WLAN_STATUS_SUCCESS)) {
 		wil_err(wil, "do not apply ba, rc(%d), status(%d)\n", rc,
@@ -393,7 +394,7 @@ int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize)
 		goto out;
 	}
 	txdata->addba_in_progress = true;
-	rc = wmi_addba(wil, ringid, agg_wsize, agg_timeout);
+	rc = wmi_addba(wil, txdata->mid, ringid, agg_wsize, agg_timeout);
 	if (rc) {
 		wil_err(wil, "wmi_addba failed, rc (%d)", rc);
 		txdata->addba_in_progress = false;
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 16b8a4e..a532386 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2012-2017 Qualcomm Atheros, Inc.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -474,7 +475,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
 					 struct vring *vring)
 {
 	struct device *dev = wil_to_dev(wil);
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	volatile struct vring_rx_desc *_d;
 	struct vring_rx_desc *d;
 	struct sk_buff *skb;
@@ -624,7 +625,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
  */
 static int wil_rx_refill(struct wil6210_priv *wil, int count)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	struct vring *v = &wil->vring_rx;
 	u32 next_tail;
 	int rc = 0;
@@ -713,8 +714,9 @@ static int wil_rx_crypto_check(struct wil6210_priv *wil, struct sk_buff *skb)
 void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
 {
 	gro_result_t rc = GRO_NORMAL;
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
 	struct wil6210_priv *wil = ndev_to_wil(ndev);
-	struct wireless_dev *wdev = wil_to_wdev(wil);
+	struct wireless_dev *wdev = vif_to_wdev(vif);
 	unsigned int len = skb->len;
 	struct vring_rx_desc *d = wil_skb_rxdesc(skb);
 	int cid = wil_rxdesc_cid(d); /* always 0..7, no need to check */
@@ -751,14 +753,15 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
 		goto stats;
 	}
 
-	if (wdev->iftype == NL80211_IFTYPE_AP && !wil->ap_isolate) {
+	if (wdev->iftype == NL80211_IFTYPE_AP && !vif->ap_isolate) {
 		if (mcast) {
 			/* send multicast frames both to higher layers in
 			 * local net stack and back to the wireless medium
 			 */
 			xmit_skb = skb_copy(skb, GFP_ATOMIC);
 		} else {
-			int xmit_cid = wil_find_cid(wil, eth->h_dest);
+			int xmit_cid = wil_find_cid(wil, vif->mid,
+						    eth->h_dest);
 
 			if (xmit_cid >= 0) {
 				/* The destination station is associated to
@@ -815,7 +818,8 @@ void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
  */
 void wil_rx_handle(struct wil6210_priv *wil, int *quota)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
+	struct wireless_dev *wdev = ndev->ieee80211_ptr;
 	struct vring *v = &wil->vring_rx;
 	struct sk_buff *skb;
 
@@ -827,7 +831,8 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota)
 	while ((*quota > 0) && (NULL != (skb = wil_vring_reap_rx(wil, v)))) {
 		(*quota)--;
 
-		if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+		/* monitor is currently supported on main interface only */
+		if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
 			skb->dev = ndev;
 			skb_reset_mac_header(skb);
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -911,12 +916,14 @@ static inline void wil_tx_data_init(struct vring_tx_data *txdata)
 	txdata->agg_timeout = 0;
 	txdata->agg_amsdu = 0;
 	txdata->addba_in_progress = false;
+	txdata->mid = U8_MAX;
 	spin_unlock_bh(&txdata->lock);
 }
 
-int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
+int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
 		      int cid, int tid)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 	struct wmi_vring_cfg_cmd cmd = {
 		.action = cpu_to_le32(WMI_VRING_CMD_ADD),
@@ -966,9 +973,9 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
 
 	cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
 
-	if (!wil->privacy)
+	if (!vif->privacy)
 		txdata->dot1x_open = true;
-	rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_VRING_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
 		      WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
 	if (rc)
 		goto out_free;
@@ -982,6 +989,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
 
 	spin_lock_bh(&txdata->lock);
 	vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
+	txdata->mid = vif->mid;
 	txdata->enabled = 1;
 	spin_unlock_bh(&txdata->lock);
 
@@ -1003,8 +1011,9 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
 	return rc;
 }
 
-int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
+int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 	struct wmi_bcast_vring_cfg_cmd cmd = {
 		.action = cpu_to_le32(WMI_VRING_CMD_ADD),
@@ -1046,9 +1055,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
 
 	cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
 
-	if (!wil->privacy)
+	if (!vif->privacy)
 		txdata->dot1x_open = true;
-	rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_BCAST_VRING_CFG_CMDID, vif->mid,
+		      &cmd, sizeof(cmd),
 		      WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
 	if (rc)
 		goto out_free;
@@ -1062,6 +1072,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
 
 	spin_lock_bh(&txdata->lock);
 	vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
+	txdata->mid = vif->mid;
 	txdata->enabled = 1;
 	spin_unlock_bh(&txdata->lock);
 
@@ -1091,6 +1102,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
 
 	spin_lock_bh(&txdata->lock);
 	txdata->dot1x_open = false;
+	txdata->mid = U8_MAX;
 	txdata->enabled = 0; /* no Tx can be in progress or start anew */
 	spin_unlock_bh(&txdata->lock);
 	/* napi_synchronize waits for completion of the current NAPI but will
@@ -1108,11 +1120,12 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
 }
 
 static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil,
+				       struct wil6210_vif *vif,
 				       struct sk_buff *skb)
 {
 	int i;
 	struct ethhdr *eth = (void *)skb->data;
-	int cid = wil_find_cid(wil, eth->h_dest);
+	int cid = wil_find_cid(wil, vif->mid, eth->h_dest);
 
 	if (cid < 0)
 		return NULL;
@@ -1142,10 +1155,11 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil,
 	return NULL;
 }
 
-static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
-			struct sk_buff *skb);
+static int wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif,
+			struct vring *vring, struct sk_buff *skb);
 
 static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
+					   struct wil6210_vif *vif,
 					   struct sk_buff *skb)
 {
 	struct vring *v;
@@ -1160,7 +1174,7 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
 	for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
 		v = &wil->vring_tx[i];
 		txdata = &wil->vring_tx_data[i];
-		if (!v->va || !txdata->enabled)
+		if (!v->va || !txdata->enabled || txdata->mid != vif->mid)
 			continue;
 
 		cid = wil->vring2cid_tid[i][0];
@@ -1193,11 +1207,12 @@ static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
  *  - for PBSS
  */
 static struct vring *wil_find_tx_bcast_1(struct wil6210_priv *wil,
+					 struct wil6210_vif *vif,
 					 struct sk_buff *skb)
 {
 	struct vring *v;
 	struct vring_tx_data *txdata;
-	int i = wil->bcast_vring;
+	int i = vif->bcast_vring;
 
 	if (i < 0)
 		return NULL;
@@ -1222,6 +1237,7 @@ static void wil_set_da_for_vring(struct wil6210_priv *wil,
 }
 
 static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
+					 struct wil6210_vif *vif,
 					 struct sk_buff *skb)
 {
 	struct vring *v, *v2;
@@ -1230,13 +1246,13 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
 	u8 cid;
 	struct ethhdr *eth = (void *)skb->data;
 	char *src = eth->h_source;
-	struct vring_tx_data *txdata;
+	struct vring_tx_data *txdata, *txdata2;
 
 	/* find 1-st vring eligible for data */
 	for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
 		v = &wil->vring_tx[i];
 		txdata = &wil->vring_tx_data[i];
-		if (!v->va || !txdata->enabled)
+		if (!v->va || !txdata->enabled || txdata->mid != vif->mid)
 			continue;
 
 		cid = wil->vring2cid_tid[i][0];
@@ -1264,7 +1280,8 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
 	/* find other active vrings and duplicate skb for each */
 	for (i++; i < WIL6210_MAX_TX_RINGS; i++) {
 		v2 = &wil->vring_tx[i];
-		if (!v2->va)
+		txdata2 = &wil->vring_tx_data[i];
+		if (!v2->va || txdata2->mid != vif->mid)
 			continue;
 		cid = wil->vring2cid_tid[i][0];
 		if (cid >= WIL6210_MAX_CID) /* skip BCAST */
@@ -1280,7 +1297,7 @@ static struct vring *wil_find_tx_bcast_2(struct wil6210_priv *wil,
 		if (skb2) {
 			wil_dbg_txrx(wil, "BCAST DUP -> ring %d\n", i);
 			wil_set_da_for_vring(wil, skb2, i);
-			wil_tx_vring(wil, v2, skb2);
+			wil_tx_vring(wil, vif, v2, skb2);
 		} else {
 			wil_err(wil, "skb_copy failed\n");
 		}
@@ -1417,8 +1434,8 @@ static inline void wil_set_tx_desc_last_tso(volatile struct vring_tx_desc *d)
 		  DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS;
 }
 
-static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
-			      struct sk_buff *skb)
+static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct wil6210_vif *vif,
+			      struct vring *vring, struct sk_buff *skb)
 {
 	struct device *dev = wil_to_dev(wil);
 
@@ -1710,8 +1727,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring,
 	return rc;
 }
 
-static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
-			  struct sk_buff *skb)
+static int __wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif,
+			  struct vring *vring, struct sk_buff *skb)
 {
 	struct device *dev = wil_to_dev(wil);
 	struct vring_tx_desc dd, *d = &dd;
@@ -1725,7 +1742,7 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	uint i = swhead;
 	dma_addr_t pa;
 	int used;
-	bool mcast = (vring_index == wil->bcast_vring);
+	bool mcast = (vring_index == vif->bcast_vring);
 	uint len = skb_headlen(skb);
 
 	wil_dbg_txrx(wil, "tx_vring: %d bytes to vring %d\n", skb->len,
@@ -1860,8 +1877,8 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	return -EINVAL;
 }
 
-static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
-			struct sk_buff *skb)
+static int wil_tx_vring(struct wil6210_priv *wil, struct wil6210_vif *vif,
+			struct vring *vring, struct sk_buff *skb)
 {
 	int vring_index = vring - wil->vring_tx;
 	struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index];
@@ -1879,7 +1896,7 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
 	}
 
 	rc = (skb_is_gso(skb) ? __wil_tx_vring_tso : __wil_tx_vring)
-	     (wil, vring, skb);
+	     (wil, vif, vring, skb);
 
 	spin_unlock(&txdata->lock);
 
@@ -1923,7 +1940,7 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil,
 	if (check_stop) {
 		if (!vring || unlikely(wil_vring_avail_low(vring))) {
 			/* not enough room in the vring */
-			netif_tx_stop_all_queues(wil_to_ndev(wil));
+			netif_tx_stop_all_queues(wil->main_ndev);
 			wil->net_queue_stopped = true;
 			wil_dbg_txrx(wil, "netif_tx_stop called\n");
 		}
@@ -1953,7 +1970,7 @@ static inline void __wil_update_net_queues(struct wil6210_priv *wil,
 	if (!vring || wil_vring_avail_high(vring)) {
 		/* enough room in the vring */
 		wil_dbg_txrx(wil, "calling netif_tx_wake\n");
-		netif_tx_wake_all_queues(wil_to_ndev(wil));
+		netif_tx_wake_all_queues(wil->main_ndev);
 		wil->net_queue_stopped = false;
 	}
 }
@@ -1976,7 +1993,8 @@ void wil_update_net_queues_bh(struct wil6210_priv *wil, struct vring *vring,
 
 netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
-	struct wil6210_priv *wil = ndev_to_wil(ndev);
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct ethhdr *eth = (void *)skb->data;
 	bool bcast = is_multicast_ether_addr(eth->h_dest);
 	struct vring *vring;
@@ -1995,40 +2013,40 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 		wil_dbg_ratelimited(wil, "FW not connected, packet dropped\n");
 		goto drop;
 	}
-	if (unlikely(wil->wdev->iftype == NL80211_IFTYPE_MONITOR)) {
+	if (unlikely(vif->wdev.iftype == NL80211_IFTYPE_MONITOR)) {
 		wil_err(wil, "Xmit in monitor mode not supported\n");
 		goto drop;
 	}
 	pr_once_fw = false;
 
 	/* find vring */
-	if (wil->wdev->iftype == NL80211_IFTYPE_STATION && !wil->pbss) {
+	if (vif->wdev.iftype == NL80211_IFTYPE_STATION && !vif->pbss) {
 		/* in STA mode (ESS), all to same VRING (to AP) */
-		vring = wil_find_tx_vring_sta(wil, skb);
+		vring = wil_find_tx_vring_sta(wil, vif, skb);
 	} else if (bcast) {
-		if (wil->pbss)
+		if (vif->pbss)
 			/* in pbss, no bcast VRING - duplicate skb in
 			 * all stations VRINGs
 			 */
-			vring = wil_find_tx_bcast_2(wil, skb);
-		else if (wil->wdev->iftype == NL80211_IFTYPE_AP)
+			vring = wil_find_tx_bcast_2(wil, vif, skb);
+		else if (vif->wdev.iftype == NL80211_IFTYPE_AP)
 			/* AP has a dedicated bcast VRING */
-			vring = wil_find_tx_bcast_1(wil, skb);
+			vring = wil_find_tx_bcast_1(wil, vif, skb);
 		else
 			/* unexpected combination, fallback to duplicating
 			 * the skb in all stations VRINGs
 			 */
-			vring = wil_find_tx_bcast_2(wil, skb);
+			vring = wil_find_tx_bcast_2(wil, vif, skb);
 	} else {
 		/* unicast, find specific VRING by dest. address */
-		vring = wil_find_tx_ucast(wil, skb);
+		vring = wil_find_tx_ucast(wil, vif, skb);
 	}
 	if (unlikely(!vring)) {
 		wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest);
 		goto drop;
 	}
 	/* set up vring entry */
-	rc = wil_tx_vring(wil, vring, skb);
+	rc = wil_tx_vring(wil, vif, vring, skb);
 
 	switch (rc) {
 	case 0:
@@ -2074,7 +2092,7 @@ static inline void wil_consume_skb(struct sk_buff *skb, bool acked)
  */
 int wil_tx_complete(struct wil6210_priv *wil, int ringid)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
 	struct device *dev = wil_to_dev(wil);
 	struct vring *vring = &wil->vring_tx[ringid];
 	struct vring_tx_data *txdata = &wil->vring_tx_data[ringid];
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 81cb27a..fa8df41 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -464,6 +464,7 @@ struct vring_tx_data {
 	u16 agg_timeout;
 	u8 agg_amsdu;
 	bool addba_in_progress; /* if set, agg_xxx is for request in progress */
+	u8 mid;
 	spinlock_t lock;
 };
 
@@ -542,7 +543,6 @@ struct wil_tid_crypto_rx {
 struct wil_p2p_info {
 	struct ieee80211_channel listen_chan;
 	u8 discovery_started;
-	u8 p2p_dev_started;
 	u64 cookie;
 	struct wireless_dev *pending_listen_wdev;
 	unsigned int listen_duration;
@@ -585,6 +585,7 @@ struct wil_net_stats {
  */
 struct wil_sta_info {
 	u8 addr[ETH_ALEN];
+	u8 mid;
 	enum wil_sta_status status;
 	struct wil_net_stats stats;
 	/* Rx BACK */
@@ -672,16 +673,34 @@ struct wil_debugfs_data {
 
 struct wil6210_vif {
 	struct wireless_dev wdev;
+	struct net_device *ndev;
 	struct wil6210_priv *wil;
 	u8 mid;
+	u32 privacy; /* secure connection? */
+	u16 channel; /* relevant in AP mode */
+	u8 hidden_ssid; /* relevant in AP mode */
+	u32 ap_isolate; /* no intra-BSS communication */
+	bool pbss;
+	int bcast_vring;
+	struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */
+	int locally_generated_disc; /* relevant in STA mode */
+	struct timer_list connect_timer;
+	struct work_struct disconnect_worker;
+	/* scan */
+	struct cfg80211_scan_request *scan_request;
+	struct timer_list scan_timer; /* detect scan timeout */
+	struct wil_p2p_info p2p;
+	/* keep alive */
+	struct list_head probe_client_pending;
+	struct mutex probe_client_mutex; /* protect @probe_client_pending */
+	struct work_struct probe_client_worker;
 };
 
 struct wil6210_priv {
 	struct pci_dev *pdev;
 	u32 bar_size;
 	struct wiphy *wiphy;
-	struct wireless_dev *wdev;
-	struct net_device *ndev;
+	struct net_device *main_ndev;
 	void __iomem *csr;
 	DECLARE_BITMAP(status, wil_status_last);
 	u8 fw_version[ETHTOOL_FWVERS_LEN];
@@ -703,13 +722,7 @@ struct wil6210_priv {
 	/* profile */
 	struct cfg80211_chan_def monitor_chandef;
 	u32 monitor_flags;
-	u32 privacy; /* secure connection? */
-	u8 hidden_ssid; /* relevant in AP mode */
-	u16 channel; /* relevant in AP mode */
 	int sinfo_gen;
-	u32 ap_isolate; /* no intra-BSS communication */
-	struct cfg80211_bss *bss; /* connected bss, relevant in STA mode */
-	int locally_generated_disc; /* relevant in STA mode */
 	/* interrupt moderation */
 	u32 tx_max_burst_duration;
 	u32 tx_interframe_timeout;
@@ -724,15 +737,13 @@ struct wil6210_priv {
 	struct completion wmi_call;
 	u16 wmi_seq;
 	u16 reply_id; /**< wait for this WMI event */
+	u8 reply_mid;
 	void *reply_buf;
 	u16 reply_size;
 	struct workqueue_struct *wmi_wq; /* for deferred calls */
 	struct work_struct wmi_event_worker;
 	struct workqueue_struct *wq_service;
-	struct work_struct disconnect_worker;
 	struct work_struct fw_error_worker;	/* for FW error recovery */
-	struct timer_list connect_timer;
-	struct timer_list scan_timer; /* detect scan timeout */
 	struct list_head pending_wmi_ev;
 	/*
 	 * protect pending_wmi_ev
@@ -744,10 +755,6 @@ struct wil6210_priv {
 	int net_queue_stopped; /* netif_tx_stop_all_queues invoked */
 	struct napi_struct napi_rx;
 	struct napi_struct napi_tx;
-	/* keep alive */
-	struct list_head probe_client_pending;
-	struct mutex probe_client_mutex; /* protect @probe_client_pending */
-	struct work_struct probe_client_worker;
 	/* DMA related */
 	struct vring vring_rx;
 	unsigned int rx_buf_len;
@@ -755,11 +762,8 @@ struct wil6210_priv {
 	struct vring_tx_data vring_tx_data[WIL6210_MAX_TX_RINGS];
 	u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */
 	struct wil_sta_info sta[WIL6210_MAX_CID];
-	int bcast_vring;
 	u32 vring_idle_trsh; /* HW fetches up to 16 descriptors at once  */
 	u32 dma_addr_size; /* indicates dma addr size */
-	/* scan */
-	struct cfg80211_scan_request *scan_request;
 
 	struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */
 	/* statistics */
@@ -779,9 +783,7 @@ struct wil6210_priv {
 
 	struct pmc_ctx pmc;
 
-	bool pbss;
-
-	struct wil_p2p_info p2p;
+	u8 p2p_dev_started;
 
 	/* P2P_DEVICE vif */
 	struct wireless_dev *p2p_wdev;
@@ -810,12 +812,32 @@ struct wil6210_priv {
 #define wil_to_wiphy(i) (i->wiphy)
 #define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i)))
 #define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w))
-#define wil_to_wdev(i) (i->wdev)
 #define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w))
-#define wil_to_ndev(i) (i->ndev)
 #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr))
 #define ndev_to_vif(n) (struct wil6210_vif *)(netdev_priv(n))
-#define wdev_to_vif(w) (container_of(w, struct wil6210_vif, wdev))
+#define vif_to_wil(v) (v->wil)
+#define vif_to_ndev(v) (v->ndev)
+#define vif_to_wdev(v) (&v->wdev)
+
+static inline struct wil6210_vif *wdev_to_vif(struct wil6210_priv *wil,
+					      struct wireless_dev *wdev)
+{
+	/* main interface is shared with P2P device */
+	if (wdev == wil->p2p_wdev)
+		return ndev_to_vif(wil->main_ndev);
+	else
+		return container_of(wdev, struct wil6210_vif, wdev);
+}
+
+static inline struct wireless_dev *
+vif_to_radio_wdev(struct wil6210_priv *wil, struct wil6210_vif *vif)
+{
+	/* main interface is shared with P2P device */
+	if (vif->mid)
+		return vif_to_wdev(vif);
+	else
+		return wil->radio_wdev;
+}
 
 __printf(2, 3)
 void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...);
@@ -828,7 +850,7 @@ struct wil6210_priv {
 __printf(2, 3)
 void wil_dbg_ratelimited(const struct wil6210_priv *wil, const char *fmt, ...);
 #define wil_dbg(wil, fmt, arg...) do { \
-	netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \
+	netdev_dbg(wil->main_ndev, fmt, ##arg); \
 	wil_dbg_trace(wil, fmt, ##arg); \
 } while (0)
 
@@ -933,7 +955,7 @@ int wil_ps_update(struct wil6210_priv *wil,
 int __wil_down(struct wil6210_priv *wil);
 void wil_refresh_fw_capabilities(struct wil6210_priv *wil);
 void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r);
-int wil_find_cid(struct wil6210_priv *wil, const u8 *mac);
+int wil_find_cid(struct wil6210_priv *wil, u8 mid, const u8 *mac);
 void wil_set_ethtoolops(struct net_device *ndev);
 
 struct fw_map *wil_find_fw_mapping(const char *section);
@@ -942,40 +964,42 @@ int wil_ps_update(struct wil6210_priv *wil,
 void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr);
 int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
 		 struct wil6210_mbox_hdr *hdr);
-int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len);
+int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len);
 void wmi_recv_cmd(struct wil6210_priv *wil);
-int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
+int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len,
 	     u16 reply_id, void *reply, u8 reply_size, int to_msec);
 void wmi_event_worker(struct work_struct *work);
 void wmi_event_flush(struct wil6210_priv *wil);
-int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid);
-int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid);
+int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid);
+int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid);
 int wmi_set_channel(struct wil6210_priv *wil, int channel);
 int wmi_get_channel(struct wil6210_priv *wil, int *channel);
-int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
+int wmi_del_cipher_key(struct wil6210_vif *vif, u8 key_index,
 		       const void *mac_addr, int key_usage);
-int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
+int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index,
 		       const void *mac_addr, int key_len, const void *key,
 		       int key_usage);
 int wmi_echo(struct wil6210_priv *wil);
-int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie);
+int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie);
 int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring);
 int wmi_rxon(struct wil6210_priv *wil, bool on);
 int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r);
-int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac,
+int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac,
 		       u16 reason, bool full_disconnect, bool del_sta);
-int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout);
-int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason);
-int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason);
-int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
+int wmi_addba(struct wil6210_priv *wil, u8 mid,
+	      u8 ringid, u8 size, u16 timeout);
+int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason);
+int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason);
+int wmi_addba_rx_resp(struct wil6210_priv *wil,
+		      u8 mid, u8 cid, u8 tid, u8 token,
 		      u16 status, bool amsdu, u16 agg_wsize, u16 timeout);
 int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
 			   enum wmi_ps_profile_type ps_profile);
 int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short);
 int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short);
-int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid);
-int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
-			 u8 dialog_token, __le16 ba_param_set,
+int wmi_new_sta(struct wil6210_vif *vif, const u8 *mac, u8 aid);
+int wil_addba_rx_request(struct wil6210_priv *wil, u8 mid,
+			 u8 cidxtid, u8 dialog_token, __le16 ba_param_set,
 			 __le16 ba_timeout, __le16 ba_seq_ctrl);
 int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize);
 
@@ -991,24 +1015,23 @@ int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid,
 
 /* P2P */
 bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request);
-void wil_p2p_discovery_timer_fn(struct timer_list *t);
-int wil_p2p_search(struct wil6210_priv *wil,
+int wil_p2p_search(struct wil6210_vif *vif,
 		   struct cfg80211_scan_request *request);
 int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev,
 		   unsigned int duration, struct ieee80211_channel *chan,
 		   u64 *cookie);
-u8 wil_p2p_stop_discovery(struct wil6210_priv *wil);
-int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie);
+u8 wil_p2p_stop_discovery(struct wil6210_vif *vif);
+int wil_p2p_cancel_listen(struct wil6210_vif *vif, u64 cookie);
 void wil_p2p_listen_expired(struct work_struct *work);
 void wil_p2p_search_expired(struct work_struct *work);
 void wil_p2p_stop_radio_operations(struct wil6210_priv *wil);
 void wil_p2p_delayed_listen_work(struct work_struct *work);
 
 /* WMI for P2P */
-int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi);
-int wmi_start_listen(struct wil6210_priv *wil);
-int wmi_start_search(struct wil6210_priv *wil);
-int wmi_stop_discovery(struct wil6210_priv *wil);
+int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi);
+int wmi_start_listen(struct wil6210_vif *vif);
+int wmi_start_search(struct wil6210_vif *vif);
+int wmi_stop_discovery(struct wil6210_vif *vif);
 
 int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 			 struct cfg80211_mgmt_tx_params *params,
@@ -1025,7 +1048,7 @@ int wil_cfg80211_iface_combinations_from_fw(
 static inline void wil6210_debugfs_remove(struct wil6210_priv *wil) {}
 #endif
 
-int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
+int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid,
 		       struct station_info *sinfo);
 
 struct wil6210_priv *wil_cfg80211_init(struct device *dev);
@@ -1033,29 +1056,30 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
 void wil_p2p_wdev_free(struct wil6210_priv *wil);
 
 int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
-int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
-		  u8 chan, u8 hidden_ssid, u8 is_go);
-int wmi_pcp_stop(struct wil6210_priv *wil);
+int wmi_pcp_start(struct wil6210_vif *vif, int bi, u8 wmi_nettype, u8 chan,
+		  u8 hidden_ssid, u8 is_go);
+int wmi_pcp_stop(struct wil6210_vif *vif);
 int wmi_led_cfg(struct wil6210_priv *wil, bool enable);
-int wmi_abort_scan(struct wil6210_priv *wil);
-void wil_abort_scan(struct wil6210_priv *wil, bool sync);
+int wmi_abort_scan(struct wil6210_vif *vif);
+void wil_abort_scan(struct wil6210_vif *vif, bool sync);
 void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps);
-void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
+void wil6210_disconnect(struct wil6210_vif *vif, const u8 *bssid,
 			u16 reason_code, bool from_event);
-void wil_probe_client_flush(struct wil6210_priv *wil);
+void wil_probe_client_flush(struct wil6210_vif *vif);
 void wil_probe_client_worker(struct work_struct *work);
+void wil_disconnect_worker(struct work_struct *work);
 
 int wil_rx_init(struct wil6210_priv *wil, u16 size);
 void wil_rx_fini(struct wil6210_priv *wil);
 
 /* TX API */
-int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
+int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size,
 		      int cid, int tid);
 void wil_vring_fini_tx(struct wil6210_priv *wil, int id);
-int wil_tx_init(struct wil6210_priv *wil, int cid);
-int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size);
-int wil_bcast_init(struct wil6210_priv *wil);
-void wil_bcast_fini(struct wil6210_priv *wil);
+int wil_tx_init(struct wil6210_vif *vif, int cid);
+int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size);
+int wil_bcast_init(struct wil6210_vif *vif);
+void wil_bcast_fini(struct wil6210_vif *vif);
 
 void wil_update_net_queues(struct wil6210_priv *wil, struct vring *vring,
 			   bool should_stop);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index b31e251..044d698 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -516,7 +516,8 @@ static const char *eventid2name(u16 eventid)
 	}
 }
 
-static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
+static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid,
+		      void *buf, u16 len)
 {
 	struct {
 		struct wil6210_mbox_hdr hdr;
@@ -528,7 +529,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 			.len = cpu_to_le16(sizeof(cmd.wmi) + len),
 		},
 		.wmi = {
-			.mid = 0,
+			.mid = mid,
 			.command_id = cpu_to_le16(cmdid),
 		},
 	};
@@ -612,8 +613,8 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 	}
 	cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
 	/* set command */
-	wil_dbg_wmi(wil, "sending %s (0x%04x) [%d]\n",
-		    cmdid2name(cmdid), cmdid, len);
+	wil_dbg_wmi(wil, "sending %s (0x%04x) [%d] mid %d\n",
+		    cmdid2name(cmdid), cmdid, len, mid);
 	wil_hex_dump_wmi("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
 			 sizeof(cmd), true);
 	wil_hex_dump_wmi("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
@@ -637,21 +638,22 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
 	return rc;
 }
 
-int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
+int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len)
 {
 	int rc;
 
 	mutex_lock(&wil->wmi_mutex);
-	rc = __wmi_send(wil, cmdid, buf, len);
+	rc = __wmi_send(wil, cmdid, mid, buf, len);
 	mutex_unlock(&wil->wmi_mutex);
 
 	return rc;
 }
 
 /*=== Event handlers ===*/
-static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
+static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len)
 {
-	struct wireless_dev *wdev = wil->wdev;
+	struct wil6210_priv *wil = vif_to_wil(vif);
+	struct wiphy *wiphy = wil_to_wiphy(wil);
 	struct wmi_ready_event *evt = d;
 
 	wil->n_mids = evt->numof_additional_mids;
@@ -660,8 +662,7 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
 		 wil->fw_version, le32_to_cpu(evt->sw_version),
 		 evt->mac, wil->n_mids);
 	/* ignore MAC address, we already have it from the boot loader */
-	strlcpy(wdev->wiphy->fw_version, wil->fw_version,
-		sizeof(wdev->wiphy->fw_version));
+	strlcpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));
 
 	if (len > offsetof(struct wmi_ready_event, rfc_read_calib_result)) {
 		wil_dbg_wmi(wil, "rfc calibration result %d\n",
@@ -674,8 +675,9 @@ static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
 	complete(&wil->wmi_ready);
 }
 
-static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
+static void wmi_evt_rx_mgmt(struct wil6210_vif *vif, int id, void *d, int len)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_rx_mgmt_packet_event *data = d;
 	struct wiphy *wiphy = wil_to_wiphy(wil);
 	struct ieee80211_mgmt *rx_mgmt_frame =
@@ -754,13 +756,13 @@ static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
 		}
 	} else {
 		mutex_lock(&wil->p2p_wdev_mutex);
-		cfg80211_rx_mgmt(wil->radio_wdev, freq, signal,
+		cfg80211_rx_mgmt(vif_to_radio_wdev(wil, vif), freq, signal,
 				 (void *)rx_mgmt_frame, d_len, 0);
 		mutex_unlock(&wil->p2p_wdev_mutex);
 	}
 }
 
-static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
+static void wmi_evt_tx_mgmt(struct wil6210_vif *vif, int id, void *d, int len)
 {
 	struct wmi_tx_mgmt_packet_event *data = d;
 	struct ieee80211_mgmt *mgmt_frame =
@@ -771,11 +773,13 @@ static void wmi_evt_tx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
 			 flen, true);
 }
 
-static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
+static void wmi_evt_scan_complete(struct wil6210_vif *vif, int id,
 				  void *d, int len)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
+
 	mutex_lock(&wil->p2p_wdev_mutex);
-	if (wil->scan_request) {
+	if (vif->scan_request) {
 		struct wmi_scan_complete_event *data = d;
 		int status = le32_to_cpu(data->status);
 		struct cfg80211_scan_info info = {
@@ -785,15 +789,16 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
 
 		wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", status);
 		wil_dbg_misc(wil, "Complete scan_request 0x%p aborted %d\n",
-			     wil->scan_request, info.aborted);
-		del_timer_sync(&wil->scan_timer);
-		cfg80211_scan_done(wil->scan_request, &info);
-		wil->radio_wdev = wil->wdev;
-		wil->scan_request = NULL;
+			     vif->scan_request, info.aborted);
+		del_timer_sync(&vif->scan_timer);
+		cfg80211_scan_done(vif->scan_request, &info);
+		if (vif->mid == 0)
+			wil->radio_wdev = wil->main_ndev->ieee80211_ptr;
+		vif->scan_request = NULL;
 		wake_up_interruptible(&wil->wq);
-		if (wil->p2p.pending_listen_wdev) {
+		if (vif->p2p.pending_listen_wdev) {
 			wil_dbg_misc(wil, "Scheduling delayed listen\n");
-			schedule_work(&wil->p2p.delayed_listen_work);
+			schedule_work(&vif->p2p.delayed_listen_work);
 		}
 	} else {
 		wil_err(wil, "SCAN_COMPLETE while not scanning\n");
@@ -801,10 +806,11 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
 	mutex_unlock(&wil->p2p_wdev_mutex);
 }
 
-static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
+static void wmi_evt_connect(struct wil6210_vif *vif, int id, void *d, int len)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
-	struct wireless_dev *wdev = wil->wdev;
+	struct wil6210_priv *wil = vif_to_wil(vif);
+	struct net_device *ndev = vif_to_ndev(vif);
+	struct wireless_dev *wdev = vif_to_wdev(vif);
 	struct wmi_connect_event *evt = d;
 	int ch; /* channel number */
 	struct station_info sinfo;
@@ -874,7 +880,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
 			mutex_unlock(&wil->mutex);
 			return;
 		}
-		del_timer_sync(&wil->connect_timer);
+		del_timer_sync(&vif->connect_timer);
 	} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
 		   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
 		if (wil->sta[evt->cid].status != wil_sta_unused) {
@@ -886,13 +892,14 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
 	}
 
 	ether_addr_copy(wil->sta[evt->cid].addr, evt->bssid);
+	wil->sta[evt->cid].mid = vif->mid;
 	wil->sta[evt->cid].status = wil_sta_conn_pending;
 
-	rc = wil_tx_init(wil, evt->cid);
+	rc = wil_tx_init(vif, evt->cid);
 	if (rc) {
 		wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n",
 			evt->cid, rc);
-		wmi_disconnect_sta(wil, wil->sta[evt->cid].addr,
+		wmi_disconnect_sta(vif, wil->sta[evt->cid].addr,
 				   WLAN_REASON_UNSPECIFIED, false, false);
 	} else {
 		wil_info(wil, "successful connection to CID %d\n", evt->cid);
@@ -912,14 +919,14 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
 		} else {
 			struct wiphy *wiphy = wil_to_wiphy(wil);
 
-			cfg80211_ref_bss(wiphy, wil->bss);
-			cfg80211_connect_bss(ndev, evt->bssid, wil->bss,
+			cfg80211_ref_bss(wiphy, vif->bss);
+			cfg80211_connect_bss(ndev, evt->bssid, vif->bss,
 					     assoc_req_ie, assoc_req_ielen,
 					     assoc_resp_ie, assoc_resp_ielen,
 					     WLAN_STATUS_SUCCESS, GFP_KERNEL,
 					     NL80211_TIMEOUT_UNSPECIFIED);
 		}
-		wil->bss = NULL;
+		vif->bss = NULL;
 	} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
 		   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
 		if (rc) {
@@ -951,15 +958,18 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
 	wil_update_net_queues_bh(wil, NULL, false);
 
 out:
-	if (rc)
+	if (rc) {
 		wil->sta[evt->cid].status = wil_sta_unused;
+		wil->sta[evt->cid].mid = U8_MAX;
+	}
 	clear_bit(wil_status_fwconnecting, wil->status);
 	mutex_unlock(&wil->mutex);
 }
 
-static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
+static void wmi_evt_disconnect(struct wil6210_vif *vif, int id,
 			       void *d, int len)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_disconnect_event *evt = d;
 	u16 reason_code = le16_to_cpu(evt->protocol_reason_status);
 
@@ -976,7 +986,7 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
 	}
 
 	mutex_lock(&wil->mutex);
-	wil6210_disconnect(wil, evt->bssid, reason_code, true);
+	wil6210_disconnect(vif, evt->bssid, reason_code, true);
 	mutex_unlock(&wil->mutex);
 }
 
@@ -984,10 +994,10 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
  * Firmware reports EAPOL frame using WME event.
  * Reconstruct Ethernet frame and deliver it via normal Rx
  */
-static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
-			     void *d, int len)
+static void wmi_evt_eapol_rx(struct wil6210_vif *vif, int id, void *d, int len)
 {
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct wil6210_priv *wil = vif_to_wil(vif);
+	struct net_device *ndev = vif_to_ndev(vif);
 	struct wmi_eapol_rx_event *evt = d;
 	u16 eapol_len = le16_to_cpu(evt->eapol_len);
 	int sz = eapol_len + ETH_HLEN;
@@ -996,10 +1006,10 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
 	int cid;
 	struct wil_net_stats *stats = NULL;
 
-	wil_dbg_wmi(wil, "EAPOL len %d from %pM\n", eapol_len,
-		    evt->src_mac);
+	wil_dbg_wmi(wil, "EAPOL len %d from %pM MID %d\n", eapol_len,
+		    evt->src_mac, vif->mid);
 
-	cid = wil_find_cid(wil, evt->src_mac);
+	cid = wil_find_cid(wil, vif->mid, evt->src_mac);
 	if (cid >= 0)
 		stats = &wil->sta[cid].stats;
 
@@ -1034,13 +1044,14 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
 	}
 }
 
-static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len)
+static void wmi_evt_vring_en(struct wil6210_vif *vif, int id, void *d, int len)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_vring_en_event *evt = d;
 	u8 vri = evt->vring_index;
-	struct wireless_dev *wdev = wil_to_wdev(wil);
+	struct wireless_dev *wdev = vif_to_wdev(vif);
 
-	wil_dbg_wmi(wil, "Enable vring %d\n", vri);
+	wil_dbg_wmi(wil, "Enable vring %d MID %d\n", vri, vif->mid);
 
 	if (vri >= ARRAY_SIZE(wil->vring_tx)) {
 		wil_err(wil, "Enable for invalid vring %d\n", vri);
@@ -1052,15 +1063,16 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len)
 		 * wil_cfg80211_change_station()
 		 */
 		wil->vring_tx_data[vri].dot1x_open = true;
-	if (vri == wil->bcast_vring) /* no BA for bcast */
+	if (vri == vif->bcast_vring) /* no BA for bcast */
 		return;
 	if (agg_wsize >= 0)
 		wil_addba_tx_request(wil, vri, agg_wsize);
 }
 
-static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
-			      int len)
+static void wmi_evt_ba_status(struct wil6210_vif *vif, int id,
+			      void *d, int len)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_ba_status_event *evt = d;
 	struct vring_tx_data *txdata;
 
@@ -1089,19 +1101,21 @@ static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
 	txdata->addba_in_progress = false;
 }
 
-static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d,
-				 int len)
+static void wmi_evt_addba_rx_req(struct wil6210_vif *vif, int id,
+				 void *d, int len)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_rcp_addba_req_event *evt = d;
 
-	wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token,
+	wil_addba_rx_request(wil, vif->mid, evt->cidxtid, evt->dialog_token,
 			     evt->ba_param_set, evt->ba_timeout,
 			     evt->ba_seq_ctrl);
 }
 
-static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
+static void wmi_evt_delba(struct wil6210_vif *vif, int id, void *d, int len)
 __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_delba_event *evt = d;
 	u8 cid, tid;
 	u16 reason = __le16_to_cpu(evt->reason);
@@ -1110,8 +1124,8 @@ static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
 
 	might_sleep();
 	parse_cidxtid(evt->cidxtid, &cid, &tid);
-	wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n",
-		    cid, tid,
+	wil_dbg_wmi(wil, "DELBA MID %d CID %d TID %d from %s reason %d\n",
+		    vif->mid, cid, tid,
 		    evt->from_initiator ? "originator" : "recipient",
 		    reason);
 	if (!evt->from_initiator) {
@@ -1148,8 +1162,9 @@ static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
 }
 
 static void
-wmi_evt_sched_scan_result(struct wil6210_priv *wil, int id, void *d, int len)
+wmi_evt_sched_scan_result(struct wil6210_vif *vif, int id, void *d, int len)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_sched_scan_result_event *data = d;
 	struct wiphy *wiphy = wil_to_wiphy(wil);
 	struct ieee80211_mgmt *rx_mgmt_frame =
@@ -1220,15 +1235,17 @@ static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
  * Some events are ignored for purpose; and need not be interpreted as
  * "unhandled events"
  */
-static void wmi_evt_ignore(struct wil6210_priv *wil, int id, void *d, int len)
+static void wmi_evt_ignore(struct wil6210_vif *vif, int id, void *d, int len)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
+
 	wil_dbg_wmi(wil, "Ignore event 0x%04x len %d\n", id, len);
 }
 
 static const struct {
 	int eventid;
-	void (*handler)(struct wil6210_priv *wil, int eventid,
-			void *data, int data_len);
+	void (*handler)(struct wil6210_vif *vif,
+			int eventid, void *data, int data_len);
 } wmi_evt_handlers[] = {
 	{WMI_READY_EVENTID,		wmi_evt_ready},
 	{WMI_FW_READY_EVENTID,			wmi_evt_ignore},
@@ -1325,6 +1342,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
 		    (len >= sizeof(struct wmi_cmd_hdr))) {
 			struct wmi_cmd_hdr *wmi = &evt->event.wmi;
 			u16 id = le16_to_cpu(wmi->command_id);
+			u8 mid = wmi->mid;
 			u32 tstamp = le32_to_cpu(wmi->fw_timestamp);
 			if (test_bit(wil_status_resuming, wil->status)) {
 				if (id == WMI_TRAFFIC_RESUME_EVENTID)
@@ -1336,7 +1354,8 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
 						id);
 			}
 			spin_lock_irqsave(&wil->wmi_ev_lock, flags);
-			if (wil->reply_id && wil->reply_id == id) {
+			if (wil->reply_id && wil->reply_id == id &&
+			    wil->reply_mid == mid) {
 				if (wil->reply_buf) {
 					memcpy(wil->reply_buf, wmi,
 					       min(len, wil->reply_size));
@@ -1384,7 +1403,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
 		    n - num_immed_reply, num_immed_reply);
 }
 
-int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
+int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len,
 	     u16 reply_id, void *reply, u8 reply_size, int to_msec)
 {
 	int rc;
@@ -1394,12 +1413,13 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
 
 	spin_lock(&wil->wmi_ev_lock);
 	wil->reply_id = reply_id;
+	wil->reply_mid = mid;
 	wil->reply_buf = reply;
 	wil->reply_size = reply_size;
 	reinit_completion(&wil->wmi_call);
 	spin_unlock(&wil->wmi_ev_lock);
 
-	rc = __wmi_send(wil, cmdid, buf, len);
+	rc = __wmi_send(wil, cmdid, mid, buf, len);
 	if (rc)
 		goto out;
 
@@ -1419,6 +1439,7 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
 out:
 	spin_lock(&wil->wmi_ev_lock);
 	wil->reply_id = 0;
+	wil->reply_mid = U8_MAX;
 	wil->reply_buf = NULL;
 	wil->reply_size = 0;
 	spin_unlock(&wil->wmi_ev_lock);
@@ -1430,27 +1451,31 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
 
 int wmi_echo(struct wil6210_priv *wil)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	struct wmi_echo_cmd cmd = {
 		.value = cpu_to_le32(0x12345678),
 	};
 
-	return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd),
+	return wmi_call(wil, WMI_ECHO_CMDID, vif->mid, &cmd, sizeof(cmd),
 			WMI_ECHO_RSP_EVENTID, NULL, 0, 50);
 }
 
 int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	struct wmi_set_mac_address_cmd cmd;
 
 	ether_addr_copy(cmd.mac, addr);
 
 	wil_dbg_wmi(wil, "Set MAC %pM\n", addr);
 
-	return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
+	return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, vif->mid,
+			&cmd, sizeof(cmd));
 }
 
 int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int rc = 0;
 	struct wmi_led_cfg_cmd cmd = {
 		.led_mode = enable,
@@ -1487,7 +1512,7 @@ int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
 		    "%s led %d\n",
 		    enable ? "enabling" : "disabling", led_id);
 
-	rc = wmi_call(wil, WMI_LED_CFG_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_LED_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
 		      WMI_LED_CFG_DONE_EVENTID, &reply, sizeof(reply),
 		      100);
 	if (rc)
@@ -1503,9 +1528,10 @@ int wmi_led_cfg(struct wil6210_priv *wil, bool enable)
 	return rc;
 }
 
-int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
-		  u8 chan, u8 hidden_ssid, u8 is_go)
+int wmi_pcp_start(struct wil6210_vif *vif,
+		  int bi, u8 wmi_nettype, u8 chan, u8 hidden_ssid, u8 is_go)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 
 	struct wmi_pcp_start_cmd cmd = {
@@ -1524,7 +1550,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
 		struct wmi_pcp_started_event evt;
 	} __packed reply;
 
-	if (!wil->privacy)
+	if (!vif->privacy)
 		cmd.disable_sec = 1;
 
 	if ((cmd.pcp_max_assoc_sta > WIL6210_MAX_CID) ||
@@ -1546,7 +1572,7 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
 	 * Processing time may be huge, in case of secure AP it takes about
 	 * 3500ms for FW to start AP
 	 */
-	rc = wmi_call(wil, WMI_PCP_START_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_PCP_START_CMDID, vif->mid, &cmd, sizeof(cmd),
 		      WMI_PCP_STARTED_EVENTID, &reply, sizeof(reply), 5000);
 	if (rc)
 		return rc;
@@ -1561,20 +1587,22 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype,
 	return rc;
 }
 
-int wmi_pcp_stop(struct wil6210_priv *wil)
+int wmi_pcp_stop(struct wil6210_vif *vif)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 
 	rc = wmi_led_cfg(wil, false);
 	if (rc)
 		return rc;
 
-	return wmi_call(wil, WMI_PCP_STOP_CMDID, NULL, 0,
+	return wmi_call(wil, WMI_PCP_STOP_CMDID, vif->mid, NULL, 0,
 			WMI_PCP_STOPPED_EVENTID, NULL, 0, 20);
 }
 
-int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid)
+int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_set_ssid_cmd cmd = {
 		.ssid_len = cpu_to_le32(ssid_len),
 	};
@@ -1584,11 +1612,12 @@ int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid)
 
 	memcpy(cmd.ssid, ssid, ssid_len);
 
-	return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd));
+	return wmi_send(wil, WMI_SET_SSID_CMDID, vif->mid, &cmd, sizeof(cmd));
 }
 
-int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
+int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 	struct {
 		struct wmi_cmd_hdr wmi;
@@ -1596,8 +1625,8 @@ int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
 	} __packed reply;
 	int len; /* reply.cmd.ssid_len in CPU order */
 
-	rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID,
-		      &reply, sizeof(reply), 20);
+	rc = wmi_call(wil, WMI_GET_SSID_CMDID, vif->mid, NULL, 0,
+		      WMI_GET_SSID_EVENTID, &reply, sizeof(reply), 20);
 	if (rc)
 		return rc;
 
@@ -1613,22 +1642,25 @@ int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
 
 int wmi_set_channel(struct wil6210_priv *wil, int channel)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	struct wmi_set_pcp_channel_cmd cmd = {
 		.channel = channel - 1,
 	};
 
-	return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd));
+	return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, vif->mid,
+			&cmd, sizeof(cmd));
 }
 
 int wmi_get_channel(struct wil6210_priv *wil, int *channel)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int rc;
 	struct {
 		struct wmi_cmd_hdr wmi;
 		struct wmi_set_pcp_channel_cmd cmd;
 	} __packed reply;
 
-	rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0,
+	rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, vif->mid, NULL, 0,
 		      WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20);
 	if (rc)
 		return rc;
@@ -1641,8 +1673,9 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel)
 	return 0;
 }
 
-int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi)
+int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 	struct wmi_p2p_cfg_cmd cmd = {
 		.discovery_mode = WMI_DISCOVERY_MODE_PEER2PEER,
@@ -1656,7 +1689,7 @@ int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi)
 
 	wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n");
 
-	rc = wmi_call(wil, WMI_P2P_CFG_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_P2P_CFG_CMDID, vif->mid, &cmd, sizeof(cmd),
 		      WMI_P2P_CFG_DONE_EVENTID, &reply, sizeof(reply), 300);
 	if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
 		wil_err(wil, "P2P_CFG failed. status %d\n", reply.evt.status);
@@ -1666,8 +1699,9 @@ int wmi_p2p_cfg(struct wil6210_priv *wil, int channel, int bi)
 	return rc;
 }
 
-int wmi_start_listen(struct wil6210_priv *wil)
+int wmi_start_listen(struct wil6210_vif *vif)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 	struct {
 		struct wmi_cmd_hdr wmi;
@@ -1676,7 +1710,7 @@ int wmi_start_listen(struct wil6210_priv *wil)
 
 	wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n");
 
-	rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
+	rc = wmi_call(wil, WMI_START_LISTEN_CMDID, vif->mid, NULL, 0,
 		      WMI_LISTEN_STARTED_EVENTID, &reply, sizeof(reply), 300);
 	if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
 		wil_err(wil, "device failed to start listen. status %d\n",
@@ -1687,8 +1721,9 @@ int wmi_start_listen(struct wil6210_priv *wil)
 	return rc;
 }
 
-int wmi_start_search(struct wil6210_priv *wil)
+int wmi_start_search(struct wil6210_vif *vif)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 	struct {
 		struct wmi_cmd_hdr wmi;
@@ -1697,7 +1732,7 @@ int wmi_start_search(struct wil6210_priv *wil)
 
 	wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n");
 
-	rc = wmi_call(wil, WMI_START_SEARCH_CMDID, NULL, 0,
+	rc = wmi_call(wil, WMI_START_SEARCH_CMDID, vif->mid, NULL, 0,
 		      WMI_SEARCH_STARTED_EVENTID, &reply, sizeof(reply), 300);
 	if (!rc && reply.evt.status != WMI_FW_STATUS_SUCCESS) {
 		wil_err(wil, "device failed to start search. status %d\n",
@@ -1708,13 +1743,14 @@ int wmi_start_search(struct wil6210_priv *wil)
 	return rc;
 }
 
-int wmi_stop_discovery(struct wil6210_priv *wil)
+int wmi_stop_discovery(struct wil6210_vif *vif)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 
 	wil_dbg_wmi(wil, "sending WMI_DISCOVERY_STOP_CMDID\n");
 
-	rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
+	rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0,
 		      WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 100);
 
 	if (rc)
@@ -1723,9 +1759,10 @@ int wmi_stop_discovery(struct wil6210_priv *wil)
 	return rc;
 }
 
-int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
+int wmi_del_cipher_key(struct wil6210_vif *vif, u8 key_index,
 		       const void *mac_addr, int key_usage)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_delete_cipher_key_cmd cmd = {
 		.key_index = key_index,
 	};
@@ -1733,13 +1770,15 @@ int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
 	if (mac_addr)
 		memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
 
-	return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
+	return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, vif->mid,
+			&cmd, sizeof(cmd));
 }
 
-int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
+int wmi_add_cipher_key(struct wil6210_vif *vif, u8 key_index,
 		       const void *mac_addr, int key_len, const void *key,
 		       int key_usage)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	struct wmi_add_cipher_key_cmd cmd = {
 		.key_index = key_index,
 		.key_usage = key_usage,
@@ -1753,11 +1792,13 @@ int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
 	if (mac_addr)
 		memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
 
-	return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
+	return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, vif->mid,
+			&cmd, sizeof(cmd));
 }
 
-int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
+int wmi_set_ie(struct wil6210_vif *vif, u8 type, u16 ie_len, const void *ie)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	static const char *const names[] = {
 		[WMI_FRAME_BEACON]	= "BEACON",
 		[WMI_FRAME_PROBE_REQ]	= "PROBE_REQ",
@@ -1786,7 +1827,7 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
 	/* BUG: FW API define ieLen as u8. Will fix FW */
 	cmd->ie_len = cpu_to_le16(ie_len);
 	memcpy(cmd->ie_info, ie, ie_len);
-	rc = wmi_send(wil, WMI_SET_APPIE_CMDID, cmd, len);
+	rc = wmi_send(wil, WMI_SET_APPIE_CMDID, vif->mid, cmd, len);
 	kfree(cmd);
 out:
 	if (rc) {
@@ -1808,6 +1849,7 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
  */
 int wmi_rxon(struct wil6210_priv *wil, bool on)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int rc;
 	struct {
 		struct wmi_cmd_hdr wmi;
@@ -1817,13 +1859,13 @@ int wmi_rxon(struct wil6210_priv *wil, bool on)
 	wil_info(wil, "(%s)\n", on ? "on" : "off");
 
 	if (on) {
-		rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0,
+		rc = wmi_call(wil, WMI_START_LISTEN_CMDID, vif->mid, NULL, 0,
 			      WMI_LISTEN_STARTED_EVENTID,
 			      &reply, sizeof(reply), 100);
 		if ((rc == 0) && (reply.evt.status != WMI_FW_STATUS_SUCCESS))
 			rc = -EINVAL;
 	} else {
-		rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, NULL, 0,
+		rc = wmi_call(wil, WMI_DISCOVERY_STOP_CMDID, vif->mid, NULL, 0,
 			      WMI_DISCOVERY_STOPPED_EVENTID, NULL, 0, 20);
 	}
 
@@ -1832,8 +1874,9 @@ int wmi_rxon(struct wil6210_priv *wil, bool on)
 
 int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
 {
-	struct wireless_dev *wdev = wil->wdev;
-	struct net_device *ndev = wil_to_ndev(wil);
+	struct net_device *ndev = wil->main_ndev;
+	struct wireless_dev *wdev = ndev->ieee80211_ptr;
+	struct wil6210_vif *vif = ndev_to_vif(ndev);
 	struct wmi_cfg_rx_chain_cmd cmd = {
 		.action = WMI_RX_CHAIN_ADD,
 		.rx_sw_ring = {
@@ -1877,7 +1920,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
 				L2_802_3_OFFLOAD_CTRL_SNAP_KEEP_MSK;
 
 	/* typical time for secure PCP is 840ms */
-	rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, vif->mid, &cmd, sizeof(cmd),
 		      WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
 	if (rc)
 		return rc;
@@ -1895,6 +1938,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
 
 int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int rc;
 	struct wmi_temp_sense_cmd cmd = {
 		.measure_baseband_en = cpu_to_le32(!!t_bb),
@@ -1906,7 +1950,7 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
 		struct wmi_temp_sense_done_event evt;
 	} __packed reply;
 
-	rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, vif->mid, &cmd, sizeof(cmd),
 		      WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100);
 	if (rc)
 		return rc;
@@ -1919,9 +1963,10 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf)
 	return 0;
 }
 
-int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac,
+int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac,
 		       u16 reason, bool full_disconnect, bool del_sta)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 	u16 reason_code;
 	struct wmi_disconnect_sta_cmd disc_sta_cmd = {
@@ -1937,16 +1982,17 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac,
 
 	wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason);
 
-	wil->locally_generated_disc = true;
+	vif->locally_generated_disc = true;
 	if (del_sta) {
 		ether_addr_copy(del_sta_cmd.dst_mac, mac);
-		rc = wmi_call(wil, WMI_DEL_STA_CMDID, &del_sta_cmd,
+		rc = wmi_call(wil, WMI_DEL_STA_CMDID, vif->mid, &del_sta_cmd,
 			      sizeof(del_sta_cmd), WMI_DISCONNECT_EVENTID,
 			      &reply, sizeof(reply), 1000);
 	} else {
 		ether_addr_copy(disc_sta_cmd.dst_mac, mac);
-		rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &disc_sta_cmd,
-			      sizeof(disc_sta_cmd), WMI_DISCONNECT_EVENTID,
+		rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, vif->mid,
+			      &disc_sta_cmd, sizeof(disc_sta_cmd),
+			      WMI_DISCONNECT_EVENTID,
 			      &reply, sizeof(reply), 1000);
 	}
 	/* failure to disconnect in reasonable time treated as FW error */
@@ -1967,12 +2013,13 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac,
 			    reply.evt.disconnect_reason);
 
 		wil->sinfo_gen++;
-		wil6210_disconnect(wil, reply.evt.bssid, reason_code, true);
+		wil6210_disconnect(vif, reply.evt.bssid, reason_code, true);
 	}
 	return 0;
 }
 
-int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout)
+int wmi_addba(struct wil6210_priv *wil, u8 mid,
+	      u8 ringid, u8 size, u16 timeout)
 {
 	struct wmi_vring_ba_en_cmd cmd = {
 		.ringid = ringid,
@@ -1984,10 +2031,10 @@ int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout)
 	wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d)\n", ringid, size,
 		    timeout);
 
-	return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd));
+	return wmi_send(wil, WMI_VRING_BA_EN_CMDID, mid, &cmd, sizeof(cmd));
 }
 
-int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason)
+int wmi_delba_tx(struct wil6210_priv *wil, u8 mid, u8 ringid, u16 reason)
 {
 	struct wmi_vring_ba_dis_cmd cmd = {
 		.ringid = ringid,
@@ -1996,10 +2043,10 @@ int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason)
 
 	wil_dbg_wmi(wil, "delba_tx: (ring %d reason %d)\n", ringid, reason);
 
-	return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd));
+	return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, mid, &cmd, sizeof(cmd));
 }
 
-int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason)
+int wmi_delba_rx(struct wil6210_priv *wil, u8 mid, u8 cidxtid, u16 reason)
 {
 	struct wmi_rcp_delba_cmd cmd = {
 		.cidxtid = cidxtid,
@@ -2009,10 +2056,11 @@ int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason)
 	wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf,
 		    (cidxtid >> 4) & 0xf, reason);
 
-	return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd));
+	return wmi_send(wil, WMI_RCP_DELBA_CMDID, mid, &cmd, sizeof(cmd));
 }
 
-int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
+int wmi_addba_rx_resp(struct wil6210_priv *wil,
+		      u8 mid, u8 cid, u8 tid, u8 token,
 		      u16 status, bool amsdu, u16 agg_wsize, u16 timeout)
 {
 	int rc;
@@ -2035,10 +2083,11 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
 	} __packed reply;
 
 	wil_dbg_wmi(wil,
-		    "ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
-		    cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-");
+		    "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
+		    mid, cid, tid, agg_wsize,
+		    timeout, status, amsdu ? "+" : "-");
 
-	rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, mid, &cmd, sizeof(cmd),
 		      WMI_RCP_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply),
 		      100);
 	if (rc)
@@ -2056,6 +2105,7 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
 int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
 			   enum wmi_ps_profile_type ps_profile)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int rc;
 	struct wmi_ps_dev_profile_cfg_cmd cmd = {
 		.ps_profile = ps_profile,
@@ -2070,7 +2120,8 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
 
 	reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR);
 
-	rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, vif->mid,
+		      &cmd, sizeof(cmd),
 		      WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply),
 		      100);
 	if (rc)
@@ -2089,6 +2140,7 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil,
 
 int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int rc;
 	struct wmi_set_mgmt_retry_limit_cmd cmd = {
 		.mgmt_retry_limit = retry_short,
@@ -2105,7 +2157,8 @@ int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short)
 
 	reply.evt.status = WMI_FW_STATUS_FAILURE;
 
-	rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, vif->mid,
+		      &cmd, sizeof(cmd),
 		      WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
 		      100);
 	if (rc)
@@ -2122,6 +2175,7 @@ int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short)
 
 int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int rc;
 	struct {
 		struct wmi_cmd_hdr wmi;
@@ -2134,7 +2188,7 @@ int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short)
 		return -ENOTSUPP;
 
 	reply.evt.mgmt_retry_limit = 0;
-	rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, NULL, 0,
+	rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, vif->mid, NULL, 0,
 		      WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply),
 		      100);
 	if (rc)
@@ -2146,21 +2200,23 @@ int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short)
 	return 0;
 }
 
-int wmi_abort_scan(struct wil6210_priv *wil)
+int wmi_abort_scan(struct wil6210_vif *vif)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 
 	wil_dbg_wmi(wil, "sending WMI_ABORT_SCAN_CMDID\n");
 
-	rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, NULL, 0);
+	rc = wmi_send(wil, WMI_ABORT_SCAN_CMDID, vif->mid, NULL, 0);
 	if (rc)
 		wil_err(wil, "Failed to abort scan (%d)\n", rc);
 
 	return rc;
 }
 
-int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid)
+int wmi_new_sta(struct wil6210_vif *vif, const u8 *mac, u8 aid)
 {
+	struct wil6210_priv *wil = vif_to_wil(vif);
 	int rc;
 	struct wmi_new_sta_cmd cmd = {
 		.aid = aid,
@@ -2170,7 +2226,7 @@ int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid)
 
 	ether_addr_copy(cmd.dst_mac, mac);
 
-	rc = wmi_send(wil, WMI_NEW_STA_CMDID, &cmd, sizeof(cmd));
+	rc = wmi_send(wil, WMI_NEW_STA_CMDID, vif->mid, &cmd, sizeof(cmd));
 	if (rc)
 		wil_err(wil, "Failed to send new sta (%d)\n", rc);
 
@@ -2206,6 +2262,7 @@ static const char *suspend_status2name(u8 status)
 
 int wmi_suspend(struct wil6210_priv *wil)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int rc;
 	struct wmi_traffic_suspend_cmd cmd = {
 		.wakeup_trigger = wil->wakeup_trigger,
@@ -2221,7 +2278,8 @@ int wmi_suspend(struct wil6210_priv *wil)
 
 	reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE;
 
-	rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, vif->mid,
+		      &cmd, sizeof(cmd),
 		      WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply),
 		      suspend_to);
 	if (rc) {
@@ -2289,6 +2347,7 @@ static void resume_triggers2string(u32 triggers, char *string, int str_size)
 
 int wmi_resume(struct wil6210_priv *wil)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int rc;
 	char string[100];
 	struct {
@@ -2299,7 +2358,7 @@ int wmi_resume(struct wil6210_priv *wil)
 	reply.evt.status = WMI_TRAFFIC_RESUME_FAILED;
 	reply.evt.resume_triggers = WMI_RESUME_TRIGGER_UNKNOWN;
 
-	rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, NULL, 0,
+	rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, vif->mid, NULL, 0,
 		      WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply),
 		      WIL_WAIT_FOR_SUSPEND_RESUME_COMP);
 	if (rc)
@@ -2313,14 +2372,14 @@ int wmi_resume(struct wil6210_priv *wil)
 	return reply.evt.status;
 }
 
-static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
+static bool wmi_evt_call_handler(struct wil6210_vif *vif, int id,
 				 void *d, int len)
 {
 	uint i;
 
 	for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) {
 		if (wmi_evt_handlers[i].eventid == id) {
-			wmi_evt_handlers[i].handler(wil, id, d, len);
+			wmi_evt_handlers[i].handler(vif, id, d, len);
 			return true;
 		}
 	}
@@ -2332,19 +2391,25 @@ static void wmi_event_handle(struct wil6210_priv *wil,
 			     struct wil6210_mbox_hdr *hdr)
 {
 	u16 len = le16_to_cpu(hdr->len);
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 
 	if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
 	    (len >= sizeof(struct wmi_cmd_hdr))) {
 		struct wmi_cmd_hdr *wmi = (void *)(&hdr[1]);
 		void *evt_data = (void *)(&wmi[1]);
 		u16 id = le16_to_cpu(wmi->command_id);
+		u8 mid = wmi->mid;
+
+		wil_dbg_wmi(wil, "Handle %s (0x%04x) (reply_id 0x%04x,%d)\n",
+			    eventid2name(id), id, wil->reply_id,
+			    wil->reply_mid);
 
-		wil_dbg_wmi(wil, "Handle %s (0x%04x) (reply_id 0x%04x)\n",
-			    eventid2name(id), id, wil->reply_id);
 		/* check if someone waits for this event */
-		if (wil->reply_id && wil->reply_id == id) {
+		if (wil->reply_id && wil->reply_id == id &&
+		    wil->reply_mid == mid) {
 			WARN_ON(wil->reply_buf);
-			wmi_evt_call_handler(wil, id, evt_data,
+
+			wmi_evt_call_handler(vif, id, evt_data,
 					     len - sizeof(*wmi));
 			wil_dbg_wmi(wil, "event_handle: Complete WMI 0x%04x\n",
 				    id);
@@ -2353,7 +2418,7 @@ static void wmi_event_handle(struct wil6210_priv *wil,
 		}
 		/* unsolicited event */
 		/* search for handler */
-		if (!wmi_evt_call_handler(wil, id, evt_data,
+		if (!wmi_evt_call_handler(vif, id, evt_data,
 					  len - sizeof(*wmi))) {
 			wil_info(wil, "Unhandled event 0x%04x\n", id);
 		}
@@ -2523,6 +2588,7 @@ bool wil_is_wmi_idle(struct wil6210_priv *wil)
 int wmi_start_sched_scan(struct wil6210_priv *wil,
 			 struct cfg80211_sched_scan_request *request)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int rc;
 	struct wmi_start_sched_scan_cmd cmd = {
 		.min_rssi_threshold = S8_MIN,
@@ -2549,7 +2615,8 @@ int wmi_start_sched_scan(struct wil6210_priv *wil,
 
 	reply.evt.result = WMI_PNO_REJECT;
 
-	rc = wmi_call(wil, WMI_START_SCHED_SCAN_CMDID, &cmd, sizeof(cmd),
+	rc = wmi_call(wil, WMI_START_SCHED_SCAN_CMDID, vif->mid,
+		      &cmd, sizeof(cmd),
 		      WMI_START_SCHED_SCAN_EVENTID, &reply, sizeof(reply),
 		      WIL_WMI_CALL_GENERAL_TO_MS);
 	if (rc)
@@ -2566,6 +2633,7 @@ int wmi_start_sched_scan(struct wil6210_priv *wil,
 
 int wmi_stop_sched_scan(struct wil6210_priv *wil)
 {
+	struct wil6210_vif *vif = ndev_to_vif(wil->main_ndev);
 	int rc;
 	struct {
 		struct wmi_cmd_hdr wmi;
@@ -2577,7 +2645,7 @@ int wmi_stop_sched_scan(struct wil6210_priv *wil)
 
 	reply.evt.result = WMI_PNO_REJECT;
 
-	rc = wmi_call(wil, WMI_STOP_SCHED_SCAN_CMDID, NULL, 0,
+	rc = wmi_call(wil, WMI_STOP_SCHED_SCAN_CMDID, vif->mid, NULL, 0,
 		      WMI_STOP_SCHED_SCAN_EVENTID, &reply, sizeof(reply),
 		      WIL_WMI_CALL_GENERAL_TO_MS);
 	if (rc)
