summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSameer Thalappil <sameert@qca.qualcomm.com>2014-02-05 20:42:02 -0800
committerAkash Patel <c_akashp@qca.qualcomm.com>2014-02-07 17:38:22 -0800
commitded58968277eea8bcdcf2eafb11198c6b7deb538 (patch)
treea216eeeb7310f60a2fd13ed874b2cbcb5aa7f342
parent84681c9150f591bdfda1f5ce7348b1cea5a29966 (diff)
qcacld: Silent recovery on FW dump failure
When host fails to collect dump on FW assert, there is no reason to put device to download mode when SSR level is set to system. So instead of going thru SSR framework, silently recover from this assert. Change-Id: Ib8af1d25b3d0a66004984e1ffdbedfa19c71f175 CRs-Fixed: 612268
-rw-r--r--CORE/SERVICES/BMI/ol_fw.c39
-rw-r--r--CORE/SERVICES/BMI/ol_fw.h4
-rw-r--r--CORE/SERVICES/HIF/PCIe/if_pci.c9
-rw-r--r--CORE/SERVICES/HIF/PCIe/if_pci.h2
4 files changed, 35 insertions, 19 deletions
diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c
index 29e55d563dc5..515bdc81a3bf 100644
--- a/CORE/SERVICES/BMI/ol_fw.c
+++ b/CORE/SERVICES/BMI/ol_fw.c
@@ -492,7 +492,7 @@ u_int32_t host_interest_item_address(u_int32_t target_type, u_int32_t item_offse
}
#if defined(QCA_WIFI_2_0) && !defined(QCA_WIFI_ISOC)
-void dump_CE_register(struct ol_softc *scn)
+int dump_CE_register(struct ol_softc *scn)
{
A_UINT32 CE_reg_address = CE7_LOCATION;
A_UINT32 CE_reg_values[CE_USEFUL_SIZE>>2];
@@ -504,13 +504,14 @@ void dump_CE_register(struct ol_softc *scn)
CE_reg_word_size * sizeof(A_UINT32)) != A_OK)
{
printk(KERN_ERR "Dumping CE register failed!\n");
- return;
+ return -EACCES;
}
printk("CE7 Register Dump:\n");
for (i = 0; i < CE_reg_word_size; i++) {
printk("[%02d] : 0x%08X\n", i, CE_reg_values[i]);
}
+ return EOK;
}
#endif
@@ -522,15 +523,21 @@ static void ramdump_work_handler(struct work_struct *ramdump)
void __iomem *ramdump_base;
unsigned long address;
unsigned long size;
+ int ret;
u_int32_t host_interest_address;
if (!ramdump_scn) {
printk("No RAM dump will be collected since ramdump_scn is NULL!\n");
- goto out;
+ goto out_fail;
}
- hif_pci_check_soc_status(ramdump_scn->hif_sc);
- dump_CE_register(ramdump_scn);
+ ret = hif_pci_check_soc_status(ramdump_scn->hif_sc);
+ if (ret)
+ goto out_fail;
+
+ ret = dump_CE_register(ramdump_scn);
+ if (ret)
+ goto out_fail;
if (HIFDiagReadMem(ramdump_scn->hif_hdl,
host_interest_item_address(ramdump_scn->target_type,
@@ -539,7 +546,7 @@ static void ramdump_work_handler(struct work_struct *ramdump)
printk(KERN_ERR "HifDiagReadiMem FW Dump Area Pointer failed!\n");
dump_CE_register(ramdump_scn);
- goto out;
+ goto out_fail;
}
printk("Host interest item address: 0x%08X\n", host_interest_address);
@@ -547,25 +554,30 @@ static void ramdump_work_handler(struct work_struct *ramdump)
if (cnss_get_ramdump_mem(&address, &size)) {
printk("No RAM dump will be collected since failed to get "
"memory address or size!\n");
- goto out;
+ goto out_fail;
}
ramdump_base = ioremap(address, size);
if (!ramdump_base) {
printk("No RAM dump will be collected since ramdump_base is NULL!\n");
- goto out;
+ goto out_fail;
}
- ol_target_coredump(ramdump_scn, ramdump_base, TOTAL_DUMP_SIZE);
+ ret = ol_target_coredump(ramdump_scn, ramdump_base, TOTAL_DUMP_SIZE);
iounmap(ramdump_base);
+ if (ret)
+ goto out_fail;
printk("%s: RAM dump collecting completed!\n", __func__);
msleep(250);
-
-out:
/* Notify SSR framework the target has crashed. */
cnss_device_crashed();
return;
+
+out_fail:
+ /* silent SSR on dump failure */
+ cnss_device_self_recovery();
+ return;
}
static DECLARE_WORK(ramdump_work, ramdump_work_handler);
@@ -1003,11 +1015,12 @@ int ol_diag_read(struct ol_softc *scn, u_int8_t *buffer,
*
* \return: None
* --------------------------------------------------------------------------*/
-void ol_target_coredump(void *inst, void *memoryBlock, u_int32_t blockLength)
+int ol_target_coredump(void *inst, void *memoryBlock, u_int32_t blockLength)
{
struct ol_softc *scn = (struct ol_softc *)inst;
char *bufferLoc = memoryBlock;
int result = 0;
+ int ret = 0;
u_int32_t amountRead = 0;
u_int32_t sectionCount = 0;
u_int32_t pos = 0;
@@ -1055,6 +1068,7 @@ void ol_target_coredump(void *inst, void *memoryBlock, u_int32_t blockLength)
} else {
printk(KERN_ERR "Could not read dump section!\n");
dump_CE_register(scn);
+ ret = -EACCES;
break; /* Could not read the section */
}
} else {
@@ -1062,6 +1076,7 @@ void ol_target_coredump(void *inst, void *memoryBlock, u_int32_t blockLength)
break; /* Insufficient room in buffer */
}
}
+ return ret;
}
#endif
diff --git a/CORE/SERVICES/BMI/ol_fw.h b/CORE/SERVICES/BMI/ol_fw.h
index 1b5f9f296269..f15e2d3b501f 100644
--- a/CORE/SERVICES/BMI/ol_fw.h
+++ b/CORE/SERVICES/BMI/ol_fw.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -68,7 +68,7 @@
#define TOTAL_DUMP_SIZE 0x00200000
#define PCIE_READ_LIMIT 0x00005000
-void ol_target_coredump(void *instance, void* memoryBlock,
+int ol_target_coredump(void *instance, void* memoryBlock,
u_int32_t blockLength);
int ol_diag_read(struct ol_softc *scn, u_int8_t* buffer,
u_int32_t pos, size_t count);
diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c
index 4b5e32bd863d..90b4ccab0b28 100644
--- a/CORE/SERVICES/HIF/PCIe/if_pci.c
+++ b/CORE/SERVICES/HIF/PCIe/if_pci.c
@@ -331,8 +331,8 @@ hif_pci_device_warm_reset(struct hif_pci_softc *sc)
}
-void
-hif_pci_check_soc_status(struct hif_pci_softc *sc)
+
+int hif_pci_check_soc_status(struct hif_pci_softc *sc)
{
u_int16_t device_id;
u_int32_t val;
@@ -342,7 +342,7 @@ hif_pci_check_soc_status(struct hif_pci_softc *sc)
pci_read_config_word(sc->pdev, PCI_DEVICE_ID, &device_id);
if(device_id != sc->devid) {
printk(KERN_ERR "PCIe link is down!\n");
- return;
+ return -EACCES;
}
/* Check PCIe local register for bar/memory access */
@@ -365,7 +365,7 @@ hif_pci_check_soc_status(struct hif_pci_softc *sc)
A_PCI_READ32(sc->mem + PCIE_LOCAL_BASE_ADDRESS +
RTC_STATE_ADDRESS), A_PCI_READ32(sc->mem +
PCIE_LOCAL_BASE_ADDRESS + PCIE_SOC_WAKE_ADDRESS));
- return;
+ return -EACCES;
}
A_PCI_WRITE32(sc->mem + PCIE_LOCAL_BASE_ADDRESS +
@@ -378,6 +378,7 @@ hif_pci_check_soc_status(struct hif_pci_softc *sc)
/* Check BAR + 0x10c register for SoC internal bus issues */
val = A_PCI_READ32(sc->mem + 0x10c);
printk("BAR + 0x10c is %08x\n", val);
+ return EOK;
}
/*
diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.h b/CORE/SERVICES/HIF/PCIe/if_pci.h
index ee3fb120c040..d3955f7f0e5a 100644
--- a/CORE/SERVICES/HIF/PCIe/if_pci.h
+++ b/CORE/SERVICES/HIF/PCIe/if_pci.h
@@ -121,7 +121,7 @@ extern int pktlogmod_init(void *context);
extern void pktlogmod_exit(void *context);
#endif
-void hif_pci_check_soc_status(struct hif_pci_softc *sc);
+int hif_pci_check_soc_status(struct hif_pci_softc *sc);
/*
* A firmware interrupt to the Host is indicated by the