brintos

brintos / linux-shallow public Read only

0
0
Text · 19.3 KiB · 574f74a Raw
757 lines · c
1// SPDX-License-Identifier: ISC2 3#include <linux/etherdevice.h>4#include <linux/platform_device.h>5#include <linux/pci.h>6#include <linux/module.h>7#include "mt7603.h"8#include "mac.h"9#include "eeprom.h"10 11static int12mt7603_start(struct ieee80211_hw *hw)13{14	struct mt7603_dev *dev = hw->priv;15 16	mt7603_mac_reset_counters(dev);17	mt7603_mac_start(dev);18	dev->mphy.survey_time = ktime_get_boottime();19	set_bit(MT76_STATE_RUNNING, &dev->mphy.state);20	mt7603_mac_work(&dev->mphy.mac_work.work);21 22	return 0;23}24 25static void26mt7603_stop(struct ieee80211_hw *hw, bool suspend)27{28	struct mt7603_dev *dev = hw->priv;29 30	clear_bit(MT76_STATE_RUNNING, &dev->mphy.state);31	cancel_delayed_work_sync(&dev->mphy.mac_work);32	mt7603_mac_stop(dev);33}34 35static int36mt7603_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)37{38	struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;39	struct mt7603_dev *dev = hw->priv;40	struct mt76_txq *mtxq;41	u8 bc_addr[ETH_ALEN];42	int idx;43	int ret = 0;44 45	mutex_lock(&dev->mt76.mutex);46 47	mvif->idx = __ffs64(~dev->mt76.vif_mask);48	if (mvif->idx >= MT7603_MAX_INTERFACES) {49		ret = -ENOSPC;50		goto out;51	}52 53	mt76_wr(dev, MT_MAC_ADDR0(mvif->idx),54		get_unaligned_le32(vif->addr));55	mt76_wr(dev, MT_MAC_ADDR1(mvif->idx),56		(get_unaligned_le16(vif->addr + 4) |57		 MT_MAC_ADDR1_VALID));58 59	if (vif->type == NL80211_IFTYPE_AP) {60		mt76_wr(dev, MT_BSSID0(mvif->idx),61			get_unaligned_le32(vif->addr));62		mt76_wr(dev, MT_BSSID1(mvif->idx),63			(get_unaligned_le16(vif->addr + 4) |64			 MT_BSSID1_VALID));65	}66 67	idx = MT7603_WTBL_RESERVED - 1 - mvif->idx;68	dev->mt76.vif_mask |= BIT_ULL(mvif->idx);69	INIT_LIST_HEAD(&mvif->sta.wcid.poll_list);70	mvif->sta.wcid.idx = idx;71	mvif->sta.wcid.hw_key_idx = -1;72	mvif->sta.vif = mvif;73	mt76_wcid_init(&mvif->sta.wcid);74 75	eth_broadcast_addr(bc_addr);76	mt7603_wtbl_init(dev, idx, mvif->idx, bc_addr);77 78	mtxq = (struct mt76_txq *)vif->txq->drv_priv;79	mtxq->wcid = idx;80	rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);81 82out:83	mutex_unlock(&dev->mt76.mutex);84 85	return ret;86}87 88static void89mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)90{91	struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;92	struct mt7603_sta *msta = &mvif->sta;93	struct mt7603_dev *dev = hw->priv;94	int idx = msta->wcid.idx;95 96	mt76_wr(dev, MT_MAC_ADDR0(mvif->idx), 0);97	mt76_wr(dev, MT_MAC_ADDR1(mvif->idx), 0);98	mt76_wr(dev, MT_BSSID0(mvif->idx), 0);99	mt76_wr(dev, MT_BSSID1(mvif->idx), 0);100	mt7603_beacon_set_timer(dev, mvif->idx, 0);101 102	rcu_assign_pointer(dev->mt76.wcid[idx], NULL);103 104	spin_lock_bh(&dev->mt76.sta_poll_lock);105	if (!list_empty(&msta->wcid.poll_list))106		list_del_init(&msta->wcid.poll_list);107	spin_unlock_bh(&dev->mt76.sta_poll_lock);108 109	mutex_lock(&dev->mt76.mutex);110	dev->mt76.vif_mask &= ~BIT_ULL(mvif->idx);111	mutex_unlock(&dev->mt76.mutex);112 113	mt76_wcid_cleanup(&dev->mt76, &mvif->sta.wcid);114}115 116void mt7603_init_edcca(struct mt7603_dev *dev)117{118	/* Set lower signal level to -65dBm */119	mt76_rmw_field(dev, MT_RXTD(8), MT_RXTD_8_LOWER_SIGNAL, 0x23);120 121	/* clear previous energy detect monitor results */122	mt76_rr(dev, MT_MIB_STAT_ED);123 124	if (dev->ed_monitor)125		mt76_set(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME);126	else127		mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME);128 129	dev->ed_strict_mode = 0xff;130	dev->ed_strong_signal = 0;131	dev->ed_time = ktime_get_boottime();132 133	mt7603_edcca_set_strict(dev, false);134}135 136int mt7603_set_channel(struct mt76_phy *mphy)137{138	struct mt7603_dev *dev = container_of(mphy->dev, struct mt7603_dev, mt76);139	struct cfg80211_chan_def *def = &mphy->chandef;140 141	u8 *rssi_data = (u8 *)dev->mt76.eeprom.data;142	int idx, ret;143	u8 bw = MT_BW_20;144	bool failed = false;145 146	tasklet_disable(&dev->mt76.pre_tbtt_tasklet);147 148	mt7603_beacon_set_timer(dev, -1, 0);149	mt7603_mac_stop(dev);150 151	if (def->width == NL80211_CHAN_WIDTH_40)152		bw = MT_BW_40;153 154	mt76_rmw_field(dev, MT_AGG_BWCR, MT_AGG_BWCR_BW, bw);155	ret = mt7603_mcu_set_channel(dev);156	if (ret) {157		failed = true;158		goto out;159	}160 161	if (def->chan->band == NL80211_BAND_5GHZ) {162		idx = 1;163		rssi_data += MT_EE_RSSI_OFFSET_5G;164	} else {165		idx = 0;166		rssi_data += MT_EE_RSSI_OFFSET_2G;167	}168 169	memcpy(dev->rssi_offset, rssi_data, sizeof(dev->rssi_offset));170 171	idx |= (def->chan -172		mt76_hw(dev)->wiphy->bands[def->chan->band]->channels) << 1;173	mt76_wr(dev, MT_WF_RMAC_CH_FREQ, idx);174	mt7603_mac_set_timing(dev);175	mt7603_mac_start(dev);176 177	ieee80211_queue_delayed_work(mt76_hw(dev), &dev->mphy.mac_work,178				     msecs_to_jiffies(MT7603_WATCHDOG_TIME));179 180	/* reset channel stats */181	mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_READ_CLR_DIS);182	mt76_set(dev, MT_MIB_CTL,183		 MT_MIB_CTL_CCA_NAV_TX | MT_MIB_CTL_PSCCA_TIME);184	mt76_rr(dev, MT_MIB_STAT_CCA);185	mt7603_cca_stats_reset(dev);186 187	dev->mphy.survey_time = ktime_get_boottime();188 189	mt7603_init_edcca(dev);190 191out:192	if (!mphy->offchannel)193		mt7603_beacon_set_timer(dev, -1, dev->mt76.beacon_int);194 195	tasklet_enable(&dev->mt76.pre_tbtt_tasklet);196 197	if (failed)198		mt7603_mac_work(&dev->mphy.mac_work.work);199 200	return ret;201}202 203static int mt7603_set_sar_specs(struct ieee80211_hw *hw,204				const struct cfg80211_sar_specs *sar)205{206	struct mt7603_dev *dev = hw->priv;207	struct mt76_phy *mphy = &dev->mphy;208	int err;209 210	if (!cfg80211_chandef_valid(&mphy->chandef))211		return -EINVAL;212 213	err = mt76_init_sar_power(hw, sar);214	if (err)215		return err;216 217	return mt76_update_channel(mphy);218}219 220static int221mt7603_config(struct ieee80211_hw *hw, u32 changed)222{223	struct mt7603_dev *dev = hw->priv;224	int ret = 0;225 226	if (changed & (IEEE80211_CONF_CHANGE_CHANNEL |227		       IEEE80211_CONF_CHANGE_POWER))228		ret = mt76_update_channel(&dev->mphy);229 230	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {231		mutex_lock(&dev->mt76.mutex);232 233		if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))234			dev->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;235		else236			dev->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;237 238		mt76_wr(dev, MT_WF_RFCR, dev->rxfilter);239 240		mutex_unlock(&dev->mt76.mutex);241	}242 243	return ret;244}245 246static void247mt7603_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags,248			unsigned int *total_flags, u64 multicast)249{250	struct mt7603_dev *dev = hw->priv;251	u32 flags = 0;252 253#define MT76_FILTER(_flag, _hw) do { \254		flags |= *total_flags & FIF_##_flag;			\255		dev->rxfilter &= ~(_hw);				\256		dev->rxfilter |= !(flags & FIF_##_flag) * (_hw);	\257	} while (0)258 259	dev->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |260			   MT_WF_RFCR_DROP_OTHER_BEACON |261			   MT_WF_RFCR_DROP_FRAME_REPORT |262			   MT_WF_RFCR_DROP_PROBEREQ |263			   MT_WF_RFCR_DROP_MCAST_FILTERED |264			   MT_WF_RFCR_DROP_MCAST |265			   MT_WF_RFCR_DROP_BCAST |266			   MT_WF_RFCR_DROP_DUPLICATE |267			   MT_WF_RFCR_DROP_A2_BSSID |268			   MT_WF_RFCR_DROP_UNWANTED_CTL |269			   MT_WF_RFCR_DROP_STBC_MULTI);270 271	MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |272			       MT_WF_RFCR_DROP_A3_MAC |273			       MT_WF_RFCR_DROP_A3_BSSID);274 275	MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL);276 277	MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS |278			     MT_WF_RFCR_DROP_RTS |279			     MT_WF_RFCR_DROP_CTL_RSV |280			     MT_WF_RFCR_DROP_NDPA);281 282	*total_flags = flags;283	mt76_wr(dev, MT_WF_RFCR, dev->rxfilter);284}285 286static void287mt7603_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,288			struct ieee80211_bss_conf *info, u64 changed)289{290	struct mt7603_dev *dev = hw->priv;291	struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;292 293	mutex_lock(&dev->mt76.mutex);294 295	if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BSSID)) {296		if (vif->cfg.assoc || vif->cfg.ibss_joined) {297			mt76_wr(dev, MT_BSSID0(mvif->idx),298				get_unaligned_le32(info->bssid));299			mt76_wr(dev, MT_BSSID1(mvif->idx),300				(get_unaligned_le16(info->bssid + 4) |301				 MT_BSSID1_VALID));302		} else {303			mt76_wr(dev, MT_BSSID0(mvif->idx), 0);304			mt76_wr(dev, MT_BSSID1(mvif->idx), 0);305		}306	}307 308	if (changed & BSS_CHANGED_ERP_SLOT) {309		int slottime = info->use_short_slot ? 9 : 20;310 311		if (slottime != dev->slottime) {312			dev->slottime = slottime;313			mt7603_mac_set_timing(dev);314		}315	}316 317	if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON_INT)) {318		int beacon_int = !!info->enable_beacon * info->beacon_int;319 320		tasklet_disable(&dev->mt76.pre_tbtt_tasklet);321		mt7603_beacon_set_timer(dev, mvif->idx, beacon_int);322		tasklet_enable(&dev->mt76.pre_tbtt_tasklet);323	}324 325	mutex_unlock(&dev->mt76.mutex);326}327 328int329mt7603_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,330	       struct ieee80211_sta *sta)331{332	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);333	struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;334	struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;335	int idx;336	int ret = 0;337 338	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7603_WTBL_STA - 1);339	if (idx < 0)340		return -ENOSPC;341 342	INIT_LIST_HEAD(&msta->wcid.poll_list);343	__skb_queue_head_init(&msta->psq);344	msta->ps = ~0;345	msta->smps = ~0;346	msta->wcid.sta = 1;347	msta->wcid.idx = idx;348	msta->vif = mvif;349	mt7603_wtbl_init(dev, idx, mvif->idx, sta->addr);350	mt7603_wtbl_set_ps(dev, msta, false);351 352	if (vif->type == NL80211_IFTYPE_AP)353		set_bit(MT_WCID_FLAG_CHECK_PS, &msta->wcid.flags);354 355	return ret;356}357 358int359mt7603_sta_event(struct mt76_dev *mdev, struct ieee80211_vif *vif,360		 struct ieee80211_sta *sta, enum mt76_sta_event ev)361{362	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);363 364	if (ev == MT76_STA_EVENT_ASSOC) {365		mutex_lock(&dev->mt76.mutex);366		mt7603_wtbl_update_cap(dev, sta);367		mutex_unlock(&dev->mt76.mutex);368	}369 370	return 0;371}372 373void374mt7603_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,375		  struct ieee80211_sta *sta)376{377	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);378	struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;379	struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;380	struct mt76_wcid *wcid = (struct mt76_wcid *)sta->drv_priv;381 382	spin_lock_bh(&dev->ps_lock);383	__skb_queue_purge(&msta->psq);384	mt7603_filter_tx(dev, mvif->idx, wcid->idx, true);385	spin_unlock_bh(&dev->ps_lock);386 387	spin_lock_bh(&mdev->sta_poll_lock);388	if (!list_empty(&msta->wcid.poll_list))389		list_del_init(&msta->wcid.poll_list);390	spin_unlock_bh(&mdev->sta_poll_lock);391 392	mt7603_wtbl_clear(dev, wcid->idx);393}394 395static void396mt7603_ps_tx_list(struct mt7603_dev *dev, struct sk_buff_head *list)397{398	struct sk_buff *skb;399 400	while ((skb = __skb_dequeue(list)) != NULL) {401		int qid = skb_get_queue_mapping(skb);402 403		mt76_tx_queue_skb_raw(dev, dev->mphy.q_tx[qid], skb, 0);404	}405}406 407void408mt7603_sta_ps(struct mt76_dev *mdev, struct ieee80211_sta *sta, bool ps)409{410	struct mt7603_dev *dev = container_of(mdev, struct mt7603_dev, mt76);411	struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;412	struct sk_buff_head list;413 414	mt76_stop_tx_queues(&dev->mphy, sta, true);415	mt7603_wtbl_set_ps(dev, msta, ps);416	if (ps)417		return;418 419	__skb_queue_head_init(&list);420 421	spin_lock_bh(&dev->ps_lock);422	skb_queue_splice_tail_init(&msta->psq, &list);423	spin_unlock_bh(&dev->ps_lock);424 425	mt7603_ps_tx_list(dev, &list);426}427 428static void429mt7603_ps_set_more_data(struct sk_buff *skb)430{431	struct ieee80211_hdr *hdr;432 433	hdr = (struct ieee80211_hdr *)&skb->data[MT_TXD_SIZE];434	hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);435}436 437static void438mt7603_release_buffered_frames(struct ieee80211_hw *hw,439			       struct ieee80211_sta *sta,440			       u16 tids, int nframes,441			       enum ieee80211_frame_release_type reason,442			       bool more_data)443{444	struct mt7603_dev *dev = hw->priv;445	struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;446	struct sk_buff_head list;447	struct sk_buff *skb, *tmp;448 449	__skb_queue_head_init(&list);450 451	mt7603_wtbl_set_ps(dev, msta, false);452 453	spin_lock_bh(&dev->ps_lock);454	skb_queue_walk_safe(&msta->psq, skb, tmp) {455		if (!nframes)456			break;457 458		if (!(tids & BIT(skb->priority)))459			continue;460 461		skb_set_queue_mapping(skb, MT_TXQ_PSD);462		__skb_unlink(skb, &msta->psq);463		mt7603_ps_set_more_data(skb);464		__skb_queue_tail(&list, skb);465		nframes--;466	}467	spin_unlock_bh(&dev->ps_lock);468 469	if (!skb_queue_empty(&list))470		ieee80211_sta_eosp(sta);471 472	mt7603_ps_tx_list(dev, &list);473 474	if (nframes)475		mt76_release_buffered_frames(hw, sta, tids, nframes, reason,476					     more_data);477}478 479static int480mt7603_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,481	       struct ieee80211_vif *vif, struct ieee80211_sta *sta,482	       struct ieee80211_key_conf *key)483{484	struct mt7603_dev *dev = hw->priv;485	struct mt7603_vif *mvif = (struct mt7603_vif *)vif->drv_priv;486	struct mt7603_sta *msta = sta ? (struct mt7603_sta *)sta->drv_priv :487				  &mvif->sta;488	struct mt76_wcid *wcid = &msta->wcid;489	int idx = key->keyidx;490 491	/* fall back to sw encryption for unsupported ciphers */492	switch (key->cipher) {493	case WLAN_CIPHER_SUITE_TKIP:494	case WLAN_CIPHER_SUITE_CCMP:495		break;496	default:497		return -EOPNOTSUPP;498	}499 500	/*501	 * The hardware does not support per-STA RX GTK, fall back502	 * to software mode for these.503	 */504	if ((vif->type == NL80211_IFTYPE_ADHOC ||505	     vif->type == NL80211_IFTYPE_MESH_POINT) &&506	    (key->cipher == WLAN_CIPHER_SUITE_TKIP ||507	     key->cipher == WLAN_CIPHER_SUITE_CCMP) &&508	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))509		return -EOPNOTSUPP;510 511	if (cmd != SET_KEY) {512		if (idx == wcid->hw_key_idx)513			wcid->hw_key_idx = -1;514 515		return 0;516	}517 518	key->hw_key_idx = wcid->idx;519	wcid->hw_key_idx = idx;520	mt76_wcid_key_setup(&dev->mt76, wcid, key);521 522	return mt7603_wtbl_set_key(dev, wcid->idx, key);523}524 525static int526mt7603_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,527	       unsigned int link_id, u16 queue,528	       const struct ieee80211_tx_queue_params *params)529{530	struct mt7603_dev *dev = hw->priv;531	u16 cw_min = (1 << 5) - 1;532	u16 cw_max = (1 << 10) - 1;533	u32 val;534 535	queue = dev->mphy.q_tx[queue]->hw_idx;536 537	if (params->cw_min)538		cw_min = params->cw_min;539	if (params->cw_max)540		cw_max = params->cw_max;541 542	mutex_lock(&dev->mt76.mutex);543	mt7603_mac_stop(dev);544 545	val = mt76_rr(dev, MT_WMM_TXOP(queue));546	val &= ~(MT_WMM_TXOP_MASK << MT_WMM_TXOP_SHIFT(queue));547	val |= params->txop << MT_WMM_TXOP_SHIFT(queue);548	mt76_wr(dev, MT_WMM_TXOP(queue), val);549 550	val = mt76_rr(dev, MT_WMM_AIFSN);551	val &= ~(MT_WMM_AIFSN_MASK << MT_WMM_AIFSN_SHIFT(queue));552	val |= params->aifs << MT_WMM_AIFSN_SHIFT(queue);553	mt76_wr(dev, MT_WMM_AIFSN, val);554 555	val = mt76_rr(dev, MT_WMM_CWMIN);556	val &= ~(MT_WMM_CWMIN_MASK << MT_WMM_CWMIN_SHIFT(queue));557	val |= cw_min << MT_WMM_CWMIN_SHIFT(queue);558	mt76_wr(dev, MT_WMM_CWMIN, val);559 560	val = mt76_rr(dev, MT_WMM_CWMAX(queue));561	val &= ~(MT_WMM_CWMAX_MASK << MT_WMM_CWMAX_SHIFT(queue));562	val |= cw_max << MT_WMM_CWMAX_SHIFT(queue);563	mt76_wr(dev, MT_WMM_CWMAX(queue), val);564 565	mt7603_mac_start(dev);566	mutex_unlock(&dev->mt76.mutex);567 568	return 0;569}570 571static void572mt7603_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,573	     u32 queues, bool drop)574{575}576 577static int578mt7603_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,579		    struct ieee80211_ampdu_params *params)580{581	enum ieee80211_ampdu_mlme_action action = params->action;582	struct mt7603_dev *dev = hw->priv;583	struct ieee80211_sta *sta = params->sta;584	struct ieee80211_txq *txq = sta->txq[params->tid];585	struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;586	u16 tid = params->tid;587	u16 ssn = params->ssn;588	u8 ba_size = params->buf_size;589	struct mt76_txq *mtxq;590	int ret = 0;591 592	if (!txq)593		return -EINVAL;594 595	mtxq = (struct mt76_txq *)txq->drv_priv;596 597	mutex_lock(&dev->mt76.mutex);598	switch (action) {599	case IEEE80211_AMPDU_RX_START:600		mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,601				   params->buf_size);602		mt7603_mac_rx_ba_reset(dev, sta->addr, tid);603		break;604	case IEEE80211_AMPDU_RX_STOP:605		mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);606		break;607	case IEEE80211_AMPDU_TX_OPERATIONAL:608		mtxq->aggr = true;609		mtxq->send_bar = false;610		mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, ba_size);611		break;612	case IEEE80211_AMPDU_TX_STOP_FLUSH:613	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:614		mtxq->aggr = false;615		mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, -1);616		break;617	case IEEE80211_AMPDU_TX_START:618		mtxq->agg_ssn = IEEE80211_SN_TO_SEQ(ssn);619		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;620		break;621	case IEEE80211_AMPDU_TX_STOP_CONT:622		mtxq->aggr = false;623		mt7603_mac_tx_ba_reset(dev, msta->wcid.idx, tid, -1);624		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);625		break;626	}627	mutex_unlock(&dev->mt76.mutex);628 629	return ret;630}631 632static void633mt7603_sta_rate_tbl_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif,634			   struct ieee80211_sta *sta)635{636	struct mt7603_dev *dev = hw->priv;637	struct mt7603_sta *msta = (struct mt7603_sta *)sta->drv_priv;638	struct ieee80211_sta_rates *sta_rates = rcu_dereference(sta->rates);639	int i;640 641	if (!sta_rates)642		return;643 644	spin_lock_bh(&dev->mt76.lock);645	for (i = 0; i < ARRAY_SIZE(msta->rates); i++) {646		msta->rates[i].idx = sta_rates->rate[i].idx;647		msta->rates[i].count = sta_rates->rate[i].count;648		msta->rates[i].flags = sta_rates->rate[i].flags;649 650		if (msta->rates[i].idx < 0 || !msta->rates[i].count)651			break;652	}653	msta->n_rates = i;654	mt7603_wtbl_set_rates(dev, msta, NULL, msta->rates);655	msta->rate_probe = false;656	mt7603_wtbl_set_smps(dev, msta,657			     sta->deflink.smps_mode == IEEE80211_SMPS_DYNAMIC);658	spin_unlock_bh(&dev->mt76.lock);659}660 661static void662mt7603_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)663{664	struct mt7603_dev *dev = hw->priv;665 666	mutex_lock(&dev->mt76.mutex);667	dev->coverage_class = max_t(s16, coverage_class, 0);668	mt7603_mac_set_timing(dev);669	mutex_unlock(&dev->mt76.mutex);670}671 672static void mt7603_tx(struct ieee80211_hw *hw,673		      struct ieee80211_tx_control *control,674		      struct sk_buff *skb)675{676	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);677	struct ieee80211_vif *vif = info->control.vif;678	struct mt7603_dev *dev = hw->priv;679	struct mt76_wcid *wcid = &dev->global_sta.wcid;680 681	if (control->sta) {682		struct mt7603_sta *msta;683 684		msta = (struct mt7603_sta *)control->sta->drv_priv;685		wcid = &msta->wcid;686	} else if (vif) {687		struct mt7603_vif *mvif;688 689		mvif = (struct mt7603_vif *)vif->drv_priv;690		wcid = &mvif->sta.wcid;691	}692 693	mt76_tx(&dev->mphy, control->sta, wcid, skb);694}695 696const struct ieee80211_ops mt7603_ops = {697	.add_chanctx = ieee80211_emulate_add_chanctx,698	.remove_chanctx = ieee80211_emulate_remove_chanctx,699	.change_chanctx = ieee80211_emulate_change_chanctx,700	.switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,701	.tx = mt7603_tx,702	.start = mt7603_start,703	.stop = mt7603_stop,704	.add_interface = mt7603_add_interface,705	.remove_interface = mt7603_remove_interface,706	.config = mt7603_config,707	.configure_filter = mt7603_configure_filter,708	.bss_info_changed = mt7603_bss_info_changed,709	.sta_state = mt76_sta_state,710	.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,711	.set_key = mt7603_set_key,712	.conf_tx = mt7603_conf_tx,713	.sw_scan_start = mt76_sw_scan,714	.sw_scan_complete = mt76_sw_scan_complete,715	.flush = mt7603_flush,716	.ampdu_action = mt7603_ampdu_action,717	.get_txpower = mt76_get_txpower,718	.wake_tx_queue = mt76_wake_tx_queue,719	.sta_rate_tbl_update = mt7603_sta_rate_tbl_update,720	.release_buffered_frames = mt7603_release_buffered_frames,721	.set_coverage_class = mt7603_set_coverage_class,722	.set_tim = mt76_set_tim,723	.get_survey = mt76_get_survey,724	.get_antenna = mt76_get_antenna,725	.set_sar_specs = mt7603_set_sar_specs,726};727 728MODULE_DESCRIPTION("MediaTek MT7603E and MT76x8 wireless driver");729MODULE_LICENSE("Dual BSD/GPL");730 731static int __init mt7603_init(void)732{733	int ret;734 735	ret = platform_driver_register(&mt76_wmac_driver);736	if (ret)737		return ret;738 739#ifdef CONFIG_PCI740	ret = pci_register_driver(&mt7603_pci_driver);741	if (ret)742		platform_driver_unregister(&mt76_wmac_driver);743#endif744	return ret;745}746 747static void __exit mt7603_exit(void)748{749#ifdef CONFIG_PCI750	pci_unregister_driver(&mt7603_pci_driver);751#endif752	platform_driver_unregister(&mt76_wmac_driver);753}754 755module_init(mt7603_init);756module_exit(mt7603_exit);757