diff options
| author | Yue Ma <yuem@qca.qualcomm.com> | 2014-02-10 17:55:22 -0800 |
|---|---|---|
| committer | Akash Patel <c_akashp@qca.qualcomm.com> | 2014-02-12 19:20:36 -0800 |
| commit | 63d1786452bf80570b478a9b5ec276dc5064a48c (patch) | |
| tree | 9490590a3319f994527353f0b5a83867b81c8c50 | |
| parent | a06219fb808bca7976f3e2063ecd722d64a77170 (diff) | |
qcacld: Add SSR crash shutdown API
Add the SSR crash shutdown API in order to support collect target RAM
dump when kernel panic happens or other subsystems crash.
Change-Id: Ibe97baee5e1d782ecdc173a2f8d4dc9e841a2a37
CRs-Fixed: 609070
| -rw-r--r-- | CORE/SERVICES/BMI/ol_fw.c | 69 | ||||
| -rw-r--r-- | CORE/SERVICES/BMI/ol_fw.h | 3 | ||||
| -rw-r--r-- | CORE/SERVICES/COMMON/ol_if_athvar.h | 2 | ||||
| -rw-r--r-- | CORE/SERVICES/HIF/PCIe/if_pci.c | 37 |
4 files changed, 89 insertions, 22 deletions
diff --git a/CORE/SERVICES/BMI/ol_fw.c b/CORE/SERVICES/BMI/ol_fw.c index 4f5534af58b8..26e2ed4f154c 100644 --- a/CORE/SERVICES/BMI/ol_fw.c +++ b/CORE/SERVICES/BMI/ol_fw.c @@ -529,12 +529,35 @@ int dump_CE_register(struct ol_softc *scn) #if defined(QCA_WIFI_2_0) && !defined(QCA_WIFI_ISOC) && defined(CONFIG_CNSS) static struct ol_softc *ramdump_scn; -static void ramdump_work_handler(struct work_struct *ramdump) +int ol_copy_ramdump(struct ol_softc *scn) { void __iomem *ramdump_base; unsigned long address; unsigned long size; int ret; + + /* Get RAM dump memory address and size */ + if (cnss_get_ramdump_mem(&address, &size)) { + printk("No RAM dump will be collected since failed to get " + "memory address or size!\n"); + ret = -EACCES; + } + + ramdump_base = ioremap(address, size); + if (!ramdump_base) { + printk("No RAM dump will be collected since ramdump_base is NULL!\n"); + ret = -EACCES; + } + + ret = ol_target_coredump(scn, ramdump_base, TOTAL_DUMP_SIZE); + iounmap(ramdump_base); + + return ret; +} + +static void ramdump_work_handler(struct work_struct *ramdump) +{ + int ret; u_int32_t host_interest_address; if (!ramdump_scn) { @@ -542,6 +565,21 @@ static void ramdump_work_handler(struct work_struct *ramdump) goto out_fail; } + if (ramdump_scn->crash_shutdown) { + if (hif_pci_check_soc_status(ramdump_scn->hif_sc)) + goto out; + + if (ol_copy_ramdump(ramdump_scn)) + goto out; + + printk("%s: RAM dump collecting completed!\n", __func__); + +out: + ramdump_scn->crash_shutdown = false; + complete(&ramdump_scn->ramdump_event); + return; + } + #ifdef DEBUG ret = hif_pci_check_soc_status(ramdump_scn->hif_sc); if (ret) @@ -566,32 +604,18 @@ static void ramdump_work_handler(struct work_struct *ramdump) } printk("Host interest item address: 0x%08x\n", host_interest_address); - /* Get RAM dump memory address and size */ - 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_fail; - } - - ramdump_base = ioremap(address, size); - if (!ramdump_base) { - printk("No RAM dump will be collected since ramdump_base is NULL!\n"); - goto out_fail; - } - - ret = ol_target_coredump(ramdump_scn, ramdump_base, TOTAL_DUMP_SIZE); - iounmap(ramdump_base); - if (ret) + if (ol_copy_ramdump(ramdump_scn)) goto out_fail; printk("%s: RAM dump collecting completed!\n", __func__); msleep(250); + /* Notify SSR framework the target has crashed. */ cnss_device_crashed(); return; out_fail: - /* silent SSR on dump failure */ + /* Silent SSR on dump failure */ #ifdef CNSS_SELF_RECOVERY cnss_device_self_recovery(); #else @@ -602,7 +626,7 @@ out_fail: static DECLARE_WORK(ramdump_work, ramdump_work_handler); -void schedule_ramdump_work(struct ol_softc *scn) +void ol_schedule_ramdump_work(struct ol_softc *scn) { ramdump_scn = scn; schedule_work(&ramdump_work); @@ -633,7 +657,10 @@ void ol_target_failure(void *instance, A_STATUS status) return; } - printk("XXX TARGET ASSERTED XXX\n"); + if (scn->crash_shutdown) + printk("XXX TARGET ASSERTED because of Kernel Panic XXX\n"); + else + printk("XXX TARGET ASSERTED XXX\n"); scn->target_status = OL_TRGET_STATUS_RESET; #if defined(QCA_WIFI_2_0) && !defined(QCA_WIFI_ISOC) @@ -719,7 +746,7 @@ void ol_target_failure(void *instance, A_STATUS status) #if defined(QCA_WIFI_2_0) && !defined(QCA_WIFI_ISOC) && defined(CONFIG_CNSS) /* Collect the RAM dump through a workqueue */ - schedule_ramdump_work(scn); + ol_schedule_ramdump_work(scn); #endif return; diff --git a/CORE/SERVICES/BMI/ol_fw.h b/CORE/SERVICES/BMI/ol_fw.h index 4b81a01005ab..bfd4b3e5ee5c 100644 --- a/CORE/SERVICES/BMI/ol_fw.h +++ b/CORE/SERVICES/BMI/ol_fw.h @@ -72,7 +72,8 @@ 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); -void schedule_ramdump_work(struct ol_softc *scn); +void ol_schedule_ramdump_work(struct ol_softc *scn); +int ol_copy_ramdump(struct ol_softc *scn); #endif int ol_download_firmware(struct ol_softc *scn); int ol_configure_target(struct ol_softc *scn); diff --git a/CORE/SERVICES/COMMON/ol_if_athvar.h b/CORE/SERVICES/COMMON/ol_if_athvar.h index 0b8d4c6d490c..a6495ea58b7b 100644 --- a/CORE/SERVICES/COMMON/ol_if_athvar.h +++ b/CORE/SERVICES/COMMON/ol_if_athvar.h @@ -206,6 +206,8 @@ struct ol_softc { u_int32_t set_ht_vht_ies:1; /* true if vht ies are set on target */ bool scn_cwmenable; /*CWM enable/disable state*/ u_int8_t max_no_of_peers; + struct completion ramdump_event; + bool crash_shutdown; }; #ifdef PERE_IP_HDR_ALIGNMENT_WAR diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c index 90e1f71ed4fb..bbe206bd6c09 100644 --- a/CORE/SERVICES/HIF/PCIe/if_pci.c +++ b/CORE/SERVICES/HIF/PCIe/if_pci.c @@ -70,6 +70,7 @@ #define MAX_NUM_OF_RECEIVES 1000 /* Maximum number of Rx buf to process before break out */ #define PCIE_WAKE_TIMEOUT 1000 /* Maximum ms timeout for host to wake up target */ +#define RAMDUMP_EVENT_TIMEOUT 2500 unsigned int msienable = 0; module_param(msienable, int, 0644); @@ -780,6 +781,7 @@ again: adf_os_atomic_init(&sc->tasklet_from_intr); init_waitqueue_head(&ol_sc->sc_osdev->event_queue); + init_completion(&ol_sc->ramdump_event); ret = hdd_wlan_startup(&pdev->dev, ol_sc); @@ -1078,7 +1080,9 @@ again: ol_sc->enablesinglebinary = FALSE; ol_sc->max_no_of_peers = 1; + adf_os_atomic_init(&sc->tasklet_from_intr); init_waitqueue_head(&ol_sc->sc_osdev->event_queue); + init_completion(&ol_sc->ramdump_event); if (VOS_STATUS_SUCCESS == hdd_wlan_re_init(ol_sc)) { ret = 0; @@ -1487,6 +1491,38 @@ void hif_pci_shutdown(struct pci_dev *pdev) printk("%s: WLAN host driver shutting down completed!\n", __func__); } + +void hif_pci_crash_shutdown(struct pci_dev *pdev) +{ + struct hif_pci_softc *sc; + struct ol_softc *scn; + int status; + + sc = pci_get_drvdata(pdev); + if (!sc) + return; + + scn = sc->ol_sc; + if (!scn) + return; + + if (OL_TRGET_STATUS_RESET == scn->target_status) { + printk("%s: Target is already asserted, ignore!\n", __func__); + return; + } + + scn->crash_shutdown = true; + process_wma_set_command(0,(int)GEN_PARAM_CRASH_INJECT, + 0, GEN_CMD); + + status = wait_for_completion_interruptible_timeout( + &scn->ramdump_event, + msecs_to_jiffies(RAMDUMP_EVENT_TIMEOUT)); + if (!status) { + printk("%s: RAM dump collecting timeout!\n", __func__); + return; + } +} #endif #define OL_ATH_PCI_PM_CONTROL 0x44 @@ -1609,6 +1645,7 @@ struct cnss_wlan_driver cnss_wlan_drv_id = { .remove = hif_pci_remove, .reinit = hif_pci_reinit, .shutdown = hif_pci_shutdown, + .crash_shutdown = hif_pci_crash_shutdown, #ifdef ATH_BUS_PM .suspend = hif_pci_suspend, .resume = hif_pci_resume, |
