Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 Apr 2026 14:22:08 +0000
From:      Bjoern A. Zeeb <bz@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 41b641cc0537 - main - rtw88: update Realtek's rtw88 driver
Message-ID:  <69e39390.22a69.6427e8b@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=41b641cc0537d1288cc05332bb4c5de3dcb12589

commit 41b641cc0537d1288cc05332bb4c5de3dcb12589
Merge: 480ba21efdc7 29163571ee4d
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2026-04-18 14:21:04 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-04-18 14:21:04 +0000

    rtw88: update Realtek's rtw88 driver
    
    This version is based on
    git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
    028ef9c96e96197026887c0f092424679298aae8 ( tag: v7.0 ).
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days

 sys/contrib/dev/rtw88/fw.c        |  2 +-
 sys/contrib/dev/rtw88/main.c      | 54 +++++++++++++++++++++++++++------------
 sys/contrib/dev/rtw88/main.h      |  2 +-
 sys/contrib/dev/rtw88/phy.c       | 20 +++++++++++++++
 sys/contrib/dev/rtw88/phy.h       |  2 ++
 sys/contrib/dev/rtw88/rtw8723cs.c |  2 +-
 sys/contrib/dev/rtw88/rtw8723ds.c |  2 +-
 sys/contrib/dev/rtw88/rtw8821cs.c |  2 +-
 sys/contrib/dev/rtw88/rtw8821cu.c |  2 ++
 sys/contrib/dev/rtw88/rtw8822b.c  |  3 ++-
 sys/contrib/dev/rtw88/rtw8822bs.c |  2 +-
 sys/contrib/dev/rtw88/rtw8822cs.c |  2 +-
 sys/contrib/dev/rtw88/sdio.c      |  6 ++---
 sys/contrib/dev/rtw88/sdio.h      |  2 +-
 sys/contrib/dev/rtw88/usb.c       |  5 ++--
 sys/contrib/dev/rtw88/util.c      |  4 +--
 16 files changed, 78 insertions(+), 34 deletions(-)

