summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Lin <seanlin@qca.qualcomm.com>2014-06-11 16:41:23 +0800
committerAkash Patel <c_akashp@qca.qualcomm.com>2014-06-23 18:20:05 -0700
commite2f210d0cd5ed22aa9bd4f5689de120121204613 (patch)
tree03296ebc50610fc21ccf5e3820bc1c276d139855
parente5eed42828f905b8945f15621353727269fb4b68 (diff)
qcacld: HIF: complete firmware stack dump feature for usb interface.
Dump host driver version, target firmware version and target firmware stack once occurring firmware crash for usb interface. Change-Id: Ic55030642b5f7eea165c7438a197a2aa52be70f2 CRs-fixed: 678611
-rwxr-xr-xCORE/HDD/src/wlan_hdd_main.c7
-rw-r--r--CORE/SERVICES/COMMON/ol_if_athvar.h1
-rw-r--r--CORE/SERVICES/HIF/PCIe/if_pci.c7
-rw-r--r--CORE/SERVICES/HIF/PCIe/if_pci.h19
-rw-r--r--CORE/SERVICES/HIF/USB/if_usb.c7
-rw-r--r--CORE/SERVICES/HIF/USB/if_usb.h18
-rw-r--r--CORE/SERVICES/HIF/USB/usbdrv.c44
-rw-r--r--CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c7
-rw-r--r--CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h1
9 files changed, 86 insertions, 25 deletions
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index 2ad602b2f4de..4d3ee691eb7a 100755
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -276,10 +276,6 @@ static int hdd_parse_reassoc_command_v1_data(const tANI_U8 *pValue,
#if defined (QCA_WIFI_2_0) && \
!defined (QCA_WIFI_ISOC)
struct completion wlan_start_comp;
-extern void hif_init_adf_ctx(adf_os_device_t adf_ctx, v_VOID_t *hif_sc);
-extern int hif_register_driver(void);
-extern void hif_unregister_driver(void);
-extern void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision);
#ifdef QCA_WIFI_FTM
extern int hdd_ftm_start(hdd_context_t *pHddCtx);
extern int hdd_ftm_stop(hdd_context_t *pHddCtx);
@@ -11704,6 +11700,9 @@ int hdd_wlan_startup(struct device *dev, v_VOID_t *hif_sc)
/* Get the wlan hw/fw version */
hdd_wlan_get_version(pAdapter, NULL, NULL);
+
+ /* pass target_fw_version to HIF layer */
+ hif_set_fw_info(hif_sc, pHddCtx->target_fw_version);
#else
/* Exchange capability info between Host and FW and also get versioning info from FW */
hdd_exchange_version_and_caps(pHddCtx);
diff --git a/CORE/SERVICES/COMMON/ol_if_athvar.h b/CORE/SERVICES/COMMON/ol_if_athvar.h
index 6518adc7cf0e..e5993250431b 100644
--- a/CORE/SERVICES/COMMON/ol_if_athvar.h
+++ b/CORE/SERVICES/COMMON/ol_if_athvar.h
@@ -132,6 +132,7 @@ struct ol_softc {
struct ol_ath_stats pkt_stats;
u_int32_t target_type; /* A_TARGET_TYPE_* */
+ u_int32_t target_fw_version;
u_int32_t target_version;
u_int32_t target_revision;
u_int8_t crm_version_string[64]; /* store pHalStartRsp->startRspParams.wcnssCrmVersionString */
diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.c b/CORE/SERVICES/HIF/PCIe/if_pci.c
index 713e808e5263..50e2f94e829a 100644
--- a/CORE/SERVICES/HIF/PCIe/if_pci.c
+++ b/CORE/SERVICES/HIF/PCIe/if_pci.c
@@ -1987,6 +1987,7 @@ void hif_unregister_driver(void)
#endif
}
+/* Function to set the TXRX handle in the ol_sc context */
void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle)
{
struct ol_softc *sc = (struct ol_softc *)ol_sc;
@@ -2011,6 +2012,7 @@ void hif_disable_isr(void *ol_sc)
tasklet_kill(&hif_sc->intr_tq);
}
+/* Function to reset SoC */
void hif_reset_soc(void *ol_sc)
{
struct ol_softc *scn = (struct ol_softc *)ol_sc;
@@ -2070,3 +2072,8 @@ void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision)
*version = ((struct ol_softc *)ol_sc)->target_version;
*revision = ((struct ol_softc *)ol_sc)->target_revision;
}
+
+void hif_set_fw_info(void *ol_sc, u32 target_fw_version)
+{
+ ((struct ol_softc *)ol_sc)->target_fw_version = target_fw_version;
+}
diff --git a/CORE/SERVICES/HIF/PCIe/if_pci.h b/CORE/SERVICES/HIF/PCIe/if_pci.h
index 657a0e32e414..899686081460 100644
--- a/CORE/SERVICES/HIF/PCIe/if_pci.h
+++ b/CORE/SERVICES/HIF/PCIe/if_pci.h
@@ -111,19 +111,9 @@ irqreturn_t HIF_fw_interrupt_handler(int irq, void *arg);
*/
adf_os_size_t initBufferCount(adf_os_size_t maxSize);
-/* Function to set the TXRX handle in the ol_sc context */
-void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle);
-void hif_disable_isr(void *ol_sc);
-
-/* Function to reset SoC */
-void hif_reset_soc(void *ol_sc);
-
/* Function to disable ASPM */
void hif_disable_aspm(void);
-void hif_init_adf_ctx(adf_os_device_t adf_dev, void *ol_sc);
-void hif_deinit_adf_ctx(void *ol_sc);
-
void hif_pci_save_htc_htt_config_endpoint(int htc_endpoint);
#ifndef REMOVE_PKT_LOG
@@ -135,7 +125,16 @@ int hif_pci_check_fw_reg(struct hif_pci_softc *sc);
int hif_pci_check_soc_status(struct hif_pci_softc *sc);
void dump_CE_debug_register(struct hif_pci_softc *sc);
+/*These functions are exposed to HDD*/
+int hif_register_driver(void);
+void hif_unregister_driver(void);
+void hif_init_adf_ctx(adf_os_device_t adf_dev, void *ol_sc);
+void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle);
+void hif_disable_isr(void *ol_sc);
+void hif_reset_soc(void *ol_sc);
+void hif_deinit_adf_ctx(void *ol_sc);
void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision);
+void hif_set_fw_info(void *ol_sc, u32 target_fw_version);
/*
* A firmware interrupt to the Host is indicated by the
diff --git a/CORE/SERVICES/HIF/USB/if_usb.c b/CORE/SERVICES/HIF/USB/if_usb.c
index 48be9e824d67..b86156059535 100644
--- a/CORE/SERVICES/HIF/USB/if_usb.c
+++ b/CORE/SERVICES/HIF/USB/if_usb.c
@@ -445,6 +445,7 @@ void hif_unregister_driver(void)
}
}
+/* Function to set the TXRX handle in the ol_sc context */
void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle)
{
struct ol_softc *sc = (struct ol_softc *)ol_sc;
@@ -456,6 +457,7 @@ void hif_disable_isr(void *ol_sc)
/* TODO */
}
+/* Function to reset SoC */
void hif_reset_soc(void *ol_sc)
{
/* TODO */
@@ -467,4 +469,9 @@ void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision)
/* Chip version should be supported, set to 0 for now */
*revision = 0;
}
+
+void hif_set_fw_info(void *ol_sc, u32 target_fw_version)
+{
+ ((struct ol_softc *)ol_sc)->target_fw_version = target_fw_version;
+}
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/CORE/SERVICES/HIF/USB/if_usb.h b/CORE/SERVICES/HIF/USB/if_usb.h
index 27fa2cd2f55d..a197f6238b2f 100644
--- a/CORE/SERVICES/HIF/USB/if_usb.h
+++ b/CORE/SERVICES/HIF/USB/if_usb.h
@@ -89,18 +89,20 @@ static inline int athdiag_procfs_init(void *scn) { return 0; }
static inline void athdiag_procfs_remove(void) { return; }
#endif
-/* Function to set the TXRX handle in the ol_sc context */
-void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle);
-void hif_disable_isr(void *ol_sc);
-void hif_reset_soc(void *ol_sc);
-void hif_init_adf_ctx(adf_os_device_t adf_dev, void *ol_sc);
-void hif_deinit_adf_ctx(void *ol_sc);
-
#ifndef REMOVE_PKT_LOG
extern int pktlogmod_init(void *context);
extern void pktlogmod_exit(void *context);
#endif
-void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision);
+/*These functions are exposed to HDD*/
+int hif_register_driver(void);
+void hif_unregister_driver(void);
+void hif_init_adf_ctx(adf_os_device_t adf_dev, void *ol_sc);
+void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle);
+void hif_disable_isr(void *ol_sc);
+void hif_reset_soc(void *ol_sc);
+void hif_deinit_adf_ctx(void *ol_sc);
+void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision);
+void hif_set_fw_info(void *ol_sc, u32 target_fw_version);
#endif /* __ATH_USB_H__ */
diff --git a/CORE/SERVICES/HIF/USB/usbdrv.c b/CORE/SERVICES/HIF/USB/usbdrv.c
index 986c88f8ef35..4de4ff6a7319 100644
--- a/CORE/SERVICES/HIF/USB/usbdrv.c
+++ b/CORE/SERVICES/HIF/USB/usbdrv.c
@@ -39,6 +39,8 @@
#include "a_usb_defs.h"
#include "htc.h"
#include "htc_packet.h"
+#include "qwlan_version.h"
+#include "if_usb.h"
#define IS_BULK_EP(attr) (((attr) & 3) == 0x02)
#define IS_INT_EP(attr) (((attr) & 3) == 0x03)
@@ -978,6 +980,11 @@ void usb_hif_io_comp_work(struct work_struct *work)
A_UINT32 *reg;
A_UINT32 len, i;
static A_UINT32 assert_pattern = 0x0000c600;
+ static A_UINT32 reg_pattern = 0x0000d600;
+ static A_UINT32 regend_pattern = 0x0000e600;
+ A_UINT32 start_addr = 0;
+ static A_UINT32 stack_dumping = 0;
+ A_UINT32 MSPId = 0, mSPId = 0, SIId = 0, CRMId = 0;
AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+%s\n", __func__));
device = pipe->device;
@@ -1007,10 +1014,41 @@ void usb_hif_io_comp_work(struct work_struct *work)
buf));
adf_nbuf_peek_header(buf, &data, &len);
if (!memcmp(data, &assert_pattern, sizeof(assert_pattern))) {
- printk("Firmware crash detected... len %d\n", len);
+ MSPId = (device->sc->ol_sc->target_fw_version & 0xf0000000) >> 28;
+ mSPId = (device->sc->ol_sc->target_fw_version & 0xf000000) >> 24;
+ SIId = (device->sc->ol_sc->target_fw_version & 0xf00000) >> 20;
+ CRMId = device->sc->ol_sc->target_fw_version & 0x7fff;
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Firmware crash detected...\n"));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Host SW version: %s\n", QWLAN_VERSIONSTR));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("FW version: %d.%d.%d.%d", MSPId, mSPId, SIId, CRMId));
reg = (A_UINT32 *) (data+4);
- for (i = 0; i < 60; i++, reg++) {
- printk("[%02d] : 0x%08X\n", i, *reg);
+ for (i = 0; i < 60; reg++, i++ ) {
+ if (i%4 == 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("\n"));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("%2d: ", i));
+ }
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("0x%08x ", *reg));
+ }
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("\n"));
+ dev_kfree_skb(buf);
+ } else if (!memcmp(data, &reg_pattern, sizeof(reg_pattern))) {
+ reg = (A_UINT32 *) (data+4);
+ start_addr = *reg++;
+ if(stack_dumping == 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Firmware stack dump:"));
+ stack_dumping = 1;
+ }
+ for (i = 0; i < (len>>2)-2; reg++, i++ ) {
+ if (*reg == regend_pattern && (i == (len>>2)-3)) {
+ stack_dumping = 0;
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("\n"));
+ break;
+ }
+ if (i%4 == 0) {
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("\n"));
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("0x%08X: ", start_addr + (i << 2)));
+ }
+ AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("0x%08X ", *reg));
}
dev_kfree_skb(buf);
} else {
diff --git a/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c b/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c
index 9484cd060abc..9f674a066066 100644
--- a/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c
+++ b/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.c
@@ -296,6 +296,7 @@ void hif_deinit_adf_ctx(void *ol_sc)
sc->adf_dev = NULL;
}
+/* Function to set the TXRX handle in the ol_sc context */
void hif_init_pdev_txrx_handle(void *ol_sc, void *txrx_handle)
{
struct ol_softc *sc = (struct ol_softc *)ol_sc;
@@ -321,6 +322,7 @@ HIFCancelDeferredTargetSleep(HIF_DEVICE *hif_device)
}
+/* Function to reset SoC */
void hif_reset_soc(void *ol_sc)
{
ENTER("- dummy function!");
@@ -332,3 +334,8 @@ void hif_get_hw_info(void *ol_sc, u32 *version, u32 *revision)
/* Chip revision should be supported, set to 0 for now */
*revision = 0;
}
+
+void hif_set_fw_info(void *ol_sc, u32 target_fw_version)
+{
+ ((struct ol_softc *)ol_sc)->target_fw_version = target_fw_version;
+}
diff --git a/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h b/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h
index d4847cc8b076..d326a919882e 100644
--- a/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h
+++ b/CORE/SERVICES/HIF/sdio/linux/if_ath_sdio.h
@@ -98,5 +98,6 @@ void hif_register_tbl_attach(u32 hif_type);
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);
#endif /* __IF_ATH_SDIO_H__*/