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
This commit is contained in:
Dustin Brown 2018-09-05 14:27:50 -07:00 • committed by nshrivas
commit 623e7e358d
3 changed files with 184 additions and 90 deletions

View file

@ -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
/**

View file

@ -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);
}

View file

@ -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();