Browse Source

qcacld-3.0: Integrate DSC (psoc probe/remove)

The Driver Synchronization Core (DSC) is a set of synchronization
primitives for use by the driver's orchestration layer. It provides APIs
for ensuring safe state transitions (including bring up and tear down)
of major driver objects: a single driver, associated psocs, and their
associated vdevs.

As part of integrating the DSC APIs into HDD, protect psoc probe and
remove.

Change-Id: I5db13fb321695f535b5765c637ee638396e5ca6f
CRs-Fixed: 2347016
Dustin Brown 6 years ago
parent
commit
623e7e358d
3 changed files with 184 additions and 90 deletions
  1. 44 3
      core/hdd/inc/wlan_hdd_main.h
  2. 98 11
      core/hdd/src/wlan_hdd_driver_ops.c
  3. 42 76
      core/hdd/src/wlan_hdd_main.c

+ 44 - 3
core/hdd/inc/wlan_hdd_main.h

@@ -1716,14 +1716,35 @@ struct hdd_driver {
 
 struct hdd_driver *hdd_driver_get(void);
 
+enum hdd_psoc_state {
+	psoc_state_uninit,
+	psoc_state_deinit,
+	psoc_state_active, /* historically "ENABLED" */
+	psoc_state_idle, /* historically "CLOSED" */
+};
+
+/**
+ * struct hdd_psoc - HDD psoc-level context information
+ * @hdd_driver: pointer to parent HDD driver context
+ * @dsc_psoc: driver synchronization psoc context handle
+ * @state: the current stable state of the psoc
+ */
+struct hdd_psoc {
+	struct hdd_driver *hdd_driver;
+	struct dsc_psoc *dsc_psoc;
+	enum hdd_psoc_state state;
+};
+
 /**
  * struct hdd_context - hdd shared driver and psoc/device context
+ * @hdd_psoc: hdd psoc context
  * @psoc: object manager psoc context
  * @pdev: object manager pdev context
  * @g_event_flags: a bitmap of hdd_driver_flags
  * @psoc_idle_timeout_work: delayed work for psoc idle shutdown
  */
 struct hdd_context {
+	struct hdd_psoc *hdd_psoc;
 	struct wlan_objmgr_psoc *psoc;
 	struct wlan_objmgr_pdev *pdev;
 	mac_handle_t mac_handle;
@@ -2391,12 +2412,11 @@ void hdd_deinit(void);
 
 /**
  * hdd_wlan_startup() - HDD init function
- * @dev: pointer to the underlying device
- * @out_hdd_ctx: output hdd context pointer for the newly created context
+ * hdd_ctx: the HDD context corresponding to the psoc to startup
  *
  * Return: Errno
  */
-int hdd_wlan_startup(struct device *dev, struct hdd_context **out_hdd_ctx);
+int hdd_wlan_startup(struct hdd_context *hdd_ctx);
 
 /**
  * hdd_wlan_exit() - HDD WLAN exit function
@@ -2414,6 +2434,27 @@ void hdd_wlan_exit(struct hdd_context *hdd_ctx);
  */
 QDF_STATUS hdd_psoc_create_vdevs(struct hdd_context *hdd_ctx);
 
+/*
+ * hdd_context_create() - Allocate and inialize HDD context.
+ * @dev: Device Pointer to the underlying device
+ *
+ * Allocate and initialize HDD context. HDD context is allocated as part of
+ * wiphy allocation and then context is initialized.
+ *
+ * Return: HDD context on success and ERR_PTR on failure
+ */
+struct hdd_context *hdd_context_create(struct device *dev);
+
+/**
+ * hdd_context_destroy() - Destroy HDD context
+ * @hdd_ctx: HDD context to be destroyed.
+ *
+ * Free config and HDD context as well as destroy all the resources.
+ *
+ * Return: None
+ */
+void hdd_context_destroy(struct hdd_context *hdd_ctx);
+
 int hdd_wlan_notify_modem_power_state(int state);
 #ifdef QCA_HT_2040_COEX
 /**

+ 98 - 11
core/hdd/src/wlan_hdd_driver_ops.c

@@ -356,6 +356,56 @@ static int check_for_probe_defer(int ret)
 }
 #endif
 
+static QDF_STATUS hdd_psoc_ctx_create(struct hdd_psoc **out_hdd_psoc)
+{
+	QDF_STATUS status;
+	struct hdd_driver *hdd_driver = hdd_driver_get();
+	struct hdd_psoc *hdd_psoc;
+
+	QDF_BUG(out_hdd_psoc);
+	if (!out_hdd_psoc)
+		return QDF_STATUS_E_INVAL;
+
+	hdd_psoc = qdf_mem_malloc(sizeof(*hdd_psoc));
+	if (!hdd_psoc)
+		return QDF_STATUS_E_NOMEM;
+
+	hdd_psoc->hdd_driver = hdd_driver;
+	hdd_psoc->state = psoc_state_uninit;
+
+	status = dsc_psoc_create(hdd_driver->dsc_driver, &hdd_psoc->dsc_psoc);
+	if (QDF_IS_STATUS_ERROR(status))
+		goto free_ctx;
+
+	*out_hdd_psoc = hdd_psoc;
+
+	return QDF_STATUS_SUCCESS;
+
+free_ctx:
+	qdf_mem_free(hdd_psoc);
+
+	return status;
+}
+
+static void hdd_psoc_ctx_destroy(struct hdd_psoc **out_hdd_psoc)
+{
+	struct hdd_psoc *hdd_psoc;
+
+	QDF_BUG(out_hdd_psoc);
+	if (!out_hdd_psoc)
+		return;
+
+	hdd_psoc = *out_hdd_psoc;
+	QDF_BUG(hdd_psoc);
+	if (!hdd_psoc)
+		return;
+
+	*out_hdd_psoc = NULL;
+
+	dsc_psoc_destroy(&hdd_psoc->dsc_psoc);
+	qdf_mem_free(hdd_psoc);
+}
+
 static void hdd_soc_load_lock(struct device *dev, int load_op)
 {
 	mutex_lock(&hdd_init_deinit_lock);
@@ -390,11 +440,23 @@ static int hdd_soc_probe(struct device *dev,
 			 enum qdf_bus_type bus_type)
 {
 	struct hdd_context *hdd_ctx;
+	struct hdd_psoc *hdd_psoc;
 	QDF_STATUS status;
 	int errno;
 
 	hdd_info("probing driver");
 
+	status = hdd_psoc_ctx_create(&hdd_psoc);
+	if (QDF_IS_STATUS_ERROR(status))
+		return qdf_status_to_os_return(status);
+
+	status = dsc_psoc_trans_start(hdd_psoc->dsc_psoc, "probe");
+	if (QDF_IS_STATUS_ERROR(status)) {
+		hdd_err("Failed to start transition; probe, status:%u", status);
+		errno = qdf_status_to_os_return(status);
+		goto free_psoc;
+	}
+
 	hdd_soc_load_lock(dev, eHDD_DRV_OP_PROBE);
 	cds_set_load_in_progress(true);
 	cds_set_driver_in_bad_state(false);
@@ -403,9 +465,17 @@ static int hdd_soc_probe(struct device *dev,
 	if (errno)
 		goto unlock;
 
-	errno = hdd_wlan_startup(dev, &hdd_ctx);
-	if (errno)
+	hdd_ctx = hdd_context_create(dev);
+	if (IS_ERR(hdd_ctx)) {
+		errno = PTR_ERR(hdd_ctx);
 		goto assert_fail_count;
+	}
+
+	hdd_ctx->hdd_psoc = hdd_psoc;
+
+	errno = hdd_wlan_startup(hdd_ctx);
+	if (errno)
+		goto hdd_context_destroy;
 
 	status = hdd_psoc_create_vdevs(hdd_ctx);
 	if (QDF_IS_STATUS_ERROR(status)) {
@@ -415,16 +485,22 @@ static int hdd_soc_probe(struct device *dev,
 
 	probe_fail_cnt = 0;
 	cds_set_driver_loaded(true);
-	hdd_start_complete(0);
 	cds_set_load_in_progress(false);
+	hdd_start_complete(0);
 
 	hdd_soc_load_unlock(dev);
 
+	hdd_psoc->state = psoc_state_active;
+	dsc_psoc_trans_stop(hdd_psoc->dsc_psoc);
+
 	return 0;
 
 wlan_exit:
 	hdd_wlan_exit(hdd_ctx);
 
+hdd_context_destroy:
+	hdd_context_destroy(hdd_ctx);
+
 assert_fail_count:
 	probe_fail_cnt++;
 	hdd_err("consecutive probe failures:%u", probe_fail_cnt);
@@ -434,6 +510,11 @@ unlock:
 	cds_set_load_in_progress(false);
 	hdd_soc_load_unlock(dev);
 
+	dsc_psoc_trans_stop(hdd_psoc->dsc_psoc);
+
+free_psoc:
+	hdd_psoc_ctx_destroy(&hdd_psoc);
+
 	return check_for_probe_defer(errno);
 }
 
@@ -505,9 +586,16 @@ unlock:
  */
 static void hdd_soc_remove(struct device *dev)
 {
+	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
+	struct hdd_psoc *hdd_psoc = hdd_ctx->hdd_psoc;
+
 	pr_info("%s: Removing driver v%s\n", WLAN_MODULE_NAME,
 		QWLAN_VERSIONSTR);
 
+	/* remove is triggered by rmmod, so assert we are protected by rmmod */
+	dsc_psoc_assert_trans_protected(hdd_psoc->dsc_psoc);
+	dsc_psoc_wait_for_ops(hdd_psoc->dsc_psoc);
+
 	cds_set_driver_loaded(false);
 	cds_set_unload_in_progress(true);
 
@@ -523,14 +611,8 @@ static void hdd_soc_remove(struct device *dev)
 		epping_disable();
 		epping_close();
 	} else {
-		struct hdd_context *hdd_ctx;
-
-		hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
-		if (hdd_ctx)
-			hdd_wlan_exit(hdd_ctx);
-		else
-			hdd_err("invalid hdd context");
-
+		hdd_wlan_exit(hdd_ctx);
+		hdd_context_destroy(hdd_ctx);
 	}
 	hdd_stop_driver_ops_timer();
 	mutex_unlock(&hdd_init_deinit_lock);
@@ -538,6 +620,11 @@ static void hdd_soc_remove(struct device *dev)
 	cds_set_driver_in_bad_state(false);
 	cds_set_unload_in_progress(false);
 
+	hdd_psoc->state = psoc_state_deinit;
+	dsc_psoc_assert_trans_protected(hdd_psoc->dsc_psoc);
+
+	hdd_psoc_ctx_destroy(&hdd_psoc);
+
 	pr_info("%s: Driver De-initialized\n", WLAN_MODULE_NAME);
 }
 

+ 42 - 76
core/hdd/src/wlan_hdd_main.c

@@ -6876,18 +6876,11 @@ static int hdd_context_deinit(struct hdd_context *hdd_ctx)
 	return 0;
 }
 
-/**
- * hdd_context_destroy() - Destroy HDD context
- * @hdd_ctx:	HDD context to be destroyed.
- *
- * Free config and HDD context as well as destroy all the resources.
- *
- * Return: None
- */
-static void hdd_context_destroy(struct hdd_context *hdd_ctx)
+void hdd_context_destroy(struct hdd_context *hdd_ctx)
 {
 	cds_set_context(QDF_MODULE_ID_HDD, NULL);
 
+	hdd_exit_netlink_services(hdd_ctx);
 	wlan_hdd_deinit_tx_rx_histogram(hdd_ctx);
 
 	hdd_context_deinit(hdd_ctx);
@@ -6896,7 +6889,6 @@ static void hdd_context_destroy(struct hdd_context *hdd_ctx)
 
 	qdf_mem_free(hdd_ctx->config);
 	hdd_ctx->config = NULL;
-
 	cfg_release();
 
 	wiphy_free(hdd_ctx->wiphy);
@@ -7041,8 +7033,6 @@ void hdd_wlan_exit(struct hdd_context *hdd_ctx)
 #ifdef FEATURE_WLAN_CH_AVOID
 	mutex_destroy(&hdd_ctx->avoid_freq_lock);
 #endif
-
-	hdd_context_destroy(hdd_ctx);
 }
 
 #ifdef FEATURE_WLAN_AP_AP_ACS_OPTIMIZE
