Quellcode durchsuchen

qcacld-3.0: Get vdev from adapter directly

For the case that there is leakage of vdev, get ref of vdev by mac address
might get the incorrect vdev object. Get vdev from adapter directly.

Add help function to get vdev reference counted before use it.

Change-Id: I7d4ad1a2b7031f2877adb19bc15f690616e87c74
CRs-Fixed: 2312152
Min Liu vor 6 Jahren
Ursprung
Commit
8c5d99e012

+ 2 - 0
core/hdd/inc/wlan_hdd_main.h

@@ -1223,6 +1223,7 @@ struct hdd_context;
 /**
  * struct hdd_adapter - hdd vdev/net_device context
  * @vdev: object manager vdev context
+ * @vdev_lock: lock to protect vdev context access
  * @event_flags: a bitmap of hdd_adapter_flags
  */
 struct hdd_adapter {
@@ -1238,6 +1239,7 @@ struct hdd_adapter {
 
 	struct hdd_context *hdd_ctx;
 	struct wlan_objmgr_vdev *vdev;
+	qdf_spinlock_t vdev_lock;
 
 	void *txrx_vdev;
 

+ 91 - 31
core/hdd/src/wlan_hdd_cfg80211.c

@@ -127,6 +127,7 @@
 #include "wlan_nl_to_crypto_params.h"
 #include "wlan_crypto_global_def.h"
 #include "cdp_txrx_cfg.h"
+#include "wlan_hdd_object_manager.h"
 
 #define g_mode_rates_size (12)
 #define a_mode_rates_size (8)
@@ -4794,6 +4795,7 @@ void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
 	uint8_t *buf;
 	int i;
 	struct pmo_gtk_req *gtk_req = NULL;
+	struct wlan_objmgr_vdev *vdev;
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
 
 	gtk_req = qdf_mem_malloc(sizeof(*gtk_req));
@@ -4823,10 +4825,15 @@ void wlan_hdd_save_gtk_offload_params(struct hdd_adapter *adapter,
 	for (i = 0; i < 8; i++)
 		buf[7 - i] = replay_ctr[i];
 
-	status = ucfg_pmo_cache_gtk_offload_req(adapter->vdev, gtk_req);
+	vdev = hdd_objmgr_get_vdev(adapter);
+	if (!vdev)
+		goto end;
+	status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
+	hdd_objmgr_put_vdev(adapter);
 	if (status != QDF_STATUS_SUCCESS)
 		hdd_err("Failed to cache GTK Offload");
 
+end:
 	qdf_mem_free(gtk_req);
 }
 #else
@@ -5283,29 +5290,26 @@ static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
 {
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
 	enum QDF_OPMODE dev_mode = adapter->device_mode;
+	struct wlan_objmgr_vdev *vdev;
 	int ret_val = 0;
-	QDF_STATUS status;
 
 	if (!(dev_mode == QDF_SAP_MODE || dev_mode == QDF_P2P_GO_MODE)) {
 		hdd_err("Invalid interface type:%d", dev_mode);
 		return -EINVAL;
 	}
-	status = wlan_objmgr_vdev_try_get_ref(adapter->vdev, WLAN_OSIF_ID);
-	if (status != QDF_STATUS_SUCCESS) {
-		hdd_err("Access hdd_vdev failed: %d", status);
+	vdev = hdd_objmgr_get_vdev(adapter);
+	if (!vdev)
 		return -EINVAL;
-	}
 	if (restrict_offchan == 1) {
 		enum policy_mgr_con_mode pmode =
 		policy_mgr_convert_device_mode_to_qdf_type(dev_mode);
 		int chan;
 
-		u32 vdev_id = wlan_vdev_get_id(adapter->vdev);
+		u32 vdev_id = wlan_vdev_get_id(vdev);
 
-		wlan_vdev_obj_lock(adapter->vdev);
-		wlan_vdev_mlme_cap_set(adapter->vdev,
-				       WLAN_VDEV_C_RESTRICT_OFFCHAN);
-		wlan_vdev_obj_unlock(adapter->vdev);
+		wlan_vdev_obj_lock(vdev);
+		wlan_vdev_mlme_cap_set(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
+		wlan_vdev_obj_unlock(vdev);
 		chan = policy_mgr_get_channel(hdd_ctx->psoc, pmode,
 					      &vdev_id);
 		if (!chan ||
@@ -5315,10 +5319,9 @@ static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
 		}
 		hdd_info("vdev %d mode %d dnbs enabled", vdev_id, dev_mode);
 	} else if (restrict_offchan == 0) {
-		wlan_vdev_obj_lock(adapter->vdev);
-		wlan_vdev_mlme_cap_clear(adapter->vdev,
-					 WLAN_VDEV_C_RESTRICT_OFFCHAN);
-		wlan_vdev_obj_unlock(adapter->vdev);
+		wlan_vdev_obj_lock(vdev);
+		wlan_vdev_mlme_cap_clear(vdev, WLAN_VDEV_C_RESTRICT_OFFCHAN);
+		wlan_vdev_obj_unlock(vdev);
 		if (wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0)) {
 			hdd_err("unable to clear avoid_freq");
 			ret_val = -EINVAL;
@@ -5328,7 +5331,7 @@ static int wlan_hdd_handle_restrict_offchan_config(struct hdd_adapter *adapter,
 		ret_val = -EINVAL;
 		hdd_err("Invalid RESTRICT_OFFCHAN setting");
 	}
-	wlan_objmgr_vdev_release_ref(adapter->vdev, WLAN_OSIF_ID);
+	hdd_objmgr_put_vdev(adapter);
 	return ret_val;
 }
 
@@ -5560,6 +5563,7 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
 	uint16_t latency_level;
 	mac_handle_t mac_handle;
 	bool b_value;
+	struct wlan_objmgr_vdev *vdev;
 
 	hdd_enter_dev(dev);
 	qdf_mem_zero(&request, sizeof(request));
@@ -5600,8 +5604,12 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
 		modulated_dtim = nla_get_u32(
 			tb[QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM]);
 
-		status = ucfg_pmo_config_modulated_dtim(adapter->vdev,
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev)
+			return -EINVAL;
+		status = ucfg_pmo_config_modulated_dtim(vdev,
 							modulated_dtim);
+		hdd_objmgr_put_vdev(adapter);
 		if (QDF_STATUS_SUCCESS != status)
 			ret_val = -EPERM;
 	}
@@ -5616,8 +5624,12 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
 			return -EINVAL;
 		}
 
-		status = ucfg_pmo_config_listen_interval(adapter->vdev,
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev)
+			return -EINVAL;
+		status = ucfg_pmo_config_listen_interval(vdev,
 							 override_li);
+		hdd_objmgr_put_vdev(adapter);
 		if (status != QDF_STATUS_SUCCESS)
 			ret_val = -EPERM;
 	}
@@ -5652,7 +5664,6 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy,
 			ret_val = -EPERM;
 	}
 
-
 	if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]) {
 		guard_time = nla_get_u32(
 			tb[QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME]);
@@ -13212,8 +13223,14 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
 
 	/* TDLS ignores p2p-device mode for concurrency considerations */
 	if (new_mode != QDF_P2P_DEVICE_MODE) {
+		struct wlan_objmgr_vdev *vdev;
+
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev)
+			return -EINVAL;
 		hdd_debug("Disable tdls; new interface is coming up");
-		hdd_notify_teardown_tdls_links(adapter->vdev);
+		hdd_notify_teardown_tdls_links(vdev);
+		hdd_objmgr_put_vdev(adapter);
 	}
 
 	if (hdd_is_client_mode(adapter->device_mode)) {
@@ -13431,8 +13448,13 @@ static int __wlan_hdd_change_station(struct wiphy *wiphy,
 		   (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
 		if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
 #if defined(FEATURE_WLAN_TDLS)
-			ret = wlan_cfg80211_tdls_update_peer(hdd_ctx->pdev,
-							     dev, mac, params);
+			struct wlan_objmgr_vdev *vdev;
+
+			vdev = hdd_objmgr_get_vdev(adapter);
+			if (!vdev)
+				return -EINVAL;
+			ret = wlan_cfg80211_tdls_update_peer(vdev, mac, params);
+			hdd_objmgr_put_vdev(adapter);
 #endif
 		}
 	}
@@ -14855,6 +14877,7 @@ static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter,
 	mac_handle_t mac_handle;
 	uint8_t wmm_mode = 0;
 	uint8_t value = 0;
+	struct wlan_objmgr_vdev *vdev;
 
 	hdd_enter();
 
@@ -14880,7 +14903,13 @@ static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter,
 	/* Disable roaming on all other adapters before connect start */
 	wlan_hdd_disable_roaming(adapter);
 
-	hdd_notify_teardown_tdls_links(adapter->vdev);
+	vdev = hdd_objmgr_get_vdev(adapter);
+	if (!vdev) {
+		status = -EINVAL;
+		goto ret_status;
+	}
+	hdd_notify_teardown_tdls_links(vdev);
+	hdd_objmgr_put_vdev(adapter);
 
 	qdf_mem_zero(&hdd_sta_ctx->conn_info.conn_flag,
 		     sizeof(hdd_sta_ctx->conn_info.conn_flag));
@@ -15024,7 +15053,13 @@ static int wlan_hdd_cfg80211_connect_start(struct hdd_adapter *adapter,
 			}
 		}
 #endif
-		ucfg_pmo_flush_gtk_offload_req(adapter->vdev);
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev) {
+			status = -EINVAL;
+			goto conn_failure;
+		}
+		ucfg_pmo_flush_gtk_offload_req(vdev);
+		hdd_objmgr_put_vdev(adapter);
 		roam_profile->csrPersona = adapter->device_mode;
 
 		if (operatingChannel) {
@@ -16341,6 +16376,7 @@ static int wlan_hdd_cfg80211_set_privacy(struct hdd_adapter *adapter,
 	int status = 0;
 	struct hdd_station_ctx *sta_ctx;
 	struct csr_roam_profile *roam_profile;
+	struct wlan_objmgr_vdev *vdev;
 
 	hdd_enter();
 
@@ -16351,7 +16387,11 @@ static int wlan_hdd_cfg80211_set_privacy(struct hdd_adapter *adapter,
 	roam_profile = hdd_roam_profile(adapter);
 
 	/* populate auth,akm and cipher params for crypto */
-	hdd_populate_crypto_params(adapter->vdev, req);
+	vdev = hdd_objmgr_get_vdev(adapter);
+	if (!vdev)
+		return -EINVAL;
+	hdd_populate_crypto_params(vdev, req);
+	hdd_objmgr_put_vdev(adapter);
 
 	/*set authentication type */
 	status = wlan_hdd_cfg80211_set_auth_type(adapter, req->auth_type);
@@ -17122,6 +17162,7 @@ static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
 	struct hdd_station_ctx *sta_ctx =
 		WLAN_HDD_GET_STATION_CTX_PTR(adapter);
 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+	struct wlan_objmgr_vdev *vdev;
 
 	hdd_enter();
 
@@ -17194,7 +17235,11 @@ static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
 			reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED;
 			break;
 		}
-		if (ucfg_scan_get_vdev_status(adapter->vdev) !=
+
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev)
+			return -EINVAL;
+		if (ucfg_scan_get_vdev_status(vdev) !=
 				SCAN_NOT_IN_PROGRESS) {
 			hdd_debug("Disconnect is in progress, Aborting Scan");
 			wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
@@ -17204,7 +17249,8 @@ static int __wlan_hdd_cfg80211_disconnect(struct wiphy *wiphy,
 		wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
 		/* First clean up the tdls peers if any */
 		hdd_notify_sta_disconnect(adapter->session_id,
-			  false, true, adapter->vdev);
+					  false, true, vdev);
+		hdd_objmgr_put_vdev(adapter);
 
 		hdd_info("Disconnect from userspace; reason:%d (%s)",
 			 reason, hdd_ieee80211_reason_code_to_str(reason));
@@ -18117,9 +18163,16 @@ static int __wlan_hdd_cfg80211_add_station(struct wiphy *wiphy,
 		MAC_ADDR_ARRAY(mac));
 
 	if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
-		if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
-			status = wlan_cfg80211_tdls_add_peer(hdd_ctx->pdev,
-							     dev, mac);
+		if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
+			struct wlan_objmgr_vdev *vdev;
+
+			vdev = hdd_objmgr_get_vdev(adapter);
+			if (vdev) {
+				status = wlan_cfg80211_tdls_add_peer(vdev,
+								     mac);
+				hdd_objmgr_put_vdev(adapter);
+			}
+		}
 	}
 #endif
 	hdd_exit();
@@ -18678,6 +18731,7 @@ int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
 	struct pmo_gtk_req *gtk_req = NULL;
 	struct hdd_context *hdd_ctx =  WLAN_HDD_GET_CTX(adapter);
 	uint8_t *buf;
+	struct wlan_objmgr_vdev *vdev;
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
 
 	hdd_enter();
@@ -18718,7 +18772,13 @@ int __wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy,
 	wlan_hdd_copy_gtk_kek(gtk_req, data);
 	qdf_mem_copy(gtk_req->kck, data->kck, NL80211_KCK_LEN);
 	gtk_req->is_fils_connection = hdd_is_fils_connection(adapter);
-	status = ucfg_pmo_cache_gtk_offload_req(adapter->vdev, gtk_req);
+	vdev = hdd_objmgr_get_vdev(adapter);
+	if (!vdev) {
+		result = -EINVAL;
+		goto out;
+	}
+	status = ucfg_pmo_cache_gtk_offload_req(vdev, gtk_req);
+	hdd_objmgr_put_vdev(adapter);
 	if (status != QDF_STATUS_SUCCESS) {
 		hdd_err("Failed to cache GTK Offload");
 		result = qdf_status_to_os_return(status);

+ 74 - 22
core/hdd/src/wlan_hdd_main.c

@@ -748,6 +748,7 @@ static int __hdd_netdev_notifier_call(struct notifier_block *nb,
 #endif
 	struct hdd_adapter *adapter;
 	struct hdd_context *hdd_ctx;
+	struct wlan_objmgr_vdev *vdev;
 
 	hdd_enter_dev(dev);
 
@@ -811,12 +812,16 @@ static int __hdd_netdev_notifier_call(struct notifier_block *nb,
 		break;
 
 	case NETDEV_GOING_DOWN:
-		if (ucfg_scan_get_vdev_status(adapter->vdev) !=
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev)
+			break;
+		if (ucfg_scan_get_vdev_status(vdev) !=
 				SCAN_NOT_IN_PROGRESS) {
 			wlan_abort_scan(hdd_ctx->pdev, INVAL_PDEV_ID,
 					adapter->session_id, INVALID_SCAN_ID,
 					true);
 		}
+		hdd_objmgr_put_vdev(adapter);
 		cds_flush_work(&adapter->scan_block_work);
 		/* Need to clean up blocked scan request */
 		wlan_hdd_cfg80211_scan_block_cb(&adapter->scan_block_work);
@@ -3914,20 +3919,31 @@ QDF_STATUS hdd_sme_close_session_callback(uint8_t session_id)
 
 int hdd_vdev_ready(struct hdd_adapter *adapter)
 {
+	struct wlan_objmgr_vdev *vdev;
 	QDF_STATUS status;
 
-	status = pmo_vdev_ready(adapter->vdev);
-	if (QDF_IS_STATUS_ERROR(status))
+	vdev = hdd_objmgr_get_vdev(adapter);
+	if (!vdev)
+		return -EINVAL;
+
+	status = pmo_vdev_ready(vdev);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_objmgr_put_vdev(adapter);
 		return qdf_status_to_os_return(status);
+	}
 
-	status = ucfg_reg_11d_vdev_created_update(adapter->vdev);
-	if (QDF_IS_STATUS_ERROR(status))
+	status = ucfg_reg_11d_vdev_created_update(vdev);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_objmgr_put_vdev(adapter);
 		return qdf_status_to_os_return(status);
+	}
 
 	if (wma_capability_enhanced_mcast_filter())
-		status = ucfg_pmo_enhanced_mc_filter_enable(adapter->vdev);
+		status = ucfg_pmo_enhanced_mc_filter_enable(vdev);
 	else
-		status = ucfg_pmo_enhanced_mc_filter_disable(adapter->vdev);
+		status = ucfg_pmo_enhanced_mc_filter_disable(vdev);
+
+	hdd_objmgr_put_vdev(adapter);
 
 	return qdf_status_to_os_return(status);
 }
@@ -3938,6 +3954,7 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter)
 	int errno;
 	struct hdd_context *hdd_ctx;
 	uint8_t vdev_id;
+	struct wlan_objmgr_vdev *vdev;
 
 	vdev_id = adapter->session_id;
 	hdd_info("destroying vdev %d", vdev_id);
@@ -3948,8 +3965,12 @@ int hdd_vdev_destroy(struct hdd_adapter *adapter)
 		return -EINVAL;
 	}
 
