wifi: brcmfmac: Fix potential kernel oops when probe fails
[ Upstream commit 243307a0d1b0d01538e202c00454c28b21d4432e ]
When probe of the sdio brcmfmac device fails for some reasons (i.e.
missing firmware), the sdiodev->bus is set to error instead of NULL, thus
the cleanup later in brcmf_sdio_remove() tries to free resources via
invalid bus pointer. This happens because sdiodev->bus is set 2 times:
first in brcmf_sdio_probe() and second time in brcmf_sdiod_probe(). Fix
this by chaning the brcmf_sdio_probe() function to return the error code
and set sdio->bus only there.
Fixes: 0ff0843310 ("wifi: brcmfmac: Add optional lpo clock enable support")
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Acked-by: Arend van Spriel<arend.vanspriel@broadcom.com>
Link: https://patch.msgid.link/20260203102133.1478331-1-m.szyprowski@samsung.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
3c87b7e647
commit
64ccb0aac4
|
|
@ -951,11 +951,10 @@ int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* try to attach to the target device */
|
/* try to attach to the target device */
|
||||||
sdiodev->bus = brcmf_sdio_probe(sdiodev);
|
ret = brcmf_sdio_probe(sdiodev);
|
||||||
if (IS_ERR(sdiodev->bus)) {
|
if (ret)
|
||||||
ret = PTR_ERR(sdiodev->bus);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
brcmf_sdiod_host_fixup(sdiodev->func2->card->host);
|
brcmf_sdiod_host_fixup(sdiodev->func2->card->host);
|
||||||
out:
|
out:
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
||||||
|
|
@ -4445,7 +4445,7 @@ brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus)
|
||||||
return fwreq;
|
return fwreq;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
|
int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct brcmf_sdio *bus;
|
struct brcmf_sdio *bus;
|
||||||
|
|
@ -4551,11 +4551,12 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bus;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
brcmf_sdio_remove(bus);
|
brcmf_sdio_remove(bus);
|
||||||
return ERR_PTR(ret);
|
sdiodev->bus = NULL;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detach and free everything */
|
/* Detach and free everything */
|
||||||
|
|
|
||||||
|
|
@ -358,7 +358,7 @@ void brcmf_sdiod_freezer_uncount(struct brcmf_sdio_dev *sdiodev);
|
||||||
int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev);
|
int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev);
|
||||||
int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev);
|
int brcmf_sdiod_remove(struct brcmf_sdio_dev *sdiodev);
|
||||||
|
|
||||||
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
|
int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
|
||||||
void brcmf_sdio_remove(struct brcmf_sdio *bus);
|
void brcmf_sdio_remove(struct brcmf_sdio *bus);
|
||||||
void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr);
|
void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue