qcacld-3.0: Do SSR cleanup during uevent/shutdown based on context

Currently we have two different cleanup approach for SSR. In case of
Adrastea hardware, cleanup can be done during the receipt of FW_DOWN
uevent while in case of HS/HSP it has to be defered to shutdown.

These two approaches are segregated by different branches and thus did
not need to coexist. But as part of future upgrades, a single component
would be used for both the hardware types.

To enable having both these paths, use the context of execution of the
pld_uevent as the differentiating agent. In case of interrupt context,
go with the deferred cleanup and in case of normal process context,
perform the cleanup in pld_uevent itself.

Change-Id: I554a10cdd99b17a6d3e059ebf7a157b0cddb6226
CRs-Fixed: 2669840
This commit is contained in:
Sourav Mohapatra 2020-04-21 10:25:41 +05:30 committed by nshrivas
parent d51eb89859
commit a777718385

View File

@ -58,6 +58,9 @@
#define SSR_MAX_FAIL_CNT 3
static uint8_t re_init_fail_cnt, probe_fail_cnt;
/* An atomic flag to check if SSR cleanup has been done or not */
static qdf_atomic_t is_recovery_cleanup_done;
/*
* In BMI Phase we are only sending small chunk (256 bytes) of the FW image at
* a time, and wait for the completion interrupt to start the next transfer.
@ -753,13 +756,18 @@ static void hdd_psoc_shutdown_notify(struct hdd_context *hdd_ctx)
hdd_wlan_ssr_shutdown_event();
}
static void __hdd_soc_recovery_shutdown(void)
/**
* hdd_soc_recovery_cleanup() - Perform SSR related cleanup activities.
*
* This function will perform cleanup activities related to when driver
* undergoes SSR. Activities inclues stopping idle timer and invoking shutdown
* notifier.
*
* Return: None
*/
static void hdd_soc_recovery_cleanup(void)
{
struct hdd_context *hdd_ctx;
void *hif_ctx;
/* recovery starts via firmware down indication; ensure we got one */
QDF_BUG(cds_is_driver_recovering());
hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
if (!hdd_ctx) {
@ -782,6 +790,35 @@ static void __hdd_soc_recovery_shutdown(void)
return;
}
hdd_psoc_shutdown_notify(hdd_ctx);
}
static void __hdd_soc_recovery_shutdown(void)
{
struct hdd_context *hdd_ctx;
void *hif_ctx;
/* recovery starts via firmware down indication; ensure we got one */
QDF_BUG(cds_is_driver_recovering());
hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
if (!hdd_ctx) {
hdd_err("hdd_ctx is null");
return;
}
/*
* Perform SSR related cleanup if it has not already been done as a
* part of receiving the uevent.
*/
if (!qdf_atomic_read(&is_recovery_cleanup_done))
hdd_soc_recovery_cleanup();
else
qdf_atomic_set(&is_recovery_cleanup_done, 0);
if (!hdd_wait_for_debugfs_threads_completion())
hdd_err("Debufs threads are still pending, attempting SSR anyway");
hif_ctx = cds_get_context(QDF_MODULE_ID_HIF);
if (!hif_ctx) {
hdd_err("Failed to get HIF context, ignore SSR shutdown");
@ -791,11 +828,6 @@ static void __hdd_soc_recovery_shutdown(void)
/* mask the host controller interrupts */
hif_mask_interrupt_call(hif_ctx);
hdd_psoc_shutdown_notify(hdd_ctx);
if (!hdd_wait_for_debugfs_threads_completion())
hdd_err("Debufs threads are still pending, attempting SSR anyway");
if (!QDF_IS_EPPING_ENABLED(cds_get_conparam())) {
hif_disable_isr(hif_ctx);
hdd_wlan_shutdown();
@ -1720,21 +1752,24 @@ wlan_hdd_pld_uevent(struct device *dev, struct pld_uevent_data *event_data)
case PLD_FW_DOWN:
hdd_info("Received firmware down indication");
/* NOTE! SSR cleanup logic goes in pld shutdown, not here */
cds_set_target_ready(false);
cds_set_recovery_in_progress(true);
/* SSR cleanup happens in pld shutdown, which is serialized by
* the platform driver. Other operations are also serialized by
* platform driver, such as probe, remove, and reinit. If the
* firmware goes down during one of these operations, the driver
* would normally have to wait for a timeout before shutdown
* could begin. Instead, forcefully complete events waiting on
* firmware with a "reset" status to avoid waiting to time out
* on a firmware we already know is down.
/*
* In case of some platforms, uevent will come to the driver in
* process context. In that case, it is safe to complete the
* SSR cleanup activities in the same context. In case of
* other platforms, it will be invoked in interrupt context.
* Performing the cleanup in interrupt context is not ideal,
* thus defer the cleanup to be done during
* hdd_soc_recovery_shutdown
*/
qdf_complete_wait_events();
if (qdf_in_interrupt())
break;
hdd_soc_recovery_cleanup();
qdf_atomic_set(&is_recovery_cleanup_done, 1);
break;
case PLD_FW_HANG_EVENT:
hdd_info("Received fimrware hang event");
@ -1760,6 +1795,7 @@ wlan_hdd_pld_uevent(struct device *dev, struct pld_uevent_data *event_data)
hdd_send_hang_data(hang_evt_data.hang_data,
QDF_HANG_EVENT_DATA_SIZE);
qdf_mem_free(hang_evt_data.hang_data);
break;
default:
/* other events intentionally not handled */