qcacld-3.0: synchronize interface change timer with driver shutdown

As part of the last interface down, driver starts the interface
change timer to close the modules of 15seconds, if there is no
request to use the interfaces from upper layer during this time
the timer expiers and closes modules. There can be SSR/PDR triggered in the
different context which during shutdown tries to call the
respective module notifiers which can be purged/freed
in the timer context.

Synchronize the interface change timer callback with the shutdown
using the interface change timer lock. Following steps are taken
to make sure one thread is completed before other thread starts
execution:
	* Set the respective flag of recovery inprogress or fw_down
          so that access to firmware is blocked.
	* Take the interface change lock, so if the timer callback
	  is running it will complete the closing the modulkes,
	  or if the uevent gets the lock it completes the calling
	  notifiers and purges the same.
	* Release the interface change lock.

Change-Id: I1d7f62cd0ce7268cc9a5bda2a72dae384b70a6e2
CRs-Fixed: 2100846
This commit is contained in:
Arunk Khandavalli 2017-10-04 12:41:27 +05:30 • committed by snandini
commit 932a9e161a
3 changed files with 33 additions and 3 deletions

View file

@ -484,4 +484,11 @@ QDF_STATUS cds_shutdown_notifier_register(void (*cb)(void *priv), void *priv);
*/
void cds_shutdown_notifier_purge(void);
/**
* cds_shutdown_notifier_call() - Call shutdown notifier call back
*
* Call registered shutdown notifier call back to indicate about remove or
* shutdown.
*/
void cds_shutdown_notifier_call(void);
#endif /* #if !defined __CDS_SCHED_H */

View file

@ -1120,7 +1120,7 @@ void cds_shutdown_notifier_purge(void)
* Call registered shutdown notifier call back to indicate about remove or
* shutdown.
*/
static void cds_shutdown_notifier_call(void)
void cds_shutdown_notifier_call(void)
{
struct shutdown_notifier *notifier;
unsigned long irq_flags;
@ -1153,8 +1153,6 @@ bool cds_wait_for_external_threads_completion(const char *caller_func)
int count = MAX_SSR_WAIT_ITERATIONS;
int r;
cds_shutdown_notifier_call();
while (count) {
r = atomic_read(&ssr_protect_entry_count);

View file

@ -1363,6 +1363,29 @@ static void wlan_hdd_pld_notify_handler(struct device *dev,
wlan_hdd_notify_handler(state);
}
static void wlan_hdd_purge_notifier(void)
{
struct hdd_context *hdd_ctx;
ENTER();
hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
if (!hdd_ctx) {
hdd_err("hdd context is NULL return!!");
return;
}
mutex_lock(&hdd_ctx->iface_change_lock);
if (QDF_TIMER_STATE_RUNNING ==
qdf_mc_timer_get_current_state(&hdd_ctx->iface_change_timer))
qdf_mc_timer_stop(&hdd_ctx->iface_change_timer);
cds_shutdown_notifier_call();
cds_shutdown_notifier_purge();
mutex_unlock(&hdd_ctx->iface_change_lock);
EXIT();
}
/**
* wlan_hdd_pld_uevent() - update driver status
* @dev: device
@ -1379,6 +1402,8 @@ static void wlan_hdd_pld_uevent(struct device *dev,
} else if (uevent->uevent == PLD_FW_DOWN) {
cds_set_fw_state(CDS_FW_STATE_DOWN);
}
wlan_hdd_purge_notifier();
}
#ifdef FEATURE_RUNTIME_PM