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:
parent
d51eb89859
commit
a777718385
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user