static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter,
					u8 *payload, u32 pkt_len, u8 port,
					u32 next_pkt_len)
{
	struct sdio_mmc_card *card = adapter->card;
	int ret = 0;
	s32 f_send_aggr_buf = 0;
	s32 f_send_cur_buf = 0;
	s32 f_precopy_cur_buf = 0;
	s32 f_postcopy_cur_buf = 0;

	if ((!card->mpa_tx.enabled) || (port == CTRL_PORT)) {
		dev_dbg(adapter->dev, "info: %s: tx aggregation disabled\n",
			__func__);

		f_send_cur_buf = 1;
		goto tx_curr_single;
	}

	if (next_pkt_len) {
		
		dev_dbg(adapter->dev, "info: %s: more packets in queue.\n",
			__func__);

		if (MP_TX_AGGR_IN_PROGRESS(card)) {
			if (!MP_TX_AGGR_PORT_LIMIT_REACHED(card) &&
			    MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) {
				f_precopy_cur_buf = 1;

				if (!(card->mp_wr_bitmap &
				      (1 << card->curr_wr_port)) ||
				    !MP_TX_AGGR_BUF_HAS_ROOM(
					    card, pkt_len + next_pkt_len))
					f_send_aggr_buf = 1;
			} else {
				
				f_send_aggr_buf = 1;

				if (MP_TX_AGGR_PORT_LIMIT_REACHED(card) ||
				    !(card->mp_wr_bitmap &
				      (1 << card->curr_wr_port)))
					f_send_cur_buf = 1;
				else
					f_postcopy_cur_buf = 1;
			}
		} else {
			if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len) &&
			    (card->mp_wr_bitmap & (1 << card->curr_wr_port)))
				f_precopy_cur_buf = 1;
			else
				f_send_cur_buf = 1;
		}
	} else {
		
		dev_dbg(adapter->dev, "info: %s: Last packet in Tx Queue.\n",
			__func__);

		if (MP_TX_AGGR_IN_PROGRESS(card)) {
			
			f_send_aggr_buf = 1;

			if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len))
				f_precopy_cur_buf = 1;
			else
				
				f_send_cur_buf = 1;
		} else {
			f_send_cur_buf = 1;
		}
	}

	if (f_precopy_cur_buf) {
		dev_dbg(adapter->dev, "data: %s: precopy current buffer\n",
			__func__);
		MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);

		if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) ||
		    MP_TX_AGGR_PORT_LIMIT_REACHED(card))
			
			f_send_aggr_buf = 1;
	}

	if (f_send_aggr_buf) {
		dev_dbg(adapter->dev, "data: %s: send aggr buffer: %d %d\n",
			__func__,
				card->mpa_tx.start_port, card->mpa_tx.ports);
		ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf,
						 card->mpa_tx.buf_len,
						 (adapter->ioport | 0x1000 |
						 (card->mpa_tx.ports << 4)) +
						  card->mpa_tx.start_port);

		MP_TX_AGGR_BUF_RESET(card);
	}

tx_curr_single:
	if (f_send_cur_buf) {
		dev_dbg(adapter->dev, "data: %s: send current buffer %d\n",
			__func__, port);
		ret = mwifiex_write_data_to_card(adapter, payload, pkt_len,
						 adapter->ioport + port);
	}

	if (f_postcopy_cur_buf) {
		dev_dbg(adapter->dev, "data: %s: postcopy current buffer\n",
			__func__);
		MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port);
	}

	return ret;
}
/**
 *  @brief This function sends data to the card in SDIO aggregated mode.
 *
 *  @param pmadapter A pointer to mlan_adapter structure
 *  @param mbuf      A pointer to the SDIO data/cmd buffer
 *  @param port	     current port for aggregation
 *  @param next_pkt_len Length of next packet used for multiport aggregation
 *  @return 	     MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
 */
static mlan_status
wlan_host_to_card_mp_aggr(mlan_adapter * pmadapter, mlan_buffer * mbuf,
			  t_u8 port, t_u32 next_pkt_len)
{
	mlan_status ret = MLAN_STATUS_SUCCESS;
	t_s32 f_send_aggr_buf = 0;
	t_s32 f_send_cur_buf = 0;
	t_s32 f_precopy_cur_buf = 0;
	t_s32 f_postcopy_cur_buf = 0;
	t_u32 cmd53_port = 0;
	mlan_buffer mbuf_aggr;

	ENTER();

	PRINTM(MIF_D, "host_2_card_mp_aggr: next_pkt_len: %d curr_port:%d\n",
	       next_pkt_len, port);

	if (!pmadapter->mpa_tx.enabled) {
		PRINTM(MINFO,
		       "host_2_card_mp_aggr: tx aggregation disabled !\n");

		f_send_cur_buf = 1;
		goto tx_curr_single;
	}

	if (next_pkt_len) {
		/* More pkt in TX queue */
		PRINTM(MINFO, "host_2_card_mp_aggr: More packets in Queue.\n");

		if (MP_TX_AGGR_IN_PROGRESS(pmadapter)) {
			if (!MP_TX_AGGR_PORT_LIMIT_REACHED(pmadapter) &&
			    MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
						    mbuf->data_len)) {
				f_precopy_cur_buf = 1;

				if (!
				    (pmadapter->
				     mp_wr_bitmap & (1 << pmadapter->
						     curr_wr_port)) ||
				    !MP_TX_AGGR_BUF_HAS_ROOM(pmadapter, mbuf,
							     mbuf->data_len +
							     next_pkt_len)) {
					f_send_aggr_buf = 1;
				}
			} else {
				/* No room in Aggr buf, send it */
				f_send_aggr_buf = 1;

				if (MP_TX_AGGR_PORT_LIMIT_REACHED(pmadapter) ||
				    !(pmadapter->
				      mp_wr_bitmap & (1 << pmadapter->
						      curr_wr_port))) {
					f_send_cur_buf = 1;
				} else {
					f_postcopy_cur_buf = 1;
				}
			}
		} else {
			if (MP_TX_AGGR_BUF_HAS_ROOM
			    (pmadapter, mbuf, mbuf->data_len) &&
			    (pmadapter->
			     mp_wr_bitmap & (1 << pmadapter->curr_wr_port)))
				f_precopy_cur_buf = 1;
			else
				f_send_cur_buf = 1;
		}
	} else {
		/* Last pkt in TX queue */
		PRINTM(MINFO,
		       "host_2_card_mp_aggr: Last packet in Tx Queue.\n");

		if (MP_TX_AGGR_IN_PROGRESS(pmadapter)) {
			/* some packs in Aggr buf already */
			f_send_aggr_buf = 1;

			if (MP_TX_AGGR_BUF_HAS_ROOM
			    (pmadapter, mbuf, mbuf->data_len)) {
				f_precopy_cur_buf = 1;
			} else {
				/* No room in Aggr buf, send it */
				f_send_cur_buf = 1;
			}
		} else {
			f_send_cur_buf = 1;
		}
	}

	if (f_precopy_cur_buf) {
		PRINTM(MINFO, "host_2_card_mp_aggr: Precopy current buffer\n");
		MP_TX_AGGR_BUF_PUT(pmadapter, mbuf, port);

		if (MP_TX_AGGR_PKT_LIMIT_REACHED(pmadapter) ||
		    MP_TX_AGGR_PORT_LIMIT_REACHED(pmadapter)) {
			PRINTM(MIF_D,
			       "host_2_card_mp_aggr: Aggregation Pkt limit reached\n");
			/* No more pkts allowed in Aggr buf, send it */
			f_send_aggr_buf = 1;
		}
	}

	if (f_send_aggr_buf) {
		PRINTM(MINFO, "host_2_card_mp_aggr: Send aggregation buffer."
		       "%d %d\n", pmadapter->mpa_tx.start_port,
		       pmadapter->mpa_tx.ports);

		memset(pmadapter, &mbuf_aggr, 0, sizeof(mlan_buffer));

		mbuf_aggr.pbuf = (t_u8 *) pmadapter->mpa_tx.buf;
		mbuf_aggr.data_len = pmadapter->mpa_tx.buf_len;
		cmd53_port = (pmadapter->ioport | SDIO_MPA_ADDR_BASE |
			      (pmadapter->mpa_tx.ports << 4)) +
			pmadapter->mpa_tx.start_port;
		ret = wlan_write_data_sync(pmadapter, &mbuf_aggr, cmd53_port);
		MP_TX_AGGR_BUF_RESET(pmadapter);
	}

tx_curr_single:
	if (f_send_cur_buf) {
		PRINTM(MINFO, "host_2_card_mp_aggr: writing to port #%d\n",
		       port);
		ret = wlan_write_data_sync(pmadapter, mbuf,
					   pmadapter->ioport + port);
	}
	if (f_postcopy_cur_buf) {
		PRINTM(MINFO, "host_2_card_mp_aggr: Postcopy current buffer\n");
		MP_TX_AGGR_BUF_PUT(pmadapter, mbuf, port);
	}

	LEAVE();
	return ret;
}