Commit 6250aac6 authored by Kalle Valo's avatar Kalle Valo

ath6kl: print firmware crashes always

Currently firmware crash dump is printed only if debug is enabled.
Change it so that the crash dump is always printed.

Also move the code from init.c to hif.c.
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 68469341
...@@ -654,7 +654,6 @@ void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid); ...@@ -654,7 +654,6 @@ void aggr_recv_delba_req_evt(struct ath6kl_vif *vif, u8 tid);
void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no, void aggr_recv_addba_req_evt(struct ath6kl_vif *vif, u8 tid, u16 seq_no,
u8 win_sz); u8 win_sz);
void ath6kl_wakeup_event(void *dev); void ath6kl_wakeup_event(void *dev);
void ath6kl_target_failure(struct ath6kl *ar);
void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
bool wait_fot_compltn, bool cold_reset); bool wait_fot_compltn, bool cold_reset);
......
...@@ -59,26 +59,79 @@ int ath6kl_hif_rw_comp_handler(void *context, int status) ...@@ -59,26 +59,79 @@ int ath6kl_hif_rw_comp_handler(void *context, int status)
return 0; return 0;
} }
#define REG_DUMP_COUNT_AR6003 60
#define REGISTER_DUMP_LEN_MAX 60
static void ath6kl_hif_dump_fw_crash(struct ath6kl *ar)
{
__le32 regdump_val[REGISTER_DUMP_LEN_MAX];
u32 i, address, regdump_addr = 0;
int ret;
if (ar->target_type != TARGET_TYPE_AR6003)
return;
/* the reg dump pointer is copied to the host interest area */
address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
address = TARG_VTOP(ar->target_type, address);
/* read RAM location through diagnostic window */
ret = ath6kl_diag_read32(ar, address, &regdump_addr);
if (ret || !regdump_addr) {
ath6kl_warn("failed to get ptr to register dump area: %d\n",
ret);
return;
}
ath6kl_dbg(ATH6KL_DBG_IRQ, "register dump data address 0x%x\n",
regdump_addr);
regdump_addr = TARG_VTOP(ar->target_type, regdump_addr);
/* fetch register dump data */
ret = ath6kl_diag_read(ar, regdump_addr, (u8 *)&regdump_val[0],
REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
if (ret) {
ath6kl_warn("failed to get register dump: %d\n", ret);
return;
}
ath6kl_info("crash dump:\n");
ath6kl_info("hw 0x%x fw %s\n", ar->wiphy->hw_version,
ar->wiphy->fw_version);
BUILD_BUG_ON(REG_DUMP_COUNT_AR6003 % 4);
for (i = 0; i < REG_DUMP_COUNT_AR6003 / 4; i++) {
ath6kl_info("%d: 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
4 * i,
le32_to_cpu(regdump_val[i]),
le32_to_cpu(regdump_val[i + 1]),
le32_to_cpu(regdump_val[i + 2]),
le32_to_cpu(regdump_val[i + 3]));
}
}
static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev) static int ath6kl_hif_proc_dbg_intr(struct ath6kl_device *dev)
{ {
u32 dummy; u32 dummy;
int status; int ret;
ath6kl_err("target debug interrupt\n"); ath6kl_warn("firmware crashed\n");
ath6kl_target_failure(dev->ar);
/* /*
* read counter to clear the interrupt, the debug error interrupt is * read counter to clear the interrupt, the debug error interrupt is
* counter 0. * counter 0.
*/ */
status = hif_read_write_sync(dev->ar, COUNT_DEC_ADDRESS, ret = hif_read_write_sync(dev->ar, COUNT_DEC_ADDRESS,
(u8 *)&dummy, 4, HIF_RD_SYNC_BYTE_INC); (u8 *)&dummy, 4, HIF_RD_SYNC_BYTE_INC);
if (status) if (ret)
WARN_ON(1); ath6kl_warn("Failed to clear debug interrupt: %d\n", ret);
return status; ath6kl_hif_dump_fw_crash(dev->ar);
return ret;
} }
/* mailbox recv message polling */ /* mailbox recv message polling */
......
...@@ -298,61 +298,6 @@ static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val, ...@@ -298,61 +298,6 @@ static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
return status; return status;
} }
#define REG_DUMP_COUNT_AR6003 60
#define REGISTER_DUMP_LEN_MAX 60
static void ath6kl_dump_target_assert_info(struct ath6kl *ar)
{
u32 address;
u32 regdump_loc = 0;
int status;
u32 regdump_val[REGISTER_DUMP_LEN_MAX];
u32 i;
if (ar->target_type != TARGET_TYPE_AR6003)
return;
/* the reg dump pointer is copied to the host interest area */
address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
address = TARG_VTOP(ar->target_type, address);
/* read RAM location through diagnostic window */
status = ath6kl_diag_read32(ar, address, &regdump_loc);
if (status || !regdump_loc) {
ath6kl_err("failed to get ptr to register dump area\n");
return;
}
ath6kl_dbg(ATH6KL_DBG_TRC, "location of register dump data: 0x%X\n",
regdump_loc);
regdump_loc = TARG_VTOP(ar->target_type, regdump_loc);
/* fetch register dump data */
status = ath6kl_diag_read(ar, regdump_loc, (u8 *)&regdump_val[0],
REG_DUMP_COUNT_AR6003 * (sizeof(u32)));
if (status) {
ath6kl_err("failed to get register dump\n");
return;
}
ath6kl_dbg(ATH6KL_DBG_TRC, "Register Dump:\n");
for (i = 0; i < REG_DUMP_COUNT_AR6003; i++)
ath6kl_dbg(ATH6KL_DBG_TRC, " %d : 0x%8.8X\n",
i, regdump_val[i]);
}
void ath6kl_target_failure(struct ath6kl *ar)
{
ath6kl_err("target asserted\n");
/* try dumping target assertion information (if any) */
ath6kl_dump_target_assert_info(ar);
}
static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx)
{ {
int status = 0; int status = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment