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:
Dustin Brown 2018-09-19 16:37:13 -07:00 • committed by nshrivas
commit 3ecc87863e
5 changed files with 104 additions and 57 deletions

View file

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

View file

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

View file

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

View file

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

View file

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