xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/mediatek/mt76/mt7915/main.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: ISC
2*4882a593Smuzhiyun /* Copyright (C) 2020 MediaTek Inc. */
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <linux/etherdevice.h>
5*4882a593Smuzhiyun #include <linux/platform_device.h>
6*4882a593Smuzhiyun #include <linux/pci.h>
7*4882a593Smuzhiyun #include <linux/module.h>
8*4882a593Smuzhiyun #include "mt7915.h"
9*4882a593Smuzhiyun #include "mcu.h"
10*4882a593Smuzhiyun 
mt7915_dev_running(struct mt7915_dev * dev)11*4882a593Smuzhiyun static bool mt7915_dev_running(struct mt7915_dev *dev)
12*4882a593Smuzhiyun {
13*4882a593Smuzhiyun 	struct mt7915_phy *phy;
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun 	if (test_bit(MT76_STATE_RUNNING, &dev->mphy.state))
16*4882a593Smuzhiyun 		return true;
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun 	phy = mt7915_ext_phy(dev);
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun 	return phy && test_bit(MT76_STATE_RUNNING, &phy->mt76->state);
21*4882a593Smuzhiyun }
22*4882a593Smuzhiyun 
mt7915_start(struct ieee80211_hw * hw)23*4882a593Smuzhiyun static int mt7915_start(struct ieee80211_hw *hw)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
26*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
27*4882a593Smuzhiyun 	bool running;
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 	running = mt7915_dev_running(dev);
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun 	if (!running) {
34*4882a593Smuzhiyun 		mt7915_mcu_set_pm(dev, 0, 0);
35*4882a593Smuzhiyun 		mt7915_mcu_set_mac(dev, 0, true, false);
36*4882a593Smuzhiyun 		mt7915_mcu_set_scs(dev, 0, true);
37*4882a593Smuzhiyun 	}
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun 	if (phy != &dev->phy) {
40*4882a593Smuzhiyun 		mt7915_mcu_set_pm(dev, 1, 0);
41*4882a593Smuzhiyun 		mt7915_mcu_set_mac(dev, 1, true, false);
42*4882a593Smuzhiyun 		mt7915_mcu_set_scs(dev, 1, true);
43*4882a593Smuzhiyun 	}
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	mt7915_mcu_set_sku_en(phy, true);
46*4882a593Smuzhiyun 	mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	set_bit(MT76_STATE_RUNNING, &phy->mt76->state);
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	ieee80211_queue_delayed_work(hw, &phy->mac_work,
51*4882a593Smuzhiyun 				     MT7915_WATCHDOG_TIME);
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	if (!running)
54*4882a593Smuzhiyun 		mt7915_mac_reset_counters(phy);
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	return 0;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
mt7915_stop(struct ieee80211_hw * hw)61*4882a593Smuzhiyun static void mt7915_stop(struct ieee80211_hw *hw)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
64*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	cancel_delayed_work_sync(&phy->mac_work);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun 	clear_bit(MT76_STATE_RUNNING, &phy->mt76->state);
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun 	if (phy != &dev->phy) {
73*4882a593Smuzhiyun 		mt7915_mcu_set_pm(dev, 1, 1);
74*4882a593Smuzhiyun 		mt7915_mcu_set_mac(dev, 1, false, false);
75*4882a593Smuzhiyun 	}
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	if (!mt7915_dev_running(dev)) {
78*4882a593Smuzhiyun 		mt7915_mcu_set_pm(dev, 0, 1);
79*4882a593Smuzhiyun 		mt7915_mcu_set_mac(dev, 0, false, false);
80*4882a593Smuzhiyun 	}
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun 
get_omac_idx(enum nl80211_iftype type,u32 mask)85*4882a593Smuzhiyun static int get_omac_idx(enum nl80211_iftype type, u32 mask)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun 	int i;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	switch (type) {
90*4882a593Smuzhiyun 	case NL80211_IFTYPE_MONITOR:
91*4882a593Smuzhiyun 	case NL80211_IFTYPE_AP:
92*4882a593Smuzhiyun 		/* ap uses hw bssid 0 and ext bssid */
93*4882a593Smuzhiyun 		if (~mask & BIT(HW_BSSID_0))
94*4882a593Smuzhiyun 			return HW_BSSID_0;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 		for (i = EXT_BSSID_1; i < EXT_BSSID_END; i++)
97*4882a593Smuzhiyun 			if (~mask & BIT(i))
98*4882a593Smuzhiyun 				return i;
99*4882a593Smuzhiyun 		break;
100*4882a593Smuzhiyun 	case NL80211_IFTYPE_MESH_POINT:
101*4882a593Smuzhiyun 	case NL80211_IFTYPE_ADHOC:
102*4882a593Smuzhiyun 	case NL80211_IFTYPE_STATION:
103*4882a593Smuzhiyun 		/* station uses hw bssid other than 0 */
104*4882a593Smuzhiyun 		for (i = HW_BSSID_1; i < HW_BSSID_MAX; i++)
105*4882a593Smuzhiyun 			if (~mask & BIT(i))
106*4882a593Smuzhiyun 				return i;
107*4882a593Smuzhiyun 		break;
108*4882a593Smuzhiyun 	default:
109*4882a593Smuzhiyun 		WARN_ON(1);
110*4882a593Smuzhiyun 		break;
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	return -1;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
mt7915_add_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)116*4882a593Smuzhiyun static int mt7915_add_interface(struct ieee80211_hw *hw,
117*4882a593Smuzhiyun 				struct ieee80211_vif *vif)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun 	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
120*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
121*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
122*4882a593Smuzhiyun 	struct mt76_txq *mtxq;
123*4882a593Smuzhiyun 	bool ext_phy = phy != &dev->phy;
124*4882a593Smuzhiyun 	int idx, ret = 0;
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	mvif->idx = ffs(~phy->mt76->vif_mask) - 1;
129*4882a593Smuzhiyun 	if (mvif->idx >= MT7915_MAX_INTERFACES) {
130*4882a593Smuzhiyun 		ret = -ENOSPC;
131*4882a593Smuzhiyun 		goto out;
132*4882a593Smuzhiyun 	}
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	idx = get_omac_idx(vif->type, phy->omac_mask);
135*4882a593Smuzhiyun 	if (idx < 0) {
136*4882a593Smuzhiyun 		ret = -ENOSPC;
137*4882a593Smuzhiyun 		goto out;
138*4882a593Smuzhiyun 	}
139*4882a593Smuzhiyun 	mvif->omac_idx = idx;
140*4882a593Smuzhiyun 	mvif->phy = phy;
141*4882a593Smuzhiyun 	mvif->band_idx = ext_phy;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	if (ext_phy)
144*4882a593Smuzhiyun 		mvif->wmm_idx = ext_phy * (MT7915_MAX_WMM_SETS / 2) +
145*4882a593Smuzhiyun 				mvif->idx % (MT7915_MAX_WMM_SETS / 2);
146*4882a593Smuzhiyun 	else
147*4882a593Smuzhiyun 		mvif->wmm_idx = mvif->idx % MT7915_MAX_WMM_SETS;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun 	ret = mt7915_mcu_add_dev_info(dev, vif, true);
150*4882a593Smuzhiyun 	if (ret)
151*4882a593Smuzhiyun 		goto out;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	phy->mt76->vif_mask |= BIT(mvif->idx);
154*4882a593Smuzhiyun 	phy->omac_mask |= BIT(mvif->omac_idx);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	idx = MT7915_WTBL_RESERVED - mvif->idx;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mvif->sta.rc_list);
159*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mvif->sta.stats_list);
160*4882a593Smuzhiyun 	INIT_LIST_HEAD(&mvif->sta.poll_list);
161*4882a593Smuzhiyun 	mvif->sta.wcid.idx = idx;
162*4882a593Smuzhiyun 	mvif->sta.wcid.ext_phy = mvif->band_idx;
163*4882a593Smuzhiyun 	mvif->sta.wcid.hw_key_idx = -1;
164*4882a593Smuzhiyun 	mvif->sta.wcid.tx_info |= MT_WCID_TX_INFO_SET;
165*4882a593Smuzhiyun 	mt7915_mac_wtbl_update(dev, idx,
166*4882a593Smuzhiyun 			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
169*4882a593Smuzhiyun 	if (vif->txq) {
170*4882a593Smuzhiyun 		mtxq = (struct mt76_txq *)vif->txq->drv_priv;
171*4882a593Smuzhiyun 		mtxq->wcid = &mvif->sta.wcid;
172*4882a593Smuzhiyun 	}
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun out:
175*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	return ret;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun 
mt7915_remove_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)180*4882a593Smuzhiyun static void mt7915_remove_interface(struct ieee80211_hw *hw,
181*4882a593Smuzhiyun 				    struct ieee80211_vif *vif)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun 	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
184*4882a593Smuzhiyun 	struct mt7915_sta *msta = &mvif->sta;
185*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
186*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
187*4882a593Smuzhiyun 	int idx = msta->wcid.idx;
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	/* TODO: disable beacon for the bss */
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	mt7915_mcu_add_dev_info(dev, vif, false);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	rcu_assign_pointer(dev->mt76.wcid[idx], NULL);
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
196*4882a593Smuzhiyun 	phy->mt76->vif_mask &= ~BIT(mvif->idx);
197*4882a593Smuzhiyun 	phy->omac_mask &= ~BIT(mvif->omac_idx);
198*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	spin_lock_bh(&dev->sta_poll_lock);
201*4882a593Smuzhiyun 	if (!list_empty(&msta->poll_list))
202*4882a593Smuzhiyun 		list_del_init(&msta->poll_list);
203*4882a593Smuzhiyun 	spin_unlock_bh(&dev->sta_poll_lock);
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun 
mt7915_init_dfs_state(struct mt7915_phy * phy)206*4882a593Smuzhiyun static void mt7915_init_dfs_state(struct mt7915_phy *phy)
207*4882a593Smuzhiyun {
208*4882a593Smuzhiyun 	struct mt76_phy *mphy = phy->mt76;
209*4882a593Smuzhiyun 	struct ieee80211_hw *hw = mphy->hw;
210*4882a593Smuzhiyun 	struct cfg80211_chan_def *chandef = &hw->conf.chandef;
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
213*4882a593Smuzhiyun 		return;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR))
216*4882a593Smuzhiyun 		return;
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	if (mphy->chandef.chan->center_freq == chandef->chan->center_freq &&
219*4882a593Smuzhiyun 	    mphy->chandef.width == chandef->width)
220*4882a593Smuzhiyun 		return;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 	phy->dfs_state = -1;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
mt7915_set_channel(struct mt7915_phy * phy)225*4882a593Smuzhiyun static int mt7915_set_channel(struct mt7915_phy *phy)
226*4882a593Smuzhiyun {
227*4882a593Smuzhiyun 	struct mt7915_dev *dev = phy->dev;
228*4882a593Smuzhiyun 	int ret;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	cancel_delayed_work_sync(&phy->mac_work);
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
233*4882a593Smuzhiyun 	set_bit(MT76_RESET, &phy->mt76->state);
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun 	mt7915_init_dfs_state(phy);
236*4882a593Smuzhiyun 	mt76_set_channel(phy->mt76);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	ret = mt7915_mcu_set_chan_info(phy, MCU_EXT_CMD_CHANNEL_SWITCH);
239*4882a593Smuzhiyun 	if (ret)
240*4882a593Smuzhiyun 		goto out;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	mt7915_mac_set_timing(phy);
243*4882a593Smuzhiyun 	ret = mt7915_dfs_init_radar_detector(phy);
244*4882a593Smuzhiyun 	mt7915_mac_cca_stats_reset(phy);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	mt7915_mac_reset_counters(phy);
247*4882a593Smuzhiyun 	phy->noise = 0;
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun out:
250*4882a593Smuzhiyun 	clear_bit(MT76_RESET, &phy->mt76->state);
251*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	mt76_txq_schedule_all(phy->mt76);
254*4882a593Smuzhiyun 	ieee80211_queue_delayed_work(phy->mt76->hw, &phy->mac_work,
255*4882a593Smuzhiyun 				     MT7915_WATCHDOG_TIME);
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	return ret;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun 
mt7915_set_key(struct ieee80211_hw * hw,enum set_key_cmd cmd,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ieee80211_key_conf * key)260*4882a593Smuzhiyun static int mt7915_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
261*4882a593Smuzhiyun 			  struct ieee80211_vif *vif, struct ieee80211_sta *sta,
262*4882a593Smuzhiyun 			  struct ieee80211_key_conf *key)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
265*4882a593Smuzhiyun 	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
266*4882a593Smuzhiyun 	struct mt7915_sta *msta = sta ? (struct mt7915_sta *)sta->drv_priv :
267*4882a593Smuzhiyun 				  &mvif->sta;
268*4882a593Smuzhiyun 	struct mt76_wcid *wcid = &msta->wcid;
269*4882a593Smuzhiyun 	int idx = key->keyidx;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	/* The hardware does not support per-STA RX GTK, fallback
272*4882a593Smuzhiyun 	 * to software mode for these.
273*4882a593Smuzhiyun 	 */
274*4882a593Smuzhiyun 	if ((vif->type == NL80211_IFTYPE_ADHOC ||
275*4882a593Smuzhiyun 	     vif->type == NL80211_IFTYPE_MESH_POINT) &&
276*4882a593Smuzhiyun 	    (key->cipher == WLAN_CIPHER_SUITE_TKIP ||
277*4882a593Smuzhiyun 	     key->cipher == WLAN_CIPHER_SUITE_CCMP) &&
278*4882a593Smuzhiyun 	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
279*4882a593Smuzhiyun 		return -EOPNOTSUPP;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 	/* fall back to sw encryption for unsupported ciphers */
282*4882a593Smuzhiyun 	switch (key->cipher) {
283*4882a593Smuzhiyun 	case WLAN_CIPHER_SUITE_AES_CMAC:
284*4882a593Smuzhiyun 		key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIE;
285*4882a593Smuzhiyun 		break;
286*4882a593Smuzhiyun 	case WLAN_CIPHER_SUITE_WEP40:
287*4882a593Smuzhiyun 	case WLAN_CIPHER_SUITE_WEP104:
288*4882a593Smuzhiyun 	case WLAN_CIPHER_SUITE_TKIP:
289*4882a593Smuzhiyun 	case WLAN_CIPHER_SUITE_CCMP:
290*4882a593Smuzhiyun 	case WLAN_CIPHER_SUITE_CCMP_256:
291*4882a593Smuzhiyun 	case WLAN_CIPHER_SUITE_GCMP:
292*4882a593Smuzhiyun 	case WLAN_CIPHER_SUITE_GCMP_256:
293*4882a593Smuzhiyun 	case WLAN_CIPHER_SUITE_SMS4:
294*4882a593Smuzhiyun 		break;
295*4882a593Smuzhiyun 	default:
296*4882a593Smuzhiyun 		return -EOPNOTSUPP;
297*4882a593Smuzhiyun 	}
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	if (cmd == SET_KEY) {
300*4882a593Smuzhiyun 		key->hw_key_idx = wcid->idx;
301*4882a593Smuzhiyun 		wcid->hw_key_idx = idx;
302*4882a593Smuzhiyun 	} else if (idx == wcid->hw_key_idx) {
303*4882a593Smuzhiyun 		wcid->hw_key_idx = -1;
304*4882a593Smuzhiyun 	}
305*4882a593Smuzhiyun 	mt76_wcid_key_setup(&dev->mt76, wcid,
306*4882a593Smuzhiyun 			    cmd == SET_KEY ? key : NULL);
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	return mt7915_mcu_add_key(dev, vif, msta, key, cmd);
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun 
mt7915_config(struct ieee80211_hw * hw,u32 changed)311*4882a593Smuzhiyun static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
314*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
315*4882a593Smuzhiyun 	bool band = phy != &dev->phy;
316*4882a593Smuzhiyun 	int ret;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
319*4882a593Smuzhiyun 		ieee80211_stop_queues(hw);
320*4882a593Smuzhiyun 		ret = mt7915_set_channel(phy);
321*4882a593Smuzhiyun 		if (ret)
322*4882a593Smuzhiyun 			return ret;
323*4882a593Smuzhiyun 		ieee80211_wake_queues(hw);
324*4882a593Smuzhiyun 	}
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
327*4882a593Smuzhiyun 		ret = mt7915_mcu_set_sku(phy);
328*4882a593Smuzhiyun 		if (ret)
329*4882a593Smuzhiyun 			return ret;
330*4882a593Smuzhiyun 	}
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
335*4882a593Smuzhiyun 		if (!(hw->conf.flags & IEEE80211_CONF_MONITOR))
336*4882a593Smuzhiyun 			phy->rxfilter |= MT_WF_RFCR_DROP_OTHER_UC;
337*4882a593Smuzhiyun 		else
338*4882a593Smuzhiyun 			phy->rxfilter &= ~MT_WF_RFCR_DROP_OTHER_UC;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 		mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
341*4882a593Smuzhiyun 	}
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	return 0;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun static int
mt7915_conf_tx(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u16 queue,const struct ieee80211_tx_queue_params * params)349*4882a593Smuzhiyun mt7915_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
350*4882a593Smuzhiyun 	       const struct ieee80211_tx_queue_params *params)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
353*4882a593Smuzhiyun 	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun 	/* no need to update right away, we'll get BSS_CHANGED_QOS */
356*4882a593Smuzhiyun 	queue = mt7915_lmac_mapping(dev, queue);
357*4882a593Smuzhiyun 	mvif->queue_params[queue] = *params;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun 	return 0;
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun 
mt7915_configure_filter(struct ieee80211_hw * hw,unsigned int changed_flags,unsigned int * total_flags,u64 multicast)362*4882a593Smuzhiyun static void mt7915_configure_filter(struct ieee80211_hw *hw,
363*4882a593Smuzhiyun 				    unsigned int changed_flags,
364*4882a593Smuzhiyun 				    unsigned int *total_flags,
365*4882a593Smuzhiyun 				    u64 multicast)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
368*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
369*4882a593Smuzhiyun 	bool band = phy != &dev->phy;
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun 	u32 ctl_flags = MT_WF_RFCR1_DROP_ACK |
372*4882a593Smuzhiyun 			MT_WF_RFCR1_DROP_BF_POLL |
373*4882a593Smuzhiyun 			MT_WF_RFCR1_DROP_BA |
374*4882a593Smuzhiyun 			MT_WF_RFCR1_DROP_CFEND |
375*4882a593Smuzhiyun 			MT_WF_RFCR1_DROP_CFACK;
376*4882a593Smuzhiyun 	u32 flags = 0;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun #define MT76_FILTER(_flag, _hw) do {					\
379*4882a593Smuzhiyun 		flags |= *total_flags & FIF_##_flag;			\
380*4882a593Smuzhiyun 		phy->rxfilter &= ~(_hw);				\
381*4882a593Smuzhiyun 		phy->rxfilter |= !(flags & FIF_##_flag) * (_hw);	\
382*4882a593Smuzhiyun 	} while (0)
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	phy->rxfilter &= ~(MT_WF_RFCR_DROP_OTHER_BSS |
385*4882a593Smuzhiyun 			   MT_WF_RFCR_DROP_OTHER_BEACON |
386*4882a593Smuzhiyun 			   MT_WF_RFCR_DROP_FRAME_REPORT |
387*4882a593Smuzhiyun 			   MT_WF_RFCR_DROP_PROBEREQ |
388*4882a593Smuzhiyun 			   MT_WF_RFCR_DROP_MCAST_FILTERED |
389*4882a593Smuzhiyun 			   MT_WF_RFCR_DROP_MCAST |
390*4882a593Smuzhiyun 			   MT_WF_RFCR_DROP_BCAST |
391*4882a593Smuzhiyun 			   MT_WF_RFCR_DROP_DUPLICATE |
392*4882a593Smuzhiyun 			   MT_WF_RFCR_DROP_A2_BSSID |
393*4882a593Smuzhiyun 			   MT_WF_RFCR_DROP_UNWANTED_CTL |
394*4882a593Smuzhiyun 			   MT_WF_RFCR_DROP_STBC_MULTI);
395*4882a593Smuzhiyun 
396*4882a593Smuzhiyun 	MT76_FILTER(OTHER_BSS, MT_WF_RFCR_DROP_OTHER_TIM |
397*4882a593Smuzhiyun 			       MT_WF_RFCR_DROP_A3_MAC |
398*4882a593Smuzhiyun 			       MT_WF_RFCR_DROP_A3_BSSID);
399*4882a593Smuzhiyun 
400*4882a593Smuzhiyun 	MT76_FILTER(FCSFAIL, MT_WF_RFCR_DROP_FCSFAIL);
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun 	MT76_FILTER(CONTROL, MT_WF_RFCR_DROP_CTS |
403*4882a593Smuzhiyun 			     MT_WF_RFCR_DROP_RTS |
404*4882a593Smuzhiyun 			     MT_WF_RFCR_DROP_CTL_RSV |
405*4882a593Smuzhiyun 			     MT_WF_RFCR_DROP_NDPA);
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	*total_flags = flags;
408*4882a593Smuzhiyun 	mt76_wr(dev, MT_WF_RFCR(band), phy->rxfilter);
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	if (*total_flags & FIF_CONTROL)
411*4882a593Smuzhiyun 		mt76_clear(dev, MT_WF_RFCR1(band), ctl_flags);
412*4882a593Smuzhiyun 	else
413*4882a593Smuzhiyun 		mt76_set(dev, MT_WF_RFCR1(band), ctl_flags);
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun 
mt7915_bss_info_changed(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * info,u32 changed)416*4882a593Smuzhiyun static void mt7915_bss_info_changed(struct ieee80211_hw *hw,
417*4882a593Smuzhiyun 				    struct ieee80211_vif *vif,
418*4882a593Smuzhiyun 				    struct ieee80211_bss_conf *info,
419*4882a593Smuzhiyun 				    u32 changed)
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
422*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	/*
427*4882a593Smuzhiyun 	 * station mode uses BSSID to map the wlan entry to a peer,
428*4882a593Smuzhiyun 	 * and then peer references bss_info_rfch to set bandwidth cap.
429*4882a593Smuzhiyun 	 */
430*4882a593Smuzhiyun 	if (changed & BSS_CHANGED_BSSID &&
431*4882a593Smuzhiyun 	    vif->type == NL80211_IFTYPE_STATION) {
432*4882a593Smuzhiyun 		bool join = !is_zero_ether_addr(info->bssid);
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 		mt7915_mcu_add_bss_info(phy, vif, join);
435*4882a593Smuzhiyun 		mt7915_mcu_add_sta(dev, vif, NULL, join);
436*4882a593Smuzhiyun 	}
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	if (changed & BSS_CHANGED_ASSOC) {
439*4882a593Smuzhiyun 		mt7915_mcu_add_bss_info(phy, vif, info->assoc);
440*4882a593Smuzhiyun 		mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable);
441*4882a593Smuzhiyun 	}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	if (changed & BSS_CHANGED_ERP_SLOT) {
444*4882a593Smuzhiyun 		int slottime = info->use_short_slot ? 9 : 20;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 		if (slottime != phy->slottime) {
447*4882a593Smuzhiyun 			phy->slottime = slottime;
448*4882a593Smuzhiyun 			mt7915_mac_set_timing(phy);
449*4882a593Smuzhiyun 		}
450*4882a593Smuzhiyun 	}
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun 	if (changed & BSS_CHANGED_BEACON_ENABLED) {
453*4882a593Smuzhiyun 		mt7915_mcu_add_bss_info(phy, vif, info->enable_beacon);
454*4882a593Smuzhiyun 		mt7915_mcu_add_sta(dev, vif, NULL, info->enable_beacon);
455*4882a593Smuzhiyun 	}
456*4882a593Smuzhiyun 
457*4882a593Smuzhiyun 	/* ensure that enable txcmd_mode after bss_info */
458*4882a593Smuzhiyun 	if (changed & (BSS_CHANGED_QOS | BSS_CHANGED_BEACON_ENABLED))
459*4882a593Smuzhiyun 		mt7915_mcu_set_tx(dev, vif);
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	if (changed & BSS_CHANGED_HE_OBSS_PD)
462*4882a593Smuzhiyun 		mt7915_mcu_add_obss_spr(dev, vif, info->he_obss_pd.enable);
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	if (changed & (BSS_CHANGED_BEACON |
465*4882a593Smuzhiyun 		       BSS_CHANGED_BEACON_ENABLED))
466*4882a593Smuzhiyun 		mt7915_mcu_add_beacon(hw, vif, info->enable_beacon);
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun static void
mt7915_channel_switch_beacon(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct cfg80211_chan_def * chandef)472*4882a593Smuzhiyun mt7915_channel_switch_beacon(struct ieee80211_hw *hw,
473*4882a593Smuzhiyun 			     struct ieee80211_vif *vif,
474*4882a593Smuzhiyun 			     struct cfg80211_chan_def *chandef)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
479*4882a593Smuzhiyun 	mt7915_mcu_add_beacon(hw, vif, true);
480*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun 
mt7915_mac_sta_add(struct mt76_dev * mdev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)483*4882a593Smuzhiyun int mt7915_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
484*4882a593Smuzhiyun 		       struct ieee80211_sta *sta)
485*4882a593Smuzhiyun {
486*4882a593Smuzhiyun 	struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
487*4882a593Smuzhiyun 	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
488*4882a593Smuzhiyun 	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
489*4882a593Smuzhiyun 	int ret, idx;
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	idx = mt76_wcid_alloc(dev->mt76.wcid_mask, MT7915_WTBL_STA - 1);
492*4882a593Smuzhiyun 	if (idx < 0)
493*4882a593Smuzhiyun 		return -ENOSPC;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun 	INIT_LIST_HEAD(&msta->rc_list);
496*4882a593Smuzhiyun 	INIT_LIST_HEAD(&msta->stats_list);
497*4882a593Smuzhiyun 	INIT_LIST_HEAD(&msta->poll_list);
498*4882a593Smuzhiyun 	msta->vif = mvif;
499*4882a593Smuzhiyun 	msta->wcid.sta = 1;
500*4882a593Smuzhiyun 	msta->wcid.idx = idx;
501*4882a593Smuzhiyun 	msta->wcid.ext_phy = mvif->band_idx;
502*4882a593Smuzhiyun 	msta->wcid.tx_info |= MT_WCID_TX_INFO_SET;
503*4882a593Smuzhiyun 	msta->stats.jiffies = jiffies;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	mt7915_mac_wtbl_update(dev, idx,
506*4882a593Smuzhiyun 			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	ret = mt7915_mcu_add_sta(dev, vif, sta, true);
509*4882a593Smuzhiyun 	if (ret)
510*4882a593Smuzhiyun 		return ret;
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 	return mt7915_mcu_add_sta_adv(dev, vif, sta, true);
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun 
mt7915_mac_sta_remove(struct mt76_dev * mdev,struct ieee80211_vif * vif,struct ieee80211_sta * sta)515*4882a593Smuzhiyun void mt7915_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
516*4882a593Smuzhiyun 			   struct ieee80211_sta *sta)
517*4882a593Smuzhiyun {
518*4882a593Smuzhiyun 	struct mt7915_dev *dev = container_of(mdev, struct mt7915_dev, mt76);
519*4882a593Smuzhiyun 	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	mt7915_mcu_add_sta_adv(dev, vif, sta, false);
522*4882a593Smuzhiyun 	mt7915_mcu_add_sta(dev, vif, sta, false);
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	mt7915_mac_wtbl_update(dev, msta->wcid.idx,
525*4882a593Smuzhiyun 			       MT_WTBL_UPDATE_ADM_COUNT_CLEAR);
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun 	spin_lock_bh(&dev->sta_poll_lock);
528*4882a593Smuzhiyun 	if (!list_empty(&msta->poll_list))
529*4882a593Smuzhiyun 		list_del_init(&msta->poll_list);
530*4882a593Smuzhiyun 	if (!list_empty(&msta->stats_list))
531*4882a593Smuzhiyun 		list_del_init(&msta->stats_list);
532*4882a593Smuzhiyun 	if (!list_empty(&msta->rc_list))
533*4882a593Smuzhiyun 		list_del_init(&msta->rc_list);
534*4882a593Smuzhiyun 	spin_unlock_bh(&dev->sta_poll_lock);
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun 
mt7915_tx(struct ieee80211_hw * hw,struct ieee80211_tx_control * control,struct sk_buff * skb)537*4882a593Smuzhiyun static void mt7915_tx(struct ieee80211_hw *hw,
538*4882a593Smuzhiyun 		      struct ieee80211_tx_control *control,
539*4882a593Smuzhiyun 		      struct sk_buff *skb)
540*4882a593Smuzhiyun {
541*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
542*4882a593Smuzhiyun 	struct mt76_phy *mphy = hw->priv;
543*4882a593Smuzhiyun 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
544*4882a593Smuzhiyun 	struct ieee80211_vif *vif = info->control.vif;
545*4882a593Smuzhiyun 	struct mt76_wcid *wcid = &dev->mt76.global_wcid;
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	if (control->sta) {
548*4882a593Smuzhiyun 		struct mt7915_sta *sta;
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun 		sta = (struct mt7915_sta *)control->sta->drv_priv;
551*4882a593Smuzhiyun 		wcid = &sta->wcid;
552*4882a593Smuzhiyun 	}
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun 	if (vif && !control->sta) {
555*4882a593Smuzhiyun 		struct mt7915_vif *mvif;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 		mvif = (struct mt7915_vif *)vif->drv_priv;
558*4882a593Smuzhiyun 		wcid = &mvif->sta.wcid;
559*4882a593Smuzhiyun 	}
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	mt76_tx(mphy, control->sta, wcid, skb);
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun 
mt7915_set_rts_threshold(struct ieee80211_hw * hw,u32 val)564*4882a593Smuzhiyun static int mt7915_set_rts_threshold(struct ieee80211_hw *hw, u32 val)
565*4882a593Smuzhiyun {
566*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
567*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
570*4882a593Smuzhiyun 	mt7915_mcu_set_rts_thresh(phy, val);
571*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	return 0;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun static int
mt7915_ampdu_action(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_ampdu_params * params)577*4882a593Smuzhiyun mt7915_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
578*4882a593Smuzhiyun 		    struct ieee80211_ampdu_params *params)
579*4882a593Smuzhiyun {
580*4882a593Smuzhiyun 	enum ieee80211_ampdu_mlme_action action = params->action;
581*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
582*4882a593Smuzhiyun 	struct ieee80211_sta *sta = params->sta;
583*4882a593Smuzhiyun 	struct ieee80211_txq *txq = sta->txq[params->tid];
584*4882a593Smuzhiyun 	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
585*4882a593Smuzhiyun 	u16 tid = params->tid;
586*4882a593Smuzhiyun 	u16 ssn = params->ssn;
587*4882a593Smuzhiyun 	struct mt76_txq *mtxq;
588*4882a593Smuzhiyun 	int ret = 0;
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun 	if (!txq)
591*4882a593Smuzhiyun 		return -EINVAL;
592*4882a593Smuzhiyun 
593*4882a593Smuzhiyun 	mtxq = (struct mt76_txq *)txq->drv_priv;
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
596*4882a593Smuzhiyun 	switch (action) {
597*4882a593Smuzhiyun 	case IEEE80211_AMPDU_RX_START:
598*4882a593Smuzhiyun 		mt76_rx_aggr_start(&dev->mt76, &msta->wcid, tid, ssn,
599*4882a593Smuzhiyun 				   params->buf_size);
600*4882a593Smuzhiyun 		mt7915_mcu_add_rx_ba(dev, params, true);
601*4882a593Smuzhiyun 		break;
602*4882a593Smuzhiyun 	case IEEE80211_AMPDU_RX_STOP:
603*4882a593Smuzhiyun 		mt76_rx_aggr_stop(&dev->mt76, &msta->wcid, tid);
604*4882a593Smuzhiyun 		mt7915_mcu_add_rx_ba(dev, params, false);
605*4882a593Smuzhiyun 		break;
606*4882a593Smuzhiyun 	case IEEE80211_AMPDU_TX_OPERATIONAL:
607*4882a593Smuzhiyun 		mtxq->aggr = true;
608*4882a593Smuzhiyun 		mtxq->send_bar = false;
609*4882a593Smuzhiyun 		mt7915_mcu_add_tx_ba(dev, params, true);
610*4882a593Smuzhiyun 		break;
611*4882a593Smuzhiyun 	case IEEE80211_AMPDU_TX_STOP_FLUSH:
612*4882a593Smuzhiyun 	case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
613*4882a593Smuzhiyun 		mtxq->aggr = false;
614*4882a593Smuzhiyun 		clear_bit(tid, &msta->ampdu_state);
615*4882a593Smuzhiyun 		mt7915_mcu_add_tx_ba(dev, params, false);
616*4882a593Smuzhiyun 		break;
617*4882a593Smuzhiyun 	case IEEE80211_AMPDU_TX_START:
618*4882a593Smuzhiyun 		set_bit(tid, &msta->ampdu_state);
619*4882a593Smuzhiyun 		ret = IEEE80211_AMPDU_TX_START_IMMEDIATE;
620*4882a593Smuzhiyun 		break;
621*4882a593Smuzhiyun 	case IEEE80211_AMPDU_TX_STOP_CONT:
622*4882a593Smuzhiyun 		mtxq->aggr = false;
623*4882a593Smuzhiyun 		clear_bit(tid, &msta->ampdu_state);
624*4882a593Smuzhiyun 		mt7915_mcu_add_tx_ba(dev, params, false);
625*4882a593Smuzhiyun 		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
626*4882a593Smuzhiyun 		break;
627*4882a593Smuzhiyun 	}
628*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun 	return ret;
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun static int
mt7915_sta_add(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta)634*4882a593Smuzhiyun mt7915_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
635*4882a593Smuzhiyun 	       struct ieee80211_sta *sta)
636*4882a593Smuzhiyun {
637*4882a593Smuzhiyun 	return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NOTEXIST,
638*4882a593Smuzhiyun 			      IEEE80211_STA_NONE);
639*4882a593Smuzhiyun }
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun static int
mt7915_sta_remove(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta)642*4882a593Smuzhiyun mt7915_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
643*4882a593Smuzhiyun 		  struct ieee80211_sta *sta)
644*4882a593Smuzhiyun {
645*4882a593Smuzhiyun 	return mt76_sta_state(hw, vif, sta, IEEE80211_STA_NONE,
646*4882a593Smuzhiyun 			      IEEE80211_STA_NOTEXIST);
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun static int
mt7915_get_stats(struct ieee80211_hw * hw,struct ieee80211_low_level_stats * stats)650*4882a593Smuzhiyun mt7915_get_stats(struct ieee80211_hw *hw,
651*4882a593Smuzhiyun 		 struct ieee80211_low_level_stats *stats)
652*4882a593Smuzhiyun {
653*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
654*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
655*4882a593Smuzhiyun 	struct mib_stats *mib = &phy->mib;
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
658*4882a593Smuzhiyun 	stats->dot11RTSSuccessCount = mib->rts_cnt;
659*4882a593Smuzhiyun 	stats->dot11RTSFailureCount = mib->rts_retries_cnt;
660*4882a593Smuzhiyun 	stats->dot11FCSErrorCount = mib->fcs_err_cnt;
661*4882a593Smuzhiyun 	stats->dot11ACKFailureCount = mib->ack_fail_cnt;
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun 	memset(mib, 0, sizeof(*mib));
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun 	return 0;
668*4882a593Smuzhiyun }
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun static u64
mt7915_get_tsf(struct ieee80211_hw * hw,struct ieee80211_vif * vif)671*4882a593Smuzhiyun mt7915_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
672*4882a593Smuzhiyun {
673*4882a593Smuzhiyun 	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
674*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
675*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
676*4882a593Smuzhiyun 	bool band = phy != &dev->phy;
677*4882a593Smuzhiyun 	union {
678*4882a593Smuzhiyun 		u64 t64;
679*4882a593Smuzhiyun 		u32 t32[2];
680*4882a593Smuzhiyun 	} tsf;
681*4882a593Smuzhiyun 	u16 n;
682*4882a593Smuzhiyun 
683*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	n = mvif->omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->omac_idx;
686*4882a593Smuzhiyun 	/* TSF software read */
687*4882a593Smuzhiyun 	mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_MODE);
688*4882a593Smuzhiyun 	tsf.t32[0] = mt76_rr(dev, MT_LPON_UTTR0(band));
689*4882a593Smuzhiyun 	tsf.t32[1] = mt76_rr(dev, MT_LPON_UTTR1(band));
690*4882a593Smuzhiyun 
691*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	return tsf.t64;
694*4882a593Smuzhiyun }
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun static void
mt7915_set_tsf(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u64 timestamp)697*4882a593Smuzhiyun mt7915_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
698*4882a593Smuzhiyun 	       u64 timestamp)
699*4882a593Smuzhiyun {
700*4882a593Smuzhiyun 	struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
701*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
702*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
703*4882a593Smuzhiyun 	bool band = phy != &dev->phy;
704*4882a593Smuzhiyun 	union {
705*4882a593Smuzhiyun 		u64 t64;
706*4882a593Smuzhiyun 		u32 t32[2];
707*4882a593Smuzhiyun 	} tsf = { .t64 = timestamp, };
708*4882a593Smuzhiyun 	u16 n;
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun 	n = mvif->omac_idx > HW_BSSID_MAX ? HW_BSSID_0 : mvif->omac_idx;
713*4882a593Smuzhiyun 	mt76_wr(dev, MT_LPON_UTTR0(band), tsf.t32[0]);
714*4882a593Smuzhiyun 	mt76_wr(dev, MT_LPON_UTTR1(band), tsf.t32[1]);
715*4882a593Smuzhiyun 	/* TSF software overwrite */
716*4882a593Smuzhiyun 	mt76_set(dev, MT_LPON_TCR(band, n), MT_LPON_TCR_SW_WRITE);
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
719*4882a593Smuzhiyun }
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun static void
mt7915_set_coverage_class(struct ieee80211_hw * hw,s16 coverage_class)722*4882a593Smuzhiyun mt7915_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class)
723*4882a593Smuzhiyun {
724*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
725*4882a593Smuzhiyun 	struct mt7915_dev *dev = phy->dev;
726*4882a593Smuzhiyun 
727*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
728*4882a593Smuzhiyun 	phy->coverage_class = max_t(s16, coverage_class, 0);
729*4882a593Smuzhiyun 	mt7915_mac_set_timing(phy);
730*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
731*4882a593Smuzhiyun }
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun static int
mt7915_set_antenna(struct ieee80211_hw * hw,u32 tx_ant,u32 rx_ant)734*4882a593Smuzhiyun mt7915_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
735*4882a593Smuzhiyun {
736*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
737*4882a593Smuzhiyun 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
738*4882a593Smuzhiyun 	int max_nss = hweight8(hw->wiphy->available_antennas_tx);
739*4882a593Smuzhiyun 	bool ext_phy = phy != &dev->phy;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun 	if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss)
742*4882a593Smuzhiyun 		return -EINVAL;
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun 	if ((BIT(hweight8(tx_ant)) - 1) != tx_ant)
745*4882a593Smuzhiyun 		tx_ant = BIT(ffs(tx_ant) - 1) - 1;
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 	mutex_lock(&dev->mt76.mutex);
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun 	phy->mt76->antenna_mask = tx_ant;
750*4882a593Smuzhiyun 
751*4882a593Smuzhiyun 	if (ext_phy) {
752*4882a593Smuzhiyun 		if (dev->chainmask == 0xf)
753*4882a593Smuzhiyun 			tx_ant <<= 2;
754*4882a593Smuzhiyun 		else
755*4882a593Smuzhiyun 			tx_ant <<= 1;
756*4882a593Smuzhiyun 	}
757*4882a593Smuzhiyun 	phy->chainmask = tx_ant;
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	mt76_set_stream_caps(phy->mt76, true);
760*4882a593Smuzhiyun 	mt7915_set_stream_vht_txbf_caps(phy);
761*4882a593Smuzhiyun 	mt7915_set_stream_he_caps(phy);
762*4882a593Smuzhiyun 
763*4882a593Smuzhiyun 	mutex_unlock(&dev->mt76.mutex);
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	return 0;
766*4882a593Smuzhiyun }
767*4882a593Smuzhiyun 
mt7915_sta_statistics(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct station_info * sinfo)768*4882a593Smuzhiyun static void mt7915_sta_statistics(struct ieee80211_hw *hw,
769*4882a593Smuzhiyun 				  struct ieee80211_vif *vif,
770*4882a593Smuzhiyun 				  struct ieee80211_sta *sta,
771*4882a593Smuzhiyun 				  struct station_info *sinfo)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun 	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
774*4882a593Smuzhiyun 	struct mt7915_sta_stats *stats = &msta->stats;
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	if (!stats->tx_rate.legacy && !stats->tx_rate.flags)
777*4882a593Smuzhiyun 		return;
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun 	if (stats->tx_rate.legacy) {
780*4882a593Smuzhiyun 		sinfo->txrate.legacy = stats->tx_rate.legacy;
781*4882a593Smuzhiyun 	} else {
782*4882a593Smuzhiyun 		sinfo->txrate.mcs = stats->tx_rate.mcs;
783*4882a593Smuzhiyun 		sinfo->txrate.nss = stats->tx_rate.nss;
784*4882a593Smuzhiyun 		sinfo->txrate.bw = stats->tx_rate.bw;
785*4882a593Smuzhiyun 		sinfo->txrate.he_gi = stats->tx_rate.he_gi;
786*4882a593Smuzhiyun 		sinfo->txrate.he_dcm = stats->tx_rate.he_dcm;
787*4882a593Smuzhiyun 		sinfo->txrate.he_ru_alloc = stats->tx_rate.he_ru_alloc;
788*4882a593Smuzhiyun 	}
789*4882a593Smuzhiyun 	sinfo->txrate.flags = stats->tx_rate.flags;
790*4882a593Smuzhiyun 	sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
791*4882a593Smuzhiyun }
792*4882a593Smuzhiyun 
793*4882a593Smuzhiyun static void
mt7915_sta_rc_update(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta,u32 changed)794*4882a593Smuzhiyun mt7915_sta_rc_update(struct ieee80211_hw *hw,
795*4882a593Smuzhiyun 		     struct ieee80211_vif *vif,
796*4882a593Smuzhiyun 		     struct ieee80211_sta *sta,
797*4882a593Smuzhiyun 		     u32 changed)
798*4882a593Smuzhiyun {
799*4882a593Smuzhiyun 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
800*4882a593Smuzhiyun 	struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv;
801*4882a593Smuzhiyun 
802*4882a593Smuzhiyun 	spin_lock_bh(&dev->sta_poll_lock);
803*4882a593Smuzhiyun 	msta->stats.changed |= changed;
804*4882a593Smuzhiyun 	if (list_empty(&msta->rc_list))
805*4882a593Smuzhiyun 		list_add_tail(&msta->rc_list, &dev->sta_rc_list);
806*4882a593Smuzhiyun 	spin_unlock_bh(&dev->sta_poll_lock);
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun 	ieee80211_queue_work(hw, &dev->rc_work);
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun 
811*4882a593Smuzhiyun const struct ieee80211_ops mt7915_ops = {
812*4882a593Smuzhiyun 	.tx = mt7915_tx,
813*4882a593Smuzhiyun 	.start = mt7915_start,
814*4882a593Smuzhiyun 	.stop = mt7915_stop,
815*4882a593Smuzhiyun 	.add_interface = mt7915_add_interface,
816*4882a593Smuzhiyun 	.remove_interface = mt7915_remove_interface,
817*4882a593Smuzhiyun 	.config = mt7915_config,
818*4882a593Smuzhiyun 	.conf_tx = mt7915_conf_tx,
819*4882a593Smuzhiyun 	.configure_filter = mt7915_configure_filter,
820*4882a593Smuzhiyun 	.bss_info_changed = mt7915_bss_info_changed,
821*4882a593Smuzhiyun 	.sta_add = mt7915_sta_add,
822*4882a593Smuzhiyun 	.sta_remove = mt7915_sta_remove,
823*4882a593Smuzhiyun 	.sta_pre_rcu_remove = mt76_sta_pre_rcu_remove,
824*4882a593Smuzhiyun 	.sta_rc_update = mt7915_sta_rc_update,
825*4882a593Smuzhiyun 	.set_key = mt7915_set_key,
826*4882a593Smuzhiyun 	.ampdu_action = mt7915_ampdu_action,
827*4882a593Smuzhiyun 	.set_rts_threshold = mt7915_set_rts_threshold,
828*4882a593Smuzhiyun 	.wake_tx_queue = mt76_wake_tx_queue,
829*4882a593Smuzhiyun 	.sw_scan_start = mt76_sw_scan,
830*4882a593Smuzhiyun 	.sw_scan_complete = mt76_sw_scan_complete,
831*4882a593Smuzhiyun 	.release_buffered_frames = mt76_release_buffered_frames,
832*4882a593Smuzhiyun 	.get_txpower = mt76_get_txpower,
833*4882a593Smuzhiyun 	.channel_switch_beacon = mt7915_channel_switch_beacon,
834*4882a593Smuzhiyun 	.get_stats = mt7915_get_stats,
835*4882a593Smuzhiyun 	.get_tsf = mt7915_get_tsf,
836*4882a593Smuzhiyun 	.set_tsf = mt7915_set_tsf,
837*4882a593Smuzhiyun 	.get_survey = mt76_get_survey,
838*4882a593Smuzhiyun 	.get_antenna = mt76_get_antenna,
839*4882a593Smuzhiyun 	.set_antenna = mt7915_set_antenna,
840*4882a593Smuzhiyun 	.set_coverage_class = mt7915_set_coverage_class,
841*4882a593Smuzhiyun 	.sta_statistics = mt7915_sta_statistics,
842*4882a593Smuzhiyun #ifdef CONFIG_MAC80211_DEBUGFS
843*4882a593Smuzhiyun 	.sta_add_debugfs = mt7915_sta_add_debugfs,
844*4882a593Smuzhiyun #endif
845*4882a593Smuzhiyun };
846