From 6fa74f82cf5d844576537939ce9877c0250be8b6 Mon Sep 17 00:00:00 2001 From: Ishan Deshpande Date: Tue, 25 Apr 2023 00:02:11 -0500 Subject: [PATCH 205/296] brcmfmac: Increase the kso_sequence bail out timer Issue: The SDIO kso_sequence runs only for 1 msec causing "adaptor not found errors" in ds2 exit Analysis: 1) In brcmf_sdio_kso_control function in fmac, there is a loop which runs until either of the conditions are met: - kso is set to 1 or 0 (depending on the condition) - try_cnt > MAX_KSO_ATTEMPTS (this translates to 1 sec to total loop time) 2) So ideally fmac should keep on trying to set/clr the kso bit until MAX_KSO_ATTEMPTS 3) But there is a condition in the loop to bail out upon 20 subsequent access errors which turns out to be 1 msec (as each iteration in loop takes 50 us) 4) Ideally time for kso_sequence in HW is 3-4 msec, but 1 msec is too less for wait time before bail out Solution: 1) Remove the error condition in the loop which bails out after 20 subsequent errors 2) Print a warning message if the kso sequence took more than 10 msec which is calculated based on jiffies. It makes it easier to figure out a possible issue with FW/HW/ucode Signed-off-by: Ishan Deshpande --- .../broadcom/brcm80211/brcmfmac/sdio.c | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 7e0165f0e0cb..697d98766c89 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -343,8 +343,8 @@ struct rte_console { #define BRCMF_IDLE_INTERVAL 1 #define KSO_WAIT_US 50 +#define KSO_MAX_SEQ_TIME (1000 * 10) /* Ideal time for kso sequence 10ms */ #define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US) -#define BRCMF_SDIO_MAX_ACCESS_ERRORS 20 static void brcmf_sdio_firmware_callback(struct device *dev, int err, struct brcmf_fw_request *fwreq); @@ -753,6 +753,8 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) int err = 0; int err_cnt = 0; int try_cnt = 0; + unsigned long start_jiffy = 0; + unsigned int kso_loop_time = 0; brcmf_dbg(TRACE, "Enter: on=%d\n", on); @@ -763,6 +765,10 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) sdio_retune_hold_now(bus->sdiodev->func1); wr_val = (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT); + + /* Start time of kso_sequence */ + start_jiffy = jiffies; + /* 1st KSO write goes to AOS wake up core if device is asleep */ brcmf_sdiod_writeb(bus->sdiodev, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); @@ -805,11 +811,9 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) if (!err) { if ((rd_val & bmask) == cmp_val) break; - err_cnt = 0; + } else { + err_cnt++; } - /* bail out upon subsequent access errors */ - if (err && (err_cnt++ > BRCMF_SDIO_MAX_ACCESS_ERRORS)) - break; /* Do one KSO write-read-check without any delay in between the steps, * if Device is already up KSO sequence will complete immediately @@ -839,12 +843,18 @@ brcmf_sdio_kso_control(struct brcmf_sdio *bus, bool on) } while (try_cnt++ < MAX_KSO_ATTEMPTS); - if (try_cnt > 2) - brcmf_dbg(SDIO, "try_cnt=%d rd_val=0x%x err=%d\n", try_cnt, - rd_val, err); + kso_loop_time = jiffies_to_usecs(jiffies - start_jiffy); if (try_cnt > MAX_KSO_ATTEMPTS) - brcmf_err("max tries: rd_val=0x%x err=%d\n", rd_val, err); + brcmf_err("ERR: KSO=%d sequence failed after max tries=%d and err_cnt=%d kso_seq_time=%uus rd_val=0x%x err=%d\n", + on, try_cnt, err_cnt, kso_loop_time, rd_val, err); + + if (kso_loop_time > KSO_MAX_SEQ_TIME) + brcmf_dbg(SDIO, "WARN: KSO=%d sequence took %uus > expected %uus try_cnt=%d err_cnt=%d rd_val=0x%x err=%d\n", + on, kso_loop_time, KSO_MAX_SEQ_TIME, try_cnt, err_cnt, rd_val, err); + else + brcmf_dbg(SDIO, "INFO: KSO=%d try_cnt=%d err_cnt=%d kso_seq_time=%uus rd_val=0x%x err=%d\n", + on, try_cnt, err_cnt, kso_loop_time, rd_val, err); if (on) sdio_retune_release(bus->sdiodev->func1); -- 2.25.1