brintos

brintos / linux-shallow public Read only

0
0
Text · 83.1 KiB · 864246f Raw
3194 lines · c
1// SPDX-License-Identifier: ISC2/* Copyright (C) 2020 MediaTek Inc. */3 4#include <linux/firmware.h>5#include "mt76_connac2_mac.h"6#include "mt76_connac_mcu.h"7 8int mt76_connac_mcu_start_firmware(struct mt76_dev *dev, u32 addr, u32 option)9{10	struct {11		__le32 option;12		__le32 addr;13	} req = {14		.option = cpu_to_le32(option),15		.addr = cpu_to_le32(addr),16	};17 18	return mt76_mcu_send_msg(dev, MCU_CMD(FW_START_REQ), &req,19				 sizeof(req), true);20}21EXPORT_SYMBOL_GPL(mt76_connac_mcu_start_firmware);22 23int mt76_connac_mcu_patch_sem_ctrl(struct mt76_dev *dev, bool get)24{25	u32 op = get ? PATCH_SEM_GET : PATCH_SEM_RELEASE;26	struct {27		__le32 op;28	} req = {29		.op = cpu_to_le32(op),30	};31 32	return mt76_mcu_send_msg(dev, MCU_CMD(PATCH_SEM_CONTROL),33				 &req, sizeof(req), true);34}35EXPORT_SYMBOL_GPL(mt76_connac_mcu_patch_sem_ctrl);36 37int mt76_connac_mcu_start_patch(struct mt76_dev *dev)38{39	struct {40		u8 check_crc;41		u8 reserved[3];42	} req = {43		.check_crc = 0,44	};45 46	return mt76_mcu_send_msg(dev, MCU_CMD(PATCH_FINISH_REQ),47				 &req, sizeof(req), true);48}49EXPORT_SYMBOL_GPL(mt76_connac_mcu_start_patch);50 51#define MCU_PATCH_ADDRESS	0x20000052 53int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,54				  u32 mode)55{56	struct {57		__le32 addr;58		__le32 len;59		__le32 mode;60	} req = {61		.addr = cpu_to_le32(addr),62		.len = cpu_to_le32(len),63		.mode = cpu_to_le32(mode),64	};65	int cmd;66 67	if ((!is_connac_v1(dev) && addr == MCU_PATCH_ADDRESS) ||68	    (is_mt7921(dev) && addr == 0x900000) ||69	    (is_mt7925(dev) && (addr == 0x900000 || addr == 0xe0002800)) ||70	    (is_mt7996(dev) && addr == 0x900000) ||71	    (is_mt7992(dev) && addr == 0x900000))72		cmd = MCU_CMD(PATCH_START_REQ);73	else74		cmd = MCU_CMD(TARGET_ADDRESS_LEN_REQ);75 76	return mt76_mcu_send_msg(dev, cmd, &req, sizeof(req), true);77}78EXPORT_SYMBOL_GPL(mt76_connac_mcu_init_download);79 80int mt76_connac_mcu_set_channel_domain(struct mt76_phy *phy)81{82	int len, i, n_max_channels, n_2ch = 0, n_5ch = 0, n_6ch = 0;83	struct mt76_connac_mcu_channel_domain {84		u8 alpha2[4]; /* regulatory_request.alpha2 */85		u8 bw_2g; /* BW_20_40M		086			   * BW_20M		187			   * BW_20_40_80M	288			   * BW_20_40_80_160M	389			   * BW_20_40_80_8080M	490			   */91		u8 bw_5g;92		u8 bw_6g;93		u8 pad;94		u8 n_2ch;95		u8 n_5ch;96		u8 n_6ch;97		u8 pad2;98	} __packed hdr = {99		.bw_2g = 0,100		.bw_5g = 3, /* BW_20_40_80_160M */101		.bw_6g = 3,102	};103	struct mt76_connac_mcu_chan {104		__le16 hw_value;105		__le16 pad;106		__le32 flags;107	} __packed channel;108	struct mt76_dev *dev = phy->dev;109	struct ieee80211_channel *chan;110	struct sk_buff *skb;111 112	n_max_channels = phy->sband_2g.sband.n_channels +113			 phy->sband_5g.sband.n_channels +114			 phy->sband_6g.sband.n_channels;115	len = sizeof(hdr) + n_max_channels * sizeof(channel);116 117	skb = mt76_mcu_msg_alloc(dev, NULL, len);118	if (!skb)119		return -ENOMEM;120 121	skb_reserve(skb, sizeof(hdr));122 123	for (i = 0; i < phy->sband_2g.sband.n_channels; i++) {124		chan = &phy->sband_2g.sband.channels[i];125		if (chan->flags & IEEE80211_CHAN_DISABLED)126			continue;127 128		channel.hw_value = cpu_to_le16(chan->hw_value);129		channel.flags = cpu_to_le32(chan->flags);130		channel.pad = 0;131 132		skb_put_data(skb, &channel, sizeof(channel));133		n_2ch++;134	}135	for (i = 0; i < phy->sband_5g.sband.n_channels; i++) {136		chan = &phy->sband_5g.sband.channels[i];137		if (chan->flags & IEEE80211_CHAN_DISABLED)138			continue;139 140		channel.hw_value = cpu_to_le16(chan->hw_value);141		channel.flags = cpu_to_le32(chan->flags);142		channel.pad = 0;143 144		skb_put_data(skb, &channel, sizeof(channel));145		n_5ch++;146	}147	for (i = 0; i < phy->sband_6g.sband.n_channels; i++) {148		chan = &phy->sband_6g.sband.channels[i];149		if (chan->flags & IEEE80211_CHAN_DISABLED)150			continue;151 152		channel.hw_value = cpu_to_le16(chan->hw_value);153		channel.flags = cpu_to_le32(chan->flags);154		channel.pad = 0;155 156		skb_put_data(skb, &channel, sizeof(channel));157		n_6ch++;158	}159 160	BUILD_BUG_ON(sizeof(dev->alpha2) > sizeof(hdr.alpha2));161	memcpy(hdr.alpha2, dev->alpha2, sizeof(dev->alpha2));162	hdr.n_2ch = n_2ch;163	hdr.n_5ch = n_5ch;164	hdr.n_6ch = n_6ch;165 166	memcpy(__skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));167 168	return mt76_mcu_skb_send_msg(dev, skb, MCU_CE_CMD(SET_CHAN_DOMAIN),169				     false);170}171EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_channel_domain);172 173int mt76_connac_mcu_set_mac_enable(struct mt76_dev *dev, int band, bool enable,174				   bool hdr_trans)175{176	struct {177		u8 enable;178		u8 band;179		u8 rsv[2];180	} __packed req_mac = {181		.enable = enable,182		.band = band,183	};184 185	return mt76_mcu_send_msg(dev, MCU_EXT_CMD(MAC_INIT_CTRL), &req_mac,186				 sizeof(req_mac), true);187}188EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_mac_enable);189 190int mt76_connac_mcu_set_vif_ps(struct mt76_dev *dev, struct ieee80211_vif *vif)191{192	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;193	struct {194		u8 bss_idx;195		u8 ps_state; /* 0: device awake196			      * 1: static power save197			      * 2: dynamic power saving198			      */199	} req = {200		.bss_idx = mvif->idx,201		.ps_state = vif->cfg.ps ? 2 : 0,202	};203 204	if (vif->type != NL80211_IFTYPE_STATION)205		return -EOPNOTSUPP;206 207	return mt76_mcu_send_msg(dev, MCU_CE_CMD(SET_PS_PROFILE),208				 &req, sizeof(req), false);209}210EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_vif_ps);211 212int mt76_connac_mcu_set_rts_thresh(struct mt76_dev *dev, u32 val, u8 band)213{214	struct {215		u8 prot_idx;216		u8 band;217		u8 rsv[2];218		__le32 len_thresh;219		__le32 pkt_thresh;220	} __packed req = {221		.prot_idx = 1,222		.band = band,223		.len_thresh = cpu_to_le32(val),224		.pkt_thresh = cpu_to_le32(0x2),225	};226 227	return mt76_mcu_send_msg(dev, MCU_EXT_CMD(PROTECT_CTRL), &req,228				 sizeof(req), true);229}230EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rts_thresh);231 232void mt76_connac_mcu_beacon_loss_iter(void *priv, u8 *mac,233				      struct ieee80211_vif *vif)234{235	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;236	struct mt76_connac_beacon_loss_event *event = priv;237 238	if (mvif->idx != event->bss_idx)239		return;240 241	if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER))242		return;243 244	ieee80211_beacon_loss(vif);245}246EXPORT_SYMBOL_GPL(mt76_connac_mcu_beacon_loss_iter);247 248struct tlv *249mt76_connac_mcu_add_nested_tlv(struct sk_buff *skb, int tag, int len,250			       void *sta_ntlv, void *sta_wtbl)251{252	struct sta_ntlv_hdr *ntlv_hdr = sta_ntlv;253	struct tlv *sta_hdr = sta_wtbl;254	struct tlv *ptlv, tlv = {255		.tag = cpu_to_le16(tag),256		.len = cpu_to_le16(len),257	};258	u16 ntlv;259 260	ptlv = skb_put_zero(skb, len);261	memcpy(ptlv, &tlv, sizeof(tlv));262 263	ntlv = le16_to_cpu(ntlv_hdr->tlv_num);264	ntlv_hdr->tlv_num = cpu_to_le16(ntlv + 1);265 266	if (sta_hdr) {267		len += le16_to_cpu(sta_hdr->len);268		sta_hdr->len = cpu_to_le16(len);269	}270 271	return ptlv;272}273EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_nested_tlv);274 275struct sk_buff *276__mt76_connac_mcu_alloc_sta_req(struct mt76_dev *dev, struct mt76_vif *mvif,277				struct mt76_wcid *wcid, int len)278{279	struct sta_req_hdr hdr = {280		.bss_idx = mvif->idx,281		.muar_idx = wcid ? mvif->omac_idx : 0,282		.is_tlv_append = 1,283	};284	struct sk_buff *skb;285 286	if (wcid && !wcid->sta && !wcid->sta_disabled)287		hdr.muar_idx = 0xe;288 289	mt76_connac_mcu_get_wlan_idx(dev, wcid, &hdr.wlan_idx_lo,290				     &hdr.wlan_idx_hi);291	skb = mt76_mcu_msg_alloc(dev, NULL, len);292	if (!skb)293		return ERR_PTR(-ENOMEM);294 295	skb_put_data(skb, &hdr, sizeof(hdr));296 297	return skb;298}299EXPORT_SYMBOL_GPL(__mt76_connac_mcu_alloc_sta_req);300 301struct wtbl_req_hdr *302mt76_connac_mcu_alloc_wtbl_req(struct mt76_dev *dev, struct mt76_wcid *wcid,303			       int cmd, void *sta_wtbl, struct sk_buff **skb)304{305	struct tlv *sta_hdr = sta_wtbl;306	struct wtbl_req_hdr hdr = {307		.operation = cmd,308	};309	struct sk_buff *nskb = *skb;310 311	mt76_connac_mcu_get_wlan_idx(dev, wcid, &hdr.wlan_idx_lo,312				     &hdr.wlan_idx_hi);313	if (!nskb) {314		nskb = mt76_mcu_msg_alloc(dev, NULL,315					  MT76_CONNAC_WTBL_UPDATE_MAX_SIZE);316		if (!nskb)317			return ERR_PTR(-ENOMEM);318 319		*skb = nskb;320	}321 322	if (sta_hdr)323		le16_add_cpu(&sta_hdr->len, sizeof(hdr));324 325	return skb_put_data(nskb, &hdr, sizeof(hdr));326}327EXPORT_SYMBOL_GPL(mt76_connac_mcu_alloc_wtbl_req);328 329void mt76_connac_mcu_bss_omac_tlv(struct sk_buff *skb,330				  struct ieee80211_vif *vif)331{332	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;333	u8 omac_idx = mvif->omac_idx;334	struct bss_info_omac *omac;335	struct tlv *tlv;336	u32 type = 0;337 338	switch (vif->type) {339	case NL80211_IFTYPE_MONITOR:340	case NL80211_IFTYPE_MESH_POINT:341	case NL80211_IFTYPE_AP:342		if (vif->p2p)343			type = CONNECTION_P2P_GO;344		else345			type = CONNECTION_INFRA_AP;346		break;347	case NL80211_IFTYPE_STATION:348		if (vif->p2p)349			type = CONNECTION_P2P_GC;350		else351			type = CONNECTION_INFRA_STA;352		break;353	case NL80211_IFTYPE_ADHOC:354		type = CONNECTION_IBSS_ADHOC;355		break;356	default:357		WARN_ON(1);358		break;359	}360 361	tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_OMAC, sizeof(*omac));362 363	omac = (struct bss_info_omac *)tlv;364	omac->conn_type = cpu_to_le32(type);365	omac->omac_idx = mvif->omac_idx;366	omac->band_idx = mvif->band_idx;367	omac->hw_bss_idx = omac_idx > EXT_BSSID_START ? HW_BSSID_0 : omac_idx;368}369EXPORT_SYMBOL_GPL(mt76_connac_mcu_bss_omac_tlv);370 371void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,372				   struct ieee80211_vif *vif,373				   struct ieee80211_link_sta *link_sta,374				   int conn_state, bool newly)375{376	struct sta_rec_basic *basic;377	struct tlv *tlv;378	int conn_type;379 380	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BASIC, sizeof(*basic));381 382	basic = (struct sta_rec_basic *)tlv;383	basic->extra_info = cpu_to_le16(EXTRA_INFO_VER);384 385	if (newly && conn_state != CONN_STATE_DISCONNECT)386		basic->extra_info |= cpu_to_le16(EXTRA_INFO_NEW);387	basic->conn_state = conn_state;388 389	if (!link_sta) {390		basic->conn_type = cpu_to_le32(CONNECTION_INFRA_BC);391 392		if (vif->type == NL80211_IFTYPE_STATION &&393		    !is_zero_ether_addr(vif->bss_conf.bssid)) {394			memcpy(basic->peer_addr, vif->bss_conf.bssid, ETH_ALEN);395			basic->aid = cpu_to_le16(vif->cfg.aid);396		} else {397			eth_broadcast_addr(basic->peer_addr);398		}399		return;400	}401 402	switch (vif->type) {403	case NL80211_IFTYPE_MESH_POINT:404	case NL80211_IFTYPE_AP:405		if (vif->p2p && !is_mt7921(dev))406			conn_type = CONNECTION_P2P_GC;407		else408			conn_type = CONNECTION_INFRA_STA;409		basic->conn_type = cpu_to_le32(conn_type);410		basic->aid = cpu_to_le16(link_sta->sta->aid);411		break;412	case NL80211_IFTYPE_STATION:413		if (vif->p2p && !is_mt7921(dev))414			conn_type = CONNECTION_P2P_GO;415		else416			conn_type = CONNECTION_INFRA_AP;417		basic->conn_type = cpu_to_le32(conn_type);418		basic->aid = cpu_to_le16(vif->cfg.aid);419		break;420	case NL80211_IFTYPE_ADHOC:421		basic->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC);422		basic->aid = cpu_to_le16(link_sta->sta->aid);423		break;424	default:425		WARN_ON(1);426		break;427	}428 429	memcpy(basic->peer_addr, link_sta->addr, ETH_ALEN);430	basic->qos = link_sta->sta->wme;431}432EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_basic_tlv);433 434void mt76_connac_mcu_sta_uapsd(struct sk_buff *skb, struct ieee80211_vif *vif,435			       struct ieee80211_sta *sta)436{437	struct sta_rec_uapsd *uapsd;438	struct tlv *tlv;439 440	if (vif->type != NL80211_IFTYPE_AP || !sta->wme)441		return;442 443	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_APPS, sizeof(*uapsd));444	uapsd = (struct sta_rec_uapsd *)tlv;445 446	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO) {447		uapsd->dac_map |= BIT(3);448		uapsd->tac_map |= BIT(3);449	}450	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VI) {451		uapsd->dac_map |= BIT(2);452		uapsd->tac_map |= BIT(2);453	}454	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BE) {455		uapsd->dac_map |= BIT(1);456		uapsd->tac_map |= BIT(1);457	}458	if (sta->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_BK) {459		uapsd->dac_map |= BIT(0);460		uapsd->tac_map |= BIT(0);461	}462	uapsd->max_sp = sta->max_sp;463}464EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_uapsd);465 466void mt76_connac_mcu_wtbl_hdr_trans_tlv(struct sk_buff *skb,467					struct ieee80211_vif *vif,468					struct mt76_wcid *wcid,469					void *sta_wtbl, void *wtbl_tlv)470{471	struct wtbl_hdr_trans *htr;472	struct tlv *tlv;473 474	tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_HDR_TRANS,475					     sizeof(*htr),476					     wtbl_tlv, sta_wtbl);477	htr = (struct wtbl_hdr_trans *)tlv;478	htr->no_rx_trans = true;479 480	if (vif->type == NL80211_IFTYPE_STATION)481		htr->to_ds = true;482	else483		htr->from_ds = true;484 485	if (!wcid)486		return;487 488	htr->no_rx_trans = !test_bit(MT_WCID_FLAG_HDR_TRANS, &wcid->flags);489	if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags)) {490		htr->to_ds = true;491		htr->from_ds = true;492	}493}494EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_hdr_trans_tlv);495 496int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev,497					 struct ieee80211_vif *vif,498					 struct mt76_wcid *wcid, int cmd)499{500	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;501	struct wtbl_req_hdr *wtbl_hdr;502	struct tlv *sta_wtbl;503	struct sk_buff *skb;504 505	skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid);506	if (IS_ERR(skb))507		return PTR_ERR(skb);508 509	sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,510					   sizeof(struct tlv));511 512	wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid, WTBL_SET,513						  sta_wtbl, &skb);514	if (IS_ERR(wtbl_hdr))515		return PTR_ERR(wtbl_hdr);516 517	mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, sta_wtbl, wtbl_hdr);518 519	return mt76_mcu_skb_send_msg(dev, skb, cmd, true);520}521EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_update_hdr_trans);522 523int mt76_connac_mcu_wtbl_update_hdr_trans(struct mt76_dev *dev,524					  struct ieee80211_vif *vif,525					  struct ieee80211_sta *sta)526{527	struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;528	struct wtbl_req_hdr *wtbl_hdr;529	struct sk_buff *skb = NULL;530 531	wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid, WTBL_SET, NULL,532						  &skb);533	if (IS_ERR(wtbl_hdr))534		return PTR_ERR(wtbl_hdr);535 536	mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, vif, wcid, NULL, wtbl_hdr);537 538	return mt76_mcu_skb_send_msg(dev, skb, MCU_EXT_CMD(WTBL_UPDATE), true);539}540EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_update_hdr_trans);541 542void mt76_connac_mcu_wtbl_generic_tlv(struct mt76_dev *dev,543				      struct sk_buff *skb,544				      struct ieee80211_vif *vif,545				      struct ieee80211_sta *sta,546				      void *sta_wtbl, void *wtbl_tlv)547{548	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;549	struct wtbl_generic *generic;550	struct wtbl_rx *rx;551	struct wtbl_spe *spe;552	struct tlv *tlv;553 554	tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_GENERIC,555					     sizeof(*generic),556					     wtbl_tlv, sta_wtbl);557 558	generic = (struct wtbl_generic *)tlv;559 560	if (sta) {561		if (vif->type == NL80211_IFTYPE_STATION)562			generic->partial_aid = cpu_to_le16(vif->cfg.aid);563		else564			generic->partial_aid = cpu_to_le16(sta->aid);565		memcpy(generic->peer_addr, sta->addr, ETH_ALEN);566		generic->muar_idx = mvif->omac_idx;567		generic->qos = sta->wme;568	} else {569		if (!is_connac_v1(dev) && vif->type == NL80211_IFTYPE_STATION)570			memcpy(generic->peer_addr, vif->bss_conf.bssid,571			       ETH_ALEN);572		else573			eth_broadcast_addr(generic->peer_addr);574 575		generic->muar_idx = 0xe;576	}577 578	tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_RX, sizeof(*rx),579					     wtbl_tlv, sta_wtbl);580 581	rx = (struct wtbl_rx *)tlv;582	rx->rca1 = sta ? vif->type != NL80211_IFTYPE_AP : 1;583	rx->rca2 = 1;584	rx->rv = 1;585 586	if (!is_connac_v1(dev))587		return;588 589	tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_SPE, sizeof(*spe),590					     wtbl_tlv, sta_wtbl);591	spe = (struct wtbl_spe *)tlv;592	spe->spe_idx = 24;593}594EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_generic_tlv);595 596static void597mt76_connac_mcu_sta_amsdu_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,598			      struct ieee80211_vif *vif)599{600	struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;601	struct sta_rec_amsdu *amsdu;602	struct tlv *tlv;603 604	if (vif->type != NL80211_IFTYPE_AP &&605	    vif->type != NL80211_IFTYPE_STATION)606		return;607 608	if (!sta->deflink.agg.max_amsdu_len)609		return;610 611	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HW_AMSDU, sizeof(*amsdu));612	amsdu = (struct sta_rec_amsdu *)tlv;613	amsdu->max_amsdu_num = 8;614	amsdu->amsdu_en = true;615	amsdu->max_mpdu_size = sta->deflink.agg.max_amsdu_len >=616			       IEEE80211_MAX_MPDU_LEN_VHT_7991;617 618	wcid->amsdu = true;619}620 621#define HE_PHY(p, c)	u8_get_bits(c, IEEE80211_HE_PHY_##p)622#define HE_MAC(m, c)	u8_get_bits(c, IEEE80211_HE_MAC_##m)623static void624mt76_connac_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)625{626	struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;627	struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;628	struct sta_rec_he *he;629	struct tlv *tlv;630	u32 cap = 0;631 632	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE, sizeof(*he));633 634	he = (struct sta_rec_he *)tlv;635 636	if (elem->mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_HTC_HE)637		cap |= STA_REC_HE_CAP_HTC;638 639	if (elem->mac_cap_info[2] & IEEE80211_HE_MAC_CAP2_BSR)640		cap |= STA_REC_HE_CAP_BSR;641 642	if (elem->mac_cap_info[3] & IEEE80211_HE_MAC_CAP3_OMI_CONTROL)643		cap |= STA_REC_HE_CAP_OM;644 645	if (elem->mac_cap_info[4] & IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU)646		cap |= STA_REC_HE_CAP_AMSDU_IN_AMPDU;647 648	if (elem->mac_cap_info[4] & IEEE80211_HE_MAC_CAP4_BQR)649		cap |= STA_REC_HE_CAP_BQR;650 651	if (elem->phy_cap_info[0] &652	    (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G |653	     IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G))654		cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT;655 656	if (elem->phy_cap_info[1] &657	    IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)658		cap |= STA_REC_HE_CAP_LDPC;659 660	if (elem->phy_cap_info[1] &661	    IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US)662		cap |= STA_REC_HE_CAP_SU_PPDU_1LTF_8US_GI;663 664	if (elem->phy_cap_info[2] &665	    IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US)666		cap |= STA_REC_HE_CAP_NDP_4LTF_3DOT2MS_GI;667 668	if (elem->phy_cap_info[2] &669	    IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ)670		cap |= STA_REC_HE_CAP_LE_EQ_80M_TX_STBC;671 672	if (elem->phy_cap_info[2] &673	    IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)674		cap |= STA_REC_HE_CAP_LE_EQ_80M_RX_STBC;675 676	if (elem->phy_cap_info[6] &677	    IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE)678		cap |= STA_REC_HE_CAP_PARTIAL_BW_EXT_RANGE;679 680	if (elem->phy_cap_info[7] &681	    IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI)682		cap |= STA_REC_HE_CAP_SU_MU_PPDU_4LTF_8US_GI;683 684	if (elem->phy_cap_info[7] &685	    IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ)686		cap |= STA_REC_HE_CAP_GT_80M_TX_STBC;687 688	if (elem->phy_cap_info[7] &689	    IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ)690		cap |= STA_REC_HE_CAP_GT_80M_RX_STBC;691 692	if (elem->phy_cap_info[8] &693	    IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI)694		cap |= STA_REC_HE_CAP_ER_SU_PPDU_4LTF_8US_GI;695 696	if (elem->phy_cap_info[8] &697	    IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI)698		cap |= STA_REC_HE_CAP_ER_SU_PPDU_1LTF_8US_GI;699 700	if (elem->phy_cap_info[9] &701	    IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK)702		cap |= STA_REC_HE_CAP_TRIG_CQI_FK;703 704	if (elem->phy_cap_info[9] &705	    IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU)706		cap |= STA_REC_HE_CAP_TX_1024QAM_UNDER_RU242;707 708	if (elem->phy_cap_info[9] &709	    IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU)710		cap |= STA_REC_HE_CAP_RX_1024QAM_UNDER_RU242;711 712	he->he_cap = cpu_to_le32(cap);713 714	switch (sta->deflink.bandwidth) {715	case IEEE80211_STA_RX_BW_160:716		if (elem->phy_cap_info[0] &717		    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)718			he->max_nss_mcs[CMD_HE_MCS_BW8080] =719				he_cap->he_mcs_nss_supp.rx_mcs_80p80;720 721		he->max_nss_mcs[CMD_HE_MCS_BW160] =722				he_cap->he_mcs_nss_supp.rx_mcs_160;723		fallthrough;724	default:725		he->max_nss_mcs[CMD_HE_MCS_BW80] =726				he_cap->he_mcs_nss_supp.rx_mcs_80;727		break;728	}729 730	he->t_frame_dur =731		HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]);732	he->max_ampdu_exp =733		HE_MAC(CAP3_MAX_AMPDU_LEN_EXP_MASK, elem->mac_cap_info[3]);734 735	he->bw_set =736		HE_PHY(CAP0_CHANNEL_WIDTH_SET_MASK, elem->phy_cap_info[0]);737	he->device_class =738		HE_PHY(CAP1_DEVICE_CLASS_A, elem->phy_cap_info[1]);739	he->punc_pream_rx =740		HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]);741 742	he->dcm_tx_mode =743		HE_PHY(CAP3_DCM_MAX_CONST_TX_MASK, elem->phy_cap_info[3]);744	he->dcm_tx_max_nss =745		HE_PHY(CAP3_DCM_MAX_TX_NSS_2, elem->phy_cap_info[3]);746	he->dcm_rx_mode =747		HE_PHY(CAP3_DCM_MAX_CONST_RX_MASK, elem->phy_cap_info[3]);748	he->dcm_rx_max_nss =749		HE_PHY(CAP3_DCM_MAX_RX_NSS_2, elem->phy_cap_info[3]);750	he->dcm_rx_max_nss =751		HE_PHY(CAP8_DCM_MAX_RU_MASK, elem->phy_cap_info[8]);752 753	he->pkt_ext = 2;754}755 756void757mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta)758{759	struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;760	struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;761	struct sta_rec_he_v2 *he;762	struct tlv *tlv;763 764	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE_V2, sizeof(*he));765 766	he = (struct sta_rec_he_v2 *)tlv;767	memcpy(he->he_phy_cap, elem->phy_cap_info, sizeof(he->he_phy_cap));768	memcpy(he->he_mac_cap, elem->mac_cap_info, sizeof(he->he_mac_cap));769 770	switch (sta->deflink.bandwidth) {771	case IEEE80211_STA_RX_BW_160:772		if (elem->phy_cap_info[0] &773		    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)774			he->max_nss_mcs[CMD_HE_MCS_BW8080] =775				he_cap->he_mcs_nss_supp.rx_mcs_80p80;776 777		he->max_nss_mcs[CMD_HE_MCS_BW160] =778				he_cap->he_mcs_nss_supp.rx_mcs_160;779		fallthrough;780	default:781		he->max_nss_mcs[CMD_HE_MCS_BW80] =782				he_cap->he_mcs_nss_supp.rx_mcs_80;783		break;784	}785 786	he->pkt_ext = IEEE80211_HE_PHY_CAP9_NOMINAL_PKT_PADDING_16US;787}788EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_he_tlv_v2);789 790u8791mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,792			    enum nl80211_band band,793			    struct ieee80211_link_sta *link_sta)794{795	struct ieee80211_sta_ht_cap *ht_cap;796	struct ieee80211_sta_vht_cap *vht_cap;797	const struct ieee80211_sta_he_cap *he_cap;798	const struct ieee80211_sta_eht_cap *eht_cap;799	u8 mode = 0;800 801	if (link_sta) {802		ht_cap = &link_sta->ht_cap;803		vht_cap = &link_sta->vht_cap;804		he_cap = &link_sta->he_cap;805		eht_cap = &link_sta->eht_cap;806	} else {807		struct ieee80211_supported_band *sband;808 809		sband = mphy->hw->wiphy->bands[band];810		ht_cap = &sband->ht_cap;811		vht_cap = &sband->vht_cap;812		he_cap = ieee80211_get_he_iftype_cap(sband, vif->type);813		eht_cap = ieee80211_get_eht_iftype_cap(sband, vif->type);814	}815 816	if (band == NL80211_BAND_2GHZ) {817		mode |= PHY_TYPE_BIT_HR_DSSS | PHY_TYPE_BIT_ERP;818 819		if (ht_cap->ht_supported)820			mode |= PHY_TYPE_BIT_HT;821 822		if (he_cap && he_cap->has_he)823			mode |= PHY_TYPE_BIT_HE;824 825		if (eht_cap && eht_cap->has_eht)826			mode |= PHY_TYPE_BIT_BE;827	} else if (band == NL80211_BAND_5GHZ || band == NL80211_BAND_6GHZ) {828		mode |= PHY_TYPE_BIT_OFDM;829 830		if (ht_cap->ht_supported)831			mode |= PHY_TYPE_BIT_HT;832 833		if (vht_cap->vht_supported)834			mode |= PHY_TYPE_BIT_VHT;835 836		if (he_cap && he_cap->has_he)837			mode |= PHY_TYPE_BIT_HE;838 839		if (eht_cap && eht_cap->has_eht)840			mode |= PHY_TYPE_BIT_BE;841	}842 843	return mode;844}845EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode_v2);846 847void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,848			     struct ieee80211_sta *sta,849			     struct ieee80211_vif *vif,850			     u8 rcpi, u8 sta_state)851{852	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;853	struct cfg80211_chan_def *chandef = mvif->ctx ?854					    &mvif->ctx->def : &mphy->chandef;855	enum nl80211_band band = chandef->chan->band;856	struct mt76_dev *dev = mphy->dev;857	struct sta_rec_ra_info *ra_info;858	struct sta_rec_state *state;859	struct sta_rec_phy *phy;860	struct tlv *tlv;861	u16 supp_rates;862 863	/* starec ht */864	if (sta->deflink.ht_cap.ht_supported) {865		struct sta_rec_ht *ht;866 867		tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht));868		ht = (struct sta_rec_ht *)tlv;869		ht->ht_cap = cpu_to_le16(sta->deflink.ht_cap.cap);870	}871 872	/* starec vht */873	if (sta->deflink.vht_cap.vht_supported) {874		struct sta_rec_vht *vht;875		int len;876 877		len = is_mt7921(dev) ? sizeof(*vht) : sizeof(*vht) - 4;878		tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_VHT, len);879		vht = (struct sta_rec_vht *)tlv;880		vht->vht_cap = cpu_to_le32(sta->deflink.vht_cap.cap);881		vht->vht_rx_mcs_map = sta->deflink.vht_cap.vht_mcs.rx_mcs_map;882		vht->vht_tx_mcs_map = sta->deflink.vht_cap.vht_mcs.tx_mcs_map;883	}884 885	/* starec uapsd */886	mt76_connac_mcu_sta_uapsd(skb, vif, sta);887 888	if (!is_mt7921(dev))889		return;890 891	if (sta->deflink.ht_cap.ht_supported || sta->deflink.he_cap.has_he)892		mt76_connac_mcu_sta_amsdu_tlv(skb, sta, vif);893 894	/* starec he */895	if (sta->deflink.he_cap.has_he) {896		mt76_connac_mcu_sta_he_tlv(skb, sta);897		mt76_connac_mcu_sta_he_tlv_v2(skb, sta);898		if (band == NL80211_BAND_6GHZ &&899		    sta_state == MT76_STA_INFO_STATE_ASSOC) {900			struct sta_rec_he_6g_capa *he_6g_capa;901 902			tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_HE_6G,903						      sizeof(*he_6g_capa));904			he_6g_capa = (struct sta_rec_he_6g_capa *)tlv;905			he_6g_capa->capa = sta->deflink.he_6ghz_capa.capa;906		}907	}908 909	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_PHY, sizeof(*phy));910	phy = (struct sta_rec_phy *)tlv;911	phy->phy_type = mt76_connac_get_phy_mode_v2(mphy, vif, band,912						    &sta->deflink);913	phy->basic_rate = cpu_to_le16((u16)vif->bss_conf.basic_rates);914	phy->rcpi = rcpi;915	phy->ampdu = FIELD_PREP(IEEE80211_HT_AMPDU_PARM_FACTOR,916				sta->deflink.ht_cap.ampdu_factor) |917		     FIELD_PREP(IEEE80211_HT_AMPDU_PARM_DENSITY,918				sta->deflink.ht_cap.ampdu_density);919 920	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_RA, sizeof(*ra_info));921	ra_info = (struct sta_rec_ra_info *)tlv;922 923	supp_rates = sta->deflink.supp_rates[band];924	if (band == NL80211_BAND_2GHZ)925		supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates >> 4) |926			     FIELD_PREP(RA_LEGACY_CCK, supp_rates & 0xf);927	else928		supp_rates = FIELD_PREP(RA_LEGACY_OFDM, supp_rates);929 930	ra_info->legacy = cpu_to_le16(supp_rates);931 932	if (sta->deflink.ht_cap.ht_supported)933		memcpy(ra_info->rx_mcs_bitmask,934		       sta->deflink.ht_cap.mcs.rx_mask,935		       HT_MCS_MASK_NUM);936 937	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_STATE, sizeof(*state));938	state = (struct sta_rec_state *)tlv;939	state->state = sta_state;940 941	if (sta->deflink.vht_cap.vht_supported) {942		state->vht_opmode = sta->deflink.bandwidth;943		state->vht_opmode |= (sta->deflink.rx_nss - 1) <<944			IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT;945	}946}947EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_tlv);948 949void mt76_connac_mcu_wtbl_smps_tlv(struct sk_buff *skb,950				   struct ieee80211_sta *sta,951				   void *sta_wtbl, void *wtbl_tlv)952{953	struct wtbl_smps *smps;954	struct tlv *tlv;955 956	tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_SMPS, sizeof(*smps),957					     wtbl_tlv, sta_wtbl);958	smps = (struct wtbl_smps *)tlv;959	smps->smps = (sta->deflink.smps_mode == IEEE80211_SMPS_DYNAMIC);960}961EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_smps_tlv);962 963void mt76_connac_mcu_wtbl_ht_tlv(struct mt76_dev *dev, struct sk_buff *skb,964				 struct ieee80211_sta *sta, void *sta_wtbl,965				 void *wtbl_tlv, bool ht_ldpc, bool vht_ldpc)966{967	struct wtbl_ht *ht = NULL;968	struct tlv *tlv;969	u32 flags = 0;970 971	if (sta->deflink.ht_cap.ht_supported || sta->deflink.he_6ghz_capa.capa) {972		tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_HT, sizeof(*ht),973						     wtbl_tlv, sta_wtbl);974		ht = (struct wtbl_ht *)tlv;975		ht->ldpc = ht_ldpc &&976			   !!(sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_LDPC_CODING);977 978		if (sta->deflink.ht_cap.ht_supported) {979			ht->af = sta->deflink.ht_cap.ampdu_factor;980			ht->mm = sta->deflink.ht_cap.ampdu_density;981		} else {982			ht->af = le16_get_bits(sta->deflink.he_6ghz_capa.capa,983					       IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP);984			ht->mm = le16_get_bits(sta->deflink.he_6ghz_capa.capa,985					       IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);986		}987 988		ht->ht = true;989	}990 991	if (sta->deflink.vht_cap.vht_supported || sta->deflink.he_6ghz_capa.capa) {992		struct wtbl_vht *vht;993		u8 af;994 995		tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_VHT,996						     sizeof(*vht), wtbl_tlv,997						     sta_wtbl);998		vht = (struct wtbl_vht *)tlv;999		vht->ldpc = vht_ldpc &&1000			    !!(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC);1001		vht->vht = true;1002 1003		af = FIELD_GET(IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK,1004			       sta->deflink.vht_cap.cap);1005		if (ht)1006			ht->af = max(ht->af, af);1007	}1008 1009	mt76_connac_mcu_wtbl_smps_tlv(skb, sta, sta_wtbl, wtbl_tlv);1010 1011	if (is_connac_v1(dev) && sta->deflink.ht_cap.ht_supported) {1012		/* sgi */1013		u32 msk = MT_WTBL_W5_SHORT_GI_20 | MT_WTBL_W5_SHORT_GI_40 |1014			  MT_WTBL_W5_SHORT_GI_80 | MT_WTBL_W5_SHORT_GI_160;1015		struct wtbl_raw *raw;1016 1017		tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_RAW_DATA,1018						     sizeof(*raw), wtbl_tlv,1019						     sta_wtbl);1020 1021		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_20)1022			flags |= MT_WTBL_W5_SHORT_GI_20;1023		if (sta->deflink.ht_cap.cap & IEEE80211_HT_CAP_SGI_40)1024			flags |= MT_WTBL_W5_SHORT_GI_40;1025 1026		if (sta->deflink.vht_cap.vht_supported) {1027			if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_80)1028				flags |= MT_WTBL_W5_SHORT_GI_80;1029			if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_SHORT_GI_160)1030				flags |= MT_WTBL_W5_SHORT_GI_160;1031		}1032		raw = (struct wtbl_raw *)tlv;1033		raw->val = cpu_to_le32(flags);1034		raw->msk = cpu_to_le32(~msk);1035		raw->wtbl_idx = 1;1036		raw->dw = 5;1037	}1038}1039EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_ht_tlv);1040 1041int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,1042			    struct mt76_sta_cmd_info *info)1043{1044	struct mt76_vif *mvif = (struct mt76_vif *)info->vif->drv_priv;1045	struct ieee80211_link_sta *link_sta;1046	struct mt76_dev *dev = phy->dev;1047	struct wtbl_req_hdr *wtbl_hdr;1048	struct tlv *sta_wtbl;1049	struct sk_buff *skb;1050	int conn_state;1051 1052	skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, info->wcid);1053	if (IS_ERR(skb))1054		return PTR_ERR(skb);1055 1056	conn_state = info->enable ? CONN_STATE_PORT_SECURE :1057				    CONN_STATE_DISCONNECT;1058	link_sta = info->sta ? &info->sta->deflink : NULL;1059	if (info->sta || !info->offload_fw)1060		mt76_connac_mcu_sta_basic_tlv(dev, skb, info->vif,1061					      link_sta, conn_state,1062					      info->newly);1063	if (info->sta && info->enable)1064		mt76_connac_mcu_sta_tlv(phy, skb, info->sta,1065					info->vif, info->rcpi,1066					info->state);1067 1068	sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,1069					   sizeof(struct tlv));1070 1071	wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, info->wcid,1072						  WTBL_RESET_AND_SET,1073						  sta_wtbl, &skb);1074	if (IS_ERR(wtbl_hdr))1075		return PTR_ERR(wtbl_hdr);1076 1077	if (info->enable) {1078		mt76_connac_mcu_wtbl_generic_tlv(dev, skb, info->vif,1079						 info->sta, sta_wtbl,1080						 wtbl_hdr);1081		mt76_connac_mcu_wtbl_hdr_trans_tlv(skb, info->vif, info->wcid,1082						   sta_wtbl, wtbl_hdr);1083		if (info->sta)1084			mt76_connac_mcu_wtbl_ht_tlv(dev, skb, info->sta,1085						    sta_wtbl, wtbl_hdr,1086						    true, true);1087	}1088 1089	return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true);1090}1091EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_cmd);1092 1093void mt76_connac_mcu_wtbl_ba_tlv(struct mt76_dev *dev, struct sk_buff *skb,1094				 struct ieee80211_ampdu_params *params,1095				 bool enable, bool tx, void *sta_wtbl,1096				 void *wtbl_tlv)1097{1098	struct wtbl_ba *ba;1099	struct tlv *tlv;1100 1101	tlv = mt76_connac_mcu_add_nested_tlv(skb, WTBL_BA, sizeof(*ba),1102					     wtbl_tlv, sta_wtbl);1103 1104	ba = (struct wtbl_ba *)tlv;1105	ba->tid = params->tid;1106 1107	if (tx) {1108		ba->ba_type = MT_BA_TYPE_ORIGINATOR;1109		ba->sn = enable ? cpu_to_le16(params->ssn) : 0;1110		ba->ba_winsize = enable ? cpu_to_le16(params->buf_size) : 0;1111		ba->ba_en = enable;1112	} else {1113		memcpy(ba->peer_addr, params->sta->addr, ETH_ALEN);1114		ba->ba_type = MT_BA_TYPE_RECIPIENT;1115		ba->rst_ba_tid = params->tid;1116		ba->rst_ba_sel = RST_BA_MAC_TID_MATCH;1117		ba->rst_ba_sb = 1;1118	}1119 1120	if (!is_connac_v1(dev)) {1121		ba->ba_winsize = enable ? cpu_to_le16(params->buf_size) : 0;1122		return;1123	}1124 1125	if (enable && tx) {1126		static const u8 ba_range[] = { 4, 8, 12, 24, 36, 48, 54, 64 };1127		int i;1128 1129		for (i = 7; i > 0; i--) {1130			if (params->buf_size >= ba_range[i])1131				break;1132		}1133		ba->ba_winsize_idx = i;1134	}1135}1136EXPORT_SYMBOL_GPL(mt76_connac_mcu_wtbl_ba_tlv);1137 1138int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,1139				struct ieee80211_bss_conf *bss_conf,1140				struct mt76_wcid *wcid,1141				bool enable)1142{1143	struct mt76_vif *mvif = (struct mt76_vif *)bss_conf->vif->drv_priv;1144	struct mt76_dev *dev = phy->dev;1145	struct {1146		struct {1147			u8 omac_idx;1148			u8 band_idx;1149			__le16 pad;1150		} __packed hdr;1151		struct req_tlv {1152			__le16 tag;1153			__le16 len;1154			u8 active;1155			u8 link_idx; /* not link_id */1156			u8 omac_addr[ETH_ALEN];1157		} __packed tlv;1158	} dev_req = {1159		.hdr = {1160			.omac_idx = mvif->omac_idx,1161			.band_idx = mvif->band_idx,1162		},1163		.tlv = {1164			.tag = cpu_to_le16(DEV_INFO_ACTIVE),1165			.len = cpu_to_le16(sizeof(struct req_tlv)),1166			.active = enable,1167			.link_idx = mvif->idx,1168		},1169	};1170	struct {1171		struct {1172			u8 bss_idx;1173			u8 pad[3];1174		} __packed hdr;1175		struct mt76_connac_bss_basic_tlv basic;1176	} basic_req = {1177		.hdr = {1178			.bss_idx = mvif->idx,1179		},1180		.basic = {1181			.tag = cpu_to_le16(UNI_BSS_INFO_BASIC),1182			.len = cpu_to_le16(sizeof(struct mt76_connac_bss_basic_tlv)),1183			.omac_idx = mvif->omac_idx,1184			.band_idx = mvif->band_idx,1185			.wmm_idx = mvif->wmm_idx,1186			.active = enable,1187			.bmc_tx_wlan_idx = cpu_to_le16(wcid->idx),1188			.sta_idx = cpu_to_le16(wcid->idx),1189			.conn_state = 1,1190			.link_idx = mvif->idx,1191		},1192	};1193	int err, idx, cmd, len;1194	void *data;1195 1196	switch (bss_conf->vif->type) {1197	case NL80211_IFTYPE_MESH_POINT:1198	case NL80211_IFTYPE_MONITOR:1199	case NL80211_IFTYPE_AP:1200		basic_req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_AP);1201		break;1202	case NL80211_IFTYPE_STATION:1203		basic_req.basic.conn_type = cpu_to_le32(CONNECTION_INFRA_STA);1204		break;1205	case NL80211_IFTYPE_ADHOC:1206		basic_req.basic.conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC);1207		break;1208	default:1209		WARN_ON(1);1210		break;1211	}1212 1213	idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx;1214	basic_req.basic.hw_bss_idx = idx;1215 1216	memcpy(dev_req.tlv.omac_addr, bss_conf->addr, ETH_ALEN);1217 1218	cmd = enable ? MCU_UNI_CMD(DEV_INFO_UPDATE) : MCU_UNI_CMD(BSS_INFO_UPDATE);1219	data = enable ? (void *)&dev_req : (void *)&basic_req;1220	len = enable ? sizeof(dev_req) : sizeof(basic_req);1221 1222	err = mt76_mcu_send_msg(dev, cmd, data, len, true);1223	if (err < 0)1224		return err;1225 1226	cmd = enable ? MCU_UNI_CMD(BSS_INFO_UPDATE) : MCU_UNI_CMD(DEV_INFO_UPDATE);1227	data = enable ? (void *)&basic_req : (void *)&dev_req;1228	len = enable ? sizeof(basic_req) : sizeof(dev_req);1229 1230	return mt76_mcu_send_msg(dev, cmd, data, len, true);1231}1232EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_dev);1233 1234void mt76_connac_mcu_sta_ba_tlv(struct sk_buff *skb,1235				struct ieee80211_ampdu_params *params,1236				bool enable, bool tx)1237{1238	struct sta_rec_ba *ba;1239	struct tlv *tlv;1240 1241	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BA, sizeof(*ba));1242 1243	ba = (struct sta_rec_ba *)tlv;1244	ba->ba_type = tx ? MT_BA_TYPE_ORIGINATOR : MT_BA_TYPE_RECIPIENT;1245	ba->winsize = cpu_to_le16(params->buf_size);1246	ba->ssn = cpu_to_le16(params->ssn);1247	ba->ba_en = enable << params->tid;1248	ba->amsdu = params->amsdu;1249	ba->tid = params->tid;1250}1251EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_ba_tlv);1252 1253int mt76_connac_mcu_sta_wed_update(struct mt76_dev *dev, struct sk_buff *skb)1254{1255	if (!mt76_is_mmio(dev))1256		return 0;1257 1258	if (!mtk_wed_device_active(&dev->mmio.wed))1259		return 0;1260 1261	return mtk_wed_device_update_msg(&dev->mmio.wed, WED_WO_STA_REC,1262					 skb->data, skb->len);1263}1264EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_wed_update);1265 1266int mt76_connac_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif *mvif,1267			   struct ieee80211_ampdu_params *params,1268			   int cmd, bool enable, bool tx)1269{1270	struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv;1271	struct wtbl_req_hdr *wtbl_hdr;1272	struct tlv *sta_wtbl;1273	struct sk_buff *skb;1274	int ret;1275 1276	skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid);1277	if (IS_ERR(skb))1278		return PTR_ERR(skb);1279 1280	sta_wtbl = mt76_connac_mcu_add_tlv(skb, STA_REC_WTBL,1281					   sizeof(struct tlv));1282 1283	wtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(dev, wcid, WTBL_SET,1284						  sta_wtbl, &skb);1285	if (IS_ERR(wtbl_hdr))1286		return PTR_ERR(wtbl_hdr);1287 1288	mt76_connac_mcu_wtbl_ba_tlv(dev, skb, params, enable, tx, sta_wtbl,1289				    wtbl_hdr);1290 1291	ret = mt76_connac_mcu_sta_wed_update(dev, skb);1292	if (ret)1293		return ret;1294 1295	ret = mt76_mcu_skb_send_msg(dev, skb, cmd, true);1296	if (ret)1297		return ret;1298 1299	skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid);1300	if (IS_ERR(skb))1301		return PTR_ERR(skb);1302 1303	mt76_connac_mcu_sta_ba_tlv(skb, params, enable, tx);1304 1305	ret = mt76_connac_mcu_sta_wed_update(dev, skb);1306	if (ret)1307		return ret;1308 1309	return mt76_mcu_skb_send_msg(dev, skb, cmd, true);1310}1311EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_ba);1312 1313u8 mt76_connac_get_phy_mode(struct mt76_phy *phy, struct ieee80211_vif *vif,1314			    enum nl80211_band band,1315			    struct ieee80211_link_sta *link_sta)1316{1317	struct mt76_dev *dev = phy->dev;1318	const struct ieee80211_sta_he_cap *he_cap;1319	struct ieee80211_sta_vht_cap *vht_cap;1320	struct ieee80211_sta_ht_cap *ht_cap;1321	u8 mode = 0;1322 1323	if (is_connac_v1(dev))1324		return 0x38;1325 1326	if (link_sta) {1327		ht_cap = &link_sta->ht_cap;1328		vht_cap = &link_sta->vht_cap;1329		he_cap = &link_sta->he_cap;1330	} else {1331		struct ieee80211_supported_band *sband;1332 1333		sband = phy->hw->wiphy->bands[band];1334		ht_cap = &sband->ht_cap;1335		vht_cap = &sband->vht_cap;1336		he_cap = ieee80211_get_he_iftype_cap(sband, vif->type);1337	}1338 1339	if (band == NL80211_BAND_2GHZ) {1340		mode |= PHY_MODE_B | PHY_MODE_G;1341 1342		if (ht_cap->ht_supported)1343			mode |= PHY_MODE_GN;1344 1345		if (he_cap && he_cap->has_he)1346			mode |= PHY_MODE_AX_24G;1347	} else if (band == NL80211_BAND_5GHZ) {1348		mode |= PHY_MODE_A;1349 1350		if (ht_cap->ht_supported)1351			mode |= PHY_MODE_AN;1352 1353		if (vht_cap->vht_supported)1354			mode |= PHY_MODE_AC;1355 1356		if (he_cap && he_cap->has_he)1357			mode |= PHY_MODE_AX_5G;1358	} else if (band == NL80211_BAND_6GHZ) {1359		mode |= PHY_MODE_A | PHY_MODE_AN |1360			PHY_MODE_AC | PHY_MODE_AX_5G;1361	}1362 1363	return mode;1364}1365EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode);1366 1367u8 mt76_connac_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif,1368				enum nl80211_band band)1369{1370	const struct ieee80211_sta_eht_cap *eht_cap;1371	struct ieee80211_supported_band *sband;1372	u8 mode = 0;1373 1374	if (band == NL80211_BAND_6GHZ)1375		mode |= PHY_MODE_AX_6G;1376 1377	sband = phy->hw->wiphy->bands[band];1378	eht_cap = ieee80211_get_eht_iftype_cap(sband, vif->type);1379 1380	if (!eht_cap || !eht_cap->has_eht || !vif->bss_conf.eht_support)1381		return mode;1382 1383	switch (band) {1384	case NL80211_BAND_6GHZ:1385		mode |= PHY_MODE_BE_6G;1386		break;1387	case NL80211_BAND_5GHZ:1388		mode |= PHY_MODE_BE_5G;1389		break;1390	case NL80211_BAND_2GHZ:1391		mode |= PHY_MODE_BE_24G;1392		break;1393	default:1394		break;1395	}1396 1397	return mode;1398}1399EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode_ext);1400 1401const struct ieee80211_sta_he_cap *1402mt76_connac_get_he_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif)1403{1404	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;1405	struct cfg80211_chan_def *chandef = mvif->ctx ?1406					    &mvif->ctx->def : &phy->chandef;1407	enum nl80211_band band = chandef->chan->band;1408	struct ieee80211_supported_band *sband;1409 1410	sband = phy->hw->wiphy->bands[band];1411 1412	return ieee80211_get_he_iftype_cap(sband, vif->type);1413}1414EXPORT_SYMBOL_GPL(mt76_connac_get_he_phy_cap);1415 1416const struct ieee80211_sta_eht_cap *1417mt76_connac_get_eht_phy_cap(struct mt76_phy *phy, struct ieee80211_vif *vif)1418{1419	enum nl80211_band band = phy->chandef.chan->band;1420	struct ieee80211_supported_band *sband;1421 1422	sband = phy->hw->wiphy->bands[band];1423 1424	return ieee80211_get_eht_iftype_cap(sband, vif->type);1425}1426EXPORT_SYMBOL_GPL(mt76_connac_get_eht_phy_cap);1427 1428#define DEFAULT_HE_PE_DURATION		41429#define DEFAULT_HE_DURATION_RTS_THRES	10231430static void1431mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif,1432			       struct tlv *tlv)1433{1434	const struct ieee80211_sta_he_cap *cap;1435	struct bss_info_uni_he *he;1436 1437	cap = mt76_connac_get_he_phy_cap(phy, vif);1438 1439	he = (struct bss_info_uni_he *)tlv;1440	he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext;1441	if (!he->he_pe_duration)1442		he->he_pe_duration = DEFAULT_HE_PE_DURATION;1443 1444	he->he_rts_thres = cpu_to_le16(vif->bss_conf.frame_time_rts_th);1445	if (!he->he_rts_thres)1446		he->he_rts_thres = cpu_to_le16(DEFAULT_HE_DURATION_RTS_THRES);1447 1448	he->max_nss_mcs[CMD_HE_MCS_BW80] = cap->he_mcs_nss_supp.tx_mcs_80;1449	he->max_nss_mcs[CMD_HE_MCS_BW160] = cap->he_mcs_nss_supp.tx_mcs_160;1450	he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80;1451}1452 1453int mt76_connac_mcu_uni_set_chctx(struct mt76_phy *phy, struct mt76_vif *mvif,1454				  struct ieee80211_chanctx_conf *ctx)1455{1456	struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef;1457	int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;1458	enum nl80211_band band = chandef->chan->band;1459	struct mt76_dev *mdev = phy->dev;1460	struct {1461		struct {1462			u8 bss_idx;1463			u8 pad[3];1464		} __packed hdr;1465		struct rlm_tlv {1466			__le16 tag;1467			__le16 len;1468			u8 control_channel;1469			u8 center_chan;1470			u8 center_chan2;1471			u8 bw;1472			u8 tx_streams;1473			u8 rx_streams;1474			u8 short_st;1475			u8 ht_op_info;1476			u8 sco;1477			u8 band;1478			u8 pad[2];1479		} __packed rlm;1480	} __packed rlm_req = {1481		.hdr = {1482			.bss_idx = mvif->idx,1483		},1484		.rlm = {1485			.tag = cpu_to_le16(UNI_BSS_INFO_RLM),1486			.len = cpu_to_le16(sizeof(struct rlm_tlv)),1487			.control_channel = chandef->chan->hw_value,1488			.center_chan = ieee80211_frequency_to_channel(freq1),1489			.center_chan2 = ieee80211_frequency_to_channel(freq2),1490			.tx_streams = hweight8(phy->antenna_mask),1491			.ht_op_info = 4, /* set HT 40M allowed */1492			.rx_streams = phy->chainmask,1493			.short_st = true,1494			.band = band,1495		},1496	};1497 1498	switch (chandef->width) {1499	case NL80211_CHAN_WIDTH_40:1500		rlm_req.rlm.bw = CMD_CBW_40MHZ;1501		break;1502	case NL80211_CHAN_WIDTH_80:1503		rlm_req.rlm.bw = CMD_CBW_80MHZ;1504		break;1505	case NL80211_CHAN_WIDTH_80P80:1506		rlm_req.rlm.bw = CMD_CBW_8080MHZ;1507		break;1508	case NL80211_CHAN_WIDTH_160:1509		rlm_req.rlm.bw = CMD_CBW_160MHZ;1510		break;1511	case NL80211_CHAN_WIDTH_5:1512		rlm_req.rlm.bw = CMD_CBW_5MHZ;1513		break;1514	case NL80211_CHAN_WIDTH_10:1515		rlm_req.rlm.bw = CMD_CBW_10MHZ;1516		break;1517	case NL80211_CHAN_WIDTH_20_NOHT:1518	case NL80211_CHAN_WIDTH_20:1519	default:1520		rlm_req.rlm.bw = CMD_CBW_20MHZ;1521		rlm_req.rlm.ht_op_info = 0;1522		break;1523	}1524 1525	if (rlm_req.rlm.control_channel < rlm_req.rlm.center_chan)1526		rlm_req.rlm.sco = 1; /* SCA */1527	else if (rlm_req.rlm.control_channel > rlm_req.rlm.center_chan)1528		rlm_req.rlm.sco = 3; /* SCB */1529 1530	return mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), &rlm_req,1531				 sizeof(rlm_req), true);1532}1533EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_set_chctx);1534 1535int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,1536				struct ieee80211_vif *vif,1537				struct mt76_wcid *wcid,1538				bool enable,1539				struct ieee80211_chanctx_conf *ctx)1540{1541	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;1542	struct cfg80211_chan_def *chandef = ctx ? &ctx->def : &phy->chandef;1543	enum nl80211_band band = chandef->chan->band;1544	struct mt76_dev *mdev = phy->dev;1545	struct {1546		struct {1547			u8 bss_idx;1548			u8 pad[3];1549		} __packed hdr;1550		struct mt76_connac_bss_basic_tlv basic;1551		struct mt76_connac_bss_qos_tlv qos;1552	} basic_req = {1553		.hdr = {1554			.bss_idx = mvif->idx,1555		},1556		.basic = {1557			.tag = cpu_to_le16(UNI_BSS_INFO_BASIC),1558			.len = cpu_to_le16(sizeof(struct mt76_connac_bss_basic_tlv)),1559			.bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int),1560			.dtim_period = vif->bss_conf.dtim_period,1561			.omac_idx = mvif->omac_idx,1562			.band_idx = mvif->band_idx,1563			.wmm_idx = mvif->wmm_idx,1564			.active = true, /* keep bss deactivated */1565			.phymode = mt76_connac_get_phy_mode(phy, vif, band, NULL),1566		},1567		.qos = {1568			.tag = cpu_to_le16(UNI_BSS_INFO_QBSS),1569			.len = cpu_to_le16(sizeof(struct mt76_connac_bss_qos_tlv)),1570			.qos = vif->bss_conf.qos,1571		},1572	};1573	int err, conn_type;1574	u8 idx, basic_phy;1575 1576	idx = mvif->omac_idx > EXT_BSSID_START ? HW_BSSID_0 : mvif->omac_idx;1577	basic_req.basic.hw_bss_idx = idx;1578	if (band == NL80211_BAND_6GHZ)1579		basic_req.basic.phymode_ext = PHY_MODE_AX_6G;1580 1581	basic_phy = mt76_connac_get_phy_mode_v2(phy, vif, band, NULL);1582	basic_req.basic.nonht_basic_phy = cpu_to_le16(basic_phy);1583 1584	switch (vif->type) {1585	case NL80211_IFTYPE_MESH_POINT:1586	case NL80211_IFTYPE_AP:1587		if (vif->p2p)1588			conn_type = CONNECTION_P2P_GO;1589		else1590			conn_type = CONNECTION_INFRA_AP;1591		basic_req.basic.conn_type = cpu_to_le32(conn_type);1592		/* Fully active/deactivate BSS network in AP mode only */1593		basic_req.basic.active = enable;1594		break;1595	case NL80211_IFTYPE_STATION:1596		if (vif->p2p)1597			conn_type = CONNECTION_P2P_GC;1598		else1599			conn_type = CONNECTION_INFRA_STA;1600		basic_req.basic.conn_type = cpu_to_le32(conn_type);1601		break;1602	case NL80211_IFTYPE_ADHOC:1603		basic_req.basic.conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC);1604		break;1605	default:1606		WARN_ON(1);1607		break;1608	}1609 1610	memcpy(basic_req.basic.bssid, vif->bss_conf.bssid, ETH_ALEN);1611	basic_req.basic.bmc_tx_wlan_idx = cpu_to_le16(wcid->idx);1612	basic_req.basic.sta_idx = cpu_to_le16(wcid->idx);1613	basic_req.basic.conn_state = !enable;1614 1615	err = mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), &basic_req,1616				sizeof(basic_req), true);1617	if (err < 0)1618		return err;1619 1620	if (vif->bss_conf.he_support) {1621		struct {1622			struct {1623				u8 bss_idx;1624				u8 pad[3];1625			} __packed hdr;1626			struct bss_info_uni_he he;1627			struct bss_info_uni_bss_color bss_color;1628		} he_req = {1629			.hdr = {1630				.bss_idx = mvif->idx,1631			},1632			.he = {1633				.tag = cpu_to_le16(UNI_BSS_INFO_HE_BASIC),1634				.len = cpu_to_le16(sizeof(struct bss_info_uni_he)),1635			},1636			.bss_color = {1637				.tag = cpu_to_le16(UNI_BSS_INFO_BSS_COLOR),1638				.len = cpu_to_le16(sizeof(struct bss_info_uni_bss_color)),1639				.enable = 0,1640				.bss_color = 0,1641			},1642		};1643 1644		if (enable) {1645			he_req.bss_color.enable =1646				vif->bss_conf.he_bss_color.enabled;1647			he_req.bss_color.bss_color =1648				vif->bss_conf.he_bss_color.color;1649		}1650 1651		mt76_connac_mcu_uni_bss_he_tlv(phy, vif,1652					       (struct tlv *)&he_req.he);1653		err = mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE),1654					&he_req, sizeof(he_req), true);1655		if (err < 0)1656			return err;1657	}1658 1659	return mt76_connac_mcu_uni_set_chctx(phy, mvif, ctx);1660}1661EXPORT_SYMBOL_GPL(mt76_connac_mcu_uni_add_bss);1662 1663#define MT76_CONNAC_SCAN_CHANNEL_TIME		601664int mt76_connac_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,1665			    struct ieee80211_scan_request *scan_req)1666{1667	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;1668	struct cfg80211_scan_request *sreq = &scan_req->req;1669	int n_ssids = 0, err, i, duration;1670	int ext_channels_num = max_t(int, sreq->n_channels - 32, 0);1671	struct ieee80211_channel **scan_list = sreq->channels;1672	struct mt76_dev *mdev = phy->dev;1673	struct mt76_connac_mcu_scan_channel *chan;1674	struct mt76_connac_hw_scan_req *req;1675	struct sk_buff *skb;1676 1677	if (test_bit(MT76_HW_SCANNING, &phy->state))1678		return -EBUSY;1679 1680	skb = mt76_mcu_msg_alloc(mdev, NULL, sizeof(*req));1681	if (!skb)1682		return -ENOMEM;1683 1684	set_bit(MT76_HW_SCANNING, &phy->state);1685	mvif->scan_seq_num = (mvif->scan_seq_num + 1) & 0x7f;1686 1687	req = (struct mt76_connac_hw_scan_req *)skb_put_zero(skb, sizeof(*req));1688 1689	req->seq_num = mvif->scan_seq_num | mvif->band_idx << 7;1690	req->bss_idx = mvif->idx;1691	req->scan_type = sreq->n_ssids ? 1 : 0;1692	req->probe_req_num = sreq->n_ssids ? 2 : 0;1693	req->version = 1;1694 1695	for (i = 0; i < sreq->n_ssids; i++) {1696		if (!sreq->ssids[i].ssid_len)1697			continue;1698 1699		req->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len);1700		memcpy(req->ssids[i].ssid, sreq->ssids[i].ssid,1701		       sreq->ssids[i].ssid_len);1702		n_ssids++;1703	}1704	req->ssid_type = n_ssids ? BIT(2) : BIT(0);1705	req->ssid_type_ext = n_ssids ? BIT(0) : 0;1706	req->ssids_num = n_ssids;1707 1708	duration = is_mt7921(phy->dev) ? 0 : MT76_CONNAC_SCAN_CHANNEL_TIME;1709	/* increase channel time for passive scan */1710	if (!sreq->n_ssids)1711		duration *= 2;1712	req->timeout_value = cpu_to_le16(sreq->n_channels * duration);1713	req->channel_min_dwell_time = cpu_to_le16(duration);1714	req->channel_dwell_time = cpu_to_le16(duration);1715 1716	if (sreq->n_channels == 0 || sreq->n_channels > 64) {1717		req->channel_type = 0;1718		req->channels_num = 0;1719		req->ext_channels_num = 0;1720	} else {1721		req->channel_type = 4;1722		req->channels_num = min_t(u8, sreq->n_channels, 32);1723		req->ext_channels_num = min_t(u8, ext_channels_num, 32);1724	}1725 1726	for (i = 0; i < req->channels_num + req->ext_channels_num; i++) {1727		if (i >= 32)1728			chan = &req->ext_channels[i - 32];1729		else1730			chan = &req->channels[i];1731 1732		switch (scan_list[i]->band) {1733		case NL80211_BAND_2GHZ:1734			chan->band = 1;1735			break;1736		case NL80211_BAND_6GHZ:1737			chan->band = 3;1738			break;1739		default:1740			chan->band = 2;1741			break;1742		}1743		chan->channel_num = scan_list[i]->hw_value;1744	}1745 1746	if (sreq->ie_len > 0) {1747		memcpy(req->ies, sreq->ie, sreq->ie_len);1748		req->ies_len = cpu_to_le16(sreq->ie_len);1749	}1750 1751	if (is_mt7921(phy->dev))1752		req->scan_func |= SCAN_FUNC_SPLIT_SCAN;1753 1754	memcpy(req->bssid, sreq->bssid, ETH_ALEN);1755	if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {1756		get_random_mask_addr(req->random_mac, sreq->mac_addr,1757				     sreq->mac_addr_mask);1758		req->scan_func |= SCAN_FUNC_RANDOM_MAC;1759	}1760 1761	err = mt76_mcu_skb_send_msg(mdev, skb, MCU_CE_CMD(START_HW_SCAN),1762				    false);1763	if (err < 0)1764		clear_bit(MT76_HW_SCANNING, &phy->state);1765 1766	return err;1767}1768EXPORT_SYMBOL_GPL(mt76_connac_mcu_hw_scan);1769 1770int mt76_connac_mcu_cancel_hw_scan(struct mt76_phy *phy,1771				   struct ieee80211_vif *vif)1772{1773	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;1774	struct {1775		u8 seq_num;1776		u8 is_ext_channel;1777		u8 rsv[2];1778	} __packed req = {1779		.seq_num = mvif->scan_seq_num,1780	};1781 1782	if (test_and_clear_bit(MT76_HW_SCANNING, &phy->state)) {1783		struct cfg80211_scan_info info = {1784			.aborted = true,1785		};1786 1787		ieee80211_scan_completed(phy->hw, &info);1788	}1789 1790	return mt76_mcu_send_msg(phy->dev, MCU_CE_CMD(CANCEL_HW_SCAN),1791				 &req, sizeof(req), false);1792}1793EXPORT_SYMBOL_GPL(mt76_connac_mcu_cancel_hw_scan);1794 1795int mt76_connac_mcu_sched_scan_req(struct mt76_phy *phy,1796				   struct ieee80211_vif *vif,1797				   struct cfg80211_sched_scan_request *sreq)1798{1799	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;1800	struct ieee80211_channel **scan_list = sreq->channels;1801	struct mt76_connac_mcu_scan_channel *chan;1802	struct mt76_connac_sched_scan_req *req;1803	struct mt76_dev *mdev = phy->dev;1804	struct cfg80211_match_set *match;1805	struct cfg80211_ssid *ssid;1806	struct sk_buff *skb;1807	int i;1808 1809	skb = mt76_mcu_msg_alloc(mdev, NULL, sizeof(*req) + sreq->ie_len);1810	if (!skb)1811		return -ENOMEM;1812 1813	mvif->scan_seq_num = (mvif->scan_seq_num + 1) & 0x7f;1814 1815	req = (struct mt76_connac_sched_scan_req *)skb_put_zero(skb, sizeof(*req));1816	req->version = 1;1817	req->seq_num = mvif->scan_seq_num | mvif->band_idx << 7;1818 1819	if (sreq->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {1820		u8 *addr = is_mt7663(phy->dev) ? req->mt7663.random_mac1821					       : req->mt7921.random_mac;1822 1823		req->scan_func = 1;1824		get_random_mask_addr(addr, sreq->mac_addr,1825				     sreq->mac_addr_mask);1826	}1827	if (is_mt7921(phy->dev)) {1828		req->mt7921.bss_idx = mvif->idx;1829		req->mt7921.delay = cpu_to_le32(sreq->delay);1830	}1831 1832	req->ssids_num = sreq->n_ssids;1833	for (i = 0; i < req->ssids_num; i++) {1834		ssid = &sreq->ssids[i];1835		memcpy(req->ssids[i].ssid, ssid->ssid, ssid->ssid_len);1836		req->ssids[i].ssid_len = cpu_to_le32(ssid->ssid_len);1837	}1838 1839	req->match_num = sreq->n_match_sets;1840	for (i = 0; i < req->match_num; i++) {1841		match = &sreq->match_sets[i];1842		memcpy(req->match[i].ssid, match->ssid.ssid,1843		       match->ssid.ssid_len);1844		req->match[i].rssi_th = cpu_to_le32(match->rssi_thold);1845		req->match[i].ssid_len = match->ssid.ssid_len;1846	}1847 1848	req->channel_type = sreq->n_channels ? 4 : 0;1849	req->channels_num = min_t(u8, sreq->n_channels, 64);1850	for (i = 0; i < req->channels_num; i++) {1851		chan = &req->channels[i];1852 1853		switch (scan_list[i]->band) {1854		case NL80211_BAND_2GHZ:1855			chan->band = 1;1856			break;1857		case NL80211_BAND_6GHZ:1858			chan->band = 3;1859			break;1860		default:1861			chan->band = 2;1862			break;1863		}1864		chan->channel_num = scan_list[i]->hw_value;1865	}1866 1867	req->intervals_num = sreq->n_scan_plans;1868	for (i = 0; i < req->intervals_num; i++)1869		req->intervals[i] = cpu_to_le16(sreq->scan_plans[i].interval);1870 1871	if (sreq->ie_len > 0) {1872		req->ie_len = cpu_to_le16(sreq->ie_len);1873		memcpy(skb_put(skb, sreq->ie_len), sreq->ie, sreq->ie_len);1874	}1875 1876	return mt76_mcu_skb_send_msg(mdev, skb, MCU_CE_CMD(SCHED_SCAN_REQ),1877				     false);1878}1879EXPORT_SYMBOL_GPL(mt76_connac_mcu_sched_scan_req);1880 1881int mt76_connac_mcu_sched_scan_enable(struct mt76_phy *phy,1882				      struct ieee80211_vif *vif,1883				      bool enable)1884{1885	struct {1886		u8 active; /* 0: enabled 1: disabled */1887		u8 rsv[3];1888	} __packed req = {1889		.active = !enable,1890	};1891 1892	if (enable)1893		set_bit(MT76_HW_SCHED_SCANNING, &phy->state);1894	else1895		clear_bit(MT76_HW_SCHED_SCANNING, &phy->state);1896 1897	return mt76_mcu_send_msg(phy->dev, MCU_CE_CMD(SCHED_SCAN_ENABLE),1898				 &req, sizeof(req), false);1899}1900EXPORT_SYMBOL_GPL(mt76_connac_mcu_sched_scan_enable);1901 1902int mt76_connac_mcu_chip_config(struct mt76_dev *dev)1903{1904	struct mt76_connac_config req = {1905		.resp_type = 0,1906	};1907 1908	memcpy(req.data, "assert", 7);1909 1910	return mt76_mcu_send_msg(dev, MCU_CE_CMD(CHIP_CONFIG),1911				 &req, sizeof(req), false);1912}1913EXPORT_SYMBOL_GPL(mt76_connac_mcu_chip_config);1914 1915int mt76_connac_mcu_set_deep_sleep(struct mt76_dev *dev, bool enable)1916{1917	struct mt76_connac_config req = {1918		.resp_type = 0,1919	};1920 1921	snprintf(req.data, sizeof(req.data), "KeepFullPwr %d", !enable);1922 1923	return mt76_mcu_send_msg(dev, MCU_CE_CMD(CHIP_CONFIG),1924				 &req, sizeof(req), false);1925}1926EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_deep_sleep);1927 1928int mt76_connac_sta_state_dp(struct mt76_dev *dev,1929			     enum ieee80211_sta_state old_state,1930			     enum ieee80211_sta_state new_state)1931{1932	if ((old_state == IEEE80211_STA_ASSOC &&1933	     new_state == IEEE80211_STA_AUTHORIZED) ||1934	    (old_state == IEEE80211_STA_NONE &&1935	     new_state == IEEE80211_STA_NOTEXIST))1936		mt76_connac_mcu_set_deep_sleep(dev, true);1937 1938	if ((old_state == IEEE80211_STA_NOTEXIST &&1939	     new_state == IEEE80211_STA_NONE) ||1940	    (old_state == IEEE80211_STA_AUTHORIZED &&1941	     new_state == IEEE80211_STA_ASSOC))1942		mt76_connac_mcu_set_deep_sleep(dev, false);1943 1944	return 0;1945}1946EXPORT_SYMBOL_GPL(mt76_connac_sta_state_dp);1947 1948void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,1949				    struct mt76_connac_coredump *coredump)1950{1951	spin_lock_bh(&dev->lock);1952	__skb_queue_tail(&coredump->msg_list, skb);1953	spin_unlock_bh(&dev->lock);1954 1955	coredump->last_activity = jiffies;1956 1957	queue_delayed_work(dev->wq, &coredump->work,1958			   MT76_CONNAC_COREDUMP_TIMEOUT);1959}1960EXPORT_SYMBOL_GPL(mt76_connac_mcu_coredump_event);1961 1962static void1963mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,1964			  struct mt76_power_limits *limits,1965			  enum nl80211_band band)1966{1967	int max_power = is_mt7921(dev) ? 127 : 63;1968	int i, offset = sizeof(limits->cck);1969 1970	memset(sku, max_power, MT_SKU_POWER_LIMIT);1971 1972	if (band == NL80211_BAND_2GHZ) {1973		/* cck */1974		memcpy(sku, limits->cck, sizeof(limits->cck));1975	}1976 1977	/* ofdm */1978	memcpy(&sku[offset], limits->ofdm, sizeof(limits->ofdm));1979	offset += sizeof(limits->ofdm);1980 1981	/* ht */1982	for (i = 0; i < 2; i++) {1983		memcpy(&sku[offset], limits->mcs[i], 8);1984		offset += 8;1985	}1986	sku[offset++] = limits->mcs[0][0];1987 1988	/* vht */1989	for (i = 0; i < ARRAY_SIZE(limits->mcs); i++) {1990		memcpy(&sku[offset], limits->mcs[i],1991		       ARRAY_SIZE(limits->mcs[i]));1992		offset += 12;1993	}1994 1995	if (!is_mt7921(dev))1996		return;1997 1998	/* he */1999	for (i = 0; i < ARRAY_SIZE(limits->ru); i++) {2000		memcpy(&sku[offset], limits->ru[i], ARRAY_SIZE(limits->ru[i]));2001		offset += ARRAY_SIZE(limits->ru[i]);2002	}2003}2004 2005s8 mt76_connac_get_ch_power(struct mt76_phy *phy,2006			    struct ieee80211_channel *chan,2007			    s8 target_power)2008{2009	struct mt76_dev *dev = phy->dev;2010	struct ieee80211_supported_band *sband;2011	int i;2012 2013	switch (chan->band) {2014	case NL80211_BAND_2GHZ:2015		sband = &phy->sband_2g.sband;2016		break;2017	case NL80211_BAND_5GHZ:2018		sband = &phy->sband_5g.sband;2019		break;2020	case NL80211_BAND_6GHZ:2021		sband = &phy->sband_6g.sband;2022		break;2023	default:2024		return target_power;2025	}2026 2027	for (i = 0; i < sband->n_channels; i++) {2028		struct ieee80211_channel *ch = &sband->channels[i];2029 2030		if (ch->hw_value == chan->hw_value) {2031			if (!(ch->flags & IEEE80211_CHAN_DISABLED)) {2032				int power = 2 * ch->max_reg_power;2033 2034				if (is_mt7663(dev) && (power > 63 || power < -64))2035					power = 63;2036				target_power = min_t(s8, power, target_power);2037			}2038			break;2039		}2040	}2041 2042	return target_power;2043}2044EXPORT_SYMBOL_GPL(mt76_connac_get_ch_power);2045 2046static int2047mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,2048				  enum nl80211_band band)2049{2050	struct mt76_dev *dev = phy->dev;2051	int sku_len, batch_len = is_mt7921(dev) ? 8 : 16;2052	static const u8 chan_list_2ghz[] = {2053		1, 2,  3,  4,  5,  6,  7,2054		8, 9, 10, 11, 12, 13, 142055	};2056	static const u8 chan_list_5ghz[] = {2057		 36,  38,  40,  42,  44,  46,  48,2058		 50,  52,  54,  56,  58,  60,  62,2059		 64, 100, 102, 104, 106, 108, 110,2060		112, 114, 116, 118, 120, 122, 124,2061		126, 128, 132, 134, 136, 138, 140,2062		142, 144, 149, 151, 153, 155, 157,2063		159, 161, 165, 169, 173, 1772064	};2065	static const u8 chan_list_6ghz[] = {2066		  1,   3,   5,   7,   9,  11,  13,2067		 15,  17,  19,  21,  23,  25,  27,2068		 29,  33,  35,  37,  39,  41,  43,2069		 45,  47,  49,  51,  53,  55,  57,2070		 59,  61,  65,  67,  69,  71,  73,2071		 75,  77,  79,  81,  83,  85,  87,2072		 89,  91,  93,  97,  99, 101, 103,2073		105, 107, 109, 111, 113, 115, 117,2074		119, 121, 123, 125, 129, 131, 133,2075		135, 137, 139, 141, 143, 145, 147,2076		149, 151, 153, 155, 157, 161, 163,2077		165, 167, 169, 171, 173, 175, 177,2078		179, 181, 183, 185, 187, 189, 193,2079		195, 197, 199, 201, 203, 205, 207,2080		209, 211, 213, 215, 217, 219, 221,2081		225, 227, 229, 2332082	};2083	int i, n_chan, batch_size, idx = 0, tx_power, last_ch, err = 0;2084	struct mt76_connac_sku_tlv sku_tlbv;2085	struct mt76_power_limits *limits;2086	const u8 *ch_list;2087 2088	limits = devm_kmalloc(dev->dev, sizeof(*limits), GFP_KERNEL);2089	if (!limits)2090		return -ENOMEM;2091 2092	sku_len = is_mt7921(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92;2093	tx_power = 2 * phy->hw->conf.power_level;2094	if (!tx_power)2095		tx_power = 127;2096 2097	if (band == NL80211_BAND_2GHZ) {2098		n_chan = ARRAY_SIZE(chan_list_2ghz);2099		ch_list = chan_list_2ghz;2100	} else if (band == NL80211_BAND_6GHZ) {2101		n_chan = ARRAY_SIZE(chan_list_6ghz);2102		ch_list = chan_list_6ghz;2103	} else {2104		n_chan = ARRAY_SIZE(chan_list_5ghz);2105		ch_list = chan_list_5ghz;2106	}2107	batch_size = DIV_ROUND_UP(n_chan, batch_len);2108 2109	if (phy->cap.has_6ghz)2110		last_ch = chan_list_6ghz[ARRAY_SIZE(chan_list_6ghz) - 1];2111	else if (phy->cap.has_5ghz)2112		last_ch = chan_list_5ghz[ARRAY_SIZE(chan_list_5ghz) - 1];2113	else2114		last_ch = chan_list_2ghz[ARRAY_SIZE(chan_list_2ghz) - 1];2115 2116	for (i = 0; i < batch_size; i++) {2117		struct mt76_connac_tx_power_limit_tlv tx_power_tlv = {};2118		int j, msg_len, num_ch;2119		struct sk_buff *skb;2120 2121		num_ch = i == batch_size - 1 ? n_chan - i * batch_len : batch_len;2122		msg_len = sizeof(tx_power_tlv) + num_ch * sizeof(sku_tlbv);2123		skb = mt76_mcu_msg_alloc(dev, NULL, msg_len);2124		if (!skb) {2125			err = -ENOMEM;2126			goto out;2127		}2128 2129		skb_reserve(skb, sizeof(tx_power_tlv));2130 2131		BUILD_BUG_ON(sizeof(dev->alpha2) > sizeof(tx_power_tlv.alpha2));2132		memcpy(tx_power_tlv.alpha2, dev->alpha2, sizeof(dev->alpha2));2133		tx_power_tlv.n_chan = num_ch;2134 2135		switch (band) {2136		case NL80211_BAND_2GHZ:2137			tx_power_tlv.band = 1;2138			break;2139		case NL80211_BAND_6GHZ:2140			tx_power_tlv.band = 3;2141			break;2142		default:2143			tx_power_tlv.band = 2;2144			break;2145		}2146 2147		for (j = 0; j < num_ch; j++, idx++) {2148			struct ieee80211_channel chan = {2149				.hw_value = ch_list[idx],2150				.band = band,2151			};2152			s8 reg_power, sar_power;2153 2154			reg_power = mt76_connac_get_ch_power(phy, &chan,2155							     tx_power);2156			sar_power = mt76_get_sar_power(phy, &chan, reg_power);2157 2158			mt76_get_rate_power_limits(phy, &chan, limits,2159						   sar_power);2160 2161			tx_power_tlv.last_msg = ch_list[idx] == last_ch;2162			sku_tlbv.channel = ch_list[idx];2163 2164			mt76_connac_mcu_build_sku(dev, sku_tlbv.pwr_limit,2165						  limits, band);2166			skb_put_data(skb, &sku_tlbv, sku_len);2167		}2168		__skb_push(skb, sizeof(tx_power_tlv));2169		memcpy(skb->data, &tx_power_tlv, sizeof(tx_power_tlv));2170 2171		err = mt76_mcu_skb_send_msg(dev, skb,2172					    MCU_CE_CMD(SET_RATE_TX_POWER),2173					    false);2174		if (err < 0)2175			goto out;2176	}2177 2178out:2179	devm_kfree(dev->dev, limits);2180	return err;2181}2182 2183int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)2184{2185	int err;2186 2187	if (phy->cap.has_2ghz) {2188		err = mt76_connac_mcu_rate_txpower_band(phy,2189							NL80211_BAND_2GHZ);2190		if (err < 0)2191			return err;2192	}2193	if (phy->cap.has_5ghz) {2194		err = mt76_connac_mcu_rate_txpower_band(phy,2195							NL80211_BAND_5GHZ);2196		if (err < 0)2197			return err;2198	}2199	if (phy->cap.has_6ghz) {2200		err = mt76_connac_mcu_rate_txpower_band(phy,2201							NL80211_BAND_6GHZ);2202		if (err < 0)2203			return err;2204	}2205 2206	return 0;2207}2208EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rate_txpower);2209 2210int mt76_connac_mcu_update_arp_filter(struct mt76_dev *dev,2211				      struct mt76_vif *vif,2212				      struct ieee80211_bss_conf *info)2213{2214	struct ieee80211_vif *mvif = container_of(info, struct ieee80211_vif,2215						  bss_conf);2216	struct sk_buff *skb;2217	int i, len = min_t(int, mvif->cfg.arp_addr_cnt,2218			   IEEE80211_BSS_ARP_ADDR_LIST_LEN);2219	struct {2220		struct {2221			u8 bss_idx;2222			u8 pad[3];2223		} __packed hdr;2224		struct mt76_connac_arpns_tlv arp;2225	} req_hdr = {2226		.hdr = {2227			.bss_idx = vif->idx,2228		},2229		.arp = {2230			.tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ARP),2231			.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)),2232			.ips_num = len,2233			.mode = 2,  /* update */2234			.option = 1,2235		},2236	};2237 2238	skb = mt76_mcu_msg_alloc(dev, NULL,2239				 sizeof(req_hdr) + len * sizeof(__be32));2240	if (!skb)2241		return -ENOMEM;2242 2243	skb_put_data(skb, &req_hdr, sizeof(req_hdr));2244	for (i = 0; i < len; i++)2245		skb_put_data(skb, &mvif->cfg.arp_addr_list[i], sizeof(__be32));2246 2247	return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(OFFLOAD), true);2248}2249EXPORT_SYMBOL_GPL(mt76_connac_mcu_update_arp_filter);2250 2251int mt76_connac_mcu_set_p2p_oppps(struct ieee80211_hw *hw,2252				  struct ieee80211_vif *vif)2253{2254	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;2255	int ct_window = vif->bss_conf.p2p_noa_attr.oppps_ctwindow;2256	struct mt76_phy *phy = hw->priv;2257	struct {2258		__le32 ct_win;2259		u8 bss_idx;2260		u8 rsv[3];2261	} __packed req = {2262		.ct_win = cpu_to_le32(ct_window),2263		.bss_idx = mvif->idx,2264	};2265 2266	return mt76_mcu_send_msg(phy->dev, MCU_CE_CMD(SET_P2P_OPPPS),2267				 &req, sizeof(req), false);2268}2269EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_p2p_oppps);2270 2271#ifdef CONFIG_PM2272 2273const struct wiphy_wowlan_support mt76_connac_wowlan_support = {2274	.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT |2275		 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | WIPHY_WOWLAN_NET_DETECT,2276	.n_patterns = 1,2277	.pattern_min_len = 1,2278	.pattern_max_len = MT76_CONNAC_WOW_PATTEN_MAX_LEN,2279	.max_nd_match_sets = 10,2280};2281EXPORT_SYMBOL_GPL(mt76_connac_wowlan_support);2282 2283static void2284mt76_connac_mcu_key_iter(struct ieee80211_hw *hw,2285			 struct ieee80211_vif *vif,2286			 struct ieee80211_sta *sta,2287			 struct ieee80211_key_conf *key,2288			 void *data)2289{2290	struct mt76_connac_gtk_rekey_tlv *gtk_tlv = data;2291	u32 cipher;2292 2293	if (key->cipher != WLAN_CIPHER_SUITE_AES_CMAC &&2294	    key->cipher != WLAN_CIPHER_SUITE_CCMP &&2295	    key->cipher != WLAN_CIPHER_SUITE_TKIP)2296		return;2297 2298	if (key->cipher == WLAN_CIPHER_SUITE_TKIP)2299		cipher = BIT(3);2300	else2301		cipher = BIT(4);2302 2303	/* we are assuming here to have a single pairwise key */2304	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {2305		if (key->cipher == WLAN_CIPHER_SUITE_TKIP)2306			gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_1);2307		else2308			gtk_tlv->proto = cpu_to_le32(NL80211_WPA_VERSION_2);2309 2310		gtk_tlv->pairwise_cipher = cpu_to_le32(cipher);2311		gtk_tlv->keyid = key->keyidx;2312	} else {2313		gtk_tlv->group_cipher = cpu_to_le32(cipher);2314	}2315}2316 2317int mt76_connac_mcu_update_gtk_rekey(struct ieee80211_hw *hw,2318				     struct ieee80211_vif *vif,2319				     struct cfg80211_gtk_rekey_data *key)2320{2321	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;2322	struct mt76_connac_gtk_rekey_tlv *gtk_tlv;2323	struct mt76_phy *phy = hw->priv;2324	struct sk_buff *skb;2325	struct {2326		u8 bss_idx;2327		u8 pad[3];2328	} __packed hdr = {2329		.bss_idx = mvif->idx,2330	};2331 2332	skb = mt76_mcu_msg_alloc(phy->dev, NULL,2333				 sizeof(hdr) + sizeof(*gtk_tlv));2334	if (!skb)2335		return -ENOMEM;2336 2337	skb_put_data(skb, &hdr, sizeof(hdr));2338	gtk_tlv = (struct mt76_connac_gtk_rekey_tlv *)skb_put_zero(skb,2339							 sizeof(*gtk_tlv));2340	gtk_tlv->tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_GTK_REKEY);2341	gtk_tlv->len = cpu_to_le16(sizeof(*gtk_tlv));2342	gtk_tlv->rekey_mode = 2;2343	gtk_tlv->option = 1;2344 2345	rcu_read_lock();2346	ieee80211_iter_keys_rcu(hw, vif, mt76_connac_mcu_key_iter, gtk_tlv);2347	rcu_read_unlock();2348 2349	memcpy(gtk_tlv->kek, key->kek, NL80211_KEK_LEN);2350	memcpy(gtk_tlv->kck, key->kck, NL80211_KCK_LEN);2351	memcpy(gtk_tlv->replay_ctr, key->replay_ctr, NL80211_REPLAY_CTR_LEN);2352 2353	return mt76_mcu_skb_send_msg(phy->dev, skb,2354				     MCU_UNI_CMD(OFFLOAD), true);2355}2356EXPORT_SYMBOL_GPL(mt76_connac_mcu_update_gtk_rekey);2357 2358static int2359mt76_connac_mcu_set_arp_filter(struct mt76_dev *dev, struct ieee80211_vif *vif,2360			       bool suspend)2361{2362	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;2363	struct {2364		struct {2365			u8 bss_idx;2366			u8 pad[3];2367		} __packed hdr;2368		struct mt76_connac_arpns_tlv arpns;2369	} req = {2370		.hdr = {2371			.bss_idx = mvif->idx,2372		},2373		.arpns = {2374			.tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ARP),2375			.len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)),2376			.mode = suspend,2377		},2378	};2379 2380	return mt76_mcu_send_msg(dev, MCU_UNI_CMD(OFFLOAD), &req,2381				 sizeof(req), true);2382}2383 2384int2385mt76_connac_mcu_set_gtk_rekey(struct mt76_dev *dev, struct ieee80211_vif *vif,2386			      bool suspend)2387{2388	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;2389	struct {2390		struct {2391			u8 bss_idx;2392			u8 pad[3];2393		} __packed hdr;2394		struct mt76_connac_gtk_rekey_tlv gtk_tlv;2395	} __packed req = {2396		.hdr = {2397			.bss_idx = mvif->idx,2398		},2399		.gtk_tlv = {2400			.tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_GTK_REKEY),2401			.len = cpu_to_le16(sizeof(struct mt76_connac_gtk_rekey_tlv)),2402			.rekey_mode = !suspend,2403		},2404	};2405 2406	return mt76_mcu_send_msg(dev, MCU_UNI_CMD(OFFLOAD), &req,2407				 sizeof(req), true);2408}2409EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_gtk_rekey);2410 2411int2412mt76_connac_mcu_set_suspend_mode(struct mt76_dev *dev,2413				 struct ieee80211_vif *vif,2414				 bool enable, u8 mdtim,2415				 bool wow_suspend)2416{2417	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;2418	struct {2419		struct {2420			u8 bss_idx;2421			u8 pad[3];2422		} __packed hdr;2423		struct mt76_connac_suspend_tlv suspend_tlv;2424	} req = {2425		.hdr = {2426			.bss_idx = mvif->idx,2427		},2428		.suspend_tlv = {2429			.tag = cpu_to_le16(UNI_SUSPEND_MODE_SETTING),2430			.len = cpu_to_le16(sizeof(struct mt76_connac_suspend_tlv)),2431			.enable = enable,2432			.mdtim = mdtim,2433			.wow_suspend = wow_suspend,2434		},2435	};2436 2437	return mt76_mcu_send_msg(dev, MCU_UNI_CMD(SUSPEND), &req,2438				 sizeof(req), true);2439}2440EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_suspend_mode);2441 2442static int2443mt76_connac_mcu_set_wow_pattern(struct mt76_dev *dev,2444				struct ieee80211_vif *vif,2445				u8 index, bool enable,2446				struct cfg80211_pkt_pattern *pattern)2447{2448	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;2449	struct mt76_connac_wow_pattern_tlv *ptlv;2450	struct sk_buff *skb;2451	struct req_hdr {2452		u8 bss_idx;2453		u8 pad[3];2454	} __packed hdr = {2455		.bss_idx = mvif->idx,2456	};2457 2458	skb = mt76_mcu_msg_alloc(dev, NULL, sizeof(hdr) + sizeof(*ptlv));2459	if (!skb)2460		return -ENOMEM;2461 2462	skb_put_data(skb, &hdr, sizeof(hdr));2463	ptlv = (struct mt76_connac_wow_pattern_tlv *)skb_put_zero(skb, sizeof(*ptlv));2464	ptlv->tag = cpu_to_le16(UNI_SUSPEND_WOW_PATTERN);2465	ptlv->len = cpu_to_le16(sizeof(*ptlv));2466	ptlv->data_len = pattern->pattern_len;2467	ptlv->enable = enable;2468	ptlv->index = index;2469 2470	memcpy(ptlv->pattern, pattern->pattern, pattern->pattern_len);2471	memcpy(ptlv->mask, pattern->mask, DIV_ROUND_UP(pattern->pattern_len, 8));2472 2473	return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(SUSPEND), true);2474}2475 2476int2477mt76_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,2478			     bool suspend, struct cfg80211_wowlan *wowlan)2479{2480	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;2481	struct mt76_dev *dev = phy->dev;2482	struct {2483		struct {2484			u8 bss_idx;2485			u8 pad[3];2486		} __packed hdr;2487		struct mt76_connac_wow_ctrl_tlv wow_ctrl_tlv;2488		struct mt76_connac_wow_gpio_param_tlv gpio_tlv;2489	} req = {2490		.hdr = {2491			.bss_idx = mvif->idx,2492		},2493		.wow_ctrl_tlv = {2494			.tag = cpu_to_le16(UNI_SUSPEND_WOW_CTRL),2495			.len = cpu_to_le16(sizeof(struct mt76_connac_wow_ctrl_tlv)),2496			.cmd = suspend ? 1 : 2,2497		},2498		.gpio_tlv = {2499			.tag = cpu_to_le16(UNI_SUSPEND_WOW_GPIO_PARAM),2500			.len = cpu_to_le16(sizeof(struct mt76_connac_wow_gpio_param_tlv)),2501			.gpio_pin = 0xff, /* follow fw about GPIO pin */2502		},2503	};2504 2505	if (wowlan->magic_pkt)2506		req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_MAGIC;2507	if (wowlan->disconnect)2508		req.wow_ctrl_tlv.trigger |= (UNI_WOW_DETECT_TYPE_DISCONNECT |2509					     UNI_WOW_DETECT_TYPE_BCN_LOST);2510	if (wowlan->nd_config) {2511		mt76_connac_mcu_sched_scan_req(phy, vif, wowlan->nd_config);2512		req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_SCH_SCAN_HIT;2513		mt76_connac_mcu_sched_scan_enable(phy, vif, suspend);2514	}2515	if (wowlan->n_patterns)2516		req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_BITMAP;2517 2518	if (mt76_is_mmio(dev))2519		req.wow_ctrl_tlv.wakeup_hif = WOW_PCIE;2520	else if (mt76_is_usb(dev))2521		req.wow_ctrl_tlv.wakeup_hif = WOW_USB;2522	else if (mt76_is_sdio(dev))2523		req.wow_ctrl_tlv.wakeup_hif = WOW_GPIO;2524 2525	return mt76_mcu_send_msg(dev, MCU_UNI_CMD(SUSPEND), &req,2526				 sizeof(req), true);2527}2528EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_wow_ctrl);2529 2530int mt76_connac_mcu_set_hif_suspend(struct mt76_dev *dev, bool suspend)2531{2532	struct {2533		struct {2534			u8 hif_type; /* 0x0: HIF_SDIO2535				      * 0x1: HIF_USB2536				      * 0x2: HIF_PCIE2537				      */2538			u8 pad[3];2539		} __packed hdr;2540		struct hif_suspend_tlv {2541			__le16 tag;2542			__le16 len;2543			u8 suspend;2544			u8 pad[7];2545		} __packed hif_suspend;2546	} req = {2547		.hif_suspend = {2548			.tag = cpu_to_le16(0), /* 0: UNI_HIF_CTRL_BASIC */2549			.len = cpu_to_le16(sizeof(struct hif_suspend_tlv)),2550			.suspend = suspend,2551		},2552	};2553 2554	if (mt76_is_mmio(dev))2555		req.hdr.hif_type = 2;2556	else if (mt76_is_usb(dev))2557		req.hdr.hif_type = 1;2558	else if (mt76_is_sdio(dev))2559		req.hdr.hif_type = 0;2560 2561	return mt76_mcu_send_msg(dev, MCU_UNI_CMD(HIF_CTRL), &req,2562				 sizeof(req), true);2563}2564EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_hif_suspend);2565 2566void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac,2567				      struct ieee80211_vif *vif)2568{2569	struct mt76_phy *phy = priv;2570	bool suspend = !test_bit(MT76_STATE_RUNNING, &phy->state);2571	struct ieee80211_hw *hw = phy->hw;2572	struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config;2573	int i;2574 2575	mt76_connac_mcu_set_gtk_rekey(phy->dev, vif, suspend);2576	mt76_connac_mcu_set_arp_filter(phy->dev, vif, suspend);2577 2578	mt76_connac_mcu_set_suspend_mode(phy->dev, vif, suspend, 1, true);2579 2580	for (i = 0; i < wowlan->n_patterns; i++)2581		mt76_connac_mcu_set_wow_pattern(phy->dev, vif, i, suspend,2582						&wowlan->patterns[i]);2583	mt76_connac_mcu_set_wow_ctrl(phy, vif, suspend, wowlan);2584}2585EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_suspend_iter);2586#endif /* CONFIG_PM */2587 2588u32 mt76_connac_mcu_reg_rr(struct mt76_dev *dev, u32 offset)2589{2590	struct {2591		__le32 addr;2592		__le32 val;2593	} __packed req = {2594		.addr = cpu_to_le32(offset),2595	};2596 2597	return mt76_mcu_send_msg(dev, MCU_CE_QUERY(REG_READ), &req,2598				 sizeof(req), true);2599}2600EXPORT_SYMBOL_GPL(mt76_connac_mcu_reg_rr);2601 2602void mt76_connac_mcu_reg_wr(struct mt76_dev *dev, u32 offset, u32 val)2603{2604	struct {2605		__le32 addr;2606		__le32 val;2607	} __packed req = {2608		.addr = cpu_to_le32(offset),2609		.val = cpu_to_le32(val),2610	};2611 2612	mt76_mcu_send_msg(dev, MCU_CE_CMD(REG_WRITE), &req,2613			  sizeof(req), false);2614}2615EXPORT_SYMBOL_GPL(mt76_connac_mcu_reg_wr);2616 2617static int2618mt76_connac_mcu_sta_key_tlv(struct mt76_connac_sta_key_conf *sta_key_conf,2619			    struct sk_buff *skb,2620			    struct ieee80211_key_conf *key,2621			    enum set_key_cmd cmd)2622{2623	struct sta_rec_sec *sec;2624	u32 len = sizeof(*sec);2625	struct tlv *tlv;2626 2627	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_KEY_V2, sizeof(*sec));2628	sec = (struct sta_rec_sec *)tlv;2629	sec->add = cmd;2630 2631	if (cmd == SET_KEY) {2632		struct sec_key *sec_key;2633		u8 cipher;2634 2635		cipher = mt76_connac_mcu_get_cipher(key->cipher);2636		if (cipher == MCU_CIPHER_NONE)2637			return -EOPNOTSUPP;2638 2639		sec_key = &sec->key[0];2640		sec_key->cipher_len = sizeof(*sec_key);2641 2642		if (cipher == MCU_CIPHER_BIP_CMAC_128) {2643			sec_key->cipher_id = MCU_CIPHER_AES_CCMP;2644			sec_key->key_id = sta_key_conf->keyidx;2645			sec_key->key_len = 16;2646			memcpy(sec_key->key, sta_key_conf->key, 16);2647 2648			sec_key = &sec->key[1];2649			sec_key->cipher_id = MCU_CIPHER_BIP_CMAC_128;2650			sec_key->cipher_len = sizeof(*sec_key);2651			sec_key->key_len = 16;2652			memcpy(sec_key->key, key->key, 16);2653			sec->n_cipher = 2;2654		} else {2655			sec_key->cipher_id = cipher;2656			sec_key->key_id = key->keyidx;2657			sec_key->key_len = key->keylen;2658			memcpy(sec_key->key, key->key, key->keylen);2659 2660			if (cipher == MCU_CIPHER_TKIP) {2661				/* Rx/Tx MIC keys are swapped */2662				memcpy(sec_key->key + 16, key->key + 24, 8);2663				memcpy(sec_key->key + 24, key->key + 16, 8);2664			}2665 2666			/* store key_conf for BIP batch update */2667			if (cipher == MCU_CIPHER_AES_CCMP) {2668				memcpy(sta_key_conf->key, key->key, key->keylen);2669				sta_key_conf->keyidx = key->keyidx;2670			}2671 2672			len -= sizeof(*sec_key);2673			sec->n_cipher = 1;2674		}2675	} else {2676		len -= sizeof(sec->key);2677		sec->n_cipher = 0;2678	}2679	sec->len = cpu_to_le16(len);2680 2681	return 0;2682}2683 2684int mt76_connac_mcu_add_key(struct mt76_dev *dev, struct ieee80211_vif *vif,2685			    struct mt76_connac_sta_key_conf *sta_key_conf,2686			    struct ieee80211_key_conf *key, int mcu_cmd,2687			    struct mt76_wcid *wcid, enum set_key_cmd cmd)2688{2689	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;2690	struct sk_buff *skb;2691	int ret;2692 2693	skb = mt76_connac_mcu_alloc_sta_req(dev, mvif, wcid);2694	if (IS_ERR(skb))2695		return PTR_ERR(skb);2696 2697	ret = mt76_connac_mcu_sta_key_tlv(sta_key_conf, skb, key, cmd);2698	if (ret)2699		return ret;2700 2701	ret = mt76_connac_mcu_sta_wed_update(dev, skb);2702	if (ret)2703		return ret;2704 2705	return mt76_mcu_skb_send_msg(dev, skb, mcu_cmd, true);2706}2707EXPORT_SYMBOL_GPL(mt76_connac_mcu_add_key);2708 2709/* SIFS 20us + 512 byte beacon transmitted by 1Mbps (3906us) */2710#define BCN_TX_ESTIMATE_TIME (4096 + 20)2711void mt76_connac_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt76_vif *mvif)2712{2713	struct bss_info_ext_bss *ext;2714	int ext_bss_idx, tsf_offset;2715	struct tlv *tlv;2716 2717	ext_bss_idx = mvif->omac_idx - EXT_BSSID_START;2718	if (ext_bss_idx < 0)2719		return;2720 2721	tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_EXT_BSS, sizeof(*ext));2722 2723	ext = (struct bss_info_ext_bss *)tlv;2724	tsf_offset = ext_bss_idx * BCN_TX_ESTIMATE_TIME;2725	ext->mbss_tsf_offset = cpu_to_le32(tsf_offset);2726}2727EXPORT_SYMBOL_GPL(mt76_connac_mcu_bss_ext_tlv);2728 2729int mt76_connac_mcu_bss_basic_tlv(struct sk_buff *skb,2730				  struct ieee80211_vif *vif,2731				  struct ieee80211_sta *sta,2732				  struct mt76_phy *phy, u16 wlan_idx,2733				  bool enable)2734{2735	struct mt76_vif *mvif = (struct mt76_vif *)vif->drv_priv;2736	u32 type = vif->p2p ? NETWORK_P2P : NETWORK_INFRA;2737	struct bss_info_basic *bss;2738	struct tlv *tlv;2739 2740	tlv = mt76_connac_mcu_add_tlv(skb, BSS_INFO_BASIC, sizeof(*bss));2741	bss = (struct bss_info_basic *)tlv;2742 2743	switch (vif->type) {2744	case NL80211_IFTYPE_MESH_POINT:2745	case NL80211_IFTYPE_MONITOR:2746		break;2747	case NL80211_IFTYPE_AP:2748		if (ieee80211_hw_check(phy->hw, SUPPORTS_MULTI_BSSID)) {2749			u8 bssid_id = vif->bss_conf.bssid_indicator;2750			struct wiphy *wiphy = phy->hw->wiphy;2751 2752			if (bssid_id > ilog2(wiphy->mbssid_max_interfaces))2753				return -EINVAL;2754 2755			bss->non_tx_bssid = vif->bss_conf.bssid_index;2756			bss->max_bssid = bssid_id;2757		}2758		break;2759	case NL80211_IFTYPE_STATION:2760		if (enable) {2761			rcu_read_lock();2762			if (!sta)2763				sta = ieee80211_find_sta(vif,2764							 vif->bss_conf.bssid);2765			/* TODO: enable BSS_INFO_UAPSD & BSS_INFO_PM */2766			if (sta) {2767				struct mt76_wcid *wcid;2768 2769				wcid = (struct mt76_wcid *)sta->drv_priv;2770				wlan_idx = wcid->idx;2771			}2772			rcu_read_unlock();2773		}2774		break;2775	case NL80211_IFTYPE_ADHOC:2776		type = NETWORK_IBSS;2777		break;2778	default:2779		WARN_ON(1);2780		break;2781	}2782 2783	bss->network_type = cpu_to_le32(type);2784	bss->bmc_wcid_lo = to_wcid_lo(wlan_idx);2785	bss->bmc_wcid_hi = to_wcid_hi(wlan_idx);2786	bss->wmm_idx = mvif->wmm_idx;2787	bss->active = enable;2788	bss->cipher = mvif->cipher;2789 2790	if (vif->type != NL80211_IFTYPE_MONITOR) {2791		struct cfg80211_chan_def *chandef = &phy->chandef;2792 2793		memcpy(bss->bssid, vif->bss_conf.bssid, ETH_ALEN);2794		bss->bcn_interval = cpu_to_le16(vif->bss_conf.beacon_int);2795		bss->dtim_period = vif->bss_conf.dtim_period;2796		bss->phy_mode = mt76_connac_get_phy_mode(phy, vif,2797							 chandef->chan->band, NULL);2798	} else {2799		memcpy(bss->bssid, phy->macaddr, ETH_ALEN);2800	}2801 2802	return 0;2803}2804EXPORT_SYMBOL_GPL(mt76_connac_mcu_bss_basic_tlv);2805 2806#define ENTER_PM_STATE		12807#define EXIT_PM_STATE		22808int mt76_connac_mcu_set_pm(struct mt76_dev *dev, int band, int enter)2809{2810	struct {2811		u8 pm_number;2812		u8 pm_state;2813		u8 bssid[ETH_ALEN];2814		u8 dtim_period;2815		u8 wlan_idx_lo;2816		__le16 bcn_interval;2817		__le32 aid;2818		__le32 rx_filter;2819		u8 band_idx;2820		u8 wlan_idx_hi;2821		u8 rsv[2];2822		__le32 feature;2823		u8 omac_idx;2824		u8 wmm_idx;2825		u8 bcn_loss_cnt;2826		u8 bcn_sp_duration;2827	} __packed req = {2828		.pm_number = 5,2829		.pm_state = enter ? ENTER_PM_STATE : EXIT_PM_STATE,2830		.band_idx = band,2831	};2832 2833	return mt76_mcu_send_msg(dev, MCU_EXT_CMD(PM_STATE_CTRL), &req,2834				 sizeof(req), true);2835}2836EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_pm);2837 2838int mt76_connac_mcu_restart(struct mt76_dev *dev)2839{2840	struct {2841		u8 power_mode;2842		u8 rsv[3];2843	} req = {2844		.power_mode = 1,2845	};2846 2847	return mt76_mcu_send_msg(dev, MCU_CMD(NIC_POWER_CTRL), &req,2848				 sizeof(req), false);2849}2850EXPORT_SYMBOL_GPL(mt76_connac_mcu_restart);2851 2852int mt76_connac_mcu_del_wtbl_all(struct mt76_dev *dev)2853{2854	struct wtbl_req_hdr req = {2855		.operation = WTBL_RESET_ALL,2856	};2857 2858	return mt76_mcu_send_msg(dev, MCU_EXT_CMD(WTBL_UPDATE),2859				 &req, sizeof(req), true);2860}2861EXPORT_SYMBOL_GPL(mt76_connac_mcu_del_wtbl_all);2862 2863int mt76_connac_mcu_rdd_cmd(struct mt76_dev *dev, int cmd, u8 index,2864			    u8 rx_sel, u8 val)2865{2866	struct {2867		u8 ctrl;2868		u8 rdd_idx;2869		u8 rdd_rx_sel;2870		u8 val;2871		u8 rsv[4];2872	} __packed req = {2873		.ctrl = cmd,2874		.rdd_idx = index,2875		.rdd_rx_sel = rx_sel,2876		.val = val,2877	};2878 2879	return mt76_mcu_send_msg(dev, MCU_EXT_CMD(SET_RDD_CTRL), &req,2880				 sizeof(req), true);2881}2882EXPORT_SYMBOL_GPL(mt76_connac_mcu_rdd_cmd);2883 2884static int2885mt76_connac_mcu_send_ram_firmware(struct mt76_dev *dev,2886				  const struct mt76_connac2_fw_trailer *hdr,2887				  const u8 *data, bool is_wa)2888{2889	int i, offset = 0, max_len = mt76_is_sdio(dev) ? 2048 : 4096;2890	u32 override = 0, option = 0;2891 2892	for (i = 0; i < hdr->n_region; i++) {2893		const struct mt76_connac2_fw_region *region;2894		u32 len, addr, mode;2895		int err;2896 2897		region = (const void *)((const u8 *)hdr -2898					(hdr->n_region - i) * sizeof(*region));2899		mode = mt76_connac_mcu_gen_dl_mode(dev, region->feature_set,2900						   is_wa);2901		len = le32_to_cpu(region->len);2902		addr = le32_to_cpu(region->addr);2903 2904		if (region->feature_set & FW_FEATURE_NON_DL)2905			goto next;2906 2907		if (region->feature_set & FW_FEATURE_OVERRIDE_ADDR)2908			override = addr;2909 2910		err = mt76_connac_mcu_init_download(dev, addr, len, mode);2911		if (err) {2912			dev_err(dev->dev, "Download request failed\n");2913			return err;2914		}2915 2916		err = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),2917					       data + offset, len, max_len);2918		if (err) {2919			dev_err(dev->dev, "Failed to send firmware.\n");2920			return err;2921		}2922 2923next:2924		offset += len;2925	}2926 2927	if (override)2928		option |= FW_START_OVERRIDE;2929	if (is_wa)2930		option |= FW_START_WORKING_PDA_CR4;2931 2932	return mt76_connac_mcu_start_firmware(dev, override, option);2933}2934 2935int mt76_connac2_load_ram(struct mt76_dev *dev, const char *fw_wm,2936			  const char *fw_wa)2937{2938	const struct mt76_connac2_fw_trailer *hdr;2939	const struct firmware *fw;2940	int ret;2941 2942	ret = request_firmware(&fw, fw_wm, dev->dev);2943	if (ret)2944		return ret;2945 2946	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {2947		dev_err(dev->dev, "Invalid firmware\n");2948		ret = -EINVAL;2949		goto out;2950	}2951 2952	hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));2953	dev_info(dev->dev, "WM Firmware Version: %.10s, Build Time: %.15s\n",2954		 hdr->fw_ver, hdr->build_date);2955 2956	ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, false);2957	if (ret) {2958		dev_err(dev->dev, "Failed to start WM firmware\n");2959		goto out;2960	}2961 2962	snprintf(dev->hw->wiphy->fw_version,2963		 sizeof(dev->hw->wiphy->fw_version),2964		 "%.10s-%.15s", hdr->fw_ver, hdr->build_date);2965 2966	release_firmware(fw);2967 2968	if (!fw_wa)2969		return 0;2970 2971	ret = request_firmware(&fw, fw_wa, dev->dev);2972	if (ret)2973		return ret;2974 2975	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {2976		dev_err(dev->dev, "Invalid firmware\n");2977		ret = -EINVAL;2978		goto out;2979	}2980 2981	hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));2982	dev_info(dev->dev, "WA Firmware Version: %.10s, Build Time: %.15s\n",2983		 hdr->fw_ver, hdr->build_date);2984 2985	ret = mt76_connac_mcu_send_ram_firmware(dev, hdr, fw->data, true);2986	if (ret) {2987		dev_err(dev->dev, "Failed to start WA firmware\n");2988		goto out;2989	}2990 2991	snprintf(dev->hw->wiphy->fw_version,2992		 sizeof(dev->hw->wiphy->fw_version),2993		 "%.10s-%.15s", hdr->fw_ver, hdr->build_date);2994 2995out:2996	release_firmware(fw);2997 2998	return ret;2999}3000EXPORT_SYMBOL_GPL(mt76_connac2_load_ram);3001 3002static u32 mt76_connac2_get_data_mode(struct mt76_dev *dev, u32 info)3003{3004	u32 mode = DL_MODE_NEED_RSP;3005 3006	if ((!is_mt7921(dev) && !is_mt7925(dev)) || info == PATCH_SEC_NOT_SUPPORT)3007		return mode;3008 3009	switch (FIELD_GET(PATCH_SEC_ENC_TYPE_MASK, info)) {3010	case PATCH_SEC_ENC_TYPE_PLAIN:3011		break;3012	case PATCH_SEC_ENC_TYPE_AES:3013		mode |= DL_MODE_ENCRYPT;3014		mode |= FIELD_PREP(DL_MODE_KEY_IDX,3015				(info & PATCH_SEC_ENC_AES_KEY_MASK)) & DL_MODE_KEY_IDX;3016		mode |= DL_MODE_RESET_SEC_IV;3017		break;3018	case PATCH_SEC_ENC_TYPE_SCRAMBLE:3019		mode |= DL_MODE_ENCRYPT;3020		mode |= DL_CONFIG_ENCRY_MODE_SEL;3021		mode |= DL_MODE_RESET_SEC_IV;3022		break;3023	default:3024		dev_err(dev->dev, "Encryption type not support!\n");3025	}3026 3027	return mode;3028}3029 3030int mt76_connac2_load_patch(struct mt76_dev *dev, const char *fw_name)3031{3032	int i, ret, sem, max_len = mt76_is_sdio(dev) ? 2048 : 4096;3033	const struct mt76_connac2_patch_hdr *hdr;3034	const struct firmware *fw = NULL;3035 3036	sem = mt76_connac_mcu_patch_sem_ctrl(dev, true);3037	switch (sem) {3038	case PATCH_IS_DL:3039		return 0;3040	case PATCH_NOT_DL_SEM_SUCCESS:3041		break;3042	default:3043		dev_err(dev->dev, "Failed to get patch semaphore\n");3044		return -EAGAIN;3045	}3046 3047	ret = request_firmware(&fw, fw_name, dev->dev);3048	if (ret)3049		goto out;3050 3051	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {3052		dev_err(dev->dev, "Invalid firmware\n");3053		ret = -EINVAL;3054		goto out;3055	}3056 3057	hdr = (const void *)fw->data;3058	dev_info(dev->dev, "HW/SW Version: 0x%x, Build Time: %.16s\n",3059		 be32_to_cpu(hdr->hw_sw_ver), hdr->build_date);3060 3061	for (i = 0; i < be32_to_cpu(hdr->desc.n_region); i++) {3062		struct mt76_connac2_patch_sec *sec;3063		u32 len, addr, mode;3064		const u8 *dl;3065		u32 sec_info;3066 3067		sec = (void *)(fw->data + sizeof(*hdr) + i * sizeof(*sec));3068		if ((be32_to_cpu(sec->type) & PATCH_SEC_TYPE_MASK) !=3069		    PATCH_SEC_TYPE_INFO) {3070			ret = -EINVAL;3071			goto out;3072		}3073 3074		addr = be32_to_cpu(sec->info.addr);3075		len = be32_to_cpu(sec->info.len);3076		dl = fw->data + be32_to_cpu(sec->offs);3077		sec_info = be32_to_cpu(sec->info.sec_key_idx);3078		mode = mt76_connac2_get_data_mode(dev, sec_info);3079 3080		ret = mt76_connac_mcu_init_download(dev, addr, len, mode);3081		if (ret) {3082			dev_err(dev->dev, "Download request failed\n");3083			goto out;3084		}3085 3086		ret = __mt76_mcu_send_firmware(dev, MCU_CMD(FW_SCATTER),3087					       dl, len, max_len);3088		if (ret) {3089			dev_err(dev->dev, "Failed to send patch\n");3090			goto out;3091		}3092	}3093 3094	ret = mt76_connac_mcu_start_patch(dev);3095	if (ret)3096		dev_err(dev->dev, "Failed to start patch\n");3097 3098out:3099	sem = mt76_connac_mcu_patch_sem_ctrl(dev, false);3100	switch (sem) {3101	case PATCH_REL_SEM_SUCCESS:3102		break;3103	default:3104		ret = -EAGAIN;3105		dev_err(dev->dev, "Failed to release patch semaphore\n");3106		break;3107	}3108 3109	release_firmware(fw);3110 3111	return ret;3112}3113EXPORT_SYMBOL_GPL(mt76_connac2_load_patch);3114 3115int mt76_connac2_mcu_fill_message(struct mt76_dev *dev, struct sk_buff *skb,3116				  int cmd, int *wait_seq)3117{3118	int txd_len, mcu_cmd = FIELD_GET(__MCU_CMD_FIELD_ID, cmd);3119	struct mt76_connac2_mcu_uni_txd *uni_txd;3120	struct mt76_connac2_mcu_txd *mcu_txd;3121	__le32 *txd;3122	u32 val;3123	u8 seq;3124 3125	/* TODO: make dynamic based on msg type */3126	dev->mcu.timeout = 20 * HZ;3127 3128	seq = ++dev->mcu.msg_seq & 0xf;3129	if (!seq)3130		seq = ++dev->mcu.msg_seq & 0xf;3131 3132	if (cmd == MCU_CMD(FW_SCATTER))3133		goto exit;3134 3135	txd_len = cmd & __MCU_CMD_FIELD_UNI ? sizeof(*uni_txd) : sizeof(*mcu_txd);3136	txd = (__le32 *)skb_push(skb, txd_len);3137 3138	val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len) |3139	      FIELD_PREP(MT_TXD0_PKT_FMT, MT_TX_TYPE_CMD) |3140	      FIELD_PREP(MT_TXD0_Q_IDX, MT_TX_MCU_PORT_RX_Q0);3141	txd[0] = cpu_to_le32(val);3142 3143	val = MT_TXD1_LONG_FORMAT |3144	      FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_CMD);3145	txd[1] = cpu_to_le32(val);3146 3147	if (cmd & __MCU_CMD_FIELD_UNI) {3148		uni_txd = (struct mt76_connac2_mcu_uni_txd *)txd;3149		uni_txd->len = cpu_to_le16(skb->len - sizeof(uni_txd->txd));3150		uni_txd->option = MCU_CMD_UNI_EXT_ACK;3151		uni_txd->cid = cpu_to_le16(mcu_cmd);3152		uni_txd->s2d_index = MCU_S2D_H2N;3153		uni_txd->pkt_type = MCU_PKT_ID;3154		uni_txd->seq = seq;3155 3156		goto exit;3157	}3158 3159	mcu_txd = (struct mt76_connac2_mcu_txd *)txd;3160	mcu_txd->len = cpu_to_le16(skb->len - sizeof(mcu_txd->txd));3161	mcu_txd->pq_id = cpu_to_le16(MCU_PQ_ID(MT_TX_PORT_IDX_MCU,3162					       MT_TX_MCU_PORT_RX_Q0));3163	mcu_txd->pkt_type = MCU_PKT_ID;3164	mcu_txd->seq = seq;3165	mcu_txd->cid = mcu_cmd;3166	mcu_txd->ext_cid = FIELD_GET(__MCU_CMD_FIELD_EXT_ID, cmd);3167 3168	if (mcu_txd->ext_cid || (cmd & __MCU_CMD_FIELD_CE)) {3169		if (cmd & __MCU_CMD_FIELD_QUERY)3170			mcu_txd->set_query = MCU_Q_QUERY;3171		else3172			mcu_txd->set_query = MCU_Q_SET;3173		mcu_txd->ext_cid_ack = !!mcu_txd->ext_cid;3174	} else {3175		mcu_txd->set_query = MCU_Q_NA;3176	}3177 3178	if (cmd & __MCU_CMD_FIELD_WA)3179		mcu_txd->s2d_index = MCU_S2D_H2C;3180	else3181		mcu_txd->s2d_index = MCU_S2D_H2N;3182 3183exit:3184	if (wait_seq)3185		*wait_seq = seq;3186 3187	return 0;3188}3189EXPORT_SYMBOL_GPL(mt76_connac2_mcu_fill_message);3190 3191MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");3192MODULE_DESCRIPTION("MediaTek MT76x connac layer helpers");3193MODULE_LICENSE("Dual BSD/GPL");3194