/******************************************************************************
 *
 * Copyright(c) 2019 Realtek Corporation.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 *****************************************************************************/
#define _HAL_RX_C_
#include "hal_headers.h"

void rtw_hal_cfg_rxhci(void *hal, u8 en)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;

	PHL_TRACE(COMP_PHL_DBG, _PHL_DEBUG_, "%s : enable %d.\n", __func__, en);

	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_mac_cfg_rxhci(hal_info, en))
		PHL_ERR("%s failure \n", __func__);
}

enum rtw_hal_status
rtw_hal_set_rxfltr_opt_by_mode(void *hal, u8 band, enum rtw_rx_fltr_opt_mode mode)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct rtw_hal_com_t *hal_com = hal_info->hal_com;
	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
	enum rtw_rx_fltr_opt_mode set_mode = -1;

	PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "%s : band(%d), mode(%d)\n",
		__func__, band, mode);

	/* Note: @hal_com->band[band].rx_fltr_opt_mode is used to recored any mode other than
	 * sniffer mode, it effectively records the mode before entering monitor
	 * mode and the subsequent modes set after entering monitor mode.
	 */
	if ((mode == RX_FLTR_OPT_MODE_SNIFFER && hal_info->monitor_mode[band]) ||
	    (mode == RX_FLTR_OPT_MODE_RESTORE && !hal_info->monitor_mode[band]))
		return RTW_HAL_STATUS_FAILURE;

	if (hal_info->monitor_mode[band] && mode != RX_FLTR_OPT_MODE_RESTORE) {
		hal_com->band[band].rx_fltr_opt_mode = mode;
		return RTW_HAL_STATUS_SUCCESS;
	}

	set_mode = (mode == RX_FLTR_OPT_MODE_RESTORE) ?
		hal_com->band[band].rx_fltr_opt_mode : mode;

	hstatus = rtw_hal_mac_set_rxfltr_opt_by_mode(hal_com, band, set_mode);
	if (hstatus != RTW_HAL_STATUS_SUCCESS)
		return hstatus;

	hal_info->monitor_mode[band] = (mode == RX_FLTR_OPT_MODE_SNIFFER);

	/* Record @hal_com->band[band].rx_fltr_opt_mode only when the mode is not monitor and
	 * restore, otherwise, it is kept intact.
	 */
	if (mode != RX_FLTR_OPT_MODE_SNIFFER &&
	    mode != RX_FLTR_OPT_MODE_RESTORE)
		hal_com->band[band].rx_fltr_opt_mode = mode;

	return RTW_HAL_STATUS_SUCCESS;
}

enum rtw_rx_fltr_opt_mode rtw_hal_get_rxfltr_opt_mode(void *hal, u8 band)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct rtw_hal_com_t *hal_com = hal_info->hal_com;

	return (hal_info->monitor_mode[band]) ? RX_FLTR_OPT_MODE_SNIFFER :
		hal_com->band[band].rx_fltr_opt_mode;
}

enum rtw_hal_status rtw_hal_scan_set_rxfltr_by_mode(void *hinfo,
	enum phl_phy_idx phy_idx, bool off_channel, u8 *mode)
{
	enum rtw_hal_status hal_status = RTW_HAL_STATUS_SUCCESS;

	if (off_channel) {
		/* backup rx filter opt mode */
		*mode = rtw_hal_get_rxfltr_opt_mode(hinfo, phy_idx);
		hal_status = rtw_hal_set_rxfltr_opt_by_mode(hinfo,
			phy_idx, RX_FLTR_OPT_MODE_SCAN);
	} else {
		/* restore rx filter opt mode */
		hal_status = rtw_hal_set_rxfltr_opt_by_mode(hinfo,
			phy_idx, *mode);
	}
	return hal_status;
}

enum rtw_hal_status
rtw_hal_enter_mon_mode(void *hinfo, enum phl_phy_idx phy_idx)
{
	rtw_hal_bb_snif_mode_ctrl((struct hal_info_t *)hinfo, true);

	return rtw_hal_set_rxfltr_opt_by_mode(hinfo, phy_idx, RX_FLTR_OPT_MODE_SNIFFER);
}

enum rtw_hal_status
rtw_hal_leave_mon_mode(void *hinfo, enum phl_phy_idx phy_idx)
{
	rtw_hal_bb_snif_mode_ctrl((struct hal_info_t *)hinfo, false);

	return rtw_hal_set_rxfltr_opt_by_mode(hinfo, phy_idx, RX_FLTR_OPT_MODE_RESTORE);
}

enum rtw_hal_status rtw_hal_acpt_crc_err_pkt(void *hal, u8 band, u8 enable)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct rtw_hal_com_t *hal_com = hal_info->hal_com;


	return rtw_hal_mac_set_rxfltr_acpt_crc_err(hal_com, band, enable);
}

enum rtw_hal_status rtw_hal_cfg_ppdu_sts_fltr(void *hal, struct rtw_phl_com_t *phl_com, u8 band, u8 fltr)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct rtw_hal_com_t *hal_com = hal_info->hal_com;
	enum rtw_hal_status hal_sts;
	struct hal_ppdu_sts_cfg cfg;

	hal_com->band[band].ppdu_sts_filter = fltr;

	cfg.appen_info = hal_com->band[band].ppdu_sts_appen_info;
	cfg.band_idx = band;
	cfg.filter = hal_com->band[band].ppdu_sts_filter;
	cfg.ppdu_stat_en = phl_com->ppdu_sts_info.en_ppdu_sts[band];
	cfg.todcpu = false;
	cfg.towcpu = false;


	hal_sts = rtw_hal_mac_ppdu_stat_cfg(hal_info, &cfg);

	return hal_sts;
}

enum rtw_hal_status rtw_hal_set_rxfltr_mpdu_size(void *hal, u8 band, u16 size)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct rtw_hal_com_t *hal_com = hal_info->hal_com;


	return rtw_hal_mac_set_rxfltr_mpdu_size(hal_com, band, size);
}

static const char *_hal_rxfltr_type_str(u8 type)
{
	switch (type) {
	case RTW_PHL_PKT_TYPE_CTRL:
		return "CTRL";
	case RTW_PHL_PKT_TYPE_MGNT:
		return "MGNT";
	case RTW_PHL_PKT_TYPE_DATA:
		return "DATA";
	default:
		return "UNKNOWN";
	}
}

static const char *_hal_rxfltr_stype_str_ctrl(u8 stype)
{
	switch (stype) {
	case RXFLTR_STYPE_CTRL_RSVD_0000:
		return "RSVD_0000";
	case RXFLTR_STYPE_CTRL_RSVD_0001:
		return "RSVD_0001";
	case RXFLTR_STYPE_TRIGGER:
		return "TRIGGER";
	case RXFLTR_STYPE_TACK:
		return "TACK";
	case RXFLTR_STYPE_BFRP:
		return "BFRP";
	case RXFLTR_STYPE_VHT_HE_NDPA:
		return "VHT_HE_NDPA";
	case RXFLTR_STYPE_CFE:
		return "CFE";
	case RXFLTR_STYPE_CW:
		return "CW";
	case RXFLTR_STYPE_BAR:
		return "BAR";
	case RXFLTR_STYPE_BA:
		return "BA";
	case RXFLTR_STYPE_PS_POLL:
		return "PS_POLL";
	case RXFLTR_STYPE_RTS:
		return "RTS";
	case RXFLTR_STYPE_CTS:
		return "CTS";
	case RXFLTR_STYPE_ACK:
		return "ACK";
	case RXFLTR_STYPE_CF_END:
		return "CF_END";
	case RXFLTR_STYPE_CF_END_ACK:
		return "CF_END_ACK";
	case RXFLTR_STYPE_CTRL_MAX:
	default:
		return "UNKNOWN";
	}
}

static const char *_hal_rxfltr_stype_str_mgnt(u8 stype)
{
	switch (stype) {
	case RXFLTR_STYPE_ASSOC_REQ:
		return "ASSOC_REQ";
	case RXFLTR_STYPE_ASSOC_RSP:
		return "ASSOC_RSP";
	case RXFLTR_STYPE_REASSOC_REQ:
		return "REASSOC_REQ";
	case RXFLTR_STYPE_REASSOC_RSP:
		return "REASSOC_RSP";
	case RXFLTR_STYPE_PROBE_REQ:
		return "PROBE_REQ";
	case RXFLTR_STYPE_PROBE_RSP:
		return "PROBE_RSP";
	case RXFLTR_STYPE_TIMING_ADV:
		return "TIMING_ADV";
	case RXFLTR_STYPE_MGNT_RSVD_0111:
		return "RSVD_0111";
	case RXFLTR_STYPE_BEACON:
		return "BEACON";
	case RXFLTR_STYPE_ATIM:
		return "ATIM";
	case RXFLTR_STYPE_DIS_ASSOC:
		return "DIS_ASSOC";
	case RXFLTR_STYPE_AUTH:
		return "AUTH";
	case RXFLTR_STYPE_DEAUTH:
		return "DAUTH";
	case RXFLTR_STYPE_ACTION:
		return "ACTION";
	case RXFLTR_STYPE_ACTION_NO_ACK:
		return "ACTION_NO_ACK";
	case RXFLTR_STYPE_MGNT_RSVD_1111:
		return "MGNT_RSVD_1111";
	case RXFLTR_STYPE_MGNT_MAX:
	default:
		return "UNKNOWN";
	}
}

static const char *_hal_rxfltr_stype_str_data(u8 stype)
{
	switch (stype) {
	case RXFLTR_STYPE_DATA_DATA:
		return "DATA_DATA";
	case RXFLTR_STYPE_DATA_CF_ACK:
		return "DATA_CF_ACK";
	case RXFLTR_STYPE_DATA_CF_POLL:
		return "DATA_CF_POLL";
	case RXFLTR_STYPE_DATA_CF_ACK_POLL:
		return "DATA_CF_ACK_POLL";
	case RXFLTR_STYPE_NULL_DATA:
		return "NULL_DATA";
	case RXFLTR_STYPE_CF_ACK:
		return "CF_ACK";
	case RXFLTR_STYPE_CF_POLL:
		return "CF_POLL";
	case RXFLTR_STYPE_CF_ACK_POLL:
		return "CF_ACK_POLL";
	case RXFLTR_STYPE_QOS_DATA:
		return "QOS_DATA";
	case RXFLTR_STYPE_QOS_DATA_CF_ACK:
		return "QOS_DATA_CF_ACK";
	case RXFLTR_STYPE_QOS_DATA_CF_POLL:
		return "QOS_DATA_CF_POLL";
	case RXFLTR_STYPE_QOS_DATA_CF_ACK_POLL:
		return "QOS_DATA_CF_ACK_POLL";
	case RXFLTR_STYPE_QOS_NULL_DATA:
		return "QOS_NULL_DATA";
	case RXFLTR_STYPE_DATA_RSVD_1101:
		return "RSVD_1101";
	case RXFLTR_STYPE_QOS_CF_POLL:
		return "QOS_CF_POLL";
	case RXFLTR_STYPE_QOS_CF_ACK_POLL:
		return "QOS_CF_ACK_POLL";
	case RXFLTR_STYPE_DATA_MAX:
	default:
		return "UNKNOWN";
	}
}

static const char *_hal_rxfltr_target_str(u8 target)
{
	switch (target) {
	case RXFLTR_TARGET_DROP:
		return "DROP";
	case RXFLTR_TARGET_TO_HOST:
		return "TO_HOST";
	case RXFLTR_TARGET_TO_WLCPU:
		return "TO_WLCPU";
	case RXFLTR_TARGET_MAX:
	default:
		return "UNKNOWN";
	}
}

enum rtw_hal_status rtw_hal_set_rxfltr_by_type(void *hal, u8 band, enum rtw_packet_type type,
					       enum rtw_rxfltr_target target)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	enum rtw_hal_status hstats = RTW_HAL_STATUS_FAILURE;

	hstats = rtw_hal_mac_set_rxfltr_by_type(hal_info->hal_com, band, type, target);

	if (RTW_HAL_STATUS_SUCCESS == hstats)
		PHL_TRACE(COMP_PHL_RECV, _PHL_INFO_, "Set band %u rxfltr type %s target %s\n",
			band, _hal_rxfltr_type_str(type), _hal_rxfltr_target_str(target));
	else
		PHL_TRACE(COMP_PHL_RECV, _PHL_ERR_, "%s : set band %u type %s target %s fail, status(%u)\n",
			__func__, band, _hal_rxfltr_type_str(type), _hal_rxfltr_target_str(target), hstats);

	return hstats;
}

enum rtw_hal_status
rtw_hal_set_rxfltr_by_stype_ctrl(void *hal, u8 band, struct rxfltr_cap_to_set_ctrl *cap_ctrl)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct rtw_hal_com_t *hal_com = hal_info->hal_com;
	enum rtw_hal_status hstats = RTW_HAL_STATUS_SUCCESS;
	enum rtw_packet_type type = RTW_PHL_PKT_TYPE_CTRL;
	enum rtw_rxfltr_target target = RXFLTR_TARGET_MAX, trgt_chk = RXFLTR_TARGET_MAX;
	bool type_set = true, stype_set = false;
	u8 i = 0;

	for (i = 0; i < RXFLTR_STYPE_CTRL_MAX; i++) {
		if (cap_ctrl->stype[i].set == false) {
			type_set = false;
			break;
		}
		if ((trgt_chk != RXFLTR_TARGET_MAX) && (cap_ctrl->stype[i].target != trgt_chk)) {
			type_set = false;
			break;
		}

		trgt_chk = cap_ctrl->stype[i].target;
	}

	if (type_set == true)
		return rtw_hal_set_rxfltr_by_type(hal, band, type, trgt_chk);

	for (i = 0; i < RXFLTR_STYPE_CTRL_MAX; i++) {
		stype_set = cap_ctrl->stype[i].set;
		target = cap_ctrl->stype[i].target;
		if (stype_set == true) {
			hstats = rtw_hal_mac_set_rxfltr_by_subtype(hal_com, band, type, i, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats) {
				PHL_TRACE(COMP_PHL_RECV, _PHL_ERR_, "%s: set band %u type %s sub-type %s target %s fail, status(%u)\n",
					__func__, band, _hal_rxfltr_type_str(type), _hal_rxfltr_stype_str_ctrl(i),
					_hal_rxfltr_target_str(target), hstats);
				break;
			}

			PHL_TRACE(COMP_PHL_RECV, _PHL_INFO_, "Set band %u rxfltr type %s sub-type %s target %s\n",
				band, _hal_rxfltr_type_str(type), _hal_rxfltr_stype_str_ctrl(i), _hal_rxfltr_target_str(target));
		}
	}

	return hstats;
}

enum rtw_hal_status
rtw_hal_set_rxfltr_by_stype_mgnt(void *hal, u8 band, struct rxfltr_cap_to_set_mgnt *cap_mgnt)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct rtw_hal_com_t *hal_com = hal_info->hal_com;
	enum rtw_hal_status hstats = RTW_HAL_STATUS_SUCCESS;
	enum rtw_packet_type type = RTW_PHL_PKT_TYPE_MGNT;
	enum rtw_rxfltr_target target = RXFLTR_TARGET_MAX, trgt_chk = RXFLTR_TARGET_MAX;
	bool type_set = true, stype_set = false;
	u8 i = 0;

	for (i = 0; i < RXFLTR_STYPE_MGNT_MAX; i++) {
		if (cap_mgnt->stype[i].set == false) {
			type_set = false;
			break;
		}
		if ((trgt_chk != RXFLTR_TARGET_MAX) && (cap_mgnt->stype[i].target != trgt_chk)) {
			type_set = false;
			break;
		}

		trgt_chk = cap_mgnt->stype[i].target;
	}

	if (type_set == true)
		return rtw_hal_set_rxfltr_by_type(hal, band, type, trgt_chk);

	for (i = 0; i < RXFLTR_STYPE_MGNT_MAX; i ++) {
		stype_set = cap_mgnt->stype[i].set;
		target = cap_mgnt->stype[i].target;
		if (stype_set == true) {
			hstats = rtw_hal_mac_set_rxfltr_by_subtype(hal_com, band, type, i, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats) {
				PHL_TRACE(COMP_PHL_RECV, _PHL_ERR_, "%s: set band %u type %s sub-type %s target %s fail, status(%u)\n",
					__func__, band, _hal_rxfltr_type_str(type), _hal_rxfltr_stype_str_mgnt(i),
					_hal_rxfltr_target_str(target), hstats);
				break;
			}

			PHL_TRACE(COMP_PHL_RECV, _PHL_INFO_, "Set band %u rxfltr type %s sub-type %s target %s\n",
				band, _hal_rxfltr_type_str(type), _hal_rxfltr_stype_str_mgnt(i), _hal_rxfltr_target_str(target));
		}
	}

	return hstats;
}

enum rtw_hal_status
rtw_hal_set_rxfltr_by_stype_data(void *hal, u8 band, struct rxfltr_cap_to_set_data *cap_data)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct rtw_hal_com_t *hal_com = hal_info->hal_com;
	enum rtw_hal_status hstats = RTW_HAL_STATUS_SUCCESS;
	enum rtw_packet_type type = RTW_PHL_PKT_TYPE_DATA;
	enum rtw_rxfltr_target target = RXFLTR_TARGET_MAX, trgt_chk = RXFLTR_TARGET_MAX;
	bool type_set = true, stype_set = false;
	u8 i = 0;

	for (i = 0; i < RXFLTR_STYPE_DATA_MAX; i++) {
		if (cap_data->stype[i].set == false) {
			type_set = false;
			break;
		}
		if ((trgt_chk != RXFLTR_TARGET_MAX) && (cap_data->stype[i].target != trgt_chk)) {
			type_set = false;
			break;
		}

		trgt_chk = cap_data->stype[i].target;
	}

	if (type_set == true)
		return rtw_hal_set_rxfltr_by_type(hal, band, type, trgt_chk);

	for (i = 0; i < RXFLTR_STYPE_DATA_MAX; i++) {
		stype_set = cap_data->stype[i].set;
		target = cap_data->stype[i].target;
		if (stype_set == true) {
			hstats = rtw_hal_mac_set_rxfltr_by_subtype(hal_com, band, type, i, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats) {
				PHL_TRACE(COMP_PHL_RECV, _PHL_ERR_, "%s: set band %u type %s sub-type %s target %s fail, status(%u)\n",
					__func__, band, _hal_rxfltr_type_str(type), _hal_rxfltr_stype_str_data(i),
					_hal_rxfltr_target_str(target), hstats);
				break;
			}

			PHL_TRACE(COMP_PHL_RECV, _PHL_INFO_, "Set band %u rxfltr type %s sub-type %s target %s\n",
				band, _hal_rxfltr_type_str(type), _hal_rxfltr_stype_str_data(i), _hal_rxfltr_target_str(target));
		}
	}

	return hstats;
}

enum rtw_hal_status
rtw_hal_set_rxfltr_by_stype_all(void *hal, u8 band, struct rxfltr_type_cap_to_set *cap_all)
{
	enum rtw_hal_status hstats = RTW_HAL_STATUS_FAILURE;

	do {
		hstats = rtw_hal_set_rxfltr_by_stype_ctrl(hal, band, &(cap_all->rxfltr_ctrl));
		if (RTW_HAL_STATUS_SUCCESS != hstats)
			break;

		hstats = rtw_hal_set_rxfltr_by_stype_mgnt(hal, band, &(cap_all->rxfltr_mgnt));
		if (RTW_HAL_STATUS_SUCCESS != hstats)
			break;

		hstats = rtw_hal_set_rxfltr_by_stype_data(hal, band, &(cap_all->rxfltr_data));
		if (RTW_HAL_STATUS_SUCCESS != hstats)
			break;
	} while (0);

	return hstats;
}

enum rtw_hal_status rtw_hal_set_rxfltr_type_by_mode(void *hal, u8 band, enum rtw_rxfltr_type_mode mode)
{
	enum rtw_hal_status hstats = RTW_HAL_STATUS_FAILURE;
	struct rxfltr_cap_to_set_ctrl cap_ctrl = {0};
	enum rtw_packet_type type = RTW_PHL_PKT_TYPE_MAX;
	enum rtw_rxfltr_target target = RXFLTR_TARGET_MAX;

	if (band >= MAX_BAND_NUM)
		return RTW_HAL_STATUS_FAILURE;

	if (mode >= RX_FLTR_TYPE_MODE_MAX)
		return RTW_HAL_STATUS_FAILURE;

