diff options
Diffstat (limited to 'sys/contrib/dev/mediatek/mt76/mt7925/mcu.c')
| -rw-r--r-- | sys/contrib/dev/mediatek/mt76/mt7925/mcu.c | 522 | 
1 files changed, 366 insertions, 156 deletions
| diff --git a/sys/contrib/dev/mediatek/mt76/mt7925/mcu.c b/sys/contrib/dev/mediatek/mt76/mt7925/mcu.c index f1be88f3b00b..d62d461db699 100644 --- a/sys/contrib/dev/mediatek/mt76/mt7925/mcu.c +++ b/sys/contrib/dev/mediatek/mt76/mt7925/mcu.c @@ -164,6 +164,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,  			       bool suspend, struct cfg80211_wowlan *wowlan)  {  	struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; +	struct ieee80211_scan_ies ies = {};  	struct mt76_dev *dev = phy->dev;  	struct {  		struct { @@ -194,7 +195,7 @@ mt7925_connac_mcu_set_wow_ctrl(struct mt76_phy *phy, struct ieee80211_vif *vif,  		req.wow_ctrl_tlv.trigger |= (UNI_WOW_DETECT_TYPE_DISCONNECT |  					     UNI_WOW_DETECT_TYPE_BCN_LOST);  	if (wowlan->nd_config) { -		mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config); +		mt7925_mcu_sched_scan_req(phy, vif, wowlan->nd_config, &ies);  		req.wow_ctrl_tlv.trigger |= UNI_WOW_DETECT_TYPE_SCH_SCAN_HIT;  		mt7925_mcu_sched_scan_enable(phy, vif, suspend);  	} @@ -348,14 +349,10 @@ mt7925_mcu_handle_hif_ctrl_basic(struct mt792x_dev *dev, struct tlv *tlv)  	basic = (struct mt7925_mcu_hif_ctrl_basic_tlv *)tlv;  	if (basic->hifsuspend) { -		if (basic->hif_tx_traffic_status == HIF_TRAFFIC_IDLE && -		    basic->hif_rx_traffic_status == HIF_TRAFFIC_IDLE) -			/* success */ -			dev->hif_idle = true; -		else -			/* busy */ -			/* invalid */ -			dev->hif_idle = false; +		dev->hif_idle = true; +		if (!(basic->hif_tx_traffic_status == HIF_TRAFFIC_IDLE && +		      basic->hif_rx_traffic_status == HIF_TRAFFIC_IDLE)) +			dev_info(dev->mt76.dev, "Hif traffic not idle.\n");  	} else {  		dev->hif_resumed = true;  	} @@ -576,10 +573,10 @@ void mt7925_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb)  static int  mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif, -		  struct mt76_wcid *wcid,  		  struct ieee80211_ampdu_params *params,  		  bool enable, bool tx)  { +	struct mt76_wcid *wcid = (struct mt76_wcid *)params->sta->drv_priv;  	struct sta_rec_ba_uni *ba;  	struct sk_buff *skb;  	struct tlv *tlv; @@ -607,60 +604,76 @@ mt7925_mcu_sta_ba(struct mt76_dev *dev, struct mt76_vif_link *mvif,  /** starec & wtbl **/  int mt7925_mcu_uni_tx_ba(struct mt792x_dev *dev, -			 struct ieee80211_vif *vif,  			 struct ieee80211_ampdu_params *params,  			 bool enable)  {  	struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv; -	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; -	struct mt792x_link_sta *mlink; -	struct mt792x_bss_conf *mconf; -	unsigned long usable_links = ieee80211_vif_usable_links(vif); -	struct mt76_wcid *wcid; -	u8 link_id, ret; - -	for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { -		mconf = mt792x_vif_to_link(mvif, link_id); -		mlink = mt792x_sta_to_link(msta, link_id); -		wcid = &mlink->wcid; - -		if (enable && !params->amsdu) -			mlink->wcid.amsdu = false; +	struct mt792x_vif *mvif = msta->vif; -		ret = mt7925_mcu_sta_ba(&dev->mt76, &mconf->mt76, wcid, params, -					enable, true); -		if (ret < 0) -			break; -	} +	if (enable && !params->amsdu) +		msta->deflink.wcid.amsdu = false; -	return ret; +	return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params, +				 enable, true);  }  int mt7925_mcu_uni_rx_ba(struct mt792x_dev *dev, -			 struct ieee80211_vif *vif,  			 struct ieee80211_ampdu_params *params,  			 bool enable)  {  	struct mt792x_sta *msta = (struct mt792x_sta *)params->sta->drv_priv; -	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; -	struct mt792x_link_sta *mlink; -	struct mt792x_bss_conf *mconf; -	unsigned long usable_links = ieee80211_vif_usable_links(vif); -	struct mt76_wcid *wcid; -	u8 link_id, ret; +	struct mt792x_vif *mvif = msta->vif; -	for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) { -		mconf = mt792x_vif_to_link(mvif, link_id); -		mlink = mt792x_sta_to_link(msta, link_id); -		wcid = &mlink->wcid; +	return mt7925_mcu_sta_ba(&dev->mt76, &mvif->bss_conf.mt76, params, +				 enable, false); +} -		ret = mt7925_mcu_sta_ba(&dev->mt76, &mconf->mt76, wcid, params, -					enable, false); -		if (ret < 0) -			break; -	} +static int mt7925_mcu_read_eeprom(struct mt792x_dev *dev, u32 offset, u8 *val) +{ +	struct { +		u8 rsv[4]; -	return ret; +		__le16 tag; +		__le16 len; + +		__le32 addr; +		__le32 valid; +		u8 data[MT7925_EEPROM_BLOCK_SIZE]; +	} __packed req = { +		.tag = cpu_to_le16(1), +		.len = cpu_to_le16(sizeof(req) - 4), +		.addr = cpu_to_le32(round_down(offset, +				    MT7925_EEPROM_BLOCK_SIZE)), +	}; +	struct evt { +		u8 rsv[4]; + +		__le16 tag; +		__le16 len; + +		__le32 ver; +		__le32 addr; +		__le32 valid; +		__le32 size; +		__le32 magic_num; +		__le32 type; +		__le32 rsv1[4]; +		u8 data[32]; +	} __packed *res; +	struct sk_buff *skb; +	int ret; + +	ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_WM_UNI_CMD_QUERY(EFUSE_CTRL), +					&req, sizeof(req), true, &skb); +	if (ret) +		return ret; + +	res = (struct evt *)skb->data; +	*val = res->data[offset % MT7925_EEPROM_BLOCK_SIZE]; + +	dev_kfree_skb(skb); + +	return 0;  }  static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name) @@ -671,17 +684,26 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)  	struct mt76_dev *mdev = &dev->mt76;  	struct mt792x_phy *phy = &dev->phy;  	const struct firmware *fw; -	int ret, i, len, offset = 0;  #if defined(__linux__) -	u8 *clc_base = NULL; +	u8 *clc_base = NULL, hw_encap = 0;  #elif defined(__FreeBSD__)  	const u8 *clc_base = NULL; +	u8 hw_encap = 0;  #endif +	int ret, i, len, offset = 0; +	dev->phy.clc_chan_conf = 0xff;  	if (mt7925_disable_clc ||  	    mt76_is_usb(&dev->mt76))  		return 0; +	if (mt76_is_mmio(&dev->mt76)) { +		ret = mt7925_mcu_read_eeprom(dev, MT_EE_HW_TYPE, &hw_encap); +		if (ret) +			return ret; +		hw_encap = u8_get_bits(hw_encap, MT_EE_HW_TYPE_ENCAP); +	} +  	ret = request_firmware(&fw, fw_name, mdev->dev);  	if (ret)  		return ret; @@ -730,6 +752,12 @@ static int mt7925_load_clc(struct mt792x_dev *dev, const char *fw_name)  		if (phy->clc[clc->idx])  			continue; +		/* header content sanity */ +		if ((clc->idx == MT792x_CLC_BE_CTRL && +		     u8_get_bits(clc->t2.type, MT_EE_HW_TYPE_ENCAP) != hw_encap) || +		    u8_get_bits(clc->t0.type, MT_EE_HW_TYPE_ENCAP) != hw_encap) +			continue; +  		phy->clc[clc->idx] = devm_kmemdup(mdev->dev, clc,  						  le32_to_cpu(clc->len),  						  GFP_KERNEL); @@ -765,7 +793,7 @@ int mt7925_mcu_fw_log_2_host(struct mt792x_dev *dev, u8 ctrl)  	int ret;  	ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(WSYS_CONFIG), -					&req, sizeof(req), false, NULL); +					&req, sizeof(req), true, NULL);  	return ret;  } @@ -836,7 +864,6 @@ mt7925_mcu_parse_phy_cap(struct mt792x_dev *dev, char *data)  	mdev->phy.chainmask = mdev->phy.antenna_mask;  	mdev->phy.cap.has_2ghz = cap->hw_path & BIT(WF0_24G);  	mdev->phy.cap.has_5ghz = cap->hw_path & BIT(WF0_5G); -	dev->has_eht = cap->eht;  }  static void @@ -957,6 +984,23 @@ int mt7925_mcu_set_deep_sleep(struct mt792x_dev *dev, bool enable)  }  EXPORT_SYMBOL_GPL(mt7925_mcu_set_deep_sleep); +int mt7925_mcu_set_thermal_protect(struct mt792x_dev *dev) +{ +	char cmd[64]; +	int ret = 0; + +	snprintf(cmd, sizeof(cmd), "ThermalProtGband %d %d %d %d %d %d %d %d %d %d", +		 0, 100, 90, 80, 30, 1, 1, 115, 105, 5); +	ret = mt7925_mcu_chip_config(dev, cmd); + +	snprintf(cmd, sizeof(cmd), "ThermalProtAband %d %d %d %d %d %d %d %d %d %d", +		 1, 100, 90, 80, 30, 1, 1, 115, 105, 5); +	ret |= mt7925_mcu_chip_config(dev, cmd); + +	return ret; +} +EXPORT_SYMBOL_GPL(mt7925_mcu_set_thermal_protect); +  int mt7925_run_firmware(struct mt792x_dev *dev)  {  	int err; @@ -1407,7 +1451,7 @@ int mt7925_mcu_set_eeprom(struct mt792x_dev *dev)  	};  	return mt76_mcu_send_and_get_msg(&dev->mt76, MCU_UNI_CMD(EFUSE_CTRL), -					 &req, sizeof(req), false, NULL); +					 &req, sizeof(req), true, NULL);  }  EXPORT_SYMBOL_GPL(mt7925_mcu_set_eeprom); @@ -1799,13 +1843,13 @@ mt7925_mcu_sta_eht_mld_tlv(struct sk_buff *skb,  	struct tlv *tlv;  	u16 eml_cap; +	if (!ieee80211_vif_is_mld(vif)) +		return; +  	tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_EHT_MLD, sizeof(*eht_mld));  	eht_mld = (struct sta_rec_eht_mld *)tlv;  	eht_mld->mld_type = 0xff; -	if (!ieee80211_vif_is_mld(vif)) -		return; -  	ext_capa = cfg80211_get_iftype_ext_capa(wiphy,  						ieee80211_vif_type_p2p(vif));  	if (!ext_capa) @@ -1858,49 +1902,6 @@ mt7925_mcu_sta_mld_tlv(struct sk_buff *skb,  	}  } -static int -mt7925_mcu_sta_cmd(struct mt76_phy *phy, -		   struct mt76_sta_cmd_info *info) -{ -	struct mt76_vif_link *mvif = (struct mt76_vif_link *)info->vif->drv_priv; -	struct mt76_dev *dev = phy->dev; -	struct sk_buff *skb; -	int conn_state; - -	skb = __mt76_connac_mcu_alloc_sta_req(dev, mvif, info->wcid, -					      MT7925_STA_UPDATE_MAX_SIZE); -	if (IS_ERR(skb)) -		return PTR_ERR(skb); - -	conn_state = info->enable ? CONN_STATE_PORT_SECURE : -				    CONN_STATE_DISCONNECT; -	if (info->link_sta) -		mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf, -					      info->link_sta, -					      conn_state, info->newly); -	if (info->link_sta && info->enable) { -		mt7925_mcu_sta_phy_tlv(skb, info->vif, info->link_sta); -		mt7925_mcu_sta_ht_tlv(skb, info->link_sta); -		mt7925_mcu_sta_vht_tlv(skb, info->link_sta); -		mt76_connac_mcu_sta_uapsd(skb, info->vif, info->link_sta->sta); -		mt7925_mcu_sta_amsdu_tlv(skb, info->vif, info->link_sta); -		mt7925_mcu_sta_he_tlv(skb, info->link_sta); -		mt7925_mcu_sta_he_6g_tlv(skb, info->link_sta); -		mt7925_mcu_sta_eht_tlv(skb, info->link_sta); -		mt7925_mcu_sta_rate_ctrl_tlv(skb, info->vif, -					     info->link_sta); -		mt7925_mcu_sta_state_v2_tlv(phy, skb, info->link_sta, -					    info->vif, info->rcpi, -					    info->state); -		mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta); -	} - -	if (info->enable) -		mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta); - -	return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true); -} -  static void  mt7925_mcu_sta_remove_tlv(struct sk_buff *skb)  { @@ -1913,13 +1914,14 @@ mt7925_mcu_sta_remove_tlv(struct sk_buff *skb)  }  static int -mt7925_mcu_mlo_sta_cmd(struct mt76_phy *phy, -		       struct mt76_sta_cmd_info *info) +mt7925_mcu_sta_cmd(struct mt76_phy *phy, +		   struct mt76_sta_cmd_info *info)  {  	struct mt792x_vif *mvif = (struct mt792x_vif *)info->vif->drv_priv;  	struct mt76_dev *dev = phy->dev;  	struct mt792x_bss_conf *mconf;  	struct sk_buff *skb; +	int conn_state;  	mconf = mt792x_vif_to_link(mvif, info->wcid->link_id); @@ -1928,12 +1930,13 @@ mt7925_mcu_mlo_sta_cmd(struct mt76_phy *phy,  	if (IS_ERR(skb))  		return PTR_ERR(skb); -	if (info->enable) -		mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf, -					      info->link_sta, -					      info->enable, info->newly); +	conn_state = info->enable ? CONN_STATE_PORT_SECURE : +				    CONN_STATE_DISCONNECT;  	if (info->enable && info->link_sta) { +		mt76_connac_mcu_sta_basic_tlv(dev, skb, info->link_conf, +					      info->link_sta, +					      conn_state, info->newly);  		mt7925_mcu_sta_phy_tlv(skb, info->vif, info->link_sta);  		mt7925_mcu_sta_ht_tlv(skb, info->link_sta);  		mt7925_mcu_sta_vht_tlv(skb, info->link_sta); @@ -1952,14 +1955,14 @@ mt7925_mcu_mlo_sta_cmd(struct mt76_phy *phy,  			mt7925_mcu_sta_mld_tlv(skb, info->vif, info->link_sta->sta);  			mt7925_mcu_sta_eht_mld_tlv(skb, info->vif, info->link_sta->sta);  		} - -		mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta);  	}  	if (!info->enable) {  		mt7925_mcu_sta_remove_tlv(skb);  		mt76_connac_mcu_add_tlv(skb, STA_REC_MLD_OFF,  					sizeof(struct tlv)); +	} else { +		mt7925_mcu_sta_hdr_trans_tlv(skb, info->vif, info->link_sta);  	}  	return mt76_mcu_skb_send_msg(dev, skb, info->cmd, true); @@ -1984,25 +1987,15 @@ int mt7925_mcu_sta_update(struct mt792x_dev *dev,  	};  	struct mt792x_sta *msta;  	struct mt792x_link_sta *mlink; -	int err;  	if (link_sta) {  		msta = (struct mt792x_sta *)link_sta->sta->drv_priv;  		mlink = mt792x_sta_to_link(msta, link_sta->link_id);  	}  	info.wcid = link_sta ? &mlink->wcid : &mvif->sta.deflink.wcid; +	info.newly = state != MT76_STA_INFO_STATE_ASSOC; -	if (link_sta) -		info.newly = state != MT76_STA_INFO_STATE_ASSOC; -	else -		info.newly = state == MT76_STA_INFO_STATE_ASSOC ? false : true; - -	if (ieee80211_vif_is_mld(vif)) -		err = mt7925_mcu_mlo_sta_cmd(&dev->mphy, &info); -	else -		err = mt7925_mcu_sta_cmd(&dev->mphy, &info); - -	return err; +	return mt7925_mcu_sta_cmd(&dev->mphy, &info);  }  int mt7925_mcu_set_beacon_filter(struct mt792x_dev *dev, @@ -2084,8 +2077,6 @@ int mt7925_mcu_set_sniffer(struct mt792x_dev *dev, struct ieee80211_vif *vif,  		},  	}; -	mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req), true); -  	return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(SNIFFER), &req, sizeof(req),  				 true);  } @@ -2336,6 +2327,40 @@ __mt7925_mcu_alloc_bss_req(struct mt76_dev *dev, struct mt76_vif_link *mvif, int  	return skb;  } +static +void mt7925_mcu_bss_eht_tlv(struct sk_buff *skb, struct mt76_phy *phy, +			    struct ieee80211_bss_conf *link_conf, +			    struct ieee80211_chanctx_conf *ctx) +{ +	struct cfg80211_chan_def *chandef = ctx ? &ctx->def : +						  &link_conf->chanreq.oper; + +	struct bss_eht_tlv *req; +	struct tlv *tlv; + +	tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_EHT, sizeof(*req)); +	req = (struct bss_eht_tlv *)tlv; +	req->is_eth_dscb_present = chandef->punctured ? 1 : 0; +	req->eht_dis_sub_chan_bitmap = cpu_to_le16(chandef->punctured); +} + +int mt7925_mcu_set_eht_pp(struct mt76_phy *phy, struct mt76_vif_link *mvif, +			  struct ieee80211_bss_conf *link_conf, +			  struct ieee80211_chanctx_conf *ctx) +{ +	struct sk_buff *skb; + +	skb = __mt7925_mcu_alloc_bss_req(phy->dev, mvif, +					 MT7925_BSS_UPDATE_MAX_SIZE); +	if (IS_ERR(skb)) +		return PTR_ERR(skb); + +	mt7925_mcu_bss_eht_tlv(skb, phy, link_conf, ctx); + +	return mt76_mcu_skb_send_msg(phy->dev, skb, +				     MCU_UNI_CMD(BSS_INFO_UPDATE), true); +} +  int mt7925_mcu_set_chctx(struct mt76_phy *phy, struct mt76_vif_link *mvif,  			 struct ieee80211_bss_conf *link_conf,  			 struct ieee80211_chanctx_conf *ctx) @@ -2567,6 +2592,7 @@ mt7925_mcu_bss_mld_tlv(struct sk_buff *skb,  	struct ieee80211_vif *vif = link_conf->vif;  	struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(link_conf);  	struct mt792x_vif *mvif = (struct mt792x_vif *)link_conf->vif->drv_priv; +	struct mt792x_phy *phy = mvif->phy;  	struct bss_mld_tlv *mld;  	struct tlv *tlv;  	bool is_mld; @@ -2582,8 +2608,13 @@ mt7925_mcu_bss_mld_tlv(struct sk_buff *skb,  	mld->group_mld_id = is_mld ? mvif->bss_conf.mt76.idx : 0xff;  	mld->own_mld_id = mconf->mt76.idx + 32;  	mld->remap_idx = 0xff; -	mld->eml_enable = !!(link_conf->vif->cfg.eml_cap & -			     IEEE80211_EML_CAP_EMLSR_SUPP); + +	if (phy->chip_cap & MT792x_CHIP_CAP_MLO_EML_EN) { +		mld->eml_enable = !!(link_conf->vif->cfg.eml_cap & +				     IEEE80211_EML_CAP_EMLSR_SUPP); +	} else { +		mld->eml_enable = 0; +	}  	memcpy(mld->mac_addr, vif->addr, ETH_ALEN);  } @@ -2676,6 +2707,62 @@ int mt7925_mcu_set_timing(struct mt792x_phy *phy,  				     MCU_UNI_CMD(BSS_INFO_UPDATE), true);  } +void mt7925_mcu_del_dev(struct mt76_dev *mdev, +			struct ieee80211_vif *vif) +{ +	struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv; +	struct { +		struct { +			u8 omac_idx; +			u8 band_idx; +			__le16 pad; +		} __packed hdr; +		struct req_tlv { +			__le16 tag; +			__le16 len; +			u8 active; +			u8 link_idx; /* hw link idx */ +			u8 omac_addr[ETH_ALEN]; +		} __packed tlv; +	} dev_req = { +		.tlv = { +			.tag = cpu_to_le16(DEV_INFO_ACTIVE), +			.len = cpu_to_le16(sizeof(struct req_tlv)), +			.active = true, +		}, +	}; +	struct { +		struct { +			u8 bss_idx; +			u8 pad[3]; +		} __packed hdr; +		struct mt76_connac_bss_basic_tlv basic; +	} basic_req = { +		.basic = { +			.tag = cpu_to_le16(UNI_BSS_INFO_BASIC), +			.len = cpu_to_le16(sizeof(struct mt76_connac_bss_basic_tlv)), +			.active = true, +			.conn_state = 1, +		}, +	}; + +	dev_req.hdr.omac_idx = mvif->omac_idx; +	dev_req.hdr.band_idx = mvif->band_idx; + +	basic_req.hdr.bss_idx = mvif->idx; +	basic_req.basic.omac_idx = mvif->omac_idx; +	basic_req.basic.band_idx = mvif->band_idx; +	basic_req.basic.link_idx = mvif->link_idx; + +	mt76_mcu_send_msg(mdev, MCU_UNI_CMD(BSS_INFO_UPDATE), +			  &basic_req, sizeof(basic_req), true); + +	/* recovery omac address for the legacy interface */ +	memcpy(dev_req.tlv.omac_addr, vif->addr, ETH_ALEN); +	mt76_mcu_send_msg(mdev, MCU_UNI_CMD(DEV_INFO_UPDATE), +			  &dev_req, sizeof(dev_req), true); +} +  int mt7925_mcu_add_bss_info(struct mt792x_phy *phy,  			    struct ieee80211_chanctx_conf *ctx,  			    struct ieee80211_bss_conf *link_conf, @@ -2740,11 +2827,59 @@ int mt7925_mcu_set_dbdc(struct mt76_phy *phy, bool enable)  	conf->band = 0; /* unused */  	err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SET_DBDC_PARMS), -				    false); +				    true);  	return err;  } +static void +mt7925_mcu_build_scan_ie_tlv(struct mt76_dev *mdev, +			     struct sk_buff *skb, +			     struct ieee80211_scan_ies *scan_ies) +{ +	u32 max_len = sizeof(struct scan_ie_tlv) + MT76_CONNAC_SCAN_IE_LEN; +	struct scan_ie_tlv *ie; +	enum nl80211_band i; +	struct tlv *tlv; +	const u8 *ies; +	u16 ies_len; + +	for (i = 0; i <= NL80211_BAND_6GHZ; i++) { +		if (i == NL80211_BAND_60GHZ) +			continue; + +		ies = scan_ies->ies[i]; +		ies_len = scan_ies->len[i]; + +		if (!ies || !ies_len) +			continue; + +		if (ies_len > max_len) +			return; + +		tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, +					      sizeof(*ie) + ies_len); +		ie = (struct scan_ie_tlv *)tlv; + +		memcpy(ie->ies, ies, ies_len); +		ie->ies_len = cpu_to_le16(ies_len); + +		switch (i) { +		case NL80211_BAND_2GHZ: +			ie->band = 1; +			break; +		case NL80211_BAND_6GHZ: +			ie->band = 3; +			break; +		default: +			ie->band = 2; +			break; +		} + +		max_len -= (sizeof(*ie) + ies_len); +	} +} +  int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,  		       struct ieee80211_scan_request *scan_req)  { @@ -2755,7 +2890,6 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,  	struct mt76_dev *mdev = phy->dev;  	struct mt76_connac_mcu_scan_channel *chan;  	struct sk_buff *skb; -  	struct scan_hdr_tlv *hdr;  	struct scan_req_tlv *req;  	struct scan_ssid_tlv *ssid; @@ -2766,9 +2900,13 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,  	struct tlv *tlv;  	int max_len; +	if (test_bit(MT76_HW_SCANNING, &phy->state)) +		return -EBUSY; +  	max_len = sizeof(*hdr) + sizeof(*req) + sizeof(*ssid) + -				sizeof(*bssid) + sizeof(*chan_info) + -				sizeof(*misc) + sizeof(*ie); +		  sizeof(*bssid) * MT7925_RNR_SCAN_MAX_BSSIDS + +		  sizeof(*chan_info) + sizeof(*misc) + sizeof(*ie) + +		  MT76_CONNAC_SCAN_IE_LEN;  	skb = mt76_mcu_msg_alloc(mdev, NULL, max_len);  	if (!skb) @@ -2791,19 +2929,42 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,  	for (i = 0; i < sreq->n_ssids; i++) {  		if (!sreq->ssids[i].ssid_len)  			continue; +		if (i >= MT7925_RNR_SCAN_MAX_BSSIDS) +			break; -		ssid->ssids[i].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len); -		memcpy(ssid->ssids[i].ssid, sreq->ssids[i].ssid, +		ssid->ssids[n_ssids].ssid_len = cpu_to_le32(sreq->ssids[i].ssid_len); +		memcpy(ssid->ssids[n_ssids].ssid, sreq->ssids[i].ssid,  		       sreq->ssids[i].ssid_len);  		n_ssids++;  	}  	ssid->ssid_type = n_ssids ? BIT(2) : BIT(0);  	ssid->ssids_num = n_ssids; -	tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID, sizeof(*bssid)); -	bssid = (struct scan_bssid_tlv *)tlv; +	if (sreq->n_6ghz_params) { +		u8 j; + +		mt76_connac_mcu_build_rnr_scan_param(mdev, sreq); + +		for (j = 0; j < mdev->rnr.bssid_num; j++) { +			if (j >= MT7925_RNR_SCAN_MAX_BSSIDS) +				break; + +			tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID, +						      sizeof(*bssid)); +			bssid = (struct scan_bssid_tlv *)tlv; + +			ether_addr_copy(bssid->bssid, mdev->rnr.bssid[j]); +			bssid->match_ch = mdev->rnr.channel[j]; +			bssid->match_ssid_ind = MT7925_RNR_SCAN_MAX_BSSIDS; +			bssid->match_short_ssid_ind = MT7925_RNR_SCAN_MAX_BSSIDS; +		} +		req->scan_func |= SCAN_FUNC_RNR_SCAN; +	} else { +		tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_BSSID, sizeof(*bssid)); +		bssid = (struct scan_bssid_tlv *)tlv; -	memcpy(bssid->bssid, sreq->bssid, ETH_ALEN); +		ether_addr_copy(bssid->bssid, sreq->bssid); +	}  	tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_CHANNEL, sizeof(*chan_info));  	chan_info = (struct scan_chan_info_tlv *)tlv; @@ -2827,13 +2988,6 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,  	}  	chan_info->channel_type = sreq->n_channels ? 4 : 0; -	tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie)); -	ie = (struct scan_ie_tlv *)tlv; -	if (sreq->ie_len > 0) { -		memcpy(ie->ies, sreq->ie, sreq->ie_len); -		ie->ies_len = cpu_to_le16(sreq->ie_len); -	} -  	req->scan_func |= SCAN_FUNC_SPLIT_SCAN;  	tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_MISC, sizeof(*misc)); @@ -2844,8 +2998,11 @@ int mt7925_mcu_hw_scan(struct mt76_phy *phy, struct ieee80211_vif *vif,  		req->scan_func |= SCAN_FUNC_RANDOM_MAC;  	} +	/* Append scan probe IEs as the last tlv */ +	mt7925_mcu_build_scan_ie_tlv(mdev, skb, &scan_req->ies); +  	err = mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ), -				    false); +				    true);  	if (err < 0)  		clear_bit(MT76_HW_SCANNING, &phy->state); @@ -2855,7 +3012,8 @@ EXPORT_SYMBOL_GPL(mt7925_mcu_hw_scan);  int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,  			      struct ieee80211_vif *vif, -			      struct cfg80211_sched_scan_request *sreq) +			      struct cfg80211_sched_scan_request *sreq, +			      struct ieee80211_scan_ies *ies)  {  	struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;  	struct ieee80211_channel **scan_list = sreq->channels; @@ -2943,15 +3101,11 @@ int mt7925_mcu_sched_scan_req(struct mt76_phy *phy,  	}  	chan_info->channel_type = sreq->n_channels ? 4 : 0; -	tlv = mt76_connac_mcu_add_tlv(skb, UNI_SCAN_IE, sizeof(*ie)); -	ie = (struct scan_ie_tlv *)tlv; -	if (sreq->ie_len > 0) { -		memcpy(ie->ies, sreq->ie, sreq->ie_len); -		ie->ies_len = cpu_to_le16(sreq->ie_len); -	} +	/* Append scan probe IEs as the last tlv */ +	mt7925_mcu_build_scan_ie_tlv(mdev, skb, ies);  	return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ), -				     false); +				     true);  }  EXPORT_SYMBOL_GPL(mt7925_mcu_sched_scan_req); @@ -2987,7 +3141,7 @@ mt7925_mcu_sched_scan_enable(struct mt76_phy *phy,  		clear_bit(MT76_HW_SCHED_SCANNING, &phy->state);  	return mt76_mcu_skb_send_msg(mdev, skb, MCU_UNI_CMD(SCAN_REQ), -				     false); +				     true);  }  int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy, @@ -3026,7 +3180,7 @@ int mt7925_mcu_cancel_hw_scan(struct mt76_phy *phy,  	}  	return mt76_mcu_send_msg(phy->dev, MCU_UNI_CMD(SCAN_REQ), -				 &req, sizeof(req), false); +				 &req, sizeof(req), true);  }  EXPORT_SYMBOL_GPL(mt7925_mcu_cancel_hw_scan); @@ -3131,7 +3285,7 @@ int mt7925_mcu_set_channel_domain(struct mt76_phy *phy)  	memcpy(__skb_push(skb, sizeof(req)), &req, sizeof(req));  	return mt76_mcu_skb_send_msg(dev, skb, MCU_UNI_CMD(SET_DOMAIN_INFO), -				     false); +				     true);  }  EXPORT_SYMBOL_GPL(mt7925_mcu_set_channel_domain); @@ -3163,16 +3317,17 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,  		.idx = idx,  		.env = env_cap, -		.acpi_conf = mt792x_acpi_get_flags(&dev->phy),  	};  	int ret, valid_cnt = 0; -	u8 i, *pos; +	u8 *pos, *last_pos;  	if (!clc)  		return 0; -	pos = clc->data + sizeof(*seg) * clc->nr_seg; -	for (i = 0; i < clc->nr_country; i++) { +	req.ver = clc->ver; +	pos = clc->data + sizeof(*seg) * clc->t0.nr_seg; +	last_pos = clc->data + le32_to_cpu(*(__le32 *)(clc->data + 4)); +	while (pos < last_pos) {  		struct mt7925_clc_rule *rule = (struct mt7925_clc_rule *)pos;  		pos += sizeof(*rule); @@ -3187,6 +3342,7 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,  		memcpy(req.type, rule->type, 2);  		req.size = cpu_to_le16(seg->len); +		dev->phy.clc_chan_conf = clc->ver == 1 ? 0xff : rule->flag;  		skb = __mt76_mcu_msg_alloc(&dev->mt76, &req,  					   le16_to_cpu(req.size) + sizeof(req),  					   sizeof(req), GFP_KERNEL); @@ -3202,8 +3358,10 @@ __mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,  		valid_cnt++;  	} -	if (!valid_cnt) +	if (!valid_cnt) { +		dev->phy.clc_chan_conf = 0xff;  		return -ENOENT; +	}  	return 0;  } @@ -3216,6 +3374,9 @@ int mt7925_mcu_set_clc(struct mt792x_dev *dev, u8 *alpha2,  	/* submit all clc config */  	for (i = 0; i < ARRAY_SIZE(phy->clc); i++) { +		if (i == MT792x_CLC_BE_CTRL) +			continue; +  		ret = __mt7925_mcu_set_clc(dev, alpha2, env_cap,  					   phy->clc[i], i); @@ -3274,6 +3435,18 @@ int mt7925_mcu_fill_message(struct mt76_dev *mdev, struct sk_buff *skb,  		else  			uni_txd->option = MCU_CMD_UNI_EXT_ACK; +		if (cmd == MCU_UNI_CMD(HIF_CTRL) || +		    cmd == MCU_UNI_CMD(CHIP_CONFIG)) +			uni_txd->option &= ~MCU_CMD_ACK; + +		if (mcu_cmd == MCU_UNI_CMD_TESTMODE_CTRL || +		    mcu_cmd == MCU_UNI_CMD_TESTMODE_RX_STAT) { +			if (cmd & __MCU_CMD_FIELD_QUERY) +				uni_txd->option = 0x2; +			else +				uni_txd->option = 0x6; +		} +  		goto exit;  	} @@ -3565,6 +3738,43 @@ int mt7925_mcu_set_rate_txpower(struct mt76_phy *phy)  	return 0;  } +int mt7925_mcu_wf_rf_pin_ctrl(struct mt792x_phy *phy) +{ +#define UNI_CMD_RADIO_STATUS_GET	0 +	struct mt792x_dev *dev = phy->dev; +	struct sk_buff *skb; +	int ret; +	struct { +		__le16 tag; +		__le16 len; +		u8 rsv[4]; +	} __packed req = { +		.tag = UNI_CMD_RADIO_STATUS_GET, +		.len = cpu_to_le16(sizeof(req)), +	}; +	struct mt7925_radio_status_event { +		__le16 tag; +		__le16 len; + +		u8 data; +		u8 rsv[3]; +	} __packed *status; + +	ret = mt76_mcu_send_and_get_msg(&dev->mt76, +					MCU_UNI_CMD(RADIO_STATUS), +					&req, sizeof(req), true, &skb); +	if (ret) +		return ret; + +	skb_pull(skb, sizeof(struct tlv)); +	status = (struct mt7925_radio_status_event *)skb->data; +	ret = status->data; + +	dev_kfree_skb(skb); + +	return ret; +} +  int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,  			    u8 bit_op, u32 bit_map)  { | 
