浏览代码

qcacld-3.0: Acquire pdev/psoc refs from HDD

Currently, HDD acquires an additional reference for vdevs it creates. Do
the same for pdevs and psocs, so they are not destroyed out from under
HDD.

Change-Id: Ifa89f3853f76fe98880f082a6a138068bf92b6ec
CRs-Fixed: 2179683
Dustin Brown 7 年之前
父节点
当前提交
b277dd659e
共有 3 个文件被更改,包括 68 次插入75 次删除
  1. 2 8
      core/hdd/src/wlan_hdd_main.c
  2. 65 40
      core/hdd/src/wlan_hdd_object_manager.c
  3. 1 27
      core/hdd/src/wlan_hdd_object_manager.h

+ 2 - 8
core/hdd/src/wlan_hdd_main.c

@@ -3656,18 +3656,12 @@ release_vdev:
 		return errno;
 
 	/* do vdev logical destroy via objmgr */
-	errno = hdd_objmgr_destroy_vdev(adapter);
+	errno = hdd_objmgr_release_and_destroy_vdev(adapter);
 	if (errno) {
-		hdd_err("failed to destroy objmgr vdev: %d", errno);
+		hdd_err("failed to destroy objmgr vdev; errno:%d", errno);
 		return errno;
 	}
 
-	/* now that sme session is closed, allow physical vdev destroy */
-	errno = hdd_objmgr_release_vdev(adapter);
-	if (errno) {
-		hdd_err("failed to release objmgr vdev: %d", errno);
-		return errno;
-	}
 	hdd_info("vdev %d destroyed successfully", vdev_id);
 
 	return 0;

+ 65 - 40
core/hdd/src/wlan_hdd_object_manager.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -47,9 +47,9 @@ static void hdd_init_pdev_os_priv(struct hdd_context *hdd_ctx,
 	wlan_cfg80211_scan_priv_init(hdd_ctx->hdd_pdev);
 }
 
-static void hdd_deinit_pdev_os_priv(struct hdd_context *hdd_ctx)
+static void hdd_deinit_pdev_os_priv(struct wlan_objmgr_pdev *pdev)
 {
-	wlan_cfg80211_scan_priv_deinit(hdd_ctx->hdd_pdev);
+	wlan_cfg80211_scan_priv_deinit(pdev);
 }
 
 static void hdd_init_vdev_os_priv(struct hdd_adapter *adapter,
@@ -77,33 +77,53 @@ static void hdd_init_psoc_qdf_ctx(struct wlan_objmgr_psoc *psoc)
 int hdd_objmgr_create_and_store_psoc(struct hdd_context *hdd_ctx,
 				     uint8_t psoc_id)
 {
+	QDF_STATUS status;
 	struct wlan_objmgr_psoc *psoc;
 
 	psoc = wlan_objmgr_psoc_obj_create(psoc_id, WLAN_DEV_OL);
 	if (!psoc)
 		return -ENOMEM;
 
+	status = wlan_objmgr_psoc_try_get_ref(psoc, WLAN_HDD_ID_OBJ_MGR);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Failed to acquire psoc ref; status:%d", status);
+		QDF_BUG(false);
+		goto psoc_destroy;
+	}
+
 	hdd_init_psoc_qdf_ctx(psoc);
 	hdd_ctx->hdd_psoc = psoc;
 
 	return 0;
+
+psoc_destroy:
+	wlan_objmgr_psoc_obj_delete(psoc);
+
+	return qdf_status_to_os_return(status);
 }
 
 int hdd_objmgr_release_and_destroy_psoc(struct hdd_context *hdd_ctx)
 {
+	QDF_STATUS status;
 	struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
 
 	hdd_ctx->hdd_psoc = NULL;
+
+	QDF_BUG(psoc);
 	if (!psoc)
 		return -EINVAL;
 
 	wlan_objmgr_print_ref_all_objects_per_psoc(psoc);
 
-	return qdf_status_to_os_return(wlan_objmgr_psoc_obj_delete(psoc));
+	status = wlan_objmgr_psoc_obj_delete(psoc);
+	wlan_objmgr_psoc_release_ref(psoc, WLAN_HDD_ID_OBJ_MGR);
+
+	return qdf_status_to_os_return(status);
 }
 
 int hdd_objmgr_create_and_store_pdev(struct hdd_context *hdd_ctx)
 {
+	QDF_STATUS status;
 	struct wlan_objmgr_psoc *psoc = hdd_ctx->hdd_psoc;
 	struct wlan_objmgr_pdev *pdev;
 	struct pdev_osif_priv *priv;
@@ -133,30 +153,51 @@ int hdd_objmgr_create_and_store_pdev(struct hdd_context *hdd_ctx)
 		return -ENOMEM;
 	}
 
+	status = wlan_objmgr_pdev_try_get_ref(pdev, WLAN_HDD_ID_OBJ_MGR);
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Failed to acquire pdev ref; status:%d", status);
+		QDF_BUG(false);
+		goto pdev_destroy;
+	}
+
 	hdd_ctx->hdd_pdev = pdev;
 	sme_store_pdev(hdd_ctx->hHal, hdd_ctx->hdd_pdev);
 	hdd_init_pdev_os_priv(hdd_ctx, priv);
 	wlan_pdev_obj_lock(pdev);
 	wlan_pdev_set_tgt_if_handle(pdev, psoc->tgt_if_handle);
 	wlan_pdev_obj_unlock(pdev);
+
 	return 0;