	switch (mode) {
	case RX_FLTR_TYPE_MODE_HAL_INIT:
		do {
			type = RTW_PHL_PKT_TYPE_CTRL;
			target = RXFLTR_TARGET_DROP;
			hstats = rtw_hal_set_rxfltr_by_type(hal, band, type, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;

			type = RTW_PHL_PKT_TYPE_MGNT;
			target = RXFLTR_TARGET_TO_HOST;
			hstats = rtw_hal_set_rxfltr_by_type(hal, band, type, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;

			type = RTW_PHL_PKT_TYPE_DATA;
			target = RXFLTR_TARGET_TO_HOST;
			hstats = rtw_hal_set_rxfltr_by_type(hal, band, type, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;
		} while (0);
		break;
	case RX_FLTR_TYPE_MODE_STA_WOW_INIT_PRE:
		do {
			type = RTW_PHL_PKT_TYPE_CTRL;
			target = RXFLTR_TARGET_DROP;
			hstats = rtw_hal_set_rxfltr_by_type(hal, band, type, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;

			type = RTW_PHL_PKT_TYPE_MGNT;
			target = RXFLTR_TARGET_DROP;
			hstats = rtw_hal_set_rxfltr_by_type(hal, band, type, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;

			type = RTW_PHL_PKT_TYPE_DATA;
			target = RXFLTR_TARGET_DROP;
			hstats = rtw_hal_set_rxfltr_by_type(hal, band, type, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;
		} while (0);
		break;
	case RX_FLTR_TYPE_MODE_STA_WOW_INIT_POST:
		do {
			cap_ctrl.stype[RXFLTR_STYPE_VHT_HE_NDPA].set = true;
			cap_ctrl.stype[RXFLTR_STYPE_VHT_HE_NDPA].target = RXFLTR_TARGET_TO_HOST;
			cap_ctrl.stype[RXFLTR_STYPE_BAR].set = true;
			cap_ctrl.stype[RXFLTR_STYPE_BAR].target = RXFLTR_TARGET_TO_HOST;
			hstats = rtw_hal_set_rxfltr_by_stype_ctrl(hal, band, &cap_ctrl);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;

			type = RTW_PHL_PKT_TYPE_MGNT;
			target = RXFLTR_TARGET_TO_HOST;
			hstats = rtw_hal_set_rxfltr_by_type(hal, band, type, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;

			type = RTW_PHL_PKT_TYPE_DATA;
			target = RXFLTR_TARGET_TO_HOST;
			hstats = rtw_hal_set_rxfltr_by_type(hal, band, type, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;
		} while (0);
		break;
#ifdef CONFIG_PHL_TEST_MP
	case RX_FLTR_TYPE_MODE_MP:
		do {
			struct rxfltr_cap_to_set_mgnt cap_mgnt = {0};

			type = RTW_PHL_PKT_TYPE_CTRL;
			target = RXFLTR_TARGET_DROP;
			hstats = rtw_hal_set_rxfltr_by_type(hal, band, type, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;

			type = RTW_PHL_PKT_TYPE_MGNT;
			target = RXFLTR_TARGET_DROP;
			hstats = rtw_hal_set_rxfltr_by_type(hal, band, type, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;

			type = RTW_PHL_PKT_TYPE_DATA;
			target = RXFLTR_TARGET_TO_HOST;
			hstats = rtw_hal_set_rxfltr_by_type(hal, band, type, target);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;

			cap_mgnt.stype[RXFLTR_STYPE_BEACON].set = true;
			cap_mgnt.stype[RXFLTR_STYPE_BEACON].target = RXFLTR_TARGET_TO_HOST;
			hstats = rtw_hal_set_rxfltr_by_stype_mgnt(hal, band, &cap_mgnt);
			if (RTW_HAL_STATUS_SUCCESS != hstats)
				break;
		} while (0);
		break;
#endif
	default:
		PHL_TRACE(COMP_PHL_RECV, _PHL_ERR_, "%s: does not handle rxfltr mode(%u)\n", __func__, mode);
		break;
	}

	return hstats;
}

enum rtw_hal_status
rtw_hal_poll_hw_rx_done(void *hal)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	enum rtw_hal_status sts = RTW_HAL_STATUS_SUCCESS;

	sts = rtw_hal_mac_poll_hw_rx_done(hal_info);

	return sts;
}

enum rtw_hal_status
rtw_hal_hw_rx_resume(void *hal)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	enum rtw_hal_status sts = RTW_HAL_STATUS_SUCCESS;

	sts = rtw_hal_mac_hw_rx_resume(hal_info);

	return sts;
}

#ifdef CONFIG_PCI_HCI
/**
 * rtw_hal_rx_res_query - query current HW rx resource with specifc dma channel
 * @hal: see struct hal_info_t
 * @dma_ch: the target dma channel
 * @host_idx: current host index of this channel
 * @hw_idx: current hw index of this channel
 *
 * this function returns the number of available tx resource
 * NOTE, input host_idx and hw_idx ptr shall NOT be NULL
 */
u16 rtw_hal_rx_res_query(void *hal, u8 dma_ch, u16 *host_idx, u16 *hw_idx)
{
	enum rtw_hal_status sts = RTW_HAL_STATUS_FAILURE;
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	u16 res_num = 0;

	sts = rtw_hal_mac_rx_res_query(hal_info, dma_ch, host_idx, hw_idx,
	                               &res_num);

	if (sts != RTW_HAL_STATUS_SUCCESS) {
		PHL_TRACE(COMP_PHL_RECV, _PHL_WARNING_, "%s : query rx resource fail!\n",
		          __func__);
	}

	return res_num;
}

u16 rtw_hal_get_rxbd_num(void *hal, u8 dma_ch)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
	u16 res_num = 0;

	res_num = trx_ops->get_rxbd_num(hal_info->hal_com, dma_ch);

	return res_num;
}

u16 rtw_hal_get_rxbuf_num(void *hal, u8 dma_ch)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
	u16 res_num = 0;

	res_num = trx_ops->get_rxbuf_num(hal_info->hal_com, dma_ch);

	return res_num;
}

u16 rtw_hal_get_rxbuf_size(void *hal, u8 dma_ch)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
	u16 res_num = 0;

	res_num = trx_ops->get_rxbuf_size(hal_info->hal_com, dma_ch);

	return res_num;
}

/**
 * rtw_hal_query_rxch_num - query total hw rx dma channels number
 *
 * returns the number of  hw rx dma channel
 */
u8 rtw_hal_query_rxch_num(void *hal)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
	u8 ch_num = 0;

	ch_num = trx_ops->query_rxch_num();

	return ch_num;
}

u8 rtw_hal_check_rxrdy(struct rtw_phl_com_t *phl_com, void* hal,
		       struct rtw_rx_buf *rxbuf, u8 dma_ch)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
	u8 res = 0;

	res = trx_ops->check_rxrdy(phl_com, rxbuf, dma_ch);

	return res;
}

u8 rtw_hal_handle_rxbd_info(void* hal, u8 *rxbuf, u16 *buf_size)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
	u8 res = 0;

	res = trx_ops->handle_rxbd_info(hal_info, rxbuf, buf_size);

	return res;
}

enum rtw_hal_status
rtw_hal_update_rxbd(void *hal, struct rx_base_desc *rxbd,
					struct rtw_rx_buf *rxbuf, u8 ch_idx)
{
	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;

	hstatus = trx_ops->update_rxbd(hal_info, rxbd, rxbuf, ch_idx);

	return hstatus;
}


enum rtw_hal_status
rtw_hal_notify_rxdone(void* hal, struct rx_base_desc *rxbd, u8 dma_ch)
{
	enum rtw_hal_status sts = RTW_HAL_STATUS_FAILURE;
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;

	sts = rtw_hal_mac_notify_rxdone(hal_info, rxbd, dma_ch);
	if (sts != RTW_HAL_STATUS_SUCCESS) {
		PHL_TRACE(COMP_PHL_RECV, _PHL_INFO_, "%s : notify rx done fail!\n",
		          __func__);
	}

	return sts;
}

u16 rtw_hal_handle_wp_rpt(void *hal, u8 *rp, u16 len, u8 *sw_retry, u8 *dma_ch,
			  u16 *wp_seq, u8 *macid, u8 *ac_queue, u8 *txsts)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
	u16 rsize = 0;

	rsize = trx_ops->handle_wp_rpt(hal_info, rp, len, sw_retry, dma_ch,
				       wp_seq, macid, ac_queue, txsts);
	return rsize;
}

#endif /*CONFIG_PCI_HCI*/


#ifdef CONFIG_USB_HCI
enum rtw_hal_status
rtw_hal_query_info(void* hal, u8 info_id, void *value)
{
	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;

	hstatus = trx_ops->query_hal_info(hal_info, info_id, value);

	return hstatus;
}

enum rtw_hal_status
hal_usb_rx_agg_cfg(struct hal_info_t *hal, u8 mode, u8 agg_mode,
		   u8 drv_define, u8 timeout, u8 size, u8 pkt_num)
{
	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
	switch (mode){
	case PHL_RX_AGG_DISABLE:
		hstatus = hal_mac_usb_rx_agg_cfg(hal, MAC_AX_RX_AGG_MODE_NONE,
						 0, 0, 0, 0);
		break;
	case PHL_RX_AGG_DEFAULT:
		hstatus = hal_mac_usb_rx_agg_cfg(hal, MAC_AX_RX_AGG_MODE_USB,
						 0, 0, 0, 0);
		break;
	case PHL_RX_AGG_SMALL_PKT:
		hstatus = hal_mac_usb_rx_agg_cfg(hal, MAC_AX_RX_AGG_MODE_USB,
						 1, 0x01, 0x01, 0);
		break;
	case PHL_RX_AGG_USER_DEFINE:
		hstatus = hal_mac_usb_rx_agg_cfg(hal, agg_mode, drv_define,
						 timeout, size, pkt_num);
		break;
	default:
		hstatus = RTW_HAL_STATUS_FAILURE;
		break;
	}
	return hstatus;
}

enum rtw_hal_status
	rtw_hal_usb_rx_agg_cfg(void *hal, u8 mode, u8 agg_mode,
	u8 drv_define, u8 timeout, u8 size, u8 pkt_num)
{
	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;

	hstatus = trx_ops->usb_rx_agg_cfg(hal, mode, agg_mode,
		drv_define, timeout, size, pkt_num);

	return hstatus;
}

enum rtw_hal_status
rtw_hal_usb_rx_agg_init(struct rtw_phl_com_t *phl_com, void *hal)
{
	enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct rtw_hal_com_t *hal_com = hal_info->hal_com;
	struct bus_sw_cap_t *bus_sw = &phl_com->bus_sw_cap;
	struct bus_hw_cap_t *bus_hw = &hal_com->bus_hw_cap;

	if (bus_sw->rx_buf_size == 0 ||
	    bus_sw->rx_buf_size > bus_hw->rx_buf_size) {
		hstatus = rtw_hal_usb_rx_agg_cfg(hal, PHL_RX_AGG_DEFAULT,
						 0, 0, 0, 0, 0);
	} else {
		/*
		 * agg_size unit is 1024 bytes. We make rx_buf_size 4096 bytes
		 * more than agg_size to avoid the case that the data size of
		 * USB Rx exceeds rx_buf_size.
		 */
		u8 agg_size = (u8)(bus_sw->rx_buf_size / 1024) - 4;

		hstatus = rtw_hal_usb_rx_agg_cfg(hal, PHL_RX_AGG_USER_DEFINE,
						 MAC_AX_RX_AGG_MODE_USB , 1, 32,
						 agg_size, 0);
	}

	return hstatus;
}

u16 rtw_hal_handle_wp_rpt_usb(void *hal, u8 *rp, u16 len, u8 *macid, u8 *ac_queue,
		u8 *txsts)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;
	u16 rsize = 0;

