From 7ae1ab4da84ffa53035f4e05d9340dabba2cd567 Mon Sep 17 00:00:00 2001 From: Giridharan A V Date: Tue, 11 Apr 2023 03:26:45 -0500 Subject: [PATCH 229/296] brcmfmac: fixes for FW redownload after DS1/2 exit Fixes for multiple issues seen during FW redownload after DS1/2 exit 1. Stop the WD timer when entering the re-download path to avoid attempting to the bus. 2. Reset the "last" index when the console buffer is updated. 3. Do not read the console buffer right after downloading the FW as the shared structure might be populated by then. 4. Post download, signature of the FW is verified. It is in the order of ~400-500ms. So, wait for ~500ms in the FMAC for the FW to be ready post download. 5. FW download process moves even if the post NVRAM download check fails. So, stop proceeding with FW download if post NVRAM download checks fail. 6. Add some more debug prints. 7. Do not acknowledge the HMB data read to FW when HMB data is zero. Signed-off-by: Mahankali Chandra Sekhar Signed-off-by: Giridharan A V --- .../broadcom/brcm80211/brcmfmac/bcmsdh.c | 6 ++-- .../broadcom/brcm80211/brcmfmac/chip.c | 19 ++++++++++-- .../broadcom/brcm80211/brcmfmac/chip.h | 2 +- .../broadcom/brcm80211/brcmfmac/sdio.c | 30 +++++++++++-------- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index 747cd6e7f2ed..62b5e71c74ba 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -257,12 +257,14 @@ u32 brcmf_sdiod_readl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) if (retval) goto out; - brcmf_dbg(TRACE, "reading from addr 0x%x bar0 0x%08x\n", addr, sdiodev->sbwad); + brcmf_dbg(TRACE, "reading from addr 0x%x bar0 0x%08x ", addr, sdiodev->sbwad); addr &= SBSDIO_SB_OFT_ADDR_MASK; addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; data = sdio_readl(sdiodev->func1, addr, &retval); + + brcmf_dbg(TRACE, "data 0x%08x\n", data); out: if (ret) *ret = retval; @@ -279,7 +281,7 @@ void brcmf_sdiod_writel(struct brcmf_sdio_dev *sdiodev, u32 addr, if (retval) goto out; - brcmf_dbg(TRACE, "writing %d to addr 0x%x bar0 0x%08x\n", data, addr, sdiodev->sbwad); + brcmf_dbg(TRACE, "writing 0x%08x to addr 0x%x bar0 0x%08x\n", data, addr, sdiodev->sbwad); addr &= SBSDIO_SB_OFT_ADDR_MASK; addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 86beb63408cc..e86e4ed624fe 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -1203,7 +1203,7 @@ static int brcmf_blhs_post_fw_download(struct brcmf_chip *pub) return err; } -static void brcmf_blhs_post_nvram_download(struct brcmf_chip *pub) +static int brcmf_blhs_post_nvram_download(struct brcmf_chip *pub) { struct brcmf_chip_priv *chip; u32 addr; @@ -1221,11 +1221,24 @@ static void brcmf_blhs_post_nvram_download(struct brcmf_chip *pub) BRCMF_BLHS_D2H_MV_NVRAM_DONE) == 0, BRCMF_BLHS_D2H_MV_NVRAM_DONE_TIMEOUT, BRCMF_BLHS_POLL_INTERVAL); + /* check if the NVRAM move has been done */ + regdata = pub->blhs->read(chip->ctx, addr); + if ((regdata & BRCMF_BLHS_D2H_MV_NVRAM_DONE)) { + brcmf_dbg(INFO, + "NVRAM moved to the end of the RAM. regdata 0x%08x\n", + regdata); + } else { + /* Timeout waiting for the NVRAM to be moved to the end of the RAM. */ + brcmf_err("Timeout:%dms for BRCMF_BLHS_D2H_MV_NVRAM_DONE regdata 0x%08x\n" + BRCMF_BLHS_D2H_MV_NVRAM_DONE_TIMEOUT, regdata); + return -EPERM; + } } else { regdata = pub->blhs->read(chip->ctx, addr); regdata |= BRCMF_BLHS_H2D_DL_NVRAM_DONE; pub->blhs->write(chip->ctx, addr, regdata); } + return 0; } static int brcmf_blhs_chk_validation(struct brcmf_chip *pub) @@ -1945,7 +1958,6 @@ void brcmf_chip_reset_watchdog(struct brcmf_chip *pub) switch (pub->chip) { case CY_CC_43012_CHIP_ID: - case CY_CC_43022_CHIP_ID: addr = CORE_CC_REG(base, min_res_mask); chip->ops->write32(chip->ctx, addr, CY_43012_PMU_MIN_RES_MASK); @@ -1970,6 +1982,9 @@ void brcmf_chip_reset_watchdog(struct brcmf_chip *pub) CY_4373_PMU_WATCHDOG_TICK_VAL); mdelay(100); break; + case CY_CC_43022_CHIP_ID: + brcmf_dbg(INFO, "DO NOTHING FOR 43022 here... can't access PMU registers\n"); + break; default: break; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h index ad0804d7ace1..1ca82f137448 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h @@ -103,7 +103,7 @@ struct brcmf_blhs { int (*pre_nvramdl)(struct brcmf_chip *pub); int (*prep_fwdl)(struct brcmf_chip *pub); int (*post_fwdl)(struct brcmf_chip *pub); - void (*post_nvramdl)(struct brcmf_chip *pub); + int (*post_nvramdl)(struct brcmf_chip *pub); int (*bp_clk_ack)(struct brcmf_chip *pub); int (*chk_validation)(struct brcmf_chip *pub); int (*post_wdreset)(struct brcmf_chip *pub); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index ea4f8a20a9fd..1f1a18b25cec 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -1335,8 +1335,11 @@ static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus) { struct sdpcm_shared sh; - if (brcmf_sdio_readshared(bus, &sh) == 0) + if (brcmf_sdio_readshared(bus, &sh) == 0) { + /* reset the last read count when buffer address is updated */ + bus->console.last = 0; bus->console_addr = sh.console_addr; + } } #else static void brcmf_sdio_get_console_addr(struct brcmf_sdio *bus) @@ -1359,8 +1362,8 @@ static u32 brcmf_sdio_hostmail(struct brcmf_sdio *bus, u32 *hmbd) hmb_data = brcmf_sdiod_readl(sdiod, core->base + SD_REG(tohostmailboxdata), &ret); - - if (!ret) + /* skip generating SMB_INT_ACK if there is no MB data */ + if (!ret && hmb_data) brcmf_sdiod_writel(sdiod, core->base + SD_REG(tosbmailbox), SMB_INT_ACK, &ret); @@ -3024,6 +3027,9 @@ brcmf_sdio_ulp_reinit_fw(struct brcmf_sdio *bus) if (!fwreq) return -ENOMEM; + /* stop the watch dog -> idle time until reinit is done */ + brcmf_sdio_wd_timer(bus, false); + err = brcmf_fw_get_firmwares(sdiodev->dev, fwreq, brcmf_sdio_firmware_callback); if (err != 0) { @@ -4055,8 +4061,12 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, goto err; } - bus->ci->blhs->post_nvramdl(bus->ci); - + bcmerror = bus->ci->blhs->post_nvramdl(bus->ci); + if (bcmerror) { + brcmf_err("error in post NVRAM download hs err=%d\n", + bcmerror); + goto err; + } bcmerror = bus->ci->blhs->prep_fwdl(bus->ci); bcmerror = brcmf_sdio_download_code_file(bus, fw); @@ -4079,11 +4089,6 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus, brcmf_fw_nvram_free(nvram); goto err; } -#ifdef DEBUG - brcmf_sdio_bus_sleep(bus, false, false); - if (brcmf_sdio_readconsole(bus) < 0) - brcmf_err("Console buffer read failed\n"); -#endif /* DEBUG */ } else if (bus->ci->blhs) { bcmerror = bus->ci->blhs->prep_fwdl(bus->ci); if (bcmerror) { @@ -4838,7 +4843,7 @@ static const struct brcmf_buscore_ops brcmf_sdio_buscore_ops = { .sec_attach = brcmf_sdio_buscore_sec_attach, }; -#define LOOP_TO_CHECK_FOR_BP_ENABLE 500 /* Wait for 500msec */ +#define LOOP_TO_CHECK_FOR_BP_ENABLE 50000 /* Wait for 500msec */ int brcmf_get_intr_pending_data(void *ctx) { @@ -4862,7 +4867,8 @@ int brcmf_get_intr_pending_data(void *ctx) /* Bootloader hung after backplane disable */ if (loop == LOOP_TO_CHECK_FOR_BP_ENABLE) { err = -EBUSY; - brcmf_err("Device hung, return failure.\n"); + brcmf_err("Device hung, return failure. time out %d ms\n", + (LOOP_TO_CHECK_FOR_BP_ENABLE * 10) / 1000); } return 0; -- 2.25.1