From ac5d26eb5eaf46c801ffaff1df75e042e37d2d60 Mon Sep 17 00:00:00 2001 From: Sameer Thalappil Date: Tue, 10 Jan 2017 15:32:58 -0800 Subject: [PATCH] qcacld-3.0: Add support for host initiated recovery If platform has a mechanism to initiate target assert, trigger that interface to force assert target. Certain integrated platforms (where WLAN runs on it's own PD) provides a mechanism to initiate PDR from host. That interface can be triggered when WLAN host detect timeout scenarios. CRs-Fixed: 1110243 Change-Id: I6a9408f47ca4245380dbf4177363c3c461ff948d --- core/cds/src/cds_api.c | 15 +++++++++++++++ core/pld/inc/pld_common.h | 1 + core/pld/src/pld_common.c | 31 +++++++++++++++++++++++++++++++ core/pld/src/pld_snoc.h | 8 ++++++++ 4 files changed, 55 insertions(+) diff --git a/core/cds/src/cds_api.c b/core/cds/src/cds_api.c index 1c1f40fa0c9f..10f1ae39701b 100644 --- a/core/cds/src/cds_api.c +++ b/core/cds/src/cds_api.c @@ -1763,6 +1763,20 @@ void cds_trigger_recovery(bool skip_crash_inject) qdf_runtime_pm_prevent_suspend(recovery_lock); + /* + * If force assert thru platform is available, trigger that interface. + * That should generate recovery by going thru the normal FW + * assert recovery model. + */ + if (!pld_force_assert_target(qdf_ctx->dev)) { + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, + "Force assert triggered"); + goto out; + } + + QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO_HIGH, + "Force assert not available at platform"); + if (!skip_crash_inject) { wma_crash_inject(wma_handle, RECOVERY_SIM_SELF_RECOVERY, 0); @@ -1778,6 +1792,7 @@ void cds_trigger_recovery(bool skip_crash_inject) cds_config_recovery_work(qdf_ctx); } +out: qdf_runtime_pm_allow_suspend(recovery_lock); qdf_runtime_lock_deinit(recovery_lock); } diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h index 8fbe0b8f0d67..30abc28dceb5 100644 --- a/core/pld/inc/pld_common.h +++ b/core/pld/inc/pld_common.h @@ -420,5 +420,6 @@ void pld_get_msi_address(struct device *dev, uint32_t *msi_addr_low, unsigned int pld_socinfo_get_serial_number(struct device *dev); uint8_t *pld_get_wlan_mac_address(struct device *dev, uint32_t *num); int pld_is_qmi_disable(struct device *dev); +int pld_force_assert_target(struct device *dev); #endif diff --git a/core/pld/src/pld_common.c b/core/pld/src/pld_common.c index 9080bcf81659..382a59c7bdfb 100644 --- a/core/pld/src/pld_common.c +++ b/core/pld/src/pld_common.c @@ -1694,3 +1694,34 @@ int pld_is_qmi_disable(struct device *dev) return ret; } + +/** + * pld_force_assert_target() - Send a force assert to FW. + * This can use various sideband requests available at platform to + * initiate a FW assert. + * @dev: device + * + * Return: 0 if force assert of target was triggered successfully + * Non zero failure code for errors + */ +int pld_force_assert_target(struct device *dev) +{ + int ret = 0; + enum pld_bus_type type = pld_get_bus_type(dev); + + switch (type) { + case PLD_BUS_TYPE_SNOC: + ret = pld_snoc_force_assert_target(dev); + break; + + case PLD_BUS_TYPE_PCIE: + case PLD_BUS_TYPE_SDIO: + ret = -EINVAL; + break; + default: + pr_err("Invalid device type %d\n", type); + ret = -EINVAL; + break; + } + return ret; +} diff --git a/core/pld/src/pld_snoc.h b/core/pld/src/pld_snoc.h index f10b1f7c2a29..e3d9af7e0949 100644 --- a/core/pld/src/pld_snoc.h +++ b/core/pld/src/pld_snoc.h @@ -146,6 +146,10 @@ static inline int pld_snoc_set_fw_log_mode(u8 fw_log_mode) { return 0; } +static inline int pld_snoc_force_assert_target(struct device *dev) +{ + return 0; +} #else int pld_snoc_register_driver(void); void pld_snoc_unregister_driver(void); @@ -247,5 +251,9 @@ static inline int pld_snoc_set_fw_log_mode(u8 fw_log_mode) { return icnss_set_fw_log_mode(fw_log_mode); } +static inline int pld_snoc_force_assert_target(struct device *dev) +{ + return icnss_trigger_recovery(dev); +} #endif #endif