diff options
author | Yadukishore Kodicherla <yadukishore.kodicherla@broadcom.corp-partner.google.com> | 2023-09-12 12:00:15 +0530 |
---|---|---|
committer | kensun <kensun@google.com> | 2023-09-12 13:42:13 +0000 |
commit | 3f6a07de731c84ea69ce59d9088b7c0c8547918c (patch) | |
tree | cc60bec9f467235e8c5e92194cca644934145973 | |
parent | 97a64ddb9c18696ce5f9f5af9438db6d0a89ab04 (diff) | |
download | bcm4398-3f6a07de731c84ea69ce59d9088b7c0c8547918c.tar.gz |
DHD: 4398 - Fix KP during dhd_prot_reset when htput flowring buf malloc fails during initandroid-u-qpr1-beta-2_r0.8android-u-qpr1-beta-2.1_r0.8android-gs-shusky-5.15-u-qpr1-beta2
KP reported by customer due to failure of malloc for htput ring buf:
[ 17.088063][ T1093] [09:40:43.728565][dhd][wlan]dhd_dma_buf_alloc: buf_len 327680, no memory available
[ 17.088070][ T1093] [09:40:43.728572][dhd][wlan]dhd_prot_allocate_bufs: dhd_prot_ring_attach D2H Rx Completion failed
[ 17.088091][ T1093] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000030
...
[ 17.089190][ T1093] dhd_prot_reset+0x61c/0x8e0 [bcmdhd4398]
[ 17.089399][ T1093] dhd_prot_detach+0x34/0xcd4 [bcmdhd4398]
[ 17.089607][ T1093] dhd_prot_attach+0x690/0xc74 [bcmdhd4398]
[ 17.089812][ T1093] dhd_attach+0x5b4/0x1f6c [bcmdhd4398]
[ 17.090020][ T1093] dhdpcie_bus_attach+0x18c/0x868 [bcmdhd4398]
[ 17.090225][ T1093] dhdpcie_pci_probe+0x89c/0x107c [bcmdhd4398]
Fixed by adding null checks in prot detach and reset path
Bug: 299597777
Test: Simulated the problem on hikey by making
'prot->prealloc_htput_flowring_buf = NULL;' during dhd_prot_attach().
KP is seen without fix in both dhd_prot_reset and dhd_prot_detach paths.
KP not seen with fix.
Change-Id: I98e30a18719323ec73d3a5a4597f2f9049e0b545
Signed-off-by: Yadukishore Kodicherla <yadukishore.kodicherla@broadcom.corp-partner.google.com>
-rw-r--r-- | dhd_msgbuf.c | 40 |
1 files changed, 27 insertions, 13 deletions
diff --git a/dhd_msgbuf.c b/dhd_msgbuf.c index dfb17c5..eee2cae 100644 --- a/dhd_msgbuf.c +++ b/dhd_msgbuf.c @@ -4018,6 +4018,11 @@ dhd_prot_attach(dhd_pub_t *dhd) /* pre-allocation htput ring */ dhd->prot->prealloc_htput_flowring_buf = MALLOCZ(osh, sizeof(dhd_dma_buf_t)* dhd->htput_total_flowrings); + if (dhd->prot->prealloc_htput_flowring_buf == NULL) { + DHD_ERROR(("%s : malloc of prealloc_htput_flowring_buf failed!\n", + __FUNCTION__)); + goto fail; + } for (i = 0; i < dhd->htput_total_flowrings; i++) { if (dhd_dma_buf_alloc(dhd, &dhd->prot->prealloc_htput_flowring_buf[i], (uint32)(h2d_htput_max_txpost * h2d_txpost_size_prealloc))) { @@ -4038,6 +4043,10 @@ dhd_prot_attach(dhd_pub_t *dhd) /* pre-allocation flow ring */ dhd->prot->prealloc_regular_flowring_buf = MALLOCZ(osh, sizeof(dhd_dma_buf_t) * dhd->max_prealloc_regular_flowrings); + if (dhd->prot->prealloc_regular_flowring_buf == NULL) { + DHD_ERROR(("%s : malloc of prealloc_regular_flowring_buf failed!\n", __FUNCTION__)); + goto fail; + } for (i = 0; i < dhd->max_prealloc_regular_flowrings; i++) { if (dhd_dma_buf_alloc(dhd, &dhd->prot->prealloc_regular_flowring_buf[i], (uint32)(h2d_max_txpost * h2d_txpost_size_prealloc))) { @@ -5036,19 +5045,22 @@ void dhd_prot_detach(dhd_pub_t *dhd) dhd_prot_flowrings_pool_detach(dhd); #ifdef FLOW_RING_PREALLOC - if (dhd->htput_support) { - for (i = 0; i < dhd->htput_total_flowrings; i++) { - dhd_dma_buf_free(dhd, &prot->prealloc_htput_flowring_buf[i]); + if (prot->prealloc_htput_flowring_buf) { + if (dhd->htput_support) { + for (i = 0; i < dhd->htput_total_flowrings; i++) { + dhd_dma_buf_free(dhd, &prot->prealloc_htput_flowring_buf[i]); + } } + MFREE(dhd->osh, prot->prealloc_htput_flowring_buf, + sizeof(dhd_dma_buf_t) * dhd->htput_total_flowrings); } - MFREE(dhd->osh, prot->prealloc_htput_flowring_buf, - sizeof(dhd_dma_buf_t) * dhd->htput_total_flowrings); - - for (i = 0; i < dhd->max_prealloc_regular_flowrings; i++) { - dhd_dma_buf_free(dhd, &prot->prealloc_regular_flowring_buf[i]); + if (prot->prealloc_regular_flowring_buf) { + for (i = 0; i < dhd->max_prealloc_regular_flowrings; i++) { + dhd_dma_buf_free(dhd, &prot->prealloc_regular_flowring_buf[i]); + } + MFREE(dhd->osh, prot->prealloc_regular_flowring_buf, + sizeof(dhd_dma_buf_t) * dhd->max_prealloc_regular_flowrings); } - MFREE(dhd->osh, prot->prealloc_regular_flowring_buf, - sizeof(dhd_dma_buf_t) * dhd->max_prealloc_regular_flowrings); #endif /* FLOW_RING_PREALLOC */ /* detach info rings */ @@ -5182,14 +5194,16 @@ dhd_prot_reset(dhd_pub_t *dhd) dhd_dma_buf_reset(dhd, &prot->d2h_dma_indx_wr_buf); #ifdef FLOW_RING_PREALLOC - if (dhd->htput_support) { + if (dhd->htput_support && prot->prealloc_htput_flowring_buf) { for (i = 0; i < dhd->htput_total_flowrings; i++) { dhd_dma_buf_reset(dhd, &prot->prealloc_htput_flowring_buf[i]); } } - for (i = 0; i < dhd->max_prealloc_regular_flowrings; i++) { - dhd_dma_buf_reset(dhd, &prot->prealloc_regular_flowring_buf[i]); + if (prot->prealloc_regular_flowring_buf) { + for (i = 0; i < dhd->max_prealloc_regular_flowrings; i++) { + dhd_dma_buf_reset(dhd, &prot->prealloc_regular_flowring_buf[i]); + } } #endif /* FLOW_RING_PREALLOC */ |