@@ -9037,16 +9027,7 @@ static void hdd_cfg_params_init(struct hdd_context *hdd_ctx)
 	hdd_dp_cfg_update(psoc, hdd_ctx);
 }
 
-/**
- * hdd_context_create() - Allocate and inialize HDD context.
- * @dev:	Device Pointer to the underlying device
- *
- * Allocate and initialize HDD context. HDD context is allocated as part of
- * wiphy allocation and then context is initialized.
- *
- * Return: HDD context on success and ERR_PTR on failure
- */
-static struct hdd_context *hdd_context_create(struct device *dev)
+struct hdd_context *hdd_context_create(struct device *dev)
 {
 	QDF_STATUS status;
 	int ret = 0;
@@ -11226,14 +11207,14 @@ void hdd_dp_trace_init(struct hdd_config *config)
 #endif
 
 #ifdef DISABLE_CHANNEL_LIST
-static int wlan_hdd_cache_chann_mutex_create(struct hdd_context *hdd_ctx)
+static QDF_STATUS wlan_hdd_cache_chann_mutex_create(struct hdd_context *hdd_ctx)
 {
 	return qdf_mutex_create(&hdd_ctx->cache_channel_lock);
 }
 #else
-static int wlan_hdd_cache_chann_mutex_create(struct hdd_context *hdd_ctx)
+static QDF_STATUS wlan_hdd_cache_chann_mutex_create(struct hdd_context *hdd_ctx)
 {
-	return 0;
+	return QDF_STATUS_SUCCESS;
 }
 #endif
 
@@ -11357,26 +11338,20 @@ static QDF_STATUS hdd_open_adapters_for_mode(struct hdd_context *hdd_ctx,
 	return status;
 }
 
-int hdd_wlan_startup(struct device *dev, struct hdd_context **out_hdd_ctx)
+int hdd_wlan_startup(struct hdd_context *hdd_ctx)
 {
 	QDF_STATUS status;
-	struct hdd_context *hdd_ctx;
-	int ret;
-	mac_handle_t mac_handle;
+	int errno;
 
 	hdd_enter();
 
-	hdd_ctx = hdd_context_create(dev);
-	if (IS_ERR(hdd_ctx))
-		return PTR_ERR(hdd_ctx);
-
 	hdd_action_oui_config(hdd_ctx);
 
 	qdf_nbuf_init_replenish_timer();
 
-	ret = wlan_hdd_cache_chann_mutex_create(hdd_ctx);
-	if (QDF_IS_STATUS_ERROR(ret))
-		goto err_hdd_free_context;
+	status = wlan_hdd_cache_chann_mutex_create(hdd_ctx);
+	if (QDF_IS_STATUS_ERROR(status))
+		return qdf_status_to_os_return(status);
 
 #ifdef FEATURE_WLAN_CH_AVOID
 	mutex_init(&hdd_ctx->avoid_freq_lock);
@@ -11387,41 +11362,40 @@ int hdd_wlan_startup(struct device *dev, struct hdd_context **out_hdd_ctx)
 	hdd_driver_memdump_init();
 	hdd_bus_bandwidth_init(hdd_ctx);
 
-	ret = hdd_wlan_start_modules(hdd_ctx, false);
-	if (ret) {
-		hdd_err("Failed to start modules: %d", ret);
-		goto err_memdump_deinit;
+	errno = hdd_wlan_start_modules(hdd_ctx, false);
+	if (errno) {
+		hdd_err("Failed to start modules; errno:%d", errno);
+		goto memdump_deinit;
 	}
 
 	wlan_hdd_update_wiphy(hdd_ctx);
 
-	mac_handle = cds_get_context(QDF_MODULE_ID_SME);
-	hdd_ctx->mac_handle = mac_handle;
-	if (!mac_handle) {
+	hdd_ctx->mac_handle = cds_get_context(QDF_MODULE_ID_SME);
+	if (!hdd_ctx->mac_handle) {
 		hdd_err("Mac Handle is null");
-		goto err_stop_modules;
+		goto stop_modules;
 	}
 
-	ret = hdd_wiphy_init(hdd_ctx);
-	if (ret) {
-		hdd_err("Failed to initialize wiphy: %d", ret);
-		goto err_stop_modules;
+	errno = hdd_wiphy_init(hdd_ctx);
+	if (errno) {
+		hdd_err("Failed to initialize wiphy; errno:%d", errno);
+		goto stop_modules;
 	}
 
 	hdd_dp_trace_init(hdd_ctx->config);
 
 	hdd_initialize_mac_address(hdd_ctx);
 
-	ret = register_netdevice_notifier(&hdd_netdev_notifier);
-	if (ret) {
-		hdd_err("register_netdevice_notifier failed: %d", ret);
-		goto err_wiphy_unregister;
+	errno = register_netdevice_notifier(&hdd_netdev_notifier);
+	if (errno) {
+		hdd_err("register_netdevice_notifier failed; errno:%d", errno);
+		goto unregister_wiphy;
 	}
 
-	ret = register_reboot_notifier(&system_reboot_notifier);
-	if (ret) {
-		hdd_err("Failed to register reboot notifier: %d", ret);
-		goto err_unregister_netdev;
+	errno = register_reboot_notifier(&system_reboot_notifier);
+	if (errno) {
+		hdd_err("Failed to register reboot notifier; errno:%d", errno);
+		goto unregister_netdev;
 	}
 
 	wlan_hdd_update_11n_mode(hdd_ctx->config);
@@ -11439,9 +11413,9 @@ int hdd_wlan_startup(struct device *dev, struct hdd_context **out_hdd_ctx)
 
 	hdd_lpass_notify_wlan_version(hdd_ctx);
 
-	ret = hdd_register_notifiers(hdd_ctx);
-	if (ret)
-		goto err_close_adapters;
+	errno = hdd_register_notifiers(hdd_ctx);
+	if (errno)
+		goto unregister_reboot;
 
 	status = wlansap_global_init();
 	if (QDF_IS_STATUS_ERROR(status))
@@ -11449,8 +11423,6 @@ int hdd_wlan_startup(struct device *dev, struct hdd_context **out_hdd_ctx)
 
 	hdd_set_idle_ps_config(hdd_ctx, hdd_ctx->config->fIsImpsEnabled);
 
-	*out_hdd_ctx = hdd_ctx;
-
 	hdd_exit();
 
 	return 0;
@@ -11458,40 +11430,33 @@ int hdd_wlan_startup(struct device *dev, struct hdd_context **out_hdd_ctx)
 unregister_notifiers:
 	hdd_unregister_notifiers(hdd_ctx);
 
-err_close_adapters:
-	hdd_close_all_adapters(hdd_ctx, false);
-
+unregister_reboot:
 	unregister_reboot_notifier(&system_reboot_notifier);
 
-err_unregister_netdev:
+unregister_netdev:
 	unregister_netdevice_notifier(&hdd_netdev_notifier);
 
-err_wiphy_unregister:
+unregister_wiphy:
 	qdf_dp_trace_deinit();
 	wiphy_unregister(hdd_ctx->wiphy);
 
-err_stop_modules:
+stop_modules:
 	hdd_wlan_stop_modules(hdd_ctx, false);
 
-err_memdump_deinit:
+memdump_deinit:
 	hdd_bus_bandwidth_deinit(hdd_ctx);
 	hdd_driver_memdump_deinit();
-
 	osif_request_manager_deinit();
-	hdd_exit_netlink_services(hdd_ctx);
+	qdf_nbuf_deinit_replenish_timer();
 
-err_hdd_free_context:
 	if (cds_is_fw_down())
 		hdd_err("Not setting the complete event as fw is down");
 	else
-		hdd_start_complete(ret);
-
-	qdf_nbuf_deinit_replenish_timer();
-	hdd_context_destroy(hdd_ctx);
+		hdd_start_complete(errno);
 
 	hdd_exit();
 
-	return ret;
+	return errno;
 }
 
 QDF_STATUS hdd_psoc_create_vdevs(struct hdd_context *hdd_ctx)
@@ -13049,6 +13014,7 @@ static void hdd_driver_unload(void)
 
 	hdd_driver->state = driver_state_deinit;
 	dsc_driver_trans_stop(hdd_driver->dsc_driver);
+
 	hdd_driver_ctx_deinit(hdd_driver);
 
 	hdd_qdf_deinit();