+
+pdev_destroy:
+	wlan_objmgr_pdev_obj_delete(pdev);
+	qdf_mem_free(priv);
+
+	return qdf_status_to_os_return(status);
 }
 
 int hdd_objmgr_release_and_destroy_pdev(struct hdd_context *hdd_ctx)
 {
+	QDF_STATUS status;
 	struct wlan_objmgr_pdev *pdev = hdd_ctx->hdd_pdev;
 	struct pdev_osif_priv *osif_priv;
 
-	hdd_deinit_pdev_os_priv(hdd_ctx);
 	hdd_ctx->hdd_pdev = NULL;
+
+	QDF_BUG(pdev);
 	if (!pdev)
 		return -EINVAL;
 
+	hdd_deinit_pdev_os_priv(pdev);
+
 	osif_priv = wlan_pdev_get_ospriv(pdev);
 	wlan_pdev_reset_ospriv(pdev);
 	qdf_mem_free(osif_priv);
 
-	return qdf_status_to_os_return(wlan_objmgr_pdev_obj_delete(pdev));
+	status = wlan_objmgr_pdev_obj_delete(pdev);
+	wlan_objmgr_pdev_release_ref(pdev, WLAN_HDD_ID_OBJ_MGR);
+
+	return qdf_status_to_os_return(status);
 }
 
 int hdd_objmgr_create_and_store_vdev(struct wlan_objmgr_pdev *pdev,
@@ -233,53 +274,37 @@ osif_priv_free:
 	return errno;
 }
 
-int hdd_objmgr_destroy_vdev(struct hdd_adapter *adapter)
+int hdd_objmgr_release_and_destroy_vdev(struct hdd_adapter *adapter)
 {
-	struct wlan_objmgr_vdev *vdev;
+	QDF_STATUS status;
+	struct wlan_objmgr_vdev *vdev = adapter->hdd_vdev;
 	struct vdev_osif_priv *osif_priv;
+	uint8_t *self_mac_addr;
 
-	vdev = adapter->hdd_vdev;
+	adapter->hdd_vdev = NULL;
+	adapter->session_id = HDD_SESSION_ID_INVALID;
+
+	QDF_BUG(vdev);
 	if (!vdev)
 		return -EINVAL;
 
 	osif_priv = wlan_vdev_get_ospriv(vdev);
-
-	if (!osif_priv)
-		return -EINVAL;
-
-	wlan_cfg80211_tdls_priv_deinit(osif_priv);
-	qdf_mem_free(osif_priv);
 	wlan_vdev_reset_ospriv(vdev);
 
-	if (hdd_objmgr_remove_peer_object(vdev,
-					  wlan_vdev_mlme_get_macaddr(vdev))) {
-		hdd_err("Self peer delete failed");
-		return -EINVAL;
+	QDF_BUG(osif_priv);
+	if (osif_priv) {
+		wlan_cfg80211_tdls_priv_deinit(osif_priv);
+		qdf_mem_free(osif_priv);
 	}
 
-	return qdf_status_to_os_return(wlan_objmgr_vdev_obj_delete(vdev));
-}
-
-int hdd_objmgr_release_vdev(struct hdd_adapter *adapter)
-{
-	/* allow physical vdev destroy by releasing the hdd reference */
-	wlan_objmgr_vdev_release_ref(adapter->hdd_vdev, WLAN_HDD_ID_OBJ_MGR);
-
-	adapter->hdd_vdev = NULL;
-	adapter->session_id = HDD_SESSION_ID_INVALID;
-
-	return 0;
-}
-
-int hdd_objmgr_release_and_destroy_vdev(struct hdd_adapter *adapter)
-{
-	int errno;
+	self_mac_addr = wlan_vdev_mlme_get_macaddr(vdev);
+	if (hdd_objmgr_remove_peer_object(vdev, self_mac_addr))
+		hdd_err("Self peer delete failed");
 
-	errno = hdd_objmgr_destroy_vdev(adapter);
-	if (errno)
-		return errno;
+	status = wlan_objmgr_vdev_obj_delete(vdev);
+	wlan_objmgr_vdev_release_ref(vdev, WLAN_HDD_ID_OBJ_MGR);
 
-	return hdd_objmgr_release_vdev(adapter);
+	return qdf_status_to_os_return(status);
 }
 
 int hdd_objmgr_add_peer_object(struct wlan_objmgr_vdev *vdev,

+ 1 - 27
core/hdd/src/wlan_hdd_object_manager.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -119,32 +119,6 @@ int hdd_objmgr_release_and_destroy_pdev(struct hdd_context *hdd_ctx);
 int hdd_objmgr_create_and_store_vdev(struct wlan_objmgr_pdev *pdev,
 			      struct hdd_adapter *adapter);
 
-/**
- * hdd_objmgr_destroy_vdev() - Delete vdev
- * @adapter: hdd adapter
- *
- * This function logically destroys the vdev in object manager. Physical
- * deletion is prevented until the vdev is released via a call to
- * hdd_objmgr_release_vdev(). E.g.
- *
- *	hdd_objmgr_destroy_vdev(...);
- *	sme_close_session(...);
- *	hdd_objmgr_release_vdev(...);
- *
- * Return: 0 for success, negative error code for failure
- */
-int hdd_objmgr_destroy_vdev(struct hdd_adapter *adapter);
-
-/**
- * hdd_objmgr_release_vdev() - releases the vdev from adapter
- * @adapter: hdd adapter
- *
- * See also hdd_objmgr_destroy_vdev()
- *
- * Return: 0 for success, negative error code for failure
- */
-int hdd_objmgr_release_vdev(struct hdd_adapter *adapter);
-
 /**
  * hdd_objmgr_release_and_destroy_vdev() - Delete vdev and remove from adapter
  * @adapter: hdd adapter