-	status = ucfg_reg_11d_vdev_delete_update(adapter->vdev);
-	ucfg_scan_set_vdev_del_in_progress(adapter->vdev);
+	vdev = hdd_objmgr_get_vdev(adapter);
+	if (!vdev)
+		return -EINVAL;
+	status = ucfg_reg_11d_vdev_delete_update(vdev);
+	ucfg_scan_set_vdev_del_in_progress(vdev);
+	hdd_objmgr_put_vdev(adapter);
 
 	/* close sme session (destroy vdev in firmware via legacy API) */
 	qdf_event_reset(&adapter->qdf_session_close_event);
@@ -4029,6 +4050,7 @@ int hdd_vdev_create(struct hdd_adapter *adapter,
 	bool bval;
 	struct hdd_context *hdd_ctx;
 	struct sme_session_params sme_session_params = {0};
+	struct wlan_objmgr_vdev *vdev;
 
 	hdd_info("creating new vdev");
 
@@ -4115,9 +4137,13 @@ int hdd_vdev_create(struct hdd_adapter *adapter,
 	}
 
 	if (adapter->device_mode == QDF_STA_MODE ||
-	    adapter->device_mode == QDF_P2P_CLIENT_MODE)
-		wlan_vdev_set_max_peer_count(adapter->vdev,
-					     HDD_MAX_VDEV_PEER_COUNT);
+	    adapter->device_mode == QDF_P2P_CLIENT_MODE) {
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev)
+			goto hdd_vdev_destroy_procedure;
+		wlan_vdev_set_max_peer_count(vdev, HDD_MAX_VDEV_PEER_COUNT);
+		hdd_objmgr_put_vdev(adapter);
+	}
 
 	hdd_info("vdev %d created successfully", adapter->session_id);
 
@@ -4298,7 +4324,8 @@ void hdd_deinit_adapter(struct hdd_context *hdd_ctx,
 	hdd_exit();
 }
 