	rsize = trx_ops->handle_wp_rpt(hal_info, rp, len, macid, ac_queue, txsts);
	return rsize;
}

#endif

enum rtw_hal_status
rtw_hal_handle_rx_buffer(struct rtw_phl_com_t *phl_com, void* hal,
				u8 *buf, u32 buf_size,
				struct rtw_phl_rx_pkt *rxpkt)
{
	enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	struct hal_trx_ops *trx_ops = hal_info->trx_ops;

	hstatus = trx_ops->handle_rx_buffer(phl_com, hal_info,
					      buf, buf_size, rxpkt);

	return hstatus;
}

#ifdef CONFIG_SDIO_HCI
void rtw_hal_sdio_rx_agg_cfg(void *hal, bool enable, u8 drv_define,
			     u8 timeout, u8 size, u8 pkt_num)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;


	rtw_hal_mac_sdio_rx_agg_cfg(hal_info->hal_com, enable, drv_define,
				    timeout, size, pkt_num);
}

int rtw_hal_sdio_rx(void *hal, struct rtw_rx_buf *rxbuf)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;


	return rtw_hal_mac_sdio_rx(hal_info->hal_com, rxbuf);
}

int rtw_hal_sdio_parse_rx(void *hal, struct rtw_rx_buf *rxbuf)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;


	return rtw_hal_mac_sdio_parse_rx(hal_info->hal_com, rxbuf);
}

/**
 * rtw_hal_sdio_lps_flg - get lps status
 * @hal:	pointer of struct hal_info_t
 *
 * Get driver lps status
 *
 * return lps flag state defined in enum rtw_hal_lps_flg_state
 * RTW_HAL_LPS_FLG_STATE_LPS when driver set LPS-CG/LPS-PG enable;
 * RTW_HAL_LPS_FLG_STATE_ACTIVE when driver is not in LPS-CG/LPS-PG
 */
