浏览代码

qcacmn: Fix to avoid skb buff leak when NBUF alloc fail

propagation from qcacld-2.0 to qcacmn.

If host fail to allocate receive packet bundle buffer
it will return no memory without freeing receive pkt queue.
Fix is to free the receive pkt queue before returning from message handler.
Also, fill the rx free list during driver load time itself with the
pre allocated memory so that Tx won’t take away this memory.

Change-Id: I4bf2aeb7bc85cc68cfa1314e6dbf5057665ba7ce
CRs-Fixed: 1079623
Poddar, Siddarth 8 年之前
父节点
当前提交
f176340b9e
共有 2 个文件被更改,包括 49 次插入4 次删除
  1. 25 2
      hif/src/sdio/hif_sdio_recv.c
  2. 24 2
      htc/htc.c

+ 25 - 2
hif/src/sdio/hif_sdio_recv.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -36,6 +36,7 @@
 #include <qdf_defer.h>
 #include <qdf_atomic.h>
 #include <qdf_nbuf.h>
+#include <qdf_threads.h>
 #include <athdefs.h>
 #include <qdf_net_types.h>
 #include <a_types.h>
@@ -48,6 +49,8 @@
 #include "regtable_sdio.h"
 #include "if_sdio.h"
 
+#define NBUF_ALLOC_FAIL_WAIT_TIME 100
+
 static void hif_dev_dump_registers(struct hif_sdio_device *pdev,
 				struct MBOX_IRQ_PROC_REGISTERS *irq_proc_regs,
 				struct MBOX_IRQ_ENABLE_REGISTERS *
@@ -710,6 +713,12 @@ static QDF_STATUS hif_dev_issue_recv_packet_bundle(struct hif_sdio_device *pdev,
 	bundleSpaceRemaining =
 		HTC_MAX_MSG_PER_BUNDLE * target->TargetCreditSize;
 	packet_rx_bundle = allocate_htc_bundle_packet(target);
+	if (!packet_rx_bundle) {
+		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
+				("%s: packet_rx_bundle is NULL\n", __func__));
+		qdf_sleep(NBUF_ALLOC_FAIL_WAIT_TIME);  /* 100 msec sleep */
+		return QDF_STATUS_E_NOMEM;
+	}
 	bundle_buffer = packet_rx_bundle->pBuffer;
 
 	for (i = 0;
@@ -864,8 +873,22 @@ QDF_STATUS hif_dev_recv_message_pending_handler(struct hif_sdio_device *pdev,
 						  mail_box_index,
 						  &pkts_fetched,
 						  partial_bundle);
-				if (QDF_IS_STATUS_ERROR(status))
+				if (QDF_IS_STATUS_ERROR(status)) {
+					while (!HTC_QUEUE_EMPTY(
+							&recv_pkt_queue)) {
+						qdf_nbuf_t netbuf;
+
+						packet = htc_packet_dequeue(
+							 &recv_pkt_queue);
+						if (packet == NULL)
+							break;
+						netbuf = (qdf_nbuf_t) packet->
+								pNetBufContext;
+						if (netbuf)
+							qdf_nbuf_free(netbuf);
+					}
 					break;
+				}
 
 				if (HTC_PACKET_QUEUE_DEPTH(&recv_pkt_queue) !=
 					0) {

+ 24 - 2
htc/htc.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -31,6 +31,8 @@
 #include <qdf_nbuf.h>           /* qdf_nbuf_t */
 #include <qdf_types.h>          /* qdf_print */
 
+#define MAX_HTC_RX_BUNDLE  2
+
 #if defined(WLAN_DEBUG) || defined(DEBUG)
 static ATH_DEBUG_MASK_DESCRIPTION g_htc_debug_description[] = {
 	{ATH_DEBUG_SEND, "Send"},
@@ -499,9 +501,11 @@ A_STATUS htc_wait_target(HTC_HANDLE HTCHandle)
 	HTC_SERVICE_CONNECT_RESP resp;
 	HTC_READY_MSG *rdy_msg;
 	uint16_t htc_rdy_msg_id;
+	uint8_t i = 0;
+	HTC_PACKET *rx_bundle_packet, *temp_bundle_packet;
 
 	AR_DEBUG_PRINTF(ATH_DEBUG_TRC,
-			("htc_wait_target - Enter (target:0x%p) \n", HTCHandle));
+			("htc_wait_target - Enter (target:0x%p)\n", HTCHandle));
 	AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("+HWT\n"));
 
 	do {
@@ -561,6 +565,24 @@ A_STATUS htc_wait_target(HTC_HANDLE HTCHandle)
 			status = A_ECOMM;
 			break;
 		}
+
+		/* Allocate expected number of RX bundle buffer allocation */
+		if (HTC_RX_BUNDLE_ENABLED(target)) {
+			temp_bundle_packet = NULL;
+			for (i = 0; i < MAX_HTC_RX_BUNDLE; i++) {
+				rx_bundle_packet =
+					allocate_htc_bundle_packet(target);
+				if (rx_bundle_packet != NULL)
+					rx_bundle_packet->ListLink.pNext =
+						(DL_LIST *)temp_bundle_packet;
+				else
+					break;
+
+				temp_bundle_packet = rx_bundle_packet;
+			}
+			target->pBundleFreeList = temp_bundle_packet;
+		}
+
 		/* done processing */
 		target->CtrlResponseProcessing = false;