Kaynağa Gözat

qcacmn: SDIO HIF layer refactor

Refactor the mailbox operations in a separate file mailbox.c
Collect common transfer functions in new file transfer.c
Remove redundant file hif_sdio_send.c
Remove redundant file hif_sdio_recv.c

Change-Id: I964970f4651a11000e9833ad21eef1b255682341
CRs-Fixed: 2252406
Sriram Madhvapathi 6 yıl önce
ebeveyn
işleme
df25e2251d

+ 3 - 5
hif/src/sdio/hif_sdio.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -133,11 +133,9 @@ int hif_map_service_to_pipe(struct hif_opaque_softc *hif_hdl,
 {
 	struct hif_sdio_softc *scn = HIF_GET_SDIO_SOFTC(hif_hdl);
 	struct hif_sdio_dev *hif_device = scn->hif_handle;
-	struct hif_sdio_device *htc_sdio_device = hif_dev_from_hif(hif_device);
 
-	return hif_dev_map_service_to_pipe(htc_sdio_device,
-					   service_id, ul_pipe, dl_pipe,
-					   hif_device->swap_mailbox);
+	return hif_dev_map_service_to_pipe(hif_device,
+					   service_id, ul_pipe, dl_pipe);
 }
 
 /**

+ 94 - 220
hif/src/sdio/hif_sdio_dev.c

@@ -40,129 +40,6 @@
 #include "if_sdio.h"
 #include "regtable_sdio.h"
 
-/* under HL SDIO, with Interface Memory support, we have
- * the following reasons to support 2 mboxs:
- * a) we need place different buffers in different
- * mempool, for example, data using Interface Memory,
- * desc and other using DRAM, they need different SDIO
- * mbox channels.
- * b) currently, tx mempool in LL case is separated from
- * main mempool, the structure (descs at the beginning
- * of every pool buffer) is different, because they only
- * need store tx desc from host. To align with LL case,
- * we also need 2 mbox support just as PCIe LL cases.
- */
-
-/**
- * hif_dev_map_pipe_to_mail_box() - maps pipe id to mailbox.
- * @pdev: sdio device context
- * @pipeid: pipe index
- *
- *
- * Return: mailbox index
- */
-uint8_t hif_dev_map_pipe_to_mail_box(struct hif_sdio_device *pdev,
-			uint8_t pipeid)
-{
-	/* TODO: temp version, should not hardcoded here, will be
-	 * updated after HIF design
-	 */
-	if (2 == pipeid || 3 == pipeid)
-		return 1;
-	else if (0 == pipeid || 1 == pipeid)
-		return 0;
-	AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: pipeid=%d,should not happen\n",
-					__func__, pipeid));
-	qdf_assert(0);
-	return INVALID_MAILBOX_NUMBER;
-}
-
-/**
- * hif_dev_map_mail_box_to_pipe() - map sdio mailbox to htc pipe.
- * @pdev: sdio device
- * @mboxIndex: mailbox index
- * @upload: boolean to decide mailbox index
- *
- * Disable hif device interrupts and destroy hif context
- *
- * Return: none
- */
-uint8_t hif_dev_map_mail_box_to_pipe(struct hif_sdio_device *pdev,
-			uint8_t mbox_index,
-				     bool upload)
-{
-	/* TODO: temp version, should not hardcoded here, will be
-	 * updated after HIF design
-	 */
-	if (mbox_index == 0)
-		return upload ? 1 : 0;
-	else if (mbox_index == 1)
-		return upload ? 3 : 2;
-	AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-			("%s:-----mboxIndex=%d,upload=%d, should not happen\n",
-			__func__, mbox_index, upload));
-	qdf_assert(0);
-	return 0xff;
-}
-
-/**
- * hif_dev_map_service_to_pipe() - maps ul/dl pipe to service id.
- * @pDev: sdio device context
- * @ServiceId: sevice index
- * @ULPipe: uplink pipe id
- * @DLPipe: down-linklink pipe id
- * @SwapMapping: mailbox swap mapping
- *
- * Return: int
- */
-QDF_STATUS hif_dev_map_service_to_pipe(struct hif_sdio_device *pdev,
-				     uint16_t service_id,
-				     uint8_t *ul_pipe, uint8_t *dl_pipe,
-				     bool swap_mapping)
-{
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-
-	switch (service_id) {
-	case HTT_DATA_MSG_SVC:
-		if (swap_mapping) {
-			*ul_pipe = 1;
-			*dl_pipe = 0;
-		} else {
-			*ul_pipe = 3;
-			*dl_pipe = 2;
-		}
-		break;
-
-	case HTC_CTRL_RSVD_SVC:
-	case HTC_RAW_STREAMS_SVC:
-		*ul_pipe = 1;
-		*dl_pipe = 0;
-		break;
-
-	case WMI_DATA_BE_SVC:
-	case WMI_DATA_BK_SVC:
-	case WMI_DATA_VI_SVC:
-	case WMI_DATA_VO_SVC:
-		*ul_pipe = 1;
-		*dl_pipe = 0;
-		break;
-
-	case WMI_CONTROL_SVC:
-		if (swap_mapping) {
-			*ul_pipe = 3;
-			*dl_pipe = 2;
-		} else {
-			*ul_pipe = 1;
-			*dl_pipe = 0;
-		}
-		break;
-
-	default:
-		status = !QDF_STATUS_SUCCESS;
-		break;
-	}
-	return status;
-}
 
 /**
  * hif_dev_alloc_rx_buffer() - allocate rx buffer.
@@ -226,11 +103,8 @@ struct hif_sdio_device *hif_dev_create(struct hif_sdio_dev *hif_device,
 	status = hif_configure_device(hif_device,
 				      HIF_DEVICE_SET_HTC_CONTEXT,
 				      (void *)pdev, sizeof(pdev));
-	if (status != QDF_STATUS_SUCCESS) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				("(%s)HIF_DEVICE_SET_HTC_CONTEXT failed!!!\n",
-				 __func__));
-	}
+	if (status != QDF_STATUS_SUCCESS)
+		HIF_ERROR("%s: set context failed", __func__);
 
 	A_MEMCPY(&pdev->hif_callbacks, callbacks, sizeof(*callbacks));
 
@@ -251,11 +125,9 @@ void hif_dev_destroy(struct hif_sdio_device *pdev)
 	status = hif_configure_device(pdev->HIFDevice,
 				      HIF_DEVICE_SET_HTC_CONTEXT,
 				      (void *)NULL, 0);
-	if (status != QDF_STATUS_SUCCESS) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				("(%s)HIF_DEVICE_SET_HTC_CONTEXT failed!!!\n",
-				 __func__));
-	}
+	if (status != QDF_STATUS_SUCCESS)
+		HIF_ERROR("%s: set context failed", __func__);
+
 	qdf_mem_free(pdev);
 }
 
@@ -274,11 +146,9 @@ struct hif_sdio_device *hif_dev_from_hif(struct hif_sdio_dev *hif_device)
 	status = hif_configure_device(hif_device,
 				HIF_DEVICE_GET_HTC_CONTEXT,
 				(void **)&pdev, sizeof(struct hif_sdio_device));
-	if (status != QDF_STATUS_SUCCESS) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				("(%s)HTC_SDIO_CONTEXT is NULL!!!\n",
-				 __func__));
-	}
+	if (status != QDF_STATUS_SUCCESS)
+		HIF_ERROR("%s: set context failed", __func__);
+
 	return pdev;
 }
 
@@ -291,39 +161,15 @@ struct hif_sdio_device *hif_dev_from_hif(struct hif_sdio_dev *hif_device)
  */
 QDF_STATUS hif_dev_disable_interrupts(struct hif_sdio_device *pdev)
 {
-	struct MBOX_IRQ_ENABLE_REGISTERS regs;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	HIF_ENTER();
 
-	LOCK_HIF_DEV(pdev);
-	/* Disable all interrupts */
-	pdev->IrqEnableRegisters.int_status_enable = 0;
-	pdev->IrqEnableRegisters.cpu_int_status_enable = 0;
-	pdev->IrqEnableRegisters.error_status_enable = 0;
-	pdev->IrqEnableRegisters.counter_int_status_enable = 0;
-	/* copy into our temp area */
-	A_MEMCPY(&regs,
-		 &pdev->IrqEnableRegisters, sizeof(pdev->IrqEnableRegisters));
-
-	UNLOCK_HIF_DEV(pdev);
-
-	/* always synchronous */
-	status = hif_read_write(pdev->HIFDevice,
-				INT_STATUS_ENABLE_ADDRESS,
-				(char *) &regs,
-				sizeof(struct MBOX_IRQ_ENABLE_REGISTERS),
-				HIF_WR_SYNC_BYTE_INC, NULL);
-
-	if (status != QDF_STATUS_SUCCESS) {
-		/* Can't write it for some reason */
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-			("Failed to update interrupt control registers err: %d",
-			 status));
-	}
+	hif_dev_mask_interrupts(pdev);
 
 	/* To Do mask the host controller interrupts */
 	hif_mask_interrupt(pdev->HIFDevice);
+
 	HIF_EXIT("status :%d", status);
 	return status;
 }
@@ -338,7 +184,6 @@ QDF_STATUS hif_dev_disable_interrupts(struct hif_sdio_device *pdev)
 QDF_STATUS hif_dev_enable_interrupts(struct hif_sdio_device *pdev)
 {
 	QDF_STATUS status;
-	struct MBOX_IRQ_ENABLE_REGISTERS regs;
 
 	HIF_ENTER();
 
@@ -348,69 +193,102 @@ QDF_STATUS hif_dev_enable_interrupts(struct hif_sdio_device *pdev)
 	 * (where we clear the interrupts the first time)
 	 * and when HTC is finally ready to handle interrupts,
 	 * other software can perform target "soft" resets.
-	 * The AR6K interrupt enables reset back to an "enabled"
-	 * state when this happens.
 	 */
-	hif_dev_disable_interrupts(pdev);
+	status = hif_dev_disable_interrupts(pdev);
 
 	/* Unmask the host controller interrupts */
 	hif_un_mask_interrupt(pdev->HIFDevice);
 
-	LOCK_HIF_DEV(pdev);
+	hif_dev_unmask_interrupts(pdev);
 
-	/* Enable all the interrupts except for the internal
-	 * AR6000 CPU interrupt
-	 */
-	pdev->IrqEnableRegisters.int_status_enable =
-		INT_STATUS_ENABLE_ERROR_SET(0x01) |
-			INT_STATUS_ENABLE_CPU_SET(0x01)
-		| INT_STATUS_ENABLE_COUNTER_SET(0x01);
-
-		/* enable 2 mboxs INT */
-	pdev->IrqEnableRegisters.int_status_enable |=
-			INT_STATUS_ENABLE_MBOX_DATA_SET(0x01) |
-			INT_STATUS_ENABLE_MBOX_DATA_SET(0x02);
-
-	/* Set up the CPU Interrupt Status Register, enable
-	 * CPU sourced interrupt #0, #1.
-	 * #0 is used for report assertion from target
-	 * #1 is used for inform host that credit arrived
-	 */
-	pdev->IrqEnableRegisters.cpu_int_status_enable = 0x03;
+	HIF_EXIT();
 
-	/* Set up the Error Interrupt Status Register */
-	pdev->IrqEnableRegisters.error_status_enable =
-		(ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01)
-		 | ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01)) >> 16;
+	return status;
+}
 
-	/* Set up the Counter Interrupt Status Register
-	 * (only for debug interrupt to catch fatal errors)
-	 */
-	pdev->IrqEnableRegisters.counter_int_status_enable =
-	   (COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK)) >>
-		24;
+#define DEV_CHECK_RECV_YIELD(pdev) \
+	((pdev)->CurrentDSRRecvCount >= \
+	 (pdev)->HifIRQYieldParams.recv_packet_yield_count)
 
-	/* copy into our temp area */
-	A_MEMCPY(&regs,
-		 &pdev->IrqEnableRegisters,
-		 sizeof(struct MBOX_IRQ_ENABLE_REGISTERS));
+/**
+ * hif_dev_dsr_handler() - Synchronous interrupt handler
+ *
+ * @context: hif send context
+ *
+ * Return: 0 for success and non-zero for failure
+ */
+QDF_STATUS hif_dev_dsr_handler(void *context)
+{
+	struct hif_sdio_device *pdev = (struct hif_sdio_device *)context;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	bool done = false;
+	bool async_proc = false;
 
-	UNLOCK_HIF_DEV(pdev);
+	HIF_ENTER();
 
-	/* always synchronous */
-	status = hif_read_write(pdev->HIFDevice,
-				INT_STATUS_ENABLE_ADDRESS,
-				(char *) &regs,
-				sizeof(struct MBOX_IRQ_ENABLE_REGISTERS),
-				HIF_WR_SYNC_BYTE_INC, NULL);
+	/* reset the recv counter that tracks when we need
+	 * to yield from the DSR
+	 */
+	pdev->CurrentDSRRecvCount = 0;
+	/* reset counter used to flag a re-scan of IRQ
+	 * status registers on the target
+	 */
+	pdev->RecheckIRQStatusCnt = 0;
+
+	while (!done) {
+		status = hif_dev_process_pending_irqs(pdev, &done, &async_proc);
+		if (QDF_IS_STATUS_ERROR(status))
+			break;
+
+		if (pdev->HifIRQProcessingMode == HIF_DEVICE_IRQ_SYNC_ONLY) {
+			/* the HIF layer does not allow async IRQ processing,
+			 * override the asyncProc flag
+			 */
+			async_proc = false;
+			/* this will cause us to re-enter ProcessPendingIRQ()
+			 * and re-read interrupt status registers.
+			 * This has a nice side effect of blocking us until all
+			 * async read requests are completed. This behavior is
+			 * required as we  do not allow ASYNC processing
+			 * in interrupt handlers (like Windows CE)
+			 */
+
+			if (pdev->DSRCanYield && DEV_CHECK_RECV_YIELD(pdev))
+				/* ProcessPendingIRQs() pulled enough recv
+				 * messages to satisfy the yield count, stop
+				 * checking for more messages and return
+				 */
+				break;
+		}
 
-	if (status != QDF_STATUS_SUCCESS) {
-		/* Can't write it for some reason */
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-		  ("Failed to update interrupt control registers err: %d\n",
-				 status));
+		if (async_proc) {
+			/* the function does some async I/O for performance,
+			 * we need to exit the ISR immediately, the check below
+			 * will prevent the interrupt from being
+			 * Ack'd while we handle it asynchronously
+			 */
+			break;
+		}
+	}
 
+	if (QDF_IS_STATUS_SUCCESS(status) && !async_proc) {
+		/* Ack the interrupt only if :
+		 *  1. we did not get any errors in processing interrupts
+		 *  2. there are no outstanding async processing requests
+		 */
+		if (pdev->DSRCanYield) {
+			/* if the DSR can yield do not ACK the interrupt, there
+			 * could be more pending messages. The HIF layer
+			 * must ACK the interrupt on behalf of HTC
+			 */
+			HIF_INFO("%s:  Yield (RX count: %d)",
+				 __func__, pdev->CurrentDSRRecvCount);
+		} else {
+			HIF_INFO("%s: Ack interrupt", __func__);
+			hif_ack_interrupt(pdev->HIFDevice);
+		}
 	}
+
 	HIF_EXIT();
 	return status;
 }
@@ -436,12 +314,8 @@ QDF_STATUS hif_dev_setup(struct hif_sdio_device *pdev)
 				      &pdev->MailBoxInfo,
 				      sizeof(pdev->MailBoxInfo));
 
-	if (status != QDF_STATUS_SUCCESS) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				("(%s)HIF_DEVICE_GET_MBOX_ADDR failed!!!\n",
-				 __func__));
-		A_ASSERT(false);
-	}
+	if (status != QDF_STATUS_SUCCESS)
+		HIF_ERROR("%s: HIF_DEVICE_GET_MBOX_ADDR failed", __func__);
 
 	status = hif_configure_device(hif_device,
 				      HIF_DEVICE_GET_MBOX_BLOCK_SIZE,

+ 18 - 4
hif/src/sdio/hif_sdio_dev.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016, 2018 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -45,10 +45,24 @@ QDF_STATUS hif_dev_send_buffer(struct hif_sdio_device *htc_sdio_device,
 			     unsigned int transfer_id, uint8_t pipe,
 			     unsigned int nbytes, qdf_nbuf_t buf);
 
-QDF_STATUS hif_dev_map_service_to_pipe(struct hif_sdio_device *pdev,
+QDF_STATUS hif_dev_process_pending_irqs(struct hif_sdio_device *pdev,
+					bool *done,
+					      bool *async_processing);
+
+void hif_dev_mask_interrupts(struct hif_sdio_device *pdev);
+
+QDF_STATUS hif_dev_map_service_to_pipe(struct hif_sdio_dev *pdev,
 				       uint16_t service_id,
 				       uint8_t *ul_pipe,
-				       uint8_t *dl_pipe,
-				       bool swap_mapping);
+				       uint8_t *dl_pipe);
+
+void hif_dev_unmask_interrupts(struct hif_sdio_device *pdev);
+
+#ifdef CONFIG_SDIO_TRANSFER_MAILBOX
+QDF_STATUS hif_dev_get_mbox_address(struct hif_sdio_dev *pdev,
+				    struct hif_device_mbox_info *config,
+				    uint32_t config_len);
 
+void hif_dev_get_mbox_block_size(void *config);
+#endif
 #endif /* HIF_SDIO_DEV_H_ */

+ 1 - 7
hif/src/sdio/hif_sdio_internal.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 2016-2018 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -136,12 +136,6 @@ struct hif_sdio_device {
 /* hif_sdio_dev.c */
 HTC_PACKET *hif_dev_alloc_rx_buffer(struct hif_sdio_device *pDev);
 
-uint8_t hif_dev_map_pipe_to_mail_box(struct hif_sdio_device *pDev,
-			uint8_t pipeid);
-uint8_t hif_dev_map_mail_box_to_pipe(struct hif_sdio_device *pDev,
-			uint8_t mboxIndex,
-				     bool upload);
-
 /* hif_sdio_recv.c */
 QDF_STATUS hif_dev_rw_completion_handler(void *context, QDF_STATUS status);
 QDF_STATUS hif_dev_dsr_handler(void *context);

+ 0 - 1538
hif/src/sdio/hif_sdio_recv.c

@@ -1,1538 +0,0 @@
-/*
- * Copyright (c) 2014-2017 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for
- * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define ATH_MODULE_NAME hif
-#include <qdf_types.h>
-#include <qdf_status.h>
-#include <qdf_timer.h>
-#include <qdf_time.h>
-#include <qdf_lock.h>
-#include <qdf_mem.h>
-#include <qdf_util.h>
-#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>
-#include <athdefs.h>
-#include <a_osapi.h>
-#include <hif.h>
-#include <htc_services.h>
-#include "hif_sdio_internal.h"
-#include <htc_internal.h>
-#include "regtable_sdio.h"
-#include "if_sdio.h"
-
-#define NBUF_ALLOC_FAIL_WAIT_TIME 100
-/* high nibble */
-#define BUNDLE_COUNT_HIGH(f) ((f & 0x0C) << 2)
-/* low nibble */
-#define BUNDLE_COUNT_LOW(f)  ((f & 0xF0) >> 4)
-#define GET_RECV_BUNDLE_COUNT(f) (BUNDLE_COUNT_HIGH(f) + BUNDLE_COUNT_LOW(f))
-
-static void hif_dev_dump_registers(struct hif_sdio_device *pdev,
-				struct MBOX_IRQ_PROC_REGISTERS *irq_proc_regs,
-				struct MBOX_IRQ_ENABLE_REGISTERS *
-				irq_enable_regs,
-				struct MBOX_COUNTER_REGISTERS *
-				mailbox_counter_registers)
-{
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("RegTable->"));
-
-	if (irq_proc_regs != NULL) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("HostIntStatus: 0x%x ",
-				 irq_proc_regs->host_int_status));
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("CPUIntStatus: 0x%x ",
-				 irq_proc_regs->cpu_int_status));
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("ErrorIntStatus: 0x%x ",
-				 irq_proc_regs->error_int_status));
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("CounterIntStatus: 0x%x ",
-				 irq_proc_regs->counter_int_status));
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("MboxFrame: 0x%x ",
-				 irq_proc_regs->mbox_frame));
-
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("\nRegTable->"));
-
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("RxLKAValid: 0x%x ",
-				 irq_proc_regs->rx_lookahead_valid));
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("RxLKA0: 0x%x",
-				 irq_proc_regs->rx_lookahead[0]));
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("RxLKA1: 0x%x ",
-				 irq_proc_regs->rx_lookahead[1]));
-
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("RxLKA2: 0x%x ",
-				 irq_proc_regs->rx_lookahead[2]));
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("RxLKA3: 0x%x",
-				 irq_proc_regs->rx_lookahead[3]));
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("\nRegTable->"));
-
-		if (pdev->MailBoxInfo.gmbox_address != 0) {
-			/* if the target supports GMBOX hardware,
-			 * dump some additional state
-			 */
-			AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-					("GMBOX-HostIntStatus2:  0x%x ",
-					 irq_proc_regs->host_int_status2));
-			AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-					("GMBOX-RX-Avail: 0x%x ",
-					 irq_proc_regs->gmbox_rx_avail));
-		}
-	}
-
-	if (irq_enable_regs != NULL) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("Int Status Enable:         0x%x\n",
-				 irq_enable_regs->int_status_enable));
-		AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-				("Counter Int Status Enable: 0x%x\n",
-				 irq_enable_regs->counter_int_status_enable));
-	}
-
-	if (mailbox_counter_registers != NULL) {
-		int i;
-
-		for (i = 0; i < 4; i++) {
-			AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-					("Counter[%d]:               0x%x\n", i,
-					 mailbox_counter_registers->
-								counter[i]));
-		}
-	}
-	AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
-			("<------------------------------->\n"));
-}
-
-static
-QDF_STATUS hif_dev_alloc_and_prepare_rx_packets(struct hif_sdio_device *pdev,
-						uint32_t look_aheads[],
-						int messages,
-						HTC_PACKET_QUEUE *queue)
-{
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	HTC_PACKET *packet;
-	HTC_FRAME_HDR *hdr;
-	int i, j;
-	int num_messages;
-	int full_length;
-	bool no_recycle;
-
-	/* lock RX while we assemble the packet buffers */
-	LOCK_HIF_DEV_RX(pdev);
-
-	for (i = 0; i < messages; i++) {
-
-		hdr = (HTC_FRAME_HDR *) &look_aheads[i];
-		if (hdr->EndpointID >= ENDPOINT_MAX) {
-			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-					("Invalid Endpoint in look-ahead: %d\n",
-					 hdr->EndpointID));
-			/* invalid endpoint */
-			status = QDF_STATUS_E_PROTO;
-			break;
-		}
-
-		if (hdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) {
-			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				("Payload length %d exceeds max HTC : %d !\n",
-				 hdr->PayloadLen,
-				 (uint32_t) HTC_MAX_PAYLOAD_LENGTH));
-			status = QDF_STATUS_E_PROTO;
-			break;
-		}
-
-		if ((hdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) == 0) {
-			/* HTC header only indicates 1 message to fetch */
-			num_messages = 1;
-		} else {
-			/* HTC header indicates that every packet to follow
-			 * has the same padded length so that it can
-			 * be optimally fetched as a full bundle
-			 */
-			num_messages = GET_RECV_BUNDLE_COUNT(hdr->Flags);
-			/* the count doesn't include the starter frame, just
-			 * a count of frames to follow
-			 */
-			num_messages++;
-			/* A_ASSERT(numMessages <= target->MaxMsgPerBundle); */
-			AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
-				("HTC header indicates :%d messages can be fetched as a bundle\n",
-				 num_messages));
-		}
-
-		full_length =
-			DEV_CALC_RECV_PADDED_LEN(pdev,
-						 hdr->PayloadLen +
-						 sizeof(HTC_FRAME_HDR));
-
-		/* get packet buffers for each message, if there was a
-		 * bundle detected in the header,
-		 * use pHdr as a template to fetch all packets in the bundle
-		 */
-		for (j = 0; j < num_messages; j++) {
-
-			/* reset flag, any packets allocated using the
-			 * RecvAlloc() API cannot be recycled on cleanup,
-			 * they must be explicitly returned
-			 */
-			no_recycle = false;
-			packet = hif_dev_alloc_rx_buffer(pdev);
-
-			if (packet == NULL) {
-				/* No error, simply need to mark that
-				 * we are waiting for buffers.
-				 */
-				pdev->RecvStateFlags |= HTC_RECV_WAIT_BUFFERS;
-				/* pDev->EpWaitingForBuffers = pEndpoint->Id; */
-				status = QDF_STATUS_E_RESOURCES;
-				break;
-			}
-			/* AR_DEBUG_ASSERT(pPacket->Endpoint == pEndpoint->Id);
-			 */
-			/* clear flags */
-			packet->PktInfo.AsRx.HTCRxFlags = 0;
-			packet->PktInfo.AsRx.IndicationFlags = 0;
-			packet->Status = QDF_STATUS_SUCCESS;
-
-			if (no_recycle)
-				/* flag that these packets cannot be recycled,
-				 * they have to be returned to the user
-				 */
-				packet->PktInfo.AsRx.HTCRxFlags |=
-					HTC_RX_PKT_NO_RECYCLE;
-			/* add packet to queue (also incase we need to
-			 * cleanup down below)
-			 */
-			HTC_PACKET_ENQUEUE(queue, packet);
-
-			/* if (HTC_STOPPING(target)) {
-			 *      status = QDF_STATUS_E_CANCELED;
-			 *      break;
-			 *  }
-			 */
-
-			/* make sure  message can fit in the endpoint buffer */
-			if ((uint32_t) full_length > packet->BufferLength) {
-				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				("Payload Length Error : header reports payload of: %d (%d) endpoint buffer size: %d\n",
-					 hdr->PayloadLen, full_length,
-					 packet->BufferLength));
-				status = QDF_STATUS_E_PROTO;
-				break;
-			}
-
-			if (j > 0) {
-				/* for messages fetched in a bundle the expected
-				 * lookahead is unknown as we are only using the
-				 * lookahead of the first packet as a template
-				 * of what to expect for lengths
-				 */
-				packet->PktInfo.AsRx.HTCRxFlags |=
-					HTC_RX_PKT_REFRESH_HDR;
-				/* set it to something invalid */
-				packet->PktInfo.AsRx.ExpectedHdr = 0xFFFFFFFF;
-			} else {
-				packet->PktInfo.AsRx.ExpectedHdr =
-					look_aheads[i];
-			}
-			/* set the amount of data to fetch */
-			packet->ActualLength =
-				hdr->PayloadLen + HTC_HDR_LENGTH;
-			if ((j == (num_messages-1))
-				&& ((hdr->Flags) & HTC_FLAGS_RECV_1MORE_BLOCK))
-				packet->PktInfo.AsRx.HTCRxFlags |=
-				HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK;
-			packet->Endpoint = hdr->EndpointID;
-			packet->Completion = NULL;
-		}
-
-		if (QDF_IS_STATUS_ERROR(status)) {
-			break;
-		}
-
-	}
-
-	UNLOCK_HIF_DEV_RX(pdev);
-
-	/* for NO RESOURCE error, no need to flush data queue */
-	if (QDF_IS_STATUS_ERROR(status)
-		&& (status != QDF_STATUS_E_RESOURCES)) {
-		while (!HTC_QUEUE_EMPTY(queue)) {
-			qdf_nbuf_t netbuf;
-			packet = htc_packet_dequeue(queue);
-			if (packet == NULL)
-				break;
-			netbuf = (qdf_nbuf_t) packet->pNetBufContext;
-			if (netbuf)
-				qdf_nbuf_free(netbuf);
-		}
-	}
-	if (status == QDF_STATUS_E_RESOURCES)
-		status = QDF_STATUS_SUCCESS;
-	return status;
-}
-
-static inline QDF_STATUS hif_dev_recv_packet(struct hif_sdio_device *pdev,
-				   HTC_PACKET *packet,
-				   uint32_t recv_length, uint8_t mbox_index)
-{
-	uint32_t padded_length;
-	QDF_STATUS status;
-	bool sync = (packet->Completion == NULL) ? true : false;
-
-	/* adjust the length to be a multiple of block size if appropriate */
-	padded_length = DEV_CALC_RECV_PADDED_LEN(pdev, recv_length);
-
-	if (padded_length > packet->BufferLength) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d\n",
-				 padded_length, recv_length,
-				 packet->BufferLength));
-		if (packet->Completion != NULL) {
-			COMPLETE_HTC_PACKET(packet, QDF_STATUS_E_INVAL);
-			return QDF_STATUS_SUCCESS;
-		}
-		return QDF_STATUS_E_INVAL;
-	}
-
-	/* mailbox index is saved in Endpoint member */
-	AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
-			("hif_dev_recv_packet (0x%lX : hdr:0x%X) Len:%d, Padded Length: %d Mbox:0x%X\n",
-			 (unsigned long)packet,
-			 packet->PktInfo.AsRx.ExpectedHdr, recv_length,
-			 padded_length,
-			 pdev->MailBoxInfo.mbox_addresses[mbox_index]));
-	status = hif_read_write(pdev->HIFDevice,
-				pdev->MailBoxInfo.mbox_addresses[mbox_index],
-				packet->pBuffer, padded_length,
-				(sync ? HIF_RD_SYNC_BLOCK_FIX :
-							HIF_RD_ASYNC_BLOCK_FIX),
-				sync ? NULL : packet);
-	AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("EP%d, Seq:%d\n",
-					 ((HTC_FRAME_HDR *) packet->pBuffer)->
-					 EndpointID,
-					 ((HTC_FRAME_HDR *) packet->pBuffer)->
-					 ControlBytes1));
-	if (status != QDF_STATUS_SUCCESS) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
-			("hif_dev_recv_packet (0x%lX : hdr:0x%X) Failed\n",
-			 (unsigned long)packet,
-			 packet->PktInfo.AsRx.ExpectedHdr));
-	}
-	if (sync) {
-		packet->Status = status;
-		if (status == QDF_STATUS_SUCCESS) {
-			HTC_FRAME_HDR *hdr =
-				(HTC_FRAME_HDR *) packet->pBuffer;
-			AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
-				("hif_dev_recv_packet EP:%d,Len:%d,Flag:%d,CB:0x%02X,0x%02X\n",
-				 hdr->EndpointID, hdr->PayloadLen,
-				 hdr->Flags, hdr->ControlBytes0,
-				 hdr->ControlBytes1));
-		}
-	}
-
-	return status;
-}
-
-static inline QDF_STATUS hif_dev_process_trailer(struct hif_sdio_device *pdev,
-				       uint8_t *buffer, int length,
-				       uint32_t *next_look_aheads,
-				       int *num_look_aheads,
-				       HTC_ENDPOINT_ID from_endpoint)
-{
-	HTC_RECORD_HDR *record;
-	uint8_t *record_buf;
-	HTC_LOOKAHEAD_REPORT *look_ahead;
-	uint8_t *orig_buffer;
-	int orig_length;
-	QDF_STATUS status;
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
-			("+htc_process_trailer (length:%d)\n", length));
-
-	if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV))
-		AR_DEBUG_PRINTBUF(buffer, length, "Recv Trailer");
-
-	orig_buffer = buffer;
-	orig_length = length;
-	status = QDF_STATUS_SUCCESS;
-
-	while (length > 0) {
-
-		if (length < sizeof(HTC_RECORD_HDR)) {
-			status = QDF_STATUS_E_PROTO;
-			break;
-		}
-		/* these are byte aligned structs */
-		record = (HTC_RECORD_HDR *) buffer;
-		length -= sizeof(HTC_RECORD_HDR);
-		buffer += sizeof(HTC_RECORD_HDR);
-
-		if (record->Length > length) {
-			/* no room left in buffer for record */
-			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				(" invalid record len: %d (id:%d) buffer has:%d bytes left\n",
-				 record->Length, record->RecordID,
-				 length));
-			status = QDF_STATUS_E_PROTO;
-			break;
-		}
-		/* start of record follows the header */
-		record_buf = buffer;
-
-		switch (record->RecordID) {
-		case HTC_RECORD_CREDITS:
-			/* Process in HTC, ignore here */
-			break;
-		case HTC_RECORD_LOOKAHEAD:
-			AR_DEBUG_ASSERT(record->Length >=
-					sizeof(HTC_LOOKAHEAD_REPORT));
-			look_ahead = (HTC_LOOKAHEAD_REPORT *) record_buf;
-			if ((look_ahead->PreValid ==
-			     ((~look_ahead->PostValid) & 0xFF))
-			    && (next_look_aheads != NULL)) {
-
-				AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
-					(" look_ahead Report (pre valid:0x%X, post valid:0x%X) %d %d\n",
-					 look_ahead->PreValid,
-					 look_ahead->PostValid,
-					 from_endpoint,
-					 look_ahead->LookAhead0));
-				/* look ahead bytes are valid, copy them over */
-				((uint8_t *) (&next_look_aheads[0]))[0] =
-					look_ahead->LookAhead0;
-				((uint8_t *) (&next_look_aheads[0]))[1] =
-					look_ahead->LookAhead1;
-				((uint8_t *) (&next_look_aheads[0]))[2] =
-					look_ahead->LookAhead2;
-				((uint8_t *) (&next_look_aheads[0]))[3] =
-					look_ahead->LookAhead3;
-
-				if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
-					debug_dump_bytes((uint8_t *)
-							 next_look_aheads, 4,
-							 "Next Look Ahead");
-				}
-				/* just one normal lookahead */
-				if (num_look_aheads != NULL)
-					*num_look_aheads = 1;
-			}
-			break;
-		case HTC_RECORD_LOOKAHEAD_BUNDLE:
-			AR_DEBUG_ASSERT(record->Length >=
-					sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT));
-			if (record->Length >=
-			    sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)
-			    && (next_look_aheads != NULL)) {
-				HTC_BUNDLED_LOOKAHEAD_REPORT
-				*pBundledLookAheadRpt;
-				int i;
-
-				pBundledLookAheadRpt =
-				(HTC_BUNDLED_LOOKAHEAD_REPORT *) record_buf;
-
-				if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
-					debug_dump_bytes(record_buf,
-							 record->Length,
-							 "Bundle look_ahead");
-				}
-
-				if ((record->Length /
-				     (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)))
-					> HTC_MAX_MSG_PER_BUNDLE_RX) {
-					/* this should never happen, the target
-					 * restricts the number of messages per
-					 * bundle configured by the host
-					 */
-					A_ASSERT(false);
-					status = QDF_STATUS_E_PROTO;
-					break;
-				}
-				for (i = 0;
-				     i <
-				     (int)(record->Length /
-					   (sizeof
-					    (HTC_BUNDLED_LOOKAHEAD_REPORT)));
-				     i++) {
-					((uint8_t *)(&next_look_aheads[i]))[0] =
-					   pBundledLookAheadRpt->LookAhead0;
-					((uint8_t *)(&next_look_aheads[i]))[1] =
-					   pBundledLookAheadRpt->LookAhead1;
-					((uint8_t *)(&next_look_aheads[i]))[2] =
-					   pBundledLookAheadRpt->LookAhead2;
-					((uint8_t *)(&next_look_aheads[i]))[3] =
-					   pBundledLookAheadRpt->LookAhead3;
-					pBundledLookAheadRpt++;
-				}
-				if (num_look_aheads) {
-					*num_look_aheads = i;
-				}
-			}
-			break;
-		default:
-			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				(" HIF unhandled record: id:%d length:%d\n",
-				 record->RecordID, record->Length));
-			break;
-		}
-
-		if (QDF_IS_STATUS_ERROR(status))
-			break;
-
-		/* advance buffer past this record for next time around */
-		buffer += record->Length;
-		length -= record->Length;
-	}
-
-	if (QDF_IS_STATUS_ERROR(status))
-		debug_dump_bytes(orig_buffer, orig_length,
-				  "BAD Recv Trailer");
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-htc_process_trailer\n"));
-	return status;
-
-}
-
-/* process a received message (i.e. strip off header,
- * process any trailer data).
- * note : locks must be released when this function is called
- */
-static QDF_STATUS hif_dev_process_recv_header(struct hif_sdio_device *pdev,
-				    HTC_PACKET *packet,
-				    uint32_t *next_look_aheads,
-				    int *num_look_aheads)
-{
-	uint8_t temp;
-	uint8_t *buf;
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	uint16_t payloadLen;
-	uint32_t look_ahead, actual_length;
-
-	buf = packet->pBuffer;
-	actual_length = packet->ActualLength;
-
-	if (num_look_aheads != NULL)
-		*num_look_aheads = 0;
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader\n"));
-
-	if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV))
-		AR_DEBUG_PRINTBUF(buf, packet->ActualLength, "HTC Recv PKT");
-
-	do {
-		/* note, we cannot assume the alignment of pBuffer,
-		 * so we use the safe macros to
-		 * retrieve 16 bit fields
-		 */
-		payloadLen = HTC_GET_FIELD(buf, HTC_FRAME_HDR,
-					PAYLOADLEN);
-
-		((uint8_t *) &look_ahead)[0] = buf[0];
-		((uint8_t *) &look_ahead)[1] = buf[1];
-		((uint8_t *) &look_ahead)[2] = buf[2];
-		((uint8_t *) &look_ahead)[3] = buf[3];
-
-		if (packet->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) {
-			/* refresh expected hdr, since this was unknown
-			 * at the time we grabbed the packets
-			 * as part of a bundle
-			 */
-			packet->PktInfo.AsRx.ExpectedHdr = look_ahead;
-			/* refresh actual length since we now have the
-			 * real header
-			 */
-			packet->ActualLength = payloadLen + HTC_HDR_LENGTH;
-
-			/* validate the actual header that was refreshed  */
-			if (packet->ActualLength > packet->BufferLength) {
-				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-					("Invalid  HDR payload length (%d) in bundled RECV (hdr: 0x%X)\n",
-						 payloadLen, look_ahead));
-				/* limit this to max buffer just to print out
-				 * some of the buffer
-				 */
-				packet->ActualLength =
-					min(packet->ActualLength,
-					    packet->BufferLength);
-				status = QDF_STATUS_E_PROTO;
-				break;
-			}
-
-			if (packet->Endpoint
-			    != HTC_GET_FIELD(buf, HTC_FRAME_HDR, ENDPOINTID)) {
-				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-					("Refreshed HDR endpoint (%d) does not match expected endpoint (%d)\n",
-					 HTC_GET_FIELD(buf,
-							       HTC_FRAME_HDR,
-							       ENDPOINTID),
-						 packet->Endpoint));
-				status = QDF_STATUS_E_PROTO;
-				break;
-			}
-		}
-
-		if (look_ahead != packet->PktInfo.AsRx.ExpectedHdr) {
-			/* somehow the lookahead that gave us the full read
-			 * length did not reflect the actual header
-			 * in the pending message
-			 */
-			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-			   ("hif_dev_process_recv_header, lookahead mismatch! (pPkt:0x%lX flags:0x%X), 0x%08X != 0x%08X\n",
-				 (unsigned long)packet,
-				 packet->PktInfo.AsRx.HTCRxFlags,
-				 look_ahead,
-				 packet->PktInfo.AsRx.ExpectedHdr));
-#ifdef ATH_DEBUG_MODULE
-			debug_dump_bytes((uint8_t *) &packet->PktInfo.AsRx.
-				 ExpectedHdr, 4,
-				 "Expected Message look_ahead");
-			debug_dump_bytes(buf, sizeof(HTC_FRAME_HDR),
-				 "Current Frame Header");
-#ifdef HTC_CAPTURE_LAST_FRAME
-			debug_dump_bytes((uint8_t *) &target->LastFrameHdr,
-				 sizeof(HTC_FRAME_HDR),
-				 "Last Frame Header");
-			if (target->LastTrailerLength != 0)
-				debug_dump_bytes(target->LastTrailer,
-					 target->LastTrailerLength,
-					 "Last trailer");
-#endif
-#endif
-			status = QDF_STATUS_E_PROTO;
-			break;
-		}
-
-		/* get flags */
-		temp = HTC_GET_FIELD(buf, HTC_FRAME_HDR, FLAGS);
-
-		if (temp & HTC_FLAGS_RECV_TRAILER) {
-			/* this packet has a trailer */
-
-			/* extract the trailer length in control byte 0 */
-			temp =
-				HTC_GET_FIELD(buf, HTC_FRAME_HDR,
-					CONTROLBYTES0);
-
-			if ((temp < sizeof(HTC_RECORD_HDR))
-			    || (temp > payloadLen)) {
-				AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				("hif_dev_process_recv_header, invalid header(payloadlength should be :%d, CB[0] is:%d)\n",
-					 payloadLen, temp));
-				status = QDF_STATUS_E_PROTO;
-				break;
-			}
-
-			if (packet->PktInfo.AsRx.
-			    HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
-				/* this packet was fetched as part of an HTC
-				 * bundle as the lookahead is not valid.
-				 * Next packet may have already been fetched as
-				 * part of the bundle
-				 */
-				next_look_aheads = NULL;
-				num_look_aheads = NULL;
-			}
-
-			/* process trailer data that follows HDR and
-			 * application payload
-			 */
-			status = hif_dev_process_trailer(pdev,
-						 (buf + HTC_HDR_LENGTH +
-						  payloadLen - temp), temp,
-						 next_look_aheads,
-						 num_look_aheads,
-						 packet->Endpoint);
-
-			if (QDF_IS_STATUS_ERROR(status))
-				break;
-		}
-	} while (false);
-
-	if (QDF_IS_STATUS_ERROR(status)) {
-		/* dump the whole packet */
-		debug_dump_bytes(buf, packet->ActualLength,
-			 "BAD HTC Recv PKT");
-	} else {
-		if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
-			if (packet->ActualLength > 0) {
-				AR_DEBUG_PRINTBUF(packet->pBuffer,
-						  packet->ActualLength,
-						  "HTC - Application Msg");
-			}
-		}
-	}
-	AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
-			("-hif_dev_process_recv_header\n"));
-	return status;
-}
-
-static QDF_STATUS hif_dev_issue_recv_packet_bundle(struct hif_sdio_device *pdev,
-					 HTC_PACKET_QUEUE *recv_pkt_queue,
-					 HTC_PACKET_QUEUE *
-					 sync_completion_queue,
-					 uint8_t mail_box_index,
-					 int *num_packets_fetched,
-					 bool partial_bundle)
-{
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	int i, total_length = 0;
-	unsigned char *bundle_buffer = NULL;
-	HTC_PACKET *packet, *packet_rx_bundle;
-	HTC_TARGET *target = NULL;
-	uint32_t padded_length;
-	int bundleSpaceRemaining = 0;
-
-	target = (HTC_TARGET *) pdev->pTarget;
-
-	if ((HTC_PACKET_QUEUE_DEPTH(recv_pkt_queue) -
-		 HTC_MAX_MSG_PER_BUNDLE_RX) > 0) {
-		partial_bundle = true;
-		AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
-				("%s, partial bundle detected num: %d, %d\n",
-				 __func__,
-				 HTC_PACKET_QUEUE_DEPTH(recv_pkt_queue),
-				 HTC_MAX_MSG_PER_BUNDLE_RX));
-	}
-
-	bundleSpaceRemaining =
-		HTC_MAX_MSG_PER_BUNDLE_RX * 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;
-	     !HTC_QUEUE_EMPTY(recv_pkt_queue) && i < HTC_MAX_MSG_PER_BUNDLE_RX;
-	     i++) {
-		packet = htc_packet_dequeue(recv_pkt_queue);
-		A_ASSERT(packet != NULL);
-		if (!packet) {
-			break;
-		}
-		padded_length =
-			DEV_CALC_RECV_PADDED_LEN(pdev, packet->ActualLength);
-		if (packet->PktInfo.AsRx.HTCRxFlags &
-				HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK)
-			padded_length += HIF_MBOX_BLOCK_SIZE;
-		if ((bundleSpaceRemaining - padded_length) < 0) {
-			/* exceeds what we can transfer, put the packet back */
-			HTC_PACKET_ENQUEUE_TO_HEAD(recv_pkt_queue, packet);
-			break;
-		}
-		bundleSpaceRemaining -= padded_length;
-
-		if (partial_bundle ||
-			HTC_PACKET_QUEUE_DEPTH(recv_pkt_queue) > 0) {
-			packet->PktInfo.AsRx.HTCRxFlags |=
-				HTC_RX_PKT_IGNORE_LOOKAHEAD;
-		}
-		packet->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_PART_OF_BUNDLE;
-
-		if (sync_completion_queue) {
-			HTC_PACKET_ENQUEUE(sync_completion_queue, packet);
-		}
-		total_length += padded_length;
-	}
-#if DEBUG_BUNDLE
-	qdf_print("Recv bundle count %d, length %d.\n",
-		sync_completion_queue ?
-		HTC_PACKET_QUEUE_DEPTH(sync_completion_queue) : 0,
-		total_length);
-#endif
-
-	status = hif_read_write(pdev->HIFDevice,
-				pdev->MailBoxInfo.
-				mbox_addresses[(int)mail_box_index],
-				bundle_buffer, total_length,
-				HIF_RD_SYNC_BLOCK_FIX, NULL);
-
-	if (status != QDF_STATUS_SUCCESS) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				("%s, hif_send Failed status:%d\n",
-				 __func__, status));
-	} else {
-		unsigned char *buffer = bundle_buffer;
-		*num_packets_fetched = i;
-		if (sync_completion_queue) {
-			HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(
-				sync_completion_queue, packet) {
-				padded_length =
-					DEV_CALC_RECV_PADDED_LEN(pdev,
-						packet->ActualLength);
-				if (packet->PktInfo.AsRx.HTCRxFlags &
-				HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK)
-					padded_length +=
-						HIF_MBOX_BLOCK_SIZE;
-				A_MEMCPY(packet->pBuffer,
-					buffer, padded_length);
-				buffer += padded_length;
-			} HTC_PACKET_QUEUE_ITERATE_END;
-		}
-	}
-	/* free bundle space under Sync mode */
-	free_htc_bundle_packet(target, packet_rx_bundle);
-	return status;
-}
-
-static inline void hif_dev_free_recv_pkt_queue(HTC_PACKET_QUEUE *recv_pkt_queue)
-{
-	HTC_PACKET *packet;
-	qdf_nbuf_t netbuf;
-
-	while (!HTC_QUEUE_EMPTY(recv_pkt_queue)) {
-
-		packet = htc_packet_dequeue(recv_pkt_queue);
-		if (packet == NULL)
-			break;
-		netbuf = (qdf_nbuf_t) packet->
-				pNetBufContext;
-		if (netbuf)
-			qdf_nbuf_free(netbuf);
-	}
-}
-
-static
-QDF_STATUS hif_dev_recv_message_pending_handler(struct hif_sdio_device *pdev,
-					uint8_t mail_box_index,
-					uint32_t msg_look_aheads[],
-					int num_look_aheads,
-					bool *async_proc,
-					int *num_pkts_fetched)
-{
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	HTC_PACKET *packet;
-	bool asyncProc = false;
-	uint32_t look_aheads[HTC_MAX_MSG_PER_BUNDLE_RX];
-	int pkts_fetched;
-	HTC_PACKET_QUEUE recv_pkt_queue, sync_completed_pkts_queue;
-	bool partial_bundle;
-	HTC_ENDPOINT_ID id;
-	int total_fetched = 0;
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
-			("+HTCRecvMessagePendingHandler NumLookAheads: %d\n",
-			 num_look_aheads));
-
-	if (num_pkts_fetched != NULL)
-		*num_pkts_fetched = 0;
-
-	if (IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pdev)) {
-		/* We use async mode to get the packets if the
-		 * device layer supports it. The device layer
-		 * interfaces with HIF in which HIF may have
-		 * restrictions on how interrupts are processed
-		 */
-		asyncProc = true;
-	}
-
-	if (async_proc != NULL)
-		/* indicate to caller how we decided to process this */
-		*async_proc = asyncProc;
-	if (num_look_aheads > HTC_MAX_MSG_PER_BUNDLE_RX) {
-		A_ASSERT(false);
-		return QDF_STATUS_E_PROTO;
-	}
-	A_MEMCPY(look_aheads, msg_look_aheads,
-		(sizeof(uint32_t)) * num_look_aheads);
-	while (true) {
-
-		/* reset packets queues */
-		INIT_HTC_PACKET_QUEUE(&recv_pkt_queue);
-		INIT_HTC_PACKET_QUEUE(&sync_completed_pkts_queue);
-		if (num_look_aheads > HTC_MAX_MSG_PER_BUNDLE_RX) {
-			status = QDF_STATUS_E_PROTO;
-			A_ASSERT(false);
-			break;
-		}
-
-		/* first lookahead sets the expected endpoint IDs for
-		 * all packets in a bundle
-		 */
-		id = ((HTC_FRAME_HDR *) &look_aheads[0])->EndpointID;
-
-		if (id >= ENDPOINT_MAX) {
-			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				("MsgPend, Invalid Endpoint in lookahead: %d\n",
-				 id));
-			status = QDF_STATUS_E_PROTO;
-			break;
-		}
-		/* try to allocate as many HTC RX packets indicated
-		 * by the lookaheads these packets are stored
-		 * in the recvPkt queue
-		 */
-		status = hif_dev_alloc_and_prepare_rx_packets(pdev,
-							      look_aheads,
-							      num_look_aheads,
-							      &recv_pkt_queue);
-		if (QDF_IS_STATUS_ERROR(status))
-			break;
-		total_fetched += HTC_PACKET_QUEUE_DEPTH(&recv_pkt_queue);
-
-		/* we've got packet buffers for all we can currently fetch,
-		 * this count is not valid anymore
-		 */
-		num_look_aheads = 0;
-		partial_bundle = false;
-
-		/* now go fetch the list of HTC packets */
-		while (!HTC_QUEUE_EMPTY(&recv_pkt_queue)) {
-
-			pkts_fetched = 0;
-			if ((HTC_PACKET_QUEUE_DEPTH(&recv_pkt_queue) > 1)) {
-				/* there are enough packets to attempt a bundle
-				 * transfer and recv bundling is allowed
-				 */
-				status = hif_dev_issue_recv_packet_bundle(pdev,
-						  &recv_pkt_queue,
-						  asyncProc ?
-						  NULL :
-						  &sync_completed_pkts_queue,
-						  mail_box_index,
-						  &pkts_fetched,
-						  partial_bundle);
-				if (QDF_IS_STATUS_ERROR(status)) {
-					hif_dev_free_recv_pkt_queue(
-							&recv_pkt_queue);
-					break;
-				}
-
-				if (HTC_PACKET_QUEUE_DEPTH(&recv_pkt_queue) !=
-					0) {
-					/* we couldn't fetch all packets at one,
-					 * time this creates a broken
-					 * bundle
-					 */
-					partial_bundle = true;
-				}
-			}
-
-			/* see if the previous operation fetched any
-			 * packets using bundling
-			 */
-			if (0 == pkts_fetched) {
-				/* dequeue one packet */
-				packet = htc_packet_dequeue(&recv_pkt_queue);
-				A_ASSERT(packet != NULL);
-				if (!packet) {
-					break;
-				}
-
-				packet->Completion = NULL;
-
-				if (HTC_PACKET_QUEUE_DEPTH(&recv_pkt_queue) >
-				    0) {
-					/* lookaheads in all packets except the
-					 * last one in must be ignored
-					 */
-					packet->PktInfo.AsRx.HTCRxFlags |=
-						HTC_RX_PKT_IGNORE_LOOKAHEAD;
-				}
-
-				/* go fetch the packet */
-				status =
-					hif_dev_recv_packet(pdev, packet,
-						    packet->ActualLength,
-						    mail_box_index);
-				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;
-				}
-				/* sent synchronously, queue this packet for
-				 * synchronous completion
-				 */
-				HTC_PACKET_ENQUEUE(&sync_completed_pkts_queue,
-						   packet);
-			}
-		}
-
-		/* synchronous handling */
-		if (pdev->DSRCanYield) {
-			/* for the SYNC case, increment count that tracks
-			 * when the DSR should yield
-			 */
-			pdev->CurrentDSRRecvCount++;
-		}
-
-		/* in the sync case, all packet buffers are now filled,
-		 * we can process each packet, check lookahead , then repeat
-		 */
-
-		/* unload sync completion queue */
-		while (!HTC_QUEUE_EMPTY(&sync_completed_pkts_queue)) {
-			uint8_t pipeid;
-			qdf_nbuf_t netbuf;
-
-			packet = htc_packet_dequeue(&sync_completed_pkts_queue);
-			A_ASSERT(packet != NULL);
-			if (!packet) {
-				break;
-			}
-
-			num_look_aheads = 0;
-			status =
-				hif_dev_process_recv_header(pdev, packet,
-							    look_aheads,
-							    &num_look_aheads);
-			if (QDF_IS_STATUS_ERROR(status)) {
-				HTC_PACKET_ENQUEUE_TO_HEAD(&sync_completed_pkts_queue,
-					packet);
-				break;
-			}
-
-			netbuf = (qdf_nbuf_t) packet->pNetBufContext;
-			/* set data length */
-			qdf_nbuf_put_tail(netbuf, packet->ActualLength);
-
-			if (pdev->hif_callbacks.rxCompletionHandler) {
-				pipeid =
-					hif_dev_map_mail_box_to_pipe(pdev,
-							mail_box_index,
-							true);
-				pdev->hif_callbacks.rxCompletionHandler(pdev->
-								hif_callbacks.
-								Context,
-								netbuf,
-								pipeid);
-			}
-		}
-
-		if (QDF_IS_STATUS_ERROR(status)) {
-			if (!HTC_QUEUE_EMPTY(&sync_completed_pkts_queue))
-				hif_dev_free_recv_pkt_queue(
-						&sync_completed_pkts_queue);
-			break;
-		}
-
-		if (num_look_aheads == 0) {
-			/* no more look aheads */
-			break;
-		}
-		/* check whether other OS contexts have queued any WMI
-		 * command/data for WLAN. This check is needed only if WLAN
-		 * Tx and Rx happens in same thread context
-		 */
-		/* A_CHECK_DRV_TX(); */
-	}
-	if (num_pkts_fetched != NULL)
-		*num_pkts_fetched = total_fetched;
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvMessagePendingHandler\n"));
-	return status;
-}
-
-/**
- * hif_dev_service_cpu_interrupt() - service fatal interrupts
- * synchronously
- *
- * @pDev: hif sdio device context
- *
- * Return: QDF_STATUS_SUCCESS for success
- */
-static QDF_STATUS hif_dev_service_cpu_interrupt(struct hif_sdio_device *pdev)
-{
-	QDF_STATUS status;
-	uint8_t cpu_int_status;
-	uint8_t reg_buffer[4];
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("CPU Interrupt\n"));
-	cpu_int_status = pdev->IrqProcRegisters.cpu_int_status
-			 & pdev->IrqEnableRegisters.cpu_int_status_enable;
-	A_ASSERT(cpu_int_status);
-	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
-			("Valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n",
-			 cpu_int_status));
-
-	/* Clear the interrupt */
-	pdev->IrqProcRegisters.cpu_int_status &= ~cpu_int_status;
-
-	/*set up the register transfer buffer to hit the register
-	 * 4 times , this is done to make the access 4-byte aligned
-	 * to mitigate issues with host bus interconnects that
-	 * restrict bus transfer lengths to be a multiple of 4-bytes
-	 * set W1C value to clear the interrupt, this hits the register
-	 * first
-	 */
-	reg_buffer[0] = cpu_int_status;
-	/* the remaining 4 values are set to zero which have no-effect  */
-	reg_buffer[1] = 0;
-	reg_buffer[2] = 0;
-	reg_buffer[3] = 0;
-
-	status = hif_read_write(pdev->HIFDevice,
-				CPU_INT_STATUS_ADDRESS,
-				reg_buffer, 4, HIF_WR_SYNC_BYTE_FIX, NULL);
-
-	A_ASSERT(status == QDF_STATUS_SUCCESS);
-
-	/* The Interrupt sent to the Host is generated via bit0
-	 * of CPU INT register
-	 */
-	if (cpu_int_status & 0x1) {
-		if (pdev->hif_callbacks.fwEventHandler)
-			/* It calls into HTC which propagates this
-			 * to ol_target_failure()
-			 */
-			pdev->hif_callbacks.fwEventHandler(pdev->hif_callbacks.
-						Context, QDF_STATUS_E_FAILURE);
-	} else
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
-				("%s: Unable to call fwEventHandler, invalid input arguments\n",
-				 __func__));
-
-	return status;
-}
-
-/**
- * hif_dev_service_error_interrupt() - service error interrupts
- * synchronously
- *
- * @pDev: hif sdio device context
- *
- * Return: QDF_STATUS_SUCCESS for success
- */
-static QDF_STATUS hif_dev_service_error_interrupt(struct hif_sdio_device *pdev)
-{
-	QDF_STATUS status;
-	uint8_t error_int_status;
-	uint8_t reg_buffer[4];
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error Interrupt\n"));
-	error_int_status = pdev->IrqProcRegisters.error_int_status & 0x0F;
-	A_ASSERT(error_int_status);
-	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
-			("Valid interrupt source in ERROR_INT_STATUS: 0x%x\n",
-			 error_int_status));
-
-	if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) {
-		/* Wakeup */
-		AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error : Wakeup\n"));
-	}
-
-	if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) {
-		/* Rx Underflow */
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Rx Underflow\n"));
-	}
-
-	if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) {
-		/* Tx Overflow */
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Tx Overflow\n"));
-	}
-
-	/* Clear the interrupt */
-	pdev->IrqProcRegisters.error_int_status &= ~error_int_status;
-
-	/* set up the register transfer buffer to hit the register
-	 * 4 times , this is done to make the access 4-byte
-	 * aligned to mitigate issues with host bus interconnects that
-	 * restrict bus transfer lengths to be a multiple of 4-bytes
-	 */
-
-	/* set W1C value to clear the interrupt */
-	reg_buffer[0] = error_int_status;
-	/* the remaining 4 values are set to zero which have no-effect  */
-	reg_buffer[1] = 0;
-	reg_buffer[2] = 0;
-	reg_buffer[3] = 0;
-
-	status = hif_read_write(pdev->HIFDevice,
-				ERROR_INT_STATUS_ADDRESS,
-				reg_buffer, 4, HIF_WR_SYNC_BYTE_FIX, NULL);
-
-	A_ASSERT(status == QDF_STATUS_SUCCESS);
-	return status;
-}
-
-/**
- * hif_dev_service_debug_interrupt() - service debug interrupts
- * synchronously
- *
- * @pDev: hif sdio device context
- *
- * Return: QDF_STATUS_SUCCESS for success
- */
-static QDF_STATUS hif_dev_service_debug_interrupt(struct hif_sdio_device *pdev)
-{
-	uint32_t dummy;
-	QDF_STATUS status;
-
-	/* Send a target failure event to the application */
-	AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n"));
-
-	/* clear the interrupt , the debug error interrupt is counter 0
-	 * read counter to clear interrupt
-	 */
-	status = hif_read_write(pdev->HIFDevice,
-				COUNT_DEC_ADDRESS,
-				(uint8_t *) &dummy,
-				4, HIF_RD_SYNC_BYTE_INC, NULL);
-
-	A_ASSERT(status == QDF_STATUS_SUCCESS);
-	return status;
-}
-
-/**
- * hif_dev_service_counter_interrupt() - service counter interrupts
- * synchronously
- *
- * @pDev: hif sdio device context
- *
- * Return: QDF_STATUS_SUCCESS for success
- */
-static
-QDF_STATUS hif_dev_service_counter_interrupt(struct hif_sdio_device *pdev)
-{
-	uint8_t counter_int_status;
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n"));
-
-	counter_int_status = pdev->IrqProcRegisters.counter_int_status &
-			     pdev->IrqEnableRegisters.counter_int_status_enable;
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
-			("Valid interrupt source in COUNTER_INT_STATUS: 0x%x\n",
-			 counter_int_status));
-
-	/* Check if the debug interrupt is pending
-	 * NOTE: other modules like GMBOX may use the counter interrupt
-	 * for credit flow control on other counters, we only need to
-	 * check for the debug assertion counter interrupt
-	 */
-	if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK)
-		return hif_dev_service_debug_interrupt(pdev);
-
-	return QDF_STATUS_SUCCESS;
-}
-
-/**
- * hif_dev_process_pending_irqs() - process pending interrupts
- * synchronously
- *
- * @pDev: hif sdio device context
- * @pDone: pending irq completion status
- * @pASyncProcessing: sync/async processing flag
- * Return: QDF_STATUS_SUCCESS for success
- */
-static QDF_STATUS hif_dev_process_pending_irqs(struct hif_sdio_device *pdev,
-					      bool *done,
-					      bool *async_processing)
-{
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	uint8_t host_int_status = 0;
-	uint32_t look_ahead[MAILBOX_USED_COUNT];
-	int i;
-
-	qdf_mem_zero(&look_ahead, sizeof(look_ahead));
-	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
-			("+ProcessPendingIRQs: (dev: 0x%lX)\n",
-			 (unsigned long)pdev));
-
-	/* NOTE: the HIF implementation guarantees that the context
-	 * of this call allows us to perform SYNCHRONOUS I/O,
-	 * that is we can block, sleep or call any API that
-	 * can block or switch thread/task ontexts.
-	 * This is a fully schedulable context.
-	 */
-	do {
-
-		if (pdev->IrqEnableRegisters.int_status_enable == 0) {
-			/* interrupt enables have been cleared, do not try
-			 * to process any pending interrupts that
-			 * may result in more bus transactions.
-			 * The target may be unresponsive at this point.
-			 */
-			break;
-		}
-		status = hif_read_write(pdev->HIFDevice,
-					HOST_INT_STATUS_ADDRESS,
-					(uint8_t *) &pdev->IrqProcRegisters,
-					sizeof(pdev->IrqProcRegisters),
-					HIF_RD_SYNC_BYTE_INC, NULL);
-
-		if (QDF_IS_STATUS_ERROR(status))
-			break;
-
-		if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) {
-			hif_dev_dump_registers(pdev,
-					       &pdev->IrqProcRegisters,
-					       &pdev->IrqEnableRegisters,
-					       &pdev->MailBoxCounterRegisters);
-		}
-
-		/* Update only those registers that are enabled */
-		host_int_status = pdev->IrqProcRegisters.host_int_status
-				  & pdev->IrqEnableRegisters.int_status_enable;
-
-		/* only look at mailbox status if the HIF layer did not
-		 * provide this function, on some HIF interfaces reading
-		 * the RX lookahead is not valid to do
-		 */
-		for (i = 0; i < MAILBOX_USED_COUNT; i++) {
-			look_ahead[i] = 0;
-			if (host_int_status & (1 << i)) {
-				/* mask out pending mailbox value, we use
-				 * "lookAhead" as the real flag for
-				 * mailbox processing below
-				 */
-				host_int_status &= ~(1 << i);
-				if (pdev->IrqProcRegisters.
-				    rx_lookahead_valid & (1 << i)) {
-					/* mailbox has a message and the
-					 * look ahead is valid
-					 */
-					look_ahead[i] =
-						pdev->
-						IrqProcRegisters.rx_lookahead[
-						MAILBOX_LOOKAHEAD_SIZE_IN_WORD *
-						i];
-				}
-			}
-		} /*end of for loop */
-	} while (false);
-
-	do {
-		bool bLookAheadValid = false;
-		/* did the interrupt status fetches succeed? */
-		if (QDF_IS_STATUS_ERROR(status))
-			break;
-
-		for (i = 0; i < MAILBOX_USED_COUNT; i++) {
-			if (look_ahead[i] != 0) {
-				bLookAheadValid = true;
-				break;
-			}
-		}
-
-		if ((0 == host_int_status) && !bLookAheadValid) {
-			/* nothing to process, the caller can use this
-			 * to break out of a loop
-			 */
-			*done = true;
-			break;
-		}
-
-		if (bLookAheadValid) {
-			for (i = 0; i < MAILBOX_USED_COUNT; i++) {
-				int fetched = 0;
-
-				if (look_ahead[i] == 0)
-					continue;
-				AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
-					("Pending mailbox[%d] message, look_ahead: 0x%X\n",
-					 i, look_ahead[i]));
-				/* Mailbox Interrupt, the HTC layer may issue
-				 * async requests to empty the mailbox...
-				 * When emptying the recv mailbox we use the
-				 * async handler from the completion routine of
-				 * routine of the callers read request.
-				 * This can improve performance by reducing
-				 * the  context switching when we rapidly
-				 * pull packets
-				 */
-				status = hif_dev_recv_message_pending_handler(
-							pdev, i,
-							&look_ahead
-							[i], 1,
-							async_processing,
-							&fetched);
-				if (QDF_IS_STATUS_ERROR(status))
-					break;
-
-				if (!fetched) {
-					/* HTC could not pull any messages out
-					 * due to lack of resources force DSR
-					 * handle to ack the interrupt
-					 */
-					*async_processing = false;
-					pdev->RecheckIRQStatusCnt = 0;
-				}
-			}
-		}
-
-		/* now handle the rest of them */
-		AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
-			(" Valid interrupt source for OTHER interrupts: 0x%x\n",
-			 host_int_status));
-
-		if (HOST_INT_STATUS_CPU_GET(host_int_status)) {
-			/* CPU Interrupt */
-			status = hif_dev_service_cpu_interrupt(pdev);
-			if (QDF_IS_STATUS_ERROR(status))
-				break;
-		}
-
-		if (HOST_INT_STATUS_ERROR_GET(host_int_status)) {
-			/* Error Interrupt */
-			status = hif_dev_service_error_interrupt(pdev);
-			if (QDF_IS_STATUS_ERROR(status))
-				break;
-		}
-
-		if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) {
-			/* Counter Interrupt */
-			status = hif_dev_service_counter_interrupt(pdev);
-			if (QDF_IS_STATUS_ERROR(status))
-				break;
-		}
-
-	} while (false);
-
-	/* an optimization to bypass reading the IRQ status registers
-	 * unecessarily which can re-wake the target, if upper layers
-	 * determine that we are in a low-throughput mode, we can
-	 * rely on taking another interrupt rather than re-checking
-	 * the status registers which can re-wake the target.
-	 *
-	 * NOTE : for host interfaces that use the special
-	 * GetPendingEventsFunc, this optimization cannot be used due to
-	 * possible side-effects.  For example, SPI requires the host
-	 * to drain all messages from the mailbox before exiting
-	 * the ISR routine.
-	 */
-	if (!(*async_processing) && (pdev->RecheckIRQStatusCnt == 0)) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
-			("Bypassing IRQ Status re-check, forcing done\n"));
-		*done = true;
-	}
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
-			("-ProcessPendingIRQs: (done:%d, async:%d) status=%d\n",
-			 *done, *async_processing, status));
-
-	return status;
-}
-
-#define DEV_CHECK_RECV_YIELD(pdev) \
-	((pdev)->CurrentDSRRecvCount >= \
-	 (pdev)->HifIRQYieldParams.recv_packet_yield_count)
-
-/**
- * hif_dev_dsr_handler() - Synchronous interrupt handler
- *
- * @context: hif send context
- *
- * Return: 0 for success and non-zero for failure
- */
-QDF_STATUS hif_dev_dsr_handler(void *context)
-{
-	struct hif_sdio_device *pdev = (struct hif_sdio_device *) context;
-	QDF_STATUS status = QDF_STATUS_SUCCESS;
-	bool done = false;
-	bool async_proc = false;
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
-			("+DevDsrHandler: (dev: 0x%lX)\n",
-			 (unsigned long)pdev));
-
-	/* reset the recv counter that tracks when we need
-	 * to yield from the DSR
-	 */
-	pdev->CurrentDSRRecvCount = 0;
-	/* reset counter used to flag a re-scan of IRQ
-	 * status registers on the target
-	 */
-	pdev->RecheckIRQStatusCnt = 0;
-
-	while (!done) {
-		status = hif_dev_process_pending_irqs(pdev, &done, &async_proc);
-		if (QDF_IS_STATUS_ERROR(status))
-			break;
-
-		if (HIF_DEVICE_IRQ_SYNC_ONLY == pdev->HifIRQProcessingMode) {
-			/* the HIF layer does not allow async IRQ processing,
-			 * override the asyncProc flag
-			 */
-			async_proc = false;
-			/* this will cause us to re-enter ProcessPendingIRQ()
-			 * and re-read interrupt status registers.
-			 * This has a nice side effect of blocking us until all
-			 * async read requests are completed. This behavior is
-			 * required as we  do not allow ASYNC processing
-			 * in interrupt handlers (like Windows CE)
-			 */
-
-			if (pdev->DSRCanYield && DEV_CHECK_RECV_YIELD(pdev))
-				/* ProcessPendingIRQs() pulled enough recv
-				 * messages to satisfy the yield count, stop
-				 * checking for more messages and return
-				 */
-				break;
-		}
-
-		if (async_proc) {
-			/* the function does some async I/O for performance,
-			 * we need to exit the ISR immediately, the check below
-			 * will prevent the interrupt from being
-			 * Ack'd while we handle it asynchronously
-			 */
-			break;
-		}
-
-	}
-
-	if (QDF_IS_STATUS_SUCCESS(status) && !async_proc) {
-		/* Ack the interrupt only if :
-		 *  1. we did not get any errors in processing interrupts
-		 *  2. there are no outstanding async processing requests
-		 */
-		if (pdev->DSRCanYield) {
-			/* if the DSR can yield do not ACK the interrupt, there
-			 * could be more pending messages. The HIF layer
-			 * must ACK the interrupt on behalf of HTC
-			 */
-			AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
-				(" Yield in effect (cur RX count: %d)\n",
-				 pdev->CurrentDSRRecvCount));
-		} else {
-			AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
-				(" Acking interrupt from DevDsrHandler\n"));
-			hif_ack_interrupt(pdev->HIFDevice);
-		}
-	}
-
-	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("-DevDsrHandler\n"));
-	return status;
-}
-

+ 0 - 204
hif/src/sdio/hif_sdio_send.c

@@ -1,204 +0,0 @@
-/*
- * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for
- * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
-#define ATH_MODULE_NAME hif
-#include <qdf_types.h>
-#include <qdf_status.h>
-#include <qdf_timer.h>
-#include <qdf_time.h>
-#include <qdf_lock.h>
-#include <qdf_mem.h>
-#include <qdf_util.h>
-#include <qdf_defer.h>
-#include <qdf_atomic.h>
-#include <qdf_nbuf.h>
-#include <athdefs.h>
-#include <qdf_net_types.h>
-#include <a_types.h>
-#include <athdefs.h>
-#include <a_osapi.h>
-#include <hif.h>
-#include <htc_services.h>
-#include <a_debug.h>
-#include "hif_sdio_internal.h"
-
-/*
- * Data structure to record required sending context data
- */
-struct hif_sendContext {
-	bool bNewAlloc;
-	struct hif_sdio_device *pDev;
-	qdf_nbuf_t netbuf;
-	unsigned int transferID;
-	unsigned int head_data_len;
-};
-
-/**
- * hif_dev_rw_completion_handler() - Completion routine
- * for ALL HIF layer async I/O
- * @context: hif send context
- * @status: completion routine sync/async context
- *
- * Return: 0 for success and non-zero for failure
- */
-QDF_STATUS hif_dev_rw_completion_handler(void *context, QDF_STATUS status)
-{
-	struct hif_sendContext *send_context =
-				(struct hif_sendContext *)context;
-	unsigned int transfer_id = send_context->transferID;
-	struct hif_sdio_device *pdev = send_context->pDev;
-	qdf_nbuf_t buf = send_context->netbuf;
-	/* Fix Me: Do we need toeplitz_hash_result for SDIO */
-	uint32_t toeplitz_hash_result = 0;
-
-	if (send_context->bNewAlloc)
-		qdf_mem_free((void *)send_context);
-	else
-		qdf_nbuf_pull_head(buf, send_context->head_data_len);
-	if (pdev->hif_callbacks.txCompletionHandler)
-		pdev->hif_callbacks.txCompletionHandler(pdev->hif_callbacks.
-					Context, buf,
-					transfer_id, toeplitz_hash_result);
-
-	return QDF_STATUS_SUCCESS;
-}
-
-/**
- * hif_dev_send_buffer() - send buffer to sdio device
- * @pDev: sdio function
- * @transferID: transfer id
- * @pipe: ul/dl pipe
- * @nbytes: no of bytes to transfer
- * @buf: pointer to buffer
- *
- * Return: 0 for success and non-zero for failure
- */
-QDF_STATUS hif_dev_send_buffer(struct hif_sdio_device *pdev,
-			       unsigned int transfer_id,
-			       uint8_t pipe, unsigned int nbytes,
-			       qdf_nbuf_t buf)
-{
-	QDF_STATUS status;
-	uint32_t padded_length;
-	int frag_count = 0, i, head_data_len;
-	struct hif_sendContext *send_context;
-	unsigned char *pData;
-	uint32_t request = HIF_WR_ASYNC_BLOCK_INC;
-	uint8_t mbox_index = hif_dev_map_pipe_to_mail_box(pdev, pipe);
-
-	if (mbox_index == INVALID_MAILBOX_NUMBER) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("pipe id(%d) invalid\n", pipe));
-		return QDF_STATUS_E_FAILURE;
-	}
-
-	padded_length = DEV_CALC_SEND_PADDED_LEN(pdev, nbytes);
-	A_ASSERT(padded_length - nbytes < HIF_DUMMY_SPACE_MASK + 1);
-	/*
-	 * two most significant bytes to save dummy data count
-	 * data written into the dummy space will not put into
-	 * the final mbox FIFO.
-	 */
-	request |= ((padded_length - nbytes) << 16);
-
-	frag_count = qdf_nbuf_get_num_frags(buf);
-
-	if (frag_count > 1) {
-		/* header data length should be total sending length subtract
-		 * internal data length of netbuf
-		 */
-		head_data_len = sizeof(struct hif_sendContext) +
-			(nbytes - qdf_nbuf_get_frag_len(buf, frag_count - 1));
-	} else {
-		/*
-		 * | hif_sendContext | netbuf->data
-		 */
-		head_data_len = sizeof(struct hif_sendContext);
-	}
-
-	/* Check whether head room is enough to save extra head data */
-	if ((head_data_len <= qdf_nbuf_headroom(buf)) &&
-	    (qdf_nbuf_tailroom(buf) >= (padded_length - nbytes))) {
-		send_context =
-			(struct hif_sendContext *)qdf_nbuf_push_head(buf,
-						     head_data_len);
-		send_context->bNewAlloc = false;
-	} else {
-		send_context =
-			(struct hif_sendContext *)
-			qdf_mem_malloc(sizeof(struct hif_sendContext) +
-				       padded_length);
-		if (send_context) {
-			send_context->bNewAlloc = true;
-		} else {
-			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
-				("Allocate send context fail %d\n",
-				(int) sizeof(struct hif_sendContext) +
-				padded_length));
-			return QDF_STATUS_E_NOMEM;
-		}
-	}
-
-	send_context->netbuf = buf;
-	send_context->pDev = pdev;
-	send_context->transferID = transfer_id;
-	send_context->head_data_len = head_data_len;
-	/*
-	 * Copy data to head part of netbuf or head of allocated buffer.
-	 * if buffer is new allocated, the last buffer should be copied also.
-	 * It assume last fragment is internal buffer of netbuf
-	 * sometime total length of fragments larger than nbytes
-	 */
-	pData = (unsigned char *)send_context + sizeof(struct hif_sendContext);
-	for (i = 0; i < (send_context->bNewAlloc ? frag_count : frag_count - 1);
-	     i++) {
-		int frag_len = qdf_nbuf_get_frag_len(buf, i);
-		unsigned char *frag_addr = qdf_nbuf_get_frag_vaddr(buf, i);
-
-		if (frag_len > nbytes)
-			frag_len = nbytes;
-		memcpy(pData, frag_addr, frag_len);
-		pData += frag_len;
-		nbytes -= frag_len;
-		if (nbytes <= 0)
-			break;
-	}
-
-	/* Reset pData pointer and send_context out */
-	pData = (unsigned char *)send_context + sizeof(struct hif_sendContext);
-	status = hif_read_write(pdev->HIFDevice,
-				pdev->MailBoxInfo.mbox_prop[mbox_index].
-				extended_address, (char *)pData, padded_length,
-				request, (void *)send_context);
-
-	if (status == QDF_STATUS_E_PENDING)
-		/*
-		 * it will return QDF_STATUS_E_PENDING in native HIF
-		 * implementation, which should be treated as successful
-		 * result here.
-		 */
-		status = QDF_STATUS_SUCCESS;
-	/* release buffer or move back data pointer when failed */
-	if (status != QDF_STATUS_SUCCESS) {
-		if (send_context->bNewAlloc)
-			qdf_mem_free(send_context);
-		else
-			qdf_nbuf_pull_head(buf, head_data_len);
-	}
-
-	return status;
-}

+ 15 - 2
hif/src/sdio/native_sdio/src/dev_quirks.c

@@ -229,6 +229,19 @@ int hif_sdio_quirk_mod_strength(struct sdio_func *func)
 	struct hif_sdio_dev *device = sdio_get_drvdata(func);
 	uint16_t  manfid = device->id->device & MANUFACTURER_ID_AR6K_BASE_MASK;
 
+	if (!modstrength) /* TODO: Dont set this : scn is not popolated yet */
+		return 0;
+
+	if (!scn) {
+		HIF_ERROR("%s: scn is null", __func__);
+		return -1;
+	}
+
+	if (!scn->hostdef) {
+		HIF_ERROR("%s: scn->hostdef is null", __func__);
+		return -1;
+	}
+
 	switch (manfid) {
 	case MANUFACTURER_ID_QCN7605_BASE:
 		break;
@@ -241,7 +254,7 @@ int hif_sdio_quirk_mod_strength(struct sdio_func *func)
 				  __func__, addr, value, ret);
 			break;
 		}
-		HIF_INFO("%s addr:0x%x val:0x%x\n", __func__, addr, value);
+		HIF_INFO("%s: addr 0x%x val 0x%x", __func__, addr, value);
 
 		addr = WINDOW_WRITE_ADDR_ADDRESS;
 		value = 0x50F8;
@@ -251,7 +264,7 @@ int hif_sdio_quirk_mod_strength(struct sdio_func *func)
 				  __func__, addr, value, ret);
 			break;
 		}
-		HIF_INFO("%s addr: 0x%x val:0x%x\n", __func__, addr, value);
+		HIF_INFO("%s: addr 0x%x val 0x%x\n", __func__, addr, value);
 		break;
 	}
 

+ 30 - 185
hif/src/sdio/native_sdio/src/hif.c

@@ -1018,132 +1018,6 @@ power_state_change_notify(struct hif_sdio_dev *device,
 	return status;
 }
 
-#ifdef SDIO_3_0
-/**
- * set_extended_mbox_size() - set extended MBOX size
- * @pinfo: sdio mailbox info
- *
- * Return: none.
- */
-static void set_extended_mbox_size(struct hif_device_mbox_info *pinfo)
-{
-	pinfo->mbox_prop[0].extended_size =
-		HIF_MBOX0_EXTENDED_WIDTH_AR6320_ROME_2_0;
-	pinfo->mbox_prop[1].extended_size =
-		HIF_MBOX1_EXTENDED_WIDTH_AR6320;
-}
-
-/**
- * set_extended_mbox_address() - set extended MBOX address
- * @pinfo: sdio mailbox info
- *
- * Return: none.
- */
-static void set_extended_mbox_address(struct hif_device_mbox_info *pinfo)
-{
-	pinfo->mbox_prop[1].extended_address =
-		pinfo->mbox_prop[0].extended_address +
-		pinfo->mbox_prop[0].extended_size +
-		HIF_MBOX_DUMMY_SPACE_SIZE_AR6320;
-}
-#else
-static void set_extended_mbox_size(struct hif_device_mbox_info *pinfo)
-{
-	pinfo->mbox_prop[0].extended_size =
-		HIF_MBOX0_EXTENDED_WIDTH_AR6320;
-}
-static inline void
-set_extended_mbox_address(struct hif_device_mbox_info *pinfo)
-{
-
-}
-#endif
-
-/**
- * set_extended_mbox_window_info() - set extended MBOX window
- * information for SDIO interconnects
- * @manf_id: manufacturer id
- * @pinfo: sdio mailbox info
- *
- * Return: none.
- */
-static void set_extended_mbox_window_info(uint16_t manf_id,
-			 struct hif_device_mbox_info *pinfo)
-{
-	switch (manf_id & MANUFACTURER_ID_AR6K_BASE_MASK) {
-	case MANUFACTURER_ID_AR6002_BASE:
-		/* MBOX 0 has an extended range */
-
-		pinfo->mbox_prop[0].extended_address =
-			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
-		pinfo->mbox_prop[0].extended_size =
-			HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
-
-		pinfo->mbox_prop[0].extended_address =
-			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
-		pinfo->mbox_prop[0].extended_size =
-			HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
-
-		pinfo->mbox_prop[0].extended_address =
-			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6004;
-		pinfo->mbox_prop[0].extended_size =
-			HIF_MBOX0_EXTENDED_WIDTH_AR6004;
-
-		break;
-	case MANUFACTURER_ID_AR6003_BASE:
-		/* MBOX 0 has an extended range */
-		pinfo->mbox_prop[0].extended_address =
-			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
-		pinfo->mbox_prop[0].extended_size =
-			HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
-		pinfo->gmbox_address = HIF_GMBOX_BASE_ADDR;
-		pinfo->gmbox_size = HIF_GMBOX_WIDTH;
-		break;
-	case MANUFACTURER_ID_AR6004_BASE:
-		pinfo->mbox_prop[0].extended_address =
-			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6004;
-		pinfo->mbox_prop[0].extended_size =
-			HIF_MBOX0_EXTENDED_WIDTH_AR6004;
-		pinfo->gmbox_address = HIF_GMBOX_BASE_ADDR;
-		pinfo->gmbox_size = HIF_GMBOX_WIDTH;
-		break;
-	case MANUFACTURER_ID_AR6320_BASE: {
-		uint16_t ManuRevID =
-			manf_id & MANUFACTURER_ID_AR6K_REV_MASK;
-		pinfo->mbox_prop[0].extended_address =
-			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320;
-		if (ManuRevID < 4) {
-			pinfo->mbox_prop[0].extended_size =
-				HIF_MBOX0_EXTENDED_WIDTH_AR6320;
-		} else {
-		/* from rome 2.0(0x504), the width has been extended to 56K */
-			set_extended_mbox_size(pinfo);
-		}
-		set_extended_mbox_address(pinfo);
-		pinfo->gmbox_address = HIF_GMBOX_BASE_ADDR;
-		pinfo->gmbox_size = HIF_GMBOX_WIDTH;
-		break;
-	}
-	case MANUFACTURER_ID_QCA9377_BASE:
-	case MANUFACTURER_ID_QCA9379_BASE:
-		pinfo->mbox_prop[0].extended_address =
-			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320;
-		pinfo->mbox_prop[0].extended_size =
-			HIF_MBOX0_EXTENDED_WIDTH_AR6320_ROME_2_0;
-		pinfo->mbox_prop[1].extended_address =
-			pinfo->mbox_prop[0].extended_address +
-			pinfo->mbox_prop[0].extended_size +
-			HIF_MBOX_DUMMY_SPACE_SIZE_AR6320;
-		pinfo->mbox_prop[1].extended_size =
-			HIF_MBOX1_EXTENDED_WIDTH_AR6320;
-		pinfo->gmbox_address = HIF_GMBOX_BASE_ADDR;
-		pinfo->gmbox_size = HIF_GMBOX_WIDTH;
-		break;
-	default:
-		A_ASSERT(false);
-		break;
-	}
-}
 
 /**
  * hif_configure_device() - configure sdio device
@@ -1159,35 +1033,20 @@ hif_configure_device(struct hif_sdio_dev *device,
 		     enum hif_device_config_opcode opcode,
 		     void *config, uint32_t config_len)
 {
-	uint32_t count;
 	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	switch (opcode) {
+#ifdef CONFIG_SDIO_TRANSFER_MAILBOX
 	case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
-		((uint32_t *) config)[0] = HIF_MBOX0_BLOCK_SIZE;
-		((uint32_t *) config)[1] = HIF_MBOX1_BLOCK_SIZE;
-		((uint32_t *) config)[2] = HIF_MBOX2_BLOCK_SIZE;
-		((uint32_t *) config)[3] = HIF_MBOX3_BLOCK_SIZE;
+		hif_dev_get_mbox_block_size(config);
 		break;
 
 	case HIF_DEVICE_GET_MBOX_ADDR:
-		for (count = 0; count < 4; count++) {
-			((uint32_t *) config)[count] =
-				HIF_MBOX_START_ADDR(count);
-		}
-
-		if (config_len >= sizeof(struct hif_device_mbox_info)) {
-			set_extended_mbox_window_info((uint16_t) device->func->
-					      device,
-					      (struct hif_device_mbox_info *)
-					      config);
-		}
-
+		hif_dev_get_mbox_address(device, config, config_len);
 		break;
+#endif
 	case HIF_DEVICE_GET_PENDING_EVENTS_FUNC:
-		AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
-				("%s: configuration opcode %d\n",
-				 __func__, opcode));
+		HIF_WARN("%s: opcode %d",  __func__, opcode);
 		status = QDF_STATUS_E_FAILURE;
 		break;
 	case HIF_DEVICE_GET_IRQ_PROC_MODE:
@@ -1195,9 +1054,7 @@ hif_configure_device(struct hif_sdio_dev *device,
 			HIF_DEVICE_IRQ_SYNC_ONLY;
 		break;
 	case HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC:
-		AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
-				("%s: configuration opcode %d\n",
-				 __func__, opcode));
+		HIF_WARN("%s: opcode %d", __func__, opcode);
 		status = QDF_STATUS_E_FAILURE;
 		break;
 	case HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT:
@@ -1222,9 +1079,7 @@ hif_configure_device(struct hif_sdio_dev *device,
 					   config);
 		break;
 	case HIF_DEVICE_GET_IRQ_YIELD_PARAMS:
-		AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
-			("%s: configuration opcode %d\n",
-				 __func__, opcode));
+		HIF_WARN("%s: opcode %d", __func__, opcode);
 		status = QDF_STATUS_E_FAILURE;
 		break;
 	case HIF_DEVICE_SET_HTC_CONTEXT:
@@ -1232,23 +1087,16 @@ hif_configure_device(struct hif_sdio_dev *device,
 		break;
 	case HIF_DEVICE_GET_HTC_CONTEXT:
 		if (config == NULL) {
-			AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
-				("%s: htc context is NULL\n",
-				__func__));
+			HIF_ERROR("%s: htc context is NULL", __func__);
 			return QDF_STATUS_E_FAILURE;
 		}
 		*(void **)config = device->htc_context;
 		break;
 	case HIF_BMI_DONE:
-	{
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
-			("%s: BMI_DONE\n", __func__));
+		HIF_ERROR("%s: BMI_DONE", __func__);
 		break;
-	}
 	default:
-		AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
-			("%s: Unsupported configuration opcode: %d\n",
-			 __func__, opcode));
+		HIF_ERROR("%s: Unsupported  opcode: %d", __func__, opcode);
 		status = QDF_STATUS_E_FAILURE;
 	}
 
@@ -1856,8 +1704,6 @@ static QDF_STATUS hif_enable_func(struct hif_sdio_dev *device,
 
 	HIF_ENTER();
 
-	device = get_hif_device(func);
-
 	if (!device) {
 		HIF_ERROR("%s: HIF device is NULL", __func__);
 		return QDF_STATUS_E_INVAL;
@@ -2354,9 +2200,8 @@ int func0_cmd52_write_byte(struct mmc_card *card,
 	status = mmc_wait_for_cmd(card->host, &io_cmd, 0);
 
 	if (status)
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
-				("%s: mmc_wait_for_cmd returned %d\n",
-				 __func__, status));
+		HIF_ERROR("%s: mmc_wait_for_cmd returned %d",
+			  __func__, status);
 
 	return status;
 }
@@ -2381,50 +2226,50 @@ int func0_cmd52_read_byte(struct mmc_card *card,
 		*byte = io_cmd.resp[0] & 0xFF;
 
 	if (err)
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
-				("%s: mmc_wait_for_cmd returned %d\n",
-				 __func__, err));
+		HIF_ERROR("%s: mmc_wait_for_cmd returned %d",
+			  __func__, err);
 
 	return err;
 }
 
 void hif_dump_cccr(struct hif_sdio_dev *hif_device)
 {
-	int i;
+	unsigned int i;
 	uint8_t cccr_val;
 	uint32_t err;
 
+	HIF_ERROR("%s: Enter", __func__);
+
 	if (!hif_device || !hif_device->func ||
 				!hif_device->func->card) {
-		AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
-			("hif_dump_cccr incorrect input arguments\n"));
+		HIF_ERROR("%s: incorrect input", __func__);
 		return;
 	}
 
-	AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("hif_dump_cccr "));
 	for (i = 0; i <= 0x16; i++) {
 		err = func0_cmd52_read_byte(hif_device->func->card,
 						i, &cccr_val);
-		if (err) {
-			AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
-				("Reading CCCR 0x%02X failed: %d\n",
-			       (unsigned int)i, (unsigned int)err));
-		} else {
-			AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
-				("%X(%X) ", (unsigned int)i,
-			       (unsigned int)cccr_val));
-		}
+		if (err)
+			HIF_ERROR("%s:Reading CCCR 0x%02X failed: %d",
+				  __func__, i, (unsigned int)err);
+		else
+			HIF_ERROR("%X(%X) ", i, (unsigned int)cccr_val);
 	}
 
-	AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("\n"));
+	HIF_ERROR("%s: Exit", __func__);
 }
 
 int hif_sdio_device_inserted(struct device *dev,
 					const struct sdio_device_id *id)
 {
 	struct sdio_func *func = dev_to_sdio_func(dev);
+	int status = 0;
 
-	return hif_device_inserted(func, id);
+	HIF_ERROR("%s: Enter", __func__);
+	status = hif_device_inserted(func, id);
+	HIF_ERROR("%s: Exit", __func__);
+
+	return status;
 }
 
 void hif_sdio_device_removed(struct sdio_func *func)

+ 1249 - 0
hif/src/sdio/transfer/mailbox.c

@@ -0,0 +1,1249 @@
+/*
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef CONFIG_SDIO_TRANSFER_MAILBOX
+#define ATH_MODULE_NAME hif
+#include <qdf_types.h>
+#include <qdf_status.h>
+#include <qdf_timer.h>
+#include <qdf_time.h>
+#include <qdf_lock.h>
+#include <qdf_mem.h>
+#include <qdf_util.h>
+#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>
+#include <athdefs.h>
+#include <a_osapi.h>
+#include <hif.h>
+#include <htc_internal.h>
+#include <htc_services.h>
+#include <a_debug.h>
+#include "hif_sdio_internal.h"
+#include "if_sdio.h"
+#include "regtable.h"
+#include "transfer.h"
+
+#ifdef SDIO_3_0
+/**
+ * set_extended_mbox_size() - set extended MBOX size
+ * @pinfo: sdio mailbox info
+ *
+ * Return: none.
+ */
+static void set_extended_mbox_size(struct hif_device_mbox_info *pinfo)
+{
+	pinfo->mbox_prop[0].extended_size =
+		HIF_MBOX0_EXTENDED_WIDTH_AR6320_ROME_2_0;
+	pinfo->mbox_prop[1].extended_size =
+		HIF_MBOX1_EXTENDED_WIDTH_AR6320;
+}
+
+/**
+ * set_extended_mbox_address() - set extended MBOX address
+ * @pinfo: sdio mailbox info
+ *
+ * Return: none.
+ */
+static void set_extended_mbox_address(struct hif_device_mbox_info *pinfo)
+{
+	pinfo->mbox_prop[1].extended_address =
+		pinfo->mbox_prop[0].extended_address +
+		pinfo->mbox_prop[0].extended_size +
+		HIF_MBOX_DUMMY_SPACE_SIZE_AR6320;
+}
+#else
+static void set_extended_mbox_size(struct hif_device_mbox_info *pinfo)
+{
+	pinfo->mbox_prop[0].extended_size =
+		HIF_MBOX0_EXTENDED_WIDTH_AR6320;
+}
+
+static inline void
+set_extended_mbox_address(struct hif_device_mbox_info *pinfo)
+{
+}
+#endif
+
+/**
+ * set_extended_mbox_window_info() - set extended MBOX window
+ * information for SDIO interconnects
+ * @manf_id: manufacturer id
+ * @pinfo: sdio mailbox info
+ *
+ * Return: none.
+ */
+static void set_extended_mbox_window_info(uint16_t manf_id,
+					  struct hif_device_mbox_info *pinfo)
+{
+	switch (manf_id & MANUFACTURER_ID_AR6K_BASE_MASK) {
+	case MANUFACTURER_ID_AR6002_BASE:
+		/* MBOX 0 has an extended range */
+
+		pinfo->mbox_prop[0].extended_address =
+			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
+		pinfo->mbox_prop[0].extended_size =
+			HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
+
+		pinfo->mbox_prop[0].extended_address =
+			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
+		pinfo->mbox_prop[0].extended_size =
+			HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
+
+		pinfo->mbox_prop[0].extended_address =
+			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6004;
+		pinfo->mbox_prop[0].extended_size =
+			HIF_MBOX0_EXTENDED_WIDTH_AR6004;
+
+		break;
+	case MANUFACTURER_ID_AR6003_BASE:
+		/* MBOX 0 has an extended range */
+		pinfo->mbox_prop[0].extended_address =
+			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6003_V1;
+		pinfo->mbox_prop[0].extended_size =
+			HIF_MBOX0_EXTENDED_WIDTH_AR6003_V1;
+		pinfo->gmbox_address = HIF_GMBOX_BASE_ADDR;
+		pinfo->gmbox_size = HIF_GMBOX_WIDTH;
+		break;
+	case MANUFACTURER_ID_AR6004_BASE:
+		pinfo->mbox_prop[0].extended_address =
+			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6004;
+		pinfo->mbox_prop[0].extended_size =
+			HIF_MBOX0_EXTENDED_WIDTH_AR6004;
+		pinfo->gmbox_address = HIF_GMBOX_BASE_ADDR;
+		pinfo->gmbox_size = HIF_GMBOX_WIDTH;
+		break;
+	case MANUFACTURER_ID_AR6320_BASE:
+	{
+		uint16_t rev = manf_id & MANUFACTURER_ID_AR6K_REV_MASK;
+
+		pinfo->mbox_prop[0].extended_address =
+			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320;
+		if (rev < 4)
+			pinfo->mbox_prop[0].extended_size =
+				HIF_MBOX0_EXTENDED_WIDTH_AR6320;
+		else
+			set_extended_mbox_size(pinfo);
+		set_extended_mbox_address(pinfo);
+		pinfo->gmbox_address = HIF_GMBOX_BASE_ADDR;
+		pinfo->gmbox_size = HIF_GMBOX_WIDTH;
+		break;
+	}
+	case MANUFACTURER_ID_QCA9377_BASE:
+	case MANUFACTURER_ID_QCA9379_BASE:
+		pinfo->mbox_prop[0].extended_address =
+			HIF_MBOX0_EXTENDED_BASE_ADDR_AR6320;
+		pinfo->mbox_prop[0].extended_size =
+			HIF_MBOX0_EXTENDED_WIDTH_AR6320_ROME_2_0;
+		pinfo->mbox_prop[1].extended_address =
+			pinfo->mbox_prop[0].extended_address +
+			pinfo->mbox_prop[0].extended_size +
+			HIF_MBOX_DUMMY_SPACE_SIZE_AR6320;
+		pinfo->mbox_prop[1].extended_size =
+			HIF_MBOX1_EXTENDED_WIDTH_AR6320;
+		pinfo->gmbox_address = HIF_GMBOX_BASE_ADDR;
+		pinfo->gmbox_size = HIF_GMBOX_WIDTH;
+		break;
+	default:
+		A_ASSERT(false);
+		break;
+	}
+}
+
+/**
+ * hif_dev_get_mbox_address() - get the mbox addresses for dma
+ * @pdev:  SDIO HIF object
+ * @config: mbox address config pointer
+ *
+ * Return : 0 for success, non-zero for error
+ */
+QDF_STATUS hif_dev_get_mbox_address(struct hif_sdio_dev *pdev,
+				    struct hif_device_mbox_info *config,
+				    uint32_t config_len)
+{
+	uint32_t count;
+
+	for (count = 0; count < 4; count++)
+		config->mbox_addresses[count] = HIF_MBOX_START_ADDR(count);
+
+	if (config_len >= sizeof(struct hif_device_mbox_info)) {
+		set_extended_mbox_window_info((uint16_t)pdev->func->device,
+					      config);
+		return QDF_STATUS_SUCCESS;
+	}
+
+	return QDF_STATUS_E_INVAL;
+}
+
+/**
+ * hif_dev_get_mbox_size() - get the mbox block size for dma
+ * @config : mbox size config pointer
+ *
+ * Return : NONE
+ */
+void hif_dev_get_mbox_block_size(void *config)
+{
+	((uint32_t *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
+	((uint32_t *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
+	((uint32_t *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
+	((uint32_t *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
+}
+
+/**
+ * hif_dev_map_service_to_pipe() - maps ul/dl pipe to service id.
+ * @pDev: SDIO HIF object
+ * @ServiceId: sevice index
+ * @ULPipe: uplink pipe id
+ * @DLPipe: down-linklink pipe id
+ *
+ * Return: 0 on success, error value on invalid map
+ */
+QDF_STATUS hif_dev_map_service_to_pipe(struct hif_sdio_dev *pdev, uint16_t svc,
+				       uint8_t *ul_pipe, uint8_t *dl_pipe)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	switch (svc) {
+	case HTT_DATA_MSG_SVC:
+		if (pdev->swap_mailbox) {
+			*ul_pipe = 1;
+			*dl_pipe = 0;
+		} else {
+			*ul_pipe = 3;
+			*dl_pipe = 2;
+		}
+		break;
+
+	case HTC_CTRL_RSVD_SVC:
+	case HTC_RAW_STREAMS_SVC:
+		*ul_pipe = 1;
+		*dl_pipe = 0;
+		break;
+
+	case WMI_DATA_BE_SVC:
+	case WMI_DATA_BK_SVC:
+	case WMI_DATA_VI_SVC:
+	case WMI_DATA_VO_SVC:
+		*ul_pipe = 1;
+		*dl_pipe = 0;
+		break;
+
+	case WMI_CONTROL_SVC:
+		if (pdev->swap_mailbox) {
+			*ul_pipe = 3;
+			*dl_pipe = 2;
+		} else {
+			*ul_pipe = 1;
+			*dl_pipe = 0;
+		}
+		break;
+
+	default:
+		HIF_ERROR("%s: Err : Invalid service (%d)",
+			  __func__, svc);
+		status = QDF_STATUS_E_INVAL;
+		break;
+	}
+	return status;
+}
+
+/** hif_dev_mask_interrupts() - Disable the interrupts in the device
+ * @pdev SDIO HIF Object
+ *
+ * Return: NONE
+ */
+void hif_dev_mask_interrupts(struct hif_sdio_device *pdev)
+{
+	int status = QDF_STATUS_SUCCESS;
+
+	HIF_ENTER();
+	/* Disable all interrupts */
+	LOCK_HIF_DEV(pdev);
+	pdev->IrqEnableRegisters.int_status_enable = 0;
+	pdev->IrqEnableRegisters.cpu_int_status_enable = 0;
+	pdev->IrqEnableRegisters.error_status_enable = 0;
+	pdev->IrqEnableRegisters.counter_int_status_enable = 0;
+	UNLOCK_HIF_DEV(pdev);
+
+	/* always synchronous */
+	status = hif_read_write(pdev->HIFDevice,
+				INT_STATUS_ENABLE_ADDRESS,
+				(char *)&pdev->IrqEnableRegisters,
+				sizeof(struct MBOX_IRQ_ENABLE_REGISTERS),
+				HIF_WR_SYNC_BYTE_INC, NULL);
+
+	if (status != QDF_STATUS_SUCCESS)
+		HIF_ERROR("%s: Err updating intr reg: %d", __func__, status);
+}
+
+/** hif_dev_unmask_interrupts() - Enable the interrupts in the device
+ * @pdev SDIO HIF Object
+ *
+ * Return: NONE
+ */
+void hif_dev_unmask_interrupts(struct hif_sdio_device *pdev)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	LOCK_HIF_DEV(pdev);
+
+	/* Enable all the interrupts except for the internal
+	 * AR6000 CPU interrupt
+	 */
+	pdev->IrqEnableRegisters.int_status_enable =
+		INT_STATUS_ENABLE_ERROR_SET(0x01) |
+		INT_STATUS_ENABLE_CPU_SET(0x01)
+		| INT_STATUS_ENABLE_COUNTER_SET(0x01);
+
+	/* enable 2 mboxs INT */
+	pdev->IrqEnableRegisters.int_status_enable |=
+		INT_STATUS_ENABLE_MBOX_DATA_SET(0x01) |
+		INT_STATUS_ENABLE_MBOX_DATA_SET(0x02);
+
+	/* Set up the CPU Interrupt Status Register, enable
+	 * CPU sourced interrupt #0, #1.
+	 * #0 is used for report assertion from target
+	 * #1 is used for inform host that credit arrived
+	 */
+	pdev->IrqEnableRegisters.cpu_int_status_enable = 0x03;
+
+	/* Set up the Error Interrupt Status Register */
+	pdev->IrqEnableRegisters.error_status_enable =
+		(ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01)
+		 | ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01)) >> 16;
+
+	/* Set up the Counter Interrupt Status Register
+	 * (only for debug interrupt to catch fatal errors)
+	 */
+	pdev->IrqEnableRegisters.counter_int_status_enable =
+	(COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK)) >> 24;
+
+	UNLOCK_HIF_DEV(pdev);
+
+	/* always synchronous */
+	status = hif_read_write(pdev->HIFDevice,
+				INT_STATUS_ENABLE_ADDRESS,
+				(char *)&pdev->IrqEnableRegisters,
+				sizeof(struct MBOX_IRQ_ENABLE_REGISTERS),
+				HIF_WR_SYNC_BYTE_INC,
+				NULL);
+
+	if (status != QDF_STATUS_SUCCESS)
+		HIF_ERROR("%s: Err updating intr reg: %d", __func__, status);
+}
+
+void hif_dev_dump_registers(struct hif_sdio_device *pdev,
+			    struct MBOX_IRQ_PROC_REGISTERS *irq_proc,
+			    struct MBOX_IRQ_ENABLE_REGISTERS *irq_en,
+			    struct MBOX_COUNTER_REGISTERS *mbox_regs)
+{
+	int i = 0;
+
+	HIF_DBG("%s: Mailbox registers:", __func__);
+
+	if (irq_proc) {
+		HIF_DBG("HostIntStatus: 0x%x ", irq_proc->host_int_status);
+		HIF_DBG("CPUIntStatus: 0x%x ", irq_proc->cpu_int_status);
+		HIF_DBG("ErrorIntStatus: 0x%x ", irq_proc->error_int_status);
+		HIF_DBG("CounterIntStat: 0x%x ", irq_proc->counter_int_status);
+		HIF_DBG("MboxFrame: 0x%x ", irq_proc->mbox_frame);
+		HIF_DBG("RxLKAValid: 0x%x ", irq_proc->rx_lookahead_valid);
+		HIF_DBG("RxLKA0: 0x%x", irq_proc->rx_lookahead[0]);
+		HIF_DBG("RxLKA1: 0x%x ", irq_proc->rx_lookahead[1]);
+		HIF_DBG("RxLKA2: 0x%x ", irq_proc->rx_lookahead[2]);
+		HIF_DBG("RxLKA3: 0x%x", irq_proc->rx_lookahead[3]);
+
+		if (pdev->MailBoxInfo.gmbox_address != 0) {
+			HIF_DBG("GMBOX-HostIntStatus2:  0x%x ",
+				irq_proc->host_int_status2);
+			HIF_DBG("GMBOX-RX-Avail: 0x%x ",
+				irq_proc->gmbox_rx_avail);
+		}
+	}
+
+	if (irq_en) {
+		HIF_DBG("IntStatusEnable: 0x%x\n",
+			irq_en->int_status_enable);
+		HIF_DBG("CounterIntStatus: 0x%x\n",
+			irq_en->counter_int_status_enable);
+	}
+
+	for (i = 0; mbox_regs && i < 4; i++)
+		HIF_DBG("Counter[%d]: 0x%x\n", i, mbox_regs->counter[i]);
+}
+
+/* under HL SDIO, with Interface Memory support, we have
+ * the following reasons to support 2 mboxs:
+ * a) we need place different buffers in different
+ * mempool, for example, data using Interface Memory,
+ * desc and other using DRAM, they need different SDIO
+ * mbox channels.
+ * b) currently, tx mempool in LL case is separated from
+ * main mempool, the structure (descs at the beginning
+ * of every pool buffer) is different, because they only
+ * need store tx desc from host. To align with LL case,
+ * we also need 2 mbox support just as PCIe LL cases.
+ */
+
+/**
+ * hif_dev_map_pipe_to_mail_box() - maps pipe id to mailbox.
+ * @pdev: The pointer to the hif device object
+ * @pipeid: pipe index
+ *
+ * Return: mailbox index
+ */
+static uint8_t hif_dev_map_pipe_to_mail_box(struct hif_sdio_device *pdev,
+					    uint8_t pipeid)
+{
+	if (2 == pipeid || 3 == pipeid)
+		return 1;
+	else if (0 == pipeid || 1 == pipeid)
+		return 0;
+
+	HIF_ERROR("%s: pipeid=%d invalid", __func__, pipeid);
+
+	qdf_assert(0);
+
+	return INVALID_MAILBOX_NUMBER;
+}
+
+/**
+ * hif_dev_map_mail_box_to_pipe() - map sdio mailbox to htc pipe.
+ * @pdev: The pointer to the hif device object
+ * @mboxIndex: mailbox index
+ * @upload: boolean to decide mailbox index
+ *
+ * Return: Invalid pipe index
+ */
+static uint8_t hif_dev_map_mail_box_to_pipe(struct hif_sdio_device *pdev,
+					    uint8_t mbox_index, bool upload)
+{
+	if (mbox_index == 0)
+		return upload ? 1 : 0;
+	else if (mbox_index == 1)
+		return upload ? 3 : 2;
+
+	HIF_ERROR("%s: mbox_index=%d, upload=%d invalid",
+		  __func__, mbox_index, upload);
+
+	qdf_assert(0);
+
+	return INVALID_MAILBOX_NUMBER; /* invalid pipe id */
+}
+
+/**
+ * hif_get_send_addr() - Get the transfer pipe address
+ * @pdev: The pointer to the hif device object
+ * @pipe: The pipe identifier
+ *
+ * Return 0 for success and non-zero for failure to map
+ */
+int hif_get_send_address(struct hif_sdio_device *pdev,
+			 uint8_t pipe, uint32_t *addr)
+{
+	uint8_t mbox_index = INVALID_MAILBOX_NUMBER;
+
+	if (!addr)
+		return -EINVAL;
+
+	mbox_index = hif_dev_map_pipe_to_mail_box(pdev, pipe);
+
+	if (mbox_index == INVALID_MAILBOX_NUMBER)
+		return -EINVAL;
+
+	*addr = pdev->MailBoxInfo.mbox_prop[mbox_index].extended_address;
+
+	return 0;
+}
+
+/**
+ * hif_dev_recv_packet() - Receieve HTC packet/packet information from device
+ * @pdev : HIF device object
+ * @packet : The HTC packet pointer
+ * @recv_length : The length of information to be received
+ * @mbox_index : The mailbox that contains this information
+ *
+ * Return 0 for success and non zero of error
+ */
+static QDF_STATUS hif_dev_recv_packet(struct hif_sdio_device *pdev,
+				      HTC_PACKET *packet,
+				      uint32_t recv_length,
+				      uint32_t mbox_index)
+{
+	QDF_STATUS status;
+	uint32_t padded_length;
+	bool sync = (packet->Completion) ? false : true;
+	uint32_t req = sync ? HIF_RD_SYNC_BLOCK_FIX : HIF_RD_ASYNC_BLOCK_FIX;
+
+	/* adjust the length to be a multiple of block size if appropriate */
+	padded_length = DEV_CALC_RECV_PADDED_LEN(pdev, recv_length);
+
+	if (padded_length > packet->BufferLength) {
+		HIF_ERROR("%s: No space for padlen:%d recvlen:%d bufferlen:%d",
+			  __func__, padded_length,
+			  recv_length, packet->BufferLength);
+		if (packet->Completion) {
+			COMPLETE_HTC_PACKET(packet, QDF_STATUS_E_INVAL);
+			return QDF_STATUS_SUCCESS;
+		}
+		return QDF_STATUS_E_INVAL;
+	}
+
+	/* mailbox index is saved in Endpoint member */
+	HIF_INFO("%s : hdr:0x%x, len:%d, padded length: %d Mbox:0x%x",
+		 __func__, packet->PktInfo.AsRx.ExpectedHdr, recv_length,
+		 padded_length, mbox_index);
+
+	status = hif_read_write(pdev->HIFDevice,
+				pdev->MailBoxInfo.mbox_addresses[mbox_index],
+				packet->pBuffer,
+				padded_length,
+				req, sync ? NULL : packet);
+
+	if (status != QDF_STATUS_SUCCESS && status != QDF_STATUS_E_PENDING)
+		HIF_ERROR("%s : Failed %d", __func__, status);
+
+	if (sync) {
+		packet->Status = status;
+		if (status == QDF_STATUS_SUCCESS) {
+			HTC_FRAME_HDR *hdr = (HTC_FRAME_HDR *) packet->pBuffer;
+
+			HIF_INFO("%s: EP:%d,Len:%d,Flag:%d,CB:0x%02X,0x%02X\n",
+				 __func__,
+				 hdr->EndpointID, hdr->PayloadLen,
+				 hdr->Flags, hdr->ControlBytes0,
+				 hdr->ControlBytes1);
+		}
+	}
+
+	return status;
+}
+
+static QDF_STATUS hif_dev_issue_recv_packet_bundle
+(
+	struct hif_sdio_device *pdev,
+	HTC_PACKET_QUEUE *recv_pkt_queue,
+	HTC_PACKET_QUEUE *sync_completion_queue,
+	uint8_t mail_box_index,
+	int *num_packets_fetched,
+	bool partial_bundle
+)
+{
+	uint32_t padded_length;
+	int i, total_length = 0;
+	HTC_TARGET *target = NULL;
+	int bundleSpaceRemaining = 0;
+	unsigned char *bundle_buffer = NULL;
+	HTC_PACKET *packet, *packet_rx_bundle;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	target = (HTC_TARGET *)pdev->pTarget;
+
+	if ((HTC_PACKET_QUEUE_DEPTH(recv_pkt_queue) -
+	     HTC_MAX_MSG_PER_BUNDLE_RX) > 0) {
+		partial_bundle = true;
+		HIF_WARN("%s, partial bundle detected num: %d, %d\n",
+			 __func__,
+			 HTC_PACKET_QUEUE_DEPTH(recv_pkt_queue),
+			 HTC_MAX_MSG_PER_BUNDLE_RX);
+	}
+
+	bundleSpaceRemaining =
+		HTC_MAX_MSG_PER_BUNDLE_RX * target->TargetCreditSize;
+	packet_rx_bundle = allocate_htc_bundle_packet(target);
+	if (!packet_rx_bundle) {
+		HIF_ERROR("%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;
+	     !HTC_QUEUE_EMPTY(recv_pkt_queue) && i < HTC_MAX_MSG_PER_BUNDLE_RX;
+	     i++) {
+		packet = htc_packet_dequeue(recv_pkt_queue);
+		A_ASSERT(packet != NULL);
+		if (!packet)
+			break;
+		padded_length =
+			DEV_CALC_RECV_PADDED_LEN(pdev, packet->ActualLength);
+		if (packet->PktInfo.AsRx.HTCRxFlags &
+				HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK)
+			padded_length += HIF_MBOX_BLOCK_SIZE;
+		if ((bundleSpaceRemaining - padded_length) < 0) {
+			/* exceeds what we can transfer, put the packet back */
+			HTC_PACKET_ENQUEUE_TO_HEAD(recv_pkt_queue, packet);
+			break;
+		}
+		bundleSpaceRemaining -= padded_length;
+
+		if (partial_bundle ||
+		    HTC_PACKET_QUEUE_DEPTH(recv_pkt_queue) > 0) {
+			packet->PktInfo.AsRx.HTCRxFlags |=
+				HTC_RX_PKT_IGNORE_LOOKAHEAD;
+		}
+		packet->PktInfo.AsRx.HTCRxFlags |= HTC_RX_PKT_PART_OF_BUNDLE;
+
+		if (sync_completion_queue)
+			HTC_PACKET_ENQUEUE(sync_completion_queue, packet);
+
+		total_length += padded_length;
+	}
+#if DEBUG_BUNDLE
+	qdf_print("Recv bundle count %d, length %d.\n",
+		  sync_completion_queue ?
+		  HTC_PACKET_QUEUE_DEPTH(sync_completion_queue) : 0,
+		  total_length);
+#endif
+
+	status = hif_read_write(pdev->HIFDevice,
+				pdev->MailBoxInfo.
+				mbox_addresses[(int)mail_box_index],
+				bundle_buffer, total_length,
+				HIF_RD_SYNC_BLOCK_FIX, NULL);
+
+	if (status != QDF_STATUS_SUCCESS) {
+		HIF_ERROR("%s, hif_send Failed status:%d\n",
+			  __func__, status);
+	} else {
+		unsigned char *buffer = bundle_buffer;
+		*num_packets_fetched = i;
+		if (sync_completion_queue) {
+			HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(
+				sync_completion_queue, packet) {
+				padded_length =
+				DEV_CALC_RECV_PADDED_LEN(pdev,
+							 packet->ActualLength);
+				if (packet->PktInfo.AsRx.HTCRxFlags &
+				HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK)
+					padded_length +=
+						HIF_MBOX_BLOCK_SIZE;
+				A_MEMCPY(packet->pBuffer,
+					 buffer, padded_length);
+				buffer += padded_length;
+			} HTC_PACKET_QUEUE_ITERATE_END;
+		}
+	}
+	/* free bundle space under Sync mode */
+	free_htc_bundle_packet(target, packet_rx_bundle);
+	return status;
+}
+
+#define ISSUE_BUNDLE hif_dev_issue_recv_packet_bundle
+static
+QDF_STATUS hif_dev_recv_message_pending_handler(struct hif_sdio_device *pdev,
+						uint8_t mail_box_index,
+						uint32_t msg_look_aheads[],
+						int num_look_aheads,
+						bool *async_proc,
+						int *num_pkts_fetched)
+{
+	int pkts_fetched;
+	HTC_PACKET *pkt;
+	HTC_ENDPOINT_ID id;
+	bool partial_bundle;
+	int total_fetched = 0;
+	bool asyncProc = false;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	uint32_t look_aheads[HTC_MAX_MSG_PER_BUNDLE_RX];
+	HTC_PACKET_QUEUE recv_q, sync_comp_q;
+	QDF_STATUS (*rxCompletion)(void *, qdf_nbuf_t,	uint8_t);
+
+	HIF_INFO("%s: NumLookAheads: %d\n", __func__, num_look_aheads);
+
+	if (num_pkts_fetched)
+		*num_pkts_fetched = 0;
+
+	if (IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pdev)) {
+		/* We use async mode to get the packets if the
+		 * device layer supports it. The device layer
+		 * interfaces with HIF in which HIF may have
+		 * restrictions on how interrupts are processed
+		 */
+		asyncProc = true;
+	}
+
+	if (async_proc) {
+		/* indicate to caller how we decided to process this */
+		*async_proc = asyncProc;
+	}
+
+	if (num_look_aheads > HTC_MAX_MSG_PER_BUNDLE_RX) {
+		A_ASSERT(false);
+		return QDF_STATUS_E_PROTO;
+	}
+
+	A_MEMCPY(look_aheads, msg_look_aheads,
+		 (sizeof(uint32_t)) * num_look_aheads);
+	while (true) {
+		/* reset packets queues */
+		INIT_HTC_PACKET_QUEUE(&recv_q);
+		INIT_HTC_PACKET_QUEUE(&sync_comp_q);
+		if (num_look_aheads > HTC_MAX_MSG_PER_BUNDLE_RX) {
+			status = QDF_STATUS_E_PROTO;
+			A_ASSERT(false);
+			break;
+		}
+
+		/* first lookahead sets the expected endpoint IDs for
+		 * all packets in a bundle
+		 */
+		id = ((HTC_FRAME_HDR *)&look_aheads[0])->EndpointID;
+
+		if (id >= ENDPOINT_MAX) {
+			HIF_ERROR("%s: Invalid Endpoint in lookahead: %d\n",
+				  __func__, id);
+			status = QDF_STATUS_E_PROTO;
+			break;
+		}
+		/* try to allocate as many HTC RX packets indicated
+		 * by the lookaheads these packets are stored
+		 * in the recvPkt queue
+		 */
+		status = hif_dev_alloc_and_prepare_rx_packets(pdev,
+							      look_aheads,
+							      num_look_aheads,
+							      &recv_q);
+		if (QDF_IS_STATUS_ERROR(status))
+			break;
+		total_fetched += HTC_PACKET_QUEUE_DEPTH(&recv_q);
+
+		/* we've got packet buffers for all we can currently fetch,
+		 * this count is not valid anymore
+		 */
+		num_look_aheads = 0;
+		partial_bundle = false;
+
+		/* now go fetch the list of HTC packets */
+		while (!HTC_QUEUE_EMPTY(&recv_q)) {
+			pkts_fetched = 0;
+			if ((HTC_PACKET_QUEUE_DEPTH(&recv_q) > 1)) {
+				/* there are enough packets to attempt a bundle
+				 * transfer and recv bundling is allowed
+				 */
+				status = ISSUE_BUNDLE(pdev,
+						      &recv_q,
+						      asyncProc ? NULL :
+						      &sync_comp_q,
+						      mail_box_index,
+						      &pkts_fetched,
+						      partial_bundle);
+				if (QDF_IS_STATUS_ERROR(status)) {
+					hif_dev_free_recv_pkt_queue(
+							&recv_q);
+					break;
+				}
+
+				if (HTC_PACKET_QUEUE_DEPTH(&recv_q) !=
+					0) {
+					/* we couldn't fetch all packets at one,
+					 * time this creates a broken
+					 * bundle
+					 */
+					partial_bundle = true;
+				}
+			}
+
+			/* see if the previous operation fetched any
+			 * packets using bundling
+			 */
+			if (pkts_fetched == 0) {
+				/* dequeue one packet */
+				pkt = htc_packet_dequeue(&recv_q);
+				A_ASSERT(pkt != NULL);
+				if (!pkt)
+					break;
+
+				pkt->Completion = NULL;
+
+				if (HTC_PACKET_QUEUE_DEPTH(&recv_q) >
+				    0) {
+					/* lookaheads in all packets except the
+					 * last one in must be ignored
+					 */
+					pkt->PktInfo.AsRx.HTCRxFlags |=
+						HTC_RX_PKT_IGNORE_LOOKAHEAD;
+				}
+
+				/* go fetch the packet */
+				status =
+				hif_dev_recv_packet(pdev, pkt,
+						    pkt->ActualLength,
+						    mail_box_index);
+				while (QDF_IS_STATUS_ERROR(status) &&
+				       !HTC_QUEUE_EMPTY(&recv_q)) {
+					qdf_nbuf_t nbuf;
+
+					pkt = htc_packet_dequeue(&recv_q);
+					if (pkt == NULL)
+						break;
+					nbuf = pkt->pNetBufContext;
+					if (nbuf)
+						qdf_nbuf_free(nbuf);
+				}
+
+				if (QDF_IS_STATUS_ERROR(status))
+					break;
+				/* sent synchronously, queue this packet for
+				 * synchronous completion
+				 */
+				HTC_PACKET_ENQUEUE(&sync_comp_q, pkt);
+			}
+		}
+
+		/* synchronous handling */
+		if (pdev->DSRCanYield) {
+			/* for the SYNC case, increment count that tracks
+			 * when the DSR should yield
+			 */
+			pdev->CurrentDSRRecvCount++;
+		}
+
+		/* in the sync case, all packet buffers are now filled,
+		 * we can process each packet, check lookahead , then repeat
+		 */
+		rxCompletion = pdev->hif_callbacks.rxCompletionHandler;
+
+		/* unload sync completion queue */
+		while (!HTC_QUEUE_EMPTY(&sync_comp_q)) {
+			uint8_t pipeid;
+			qdf_nbuf_t netbuf;
+
+			pkt = htc_packet_dequeue(&sync_comp_q);
+			A_ASSERT(pkt != NULL);
+			if (!pkt)
+				break;
+
+			num_look_aheads = 0;
+			status = hif_dev_process_recv_header(pdev, pkt,
+							     look_aheads,
+							     &num_look_aheads);
+			if (QDF_IS_STATUS_ERROR(status)) {
+				HTC_PACKET_ENQUEUE_TO_HEAD(&sync_comp_q, pkt);
+				break;
+			}
+
+			netbuf = (qdf_nbuf_t)pkt->pNetBufContext;
+			/* set data length */
+			qdf_nbuf_put_tail(netbuf, pkt->ActualLength);
+
+			if (rxCompletion) {
+				pipeid =
+				hif_dev_map_mail_box_to_pipe(pdev,
+							     mail_box_index,
+							     true);
+				rxCompletion(pdev->hif_callbacks.Context,
+					     netbuf, pipeid);
+			}
+		}
+
+		if (QDF_IS_STATUS_ERROR(status)) {
+			if (!HTC_QUEUE_EMPTY(&sync_comp_q))
+				hif_dev_free_recv_pkt_queue(
+						&sync_comp_q);
+			break;
+		}
+
+		if (num_look_aheads == 0) {
+			/* no more look aheads */
+			break;
+		}
+		/* check whether other OS contexts have queued any WMI
+		 * command/data for WLAN. This check is needed only if WLAN
+		 * Tx and Rx happens in same thread context
+		 */
+		/* A_CHECK_DRV_TX(); */
+	}
+	if (num_pkts_fetched)
+		*num_pkts_fetched = total_fetched;
+
+	AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvMessagePendingHandler\n"));
+	return status;
+}
+
+/**
+ * hif_dev_service_cpu_interrupt() - service fatal interrupts
+ * synchronously
+ *
+ * @pDev: hif sdio device context
+ *
+ * Return: QDF_STATUS_SUCCESS for success
+ */
+static QDF_STATUS hif_dev_service_cpu_interrupt(struct hif_sdio_device *pdev)
+{
+	QDF_STATUS status;
+	uint8_t reg_buffer[4];
+	uint8_t cpu_int_status;
+
+	cpu_int_status = pdev->IrqProcRegisters.cpu_int_status &
+			 pdev->IrqEnableRegisters.cpu_int_status_enable;
+
+	HIF_ERROR("%s: 0x%x", __func__, (uint32_t)cpu_int_status);
+
+	/* Clear the interrupt */
+	pdev->IrqProcRegisters.cpu_int_status &= ~cpu_int_status;
+
+	/*set up the register transfer buffer to hit the register
+	 * 4 times , this is done to make the access 4-byte aligned
+	 * to mitigate issues with host bus interconnects that
+	 * restrict bus transfer lengths to be a multiple of 4-bytes
+	 * set W1C value to clear the interrupt, this hits the register
+	 * first
+	 */
+	reg_buffer[0] = cpu_int_status;
+	/* the remaining 4 values are set to zero which have no-effect  */
+	reg_buffer[1] = 0;
+	reg_buffer[2] = 0;
+	reg_buffer[3] = 0;
+
+	status = hif_read_write(pdev->HIFDevice,
+				CPU_INT_STATUS_ADDRESS,
+				reg_buffer, 4, HIF_WR_SYNC_BYTE_FIX, NULL);
+
+	A_ASSERT(status == QDF_STATUS_SUCCESS);
+
+	/* The Interrupt sent to the Host is generated via bit0
+	 * of CPU INT register
+	 */
+	if (cpu_int_status & 0x1) {
+		if (pdev->hif_callbacks.fwEventHandler)
+			/* It calls into HTC which propagates this
+			 * to ol_target_failure()
+			 */
+			pdev->hif_callbacks.fwEventHandler(
+				pdev->hif_callbacks.Context,
+				QDF_STATUS_E_FAILURE);
+	} else {
+		HIF_ERROR("%s: Unrecognized CPU event", __func__);
+	}
+
+	return status;
+}
+
+/**
+ * hif_dev_service_error_interrupt() - service error interrupts
+ * synchronously
+ *
+ * @pDev: hif sdio device context
+ *
+ * Return: QDF_STATUS_SUCCESS for success
+ */
+static QDF_STATUS hif_dev_service_error_interrupt(struct hif_sdio_device *pdev)
+{
+	QDF_STATUS status;
+	uint8_t reg_buffer[4];
+	uint8_t error_int_status = 0;
+
+	error_int_status = pdev->IrqProcRegisters.error_int_status & 0x0F;
+	HIF_ERROR("%s: 0x%x", __func__, error_int_status);
+
+	if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status))
+		HIF_ERROR("%s: Error : Wakeup", __func__);
+
+	if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status))
+		HIF_ERROR("%s: Error : Rx Underflow", __func__);
+
+	if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status))
+		HIF_ERROR("%s: Error : Tx Overflow", __func__);
+
+	/* Clear the interrupt */
+	pdev->IrqProcRegisters.error_int_status &= ~error_int_status;
+
+	/* set up the register transfer buffer to hit the register
+	 * 4 times , this is done to make the access 4-byte
+	 * aligned to mitigate issues with host bus interconnects that
+	 * restrict bus transfer lengths to be a multiple of 4-bytes
+	 */
+
+	/* set W1C value to clear the interrupt */
+	reg_buffer[0] = error_int_status;
+	/* the remaining 4 values are set to zero which have no-effect  */
+	reg_buffer[1] = 0;
+	reg_buffer[2] = 0;
+	reg_buffer[3] = 0;
+
+	status = hif_read_write(pdev->HIFDevice,
+				ERROR_INT_STATUS_ADDRESS,
+				reg_buffer, 4, HIF_WR_SYNC_BYTE_FIX, NULL);
+
+	A_ASSERT(status == QDF_STATUS_SUCCESS);
+	return status;
+}
+
+/**
+ * hif_dev_service_debug_interrupt() - service debug interrupts
+ * synchronously
+ *
+ * @pDev: hif sdio device context
+ *
+ * Return: QDF_STATUS_SUCCESS for success
+ */
+static QDF_STATUS hif_dev_service_debug_interrupt(struct hif_sdio_device *pdev)
+{
+	uint32_t dummy;
+	QDF_STATUS status;
+
+	/* Send a target failure event to the application */
+	HIF_ERROR("%s: Target debug interrupt", __func__);
+
+	/* clear the interrupt , the debug error interrupt is counter 0
+	 * read counter to clear interrupt
+	 */
+	status = hif_read_write(pdev->HIFDevice,
+				COUNT_DEC_ADDRESS,
+				(uint8_t *)&dummy,
+				4, HIF_RD_SYNC_BYTE_INC, NULL);
+
+	A_ASSERT(status == QDF_STATUS_SUCCESS);
+	return status;
+}
+
+/**
+ * hif_dev_service_counter_interrupt() - service counter interrupts
+ * synchronously
+ *
+ * @pDev: hif sdio device context
+ *
+ * Return: QDF_STATUS_SUCCESS for success
+ */
+static
+QDF_STATUS hif_dev_service_counter_interrupt(struct hif_sdio_device *pdev)
+{
+	uint8_t counter_int_status;
+
+	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n"));
+
+	counter_int_status = pdev->IrqProcRegisters.counter_int_status &
+			     pdev->IrqEnableRegisters.counter_int_status_enable;
+
+	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+			("Valid interrupt source in COUNTER_INT_STATUS: 0x%x\n",
+			 counter_int_status));
+
+	/* Check if the debug interrupt is pending
+	 * NOTE: other modules like GMBOX may use the counter interrupt
+	 * for credit flow control on other counters, we only need to
+	 * check for the debug assertion counter interrupt
+	 */
+	if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK)
+		return hif_dev_service_debug_interrupt(pdev);
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * hif_dev_process_pending_irqs() - process pending interrupts
+ * @pDev: hif sdio device context
+ * @pDone: pending irq completion status
+ * @pASyncProcessing: sync/async processing flag
+ *
+ * Return: QDF_STATUS_SUCCESS for success
+ */
+QDF_STATUS hif_dev_process_pending_irqs(struct hif_sdio_device *pdev,
+					bool *done,
+					bool *async_processing)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	uint8_t host_int_status = 0;
+	uint32_t look_ahead[MAILBOX_USED_COUNT];
+	int i;
+
+	qdf_mem_zero(&look_ahead, sizeof(look_ahead));
+	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+			("+ProcessPendingIRQs: (dev: 0x%lX)\n",
+			 (unsigned long)pdev));
+
+	/* NOTE: the HIF implementation guarantees that the context
+	 * of this call allows us to perform SYNCHRONOUS I/O,
+	 * that is we can block, sleep or call any API that
+	 * can block or switch thread/task ontexts.
+	 * This is a fully schedulable context.
+	 */
+	do {
+		if (pdev->IrqEnableRegisters.int_status_enable == 0) {
+			/* interrupt enables have been cleared, do not try
+			 * to process any pending interrupts that
+			 * may result in more bus transactions.
+			 * The target may be unresponsive at this point.
+			 */
+			break;
+		}
+		status = hif_read_write(pdev->HIFDevice,
+					HOST_INT_STATUS_ADDRESS,
+					(uint8_t *)&pdev->IrqProcRegisters,
+					sizeof(pdev->IrqProcRegisters),
+					HIF_RD_SYNC_BYTE_INC, NULL);
+
+		if (QDF_IS_STATUS_ERROR(status))
+			break;
+
+		if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) {
+			hif_dev_dump_registers(pdev,
+					       &pdev->IrqProcRegisters,
+					       &pdev->IrqEnableRegisters,
+					       &pdev->MailBoxCounterRegisters);
+		}
+
+		/* Update only those registers that are enabled */
+		host_int_status = pdev->IrqProcRegisters.host_int_status
+				  & pdev->IrqEnableRegisters.int_status_enable;
+
+		/* only look at mailbox status if the HIF layer did not
+		 * provide this function, on some HIF interfaces reading
+		 * the RX lookahead is not valid to do
+		 */
+		for (i = 0; i < MAILBOX_USED_COUNT; i++) {
+			look_ahead[i] = 0;
+			if (host_int_status & (1 << i)) {
+				/* mask out pending mailbox value, we use
+				 * "lookAhead" as the real flag for
+				 * mailbox processing below
+				 */
+				host_int_status &= ~(1 << i);
+				if (pdev->IrqProcRegisters.
+				    rx_lookahead_valid & (1 << i)) {
+					/* mailbox has a message and the
+					 * look ahead is valid
+					 */
+					look_ahead[i] =
+						pdev->
+						IrqProcRegisters.rx_lookahead[
+						MAILBOX_LOOKAHEAD_SIZE_IN_WORD *
+						i];
+				}
+			}
+		} /*end of for loop */
+	} while (false);
+
+	do {
+		bool bLookAheadValid = false;
+		/* did the interrupt status fetches succeed? */
+		if (QDF_IS_STATUS_ERROR(status))
+			break;
+
+		for (i = 0; i < MAILBOX_USED_COUNT; i++) {
+			if (look_ahead[i] != 0) {
+				bLookAheadValid = true;
+				break;
+			}
+		}
+
+		if ((host_int_status == 0) && !bLookAheadValid) {
+			/* nothing to process, the caller can use this
+			 * to break out of a loop
+			 */
+			*done = true;
+			break;
+		}
+
+		if (bLookAheadValid) {
+			for (i = 0; i < MAILBOX_USED_COUNT; i++) {
+				int fetched = 0;
+
+				if (look_ahead[i] == 0)
+					continue;
+				AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+						("mbox[%d],lookahead:0x%X\n",
+						i, look_ahead[i]));
+				/* Mailbox Interrupt, the HTC layer may issue
+				 * async requests to empty the mailbox...
+				 * When emptying the recv mailbox we use the
+				 * async handler from the completion routine of
+				 * routine of the callers read request.
+				 * This can improve performance by reducing
+				 * the  context switching when we rapidly
+				 * pull packets
+				 */
+				status = hif_dev_recv_message_pending_handler(
+							pdev, i,
+							&look_ahead
+							[i], 1,
+							async_processing,
+							&fetched);
+				if (QDF_IS_STATUS_ERROR(status))
+					break;
+
+				if (!fetched) {
+					/* HTC could not pull any messages out
+					 * due to lack of resources force DSR
+					 * handle to ack the interrupt
+					 */
+					*async_processing = false;
+					pdev->RecheckIRQStatusCnt = 0;
+				}
+			}
+		}
+
+		/* now handle the rest of them */
+		AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+				("Valid source for OTHER interrupts: 0x%x\n",
+				host_int_status));
+
+		if (HOST_INT_STATUS_CPU_GET(host_int_status)) {
+			/* CPU Interrupt */
+			status = hif_dev_service_cpu_interrupt(pdev);
+			if (QDF_IS_STATUS_ERROR(status))
+				break;
+		}
+
+		if (HOST_INT_STATUS_ERROR_GET(host_int_status)) {
+			/* Error Interrupt */
+			status = hif_dev_service_error_interrupt(pdev);
+			if (QDF_IS_STATUS_ERROR(status))
+				break;
+		}
+
+		if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) {
+			/* Counter Interrupt */
+			status = hif_dev_service_counter_interrupt(pdev);
+			if (QDF_IS_STATUS_ERROR(status))
+				break;
+		}
+
+	} while (false);
+
+	/* an optimization to bypass reading the IRQ status registers
+	 * unecessarily which can re-wake the target, if upper layers
+	 * determine that we are in a low-throughput mode, we can
+	 * rely on taking another interrupt rather than re-checking
+	 * the status registers which can re-wake the target.
+	 *
+	 * NOTE : for host interfaces that use the special
+	 * GetPendingEventsFunc, this optimization cannot be used due to
+	 * possible side-effects.  For example, SPI requires the host
+	 * to drain all messages from the mailbox before exiting
+	 * the ISR routine.
+	 */
+	if (!(*async_processing) && (pdev->RecheckIRQStatusCnt == 0)) {
+		AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+				("Bypass IRQ Status re-check, forcing done\n"));
+		*done = true;
+	}
+
+	AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
+			("-ProcessPendingIRQs: (done:%d, async:%d) status=%d\n",
+			 *done, *async_processing, status));
+
+	return status;
+}
+#endif /* CONFIG_SDIO_TRANSFER_MAILBOX */

+ 92 - 0
hif/src/sdio/transfer/mailbox.h

@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013-2014, 2016-2018 The Linux Foundation. All rights reserved.
+ *
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifndef _MAILBOX_H_
+#define _MAILBOX_H__
+
+#include "a_debug.h"
+#include "hif_sdio_dev.h"
+#include "htc_packet.h"
+#include "htc_api.h"
+#include "hif_internal.h"
+
+#define INVALID_MAILBOX_NUMBER 0xFF
+
+#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK |	\
+			    INT_STATUS_ENABLE_CPU_MASK   |	\
+			    INT_STATUS_ENABLE_COUNTER_MASK)
+
+/* HTC operational parameters */
+#define HTC_TARGET_RESPONSE_TIMEOUT        2000 /* in ms */
+#define HTC_TARGET_DEBUG_INTR_MASK         0x01
+#define HTC_TARGET_CREDIT_INTR_MASK        0xF0
+
+#define MAILBOX_COUNT 4
+#define MAILBOX_FOR_BLOCK_SIZE 1
+#define MAILBOX_USED_COUNT 2
+#if defined(SDIO_3_0)
+#define MAILBOX_LOOKAHEAD_SIZE_IN_WORD 2
+#else
+#define MAILBOX_LOOKAHEAD_SIZE_IN_WORD 1
+#endif
+#define AR6K_TARGET_DEBUG_INTR_MASK     0x01
+
+PREPACK struct MBOX_IRQ_PROC_REGISTERS {
+	uint8_t host_int_status;
+	uint8_t cpu_int_status;
+	uint8_t error_int_status;
+	uint8_t counter_int_status;
+	uint8_t mbox_frame;
+	uint8_t rx_lookahead_valid;
+	uint8_t host_int_status2;
+	uint8_t gmbox_rx_avail;
+	uint32_t rx_lookahead[MAILBOX_LOOKAHEAD_SIZE_IN_WORD * MAILBOX_COUNT];
+	uint32_t int_status_enable;
+} POSTPACK;
+
+PREPACK struct MBOX_IRQ_ENABLE_REGISTERS {
+	uint8_t int_status_enable;
+	uint8_t cpu_int_status_enable;
+	uint8_t error_status_enable;
+	uint8_t counter_int_status_enable;
+} POSTPACK;
+
+#define TOTAL_CREDIT_COUNTER_CNT 4
+
+PREPACK struct MBOX_COUNTER_REGISTERS {
+	uint32_t counter[TOTAL_CREDIT_COUNTER_CNT];
+} POSTPACK;
+
+struct devRegisters {
+	struct MBOX_IRQ_PROC_REGISTERS IrqProcRegisters;
+	struct MBOX_IRQ_ENABLE_REGISTERS IrqEnableRegisters;
+	struct MBOX_COUNTER_REGISTERS MailBoxCounterRegisters;
+};
+
+#define mboxProcRegs(hdev)	hdev->devRegisters.IrqProcRegisters
+#define mboxEnaRegs(hdev)	hdev->devRegisters.IrqEnableRegisters
+#define mboxCountRegs(hdev)	hdev->devRegisters.MailBoxCounterRegisters
+
+#define DEV_REGISTERS_SIZE	(sizeof(struct MBOX_IRQ_PROC_REGISTERS) + \
+				 sizeof(struct MBOX_IRQ_ENABLE_REGISTERS) + \
+				 sizeof(struct MBOX_COUNTER_REGISTERS))
+
+#endif /* _MAILBOX_H_ */

+ 723 - 0
hif/src/sdio/transfer/transfer.c

@@ -0,0 +1,723 @@
+/*
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
+ *
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#define ATH_MODULE_NAME hif
+#include <qdf_types.h>
+#include <qdf_status.h>
+#include <qdf_timer.h>
+#include <qdf_time.h>
+#include <qdf_lock.h>
+#include <qdf_mem.h>
+#include <qdf_util.h>
+#include <qdf_defer.h>
+#include <qdf_atomic.h>
+#include <qdf_nbuf.h>
+#include <athdefs.h>
+#include <qdf_net_types.h>
+#include <a_types.h>
+#include <athdefs.h>
+#include <a_osapi.h>
+#include <hif.h>
+#include <htc_services.h>
+#include <a_debug.h>
+#include <htc_internal.h>
+#include "hif_sdio_internal.h"
+#include "transfer.h"
+
+/**
+ * hif_dev_rw_completion_handler() - Completion routine
+ * for ALL HIF layer async I/O
+ * @context: hif send context
+ * @status: completion routine sync/async context
+ *
+ * Return: 0 for success and non-zero for failure
+ */
+
+QDF_STATUS hif_dev_rw_completion_handler(void *ctx, QDF_STATUS status)
+{
+	QDF_STATUS (*txCompHandler)(void *, qdf_nbuf_t, uint32_t, uint32_t);
+	struct hif_sendContext *sctx = (struct hif_sendContext *)ctx;
+	struct hif_sdio_device *pdev = sctx->pDev;
+	unsigned int xfer_id = sctx->transferID;
+	uint32_t toeplitz_hash_result = 0;
+	qdf_nbuf_t buf = sctx->netbuf;
+
+	if (sctx->bNewAlloc)
+		qdf_mem_free(ctx);
+	else
+		qdf_nbuf_pull_head(buf, sctx->head_data_len);
+
+	txCompHandler = pdev->hif_callbacks.txCompletionHandler;
+	if (txCompHandler) {
+		txCompHandler(pdev->hif_callbacks.Context, buf,
+			      xfer_id, toeplitz_hash_result);
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/**
+ * hif_dev_send_buffer() - send buffer to sdio device
+ * @pDev: HIf device object
+ * @xfer_id: transfer id
+ * @pipe: ul/dl pipe
+ * @nbytes: no of bytes to transfer
+ * @buf: pointer to buffer
+ *
+ * Return: 0 for success and non-zero for failure
+ */
+QDF_STATUS hif_dev_send_buffer(struct hif_sdio_device *pdev, uint32_t xfer_id,
+			       uint8_t pipe, uint32_t nbytes, qdf_nbuf_t buf)
+{
+	QDF_STATUS status;
+	unsigned char *pData;
+	struct hif_sendContext *sctx;
+	uint32_t request = HIF_WR_ASYNC_BLOCK_INC;
+	uint32_t padded_length, addr = 0;
+	int frag_count = 0, i, count, head_len;
+
+	if (hif_get_send_address(pdev, pipe, &addr)) {
+		HIF_ERROR("%s: Invalid address map for pipe 0x%x",
+			  __func__, pipe);
+
+		return QDF_STATUS_E_INVAL;
+	}
+
+	padded_length = DEV_CALC_SEND_PADDED_LEN(pdev, nbytes);
+	A_ASSERT(padded_length - nbytes < HIF_DUMMY_SPACE_MASK + 1);
+
+	request |= ((padded_length - nbytes) << 16);
+
+	frag_count = qdf_nbuf_get_num_frags(buf);
+
+	if (frag_count > 1) {
+		/* Header data length should be total sending length.
+		 * Subtract internal data length of netbuf
+		 */
+		head_len = sizeof(struct hif_sendContext) +
+			(nbytes - qdf_nbuf_get_frag_len(buf, frag_count - 1));
+	} else {
+		/*
+		 * | hif_sendContext | netbuf->data
+		 */
+		head_len = sizeof(struct hif_sendContext);
+	}
+
+	/* Check whether head room is enough to save extra head data */
+	if ((head_len <= qdf_nbuf_headroom(buf)) &&
+	    (qdf_nbuf_tailroom(buf) >= (padded_length - nbytes))) {
+		sctx = (struct hif_sendContext *)qdf_nbuf_push_head(buf,
+								    head_len);
+		sctx->bNewAlloc = false;
+	} else {
+		sctx = (struct hif_sendContext *)qdf_mem_malloc(sizeof(*sctx) +
+								padded_length);
+		if (sctx) {
+			sctx->bNewAlloc = true;
+		} else {
+			HIF_ERROR("%s: Alloc send context fail %u\n",
+				  __func__, sizeof(*sctx) + padded_length);
+			return QDF_STATUS_E_NOMEM;
+		}
+	}
+
+	sctx->netbuf = buf;
+	sctx->pDev = pdev;
+	sctx->transferID = xfer_id;
+	sctx->head_data_len = head_len;
+	/*
+	 * Copy data to head part of netbuf or head of allocated buffer.
+	 * if buffer is new allocated, the last buffer should be copied also.
+	 * It assume last fragment is internal buffer of netbuf
+	 * sometime total length of fragments larger than nbytes
+	 */
+	pData = (unsigned char *)sctx + sizeof(struct hif_sendContext);
+	for (i = 0, count = sctx->bNewAlloc ? frag_count : frag_count - 1;
+	     i < count;
+	     i++) {
+		int frag_len = qdf_nbuf_get_frag_len(buf, i);
+		unsigned char *frag_addr = qdf_nbuf_get_frag_vaddr(buf, i);
+
+		if (frag_len > nbytes)
+			frag_len = nbytes;
+		memcpy(pData, frag_addr, frag_len);
+		pData += frag_len;
+		nbytes -= frag_len;
+		if (nbytes <= 0)
+			break;
+	}
+
+	/* Reset pData pointer and sctx out */
+	pData = (unsigned char *)sctx + sizeof(struct hif_sendContext);
+
+	status = hif_read_write(pdev->HIFDevice, addr, (char *)pData,
+				padded_length, request, (void *)sctx);
+
+	if (status == QDF_STATUS_E_PENDING) {
+		/*
+		 * it will return QDF_STATUS_E_PENDING in native HIF
+		 * implementation, which should be treated as successful
+		 * result here.
+		 */
+		status = QDF_STATUS_SUCCESS;
+	}
+
+	/* release buffer or move back data pointer when failed */
+	if (status != QDF_STATUS_SUCCESS) {
+		if (sctx->bNewAlloc)
+			qdf_mem_free(sctx);
+		else
+			qdf_nbuf_pull_head(buf, head_len);
+	}
+
+	return status;
+}
+
+/**
+ * hif_dev_alloc_and_prepare_rx_packets() - Allocate packets for recv frames.
+ * @pdev : HIF device object
+ * @look_aheads : Look ahead information on the frames
+ * @messages : Number of messages
+ * @queue : Queue to put the allocated frames
+ *
+ * Return : QDF_STATUS_SUCCESS on success else error value
+ */
+QDF_STATUS hif_dev_alloc_and_prepare_rx_packets(struct hif_sdio_device *pdev,
+						uint32_t look_aheads[],
+						int messages,
+						HTC_PACKET_QUEUE *queue)
+{
+	int i, j;
+	bool no_recycle;
+	int num_messages;
+	HTC_PACKET *packet;
+	HTC_FRAME_HDR *hdr;
+	uint32_t full_length;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	/* lock RX while we assemble the packet buffers */
+	LOCK_HIF_DEV_RX(pdev);
+
+	for (i = 0; i < messages; i++) {
+		hdr = (HTC_FRAME_HDR *)&look_aheads[i];
+		if (hdr->EndpointID >= ENDPOINT_MAX) {
+			HIF_ERROR("%s: Invalid Endpoint:%d\n",
+				  __func__, hdr->EndpointID);
+			status = QDF_STATUS_E_INVAL;
+			break;
+		}
+
+		if (hdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) {
+			HIF_ERROR("%s: Payload length %d exceeds max HTC : %u",
+				  __func__,
+				  hdr->PayloadLen,
+				 (uint32_t)HTC_MAX_PAYLOAD_LENGTH);
+			status = QDF_STATUS_E_INVAL;
+			break;
+		}
+
+		if ((hdr->Flags & HTC_FLAGS_RECV_BUNDLE_CNT_MASK) == 0) {
+			/* HTC header only indicates 1 message to fetch */
+			num_messages = 1;
+		} else {
+			/* HTC header indicates that every packet to follow
+			 * has the same padded length so that it can
+			 * be optimally fetched as a full bundle
+			 */
+			num_messages = GET_RECV_BUNDLE_COUNT(hdr->Flags);
+			/* the count doesn't include the starter frame, just
+			 * a count of frames to follow
+			 */
+			num_messages++;
+
+			HIF_INFO("%s: HTC header : %u messages in bundle",
+				 __func__, num_messages);
+		}
+
+		full_length = DEV_CALC_RECV_PADDED_LEN(pdev,
+						       hdr->PayloadLen +
+						       sizeof(HTC_FRAME_HDR));
+
+		/* get packet buffers for each message, if there was a
+		 * bundle detected in the header,
+		 * use pHdr as a template to fetch all packets in the bundle
+		 */
+		for (j = 0; j < num_messages; j++) {
+			/* reset flag, any packets allocated using the
+			 * RecvAlloc() API cannot be recycled on cleanup,
+			 * they must be explicitly returned
+			 */
+			no_recycle = false;
+			packet = hif_dev_alloc_rx_buffer(pdev);
+
+			if (!packet) {
+				/* No error, simply need to mark that
+				 * we are waiting for buffers.
+				 */
+				pdev->RecvStateFlags |= HTC_RECV_WAIT_BUFFERS;
+				/* pDev->EpWaitingForBuffers = pEndpoint->Id; */
+				status = QDF_STATUS_E_RESOURCES;
+				break;
+			}
+			/* clear flags */
+			packet->PktInfo.AsRx.HTCRxFlags = 0;
+			packet->PktInfo.AsRx.IndicationFlags = 0;
+			packet->Status = QDF_STATUS_SUCCESS;
+
+			if (no_recycle) {
+				/* flag that these packets cannot be recycled,
+				 * they have to be returned to the user
+				 */
+				packet->PktInfo.AsRx.HTCRxFlags |=
+					HTC_RX_PKT_NO_RECYCLE;
+			}
+			/* add packet to queue (also incase we need to
+			 * cleanup down below)
+			 */
+			HTC_PACKET_ENQUEUE(queue, packet);
+
+			/* if (HTC_STOPPING(target)) {
+			 *      status = QDF_STATUS_E_CANCELED;
+			 *      break;
+			 *  }
+			 */
+
+			/* make sure  message can fit in the endpoint buffer */
+			if (full_length > packet->BufferLength) {
+				HIF_ERROR("%s: Payload Length Error", __func__);
+				HIF_ERROR("%s: header reports payload: %u(%u)",
+					  __func__, hdr->PayloadLen,
+					  full_length);
+				HIF_ERROR("%s: endpoint buffer size: %d\n",
+					  __func__, packet->BufferLength);
+				status = QDF_STATUS_E_INVAL;
+				break;
+			}
+
+			if (j > 0) {
+				/* for messages fetched in a bundle the expected
+				 * lookahead is unknown as we are only using the
+				 * lookahead of the first packet as a template
+				 * of what to expect for lengths
+				 */
+				packet->PktInfo.AsRx.HTCRxFlags |=
+					HTC_RX_PKT_REFRESH_HDR;
+				/* set it to something invalid */
+				packet->PktInfo.AsRx.ExpectedHdr = 0xFFFFFFFF;
+			} else {
+				packet->PktInfo.AsRx.ExpectedHdr =
+					look_aheads[i];
+			}
+			/* set the amount of data to fetch */
+			packet->ActualLength =
+				hdr->PayloadLen + HTC_HDR_LENGTH;
+			if ((j == (num_messages - 1)) &&
+			    ((hdr->Flags) & HTC_FLAGS_RECV_1MORE_BLOCK))
+				packet->PktInfo.AsRx.HTCRxFlags |=
+				HTC_RX_PKT_LAST_BUNDLED_PKT_HAS_ADDTIONAL_BLOCK;
+			packet->Endpoint = hdr->EndpointID;
+			packet->Completion = NULL;
+		}
+
+		if (QDF_IS_STATUS_ERROR(status))
+			break;
+	}
+
+	UNLOCK_HIF_DEV_RX(pdev);
+
+	/* for NO RESOURCE error, no need to flush data queue */
+	if (QDF_IS_STATUS_ERROR(status)	&&
+	    (status != QDF_STATUS_E_RESOURCES)) {
+		while (!HTC_QUEUE_EMPTY(queue)) {
+			qdf_nbuf_t netbuf;
+
+			packet = htc_packet_dequeue(queue);
+			if (packet == NULL)
+				break;
+			netbuf = (qdf_nbuf_t)packet->pNetBufContext;
+			if (netbuf)
+				qdf_nbuf_free(netbuf);
+		}
+	}
+	if (status == QDF_STATUS_E_RESOURCES)
+		status = QDF_STATUS_SUCCESS;
+	return status;
+}
+
+/**
+ * hif_dev_process_trailer() - Process the receive frame trailer
+ * @pdev : HIF device object
+ * @buffer : The buffer containing the trailer
+ * @length : Length of the buffer
+ * @next_look_aheads : The lookahead that is next
+ * @num_look_aheads : Number of lookahead information
+ * @from_endpoint : The endpoint on which the trailer is received
+ */
+QDF_STATUS hif_dev_process_trailer(struct hif_sdio_device *pdev,
+				   uint8_t *buffer, int length,
+				   uint32_t *next_look_aheads,
+				   int *num_look_aheads,
+				   HTC_ENDPOINT_ID from_endpoint)
+{
+	int orig_length;
+	QDF_STATUS status;
+	uint8_t *record_buf;
+	uint8_t *orig_buffer;
+	HTC_RECORD_HDR *record;
+	HTC_LOOKAHEAD_REPORT *look_ahead;
+
+	HIF_INFO("%s: length:%d", __func__, length);
+
+	orig_buffer = buffer;
+	orig_length = length;
+	status = QDF_STATUS_SUCCESS;
+
+	while (length > 0) {
+		if (length < sizeof(HTC_RECORD_HDR)) {
+			status = QDF_STATUS_E_PROTO;
+			break;
+		}
+		/* these are byte aligned structs */
+		record = (HTC_RECORD_HDR *)buffer;
+		length -= sizeof(HTC_RECORD_HDR);
+		buffer += sizeof(HTC_RECORD_HDR);
+
+		if (record->Length > length) {
+			/* no room left in buffer for record */
+			HIF_ERROR("%s: invalid record len: (%u, %u)",
+				  __func__, record->Length,
+				  record->RecordID);
+			HIF_ERROR("%s: buffer has %d bytes left",
+				  __func__, length);
+			status = QDF_STATUS_E_PROTO;
+			break;
+		}
+		/* start of record follows the header */
+		record_buf = buffer;
+
+		switch (record->RecordID) {
+		case HTC_RECORD_CREDITS:
+			/* Process in HTC, ignore here */
+			break;
+		case HTC_RECORD_LOOKAHEAD:
+			A_ASSERT(record->Length >= sizeof(*look_ahead));
+			look_ahead = (HTC_LOOKAHEAD_REPORT *)record_buf;
+			if ((look_ahead->PreValid ==
+			     ((~look_ahead->PostValid) & 0xFF)) &&
+			    next_look_aheads) {
+				HIF_INFO_HI("%s: look_ahead Report", __func__);
+				HIF_INFO_HI("%s:prevalid:0x%x, postvalid:0x%x",
+					    __func__, look_ahead->PreValid,
+					    look_ahead->PostValid);
+				HIF_INFO_HI("%s:from endpoint %d : %u",
+					    __func__, from_endpoint,
+					    look_ahead->LookAhead0);
+				/* look ahead bytes are valid, copy them over */
+				((uint8_t *)(&next_look_aheads[0]))[0] =
+					look_ahead->LookAhead0;
+				((uint8_t *)(&next_look_aheads[0]))[1] =
+					look_ahead->LookAhead1;
+				((uint8_t *)(&next_look_aheads[0]))[2] =
+					look_ahead->LookAhead2;
+				((uint8_t *)(&next_look_aheads[0]))[3] =
+					look_ahead->LookAhead3;
+
+				if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
+					debug_dump_bytes((uint8_t *)
+							 next_look_aheads, 4,
+							 "Next Look Ahead");
+				}
+				/* just one normal lookahead */
+				if (num_look_aheads)
+					*num_look_aheads = 1;
+			}
+			break;
+		case HTC_RECORD_LOOKAHEAD_BUNDLE:
+			A_ASSERT(record->Length >=
+					sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT));
+			if ((record->Length >=
+			     sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)) &&
+			    next_look_aheads) {
+				HTC_BUNDLED_LOOKAHEAD_REPORT
+				*pBundledLookAheadRpt;
+				int i;
+
+				pBundledLookAheadRpt =
+				(HTC_BUNDLED_LOOKAHEAD_REPORT *)record_buf;
+
+				if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
+					debug_dump_bytes(record_buf,
+							 record->Length,
+							 "Bundle look_ahead");
+				}
+
+				if ((record->Length /
+				     (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT)))
+					> HTC_MAX_MSG_PER_BUNDLE_RX) {
+					/* this should never happen, the target
+					 * restricts the number of messages per
+					 * bundle configured by the host
+					 */
+					A_ASSERT(false);
+					status = QDF_STATUS_E_PROTO;
+					break;
+				}
+				for (i = 0;
+				     i <
+				     (int)(record->Length /
+					   (sizeof
+					    (HTC_BUNDLED_LOOKAHEAD_REPORT)));
+				     i++) {
+					((uint8_t *)(&next_look_aheads[i]))[0] =
+					   pBundledLookAheadRpt->LookAhead0;
+					((uint8_t *)(&next_look_aheads[i]))[1] =
+					   pBundledLookAheadRpt->LookAhead1;
+					((uint8_t *)(&next_look_aheads[i]))[2] =
+					   pBundledLookAheadRpt->LookAhead2;
+					((uint8_t *)(&next_look_aheads[i]))[3] =
+					   pBundledLookAheadRpt->LookAhead3;
+					pBundledLookAheadRpt++;
+				}
+				if (num_look_aheads)
+					*num_look_aheads = i;
+			}
+			break;
+		default:
+			HIF_ERROR("%s: HIF unhandled record: id:%u length:%u",
+				  __func__, record->RecordID, record->Length);
+			break;
+		}
+
+		if (QDF_IS_STATUS_ERROR(status))
+			break;
+
+		/* advance buffer past this record for next time around */
+		buffer += record->Length;
+		length -= record->Length;
+	}
+
+	if (QDF_IS_STATUS_ERROR(status))
+		debug_dump_bytes(orig_buffer, orig_length,
+				 "BAD Recv Trailer");
+
+	HIF_INFO("%s: status = %d", __func__, status);
+
+	return status;
+}
+
+/* process a received message (i.e. strip off header,
+ * process any trailer data).
+ * note : locks must be released when this function is called
+ */
+QDF_STATUS hif_dev_process_recv_header(struct hif_sdio_device *pdev,
+				       HTC_PACKET *packet,
+				       uint32_t *next_look_aheads,
+				       int *num_look_aheads)
+{
+	uint8_t temp;
+	uint8_t *buf;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	uint16_t payloadLen;
+	uint32_t look_ahead, actual_length;
+
+	buf = packet->pBuffer;
+	actual_length = packet->ActualLength;
+
+	if (num_look_aheads)
+		*num_look_aheads = 0;
+
+	AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader\n"));
+
+	if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV))
+		AR_DEBUG_PRINTBUF(buf, packet->ActualLength, "HTC Recv PKT");
+
+	do {
+		/* note, we cannot assume the alignment of pBuffer,
+		 * so we use the safe macros to
+		 * retrieve 16 bit fields
+		 */
+		payloadLen = HTC_GET_FIELD(buf, HTC_FRAME_HDR,
+					   PAYLOADLEN);
+
+		((uint8_t *)&look_ahead)[0] = buf[0];
+		((uint8_t *)&look_ahead)[1] = buf[1];
+		((uint8_t *)&look_ahead)[2] = buf[2];
+		((uint8_t *)&look_ahead)[3] = buf[3];
+
+		if (packet->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) {
+			/* refresh expected hdr, since this was unknown
+			 * at the time we grabbed the packets
+			 * as part of a bundle
+			 */
+			packet->PktInfo.AsRx.ExpectedHdr = look_ahead;
+			/* refresh actual length since we now have the
+			 * real header
+			 */
+			packet->ActualLength = payloadLen + HTC_HDR_LENGTH;
+
+			/* validate the actual header that was refreshed  */
+			if (packet->ActualLength > packet->BufferLength) {
+				HIF_ERROR("%s: Bundled RECV Look ahead: 0x%X",
+					  __func__, look_ahead);
+				HIF_ERROR("%s: Invalid HDR payload length(%d)",
+					  __func__,  payloadLen);
+				/* limit this to max buffer just to print out
+				 * some of the buffer
+				 */
+				packet->ActualLength =
+					min(packet->ActualLength,
+					    packet->BufferLength);
+				status = QDF_STATUS_E_PROTO;
+				break;
+			}
+
+			if (packet->Endpoint
+			    != HTC_GET_FIELD(buf, HTC_FRAME_HDR, ENDPOINTID)) {
+				HIF_ERROR("%s: Refreshed HDR EP (%d)",
+					  __func__,
+					  HTC_GET_FIELD(buf, HTC_FRAME_HDR,
+							ENDPOINTID));
+				HIF_ERROR("%s: doesn't match expected EP (%d)",
+					  __func__, packet->Endpoint);
+				status = QDF_STATUS_E_PROTO;
+				break;
+			}
+		}
+
+		if (look_ahead != packet->PktInfo.AsRx.ExpectedHdr) {
+			/* somehow the lookahead that gave us the full read
+			 * length did not reflect the actual header
+			 * in the pending message
+			 */
+			HIF_ERROR("%s: lookahead mismatch!", __func__);
+			HIF_ERROR("%s: pPkt:0x%lX flags:0x%X",
+				  __func__, (unsigned long)packet,
+				  packet->PktInfo.AsRx.HTCRxFlags);
+			HIF_ERROR("%s: look_ahead 0x%08X != 0x%08X",
+				  __func__, look_ahead,
+				  packet->PktInfo.AsRx.ExpectedHdr);
+#ifdef ATH_DEBUG_MODULE
+			debug_dump_bytes((uint8_t *)&packet->PktInfo.AsRx.
+					 ExpectedHdr, 4,
+					 "Expected Message look_ahead");
+			debug_dump_bytes(buf, sizeof(HTC_FRAME_HDR),
+					 "Current Frame Header");
+#ifdef HTC_CAPTURE_LAST_FRAME
+			debug_dump_bytes((uint8_t *)&target->LastFrameHdr,
+					 sizeof(HTC_FRAME_HDR),
+					 "Last Frame Header");
+			if (target->LastTrailerLength != 0)
+				debug_dump_bytes(target->LastTrailer,
+						 target->LastTrailerLength,
+						 "Last trailer");
+#endif
+#endif
+			status = QDF_STATUS_E_PROTO;
+			break;
+		}
+
+		/* get flags */
+		temp = HTC_GET_FIELD(buf, HTC_FRAME_HDR, FLAGS);
+
+		if (temp & HTC_FLAGS_RECV_TRAILER) {
+			/* this packet has a trailer */
+
+			/* extract the trailer length in control byte 0 */
+			temp = HTC_GET_FIELD(buf, HTC_FRAME_HDR, CONTROLBYTES0);
+
+			if ((temp < sizeof(HTC_RECORD_HDR)) ||
+			    (temp > payloadLen)) {
+				HIF_ERROR("%s: invalid header",
+					  __func__);
+				HIF_ERROR("%s: payloadlength should be :%d",
+					  __func__, payloadLen);
+				HIF_ERROR("%s: But control bytes is :%d)",
+					  __func__, temp);
+				status = QDF_STATUS_E_PROTO;
+				break;
+			}
+
+			if (packet->PktInfo.AsRx.
+			    HTCRxFlags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
+				/* this packet was fetched as part of an HTC
+				 * bundle as the lookahead is not valid.
+				 * Next packet may have already been fetched as
+				 * part of the bundle
+				 */
+				next_look_aheads = NULL;
+				num_look_aheads = NULL;
+			}
+
+			/* process trailer data that follows HDR and
+			 * application payload
+			 */
+			status =
+			hif_dev_process_trailer(pdev,
+						(buf + HTC_HDR_LENGTH +
+						 payloadLen - temp),
+						temp,
+						next_look_aheads,
+						num_look_aheads,
+						packet->Endpoint);
+
+			if (QDF_IS_STATUS_ERROR(status))
+				break;
+		}
+	} while (false);
+
+	if (QDF_IS_STATUS_ERROR(status)) {
+		/* dump the whole packet */
+		debug_dump_bytes(buf, packet->ActualLength,
+				 "BAD HTC Recv PKT");
+	} else {
+		if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
+			if (packet->ActualLength > 0) {
+				AR_DEBUG_PRINTBUF(packet->pBuffer,
+						  packet->ActualLength,
+						  "HTC - Application Msg");
+			}
+		}
+	}
+	AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
+			("-hif_dev_process_recv_header\n"));
+	return status;
+}
+
+/**
+ * hif_dev_free_recv_pkt() - Free the allocated recv packets in the queue
+ * @recv_pkt_queue : The queue that contains the packets to be queued
+ *
+ * Return : NONE
+ */
+void hif_dev_free_recv_pkt_queue(HTC_PACKET_QUEUE *recv_pkt_queue)
+{
+	HTC_PACKET *packet;
+	qdf_nbuf_t netbuf;
+
+	while (!HTC_QUEUE_EMPTY(recv_pkt_queue)) {
+		packet = htc_packet_dequeue(recv_pkt_queue);
+		if (packet == NULL)
+			break;
+		netbuf = (qdf_nbuf_t)packet->pNetBufContext;
+		if (netbuf)
+			qdf_nbuf_free(netbuf);
+	}
+}

+ 87 - 0
hif/src/sdio/transfer/transfer.h

@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
+ *
+ *
+ *
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __TRANSFER_H_
+#define __TRANSFER_H_
+
+#include <qdf_types.h>
+#include <qdf_status.h>
+#include <qdf_timer.h>
+#include <qdf_time.h>
+#include <qdf_lock.h>
+#include <qdf_mem.h>
+#include <qdf_util.h>
+#include <qdf_defer.h>
+#include <qdf_atomic.h>
+#include <qdf_nbuf.h>
+#include <athdefs.h>
+#include <qdf_net_types.h>
+#include <a_types.h>
+#include <athdefs.h>
+#include <a_osapi.h>
+#include <hif.h>
+#include <htc_services.h>
+#include <a_debug.h>
+#include "hif_sdio_internal.h"
+
+#define NBUF_ALLOC_FAIL_WAIT_TIME 100
+/* high nibble */
+#define BUNDLE_COUNT_HIGH(f) (((f) & 0x0C) << 2)
+/* low nibble */
+#define BUNDLE_COUNT_LOW(f)  (((f) & 0xF0) >> 4)
+#define GET_RECV_BUNDLE_COUNT(f) (BUNDLE_COUNT_HIGH(f) + BUNDLE_COUNT_LOW(f))
+
+/*
+ * Data structure to record required sending context data
+ */
+struct hif_sendContext {
+	bool bNewAlloc;
+	struct hif_sdio_device *pDev;
+	qdf_nbuf_t netbuf;
+	unsigned int transferID;
+	unsigned int head_data_len;
+};
+
+void hif_dev_dump_registers(struct hif_sdio_device *pdev,
+			    struct MBOX_IRQ_PROC_REGISTERS *irq_proc,
+			    struct MBOX_IRQ_ENABLE_REGISTERS *irq_en,
+			    struct MBOX_COUNTER_REGISTERS *mbox_regs);
+
+int hif_get_send_address(struct hif_sdio_device *pdev,
+			 uint8_t pipe, uint32_t *addr);
+
+QDF_STATUS hif_dev_alloc_and_prepare_rx_packets(struct hif_sdio_device *pdev,
+						uint32_t look_aheads[],
+						int messages,
+						HTC_PACKET_QUEUE *queue);
+
+QDF_STATUS hif_dev_process_trailer(struct hif_sdio_device *pdev,
+				   uint8_t *buffer, int length,
+				   uint32_t *next_look_aheads,
+				   int *num_look_aheads,
+				   HTC_ENDPOINT_ID from_endpoint);
+
+void hif_dev_free_recv_pkt_queue(HTC_PACKET_QUEUE *recv_pkt_queue);
+
+QDF_STATUS hif_dev_process_recv_header(struct hif_sdio_device *pdev,
+				       HTC_PACKET *packet,
+				       uint32_t *next_look_aheads,
+				       int *num_look_aheads);
+#endif /* __TRANSFER_H__ */