enum rtw_hal_lps_flg_state
rtw_hal_sdio_lps_flg(void *hal)
{
	struct hal_info_t *hal_info = (struct hal_info_t *)hal;
	u8 lps_flg = 0;
	enum rtw_hal_lps_flg_state state = RTW_HAL_LPS_FLG_STATE_ACTIVE;

	rtw_hal_mac_sdio_lps_flg(hal_info->hal_com, &lps_flg);

	if (lps_flg == 1)
		state = RTW_HAL_LPS_FLG_STATE_LPS;

	return state;
}
#endif /* CONFIG_SDIO_HCI */

void
hal_rx_ppdu_sts_normal_data(struct rtw_phl_com_t *phl_com,
			    void *hdr,
			    struct rtw_r_meta_data *meta)
{
	struct rtw_phl_ppdu_sts_info *ppdu_info = NULL;
	enum phl_band_idx band = HW_BAND_0;
#ifdef CONFIG_PHL_WKARD_CHANNEL_INFO_ACK
	struct rtw_chinfo_cur_parm *cur_parm = phl_com->cur_parm;
#endif

	do {
		if (NULL == meta)
			break;
		ppdu_info = &phl_com->ppdu_sts_info;
		band = (meta->bb_sel > 0) ? HW_BAND_1 : HW_BAND_0;
		if ((ppdu_info->cur_rx_ppdu_cnt[band] == meta->ppdu_cnt) &&
		    (false == ppdu_info->latest_rx_is_psts[band])) {
			/**
			 * add condition to avoid check fail for ppdu cnt run around 0 -> 1 -> ... -> 0
			 * example :
			 * 	[frame_A(ppdu_cnt = 0)] -> [ppdu_sts(ppdu_cnt = 0)]
			 *  	->[ppdu_sts(ppdu_cnt = 1)] -> [ppdu_sts(ppdu_cnt = 2)] ...
			 * 	... ->[ppdu_sts(ppdu_cnt = 7)] -> [frame_B(ppdu_cnt = 0)] ...
			 * 	Therefore, frame_B has same ppdu_cnt with frame_A.
			 *	But they are different PPDU.
			**/
			break;
		}
		meta->ppdu_cnt_chg = true;
		/* start of the PPDU */
		ppdu_info->latest_rx_is_psts[band] = false;
		ppdu_info->sts_ent[band][meta->ppdu_cnt].addr_cam_vld = meta->addr_cam_vld;
		ppdu_info->sts_ent[band][meta->ppdu_cnt].frame_type = PHL_GET_80211_HDR_TYPE(hdr);
		ppdu_info->sts_ent[band][meta->ppdu_cnt].crc32 = meta->crc32;
		ppdu_info->sts_ent[band][meta->ppdu_cnt].rx_rate = meta->rx_rate;
		ppdu_info->sts_ent[band][meta->ppdu_cnt].ppdu_type = meta->ppdu_type;
		ppdu_info->sts_ent[band][meta->ppdu_cnt].pkt_freerun_cnt = meta->freerun_cnt;

		if(RTW_IS_BEACON_OR_PROBE_RESP_PKT(ppdu_info->sts_ent[band][meta->ppdu_cnt].frame_type)) {
			PHL_GET_80211_HDR_ADDRESS3(phl_com->drv_priv, hdr,
				ppdu_info->sts_ent[band][meta->ppdu_cnt].src_mac_addr);
		}
		else if (meta->a1_match &&
			  RTW_IS_ASOC_REQ_PKT(ppdu_info->sts_ent[band][meta->ppdu_cnt].frame_type)) {

			PHL_GET_80211_HDR_ADDRESS2(phl_com->drv_priv, hdr,
				ppdu_info->sts_ent[band][meta->ppdu_cnt].src_mac_addr);

			#ifdef DBG_AP_CLIENT_ASSOC_RSSI
			{
				u8 *src = NULL;

				src = ppdu_info->sts_ent[band][meta->ppdu_cnt].src_mac_addr;

				PHL_INFO("%s [Rx-ASOC_REQ] - MAC-Addr:%02x-%02x-%02x-%02x-%02x-%02x, a1_match:%d ppdu_cnt:%d\n",
					__func__,
					src[0], src[1], src[2], src[3], src[4], src[5],
					meta->a1_match,
					meta->ppdu_cnt);
			}
			#endif
		}
		else {
			_os_mem_cpy(phl_com->drv_priv,
				ppdu_info->sts_ent[band][meta->ppdu_cnt].src_mac_addr,
				meta->ta, MAC_ADDRESS_LENGTH);
			#ifdef CONFIG_PHL_WKARD_CHANNEL_INFO_ACK
			if (rtw_hal_ch_info_process_ack(meta, ppdu_info, cur_parm, meta->macid)) {
				if (meta->macid != 0xff) {
					struct rtw_phl_stainfo_t *sta = rtw_phl_get_stainfo_by_macid(phl_com->phl_priv, meta->macid);

					_os_mem_cpy(phl_com->drv_priv, ppdu_info->sts_ent[band][meta->ppdu_cnt].src_mac_addr,
						sta->mac_addr, MAC_ADDRESS_LENGTH);
					ppdu_info->sts_ent[band][meta->ppdu_cnt].freerun_cnt = meta->freerun_cnt;
				}
			}
			#endif
		}
		ppdu_info->sts_ent[band][meta->ppdu_cnt].valid = false;
		ppdu_info->cur_rx_ppdu_cnt[band] = meta->ppdu_cnt;
		PHL_TRACE(COMP_PHL_PSTS, _PHL_INFO_,
				"Start of the PPDU : band %d ; ppdu_cnt %d ; frame_type %d ; addr_cam_vld %d ; size %d ; rate 0x%x ; crc32 %d\n",
				band,
				ppdu_info->cur_rx_ppdu_cnt[band],
				ppdu_info->sts_ent[band][meta->ppdu_cnt].frame_type,
				ppdu_info->sts_ent[band][meta->ppdu_cnt].addr_cam_vld,
				meta->pktlen,
				meta->rx_rate,
				meta->crc32);
	} while (false);

}