diff --cc sys/contrib/dev/rtw88/fw.c
index 5ce4a6bcffb6,000000000000..1574b2422240
mode 100644,000000..100644
--- a/sys/contrib/dev/rtw88/fw.c
+++ b/sys/contrib/dev/rtw88/fw.c
@@@ -1,2471 -1,0 +1,2471 @@@
 +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 +/* Copyright(c) 2018-2019  Realtek Corporation
 + */
 +
 +#include <linux/iopoll.h>
 +
 +#include "main.h"
 +#include "coex.h"
 +#include "fw.h"
 +#include "tx.h"
 +#include "reg.h"
 +#include "sec.h"
 +#include "debug.h"
 +#include "util.h"
 +#include "wow.h"
 +#include "ps.h"
 +#include "phy.h"
 +#include "mac.h"
 +
 +static const struct rtw_hw_reg_desc fw_h2c_regs[] = {
 +	{REG_FWIMR, MASKDWORD, "FWIMR"},
 +	{REG_FWIMR, BIT_FS_H2CCMD_INT_EN, "FWIMR enable"},
 +	{REG_FWISR, MASKDWORD, "FWISR"},
 +	{REG_FWISR, BIT_FS_H2CCMD_INT, "FWISR enable"},
 +	{REG_HMETFR, BIT_INT_BOX_ALL, "BoxBitMap"},
 +	{REG_HMEBOX0, MASKDWORD, "MSG 0"},
 +	{REG_HMEBOX0_EX, MASKDWORD, "MSG_EX 0"},
 +	{REG_HMEBOX1, MASKDWORD, "MSG 1"},
 +	{REG_HMEBOX1_EX, MASKDWORD, "MSG_EX 1"},
 +	{REG_HMEBOX2, MASKDWORD, "MSG 2"},
 +	{REG_HMEBOX2_EX, MASKDWORD, "MSG_EX 2"},
 +	{REG_HMEBOX3, MASKDWORD, "MSG 3"},
 +	{REG_HMEBOX3_EX, MASKDWORD, "MSG_EX 3"},
 +	{REG_FT1IMR, MASKDWORD, "FT1IMR"},
 +	{REG_FT1IMR, BIT_FS_H2C_CMD_OK_INT_EN, "FT1IMR enable"},
 +	{REG_FT1ISR, MASKDWORD, "FT1ISR"},
 +	{REG_FT1ISR, BIT_FS_H2C_CMD_OK_INT, "FT1ISR enable "},
 +};
 +
 +static const struct rtw_hw_reg_desc fw_c2h_regs[] = {
 +	{REG_FWIMR, MASKDWORD, "FWIMR"},
 +	{REG_FWIMR, BIT_FS_H2CCMD_INT_EN, "CPWM"},
 +	{REG_FWIMR, BIT_FS_HRCV_INT_EN, "HRECV"},
 +	{REG_FWISR, MASKDWORD, "FWISR"},
 +	{REG_FWISR, BIT_FS_H2CCMD_INT, "CPWM"},
 +	{REG_FWISR, BIT_FS_HRCV_INT, "HRECV"},
 +	{REG_CPWM, MASKDWORD, "REG_CPWM"},
 +};
 +
 +static const struct rtw_hw_reg_desc fw_core_regs[] = {
 +	{REG_ARFR2_V1, MASKDWORD, "EPC"},
 +	{REG_ARFRH2_V1, MASKDWORD, "BADADDR"},
 +	{REG_ARFR3_V1, MASKDWORD, "CAUSE"},
 +	{REG_ARFR3_V1, BIT_EXC_CODE, "ExcCode"},
 +	{REG_ARFRH3_V1, MASKDWORD, "Status"},
 +	{REG_ARFR4, MASKDWORD, "SP"},
 +	{REG_ARFRH4, MASKDWORD, "RA"},
 +	{REG_FW_DBG6, MASKDWORD, "DBG 6"},
 +	{REG_FW_DBG7, MASKDWORD, "DBG 7"},
 +};
 +
 +static void _rtw_fw_dump_dbg_info(struct rtw_dev *rtwdev,
 +				  const struct rtw_hw_reg_desc regs[], u32 size)
 +{
 +	const struct rtw_hw_reg_desc *reg;
 +	u32 val;
 +	int i;
 +
 +	for (i = 0;  i < size; i++) {
 +		reg = &regs[i];
 +		val = rtw_read32_mask(rtwdev, reg->addr, reg->mask);
 +
 +		rtw_dbg(rtwdev, RTW_DBG_FW, "[%s]addr:0x%x mask:0x%x value:0x%x\n",
 +			reg->desc, reg->addr, reg->mask, val);
 +	}
 +}
 +
 +void rtw_fw_dump_dbg_info(struct rtw_dev *rtwdev)
 +{
 +	int i;
 +
 +	if (!rtw_dbg_is_enabled(rtwdev, RTW_DBG_FW))
 +		return;
 +
 +	_rtw_fw_dump_dbg_info(rtwdev, fw_h2c_regs, ARRAY_SIZE(fw_h2c_regs));
 +	_rtw_fw_dump_dbg_info(rtwdev, fw_c2h_regs, ARRAY_SIZE(fw_c2h_regs));
 +	for (i = 0 ; i < RTW_DEBUG_DUMP_TIMES; i++) {
 +		rtw_dbg(rtwdev, RTW_DBG_FW, "Firmware Coredump %dth\n", i + 1);
 +		_rtw_fw_dump_dbg_info(rtwdev, fw_core_regs, ARRAY_SIZE(fw_core_regs));
 +	}
 +}
 +
 +static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
 +				      struct sk_buff *skb)
 +{
 +	struct rtw_c2h_cmd *c2h;
 +	u8 sub_cmd_id;
 +
 +	c2h = get_c2h_from_skb(skb);
 +	sub_cmd_id = c2h->payload[0];
 +
 +	switch (sub_cmd_id) {
 +	case C2H_CCX_RPT:
 +		rtw_tx_report_handle(rtwdev, skb, C2H_CCX_RPT);
 +		break;
 +	case C2H_SCAN_STATUS_RPT:
 +		rtw_hw_scan_status_report(rtwdev, skb);
 +		break;
 +	case C2H_CHAN_SWITCH:
 +		rtw_hw_scan_chan_switch(rtwdev, skb);
 +		break;
 +	default:
 +		break;
 +	}
 +}
 +
 +static u16 get_max_amsdu_len(u32 bit_rate)
 +{
 +	/* lower than ofdm, do not aggregate */
 +	if (bit_rate < 550)
 +		return 1;
 +
 +	/* lower than 20M 2ss mcs8, make it small */
 +	if (bit_rate < 1800)
 +		return 1200;
 +
 +	/* lower than 40M 2ss mcs9, make it medium */
 +	if (bit_rate < 4000)
 +		return 2600;
 +
 +	/* not yet 80M 2ss mcs8/9, make it twice regular packet size */
 +	if (bit_rate < 7000)
 +		return 3500;
 +
 +	/* unlimited */
 +	return 0;
 +}
 +
 +struct rtw_fw_iter_ra_data {
 +	struct rtw_dev *rtwdev;
 +	u8 *payload;
 +	u8 length;
 +};
 +
 +static void rtw_fw_ra_report_iter(void *data, struct ieee80211_sta *sta)
 +{
 +	struct rtw_fw_iter_ra_data *ra_data = data;
 +	struct rtw_c2h_ra_rpt *ra_rpt = (struct rtw_c2h_ra_rpt *)ra_data->payload;
 +	struct rtw_sta_info *si = (struct rtw_sta_info *)sta->drv_priv;
 +	u8 mac_id, rate, sgi, bw;
 +	u8 mcs, nss;
 +	u32 bit_rate;
 +
 +	mac_id = ra_rpt->mac_id;
 +	if (si->mac_id != mac_id)
 +		return;
 +
 +	si->ra_report.txrate.flags = 0;
 +
 +	rate = u8_get_bits(ra_rpt->rate_sgi, RTW_C2H_RA_RPT_RATE);
 +	sgi = u8_get_bits(ra_rpt->rate_sgi, RTW_C2H_RA_RPT_SGI);
 +	if (ra_data->length >= offsetofend(typeof(*ra_rpt), bw))
 +		bw = ra_rpt->bw;
 +	else
 +		bw = si->bw_mode;
 +
 +	if (rate < DESC_RATEMCS0) {
 +		si->ra_report.txrate.legacy = rtw_desc_to_bitrate(rate);
 +		goto legacy;
 +	}
 +
 +	rtw_desc_to_mcsrate(rate, &mcs, &nss);
 +	if (rate >= DESC_RATEVHT1SS_MCS0)
 +		si->ra_report.txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
 +	else if (rate >= DESC_RATEMCS0)
 +		si->ra_report.txrate.flags |= RATE_INFO_FLAGS_MCS;
 +
 +	if (rate >= DESC_RATEMCS0) {
 +		si->ra_report.txrate.mcs = mcs;
 +		si->ra_report.txrate.nss = nss;
 +	}
 +
 +	if (sgi)
 +		si->ra_report.txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
 +
 +	if (bw == RTW_CHANNEL_WIDTH_80)
 +		si->ra_report.txrate.bw = RATE_INFO_BW_80;
 +	else if (bw == RTW_CHANNEL_WIDTH_40)
 +		si->ra_report.txrate.bw = RATE_INFO_BW_40;
 +	else
 +		si->ra_report.txrate.bw = RATE_INFO_BW_20;
 +
 +legacy:
 +	bit_rate = cfg80211_calculate_bitrate(&si->ra_report.txrate);
 +
 +	si->ra_report.desc_rate = rate;
 +	si->ra_report.bit_rate = bit_rate;
 +
 +	sta->deflink.agg.max_rc_amsdu_len = get_max_amsdu_len(bit_rate);
 +}
 +
 +static void rtw_fw_ra_report_handle(struct rtw_dev *rtwdev, u8 *payload,
 +				    u8 length)
 +{
 +	struct rtw_c2h_ra_rpt *ra_rpt = (struct rtw_c2h_ra_rpt *)payload;
 +	struct rtw_fw_iter_ra_data ra_data;
 +
 +	if (WARN(length < rtwdev->chip->c2h_ra_report_size,
 +		 "invalid ra report c2h length %d\n", length))
 +		return;
 +
 +	rtwdev->dm_info.tx_rate = u8_get_bits(ra_rpt->rate_sgi,
 +					      RTW_C2H_RA_RPT_RATE);
 +	ra_data.rtwdev = rtwdev;
 +	ra_data.payload = payload;
 +	ra_data.length = length;
 +	rtw_iterate_stas_atomic(rtwdev, rtw_fw_ra_report_iter, &ra_data);
 +}
 +
 +struct rtw_beacon_filter_iter_data {
 +	struct rtw_dev *rtwdev;
 +	u8 *payload;
 +};
 +
 +static void rtw_fw_bcn_filter_notify_vif_iter(void *data,
 +					      struct ieee80211_vif *vif)
 +{
 +	struct rtw_beacon_filter_iter_data *iter_data = data;
 +	struct rtw_dev *rtwdev = iter_data->rtwdev;
 +	u8 *payload = iter_data->payload;
 +	u8 type = GET_BCN_FILTER_NOTIFY_TYPE(payload);
 +	u8 event = GET_BCN_FILTER_NOTIFY_EVENT(payload);
 +	s8 sig = (s8)GET_BCN_FILTER_NOTIFY_RSSI(payload);
 +
 +	switch (type) {
 +	case BCN_FILTER_NOTIFY_SIGNAL_CHANGE:
 +		event = event ? NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH :
 +			NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
 +		ieee80211_cqm_rssi_notify(vif, event, sig, GFP_KERNEL);
 +		break;
 +	case BCN_FILTER_CONNECTION_LOSS:
 +		ieee80211_connection_loss(vif);
 +		break;
 +	case BCN_FILTER_CONNECTED:
 +		rtwdev->beacon_loss = false;
 +		break;
 +	case BCN_FILTER_NOTIFY_BEACON_LOSS:
 +		rtwdev->beacon_loss = true;
 +		rtw_leave_lps(rtwdev);
 +		break;
 +	}
 +}
 +
 +static void rtw_fw_bcn_filter_notify(struct rtw_dev *rtwdev, u8 *payload,
 +				     u8 length)
 +{
 +	struct rtw_beacon_filter_iter_data dev_iter_data;
 +
 +	dev_iter_data.rtwdev = rtwdev;
 +	dev_iter_data.payload = payload;
 +	rtw_iterate_vifs(rtwdev, rtw_fw_bcn_filter_notify_vif_iter,
 +			 &dev_iter_data);
 +}
 +
 +static void rtw_fw_scan_result(struct rtw_dev *rtwdev, u8 *payload,
 +			       u8 length)
 +{
 +	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
 +
 +	dm_info->scan_density = payload[0];
 +
 +	rtw_dbg(rtwdev, RTW_DBG_FW, "scan.density = %x\n",
 +		dm_info->scan_density);
 +}
 +
 +static void rtw_fw_adaptivity_result(struct rtw_dev *rtwdev, u8 *payload,
 +				     u8 length)
 +{
 +	const struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;
 +	struct rtw_c2h_adaptivity *result = (struct rtw_c2h_adaptivity *)payload;
 +
 +	rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY,
 +		"Adaptivity: density %x igi %x l2h_th_init %x l2h %x h2l %x option %x\n",
 +		result->density, result->igi, result->l2h_th_init, result->l2h,
 +		result->h2l, result->option);
 +
 +	rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, "Reg Setting: L2H %x H2L %x\n",
 +		rtw_read32_mask(rtwdev, edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr,
 +				edcca_th[EDCCA_TH_L2H_IDX].hw_reg.mask),
 +		rtw_read32_mask(rtwdev, edcca_th[EDCCA_TH_H2L_IDX].hw_reg.addr,
 +				edcca_th[EDCCA_TH_H2L_IDX].hw_reg.mask));
 +
 +	rtw_dbg(rtwdev, RTW_DBG_ADAPTIVITY, "EDCCA Flag %s\n",
 +		rtw_read32_mask(rtwdev, REG_EDCCA_REPORT, BIT_EDCCA_FLAG) ?
 +		"Set" : "Unset");
 +}
 +
 +void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb)
 +{
 +	struct rtw_c2h_cmd *c2h;
 +	u32 pkt_offset;
 +	u8 len;
 +
 +	pkt_offset = *((u32 *)skb->cb);
 +	c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
 +	len = skb->len - pkt_offset - 2;
 +
 +	mutex_lock(&rtwdev->mutex);
 +
 +	if (!test_bit(RTW_FLAG_RUNNING, rtwdev->flags))
 +		goto unlock;
 +
 +	switch (c2h->id) {
 +	case C2H_CCX_TX_RPT:
 +		rtw_tx_report_handle(rtwdev, skb, C2H_CCX_TX_RPT);
 +		break;
 +	case C2H_BT_INFO:
 +		rtw_coex_bt_info_notify(rtwdev, c2h->payload, len);
 +		break;
 +	case C2H_BT_HID_INFO:
 +		rtw_coex_bt_hid_info_notify(rtwdev, c2h->payload, len);
 +		break;
 +	case C2H_WLAN_INFO:
 +		rtw_coex_wl_fwdbginfo_notify(rtwdev, c2h->payload, len);
 +		break;
 +	case C2H_BCN_FILTER_NOTIFY:
 +		rtw_fw_bcn_filter_notify(rtwdev, c2h->payload, len);
 +		break;
 +	case C2H_HALMAC:
 +		rtw_fw_c2h_cmd_handle_ext(rtwdev, skb);
 +		break;
 +	case C2H_RA_RPT:
 +		rtw_fw_ra_report_handle(rtwdev, c2h->payload, len);
 +		break;
 +	case C2H_ADAPTIVITY:
 +		rtw_fw_adaptivity_result(rtwdev, c2h->payload, len);
 +		break;
 +	default:
 +		rtw_dbg(rtwdev, RTW_DBG_FW, "C2H 0x%x isn't handled\n", c2h->id);
 +		break;
 +	}
 +
 +unlock:
 +	mutex_unlock(&rtwdev->mutex);
 +}
 +
 +void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
 +			       struct sk_buff *skb)
 +{
 +	struct rtw_c2h_cmd *c2h;
 +	u8 len;
 +
 +	c2h = (struct rtw_c2h_cmd *)(skb->data + pkt_offset);
 +	len = skb->len - pkt_offset - 2;
 +	*((u32 *)skb->cb) = pkt_offset;
 +
 +	rtw_dbg(rtwdev, RTW_DBG_FW, "recv C2H, id=0x%02x, seq=0x%02x, len=%d\n",
 +		c2h->id, c2h->seq, len);
 +
 +	switch (c2h->id) {
 +	case C2H_BT_MP_INFO:
 +		rtw_coex_info_response(rtwdev, skb);
 +		break;
 +	case C2H_WLAN_RFON:
 +		complete(&rtwdev->lps_leave_check);
 +		dev_kfree_skb_any(skb);
 +		break;
 +	case C2H_SCAN_RESULT:
 +		complete(&rtwdev->fw_scan_density);
 +		rtw_fw_scan_result(rtwdev, c2h->payload, len);
 +		dev_kfree_skb_any(skb);
 +		break;
 +	default:
 +		/* pass offset for further operation */
 +		*((u32 *)skb->cb) = pkt_offset;
 +		skb_queue_tail(&rtwdev->c2h_queue, skb);
 +		ieee80211_queue_work(rtwdev->hw, &rtwdev->c2h_work);
 +		break;
 +	}
 +}
 +EXPORT_SYMBOL(rtw_fw_c2h_cmd_rx_irqsafe);
 +
 +void rtw_fw_c2h_cmd_isr(struct rtw_dev *rtwdev)
 +{
 +	if (rtw_read8(rtwdev, REG_MCU_TST_CFG) == VAL_FW_TRIGGER)
 +		rtw_fw_recovery(rtwdev);
 +	else
 +		rtw_warn(rtwdev, "unhandled firmware c2h interrupt\n");
 +}
 +EXPORT_SYMBOL(rtw_fw_c2h_cmd_isr);
 +
 +static void rtw_fw_send_h2c_command_register(struct rtw_dev *rtwdev,
 +					     struct rtw_h2c_register *h2c)
 +{
 +	u32 box_reg, box_ex_reg;
 +	u8 box_state, box;
 +	int ret;
 +
 +	rtw_dbg(rtwdev, RTW_DBG_FW, "send H2C content %08x %08x\n", h2c->w0,
 +		h2c->w1);
 +
 +	lockdep_assert_held(&rtwdev->mutex);
 +
 +	box = rtwdev->h2c.last_box_num;
 +	switch (box) {
 +	case 0:
 +		box_reg = REG_HMEBOX0;
 +		box_ex_reg = REG_HMEBOX0_EX;
 +		break;
 +	case 1:
 +		box_reg = REG_HMEBOX1;
 +		box_ex_reg = REG_HMEBOX1_EX;
 +		break;
 +	case 2:
 +		box_reg = REG_HMEBOX2;
 +		box_ex_reg = REG_HMEBOX2_EX;
 +		break;
 +	case 3:
 +		box_reg = REG_HMEBOX3;
 +		box_ex_reg = REG_HMEBOX3_EX;
 +		break;
 +	default:
 +		WARN(1, "invalid h2c mail box number\n");
 +		return;
 +	}
 +
 +	ret = read_poll_timeout_atomic(rtw_read8, box_state,
 +				       !((box_state >> box) & 0x1), 100, 3000,
 +				       false, rtwdev, REG_HMETFR);
 +
 +	if (ret) {
 +		rtw_err(rtwdev, "failed to send h2c command\n");
 +		rtw_fw_dump_dbg_info(rtwdev);
 +		return;
 +	}
 +
 +	rtw_write32(rtwdev, box_ex_reg, h2c->w1);
 +	rtw_write32(rtwdev, box_reg, h2c->w0);
 +
 +	if (++rtwdev->h2c.last_box_num >= 4)
 +		rtwdev->h2c.last_box_num = 0;
 +}
 +
 +static void rtw_fw_send_h2c_command(struct rtw_dev *rtwdev,
 +				    u8 *h2c)
 +{
 +	struct rtw_h2c_cmd *h2c_cmd = (struct rtw_h2c_cmd *)h2c;
 +	u8 box;
 +	u8 box_state;
 +	u32 box_reg, box_ex_reg;
 +	int ret;
 +
 +	rtw_dbg(rtwdev, RTW_DBG_FW,
 +		"send H2C content %02x%02x%02x%02x %02x%02x%02x%02x\n",
 +		h2c[3], h2c[2], h2c[1], h2c[0],
 +		h2c[7], h2c[6], h2c[5], h2c[4]);
 +
 +	lockdep_assert_held(&rtwdev->mutex);
 +
 +	box = rtwdev->h2c.last_box_num;
 +	switch (box) {
 +	case 0:
 +		box_reg = REG_HMEBOX0;
 +		box_ex_reg = REG_HMEBOX0_EX;
 +		break;
 +	case 1:
 +		box_reg = REG_HMEBOX1;
 +		box_ex_reg = REG_HMEBOX1_EX;
 +		break;
 +	case 2:
 +		box_reg = REG_HMEBOX2;
 +		box_ex_reg = REG_HMEBOX2_EX;
 +		break;
 +	case 3:
 +		box_reg = REG_HMEBOX3;
 +		box_ex_reg = REG_HMEBOX3_EX;
 +		break;
 +	default:
 +		WARN(1, "invalid h2c mail box number\n");
 +		return;
 +	}
 +
 +	ret = read_poll_timeout_atomic(rtw_read8, box_state,
 +				       !((box_state >> box) & 0x1), 100, 3000,
 +				       false, rtwdev, REG_HMETFR);
 +
 +	if (ret) {
 +		rtw_err(rtwdev, "failed to send h2c command\n");
 +		return;
 +	}
 +
 +	rtw_write32(rtwdev, box_ex_reg, le32_to_cpu(h2c_cmd->msg_ext));
 +	rtw_write32(rtwdev, box_reg, le32_to_cpu(h2c_cmd->msg));
 +
 +	if (++rtwdev->h2c.last_box_num >= 4)
 +		rtwdev->h2c.last_box_num = 0;
 +}
 +
 +void rtw_fw_h2c_cmd_dbg(struct rtw_dev *rtwdev, u8 *h2c)
 +{
 +	rtw_fw_send_h2c_command(rtwdev, h2c);
 +}
 +
 +static void rtw_fw_send_h2c_packet(struct rtw_dev *rtwdev, u8 *h2c_pkt)
 +{
 +	int ret;
 +
 +	lockdep_assert_held(&rtwdev->mutex);
 +
 +	FW_OFFLOAD_H2C_SET_SEQ_NUM(h2c_pkt, rtwdev->h2c.seq);
 +	ret = rtw_hci_write_data_h2c(rtwdev, h2c_pkt, H2C_PKT_SIZE);
 +	if (ret)
 +		rtw_err(rtwdev, "failed to send h2c packet\n");
 +	rtwdev->h2c.seq++;
 +}
 +
 +void
 +rtw_fw_send_general_info(struct rtw_dev *rtwdev)
 +{
 +	struct rtw_fifo_conf *fifo = &rtwdev->fifo;
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +	u16 total_size = H2C_PKT_HDR_SIZE + 4;
 +
 +	if (rtw_chip_wcpu_8051(rtwdev))
 +		return;
 +
 +	rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_GENERAL_INFO);
 +
 +	SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
 +
 +	GENERAL_INFO_SET_FW_TX_BOUNDARY(h2c_pkt,
 +					fifo->rsvd_fw_txbuf_addr -
 +					fifo->rsvd_boundary);
 +
 +	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
 +}
 +
 +void
 +rtw_fw_send_phydm_info(struct rtw_dev *rtwdev)
 +{
 +	struct rtw_hal *hal = &rtwdev->hal;
 +	struct rtw_efuse *efuse = &rtwdev->efuse;
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +	u16 total_size = H2C_PKT_HDR_SIZE + 8;
 +	u8 fw_rf_type = 0;
 +
 +	if (rtw_chip_wcpu_8051(rtwdev))
 +		return;
 +
 +	if (hal->rf_type == RF_1T1R)
 +		fw_rf_type = FW_RF_1T1R;
 +	else if (hal->rf_type == RF_2T2R)
 +		fw_rf_type = FW_RF_2T2R;
 +
 +	rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_PHYDM_INFO);
 +
 +	SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
 +	PHYDM_INFO_SET_REF_TYPE(h2c_pkt, efuse->rfe_option);
 +	PHYDM_INFO_SET_RF_TYPE(h2c_pkt, fw_rf_type);
 +	PHYDM_INFO_SET_CUT_VER(h2c_pkt, hal->cut_version);
 +	PHYDM_INFO_SET_RX_ANT_STATUS(h2c_pkt, hal->antenna_tx);
 +	PHYDM_INFO_SET_TX_ANT_STATUS(h2c_pkt, hal->antenna_rx);
 +
 +	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_do_iqk(struct rtw_dev *rtwdev, struct rtw_iqk_para *para)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +	u16 total_size = H2C_PKT_HDR_SIZE + 1;
 +
 +	rtw_h2c_pkt_set_header(h2c_pkt, H2C_PKT_IQK);
 +	SET_PKT_H2C_TOTAL_LEN(h2c_pkt, total_size);
 +	IQK_SET_CLEAR(h2c_pkt, para->clear);
 +	IQK_SET_SEGMENT_IQK(h2c_pkt, para->segment_iqk);
 +
 +	rtw_fw_send_h2c_packet(rtwdev, h2c_pkt);
 +}
 +EXPORT_SYMBOL(rtw_fw_do_iqk);
 +
 +void rtw_fw_inform_rfk_status(struct rtw_dev *rtwdev, bool start)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WIFI_CALIBRATION);
 +
 +	RFK_SET_INFORM_START(h2c_pkt, start);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +EXPORT_SYMBOL(rtw_fw_inform_rfk_status);
 +
 +void rtw_fw_query_bt_info(struct rtw_dev *rtwdev)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_INFO);
 +
 +	SET_QUERY_BT_INFO(h2c_pkt, true);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_default_port(struct rtw_dev *rtwdev, struct rtw_vif *rtwvif)
 +{
 +	struct rtw_h2c_register h2c = {};
 +
 +	if (rtwvif->net_type != RTW_NET_MGD_LINKED)
 +		return;
 +
 +	/* Leave LPS before default port H2C so FW timer is correct */
 +	rtw_leave_lps(rtwdev);
 +
 +	h2c.w0 = u32_encode_bits(H2C_CMD_DEFAULT_PORT, RTW_H2C_W0_CMDID) |
 +		 u32_encode_bits(rtwvif->port, RTW_H2C_DEFAULT_PORT_W0_PORTID) |
 +		 u32_encode_bits(rtwvif->mac_id, RTW_H2C_DEFAULT_PORT_W0_MACID);
 +
 +	rtw_fw_send_h2c_command_register(rtwdev, &h2c);
 +}
 +
 +void rtw_fw_wl_ch_info(struct rtw_dev *rtwdev, u8 link, u8 ch, u8 bw)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WL_CH_INFO);
 +
 +	SET_WL_CH_INFO_LINK(h2c_pkt, link);
 +	SET_WL_CH_INFO_CHNL(h2c_pkt, ch);
 +	SET_WL_CH_INFO_BW(h2c_pkt, bw);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_query_bt_mp_info(struct rtw_dev *rtwdev,
 +			     struct rtw_coex_info_req *req)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_MP_INFO);
 +
 +	SET_BT_MP_INFO_SEQ(h2c_pkt, req->seq);
 +	SET_BT_MP_INFO_OP_CODE(h2c_pkt, req->op_code);
 +	SET_BT_MP_INFO_PARA1(h2c_pkt, req->para1);
 +	SET_BT_MP_INFO_PARA2(h2c_pkt, req->para2);
 +	SET_BT_MP_INFO_PARA3(h2c_pkt, req->para3);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_force_bt_tx_power(struct rtw_dev *rtwdev, u8 bt_pwr_dec_lvl)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +	u8 index = 0 - bt_pwr_dec_lvl;
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_FORCE_BT_TX_POWER);
 +
 +	SET_BT_TX_POWER_INDEX(h2c_pkt, index);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_bt_ignore_wlan_action(struct rtw_dev *rtwdev, bool enable)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_IGNORE_WLAN_ACTION);
 +
 +	SET_IGNORE_WLAN_ACTION_EN(h2c_pkt, enable);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_coex_tdma_type(struct rtw_dev *rtwdev,
 +			   u8 para1, u8 para2, u8 para3, u8 para4, u8 para5)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_COEX_TDMA_TYPE);
 +
 +	SET_COEX_TDMA_TYPE_PARA1(h2c_pkt, para1);
 +	SET_COEX_TDMA_TYPE_PARA2(h2c_pkt, para2);
 +	SET_COEX_TDMA_TYPE_PARA3(h2c_pkt, para3);
 +	SET_COEX_TDMA_TYPE_PARA4(h2c_pkt, para4);
 +	SET_COEX_TDMA_TYPE_PARA5(h2c_pkt, para5);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_coex_query_hid_info(struct rtw_dev *rtwdev, u8 sub_id, u8 data)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_QUERY_BT_HID_INFO);
 +
 +	SET_COEX_QUERY_HID_INFO_SUBID(h2c_pkt, sub_id);
 +	SET_COEX_QUERY_HID_INFO_DATA1(h2c_pkt, data);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_bt_wifi_control(struct rtw_dev *rtwdev, u8 op_code, u8 *data)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BT_WIFI_CONTROL);
 +
 +	SET_BT_WIFI_CONTROL_OP_CODE(h2c_pkt, op_code);
 +
 +	SET_BT_WIFI_CONTROL_DATA1(h2c_pkt, *data);
 +	SET_BT_WIFI_CONTROL_DATA2(h2c_pkt, *(data + 1));
 +	SET_BT_WIFI_CONTROL_DATA3(h2c_pkt, *(data + 2));
 +	SET_BT_WIFI_CONTROL_DATA4(h2c_pkt, *(data + 3));
 +	SET_BT_WIFI_CONTROL_DATA5(h2c_pkt, *(data + 4));
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_send_rssi_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +	u8 rssi = ewma_rssi_read(&si->avg_rssi);
 +	bool stbc_en = si->stbc_en ? true : false;
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RSSI_MONITOR);
 +
 +	SET_RSSI_INFO_MACID(h2c_pkt, si->mac_id);
 +	SET_RSSI_INFO_RSSI(h2c_pkt, rssi);
 +	SET_RSSI_INFO_STBC(h2c_pkt, stbc_en);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_send_ra_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si,
 +			 bool reset_ra_mask)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +	bool disable_pt = true;
 +	u32 mask_hi;
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RA_INFO);
 +
 +	SET_RA_INFO_MACID(h2c_pkt, si->mac_id);
 +	SET_RA_INFO_RATE_ID(h2c_pkt, si->rate_id);
 +	SET_RA_INFO_INIT_RA_LVL(h2c_pkt, si->init_ra_lv);
 +	SET_RA_INFO_SGI_EN(h2c_pkt, si->sgi_enable);
 +	SET_RA_INFO_BW_MODE(h2c_pkt, si->bw_mode);
 +	SET_RA_INFO_LDPC(h2c_pkt, !!si->ldpc_en);
 +	SET_RA_INFO_NO_UPDATE(h2c_pkt, !reset_ra_mask);
 +	SET_RA_INFO_VHT_EN(h2c_pkt, si->vht_enable);
 +	SET_RA_INFO_DIS_PT(h2c_pkt, disable_pt);
 +	SET_RA_INFO_RA_MASK0(h2c_pkt, (si->ra_mask & 0xff));
 +	SET_RA_INFO_RA_MASK1(h2c_pkt, (si->ra_mask & 0xff00) >> 8);
 +	SET_RA_INFO_RA_MASK2(h2c_pkt, (si->ra_mask & 0xff0000) >> 16);
 +	SET_RA_INFO_RA_MASK3(h2c_pkt, (si->ra_mask & 0xff000000) >> 24);
 +
 +	si->init_ra_lv = 0;
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +
 +	if (rtwdev->chip->id != RTW_CHIP_TYPE_8814A)
 +		return;
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_RA_INFO_HI);
 +
 +	mask_hi = si->ra_mask >> 32;
 +
 +	SET_RA_INFO_RA_MASK0(h2c_pkt, (mask_hi & 0xff));
 +	SET_RA_INFO_RA_MASK1(h2c_pkt, (mask_hi & 0xff00) >> 8);
 +	SET_RA_INFO_RA_MASK2(h2c_pkt, (mask_hi & 0xff0000) >> 16);
 +	SET_RA_INFO_RA_MASK3(h2c_pkt, (mask_hi & 0xff000000) >> 24);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_media_status_report(struct rtw_dev *rtwdev, u8 mac_id, bool connect)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_MEDIA_STATUS_RPT);
 +	MEDIA_STATUS_RPT_SET_OP_MODE(h2c_pkt, connect);
 +	MEDIA_STATUS_RPT_SET_MACID(h2c_pkt, mac_id);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_update_wl_phy_info(struct rtw_dev *rtwdev)
 +{
 +	struct rtw_traffic_stats *stats = &rtwdev->stats;
 +	struct rtw_dm_info *dm_info = &rtwdev->dm_info;
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WL_PHY_INFO);
 +	SET_WL_PHY_INFO_TX_TP(h2c_pkt, stats->tx_throughput);
 +	SET_WL_PHY_INFO_RX_TP(h2c_pkt, stats->rx_throughput);
 +	SET_WL_PHY_INFO_TX_RATE_DESC(h2c_pkt, dm_info->tx_rate);
 +	SET_WL_PHY_INFO_RX_RATE_DESC(h2c_pkt, dm_info->curr_rx_rate);
 +	SET_WL_PHY_INFO_RX_EVM(h2c_pkt, dm_info->rx_evm_dbm[RF_PATH_A]);
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_beacon_filter_config(struct rtw_dev *rtwdev, bool connect,
 +				 struct ieee80211_vif *vif)
 +{
 +	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
 +	struct ieee80211_sta *sta = ieee80211_find_sta(vif, bss_conf->bssid);
 +	static const u8 rssi_min = 0, rssi_max = 100, rssi_offset = 100;
 +	struct rtw_sta_info *si =
 +		sta ? (struct rtw_sta_info *)sta->drv_priv : NULL;
 +	s32 thold = RTW_DEFAULT_CQM_THOLD;
 +	u32 hyst = RTW_DEFAULT_CQM_HYST;
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_BCN_FILTER))
 +		return;
 +
 +	if (bss_conf->cqm_rssi_thold)
 +		thold = bss_conf->cqm_rssi_thold;
 +	if (bss_conf->cqm_rssi_hyst)
 +		hyst = bss_conf->cqm_rssi_hyst;
 +
 +	if (!connect) {
 +		SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BCN_FILTER_OFFLOAD_P1);
 +		SET_BCN_FILTER_OFFLOAD_P1_ENABLE(h2c_pkt, connect);
 +		rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +
 +		return;
 +	}
 +
 +	if (!si)
 +		return;
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BCN_FILTER_OFFLOAD_P0);
 +	ether_addr_copy(&h2c_pkt[1], bss_conf->bssid);
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +
 +	memset(h2c_pkt, 0, sizeof(h2c_pkt));
 +	thold = clamp_t(s32, thold + rssi_offset, rssi_min, rssi_max);
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_BCN_FILTER_OFFLOAD_P1);
 +	SET_BCN_FILTER_OFFLOAD_P1_ENABLE(h2c_pkt, connect);
 +	SET_BCN_FILTER_OFFLOAD_P1_OFFLOAD_MODE(h2c_pkt,
 +					       BCN_FILTER_OFFLOAD_MODE_DEFAULT);
 +	SET_BCN_FILTER_OFFLOAD_P1_THRESHOLD(h2c_pkt, thold);
 +	SET_BCN_FILTER_OFFLOAD_P1_BCN_LOSS_CNT(h2c_pkt, BCN_LOSS_CNT);
 +	SET_BCN_FILTER_OFFLOAD_P1_MACID(h2c_pkt, si->mac_id);
 +	SET_BCN_FILTER_OFFLOAD_P1_HYST(h2c_pkt, hyst);
 +	SET_BCN_FILTER_OFFLOAD_P1_BCN_INTERVAL(h2c_pkt, bss_conf->beacon_int);
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_set_pwr_mode(struct rtw_dev *rtwdev)
 +{
 +	struct rtw_lps_conf *conf = &rtwdev->lps_conf;
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_SET_PWR_MODE);
 +
 +	SET_PWR_MODE_SET_MODE(h2c_pkt, conf->mode);
 +	SET_PWR_MODE_SET_RLBM(h2c_pkt, conf->rlbm);
 +	SET_PWR_MODE_SET_SMART_PS(h2c_pkt, conf->smart_ps);
 +	SET_PWR_MODE_SET_AWAKE_INTERVAL(h2c_pkt, conf->awake_interval);
 +	SET_PWR_MODE_SET_PORT_ID(h2c_pkt, conf->port_id);
 +	SET_PWR_MODE_SET_PWR_STATE(h2c_pkt, conf->state);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_set_keep_alive_cmd(struct rtw_dev *rtwdev, bool enable)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +	struct rtw_fw_wow_keep_alive_para mode = {
 +		.adopt = true,
 +		.pkt_type = KEEP_ALIVE_NULL_PKT,
 +		.period = 5,
 +	};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_KEEP_ALIVE);
 +	SET_KEEP_ALIVE_ENABLE(h2c_pkt, enable);
 +	SET_KEEP_ALIVE_ADOPT(h2c_pkt, mode.adopt);
 +	SET_KEEP_ALIVE_PKT_TYPE(h2c_pkt, mode.pkt_type);
 +	SET_KEEP_ALIVE_CHECK_PERIOD(h2c_pkt, mode.period);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_set_disconnect_decision_cmd(struct rtw_dev *rtwdev, bool enable)
 +{
 +	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +	struct rtw_fw_wow_disconnect_para mode = {
 +		.adopt = true,
 +		.period = 30,
 +		.retry_count = 5,
 +	};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_DISCONNECT_DECISION);
 +
 +	if (test_bit(RTW_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags)) {
 +		SET_DISCONNECT_DECISION_ENABLE(h2c_pkt, enable);
 +		SET_DISCONNECT_DECISION_ADOPT(h2c_pkt, mode.adopt);
 +		SET_DISCONNECT_DECISION_CHECK_PERIOD(h2c_pkt, mode.period);
 +		SET_DISCONNECT_DECISION_TRY_PKT_NUM(h2c_pkt, mode.retry_count);
 +	}
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_set_wowlan_ctrl_cmd(struct rtw_dev *rtwdev, bool enable)
 +{
 +	struct rtw_wow_param *rtw_wow = &rtwdev->wow;
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_WOWLAN);
 +
 +	SET_WOWLAN_FUNC_ENABLE(h2c_pkt, enable);
 +	if (rtw_wow_mgd_linked(rtwdev)) {
 +		if (test_bit(RTW_WOW_FLAG_EN_MAGIC_PKT, rtw_wow->flags))
 +			SET_WOWLAN_MAGIC_PKT_ENABLE(h2c_pkt, enable);
 +		if (test_bit(RTW_WOW_FLAG_EN_DISCONNECT, rtw_wow->flags))
 +			SET_WOWLAN_DEAUTH_WAKEUP_ENABLE(h2c_pkt, enable);
 +		if (test_bit(RTW_WOW_FLAG_EN_REKEY_PKT, rtw_wow->flags))
 +			SET_WOWLAN_REKEY_WAKEUP_ENABLE(h2c_pkt, enable);
 +		if (rtw_wow->pattern_cnt)
 +			SET_WOWLAN_PATTERN_MATCH_ENABLE(h2c_pkt, enable);
 +	}
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_set_aoac_global_info_cmd(struct rtw_dev *rtwdev,
 +				     u8 pairwise_key_enc,
 +				     u8 group_key_enc)
 +{
 +	u8 h2c_pkt[H2C_PKT_SIZE] = {0};
 +
 +	SET_H2C_CMD_ID_CLASS(h2c_pkt, H2C_CMD_AOAC_GLOBAL_INFO);
 +
 +	SET_AOAC_GLOBAL_INFO_PAIRWISE_ENC_ALG(h2c_pkt, pairwise_key_enc);
 +	SET_AOAC_GLOBAL_INFO_GROUP_ENC_ALG(h2c_pkt, group_key_enc);
 +
 +	rtw_fw_send_h2c_command(rtwdev, h2c_pkt);
 +}
 +
 +void rtw_fw_set_remote_wake_ctrl_cmd(struct rtw_dev *rtwdev, bool enable)
*** 7865 LINES SKIPPED ***


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69e39390.22a69.6427e8b>