From 05f7adbb9d9d37ba39058942d87d62941c733cd1 Mon Sep 17 00:00:00 2001 From: Maya Erez Date: Sun, 30 Oct 2016 21:38:14 +0200 Subject: [PATCH] wil6210: prevent XTAL off in device bootloader Device bootloader enters deep sleep and turns off its clock after 1 second of inactivity. Waking up from this stage takes several milliseconds and can cause PCIe timeout. To prevent that, we need to add HALP vote in the reset flow which will prevent the BL from turning off its XTAL. Change-Id: Id9273e546d3565935a7b1150c27993f02c5734e3 Signed-off-by: Maya Erez --- drivers/net/wireless/ath/wil6210/interrupt.c | 4 ++-- drivers/net/wireless/ath/wil6210/main.c | 30 ++++++++++++++++++++++++---- drivers/net/wireless/ath/wil6210/wil6210.h | 3 +++ 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 64046e0bd0a2..c3853a63b083 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -141,7 +141,7 @@ static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp) unmask_halp ? WIL6210_IMC_MISC : WIL6210_IMC_MISC_NO_HALP); } -static void wil6210_unmask_halp(struct wil6210_priv *wil) +void wil6210_unmask_halp(struct wil6210_priv *wil) { wil_dbg_irq(wil, "%s()\n", __func__); @@ -149,7 +149,7 @@ static void wil6210_unmask_halp(struct wil6210_priv *wil) BIT_DMA_EP_MISC_ICR_HALP); } -static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) +void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) { wil_dbg_irq(wil, "%s()\n", __func__); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 5285ebc8b9af..94e5b67abd59 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -875,19 +875,29 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) flush_workqueue(wil->wq_service); flush_workqueue(wil->wmi_wq); + wil6210_unmask_irq_pseudo(wil); + wil6210_unmask_halp(wil); + wil_halp_vote(wil); + wil_bl_crash_info(wil, false); rc = wil_target_reset(wil); + /* wil_target_reset clears the HALP IRQ, need to set it again. + * Call wil_halp_unvote to clear the HALP reference counter + * and unmask the HALP interrupt before setting it again + */ + wil_halp_unvote(wil); + wil_halp_vote(wil); wil_rx_fini(wil); if (rc) { wil_bl_crash_info(wil, true); - return rc; + goto out; } rc = wil_get_bl_info(wil); if (rc == -EAGAIN && !load_fw) /* ignore RF error if not going up */ rc = 0; if (rc) - return rc; + goto out; wil_set_oob_mode(wil, oob_mode); if (load_fw) { @@ -899,14 +909,19 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) /* Loading f/w from the file */ rc = wil_request_firmware(wil, WIL_FW_NAME, true); if (rc) - return rc; + goto out; rc = wil_request_firmware(wil, WIL_FW2_NAME, true); if (rc) - return rc; + goto out; /* Mark FW as loaded from host */ wil_s(wil, RGF_USER_USAGE_6, 1); + /* Clear the HALP while in BL, before clearing all the IRQs + * and running the FW. + */ + wil_halp_unvote(wil); + /* clear any interrupts which on-card-firmware * may have set */ @@ -917,6 +932,9 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) wil_w(wil, RGF_CAF_ICR + offsetof(struct RGF_ICR, IMV), ~0); wil_release_cpu(wil); + } else { + /* Allow XTAL off when going down */ + wil_halp_unvote(wil); } /* init after reset */ @@ -955,6 +973,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) } return rc; + +out: + wil_halp_unvote(wil); + return rc; } void wil_fw_error_recovery(struct wil6210_priv *wil) diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index a19dba5b9e5f..8961b4ce4898 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -837,6 +837,7 @@ void wil_configure_interrupt_moderation(struct wil6210_priv *wil); void wil_disable_irq(struct wil6210_priv *wil); void wil_enable_irq(struct wil6210_priv *wil); void wil6210_mask_halp(struct wil6210_priv *wil); +void wil6210_unmask_halp(struct wil6210_priv *wil); /* P2P */ bool wil_p2p_is_social_scan(struct cfg80211_scan_request *request); @@ -902,6 +903,8 @@ void wil6210_unmask_irq_tx(struct wil6210_priv *wil); void wil_rx_handle(struct wil6210_priv *wil, int *quota); void wil6210_unmask_irq_rx(struct wil6210_priv *wil); +void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil); + int wil_iftype_nl2wmi(enum nl80211_iftype type); int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd); -- 2.11.0