mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-15 01:01:56 -04:00
qcacld-3.0: Integrate DSC (psoc idle shutdown/restart)
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 idle shutdown and restart. Change-Id: I416a8f4cfb67fabce377ff96715e3a372a3aed7d CRs-Fixed: 2347019
This commit is contained in:
parent
73cf0763b3
commit
3ecc87863e
5 changed files with 104 additions and 57 deletions
|
|
@ -2897,7 +2897,31 @@ int hdd_start_station_adapter(struct hdd_adapter *adapter);
|
|||
int hdd_start_ap_adapter(struct hdd_adapter *adapter);
|
||||
int hdd_configure_cds(struct hdd_context *hdd_ctx);
|
||||
int hdd_set_fw_params(struct hdd_adapter *adapter);
|
||||
|
||||
/**
|
||||
* hdd_wlan_start_modules() - Single driver state machine for starting modules
|
||||
* @hdd_ctx: HDD context
|
||||
* @reinit: flag to indicate from SSR or normal path
|
||||
*
|
||||
* This function maintains the driver state machine it will be invoked from
|
||||
* startup, reinit and change interface. Depending on the driver state shall
|
||||
* perform the opening of the modules.
|
||||
*
|
||||
* Return: Errno
|
||||
*/
|
||||
int hdd_wlan_start_modules(struct hdd_context *hdd_ctx, bool reinit);
|
||||
|
||||
/**
|
||||
* hdd_wlan_stop_modules - Single driver state machine for stoping modules
|
||||
* @hdd_ctx: HDD context
|
||||
* @ftm_mode: ftm mode
|
||||
*
|
||||
* This function maintains the driver state machine it will be invoked from
|
||||
* exit, shutdown and con_mode change handler. Depending on the driver state
|
||||
* shall perform the stopping/closing of the modules.
|
||||
*
|
||||
* Return: Errno
|
||||
*/
|
||||
int hdd_wlan_stop_modules(struct hdd_context *hdd_ctx, bool ftm_mode);
|
||||
|
||||
/**
|
||||
|
|
@ -2916,6 +2940,16 @@ void hdd_psoc_idle_timer_start(struct hdd_context *hdd_ctx);
|
|||
*/
|
||||
void hdd_psoc_idle_timer_stop(struct hdd_context *hdd_ctx);
|
||||
|
||||
/**
|
||||
* hdd_psoc_idle_restart() - restart a previously shutdown idle psoc, if needed
|
||||
* @hdd_ctx: the hdd context which should be restarted
|
||||
*
|
||||
* This API does nothing if the given psoc is already active.
|
||||
*
|
||||
* Return: Errno
|
||||
*/
|
||||
int hdd_psoc_idle_restart(struct hdd_context *hdd_ctx);
|
||||
|
||||
int hdd_start_adapter(struct hdd_adapter *adapter);
|
||||
void hdd_populate_random_mac_addr(struct hdd_context *hdd_ctx, uint32_t num);
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -13190,9 +13190,9 @@ static int __wlan_hdd_cfg80211_change_iface(struct wiphy *wiphy,
|
|||
qdf_opmode_str(adapter->device_mode),
|
||||
qdf_opmode_str(new_mode));
|
||||
|
||||
errno = hdd_wlan_start_modules(hdd_ctx, false);
|
||||
errno = hdd_psoc_idle_restart(hdd_ctx);
|
||||
if (errno) {
|
||||
hdd_err("Failed to start modules; errno:%d", errno);
|
||||
hdd_err("Failed to restart psoc; errno:%d", errno);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -421,11 +421,9 @@ static int __hdd_hostapd_open(struct net_device *dev)
|
|||
ret = wlan_hdd_validate_context(hdd_ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
/*
|
||||
* Check statemachine state and also stop iface change timer if running
|
||||
*/
|
||||
ret = hdd_wlan_start_modules(hdd_ctx, false);
|
||||
|
||||
/* ensure the physical soc is up */
|
||||
ret = hdd_psoc_idle_restart(hdd_ctx);
|
||||
if (ret) {
|
||||
hdd_err("Failed to start WLAN modules return");
|
||||
return ret;
|
||||
|
|
|
|||
|
|
@ -2080,7 +2080,7 @@ static int __hdd_mon_open(struct net_device *dev)
|
|||
hdd_mon_mode_ether_setup(dev);
|
||||
|
||||
if (con_mode == QDF_GLOBAL_MONITOR_MODE) {
|
||||
ret = hdd_wlan_start_modules(hdd_ctx, false);
|
||||
ret = hdd_psoc_idle_restart(hdd_ctx);
|
||||
if (ret) {
|
||||
hdd_err("Failed to start WLAN modules return");
|
||||
return ret;
|
||||
|
|
@ -2631,17 +2631,6 @@ static int hdd_update_country_code(struct hdd_context *hdd_ctx)
|
|||
return hdd_reg_set_country(hdd_ctx, country_code);
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_wlan_start_modules() - Single driver state machine for starting modules
|
||||
* @hdd_ctx: HDD context
|
||||
* @reinit: flag to indicate from SSR or normal path
|
||||
*
|
||||
* This function maintains the driver state machine it will be invoked from
|
||||
* startup, reinit and change interface. Depending on the driver state shall
|
||||
* perform the opening of the modules.
|
||||
*
|
||||
* Return: 0 for success; non-zero for failure
|
||||
*/
|
||||
int hdd_wlan_start_modules(struct hdd_context *hdd_ctx, bool reinit)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -2990,14 +2979,12 @@ static int __hdd_open(struct net_device *dev)
|
|||
goto err_hdd_hdd_init_deinit_lock;
|
||||
}
|
||||
|
||||
|
||||
ret = hdd_wlan_start_modules(hdd_ctx, false);
|
||||
ret = hdd_psoc_idle_restart(hdd_ctx);
|
||||
if (ret) {
|
||||
hdd_err("Failed to start WLAN modules return");
|
||||
goto err_hdd_hdd_init_deinit_lock;
|
||||
}
|
||||
|
||||
|
||||
if (!test_bit(SME_SESSION_OPENED, &adapter->event_flags)) {
|
||||
ret = hdd_start_adapter(adapter);
|
||||
if (ret) {
|
||||
|
|
@ -3136,7 +3123,6 @@ static int __hdd_stop(struct net_device *dev)
|
|||
/* DeInit the adapter. This ensures datapath cleanup as well */
|
||||
hdd_deinit_adapter(hdd_ctx, adapter, true);
|
||||
|
||||
|
||||
/*
|
||||
* Upon wifi turn off, DUT has to flush the scan results so if
|
||||
* this is the last cli iface, flush the scan database.
|
||||
|
|
@ -8904,31 +8890,75 @@ void hdd_psoc_idle_timer_stop(struct hdd_context *hdd_ctx)
|
|||
}
|
||||
|
||||
/**
|
||||
* hdd_iface_change_callback() - Function invoked when stop modules expires
|
||||
* @priv: pointer to hdd context
|
||||
* hdd_psoc_idle_shutdown() - perform an idle shutdown on the given psoc
|
||||
* @hdd_ctx: the hdd context which should be shutdown
|
||||
*
|
||||
* This function is invoked when the timer waiting for the interface change
|
||||
* expires, it shall cut-down the power to wlan and stop all the modules.
|
||||
* When no interfaces are "up" on a psoc, an idle shutdown timer is started.
|
||||
* If no interfaces are brought up before the timer expires, we do an
|
||||
* "idle shutdown," cutting power to the physical SoC to save power. This is
|
||||
* done completely transparently from the perspective of userspace.
|
||||
*
|
||||
* Return: void
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_iface_change_callback(void *priv)
|
||||
static void hdd_psoc_idle_shutdown(struct hdd_context *hdd_ctx)
|
||||
{
|
||||
struct hdd_context *hdd_ctx = (struct hdd_context *) priv;
|
||||
int ret;
|
||||
int status = wlan_hdd_validate_context(hdd_ctx);
|
||||
|
||||
if (status)
|
||||
return;
|
||||
struct hdd_psoc *hdd_psoc = hdd_ctx->hdd_psoc;
|
||||
QDF_STATUS status;
|
||||
|
||||
hdd_enter();
|
||||
hdd_debug("Interface change timer expired close the modules!");
|
||||
ret = hdd_wlan_stop_modules(hdd_ctx, false);
|
||||
if (ret)
|
||||
hdd_err("Failed to stop modules");
|
||||
|
||||
status = dsc_psoc_trans_start(hdd_psoc->dsc_psoc, "idle shutdown");
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
hdd_info("psoc busy, abort idle shutdown; status:%u", status);
|
||||
return;
|
||||
}
|
||||
|
||||
QDF_BUG(!hdd_wlan_stop_modules(hdd_ctx, false));
|
||||
|
||||
hdd_psoc->state = psoc_state_idle;
|
||||
dsc_psoc_trans_stop(hdd_psoc->dsc_psoc);
|
||||
|
||||
hdd_exit();
|
||||
}
|
||||
|
||||
int hdd_psoc_idle_restart(struct hdd_context *hdd_ctx)
|
||||
{
|
||||
struct hdd_psoc *hdd_psoc = hdd_ctx->hdd_psoc;
|
||||
QDF_STATUS status;
|
||||
int errno;
|
||||
|
||||
status = dsc_psoc_trans_start_wait(hdd_psoc->dsc_psoc, "idle restart");
|
||||
if (QDF_IS_STATUS_ERROR(status)) {
|
||||
hdd_info("unable to start 'idle restart'; status:%u", status);
|
||||
return qdf_status_to_os_return(status);
|
||||
}
|
||||
|
||||
errno = hdd_wlan_start_modules(hdd_ctx, false);
|
||||
if (!errno)
|
||||
hdd_psoc->state = psoc_state_active;
|
||||
|
||||
dsc_psoc_trans_stop(hdd_psoc->dsc_psoc);
|
||||
|
||||
return errno;
|
||||
}
|
||||
|
||||
/**
|
||||
* hdd_psoc_idle_timeout_callback() - Handler for psoc idle timeout
|
||||
* @priv: pointer to hdd context
|
||||
*
|
||||
* Return: None
|
||||
*/
|
||||
static void hdd_psoc_idle_timeout_callback(void *priv)
|
||||
{
|
||||
struct hdd_context *hdd_ctx = priv;
|
||||
|
||||
if (wlan_hdd_validate_context(hdd_ctx))
|
||||
return;
|
||||
|
||||
hdd_debug("Psoc idle timeout elapsed; starting psoc shutdown");
|
||||
hdd_psoc_idle_shutdown(hdd_ctx);
|
||||
}
|
||||
|
||||
#ifdef WLAN_LOGGING_SOCK_SVC_ENABLE
|
||||
static void hdd_set_wlan_logging(struct hdd_context *hdd_ctx)
|
||||
{
|
||||
|
|
@ -9042,7 +9072,7 @@ struct hdd_context *hdd_context_create(struct device *dev)
|
|||
}
|
||||
|
||||
qdf_create_delayed_work(&hdd_ctx->psoc_idle_timeout_work,
|
||||
hdd_iface_change_callback,
|
||||
hdd_psoc_idle_timeout_callback,
|
||||
hdd_ctx);
|
||||
|
||||
mutex_init(&hdd_ctx->iface_change_lock);
|
||||
|
|
@ -10870,17 +10900,6 @@ static void hdd_deregister_policy_manager_callback(
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* hdd_wlan_stop_modules - Single driver state machine for stoping modules
|
||||
* @hdd_ctx: HDD context
|
||||
* @ftm_mode: ftm mode
|
||||
*
|
||||
* This function maintains the driver state machine it will be invoked from
|
||||
* exit, shutdown and con_mode change handler. Depending on the driver state
|
||||
* shall perform the stopping/closing of the modules.
|
||||
*
|
||||
* Return: 0 for success; non-zero for failure
|
||||
*/
|
||||
int hdd_wlan_stop_modules(struct hdd_context *hdd_ctx, bool ftm_mode)
|
||||
{
|
||||
void *hif_ctx;
|
||||
|
|
|
|||
|
|
@ -696,12 +696,8 @@ struct wireless_dev *__wlan_hdd_add_virtual_intf(struct wiphy *wiphy,
|
|||
return ERR_PTR(-ENOSPC);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add interface can be requested from the upper layer at any time
|
||||
* check the statemachine for modules state and if they are closed
|
||||
* open the modules.
|
||||
*/
|
||||
ret = hdd_wlan_start_modules(hdd_ctx, false);
|
||||
/* ensure physcial soc is up */
|
||||
ret = hdd_psoc_idle_restart(hdd_ctx);
|
||||
if (ret) {
|
||||
hdd_err("Failed to start the wlan_modules");
|
||||
goto close_adapter;
|
||||
|
|
@ -840,8 +836,8 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
|
|||
if (errno)
|
||||
return errno;
|
||||
|
||||
/* check state machine state and kickstart modules if they are closed */
|
||||
errno = hdd_wlan_start_modules(hdd_ctx, false);
|
||||
/* ensure physical soc is up */
|
||||
errno = hdd_psoc_idle_restart(hdd_ctx);
|
||||
if (errno)
|
||||
return errno;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue