From 2152d62428bf3058f6916d853f791cc5c20372d3 Mon Sep 17 00:00:00 2001 From: Ishan Deshpande Date: Tue, 27 Jun 2023 03:50:12 -0500 Subject: [PATCH 220/296] brcmfmac: DS2 udp tx crash fix Issue: Host crash/FW redownload failure seen when device is in ds2 and UDP tx stream is started Root Cause: 1) When DUT is in DS2, and a tx packet goes, ucode starts the ds2 exit process and fcbs sequence initializes the sdio core 2) Until ucode completes its ds2 exit process, fmac has put the tx packet in a queue and is trying to set the kso bit 3) As soon as the fcbs seq initializes the sdio core, fmac is able to set the kso bit and tries to send all the packets from the queue 4) But the FW isn't redownloaded yet so the packet write fails. For DS0 FW to redownload, handshakes should be completed between DS2 FW (Ram BL) and fmac. 5) But UDP stream continuously tries to write the packets through sdio and puts the device into some bad state which prevents the completion of handshakes. This issue is not seen with tcp tx as with tcp 1 packet is sent and host waits for a response which gives enough time for ds2 exit Fix: Tx packet should only be sent when FW is up and F2 is ready. Add a F2 ready check before sending tx packets from queue Signed-off-by: Ishan Deshpande --- .../broadcom/brcm80211/brcmfmac/sdio.c | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 5e6e4dde772d..e35d4ed65033 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -3270,29 +3270,28 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) brcmf_sdio_clrintr(bus); - if (bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL) && - txctl_ok(bus) && brcmf_sdio_f2_ready(bus)) { - sdio_claim_host(bus->sdiodev->func1); - if (bus->ctrl_frame_stat) { - err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, - bus->ctrl_frame_len); - bus->ctrl_frame_err = err; - wmb(); - bus->ctrl_frame_stat = false; - if (err) - brcmf_err("sdio ctrlframe tx failed err=%d\n", - err); + if (bus->clkstate == CLK_AVAIL && brcmf_sdio_f2_ready(bus)) { + if (bus->ctrl_frame_stat && txctl_ok(bus)) { + sdio_claim_host(bus->sdiodev->func1); + if (bus->ctrl_frame_stat) { + err = brcmf_sdio_tx_ctrlframe(bus, bus->ctrl_frame_buf, + bus->ctrl_frame_len); + bus->ctrl_frame_err = err; + wmb(); /*Ensure tx ctrlframe cache line entry is flushed*/ + bus->ctrl_frame_stat = false; + if (err) + brcmf_err("sdio ctrlframe tx failed err=%d\n", err); + } + sdio_release_host(bus->sdiodev->func1); + brcmf_sdio_wait_event_wakeup(bus); + } + /* Send queued frames (limit 1 if rx may still be pending) */ + if (!atomic_read(&bus->fcstate) && data_ok(bus) && + brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit) { + framecnt = bus->rxpending ? min(txlimit, bus->txminmax) : + txlimit; + brcmf_sdio_sendfromq(bus, framecnt); } - sdio_release_host(bus->sdiodev->func1); - brcmf_sdio_wait_event_wakeup(bus); - } - /* Send queued frames (limit 1 if rx may still be pending) */ - if ((bus->clkstate == CLK_AVAIL) && !atomic_read(&bus->fcstate) && - brcmu_pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && - data_ok(bus)) { - framecnt = bus->rxpending ? min(txlimit, bus->txminmax) : - txlimit; - brcmf_sdio_sendfromq(bus, framecnt); } if ((bus->sdiodev->state != BRCMF_SDIOD_DATA) || (err != 0)) { -- 2.25.1