]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: brcmfmac: make release_scratchbuffers idempotent
authorFan Wu <fanwu01@zju.edu.cn>
Sat, 18 Jul 2026 02:43:52 +0000 (02:43 +0000)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 21 Jul 2026 11:35:29 +0000 (13:35 +0200)
brcmf_pcie_release_scratchbuffers() frees the shared.scratch and
shared.ringupd DMA buffers with dma_free_coherent() but does not clear
the pointers afterwards, unlike the sibling release_ringbuffers() which
NULLs commonrings/flowrings/idxbuf on release.

Both the bus_reset .reset callback (brcmf_pcie_reset) and
brcmf_pcie_remove() call release_scratchbuffers.  When reset teardown
has run before removal, remove's own teardown would call
dma_free_coherent() a second time on the already-freed DMA allocation.

NULL the pointers after free, matching release_ringbuffers(), so a later
release observes that the allocation has already been released.  This
patch makes repeated sequential release safe; the reset-work lifetime is
handled separately by the following patch.

This issue was found by an in-house static analysis tool.

Fixes: 4684997d9eea ("brcmfmac: reset PCIe bus on a firmware crash")
Cc: stable@vger.kernel.org
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
Assisted-by: Codex:gpt-5.6
Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
Link: https://patch.msgid.link/20260718024353.3147201-2-fanwu01@zju.edu.cn
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c

index 13662aa4b4ea69c5ca786ac12218aea863e0ba2e..9f10b3fff9fff5c7cf7f5765c5e25042545583b5 100644 (file)
@@ -1383,16 +1383,20 @@ fail:
 static void
 brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info *devinfo)
 {
-       if (devinfo->shared.scratch)
+       if (devinfo->shared.scratch) {
                dma_free_coherent(&devinfo->pdev->dev,
                                  BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
                                  devinfo->shared.scratch,
                                  devinfo->shared.scratch_dmahandle);
-       if (devinfo->shared.ringupd)
+               devinfo->shared.scratch = NULL;
+       }
+       if (devinfo->shared.ringupd) {
                dma_free_coherent(&devinfo->pdev->dev,
                                  BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
                                  devinfo->shared.ringupd,
                                  devinfo->shared.ringupd_dmahandle);
+               devinfo->shared.ringupd = NULL;
+       }
 }
 
 static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)