void
hal_rx_ppdu_sts(struct rtw_phl_com_t *phl_com,
		struct rtw_phl_rx_pkt *phl_rx,
		struct hal_ppdu_sts *ppdu_sts)
{
	struct rtw_phl_ppdu_sts_info *ppdu_info = NULL;
	struct rtw_phl_rssi_stat *rssi_stat = NULL;
	struct rtw_r_meta_data *meta = &(phl_rx->r.mdata);
	struct rtw_phl_ppdu_phy_info *phy_info = &(phl_rx->r.phy_info);
	u8 i = 0;
	enum phl_band_idx band = HW_BAND_0;
	struct rtw_phl_ppdu_sts_ent *sts_ent = NULL;

	if ((NULL == phl_com) || (NULL == meta) || (NULL == ppdu_sts))
		return;

	ppdu_info = &phl_com->ppdu_sts_info;
	rssi_stat = &phl_com->rssi_stat;
	band = (meta->bb_sel > 0) ? HW_BAND_1 : HW_BAND_0;
	ppdu_info->latest_rx_is_psts[band] = true;

	if (0 == phy_info->is_valid)
		return;

	if (ppdu_info->cur_rx_ppdu_cnt[band] != meta->ppdu_cnt) {
		PHL_TRACE(COMP_PHL_PSTS, _PHL_INFO_,
			  "[WARNING] ppdu cnt mis-match (band %d ; cur : %d , rxmeta : %d)\n",
			  band,
			  ppdu_info->cur_rx_ppdu_cnt[band],
			  meta->ppdu_cnt);
	}
	sts_ent = &(ppdu_info->sts_ent[band][meta->ppdu_cnt]);

	if (meta->crc32 || sts_ent->crc32) {
		UPDATE_MA_RSSI(rssi_stat, RTW_RSSI_UNKNOWN,
			 phy_info->rssi);
		if (phl_com->drv_mode != RTW_DRV_MODE_SNIFFER)
			return;
	}
	if (sts_ent->rx_rate != meta->rx_rate) {
		PHL_TRACE(COMP_PHL_PSTS, _PHL_INFO_,
			  "[WARNING] PPDU STS rx rate mis-match\n");
		UPDATE_MA_RSSI(rssi_stat, RTW_RSSI_UNKNOWN,
			       phy_info->rssi);
		return;
	}
	if (sts_ent->ppdu_type != meta->ppdu_type) {
		PHL_TRACE(COMP_PHL_PSTS, _PHL_INFO_,
			  "[WARNING] PPDU STS ppdu_type mis-match\n");
		UPDATE_MA_RSSI(rssi_stat, RTW_RSSI_UNKNOWN,
			       phy_info->rssi);
		return;
	}
	if (sts_ent->valid == true) {
		PHL_TRACE(COMP_PHL_PSTS, _PHL_INFO_,
			  "[WARNING] PPDU STS is already updated, skip this ppdu status\n");
		return;
	}

	/* update ppdu_info entry */
	sts_ent->freerun_cnt = meta->freerun_cnt;
	_os_mem_cpy(phl_com->drv_priv,
		    &(sts_ent->phy_info),
		    phy_info, sizeof(struct rtw_phl_ppdu_phy_info));

	sts_ent->usr_num = ppdu_sts->usr_num;
	for (i = 0; i < ppdu_sts->usr_num; i++) {
		if (ppdu_sts->usr[i].vld) {
			sts_ent->sta[i].macid =
				ppdu_sts->usr[i].macid;
			sts_ent->sta[i].vld = 1;
		} else {
			sts_ent->sta[i].vld = 0;
		}
	}
	sts_ent->phl_done = false;
	sts_ent->valid = true;

	/* update rssi stat */
	_os_spinlock(phl_com->drv_priv, &rssi_stat->lock, _bh, NULL);
	rssi_stat->last_rx_freerun = sts_ent->pkt_freerun_cnt;
	switch (sts_ent->frame_type &
		(BIT(1) | BIT(0))) {
		case RTW_FRAME_TYPE_MGNT :
			if (sts_ent->addr_cam_vld) {
				UPDATE_MA_RSSI(rssi_stat,
					 (1 == meta->a1_match) ?
					  RTW_RSSI_MGNT_ACAM_A1M :
					  RTW_RSSI_MGNT_ACAM,
					 phy_info->rssi);
			} else {
				UPDATE_MA_RSSI(rssi_stat, RTW_RSSI_MGNT_OTHER,
					 phy_info->rssi);
			}
		break;
		case RTW_FRAME_TYPE_CTRL :
			if (sts_ent->addr_cam_vld) {
				UPDATE_MA_RSSI(rssi_stat,
					 (1 == meta->a1_match) ?
					  RTW_RSSI_CTRL_ACAM_A1M :
					  RTW_RSSI_CTRL_ACAM,
					 phy_info->rssi);
			} else {
				UPDATE_MA_RSSI(rssi_stat, RTW_RSSI_CTRL_OTHER,
					 phy_info->rssi);
			}
		break;
		case RTW_FRAME_TYPE_DATA :
			if (sts_ent->addr_cam_vld) {
				UPDATE_MA_RSSI(rssi_stat,
					 (1 == meta->a1_match) ?
					  RTW_RSSI_DATA_ACAM_A1M :
					  RTW_RSSI_DATA_ACAM,
					 phy_info->rssi);
			} else {
				UPDATE_MA_RSSI(rssi_stat, RTW_RSSI_DATA_OTHER,
					 phy_info->rssi);
			}
		break;
		default:
			UPDATE_MA_RSSI(rssi_stat, RTW_RSSI_UNKNOWN,
				       phy_info->rssi);
		break;
	}
	_os_spinunlock(phl_com->drv_priv, &rssi_stat->lock, _bh, NULL);
}
