DHD: 4398 - Fix KP during dhd_prot_reset when htput flowring buf malloc fails during init

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>
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 @@
 		/* 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 @@
 	/* 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 @@
 		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_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 */