-static void hdd_cleanup_adapter(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter,
+static void hdd_cleanup_adapter(struct hdd_context *hdd_ctx,
+				struct hdd_adapter *adapter,
 				bool rtnl_held)
 {
 	struct net_device *dev = NULL;
@@ -4313,6 +4340,7 @@ static void hdd_cleanup_adapter(struct hdd_context *hdd_ctx, struct hdd_adapter
 	hdd_nud_deinit_tracking(adapter);
 	qdf_mutex_destroy(&adapter->disconnection_status_lock);
 	hdd_apf_context_destroy(adapter);
+	qdf_spinlock_destroy(&adapter->vdev_lock);
 
 	wlan_hdd_debugfs_csr_deinit(adapter);
 
@@ -5048,6 +5076,8 @@ struct hdd_adapter *hdd_open_adapter(struct hdd_context *hdd_ctx, uint8_t sessio
 		return NULL;
 	}
 
+	qdf_spinlock_create(&adapter->vdev_lock);
+
 	hdd_init_completion(adapter);
 	INIT_WORK(&adapter->scan_block_work, wlan_hdd_cfg80211_scan_block_cb);
 	qdf_list_create(&adapter->blocked_scan_request_q, WLAN_MAX_SCAN_COUNT);
@@ -5215,6 +5245,7 @@ QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx,
 	unsigned long rc;
 	tsap_config_t *sap_config;
 	mac_handle_t mac_handle;
+	struct wlan_objmgr_vdev *vdev;
 
 	hdd_enter();
 
@@ -5310,9 +5341,15 @@ QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx,
 #endif
 #endif
 
-		if (adapter->device_mode == QDF_STA_MODE)
-			wlan_cfg80211_sched_scan_stop(hdd_ctx->pdev,
-						      adapter->dev);
+		if (adapter->device_mode == QDF_STA_MODE) {
+			struct wlan_objmgr_vdev *vdev;
+
+			vdev = hdd_objmgr_get_vdev(adapter);
+			if (vdev) {
+				wlan_cfg80211_sched_scan_stop(vdev);
+				hdd_objmgr_put_vdev(adapter);
+			}
+		}
 
 		if (wlan_hdd_try_disconnect(adapter)) {
 			hdd_err("Can't disconnect adapter");
@@ -5414,8 +5451,12 @@ QDF_STATUS hdd_stop_adapter_ext(struct hdd_context *hdd_ctx,
 		/*
 		 * If Do_Not_Break_Stream was enabled clear avoid channel list.
 		 */
-		if (policy_mgr_is_dnsc_set(adapter->vdev))
-			wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0);
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (vdev) {
+			if (policy_mgr_is_dnsc_set(vdev))
+				wlan_hdd_send_avoid_freq_for_dnbs(hdd_ctx, 0);
+			hdd_objmgr_put_vdev(adapter);
+		}
 
 #ifdef WLAN_OPEN_SOURCE
 		cancel_work_sync(&adapter->ipv4_notifier_work);
@@ -5497,9 +5538,15 @@ static void hdd_reset_scan_operation(struct hdd_context *hdd_ctx,
 	case QDF_NDI_MODE:
 		wlan_hdd_scan_abort(adapter);
 		wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
-		if (adapter->device_mode == QDF_STA_MODE)
-			wlan_cfg80211_sched_scan_stop(hdd_ctx->pdev,
-						      adapter->dev);
+		if (adapter->device_mode == QDF_STA_MODE) {
+			struct wlan_objmgr_vdev *vdev;
+
+			vdev = hdd_objmgr_get_vdev(adapter);
+			if (vdev) {
+				wlan_cfg80211_sched_scan_stop(vdev);
+				hdd_objmgr_put_vdev(adapter);
+			}
+		}
 		break;
 	case QDF_P2P_GO_MODE:
 		wlan_hdd_cleanup_remain_on_channel_ctx(adapter);
@@ -5520,6 +5567,7 @@ QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx)
 	struct qdf_mac_addr peerMacAddr;
 	int sta_id;
 	bool value;
+	struct wlan_objmgr_vdev *vdev;
 
 	hdd_enter();
 
@@ -5533,7 +5581,11 @@ QDF_STATUS hdd_reset_all_adapters(struct hdd_context *hdd_ctx)
 		if ((adapter->device_mode == QDF_STA_MODE) ||
 		    (adapter->device_mode == QDF_P2P_CLIENT_MODE)) {
 			/* Stop tdls timers */
-			hdd_notify_tdls_reset_adapter(adapter->vdev);
+			vdev = hdd_objmgr_get_vdev(adapter);
+			if (vdev) {
+				hdd_notify_tdls_reset_adapter(vdev);
+				hdd_objmgr_put_vdev(adapter);
+			}
 			adapter->session.station.hdd_reassoc_scenario = false;
 		}
 		ucfg_mlme_get_sap_internal_restart(hdd_ctx->psoc, &value);

+ 45 - 1
core/hdd/src/wlan_hdd_object_manager.c

@@ -281,8 +281,10 @@ int hdd_objmgr_create_and_store_vdev(struct wlan_objmgr_pdev *pdev,
 		goto vdev_destroy;
 	}
 
+	qdf_spin_lock_bh(&adapter->vdev_lock);
 	adapter->vdev = vdev;
 	adapter->session_id = wlan_vdev_get_id(vdev);
+	qdf_spin_unlock_bh(&adapter->vdev_lock);
 
 	return 0;
 
@@ -298,11 +300,14 @@ osif_priv_free:
 int hdd_objmgr_release_and_destroy_vdev(struct hdd_adapter *adapter)
 {
 	QDF_STATUS status;
-	struct wlan_objmgr_vdev *vdev = adapter->vdev;
+	struct wlan_objmgr_vdev *vdev;
 	struct vdev_osif_priv *osif_priv;
 
+	qdf_spin_lock_bh(&adapter->vdev_lock);
+	vdev = adapter->vdev;
 	adapter->vdev = NULL;
 	adapter->session_id = HDD_SESSION_ID_INVALID;
+	qdf_spin_unlock_bh(&adapter->vdev_lock);
 
 	QDF_BUG(vdev);
 	if (!vdev)
@@ -320,6 +325,45 @@ int hdd_objmgr_release_and_destroy_vdev(struct hdd_adapter *adapter)
 	return qdf_status_to_os_return(status);
 }
 
+struct wlan_objmgr_vdev *__hdd_objmgr_get_vdev(struct hdd_adapter *adapter,
+					       const char *func)
+{
+	struct wlan_objmgr_vdev *vdev = NULL;
+	QDF_STATUS status;
+
+	if (!adapter) {
+		hdd_err("Adapter is NULL (via %s)", func);
+		return NULL;
+	}
+
+	qdf_spin_lock_bh(&adapter->vdev_lock);
+	vdev = adapter->vdev;
+	if (vdev) {
+		status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_OSIF_ID);
+		if (QDF_IS_STATUS_ERROR(status))
+			vdev = NULL;
+	}
+	qdf_spin_unlock_bh(&adapter->vdev_lock);
+
+	if (!vdev)
+		hdd_err("VDEV is NULL (via %s)", func);
+
+	return vdev;
+}
+
+void __hdd_objmgr_put_vdev(struct hdd_adapter *adapter, const char *func)
+{
+	if (!adapter) {
+		hdd_err("Adapter is NULL (via %s)", func);
+		return;
+	}
+
+	qdf_spin_lock_bh(&adapter->vdev_lock);
+	if (adapter->vdev)
+		wlan_objmgr_vdev_release_ref(adapter->vdev, WLAN_OSIF_ID);
+	qdf_spin_unlock_bh(&adapter->vdev_lock);
+}
+
 int hdd_objmgr_set_peer_mlme_auth_state(struct wlan_objmgr_vdev *vdev,
 					bool is_authenticated)
 {

+ 25 - 0
core/hdd/src/wlan_hdd_object_manager.h

@@ -132,6 +132,31 @@ int hdd_objmgr_create_and_store_vdev(struct wlan_objmgr_pdev *pdev,
  */
 int hdd_objmgr_release_and_destroy_vdev(struct hdd_adapter *adapter);
 
+/**
+ * hdd_objmgr_get_vdev() - Get reference of vdev from adapter
+ * @adapter: hdd adapter
+ *
+ * This API gets vdev object reference from hdd adapter
+ *
+ * Return: pointer to vdev object for success, NULL for failure
+ */
+#define hdd_objmgr_get_vdev(adapter) \
+	__hdd_objmgr_get_vdev(adapter, __func__)
+struct wlan_objmgr_vdev *__hdd_objmgr_get_vdev(struct hdd_adapter *adapter,
+					       const char *func);
+
+/**
+ * hdd_objmgr_put_vdev() - Release reference of vdev from adapter
+ * @adapter: hdd adapter
+ *
+ * This API releases vdev object reference from hdd adapter
+ *
+ * Return: void
+ */
+#define hdd_objmgr_put_vdev(adapter) \
+	__hdd_objmgr_put_vdev(adapter, __func__)
+void __hdd_objmgr_put_vdev(struct hdd_adapter *adapter, const char *func);
+
 /**
  * hdd_objmgr_set_peer_mlme_auth_state() - set the peer mlme auth state
  * @vdev: vdev pointer

+ 29 - 4
core/hdd/src/wlan_hdd_scan.c

@@ -46,6 +46,7 @@
 #include <qca_vendor.h>
 #include <wlan_cfg80211_scan.h>
 #include "wlan_utility.h"
+#include "wlan_hdd_object_manager.h"
 
 #define MAX_RATES                       12
 #define HDD_WAKE_LOCK_SCAN_DURATION (5 * 1000) /* in msec */
@@ -465,6 +466,7 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
 	static uint32_t scan_ebusy_cnt;
 	struct scan_params params = {0};
 	bool self_recovery;
+	struct wlan_objmgr_vdev *vdev;
 	QDF_STATUS qdf_status;
 
 	hdd_enter();
@@ -668,12 +670,20 @@ static int __wlan_hdd_cfg80211_scan(struct wiphy *wiphy,
 			scan_info->scan_add_ie.length;
 	}
 
+	vdev = hdd_objmgr_get_vdev(adapter);
+	if (!vdev) {
+		status = -EINVAL;
+		goto error;
+	}
+
 	if ((request->n_ssids == 1) && (request->ssids != NULL) &&
 	    (request->ssids[0].ssid_len > 7) &&
 	     !qdf_mem_cmp(&request->ssids[0], "DIRECT-", 7))
-		ucfg_p2p_status_scan(adapter->vdev);
+		ucfg_p2p_status_scan(vdev);
 
-	status = wlan_cfg80211_scan(hdd_ctx->pdev, request, &params);
+	status = wlan_cfg80211_scan(vdev, request, &params);
+	hdd_objmgr_put_vdev(adapter);
+error:
 	if (params.default_ie.ptr)
 		qdf_mem_free(params.default_ie.ptr);
 	hdd_exit();
@@ -1269,6 +1279,7 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
 {
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	struct hdd_context *hdd_ctx;
+	struct wlan_objmgr_vdev *vdev;
 	int ret;
 
 	hdd_enter();
@@ -1304,8 +1315,14 @@ static int __wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy,
 		return -EBUSY;
 	}
 
-	return wlan_cfg80211_sched_scan_start(hdd_ctx->pdev, dev, request,
+	vdev = hdd_objmgr_get_vdev(adapter);
+	if (!vdev)
+		return -EINVAL;
+	ret = wlan_cfg80211_sched_scan_start(vdev, request,
 				      hdd_ctx->config->scan_backoff_multiplier);
+	hdd_objmgr_put_vdev(adapter);
+
+	return ret;
 }
 
 /**
@@ -1334,6 +1351,8 @@ int wlan_hdd_sched_scan_stop(struct net_device *dev)
 {
 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
 	struct hdd_context *hdd_ctx;
+	struct wlan_objmgr_vdev *vdev;
+	int ret;
 
 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
 		hdd_err("Command not allowed in FTM mode");
@@ -1353,7 +1372,13 @@ int wlan_hdd_sched_scan_stop(struct net_device *dev)
 		return -EINVAL;
 	}
 
-	return wlan_cfg80211_sched_scan_stop(hdd_ctx->pdev, dev);
+	vdev = hdd_objmgr_get_vdev(adapter);
+	if (!vdev)
+		return -EINVAL;
+	ret = wlan_cfg80211_sched_scan_stop(vdev);
+	hdd_objmgr_put_vdev(adapter);
+
+	return ret;
 }
 
 /**

+ 78 - 22
core/hdd/src/wlan_hdd_tdls.c

@@ -41,6 +41,7 @@
 #include "wlan_policy_mgr_api.h"
 #include <qca_vendor.h>
 #include "wlan_tdls_cfg_api.h"
+#include "wlan_hdd_object_manager.h"
 
 /**
  * enum qca_wlan_vendor_tdls_trigger_mode_hdd_map: Maps the user space TDLS
@@ -75,6 +76,8 @@ int wlan_hdd_tdls_get_all_peers(struct hdd_adapter *adapter,
 {
 	int len;
 	struct hdd_context *hdd_ctx;
+	struct wlan_objmgr_vdev *vdev;
+	int ret;
 
 	hdd_enter();
 
@@ -92,8 +95,15 @@ int wlan_hdd_tdls_get_all_peers(struct hdd_adapter *adapter,
 		return len;
 	}
 
-	return wlan_cfg80211_tdls_get_all_peers(adapter->vdev,
-						buf, buflen);
+	vdev = hdd_objmgr_get_vdev(adapter);
+	if (!vdev) {
+		len = scnprintf(buf, buflen, "\nVDEV is NULL\n");
+		return len;
+	}
+	ret = wlan_cfg80211_tdls_get_all_peers(vdev, buf, buflen);
+	hdd_objmgr_put_vdev(adapter);
+
+	return ret;
 }
 
 static const struct nla_policy
@@ -232,8 +242,14 @@ __wlan_hdd_cfg80211_configure_tdls_mode(struct wiphy *wiphy,
 	hdd_debug("TDLS trigger mode %d", trigger_mode);
 
 	if (hdd_ctx->tdls_umac_comp_active) {
-		ret = wlan_cfg80211_tdls_configure_mode(adapter->vdev,
+		struct wlan_objmgr_vdev *vdev;
+
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev)
+			return -EINVAL;
+		ret = wlan_cfg80211_tdls_configure_mode(vdev,
 							trigger_mode);
+		hdd_objmgr_put_vdev(adapter);
 		return ret;
 	}
 
@@ -473,12 +489,20 @@ static int __wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy,
 		return -ENOTSUPP;
 	}
 
-	if (hdd_ctx->tdls_umac_comp_active)
-		return wlan_cfg80211_tdls_mgmt(hdd_ctx->pdev, dev,
-					       peer,
-					       action_code, dialog_token,
-					       status_code, peer_capability,
-					       buf, len);
+	if (hdd_ctx->tdls_umac_comp_active) {
+		struct wlan_objmgr_vdev *vdev;
+		int ret;
+
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev)
+			return -EINVAL;
+		ret = wlan_cfg80211_tdls_mgmt(vdev, peer,
+					      action_code, dialog_token,
+					      status_code, peer_capability,
+					      buf, len);
+		hdd_objmgr_put_vdev(adapter);
+		return ret;
+	}
 
 	return -EINVAL;
 }
@@ -662,8 +686,13 @@ static int __wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy,
 		return status;
 
 	if (hdd_ctx->tdls_umac_comp_active) {
-		status = wlan_cfg80211_tdls_oper(hdd_ctx->pdev,
-						 dev, peer, oper);
+		struct wlan_objmgr_vdev *vdev;
+
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev)
+			return -EINVAL;
+		status = wlan_cfg80211_tdls_oper(vdev, peer, oper);
+		hdd_objmgr_put_vdev(adapter);
 		hdd_exit();
 		return status;
 	}
@@ -746,11 +775,17 @@ int hdd_set_tdls_offchannel(struct hdd_context *hdd_ctx,
 			    struct hdd_adapter *adapter,
 			    int offchannel)
 {
+	struct wlan_objmgr_vdev *vdev;
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
 
-	if (hdd_ctx->tdls_umac_comp_active)
-		status = ucfg_set_tdls_offchannel(adapter->vdev,
-						  offchannel);
+	if (hdd_ctx->tdls_umac_comp_active) {
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (vdev) {
+			status = ucfg_set_tdls_offchannel(vdev,
+							  offchannel);
+			hdd_objmgr_put_vdev(adapter);
+		}
+	}
 	return qdf_status_to_os_return(status);
 }
 
@@ -758,11 +793,17 @@ int hdd_set_tdls_secoffchanneloffset(struct hdd_context *hdd_ctx,
 				     struct hdd_adapter *adapter,
 				     int offchanoffset)
 {
+	struct wlan_objmgr_vdev *vdev;
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
 
-	if (hdd_ctx->tdls_umac_comp_active)
-		status = ucfg_set_tdls_secoffchanneloffset(adapter->vdev,
-							   offchanoffset);
+	if (hdd_ctx->tdls_umac_comp_active) {
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (vdev) {
+			status = ucfg_set_tdls_secoffchanneloffset(vdev,
+								 offchanoffset);
+			hdd_objmgr_put_vdev(adapter);
+		}
+	}
 	return qdf_status_to_os_return(status);
 }
 
@@ -770,11 +811,17 @@ int hdd_set_tdls_offchannelmode(struct hdd_context *hdd_ctx,
 				struct hdd_adapter *adapter,
 				int offchanmode)
 {
+	struct wlan_objmgr_vdev *vdev;
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
 
-	if (hdd_ctx->tdls_umac_comp_active)
-		status = ucfg_set_tdls_offchan_mode(adapter->vdev,
-						    offchanmode);
+	if (hdd_ctx->tdls_umac_comp_active) {
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (vdev) {
+			status = ucfg_set_tdls_offchan_mode(vdev,
+							    offchanmode);
+			hdd_objmgr_put_vdev(adapter);
+		}
+	}
 	return qdf_status_to_os_return(status);
 }
 
@@ -818,8 +865,17 @@ int wlan_hdd_tdls_antenna_switch(struct hdd_context *hdd_ctx,
 				 struct hdd_adapter *adapter,
 				 uint32_t mode)
 {
-	if (hdd_ctx->tdls_umac_comp_active)
-		return wlan_tdls_antenna_switch(adapter->vdev, mode);
+	if (hdd_ctx->tdls_umac_comp_active) {
+		struct wlan_objmgr_vdev *vdev;
+		int ret;
+
+		vdev = hdd_objmgr_get_vdev(adapter);
+		if (!vdev)
+			return -EINVAL;
+		ret = wlan_tdls_antenna_switch(vdev, mode);
+		hdd_objmgr_put_vdev(adapter);
+		return ret;
+	}
 
 	return 0;
 }