summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzhangq <zhangq@qti.qualcomm.com>2016-03-30 11:23:32 +0800
committerAnjaneedevi Kapparapu <akappa@codeaurora.org>2016-04-12 14:36:53 +0530
commit41c48b8b73b50fd040c052ef848b5e9911daf5dc (patch)
tree79f2e92025d3bc05efbb57c1cb3f9d67834929b3
parent92cf5477804f13ba2795d9bc0d3decf81dff924c (diff)
qcacld-2.0: Add self_recover for SDIO
In scenario such as AXI error, firmware will enter an un-recoverable status. Cold reset is needed when that happens. Firmware will set FW_IND_HELPER flag when it enters an un-recoverable status. Host will check this flag when target asserts, If this is set and self-recovery is enabled, host will start the self-recovery progress. Change-Id: Ic15578fbbcfe8975096085c4a13abdd509d429e4 CRs-Fixed: 996500
-rw-r--r--CORE/SERVICES/BMI/ol_fw.c14
-rw-r--r--CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c41
-rw-r--r--CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h1
3 files changed, 54 insertions, 2 deletions
diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c
index e1030d5ad3d9..151208a1784e 100644
--- a/CORE/SERVICES/BMI/ol_fw.c
+++ b/CORE/SERVICES/BMI/ol_fw.c
@@ -1160,7 +1160,7 @@ void ol_schedule_ramdump_work(struct ol_softc *scn)
static void fw_indication_work_handler(struct work_struct *fw_indication)
{
-#if !defined(HIF_SDIO)
+#ifndef HIF_USB
struct device *dev = NULL;
if (ramdump_scn && ramdump_scn->adf_dev
@@ -1414,7 +1414,7 @@ void ol_target_failure(void *instance, A_STATUS status)
struct ol_softc *scn = (struct ol_softc *)instance;
void *vos_context = vos_get_global_context(VOS_MODULE_ID_WDA, NULL);
tp_wma_handle wma = vos_get_context(VOS_MODULE_ID_WDA, vos_context);
-#ifdef HIF_PCI
+#ifndef HIF_USB
int ret;
#endif
@@ -1475,6 +1475,16 @@ void ol_target_failure(void *instance, A_STATUS status)
}
#endif
+#ifdef HIF_SDIO
+ ret = hif_sdio_check_fw_reg(scn);
+ if (0 == ret) {
+ if (scn->enable_self_recovery) {
+ ol_schedule_fw_indication_work(scn);
+ return;
+ }
+ }
+#endif
+
printk("XXX TARGET ASSERTED XXX\n");
if (__ol_target_failure(scn, wma))
diff --git a/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c b/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c
index 7710a9b4faf9..602adf59432a 100644
--- a/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c
+++ b/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c
@@ -49,6 +49,7 @@
#include "vos_sched.h"
#include "regtable.h"
#include "wlan_hdd_power.h"
+#include "targaddrs.h"
#ifndef REMOVE_PKT_LOG
#include "ol_txrx_types.h"
@@ -64,6 +65,12 @@
#endif /* CONFIG_PM */
#endif /* ATH_BUS_PM */
+#ifndef offsetof
+#define offsetof(type, field) ((adf_os_size_t)(&((type *)0)->field))
+#endif
+
+#define FW_IND_HELPER 0x8000
+
#ifndef REMOVE_PKT_LOG
struct ol_pl_os_dep_funcs *g_ol_pl_os_dep_funcs = NULL;
#endif
@@ -482,3 +489,37 @@ void hif_set_fw_info(void *ol_sc, u32 target_fw_version)
{
((struct ol_softc *)ol_sc)->target_fw_version = target_fw_version;
}
+
+/**
+ * hif_sdio_check_fw_reg() - Check wether a self recovery is needed
+ * @ol_sc: os layser software context
+ *
+ * For scenario such as AXI error, cold reset is needed to recover FW.
+ * FW will set FW_IND_HELPER in such a scenario.
+ *
+ */
+int hif_sdio_check_fw_reg(void * ol_sc)
+{
+ int ret = 1;
+ unsigned int addr = 0;
+ unsigned int fw_indication = 0;
+ struct ol_softc *scn = (struct ol_softc *) ol_sc;
+
+ addr = host_interest_item_address(scn->target_type,
+ offsetof(struct host_interest_s,
+ hi_option_flag2));
+
+ if (HIFDiagReadMem(scn->hif_hdl, addr,
+ (unsigned char *)&fw_indication,
+ 4) != A_OK) {
+ printk("%s Get fw indication failed\n", __func__);
+ return -ENOENT;
+ }
+
+ printk("%s: fw indication is 0x%x.\n", __func__, fw_indication);
+
+ if (fw_indication & FW_IND_HELPER)
+ ret = 0;
+
+ return ret;
+}
diff --git a/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h b/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h
index dfbbbc7d7ad9..391658b5091f 100644
--- a/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h
+++ b/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h
@@ -107,4 +107,5 @@ void target_register_tbl_attach(u32 target_type);
void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision);
void hif_set_fw_info(void *ol_sc, u32 target_fw_version);
+int hif_sdio_check_fw_reg(void * ol_sc);
#endif /* __IF_ATH_SDIO_H__*/