|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
- * Copyright (c) 2018, 2020 The Linux Foundation. All rights reserved.
|
|
|
+ * Copyright (c) 2018, 2020-2021 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
|
|
@@ -24,6 +24,7 @@
|
|
|
#include "wlan_objmgr_global_obj.h"
|
|
|
#include "target_if_ipa.h"
|
|
|
#include "wlan_ipa_ucfg_api.h"
|
|
|
+#include "qdf_platform.h"
|
|
|
|
|
|
static bool g_ipa_is_ready;
|
|
|
bool ipa_cb_is_ready(void)
|
|
@@ -70,6 +71,7 @@ ipa_pdev_obj_destroy_notification(struct wlan_objmgr_pdev *pdev,
|
|
|
ipa_err("Failed to detatch ipa pdev object");
|
|
|
|
|
|
ipa_obj_cleanup(ipa_obj);
|
|
|
+ qdf_mutex_destroy(&ipa_obj->init_deinit_lock);
|
|
|
qdf_mem_free(ipa_obj);
|
|
|
ipa_disable_register_cb();
|
|
|
|
|
@@ -101,6 +103,7 @@ ipa_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev,
|
|
|
if (!ipa_obj)
|
|
|
return QDF_STATUS_E_NOMEM;
|
|
|
|
|
|
+ qdf_mutex_create(&ipa_obj->init_deinit_lock);
|
|
|
status = wlan_objmgr_pdev_component_obj_attach(pdev,
|
|
|
WLAN_UMAC_COMP_IPA,
|
|
|
(void *)ipa_obj,
|
|
@@ -123,31 +126,45 @@ ipa_pdev_obj_create_notification(struct wlan_objmgr_pdev *pdev,
|
|
|
static void ipa_register_ready_cb(void *user_data)
|
|
|
{
|
|
|
QDF_STATUS status = QDF_STATUS_SUCCESS;
|
|
|
- struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)
|
|
|
- user_data;
|
|
|
+ struct wlan_ipa_priv *ipa_obj = (struct wlan_ipa_priv *)user_data;
|
|
|
+ struct wlan_objmgr_pdev *pdev;
|
|
|
struct wlan_objmgr_psoc *psoc;
|
|
|
qdf_device_t qdf_dev;
|
|
|
- struct wlan_ipa_priv *ipa_obj;
|
|
|
|
|
|
if (!ipa_config_is_enabled()) {
|
|
|
ipa_info("IPA config is disabled");
|
|
|
return;
|
|
|
}
|
|
|
- if (!pdev) {
|
|
|
- ipa_err("Pdev obj mgr is NULL");
|
|
|
+ if (!ipa_obj) {
|
|
|
+ ipa_err("IPA object is NULL");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Validate driver state to determine ipa_obj is valid or not */
|
|
|
+ if (qdf_is_driver_state_module_stop()) {
|
|
|
+ ipa_err("Driver modules stop in-progress or done");
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
+ qdf_mutex_acquire(&ipa_obj->init_deinit_lock);
|
|
|
+ /*
|
|
|
+ * Meanwhile acquiring lock, driver stop modules can happen in parallel,
|
|
|
+ * validate driver state once again to proceed with IPA init.
|
|
|
+ */
|
|
|
+ if (qdf_is_driver_state_module_stop()) {
|
|
|
+ ipa_err("Driver modules stop in-progress/done, releasing lock");
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ pdev = ipa_priv_obj_get_pdev(ipa_obj);
|
|
|
psoc = wlan_pdev_get_psoc(pdev);
|
|
|
qdf_dev = wlan_psoc_get_qdf_dev(psoc);
|
|
|
-
|
|
|
if (!qdf_dev) {
|
|
|
ipa_err("QDF device context is NULL");
|
|
|
- return;
|
|
|
+ goto out;
|
|
|
}
|
|
|
|
|
|
g_ipa_is_ready = true;
|
|
|
ipa_info("IPA ready callback invoked: ipa_register_ready_cb");
|
|
|
- ipa_obj = ipa_pdev_get_priv_obj(pdev);
|
|
|
status = ipa_obj_setup(ipa_obj);
|
|
|
if (QDF_IS_STATUS_ERROR(status)) {
|
|
|
ipa_err("Failed to setup ipa component");
|
|
@@ -155,28 +172,38 @@ static void ipa_register_ready_cb(void *user_data)
|
|
|
WLAN_UMAC_COMP_IPA,
|
|
|
ipa_obj);
|
|
|
qdf_mem_free(ipa_obj);
|
|
|
- return;
|
|
|
+ goto out;
|
|
|
}
|
|
|
if (ucfg_ipa_uc_ol_init(pdev, qdf_dev)) {
|
|
|
ipa_err("IPA ucfg_ipa_uc_ol_init failed");
|
|
|
- return;
|
|
|
+ goto out;
|
|
|
}
|
|
|
+
|
|
|
+out:
|
|
|
+ qdf_mutex_release(&ipa_obj->init_deinit_lock);
|
|
|
}
|
|
|
|
|
|
QDF_STATUS ipa_register_is_ipa_ready(struct wlan_objmgr_pdev *pdev)
|
|
|
{
|
|
|
int ret;
|
|
|
+ struct wlan_ipa_priv *ipa_obj;
|
|
|
|
|
|
if (!ipa_config_is_enabled()) {
|
|
|
ipa_info("IPA config is disabled");
|
|
|
return QDF_STATUS_SUCCESS;
|
|
|
}
|
|
|
|
|
|
+ ipa_obj = ipa_pdev_get_priv_obj(pdev);
|
|
|
+ if (!ipa_obj) {
|
|
|
+ ipa_err("IPA object is NULL");
|
|
|
+ return QDF_STATUS_E_FAILURE;
|
|
|
+ }
|
|
|
+
|
|
|
ret = qdf_ipa_register_ipa_ready_cb(ipa_register_ready_cb,
|
|
|
- (void *)pdev);
|
|
|
+ (void *)ipa_obj);
|
|
|
if (ret == -EEXIST) {
|
|
|
ipa_info("IPA is ready, invoke callback");
|
|
|
- ipa_register_ready_cb((void *)pdev);
|
|
|
+ ipa_register_ready_cb((void *)ipa_obj);
|
|
|
} else if (ret) {
|
|
|
ipa_err("Failed to check IPA readiness %d", ret);
|
|
|
return QDF_STATUS_E_FAILURE;
|