From 3e7818919b4ab09a58b6c7a592fe1e999e54ee56 Mon Sep 17 00:00:00 2001 From: Manikandan Mohan Date: Fri, 19 Jun 2020 17:38:05 -0700 Subject: [PATCH] cnss2: Handle PCI register rw operation during crash shutdown During crash shutdown, system is in panic mode and all interrupts are disabled. Thus when doing CNSS pci register dump collection do not lock. Use spinlock during normal operation only. Change-Id: I82dc531e93c13aa583e8162b8dc7e8866f86c48b Signed-off-by: Manikandan Mohan --- drivers/net/wireless/cnss2/debug.c | 3 ++ drivers/net/wireless/cnss2/main.h | 1 + drivers/net/wireless/cnss2/pci.c | 46 +++++++++++++++++++++--------- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c index 290c58ecdbef..49b2348cb182 100644 --- a/drivers/net/wireless/cnss2/debug.c +++ b/drivers/net/wireless/cnss2/debug.c @@ -116,6 +116,9 @@ static int cnss_stats_show_state(struct seq_file *s, case CNSS_COLD_BOOT_CAL_DONE: seq_puts(s, "COLD_BOOT_CAL_DONE"); continue; + case CNSS_IN_PANIC: + seq_puts(s, "IN_PANIC"); + continue; } seq_printf(s, "UNKNOWN-%d", i); diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index 8d0a94092b19..9e1806c5bf10 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -238,6 +238,7 @@ enum cnss_driver_state { CNSS_IN_SUSPEND_RESUME = 15, CNSS_IN_REBOOT, CNSS_COLD_BOOT_CAL_DONE, + CNSS_IN_PANIC, }; struct cnss_recovery_data { diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index b9450154b6dd..fc88393c7eb7 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -422,6 +422,7 @@ static int cnss_pci_reg_read(struct cnss_pci_data *pci_priv, u32 offset, u32 *val) { int ret; + struct cnss_plat_data *plat_priv = pci_priv->plat_priv; if (!in_interrupt() && !irqs_disabled()) { ret = cnss_pci_check_link_status(pci_priv); @@ -435,12 +436,21 @@ static int cnss_pci_reg_read(struct cnss_pci_data *pci_priv, return 0; } - spin_lock_bh(&pci_reg_window_lock); - cnss_pci_select_window(pci_priv, offset); - - *val = readl_relaxed(pci_priv->bar + WINDOW_START + - (offset & WINDOW_RANGE_MASK)); - spin_unlock_bh(&pci_reg_window_lock); + /* If in panic, assumption is kernel panic handler will hold all threads + * and interrupts. Further pci_reg_window_lock could be held before + * panic. So only lock during normal operation. + */ + if (test_bit(CNSS_IN_PANIC, &plat_priv->driver_state)) { + cnss_pci_select_window(pci_priv, offset); + *val = readl_relaxed(pci_priv->bar + WINDOW_START + + (offset & WINDOW_RANGE_MASK)); + } else { + spin_lock_bh(&pci_reg_window_lock); + cnss_pci_select_window(pci_priv, offset); + *val = readl_relaxed(pci_priv->bar + WINDOW_START + + (offset & WINDOW_RANGE_MASK)); + spin_unlock_bh(&pci_reg_window_lock); + } return 0; } @@ -449,6 +459,7 @@ static int cnss_pci_reg_write(struct cnss_pci_data *pci_priv, u32 offset, u32 val) { int ret; + struct cnss_plat_data *plat_priv = pci_priv->plat_priv; if (!in_interrupt() && !irqs_disabled()) { ret = cnss_pci_check_link_status(pci_priv); @@ -462,12 +473,18 @@ static int cnss_pci_reg_write(struct cnss_pci_data *pci_priv, u32 offset, return 0; } - spin_lock_bh(&pci_reg_window_lock); - cnss_pci_select_window(pci_priv, offset); - - writel_relaxed(val, pci_priv->bar + WINDOW_START + - (offset & WINDOW_RANGE_MASK)); - spin_unlock_bh(&pci_reg_window_lock); + /* Same constraint as PCI register read in panic */ + if (test_bit(CNSS_IN_PANIC, &plat_priv->driver_state)) { + cnss_pci_select_window(pci_priv, offset); + writel_relaxed(val, pci_priv->bar + WINDOW_START + + (offset & WINDOW_RANGE_MASK)); + } else { + spin_lock_bh(&pci_reg_window_lock); + cnss_pci_select_window(pci_priv, offset); + writel_relaxed(val, pci_priv->bar + WINDOW_START + + (offset & WINDOW_RANGE_MASK)); + spin_unlock_bh(&pci_reg_window_lock); + } return 0; } @@ -1922,10 +1939,12 @@ static void cnss_qca6290_crash_shutdown(struct cnss_pci_data *pci_priv) { struct cnss_plat_data *plat_priv = pci_priv->plat_priv; + set_bit(CNSS_IN_PANIC, &plat_priv->driver_state); cnss_pr_dbg("Crash shutdown with driver_state 0x%lx\n", plat_priv->driver_state); cnss_pci_collect_dump_info(pci_priv, true); + clear_bit(CNSS_IN_PANIC, &plat_priv->driver_state); } static int cnss_qca6290_ramdump(struct cnss_pci_data *pci_priv) @@ -3989,7 +4008,8 @@ void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic) struct cnss_fw_mem *fw_mem = plat_priv->fw_mem; int ret, i, j; - if (test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state)) + if (test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state) && + !test_bit(CNSS_IN_PANIC, &plat_priv->driver_state)) cnss_pci_send_hang_event(pci_priv); if (test_bit(CNSS_MHI_RDDM_DONE, &pci_priv->mhi_state)) {