int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode)
{
	int ret = BCME_OK;

	dhd_os_tcpacklock(dhdp);

	if (dhdp->tcpack_sup_mode == mode) {
		DHD_ERROR(("%s %d: already set to %d\n", __FUNCTION__, __LINE__, mode));
		goto exit;
	}

	if (mode >= TCPACK_SUP_LAST_MODE ||
#ifndef BCMSDIO
		mode == TCPACK_SUP_DELAYTX ||
#endif
		FALSE) {
		DHD_ERROR(("%s %d: Invalid mode %d\n", __FUNCTION__, __LINE__, mode));
		ret = BCME_BADARG;
		goto exit;
	}

	DHD_TRACE(("%s: %d -> %d\n",
		__FUNCTION__, dhdp->tcpack_sup_mode, mode));

	/* Old tcpack_sup_mode is TCPACK_SUP_DELAYTX */
	if (dhdp->tcpack_sup_mode == TCPACK_SUP_DELAYTX) {
		tcpack_sup_module_t *tcpack_sup_mod = dhdp->tcpack_sup_module;
		/* We won't need tdata_psh_info pool and tcpddata_info_tbl anymore */
		_tdata_psh_info_pool_deinit(dhdp, tcpack_sup_mod);
		tcpack_sup_mod->tcpdata_info_cnt = 0;
		bzero(tcpack_sup_mod->tcpdata_info_tbl,
			sizeof(tcpdata_info_t) * TCPDATA_INFO_MAXNUM);
		/* For half duplex bus interface, tx precedes rx by default */
		if (dhdp->bus)
			dhd_bus_set_dotxinrx(dhdp->bus, TRUE);
	}

	dhdp->tcpack_sup_mode = mode;

	if (mode == TCPACK_SUP_OFF) {
		ASSERT(dhdp->tcpack_sup_module != NULL);
		MFREE(dhdp->osh, dhdp->tcpack_sup_module, sizeof(tcpack_sup_module_t));
		dhdp->tcpack_sup_module = NULL;
		goto exit;
	}

	if (dhdp->tcpack_sup_module == NULL) {
		tcpack_sup_module_t *tcpack_sup_mod =
			MALLOC(dhdp->osh, sizeof(tcpack_sup_module_t));
		if (tcpack_sup_mod == NULL) {
			DHD_ERROR(("%s %d: No MEM\n", __FUNCTION__, __LINE__));
			dhdp->tcpack_sup_mode = TCPACK_SUP_OFF;
			ret = BCME_NOMEM;
			goto exit;
		}
		bzero(tcpack_sup_mod, sizeof(tcpack_sup_module_t));
		dhdp->tcpack_sup_module = tcpack_sup_mod;
	}

	if (mode == TCPACK_SUP_DELAYTX) {
		ret = _tdata_psh_info_pool_init(dhdp, dhdp->tcpack_sup_module);
		if (ret != BCME_OK)
			DHD_ERROR(("%s %d: pool init fail with %d\n", __FUNCTION__, __LINE__, ret));
		else if (dhdp->bus)
			dhd_bus_set_dotxinrx(dhdp->bus, FALSE);
	}

exit:
	dhd_os_tcpackunlock(dhdp);
	return ret;
}
int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode)
{
	int ret = BCME_OK;
	unsigned long flags;

	flags = dhd_os_tcpacklock(dhdp);

	if (dhdp->tcpack_sup_mode == mode) {
		DHD_ERROR(("%s %d: already set to %d\n", __FUNCTION__, __LINE__, mode));
		goto exit;
	}

	if (mode >= TCPACK_SUP_LAST_MODE ||
#ifndef BCMSDIO
		mode == TCPACK_SUP_DELAYTX ||
#endif /* !BCMSDIO */
		FALSE) {
		DHD_ERROR(("%s %d: Invalid mode %d\n", __FUNCTION__, __LINE__, mode));
		ret = BCME_BADARG;
		goto exit;
	}

	DHD_TRACE(("%s: %d -> %d\n",
		__FUNCTION__, dhdp->tcpack_sup_mode, mode));

#ifdef BCMSDIO
	/* Old tcpack_sup_mode is TCPACK_SUP_DELAYTX */
	if (dhdp->tcpack_sup_mode == TCPACK_SUP_DELAYTX) {
		tcpack_sup_module_t *tcpack_sup_mod = dhdp->tcpack_sup_module;
		/* We won't need tdata_psh_info pool and tcpddata_info_tbl anymore */
		_tdata_psh_info_pool_deinit(dhdp, tcpack_sup_mod);
		tcpack_sup_mod->tcpdata_info_cnt = 0;
		bzero(tcpack_sup_mod->tcpdata_info_tbl,
			sizeof(tcpdata_info_t) * TCPDATA_INFO_MAXNUM);
		/* For half duplex bus interface, tx precedes rx by default */
		if (dhdp->bus)
			dhd_bus_set_dotxinrx(dhdp->bus, TRUE);
	}
#endif
	dhdp->tcpack_sup_mode = mode;

	if (mode == TCPACK_SUP_OFF) {
		ASSERT(dhdp->tcpack_sup_module != NULL);
		/* Clean up timer/data structure for any remaining/pending packet or timer. */
		dhd_tcpack_info_tbl_clean(dhdp);
		MFREE(dhdp->osh, dhdp->tcpack_sup_module, sizeof(tcpack_sup_module_t));
		dhdp->tcpack_sup_module = NULL;
		goto exit;
	}

	if (dhdp->tcpack_sup_module == NULL) {
		tcpack_sup_module_t *tcpack_sup_mod =
			MALLOC(dhdp->osh, sizeof(tcpack_sup_module_t));
		if (tcpack_sup_mod == NULL) {
			DHD_ERROR(("%s %d: No MEM\n", __FUNCTION__, __LINE__));
			dhdp->tcpack_sup_mode = TCPACK_SUP_OFF;
			ret = BCME_NOMEM;
			goto exit;
		}
		bzero(tcpack_sup_mod, sizeof(tcpack_sup_module_t));
		dhdp->tcpack_sup_module = tcpack_sup_mod;
	}

#ifdef BCMSDIO
	if (mode == TCPACK_SUP_DELAYTX) {
		ret = _tdata_psh_info_pool_init(dhdp, dhdp->tcpack_sup_module);
		if (ret != BCME_OK)
			DHD_ERROR(("%s %d: pool init fail with %d\n", __FUNCTION__, __LINE__, ret));
		else if (dhdp->bus)
			dhd_bus_set_dotxinrx(dhdp->bus, FALSE);
	}
#endif /* BCMSDIO */

	if (mode == TCPACK_SUP_HOLD) {
		int i;
		tcpack_sup_module_t *tcpack_sup_mod =
			(tcpack_sup_module_t *)dhdp->tcpack_sup_module;
		dhdp->tcpack_sup_ratio = TCPACK_SUPP_RATIO;
		dhdp->tcpack_sup_delay = TCPACK_DELAY_TIME;
		for (i = 0; i < TCPACK_INFO_MAXNUM; i++)
		{
			tcpack_sup_mod->tcpack_info_tbl[i].dhdp = dhdp;
			init_timer(&tcpack_sup_mod->tcpack_info_tbl[i].timer);
			tcpack_sup_mod->tcpack_info_tbl[i].timer.data =
				(ulong)&tcpack_sup_mod->tcpack_info_tbl[i];
			tcpack_sup_mod->tcpack_info_tbl[i].timer.function = dhd_tcpack_send;
		}
	}

exit:
	dhd_os_tcpackunlock(dhdp, flags);
	return ret;
}