diff options
Diffstat (limited to 'sys/contrib/dev/mediatek/mt76/mt7925/main.c')
| -rw-r--r-- | sys/contrib/dev/mediatek/mt76/mt7925/main.c | 219 | 
1 files changed, 157 insertions, 62 deletions
| diff --git a/sys/contrib/dev/mediatek/mt76/mt7925/main.c b/sys/contrib/dev/mediatek/mt76/mt7925/main.c index 98daf80ac131..b0e053b15227 100644 --- a/sys/contrib/dev/mediatek/mt76/mt7925/main.c +++ b/sys/contrib/dev/mediatek/mt76/mt7925/main.c @@ -251,12 +251,12 @@ int mt7925_init_mlo_caps(struct mt792x_phy *phy)  		},  	}; -	if (!(phy->chip_cap & MT792x_CHIP_CAP_MLO_EVT_EN)) +	if (!(phy->chip_cap & MT792x_CHIP_CAP_MLO_EN))  		return 0;  	ext_capab[0].eml_capabilities = phy->eml_cap;  	ext_capab[0].mld_capa_and_ops = -		u16_encode_bits(1, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS); +		u16_encode_bits(0, IEEE80211_MLD_CAP_OP_MAX_SIMUL_LINKS);  	wiphy->flags |= WIPHY_FLAG_SUPPORTS_MLO;  	wiphy->iftype_ext_capab = ext_capab; @@ -334,6 +334,9 @@ int __mt7925_start(struct mt792x_phy *phy)  	ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,  				     MT792x_WATCHDOG_TIME); +	if (phy->chip_cap & MT792x_CHIP_CAP_WF_RF_PIN_CTRL_EVT_EN) +		wiphy_rfkill_start_polling(mphy->hw->wiphy); +  	return 0;  }  EXPORT_SYMBOL_GPL(__mt7925_start); @@ -360,10 +363,15 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,  	struct mt76_txq *mtxq;  	int idx, ret = 0; -	mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask); -	if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) { -		ret = -ENOSPC; -		goto out; +	if (vif->type == NL80211_IFTYPE_P2P_DEVICE) { +		mconf->mt76.idx = MT792x_MAX_INTERFACES; +	} else { +		mconf->mt76.idx = __ffs64(~dev->mt76.vif_mask); + +		if (mconf->mt76.idx >= MT792x_MAX_INTERFACES) { +			ret = -ENOSPC; +			goto out; +		}  	}  	mconf->mt76.omac_idx = ieee80211_vif_is_mld(vif) ? @@ -371,6 +379,7 @@ static int mt7925_mac_link_bss_add(struct mt792x_dev *dev,  	mconf->mt76.band_idx = 0xff;  	mconf->mt76.wmm_idx = ieee80211_vif_is_mld(vif) ?  			      0 : mconf->mt76.idx % MT76_CONNAC_MAX_WMM_SETS; +	mconf->mt76.link_idx = hweight16(mvif->valid_links);  	if (mvif->phy->mt76->chandef.chan->band != NL80211_BAND_2GHZ)  		mconf->mt76.basic_rates_idx = MT792x_BASIC_RATES_TBL + 4; @@ -421,6 +430,7 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)  	mvif->bss_conf.vif = mvif;  	mvif->sta.vif = mvif;  	mvif->deflink_id = IEEE80211_LINK_UNSPECIFIED; +	mvif->mlo_pm_state = MT792x_MLO_LINK_DISASSOC;  	ret = mt7925_mac_link_bss_add(dev, &vif->bss_conf, &mvif->sta.deflink);  	if (ret < 0) @@ -446,7 +456,7 @@ void mt7925_roc_abort_sync(struct mt792x_dev *dev)  {  	struct mt792x_phy *phy = &dev->phy; -	del_timer_sync(&phy->roc_timer); +	timer_delete_sync(&phy->roc_timer);  	cancel_work_sync(&phy->roc_work);  	if (test_and_clear_bit(MT76_STATE_ROC, &phy->mt76->state))  		ieee80211_iterate_interfaces(mt76_hw(dev), @@ -478,7 +488,7 @@ static int mt7925_abort_roc(struct mt792x_phy *phy,  {  	int err = 0; -	del_timer_sync(&phy->roc_timer); +	timer_delete_sync(&phy->roc_timer);  	cancel_work_sync(&phy->roc_work);  	mt792x_mutex_acquire(phy->dev); @@ -747,7 +757,7 @@ void mt7925_set_runtime_pm(struct mt792x_dev *dev)  	mt7925_mcu_set_deep_sleep(dev, pm->ds_enable);  } -static int mt7925_config(struct ieee80211_hw *hw, u32 changed) +static int mt7925_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)  {  	struct mt792x_dev *dev = mt792x_hw_dev(hw);  	int ret = 0; @@ -1149,7 +1159,12 @@ static void mt7925_mac_link_sta_remove(struct mt76_dev *mdev,  		struct mt792x_bss_conf *mconf;  		mconf = mt792x_link_conf_to_mconf(link_conf); -		mt792x_mac_link_bss_remove(dev, mconf, mlink); + +		if (ieee80211_vif_is_mld(vif)) +			mt792x_mac_link_bss_remove(dev, mconf, mlink); +		else +			mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf, +						link_sta, false);  	}  	spin_lock_bh(&mdev->sta_poll_lock); @@ -1169,6 +1184,34 @@ mt7925_mac_sta_remove_links(struct mt792x_dev *dev, struct ieee80211_vif *vif,  	struct mt76_wcid *wcid;  	unsigned int link_id; +	/* clean up bss before starec */ +	for_each_set_bit(link_id, &old_links, IEEE80211_MLD_MAX_NUM_LINKS) { +		struct ieee80211_link_sta *link_sta; +		struct ieee80211_bss_conf *link_conf; +		struct mt792x_bss_conf *mconf; +		struct mt792x_link_sta *mlink; + +		if (vif->type == NL80211_IFTYPE_AP) +			break; + +		link_sta = mt792x_sta_to_link_sta(vif, sta, link_id); +		if (!link_sta) +			continue; + +		mlink = mt792x_sta_to_link(msta, link_id); +		if (!mlink) +			continue; + +		link_conf = mt792x_vif_to_bss_conf(vif, link_id); +		if (!link_conf) +			continue; + +		mconf = mt792x_link_conf_to_mconf(link_conf); + +		mt7925_mcu_add_bss_info(&dev->phy, mconf->mt76.ctx, link_conf, +					link_sta, false); +	} +  	for_each_set_bit(link_id, &old_links, IEEE80211_MLD_MAX_NUM_LINKS) {  		struct ieee80211_link_sta *link_sta;  		struct mt792x_link_sta *mlink; @@ -1206,55 +1249,27 @@ void mt7925_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,  {  	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);  	struct mt792x_sta *msta = (struct mt792x_sta *)sta->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 = { -		.hdr = { -			.omac_idx = 0, -			.band_idx = 0, -		}, -		.tlv = { -			.tag = cpu_to_le16(DEV_INFO_ACTIVE), -			.len = cpu_to_le16(sizeof(struct req_tlv)), -			.active = true, -		}, -	}; +	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;  	unsigned long rem;  	rem = ieee80211_vif_is_mld(vif) ? msta->valid_links : BIT(0);  	mt7925_mac_sta_remove_links(dev, vif, sta, rem); -	if (ieee80211_vif_is_mld(vif)) { -		mt7925_mcu_set_dbdc(&dev->mphy, false); - -		/* 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); -	} +	if (ieee80211_vif_is_mld(vif)) +		mt7925_mcu_del_dev(mdev, vif);  	if (vif->type == NL80211_IFTYPE_STATION) { -		struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; -  		mvif->wep_sta = NULL;  		ewma_rssi_init(&mvif->bss_conf.rssi);  	} + +	mvif->mlo_pm_state = MT792x_MLO_LINK_DISASSOC;  }  EXPORT_SYMBOL_GPL(mt7925_mac_sta_remove); -static int mt7925_set_rts_threshold(struct ieee80211_hw *hw, u32 val) +static int mt7925_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx, +				    u32 val)  {  	struct mt792x_dev *dev = mt792x_hw_dev(hw); @@ -1289,22 +1304,22 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	case IEEE80211_AMPDU_RX_START:  		mt76_rx_aggr_start(&dev->mt76, &msta->deflink.wcid, tid, ssn,  				   params->buf_size); -		mt7925_mcu_uni_rx_ba(dev, vif, params, true); +		mt7925_mcu_uni_rx_ba(dev, params, true);  		break;  	case IEEE80211_AMPDU_RX_STOP:  		mt76_rx_aggr_stop(&dev->mt76, &msta->deflink.wcid, tid); -		mt7925_mcu_uni_rx_ba(dev, vif, params, false); +		mt7925_mcu_uni_rx_ba(dev, params, false);  		break;  	case IEEE80211_AMPDU_TX_OPERATIONAL:  		mtxq->aggr = true;  		mtxq->send_bar = false; -		mt7925_mcu_uni_tx_ba(dev, vif, params, true); +		mt7925_mcu_uni_tx_ba(dev, params, true);  		break;  	case IEEE80211_AMPDU_TX_STOP_FLUSH:  	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:  		mtxq->aggr = false;  		clear_bit(tid, &msta->deflink.wcid.ampdu_state); -		mt7925_mcu_uni_tx_ba(dev, vif, params, false); +		mt7925_mcu_uni_tx_ba(dev, params, false);  		break;  	case IEEE80211_AMPDU_TX_START:  		set_bit(tid, &msta->deflink.wcid.ampdu_state); @@ -1313,7 +1328,7 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	case IEEE80211_AMPDU_TX_STOP_CONT:  		mtxq->aggr = false;  		clear_bit(tid, &msta->deflink.wcid.ampdu_state); -		mt7925_mcu_uni_tx_ba(dev, vif, params, false); +		mt7925_mcu_uni_tx_ba(dev, params, false);  		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);  		break;  	} @@ -1322,6 +1337,38 @@ mt7925_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	return ret;  } +static void +mt7925_mlo_pm_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) +{ +	struct mt792x_dev *dev = priv; +	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv; +	unsigned long valid = ieee80211_vif_is_mld(vif) ? +				    mvif->valid_links : BIT(0); +	struct ieee80211_bss_conf *bss_conf; +	int i; + +	if (mvif->mlo_pm_state != MT792x_MLO_CHANGED_PS) +		return; + +	mt792x_mutex_acquire(dev); +	for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { +		bss_conf = mt792x_vif_to_bss_conf(vif, i); +		mt7925_mcu_uni_bss_ps(dev, bss_conf); +	} +	mt792x_mutex_release(dev); +} + +void mt7925_mlo_pm_work(struct work_struct *work) +{ +	struct mt792x_dev *dev = container_of(work, struct mt792x_dev, +					      mlo_pm_work.work); +	struct ieee80211_hw *hw = mt76_hw(dev); + +	ieee80211_iterate_active_interfaces(hw, +					    IEEE80211_IFACE_ITER_RESUME_ALL, +					    mt7925_mlo_pm_iter, dev); +} +  static bool is_valid_alpha2(const char *alpha2)  {  	if (!alpha2) @@ -1378,6 +1425,8 @@ void mt7925_scan_work(struct work_struct *work)  				if (!is_valid_alpha2(evt->alpha2))  					break; +				mt7925_regd_be_ctrl(phy->dev, evt->alpha2); +  				if (mdev->alpha2[0] != '0' && mdev->alpha2[1] != '0')  					break; @@ -1436,7 +1485,7 @@ mt7925_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	mt792x_mutex_acquire(dev); -	err = mt7925_mcu_sched_scan_req(mphy, vif, req); +	err = mt7925_mcu_sched_scan_req(mphy, vif, req, ies);  	if (err < 0)  		goto out; @@ -1462,7 +1511,8 @@ mt7925_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)  }  static int -mt7925_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) +mt7925_set_antenna(struct ieee80211_hw *hw, int radio_idx, +		   u32 tx_ant, u32 rx_ant)  {  	struct mt792x_dev *dev = mt792x_hw_dev(hw);  	struct mt792x_phy *phy = mt792x_hw_phy(hw); @@ -1558,6 +1608,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw,  	unsigned long valid = mvif->valid_links;  	u8 i; +	if (!msta->vif) +		return; +  	mt792x_mutex_acquire(dev);  	valid = ieee80211_vif_is_mld(vif) ? mvif->valid_links : BIT(0); @@ -1572,6 +1625,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw,  		else  			clear_bit(MT_WCID_FLAG_HDR_TRANS, &mlink->wcid.flags); +		if (!mlink->wcid.sta) +			continue; +  		mt7925_mcu_wtbl_update_hdr_trans(dev, vif, sta, i);  	} @@ -1823,6 +1879,10 @@ mt7925_change_chanctx(struct ieee80211_hw *hw,  			link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id);  			mt7925_mcu_set_chctx(mvif->phy->mt76, &mconf->mt76,  					     link_conf, ctx); + +			if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING) +				mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76, +						      link_conf, ctx);  		}  	} @@ -1871,6 +1931,9 @@ static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw,  		mt7925_mcu_sta_update(dev, NULL, vif, true,  				      MT76_STA_INFO_STATE_ASSOC);  		mt7925_mcu_set_beacon_filter(dev, vif, vif->cfg.assoc); + +		if (ieee80211_vif_is_mld(vif)) +			mvif->mlo_pm_state = MT792x_MLO_LINK_ASSOC;  	}  	if (changed & BSS_CHANGED_ARP_FILTER) { @@ -1881,9 +1944,19 @@ static void mt7925_vif_cfg_changed(struct ieee80211_hw *hw,  	}  	if (changed & BSS_CHANGED_PS) { -		for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { -			bss_conf = mt792x_vif_to_bss_conf(vif, i); +		if (hweight16(mvif->valid_links) < 2) { +			/* legacy */ +			bss_conf = &vif->bss_conf;  			mt7925_mcu_uni_bss_ps(dev, bss_conf); +		} else { +			if (mvif->mlo_pm_state == MT792x_MLO_LINK_ASSOC) { +				mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS_PENDING; +			} else if (mvif->mlo_pm_state == MT792x_MLO_CHANGED_PS) { +				for_each_set_bit(i, &valid, IEEE80211_MLD_MAX_NUM_LINKS) { +					bss_conf = mt792x_vif_to_bss_conf(vif, i); +					mt7925_mcu_uni_bss_ps(dev, bss_conf); +				} +			}  		}  	} @@ -1899,8 +1972,10 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,  	struct mt792x_phy *phy = mt792x_hw_phy(hw);  	struct mt792x_dev *dev = mt792x_hw_dev(hw);  	struct mt792x_bss_conf *mconf; +	struct ieee80211_bss_conf *link_conf;  	mconf = mt792x_vif_to_link(mvif, info->link_id); +	link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id);  	mt792x_mutex_acquire(dev); @@ -1934,13 +2009,18 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,  	if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))  		mt7925_mcu_set_tx(dev, info); -	if (changed & BSS_CHANGED_BSSID) { -		if (ieee80211_vif_is_mld(vif) && -		    hweight16(mvif->valid_links) == 2) -			/* Indicate the secondary setup done */ -			mt7925_mcu_uni_bss_bcnft(dev, info, true); +	if (mvif->mlo_pm_state == MT792x_MLO_CHANGED_PS_PENDING) { +		/* Indicate the secondary setup done */ +		mt7925_mcu_uni_bss_bcnft(dev, info, true); + +		ieee80211_queue_delayed_work(hw, &dev->mlo_pm_work, 5 * HZ); +		mvif->mlo_pm_state = MT792x_MLO_CHANGED_PS;  	} +	if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING) +		mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76, +				      link_conf, NULL); +  	mt792x_mutex_release(dev);  } @@ -1992,8 +2072,10 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  					     GFP_KERNEL);  			mlink = devm_kzalloc(dev->mt76.dev, sizeof(*mlink),  					     GFP_KERNEL); -			if (!mconf || !mlink) +			if (!mconf || !mlink) { +				mt792x_mutex_release(dev);  				return -ENOMEM; +			}  		}  		mconfs[link_id] = mconf; @@ -2022,8 +2104,6 @@ mt7925_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  			goto free;  		if (mconf != &mvif->bss_conf) { -			mt7925_mcu_set_bss_pm(dev, link_conf, true); -  			err = mt7925_set_mlo_roc(phy, &mvif->bss_conf,  						 vif->active_links);  			if (err < 0) @@ -2141,6 +2221,18 @@ static void mt7925_unassign_vif_chanctx(struct ieee80211_hw *hw,  	mutex_unlock(&dev->mt76.mutex);  } +static void mt7925_rfkill_poll(struct ieee80211_hw *hw) +{ +	struct mt792x_phy *phy = mt792x_hw_phy(hw); +	int ret; + +	mt792x_mutex_acquire(phy->dev); +	ret = mt7925_mcu_wf_rf_pin_ctrl(phy); +	mt792x_mutex_release(phy->dev); + +	wiphy_rfkill_set_hw_state(hw->wiphy, ret == 0); +} +  const struct ieee80211_ops mt7925_ops = {  	.tx = mt792x_tx,  	.start = mt7925_start, @@ -2180,6 +2272,8 @@ const struct ieee80211_ops mt7925_ops = {  	.sta_statistics = mt792x_sta_statistics,  	.sched_scan_start = mt7925_start_sched_scan,  	.sched_scan_stop = mt7925_stop_sched_scan, +	CFG80211_TESTMODE_CMD(mt7925_testmode_cmd) +	CFG80211_TESTMODE_DUMP(mt7925_testmode_dump)  #ifdef CONFIG_PM  	.suspend = mt7925_suspend,  	.resume = mt7925_resume, @@ -2201,6 +2295,7 @@ const struct ieee80211_ops mt7925_ops = {  	.link_info_changed = mt7925_link_info_changed,  	.change_vif_links = mt7925_change_vif_links,  	.change_sta_links = mt7925_change_sta_links, +	.rfkill_poll = mt7925_rfkill_poll,  };  EXPORT_SYMBOL_GPL(mt7925_ops); | 
