brintos

brintos / linux-shallow public Read only

0
0
Text · 23.7 KiB · 78fe37c Raw
917 lines · c
1// SPDX-License-Identifier: ISC2/* Copyright (C) 2023 MediaTek Inc. */3 4#include <linux/module.h>5#include <linux/firmware.h>6 7#include "mt792x.h"8#include "dma.h"9 10static const struct ieee80211_iface_limit if_limits[] = {11	{12		.max = MT792x_MAX_INTERFACES,13		.types = BIT(NL80211_IFTYPE_STATION)14	},15	{16		.max = 1,17		.types = BIT(NL80211_IFTYPE_AP)18	}19};20 21static const struct ieee80211_iface_combination if_comb[] = {22	{23		.limits = if_limits,24		.n_limits = ARRAY_SIZE(if_limits),25		.max_interfaces = MT792x_MAX_INTERFACES,26		.num_different_channels = 1,27		.beacon_int_infra_match = true,28	},29};30 31static const struct ieee80211_iface_limit if_limits_chanctx[] = {32	{33		.max = 2,34		.types = BIT(NL80211_IFTYPE_STATION) |35			 BIT(NL80211_IFTYPE_P2P_CLIENT)36	},37	{38		.max = 1,39		.types = BIT(NL80211_IFTYPE_AP) |40			 BIT(NL80211_IFTYPE_P2P_GO)41	}42};43 44static const struct ieee80211_iface_combination if_comb_chanctx[] = {45	{46		.limits = if_limits_chanctx,47		.n_limits = ARRAY_SIZE(if_limits_chanctx),48		.max_interfaces = 2,49		.num_different_channels = 2,50		.beacon_int_infra_match = false,51	}52};53 54void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,55	       struct sk_buff *skb)56{57	struct mt792x_dev *dev = mt792x_hw_dev(hw);58	struct mt76_phy *mphy = hw->priv;59	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);60	struct ieee80211_vif *vif = info->control.vif;61	struct mt76_wcid *wcid = &dev->mt76.global_wcid;62	u8 link_id;63	int qid;64 65	if (control->sta) {66		struct mt792x_link_sta *mlink;67		struct mt792x_sta *sta;68		link_id = u32_get_bits(info->control.flags,69				       IEEE80211_TX_CTRL_MLO_LINK);70		sta = (struct mt792x_sta *)control->sta->drv_priv;71		mlink = mt792x_sta_to_link(sta, link_id);72		wcid = &mlink->wcid;73	}74 75	if (vif && !control->sta) {76		struct mt792x_vif *mvif;77 78		mvif = (struct mt792x_vif *)vif->drv_priv;79		wcid = &mvif->sta.deflink.wcid;80	}81 82	if (vif && control->sta && ieee80211_vif_is_mld(vif)) {83		struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;84		struct ieee80211_link_sta *link_sta;85		struct ieee80211_bss_conf *conf;86 87		link_id = wcid->link_id;88		rcu_read_lock();89		conf = rcu_dereference(vif->link_conf[link_id]);90		memcpy(hdr->addr2, conf->addr, ETH_ALEN);91 92		link_sta = rcu_dereference(control->sta->link[link_id]);93		memcpy(hdr->addr1, link_sta->addr, ETH_ALEN);94 95		if (vif->type == NL80211_IFTYPE_STATION)96			memcpy(hdr->addr3, conf->bssid, ETH_ALEN);97		rcu_read_unlock();98	}99 100	if (mt76_connac_pm_ref(mphy, &dev->pm)) {101		mt76_tx(mphy, control->sta, wcid, skb);102		mt76_connac_pm_unref(mphy, &dev->pm);103		return;104	}105 106	qid = skb_get_queue_mapping(skb);107	if (qid >= MT_TXQ_PSD) {108		qid = IEEE80211_AC_BE;109		skb_set_queue_mapping(skb, qid);110	}111 112	mt76_connac_pm_queue_skb(hw, &dev->pm, wcid, skb);113}114EXPORT_SYMBOL_GPL(mt792x_tx);115 116void mt792x_stop(struct ieee80211_hw *hw, bool suspend)117{118	struct mt792x_dev *dev = mt792x_hw_dev(hw);119	struct mt792x_phy *phy = mt792x_hw_phy(hw);120 121	cancel_delayed_work_sync(&phy->mt76->mac_work);122 123	cancel_delayed_work_sync(&dev->pm.ps_work);124	cancel_work_sync(&dev->pm.wake_work);125	cancel_work_sync(&dev->reset_work);126	mt76_connac_free_pending_tx_skbs(&dev->pm, NULL);127 128	if (is_mt7921(&dev->mt76)) {129		mt792x_mutex_acquire(dev);130		mt76_connac_mcu_set_mac_enable(&dev->mt76, 0, false, false);131		mt792x_mutex_release(dev);132	}133 134	clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);135}136EXPORT_SYMBOL_GPL(mt792x_stop);137 138void mt792x_mac_link_bss_remove(struct mt792x_dev *dev,139				struct mt792x_bss_conf *mconf,140				struct mt792x_link_sta *mlink)141{142	struct ieee80211_vif *vif = container_of((void *)mconf->vif,143						 struct ieee80211_vif, drv_priv);144	struct ieee80211_bss_conf *link_conf;145	int idx = mlink->wcid.idx;146 147	link_conf = mt792x_vif_to_bss_conf(vif, mconf->link_id);148 149	mt76_connac_free_pending_tx_skbs(&dev->pm, &mlink->wcid);150	mt76_connac_mcu_uni_add_dev(&dev->mphy, link_conf, &mlink->wcid, false);151 152	rcu_assign_pointer(dev->mt76.wcid[idx], NULL);153 154	dev->mt76.vif_mask &= ~BIT_ULL(mconf->mt76.idx);155	mconf->vif->phy->omac_mask &= ~BIT_ULL(mconf->mt76.omac_idx);156 157	spin_lock_bh(&dev->mt76.sta_poll_lock);158	if (!list_empty(&mlink->wcid.poll_list))159		list_del_init(&mlink->wcid.poll_list);160	spin_unlock_bh(&dev->mt76.sta_poll_lock);161 162	mt76_wcid_cleanup(&dev->mt76, &mlink->wcid);163}164EXPORT_SYMBOL_GPL(mt792x_mac_link_bss_remove);165 166void mt792x_remove_interface(struct ieee80211_hw *hw,167			     struct ieee80211_vif *vif)168{169	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;170	struct mt792x_dev *dev = mt792x_hw_dev(hw);171	struct mt792x_bss_conf *mconf;172 173	mt792x_mutex_acquire(dev);174 175	mconf = mt792x_link_conf_to_mconf(&vif->bss_conf);176	mt792x_mac_link_bss_remove(dev, mconf, &mvif->sta.deflink);177 178	mt792x_mutex_release(dev);179}180EXPORT_SYMBOL_GPL(mt792x_remove_interface);181 182int mt792x_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,183		   unsigned int link_id, u16 queue,184		   const struct ieee80211_tx_queue_params *params)185{186	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;187 188	/* no need to update right away, we'll get BSS_CHANGED_QOS */189	queue = mt76_connac_lmac_mapping(queue);190	mvif->bss_conf.queue_params[queue] = *params;191 192	return 0;193}194EXPORT_SYMBOL_GPL(mt792x_conf_tx);195 196int mt792x_get_stats(struct ieee80211_hw *hw,197		     struct ieee80211_low_level_stats *stats)198{199	struct mt792x_phy *phy = mt792x_hw_phy(hw);200	struct mt76_mib_stats *mib = &phy->mib;201 202	mt792x_mutex_acquire(phy->dev);203 204	stats->dot11RTSSuccessCount = mib->rts_cnt;205	stats->dot11RTSFailureCount = mib->rts_retries_cnt;206	stats->dot11FCSErrorCount = mib->fcs_err_cnt;207	stats->dot11ACKFailureCount = mib->ack_fail_cnt;208 209	mt792x_mutex_release(phy->dev);210 211	return 0;212}213EXPORT_SYMBOL_GPL(mt792x_get_stats);214 215u64 mt792x_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)216{217	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;218	struct mt792x_dev *dev = mt792x_hw_dev(hw);219	u8 omac_idx = mvif->bss_conf.mt76.omac_idx;220	union {221		u64 t64;222		u32 t32[2];223	} tsf;224	u16 n;225 226	mt792x_mutex_acquire(dev);227 228	n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx;229	/* TSF software read */230	mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_MODE);231	tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(0));232	tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(0));233 234	mt792x_mutex_release(dev);235 236	return tsf.t64;237}238EXPORT_SYMBOL_GPL(mt792x_get_tsf);239 240void mt792x_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,241		    u64 timestamp)242{243	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;244	struct mt792x_dev *dev = mt792x_hw_dev(hw);245	u8 omac_idx = mvif->bss_conf.mt76.omac_idx;246	union {247		u64 t64;248		u32 t32[2];249	} tsf = { .t64 = timestamp, };250	u16 n;251 252	mt792x_mutex_acquire(dev);253 254	n = omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : omac_idx;255	mt76_wr(dev, MT_LPON_UTTR0(0), tsf.t32[0]);256	mt76_wr(dev, MT_LPON_UTTR1(0), tsf.t32[1]);257	/* TSF software overwrite */258	mt76_set(dev, MT_LPON_TCR(0, n), MT_LPON_TCR_SW_WRITE);259 260	mt792x_mutex_release(dev);261}262EXPORT_SYMBOL_GPL(mt792x_set_tsf);263 264void mt792x_tx_worker(struct mt76_worker *w)265{266	struct mt792x_dev *dev = container_of(w, struct mt792x_dev,267					      mt76.tx_worker);268 269	if (!mt76_connac_pm_ref(&dev->mphy, &dev->pm)) {270		queue_work(dev->mt76.wq, &dev->pm.wake_work);271		return;272	}273 274	mt76_txq_schedule_all(&dev->mphy);275	mt76_connac_pm_unref(&dev->mphy, &dev->pm);276}277EXPORT_SYMBOL_GPL(mt792x_tx_worker);278 279void mt792x_roc_timer(struct timer_list *timer)280{281	struct mt792x_phy *phy = from_timer(phy, timer, roc_timer);282 283	ieee80211_queue_work(phy->mt76->hw, &phy->roc_work);284}285EXPORT_SYMBOL_GPL(mt792x_roc_timer);286 287void mt792x_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,288		  u32 queues, bool drop)289{290	struct mt792x_dev *dev = mt792x_hw_dev(hw);291 292	wait_event_timeout(dev->mt76.tx_wait,293			   !mt76_has_tx_pending(&dev->mphy), HZ / 2);294}295EXPORT_SYMBOL_GPL(mt792x_flush);296 297int mt792x_assign_vif_chanctx(struct ieee80211_hw *hw,298			      struct ieee80211_vif *vif,299			      struct ieee80211_bss_conf *link_conf,300			      struct ieee80211_chanctx_conf *ctx)301{302	struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv;303	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;304	struct mt792x_dev *dev = mt792x_hw_dev(hw);305 306	mutex_lock(&dev->mt76.mutex);307	mvif->bss_conf.mt76.ctx = ctx;308	mctx->bss_conf = &mvif->bss_conf;309	mutex_unlock(&dev->mt76.mutex);310 311	return 0;312}313EXPORT_SYMBOL_GPL(mt792x_assign_vif_chanctx);314 315void mt792x_unassign_vif_chanctx(struct ieee80211_hw *hw,316				 struct ieee80211_vif *vif,317				 struct ieee80211_bss_conf *link_conf,318				 struct ieee80211_chanctx_conf *ctx)319{320	struct mt792x_chanctx *mctx = (struct mt792x_chanctx *)ctx->drv_priv;321	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;322	struct mt792x_dev *dev = mt792x_hw_dev(hw);323 324	mutex_lock(&dev->mt76.mutex);325	mctx->bss_conf = NULL;326	mvif->bss_conf.mt76.ctx = NULL;327	mutex_unlock(&dev->mt76.mutex);328}329EXPORT_SYMBOL_GPL(mt792x_unassign_vif_chanctx);330 331void mt792x_set_wakeup(struct ieee80211_hw *hw, bool enabled)332{333	struct mt792x_dev *dev = mt792x_hw_dev(hw);334	struct mt76_dev *mdev = &dev->mt76;335 336	device_set_wakeup_enable(mdev->dev, enabled);337}338EXPORT_SYMBOL_GPL(mt792x_set_wakeup);339 340static const char mt792x_gstrings_stats[][ETH_GSTRING_LEN] = {341	/* tx counters */342	"tx_ampdu_cnt",343	"tx_mpdu_attempts",344	"tx_mpdu_success",345	"tx_pkt_ebf_cnt",346	"tx_pkt_ibf_cnt",347	"tx_ampdu_len:0-1",348	"tx_ampdu_len:2-10",349	"tx_ampdu_len:11-19",350	"tx_ampdu_len:20-28",351	"tx_ampdu_len:29-37",352	"tx_ampdu_len:38-46",353	"tx_ampdu_len:47-55",354	"tx_ampdu_len:56-79",355	"tx_ampdu_len:80-103",356	"tx_ampdu_len:104-127",357	"tx_ampdu_len:128-151",358	"tx_ampdu_len:152-175",359	"tx_ampdu_len:176-199",360	"tx_ampdu_len:200-223",361	"tx_ampdu_len:224-247",362	"ba_miss_count",363	"tx_beamformer_ppdu_iBF",364	"tx_beamformer_ppdu_eBF",365	"tx_beamformer_rx_feedback_all",366	"tx_beamformer_rx_feedback_he",367	"tx_beamformer_rx_feedback_vht",368	"tx_beamformer_rx_feedback_ht",369	"tx_msdu_pack_1",370	"tx_msdu_pack_2",371	"tx_msdu_pack_3",372	"tx_msdu_pack_4",373	"tx_msdu_pack_5",374	"tx_msdu_pack_6",375	"tx_msdu_pack_7",376	"tx_msdu_pack_8",377	/* rx counters */378	"rx_mpdu_cnt",379	"rx_ampdu_cnt",380	"rx_ampdu_bytes_cnt",381	"rx_ba_cnt",382	/* per vif counters */383	"v_tx_mode_cck",384	"v_tx_mode_ofdm",385	"v_tx_mode_ht",386	"v_tx_mode_ht_gf",387	"v_tx_mode_vht",388	"v_tx_mode_he_su",389	"v_tx_mode_he_ext_su",390	"v_tx_mode_he_tb",391	"v_tx_mode_he_mu",392	"v_tx_mode_eht_su",393	"v_tx_mode_eht_trig",394	"v_tx_mode_eht_mu",395	"v_tx_bw_20",396	"v_tx_bw_40",397	"v_tx_bw_80",398	"v_tx_bw_160",399	"v_tx_bw_320",400	"v_tx_mcs_0",401	"v_tx_mcs_1",402	"v_tx_mcs_2",403	"v_tx_mcs_3",404	"v_tx_mcs_4",405	"v_tx_mcs_5",406	"v_tx_mcs_6",407	"v_tx_mcs_7",408	"v_tx_mcs_8",409	"v_tx_mcs_9",410	"v_tx_mcs_10",411	"v_tx_mcs_11",412	"v_tx_mcs_12",413	"v_tx_mcs_13",414	"v_tx_nss_1",415	"v_tx_nss_2",416	"v_tx_nss_3",417	"v_tx_nss_4",418};419 420void mt792x_get_et_strings(struct ieee80211_hw *hw, struct ieee80211_vif *vif,421			   u32 sset, u8 *data)422{423	if (sset != ETH_SS_STATS)424		return;425 426	memcpy(data, mt792x_gstrings_stats, sizeof(mt792x_gstrings_stats));427 428	data += sizeof(mt792x_gstrings_stats);429	page_pool_ethtool_stats_get_strings(data);430}431EXPORT_SYMBOL_GPL(mt792x_get_et_strings);432 433int mt792x_get_et_sset_count(struct ieee80211_hw *hw, struct ieee80211_vif *vif,434			     int sset)435{436	if (sset != ETH_SS_STATS)437		return 0;438 439	return ARRAY_SIZE(mt792x_gstrings_stats) +440	       page_pool_ethtool_stats_get_count();441}442EXPORT_SYMBOL_GPL(mt792x_get_et_sset_count);443 444static void445mt792x_ethtool_worker(void *wi_data, struct ieee80211_sta *sta)446{447	struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;448	struct mt76_ethtool_worker_info *wi = wi_data;449 450	if (msta->vif->bss_conf.mt76.idx != wi->idx)451		return;452 453	mt76_ethtool_worker(wi, &msta->deflink.wcid.stats, true);454}455 456void mt792x_get_et_stats(struct ieee80211_hw *hw, struct ieee80211_vif *vif,457			 struct ethtool_stats *stats, u64 *data)458{459	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;460	int stats_size = ARRAY_SIZE(mt792x_gstrings_stats);461	struct mt792x_phy *phy = mt792x_hw_phy(hw);462	struct mt792x_dev *dev = phy->dev;463	struct mt76_mib_stats *mib = &phy->mib;464	struct mt76_ethtool_worker_info wi = {465		.data = data,466		.idx = mvif->bss_conf.mt76.idx,467	};468	int i, ei = 0;469 470	mt792x_mutex_acquire(dev);471 472	mt792x_mac_update_mib_stats(phy);473 474	data[ei++] = mib->tx_ampdu_cnt;475	data[ei++] = mib->tx_mpdu_attempts_cnt;476	data[ei++] = mib->tx_mpdu_success_cnt;477	data[ei++] = mib->tx_pkt_ebf_cnt;478	data[ei++] = mib->tx_pkt_ibf_cnt;479 480	/* Tx ampdu stat */481	for (i = 0; i < 15; i++)482		data[ei++] = phy->mt76->aggr_stats[i];483 484	data[ei++] = phy->mib.ba_miss_cnt;485 486	/* Tx Beamformer monitor */487	data[ei++] = mib->tx_bf_ibf_ppdu_cnt;488	data[ei++] = mib->tx_bf_ebf_ppdu_cnt;489 490	/* Tx Beamformer Rx feedback monitor */491	data[ei++] = mib->tx_bf_rx_fb_all_cnt;492	data[ei++] = mib->tx_bf_rx_fb_he_cnt;493	data[ei++] = mib->tx_bf_rx_fb_vht_cnt;494	data[ei++] = mib->tx_bf_rx_fb_ht_cnt;495 496	/* Tx amsdu info (pack-count histogram) */497	for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++)498		data[ei++] = mib->tx_amsdu[i];499 500	/* rx counters */501	data[ei++] = mib->rx_mpdu_cnt;502	data[ei++] = mib->rx_ampdu_cnt;503	data[ei++] = mib->rx_ampdu_bytes_cnt;504	data[ei++] = mib->rx_ba_cnt;505 506	/* Add values for all stations owned by this vif */507	wi.initial_stat_idx = ei;508	ieee80211_iterate_stations_atomic(hw, mt792x_ethtool_worker, &wi);509 510	mt792x_mutex_release(dev);511 512	if (!wi.sta_count)513		return;514 515	ei += wi.worker_stat_count;516 517	mt76_ethtool_page_pool_stats(&dev->mt76, &data[ei], &ei);518	stats_size += page_pool_ethtool_stats_get_count();519 520	if (ei != stats_size)521		dev_err(dev->mt76.dev, "ei: %d  SSTATS_LEN: %d", ei,522			stats_size);523}524EXPORT_SYMBOL_GPL(mt792x_get_et_stats);525 526void mt792x_sta_statistics(struct ieee80211_hw *hw,527			   struct ieee80211_vif *vif,528			   struct ieee80211_sta *sta,529			   struct station_info *sinfo)530{531	struct mt792x_sta *msta = (struct mt792x_sta *)sta->drv_priv;532	struct rate_info *txrate = &msta->deflink.wcid.rate;533 534	if (!txrate->legacy && !txrate->flags)535		return;536 537	if (txrate->legacy) {538		sinfo->txrate.legacy = txrate->legacy;539	} else {540		sinfo->txrate.mcs = txrate->mcs;541		sinfo->txrate.nss = txrate->nss;542		sinfo->txrate.bw = txrate->bw;543		sinfo->txrate.he_gi = txrate->he_gi;544		sinfo->txrate.he_dcm = txrate->he_dcm;545		sinfo->txrate.he_ru_alloc = txrate->he_ru_alloc;546	}547	sinfo->tx_failed = msta->deflink.wcid.stats.tx_failed;548	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);549 550	sinfo->tx_retries = msta->deflink.wcid.stats.tx_retries;551	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);552 553	sinfo->txrate.flags = txrate->flags;554	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);555 556	sinfo->ack_signal = (s8)msta->deflink.ack_signal;557	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL);558 559	sinfo->avg_ack_signal = -(s8)ewma_avg_signal_read(&msta->deflink.avg_ack_signal);560	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_ACK_SIGNAL_AVG);561}562EXPORT_SYMBOL_GPL(mt792x_sta_statistics);563 564void mt792x_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)565{566	struct mt792x_phy *phy = mt792x_hw_phy(hw);567	struct mt792x_dev *dev = phy->dev;568 569	mt792x_mutex_acquire(dev);570 571	phy->coverage_class = max_t(s16, coverage_class, 0);572	mt792x_mac_set_timeing(phy);573 574	mt792x_mutex_release(dev);575}576EXPORT_SYMBOL_GPL(mt792x_set_coverage_class);577 578int mt792x_init_wiphy(struct ieee80211_hw *hw)579{580	struct mt792x_phy *phy = mt792x_hw_phy(hw);581	struct mt792x_dev *dev = phy->dev;582	struct wiphy *wiphy = hw->wiphy;583 584	hw->queues = 4;585	if (dev->has_eht) {586		hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_EHT;587		hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_EHT;588	} else {589		hw->max_rx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;590		hw->max_tx_aggregation_subframes = IEEE80211_MAX_AMPDU_BUF_HE;591	}592	hw->netdev_features = NETIF_F_RXCSUM;593 594	hw->radiotap_timestamp.units_pos =595		IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US;596 597	phy->slottime = 9;598 599	hw->sta_data_size = sizeof(struct mt792x_sta);600	hw->vif_data_size = sizeof(struct mt792x_vif);601	hw->chanctx_data_size = sizeof(struct mt792x_chanctx);602 603	if (dev->fw_features & MT792x_FW_CAP_CNM) {604		wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;605		wiphy->iface_combinations = if_comb_chanctx;606		wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx);607	} else {608		wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;609		wiphy->iface_combinations = if_comb;610		wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);611	}612	wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |613			  WIPHY_FLAG_4ADDR_STATION);614	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |615				 BIT(NL80211_IFTYPE_AP) |616				 BIT(NL80211_IFTYPE_P2P_CLIENT) |617				 BIT(NL80211_IFTYPE_P2P_GO);618	wiphy->max_remain_on_channel_duration = 5000;619	wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;620	wiphy->max_scan_ssids = 4;621	wiphy->max_sched_scan_plan_interval =622		MT76_CONNAC_MAX_TIME_SCHED_SCAN_INTERVAL;623	wiphy->max_sched_scan_ie_len = IEEE80211_MAX_DATA_LEN;624	wiphy->max_sched_scan_ssids = MT76_CONNAC_MAX_SCHED_SCAN_SSID;625	wiphy->max_match_sets = MT76_CONNAC_MAX_SCAN_MATCH;626	wiphy->max_sched_scan_reqs = 1;627	wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH |628			WIPHY_FLAG_SPLIT_SCAN_6GHZ;629 630	wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |631			   NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;632	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_SET_SCAN_DWELL);633	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_LEGACY);634	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HT);635	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_VHT);636	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);637	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);638	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);639 640	ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);641	ieee80211_hw_set(hw, HAS_RATE_CONTROL);642	ieee80211_hw_set(hw, SUPPORTS_TX_ENCAP_OFFLOAD);643	ieee80211_hw_set(hw, SUPPORTS_RX_DECAP_OFFLOAD);644	ieee80211_hw_set(hw, WANT_MONITOR_VIF);645	ieee80211_hw_set(hw, SUPPORTS_PS);646	ieee80211_hw_set(hw, SUPPORTS_DYNAMIC_PS);647	ieee80211_hw_set(hw, SUPPORTS_VHT_EXT_NSS_BW);648	ieee80211_hw_set(hw, CONNECTION_MONITOR);649 650	if (dev->pm.enable)651		ieee80211_hw_set(hw, CONNECTION_MONITOR);652 653	hw->max_tx_fragments = 4;654 655	return 0;656}657EXPORT_SYMBOL_GPL(mt792x_init_wiphy);658 659static u8660mt792x_get_offload_capability(struct device *dev, const char *fw_wm)661{662	const struct mt76_connac2_fw_trailer *hdr;663	struct mt792x_realease_info *rel_info;664	const struct firmware *fw;665	int ret, i, offset = 0;666	const u8 *data, *end;667	u8 offload_caps = 0;668 669	ret = request_firmware(&fw, fw_wm, dev);670	if (ret)671		return ret;672 673	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {674		dev_err(dev, "Invalid firmware\n");675		goto out;676	}677 678	data = fw->data;679	hdr = (const void *)(fw->data + fw->size - sizeof(*hdr));680 681	for (i = 0; i < hdr->n_region; i++) {682		const struct mt76_connac2_fw_region *region;683 684		region = (const void *)((const u8 *)hdr -685					(hdr->n_region - i) * sizeof(*region));686		offset += le32_to_cpu(region->len);687	}688 689	data += offset + 16;690	rel_info = (struct mt792x_realease_info *)data;691	data += sizeof(*rel_info);692	end = data + le16_to_cpu(rel_info->len);693 694	while (data < end) {695		rel_info = (struct mt792x_realease_info *)data;696		data += sizeof(*rel_info);697 698		if (rel_info->tag == MT792x_FW_TAG_FEATURE) {699			struct mt792x_fw_features *features;700 701			features = (struct mt792x_fw_features *)data;702			offload_caps = features->data;703			break;704		}705 706		data += le16_to_cpu(rel_info->len) + rel_info->pad_len;707	}708 709out:710	release_firmware(fw);711 712	return offload_caps;713}714 715struct ieee80211_ops *716mt792x_get_mac80211_ops(struct device *dev,717			const struct ieee80211_ops *mac80211_ops,718			void *drv_data, u8 *fw_features)719{720	struct ieee80211_ops *ops;721 722	ops = devm_kmemdup(dev, mac80211_ops, sizeof(struct ieee80211_ops),723			   GFP_KERNEL);724	if (!ops)725		return NULL;726 727	*fw_features = mt792x_get_offload_capability(dev, drv_data);728	if (!(*fw_features & MT792x_FW_CAP_CNM)) {729		ops->remain_on_channel = NULL;730		ops->cancel_remain_on_channel = NULL;731		ops->add_chanctx = ieee80211_emulate_add_chanctx;732		ops->remove_chanctx = ieee80211_emulate_remove_chanctx;733		ops->change_chanctx = ieee80211_emulate_change_chanctx;734		ops->switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx;735		ops->assign_vif_chanctx = NULL;736		ops->unassign_vif_chanctx = NULL;737		ops->mgd_prepare_tx = NULL;738		ops->mgd_complete_tx = NULL;739	}740	return ops;741}742EXPORT_SYMBOL_GPL(mt792x_get_mac80211_ops);743 744int mt792x_init_wcid(struct mt792x_dev *dev)745{746	int idx;747 748	/* Beacon and mgmt frames should occupy wcid 0 */749	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT792x_WTBL_STA - 1);750	if (idx)751		return -ENOSPC;752 753	dev->mt76.global_wcid.idx = idx;754	dev->mt76.global_wcid.hw_key_idx = -1;755	dev->mt76.global_wcid.tx_info |= MT_WCID_TX_INFO_SET;756	rcu_assign_pointer(dev->mt76.wcid[idx], &dev->mt76.global_wcid);757 758	return 0;759}760EXPORT_SYMBOL_GPL(mt792x_init_wcid);761 762int mt792x_mcu_drv_pmctrl(struct mt792x_dev *dev)763{764	struct mt76_phy *mphy = &dev->mt76.phy;765	struct mt76_connac_pm *pm = &dev->pm;766	int err = 0;767 768	mutex_lock(&pm->mutex);769 770	if (!test_bit(MT76_STATE_PM, &mphy->state))771		goto out;772 773	err = __mt792x_mcu_drv_pmctrl(dev);774out:775	mutex_unlock(&pm->mutex);776 777	if (err)778		mt792x_reset(&dev->mt76);779 780	return err;781}782EXPORT_SYMBOL_GPL(mt792x_mcu_drv_pmctrl);783 784int mt792x_mcu_fw_pmctrl(struct mt792x_dev *dev)785{786	struct mt76_phy *mphy = &dev->mt76.phy;787	struct mt76_connac_pm *pm = &dev->pm;788	int err = 0;789 790	mutex_lock(&pm->mutex);791 792	if (mt76_connac_skip_fw_pmctrl(mphy, pm))793		goto out;794 795	err = __mt792x_mcu_fw_pmctrl(dev);796out:797	mutex_unlock(&pm->mutex);798 799	if (err)800		mt792x_reset(&dev->mt76);801 802	return err;803}804EXPORT_SYMBOL_GPL(mt792x_mcu_fw_pmctrl);805 806int __mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev)807{808	int i, err = 0;809 810	for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) {811		mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_CLR_OWN);812 813		if (dev->aspm_supported)814			usleep_range(2000, 3000);815 816		if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL,817					PCIE_LPCR_HOST_OWN_SYNC, 0, 50, 1))818			break;819	}820 821	if (i == MT792x_DRV_OWN_RETRY_COUNT) {822		dev_err(dev->mt76.dev, "driver own failed\n");823		err = -EIO;824	}825 826	return err;827}828EXPORT_SYMBOL_GPL(__mt792xe_mcu_drv_pmctrl);829 830int mt792xe_mcu_drv_pmctrl(struct mt792x_dev *dev)831{832	struct mt76_phy *mphy = &dev->mt76.phy;833	struct mt76_connac_pm *pm = &dev->pm;834	int err;835 836	err = __mt792xe_mcu_drv_pmctrl(dev);837	if (err < 0)838		goto out;839 840	mt792x_wpdma_reinit_cond(dev);841	clear_bit(MT76_STATE_PM, &mphy->state);842 843	pm->stats.last_wake_event = jiffies;844	pm->stats.doze_time += pm->stats.last_wake_event -845			       pm->stats.last_doze_event;846out:847	return err;848}849EXPORT_SYMBOL_GPL(mt792xe_mcu_drv_pmctrl);850 851int mt792xe_mcu_fw_pmctrl(struct mt792x_dev *dev)852{853	struct mt76_phy *mphy = &dev->mt76.phy;854	struct mt76_connac_pm *pm = &dev->pm;855	int i;856 857	for (i = 0; i < MT792x_DRV_OWN_RETRY_COUNT; i++) {858		mt76_wr(dev, MT_CONN_ON_LPCTL, PCIE_LPCR_HOST_SET_OWN);859		if (mt76_poll_msec_tick(dev, MT_CONN_ON_LPCTL,860					PCIE_LPCR_HOST_OWN_SYNC, 4, 50, 1))861			break;862	}863 864	if (i == MT792x_DRV_OWN_RETRY_COUNT) {865		dev_err(dev->mt76.dev, "firmware own failed\n");866		clear_bit(MT76_STATE_PM, &mphy->state);867		return -EIO;868	}869 870	pm->stats.last_doze_event = jiffies;871	pm->stats.awake_time += pm->stats.last_doze_event -872				pm->stats.last_wake_event;873 874	return 0;875}876EXPORT_SYMBOL_GPL(mt792xe_mcu_fw_pmctrl);877 878int mt792x_load_firmware(struct mt792x_dev *dev)879{880	int ret;881 882	ret = mt76_connac2_load_patch(&dev->mt76, mt792x_patch_name(dev));883	if (ret)884		return ret;885 886	if (mt76_is_sdio(&dev->mt76)) {887		/* activate again */888		ret = __mt792x_mcu_fw_pmctrl(dev);889		if (!ret)890			ret = __mt792x_mcu_drv_pmctrl(dev);891	}892 893	ret = mt76_connac2_load_ram(&dev->mt76, mt792x_ram_name(dev), NULL);894	if (ret)895		return ret;896 897	if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY,898			    MT_TOP_MISC2_FW_N9_RDY, 1500)) {899		dev_err(dev->mt76.dev, "Timeout for initializing firmware\n");900 901		return -EIO;902	}903 904#ifdef CONFIG_PM905	dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support;906#endif /* CONFIG_PM */907 908	dev_dbg(dev->mt76.dev, "Firmware init done\n");909 910	return 0;911}912EXPORT_SYMBOL_GPL(mt792x_load_firmware);913 914MODULE_DESCRIPTION("MediaTek MT792x core driver");915MODULE_LICENSE("Dual BSD/GPL");916MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");917