1cbb3ec25SBjoern A. Zeeb // SPDX-License-Identifier: ISC
2cbb3ec25SBjoern A. Zeeb /* Copyright (C) 2023 MediaTek Inc. */
3cbb3ec25SBjoern A. Zeeb 
4cbb3ec25SBjoern A. Zeeb #include <linux/module.h>
5cbb3ec25SBjoern A. Zeeb #if defined(__FreeBSD__)
6cbb3ec25SBjoern A. Zeeb #include <linux/delay.h>
7cbb3ec25SBjoern A. Zeeb #endif
8cbb3ec25SBjoern A. Zeeb 
9cbb3ec25SBjoern A. Zeeb #include "mt792x.h"
10cbb3ec25SBjoern A. Zeeb #include "mt792x_regs.h"
11cbb3ec25SBjoern A. Zeeb 
mt792x_mac_work(struct work_struct * work)12cbb3ec25SBjoern A. Zeeb void mt792x_mac_work(struct work_struct *work)
13cbb3ec25SBjoern A. Zeeb {
14cbb3ec25SBjoern A. Zeeb 	struct mt792x_phy *phy;
15cbb3ec25SBjoern A. Zeeb 	struct mt76_phy *mphy;
16cbb3ec25SBjoern A. Zeeb 
17cbb3ec25SBjoern A. Zeeb 	mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
18cbb3ec25SBjoern A. Zeeb 					       mac_work.work);
19cbb3ec25SBjoern A. Zeeb 	phy = mphy->priv;
20cbb3ec25SBjoern A. Zeeb 
21cbb3ec25SBjoern A. Zeeb 	mt792x_mutex_acquire(phy->dev);
22cbb3ec25SBjoern A. Zeeb 
23cbb3ec25SBjoern A. Zeeb 	mt76_update_survey(mphy);
24cbb3ec25SBjoern A. Zeeb 	if (++mphy->mac_work_count == 2) {
25cbb3ec25SBjoern A. Zeeb 		mphy->mac_work_count = 0;
26cbb3ec25SBjoern A. Zeeb 
27cbb3ec25SBjoern A. Zeeb 		mt792x_mac_update_mib_stats(phy);
28cbb3ec25SBjoern A. Zeeb 	}
29cbb3ec25SBjoern A. Zeeb 
30cbb3ec25SBjoern A. Zeeb 	mt792x_mutex_release(phy->dev);
31cbb3ec25SBjoern A. Zeeb 
32cbb3ec25SBjoern A. Zeeb 	mt76_tx_status_check(mphy->dev, false);
33cbb3ec25SBjoern A. Zeeb 	ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work,
34cbb3ec25SBjoern A. Zeeb 				     MT792x_WATCHDOG_TIME);
35cbb3ec25SBjoern A. Zeeb }
36cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_mac_work);
37cbb3ec25SBjoern A. Zeeb 
mt792x_mac_set_timeing(struct mt792x_phy * phy)38cbb3ec25SBjoern A. Zeeb void mt792x_mac_set_timeing(struct mt792x_phy *phy)
39cbb3ec25SBjoern A. Zeeb {
40cbb3ec25SBjoern A. Zeeb 	s16 coverage_class = phy->coverage_class;
41cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = phy->dev;
42cbb3ec25SBjoern A. Zeeb 	u32 val, reg_offset;
43cbb3ec25SBjoern A. Zeeb 	u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
44cbb3ec25SBjoern A. Zeeb 		  FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
45cbb3ec25SBjoern A. Zeeb 	u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
46cbb3ec25SBjoern A. Zeeb 		   FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
47cbb3ec25SBjoern A. Zeeb 	bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ;
48cbb3ec25SBjoern A. Zeeb 	int sifs = is_2ghz ? 10 : 16, offset;
49cbb3ec25SBjoern A. Zeeb 
50cbb3ec25SBjoern A. Zeeb 	if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
51cbb3ec25SBjoern A. Zeeb 		return;
52cbb3ec25SBjoern A. Zeeb 
53cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_ARB_SCR(0),
54cbb3ec25SBjoern A. Zeeb 		 MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
55cbb3ec25SBjoern A. Zeeb 	udelay(1);
56cbb3ec25SBjoern A. Zeeb 
57cbb3ec25SBjoern A. Zeeb 	offset = 3 * coverage_class;
58cbb3ec25SBjoern A. Zeeb 	reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
59cbb3ec25SBjoern A. Zeeb 		     FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
60cbb3ec25SBjoern A. Zeeb 
61cbb3ec25SBjoern A. Zeeb 	mt76_wr(dev, MT_TMAC_CDTR(0), cck + reg_offset);
62cbb3ec25SBjoern A. Zeeb 	mt76_wr(dev, MT_TMAC_ODTR(0), ofdm + reg_offset);
63cbb3ec25SBjoern A. Zeeb 	mt76_wr(dev, MT_TMAC_ICR0(0),
64cbb3ec25SBjoern A. Zeeb 		FIELD_PREP(MT_IFS_EIFS, 360) |
65cbb3ec25SBjoern A. Zeeb 		FIELD_PREP(MT_IFS_RIFS, 2) |
66cbb3ec25SBjoern A. Zeeb 		FIELD_PREP(MT_IFS_SIFS, sifs) |
67cbb3ec25SBjoern A. Zeeb 		FIELD_PREP(MT_IFS_SLOT, phy->slottime));
68cbb3ec25SBjoern A. Zeeb 
69cbb3ec25SBjoern A. Zeeb 	if (phy->slottime < 20 || !is_2ghz)
70cbb3ec25SBjoern A. Zeeb 		val = MT792x_CFEND_RATE_DEFAULT;
71cbb3ec25SBjoern A. Zeeb 	else
72cbb3ec25SBjoern A. Zeeb 		val = MT792x_CFEND_RATE_11B;
73cbb3ec25SBjoern A. Zeeb 
74cbb3ec25SBjoern A. Zeeb 	mt76_rmw_field(dev, MT_AGG_ACR0(0), MT_AGG_ACR_CFEND_RATE, val);
75cbb3ec25SBjoern A. Zeeb 	mt76_clear(dev, MT_ARB_SCR(0),
76cbb3ec25SBjoern A. Zeeb 		   MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
77cbb3ec25SBjoern A. Zeeb }
78cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_mac_set_timeing);
79cbb3ec25SBjoern A. Zeeb 
mt792x_mac_update_mib_stats(struct mt792x_phy * phy)80cbb3ec25SBjoern A. Zeeb void mt792x_mac_update_mib_stats(struct mt792x_phy *phy)
81cbb3ec25SBjoern A. Zeeb {
82cbb3ec25SBjoern A. Zeeb 	struct mt76_mib_stats *mib = &phy->mib;
83cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = phy->dev;
84cbb3ec25SBjoern A. Zeeb 	int i, aggr0 = 0, aggr1;
85cbb3ec25SBjoern A. Zeeb 	u32 val;
86cbb3ec25SBjoern A. Zeeb 
87cbb3ec25SBjoern A. Zeeb 	mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(0),
88cbb3ec25SBjoern A. Zeeb 					   MT_MIB_SDR3_FCS_ERR_MASK);
89cbb3ec25SBjoern A. Zeeb 	mib->ack_fail_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR3(0),
90cbb3ec25SBjoern A. Zeeb 					    MT_MIB_ACK_FAIL_COUNT_MASK);
91cbb3ec25SBjoern A. Zeeb 	mib->ba_miss_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR2(0),
92cbb3ec25SBjoern A. Zeeb 					   MT_MIB_BA_FAIL_COUNT_MASK);
93cbb3ec25SBjoern A. Zeeb 	mib->rts_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR0(0),
94cbb3ec25SBjoern A. Zeeb 				       MT_MIB_RTS_COUNT_MASK);
95cbb3ec25SBjoern A. Zeeb 	mib->rts_retries_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR1(0),
96cbb3ec25SBjoern A. Zeeb 					       MT_MIB_RTS_FAIL_COUNT_MASK);
97cbb3ec25SBjoern A. Zeeb 
98cbb3ec25SBjoern A. Zeeb 	mib->tx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR12(0));
99cbb3ec25SBjoern A. Zeeb 	mib->tx_mpdu_attempts_cnt += mt76_rr(dev, MT_MIB_SDR14(0));
100cbb3ec25SBjoern A. Zeeb 	mib->tx_mpdu_success_cnt += mt76_rr(dev, MT_MIB_SDR15(0));
101cbb3ec25SBjoern A. Zeeb 
102cbb3ec25SBjoern A. Zeeb 	val = mt76_rr(dev, MT_MIB_SDR32(0));
103cbb3ec25SBjoern A. Zeeb 	mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR9_EBF_CNT_MASK, val);
104cbb3ec25SBjoern A. Zeeb 	mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR9_IBF_CNT_MASK, val);
105cbb3ec25SBjoern A. Zeeb 
106cbb3ec25SBjoern A. Zeeb 	val = mt76_rr(dev, MT_ETBF_TX_APP_CNT(0));
107cbb3ec25SBjoern A. Zeeb 	mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, val);
108cbb3ec25SBjoern A. Zeeb 	mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, val);
109cbb3ec25SBjoern A. Zeeb 
110cbb3ec25SBjoern A. Zeeb 	val = mt76_rr(dev, MT_ETBF_RX_FB_CNT(0));
111cbb3ec25SBjoern A. Zeeb 	mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, val);
112cbb3ec25SBjoern A. Zeeb 	mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, val);
113cbb3ec25SBjoern A. Zeeb 	mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, val);
114cbb3ec25SBjoern A. Zeeb 	mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, val);
115cbb3ec25SBjoern A. Zeeb 
116cbb3ec25SBjoern A. Zeeb 	mib->rx_mpdu_cnt += mt76_rr(dev, MT_MIB_SDR5(0));
117cbb3ec25SBjoern A. Zeeb 	mib->rx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR22(0));
118cbb3ec25SBjoern A. Zeeb 	mib->rx_ampdu_bytes_cnt += mt76_rr(dev, MT_MIB_SDR23(0));
119cbb3ec25SBjoern A. Zeeb 	mib->rx_ba_cnt += mt76_rr(dev, MT_MIB_SDR31(0));
120cbb3ec25SBjoern A. Zeeb 
121cbb3ec25SBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
122cbb3ec25SBjoern A. Zeeb 		val = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
123cbb3ec25SBjoern A. Zeeb 		mib->tx_amsdu[i] += val;
124cbb3ec25SBjoern A. Zeeb 		mib->tx_amsdu_cnt += val;
125cbb3ec25SBjoern A. Zeeb 	}
126cbb3ec25SBjoern A. Zeeb 
127cbb3ec25SBjoern A. Zeeb 	for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) {
128cbb3ec25SBjoern A. Zeeb 		u32 val2;
129cbb3ec25SBjoern A. Zeeb 
130cbb3ec25SBjoern A. Zeeb 		val = mt76_rr(dev, MT_TX_AGG_CNT(0, i));
131cbb3ec25SBjoern A. Zeeb 		val2 = mt76_rr(dev, MT_TX_AGG_CNT2(0, i));
132cbb3ec25SBjoern A. Zeeb 
133cbb3ec25SBjoern A. Zeeb 		phy->mt76->aggr_stats[aggr0++] += val & 0xffff;
134cbb3ec25SBjoern A. Zeeb 		phy->mt76->aggr_stats[aggr0++] += val >> 16;
135cbb3ec25SBjoern A. Zeeb 		phy->mt76->aggr_stats[aggr1++] += val2 & 0xffff;
136cbb3ec25SBjoern A. Zeeb 		phy->mt76->aggr_stats[aggr1++] += val2 >> 16;
137cbb3ec25SBjoern A. Zeeb 	}
138cbb3ec25SBjoern A. Zeeb }
139cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_mac_update_mib_stats);
140cbb3ec25SBjoern A. Zeeb 
mt792x_rx_get_wcid(struct mt792x_dev * dev,u16 idx,bool unicast)141cbb3ec25SBjoern A. Zeeb struct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx,
142cbb3ec25SBjoern A. Zeeb 				     bool unicast)
143cbb3ec25SBjoern A. Zeeb {
144cbb3ec25SBjoern A. Zeeb 	struct mt792x_sta *sta;
145cbb3ec25SBjoern A. Zeeb 	struct mt76_wcid *wcid;
146cbb3ec25SBjoern A. Zeeb 
147cbb3ec25SBjoern A. Zeeb 	if (idx >= ARRAY_SIZE(dev->mt76.wcid))
148cbb3ec25SBjoern A. Zeeb 		return NULL;
149cbb3ec25SBjoern A. Zeeb 
150cbb3ec25SBjoern A. Zeeb 	wcid = rcu_dereference(dev->mt76.wcid[idx]);
151cbb3ec25SBjoern A. Zeeb 	if (unicast || !wcid)
152cbb3ec25SBjoern A. Zeeb 		return wcid;
153cbb3ec25SBjoern A. Zeeb 
154cbb3ec25SBjoern A. Zeeb 	if (!wcid->sta)
155cbb3ec25SBjoern A. Zeeb 		return NULL;
156cbb3ec25SBjoern A. Zeeb 
157cbb3ec25SBjoern A. Zeeb 	sta = container_of(wcid, struct mt792x_sta, wcid);
158cbb3ec25SBjoern A. Zeeb 	if (!sta->vif)
159cbb3ec25SBjoern A. Zeeb 		return NULL;
160cbb3ec25SBjoern A. Zeeb 
161cbb3ec25SBjoern A. Zeeb 	return &sta->vif->sta.wcid;
162cbb3ec25SBjoern A. Zeeb }
163cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_rx_get_wcid);
164cbb3ec25SBjoern A. Zeeb 
165cbb3ec25SBjoern A. Zeeb static void
mt792x_mac_rssi_iter(void * priv,u8 * mac,struct ieee80211_vif * vif)166cbb3ec25SBjoern A. Zeeb mt792x_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
167cbb3ec25SBjoern A. Zeeb {
168cbb3ec25SBjoern A. Zeeb 	struct sk_buff *skb = priv;
169cbb3ec25SBjoern A. Zeeb 	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
170cbb3ec25SBjoern A. Zeeb 	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
171cbb3ec25SBjoern A. Zeeb 	struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
172cbb3ec25SBjoern A. Zeeb 
173cbb3ec25SBjoern A. Zeeb 	if (status->signal > 0)
174cbb3ec25SBjoern A. Zeeb 		return;
175cbb3ec25SBjoern A. Zeeb 
176cbb3ec25SBjoern A. Zeeb 	if (!ether_addr_equal(vif->addr, hdr->addr1))
177cbb3ec25SBjoern A. Zeeb 		return;
178cbb3ec25SBjoern A. Zeeb 
179cbb3ec25SBjoern A. Zeeb 	ewma_rssi_add(&mvif->rssi, -status->signal);
180cbb3ec25SBjoern A. Zeeb }
181cbb3ec25SBjoern A. Zeeb 
mt792x_mac_assoc_rssi(struct mt792x_dev * dev,struct sk_buff * skb)182cbb3ec25SBjoern A. Zeeb void mt792x_mac_assoc_rssi(struct mt792x_dev *dev, struct sk_buff *skb)
183cbb3ec25SBjoern A. Zeeb {
184cbb3ec25SBjoern A. Zeeb 	struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
185cbb3ec25SBjoern A. Zeeb 
186cbb3ec25SBjoern A. Zeeb 	if (!ieee80211_is_assoc_resp(hdr->frame_control) &&
187cbb3ec25SBjoern A. Zeeb 	    !ieee80211_is_auth(hdr->frame_control))
188cbb3ec25SBjoern A. Zeeb 		return;
189cbb3ec25SBjoern A. Zeeb 
190cbb3ec25SBjoern A. Zeeb 	ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
191cbb3ec25SBjoern A. Zeeb 		IEEE80211_IFACE_ITER_RESUME_ALL,
192cbb3ec25SBjoern A. Zeeb 		mt792x_mac_rssi_iter, skb);
193cbb3ec25SBjoern A. Zeeb }
194cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_mac_assoc_rssi);
195cbb3ec25SBjoern A. Zeeb 
mt792x_mac_reset_counters(struct mt792x_phy * phy)196cbb3ec25SBjoern A. Zeeb void mt792x_mac_reset_counters(struct mt792x_phy *phy)
197cbb3ec25SBjoern A. Zeeb {
198cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = phy->dev;
199cbb3ec25SBjoern A. Zeeb 	int i;
200cbb3ec25SBjoern A. Zeeb 
201cbb3ec25SBjoern A. Zeeb 	for (i = 0; i < 4; i++) {
202cbb3ec25SBjoern A. Zeeb 		mt76_rr(dev, MT_TX_AGG_CNT(0, i));
203cbb3ec25SBjoern A. Zeeb 		mt76_rr(dev, MT_TX_AGG_CNT2(0, i));
204cbb3ec25SBjoern A. Zeeb 	}
205cbb3ec25SBjoern A. Zeeb 
206cbb3ec25SBjoern A. Zeeb 	dev->mt76.phy.survey_time = ktime_get_boottime();
207cbb3ec25SBjoern A. Zeeb 	memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats));
208cbb3ec25SBjoern A. Zeeb 
209cbb3ec25SBjoern A. Zeeb 	/* reset airtime counters */
210cbb3ec25SBjoern A. Zeeb 	mt76_rr(dev, MT_MIB_SDR9(0));
211cbb3ec25SBjoern A. Zeeb 	mt76_rr(dev, MT_MIB_SDR36(0));
212cbb3ec25SBjoern A. Zeeb 	mt76_rr(dev, MT_MIB_SDR37(0));
213cbb3ec25SBjoern A. Zeeb 
214cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
215cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
216cbb3ec25SBjoern A. Zeeb }
217cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_mac_reset_counters);
218cbb3ec25SBjoern A. Zeeb 
219cbb3ec25SBjoern A. Zeeb static u8
mt792x_phy_get_nf(struct mt792x_phy * phy,int idx)220cbb3ec25SBjoern A. Zeeb mt792x_phy_get_nf(struct mt792x_phy *phy, int idx)
221cbb3ec25SBjoern A. Zeeb {
222cbb3ec25SBjoern A. Zeeb 	return 0;
223cbb3ec25SBjoern A. Zeeb }
224cbb3ec25SBjoern A. Zeeb 
225cbb3ec25SBjoern A. Zeeb static void
mt792x_phy_update_channel(struct mt76_phy * mphy,int idx)226cbb3ec25SBjoern A. Zeeb mt792x_phy_update_channel(struct mt76_phy *mphy, int idx)
227cbb3ec25SBjoern A. Zeeb {
228cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76);
229cbb3ec25SBjoern A. Zeeb 	struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv;
230cbb3ec25SBjoern A. Zeeb 	struct mt76_channel_state *state;
231cbb3ec25SBjoern A. Zeeb 	u64 busy_time, tx_time, rx_time, obss_time;
232cbb3ec25SBjoern A. Zeeb 	int nf;
233cbb3ec25SBjoern A. Zeeb 
234cbb3ec25SBjoern A. Zeeb 	busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx),
235cbb3ec25SBjoern A. Zeeb 				   MT_MIB_SDR9_BUSY_MASK);
236cbb3ec25SBjoern A. Zeeb 	tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx),
237cbb3ec25SBjoern A. Zeeb 				 MT_MIB_SDR36_TXTIME_MASK);
238cbb3ec25SBjoern A. Zeeb 	rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx),
239cbb3ec25SBjoern A. Zeeb 				 MT_MIB_SDR37_RXTIME_MASK);
240cbb3ec25SBjoern A. Zeeb 	obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx),
241cbb3ec25SBjoern A. Zeeb 				   MT_MIB_OBSSTIME_MASK);
242cbb3ec25SBjoern A. Zeeb 
243cbb3ec25SBjoern A. Zeeb 	nf = mt792x_phy_get_nf(phy, idx);
244cbb3ec25SBjoern A. Zeeb 	if (!phy->noise)
245cbb3ec25SBjoern A. Zeeb 		phy->noise = nf << 4;
246cbb3ec25SBjoern A. Zeeb 	else if (nf)
247cbb3ec25SBjoern A. Zeeb 		phy->noise += nf - (phy->noise >> 4);
248cbb3ec25SBjoern A. Zeeb 
249cbb3ec25SBjoern A. Zeeb 	state = mphy->chan_state;
250cbb3ec25SBjoern A. Zeeb 	state->cc_busy += busy_time;
251cbb3ec25SBjoern A. Zeeb 	state->cc_tx += tx_time;
252cbb3ec25SBjoern A. Zeeb 	state->cc_rx += rx_time + obss_time;
253cbb3ec25SBjoern A. Zeeb 	state->cc_bss_rx += rx_time;
254cbb3ec25SBjoern A. Zeeb 	state->noise = -(phy->noise >> 4);
255cbb3ec25SBjoern A. Zeeb }
256cbb3ec25SBjoern A. Zeeb 
mt792x_update_channel(struct mt76_phy * mphy)257cbb3ec25SBjoern A. Zeeb void mt792x_update_channel(struct mt76_phy *mphy)
258cbb3ec25SBjoern A. Zeeb {
259cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76);
260cbb3ec25SBjoern A. Zeeb 
261cbb3ec25SBjoern A. Zeeb 	if (mt76_connac_pm_wake(mphy, &dev->pm))
262cbb3ec25SBjoern A. Zeeb 		return;
263cbb3ec25SBjoern A. Zeeb 
264cbb3ec25SBjoern A. Zeeb 	mt792x_phy_update_channel(mphy, 0);
265cbb3ec25SBjoern A. Zeeb 	/* reset obss airtime */
266cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
267cbb3ec25SBjoern A. Zeeb 	mt76_connac_power_save_sched(mphy, &dev->pm);
268cbb3ec25SBjoern A. Zeeb }
269cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_update_channel);
270cbb3ec25SBjoern A. Zeeb 
mt792x_reset(struct mt76_dev * mdev)271cbb3ec25SBjoern A. Zeeb void mt792x_reset(struct mt76_dev *mdev)
272cbb3ec25SBjoern A. Zeeb {
273cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
274cbb3ec25SBjoern A. Zeeb 	struct mt76_connac_pm *pm = &dev->pm;
275cbb3ec25SBjoern A. Zeeb 
276cbb3ec25SBjoern A. Zeeb 	if (!dev->hw_init_done)
277cbb3ec25SBjoern A. Zeeb 		return;
278cbb3ec25SBjoern A. Zeeb 
279cbb3ec25SBjoern A. Zeeb 	if (dev->hw_full_reset)
280cbb3ec25SBjoern A. Zeeb 		return;
281cbb3ec25SBjoern A. Zeeb 
282cbb3ec25SBjoern A. Zeeb 	if (pm->suspended)
283cbb3ec25SBjoern A. Zeeb 		return;
284cbb3ec25SBjoern A. Zeeb 
285cbb3ec25SBjoern A. Zeeb 	queue_work(dev->mt76.wq, &dev->reset_work);
286cbb3ec25SBjoern A. Zeeb }
287cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_reset);
288cbb3ec25SBjoern A. Zeeb 
mt792x_mac_init_band(struct mt792x_dev * dev,u8 band)289cbb3ec25SBjoern A. Zeeb void mt792x_mac_init_band(struct mt792x_dev *dev, u8 band)
290cbb3ec25SBjoern A. Zeeb {
291cbb3ec25SBjoern A. Zeeb 	u32 mask, set;
292cbb3ec25SBjoern A. Zeeb 
293cbb3ec25SBjoern A. Zeeb 	mt76_rmw_field(dev, MT_TMAC_CTCR0(band),
294cbb3ec25SBjoern A. Zeeb 		       MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);
295cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_TMAC_CTCR0(band),
296cbb3ec25SBjoern A. Zeeb 		 MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |
297cbb3ec25SBjoern A. Zeeb 		 MT_TMAC_CTCR0_INS_DDLMT_EN);
298cbb3ec25SBjoern A. Zeeb 
299cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
300cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
301cbb3ec25SBjoern A. Zeeb 
302cbb3ec25SBjoern A. Zeeb 	/* enable MIB tx-rx time reporting */
303cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_TXDUR_EN);
304cbb3ec25SBjoern A. Zeeb 	mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_RXDUR_EN);
305cbb3ec25SBjoern A. Zeeb 
306cbb3ec25SBjoern A. Zeeb 	mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536);
307cbb3ec25SBjoern A. Zeeb 	/* disable rx rate report by default due to hw issues */
308cbb3ec25SBjoern A. Zeeb 	mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
309cbb3ec25SBjoern A. Zeeb 
310cbb3ec25SBjoern A. Zeeb 	/* filter out non-resp frames and get instantaneous signal reporting */
311cbb3ec25SBjoern A. Zeeb 	mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM;
312cbb3ec25SBjoern A. Zeeb 	set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |
313cbb3ec25SBjoern A. Zeeb 	      FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);
314cbb3ec25SBjoern A. Zeeb 	mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
315cbb3ec25SBjoern A. Zeeb }
316cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_mac_init_band);
317cbb3ec25SBjoern A. Zeeb 
mt792x_pm_wake_work(struct work_struct * work)318cbb3ec25SBjoern A. Zeeb void mt792x_pm_wake_work(struct work_struct *work)
319cbb3ec25SBjoern A. Zeeb {
320cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev;
321cbb3ec25SBjoern A. Zeeb 	struct mt76_phy *mphy;
322cbb3ec25SBjoern A. Zeeb 
323cbb3ec25SBjoern A. Zeeb 	dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev,
324cbb3ec25SBjoern A. Zeeb 						pm.wake_work);
325cbb3ec25SBjoern A. Zeeb 	mphy = dev->phy.mt76;
326cbb3ec25SBjoern A. Zeeb 
327cbb3ec25SBjoern A. Zeeb 	if (!mt792x_mcu_drv_pmctrl(dev)) {
328cbb3ec25SBjoern A. Zeeb 		struct mt76_dev *mdev = &dev->mt76;
329cbb3ec25SBjoern A. Zeeb 		int i;
330cbb3ec25SBjoern A. Zeeb 
331cbb3ec25SBjoern A. Zeeb 		if (mt76_is_sdio(mdev)) {
332cbb3ec25SBjoern A. Zeeb 			mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
333cbb3ec25SBjoern A. Zeeb 			mt76_worker_schedule(&mdev->sdio.txrx_worker);
334cbb3ec25SBjoern A. Zeeb 		} else {
335cbb3ec25SBjoern A. Zeeb 			local_bh_disable();
336cbb3ec25SBjoern A. Zeeb 			mt76_for_each_q_rx(mdev, i)
337cbb3ec25SBjoern A. Zeeb 				napi_schedule(&mdev->napi[i]);
338cbb3ec25SBjoern A. Zeeb 			local_bh_enable();
339cbb3ec25SBjoern A. Zeeb 			mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
340cbb3ec25SBjoern A. Zeeb 			mt76_connac_tx_cleanup(mdev);
341cbb3ec25SBjoern A. Zeeb 		}
342cbb3ec25SBjoern A. Zeeb 		if (test_bit(MT76_STATE_RUNNING, &mphy->state))
343cbb3ec25SBjoern A. Zeeb 			ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
344cbb3ec25SBjoern A. Zeeb 						     MT792x_WATCHDOG_TIME);
345cbb3ec25SBjoern A. Zeeb 	}
346cbb3ec25SBjoern A. Zeeb 
347cbb3ec25SBjoern A. Zeeb 	ieee80211_wake_queues(mphy->hw);
348cbb3ec25SBjoern A. Zeeb 	wake_up(&dev->pm.wait);
349cbb3ec25SBjoern A. Zeeb }
350cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_pm_wake_work);
351cbb3ec25SBjoern A. Zeeb 
mt792x_pm_power_save_work(struct work_struct * work)352cbb3ec25SBjoern A. Zeeb void mt792x_pm_power_save_work(struct work_struct *work)
353cbb3ec25SBjoern A. Zeeb {
354cbb3ec25SBjoern A. Zeeb 	struct mt792x_dev *dev;
355cbb3ec25SBjoern A. Zeeb 	unsigned long delta;
356cbb3ec25SBjoern A. Zeeb 	struct mt76_phy *mphy;
357cbb3ec25SBjoern A. Zeeb 
358cbb3ec25SBjoern A. Zeeb 	dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev,
359cbb3ec25SBjoern A. Zeeb 						pm.ps_work.work);
360cbb3ec25SBjoern A. Zeeb 	mphy = dev->phy.mt76;
361cbb3ec25SBjoern A. Zeeb 
362cbb3ec25SBjoern A. Zeeb 	delta = dev->pm.idle_timeout;
363cbb3ec25SBjoern A. Zeeb 	if (test_bit(MT76_HW_SCANNING, &mphy->state) ||
364cbb3ec25SBjoern A. Zeeb 	    test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) ||
365cbb3ec25SBjoern A. Zeeb 	    dev->fw_assert)
366cbb3ec25SBjoern A. Zeeb 		goto out;
367cbb3ec25SBjoern A. Zeeb 
368cbb3ec25SBjoern A. Zeeb 	if (mutex_is_locked(&dev->mt76.mutex))
369cbb3ec25SBjoern A. Zeeb 		/* if mt76 mutex is held we should not put the device
370cbb3ec25SBjoern A. Zeeb 		 * to sleep since we are currently accessing device
371cbb3ec25SBjoern A. Zeeb 		 * register map. We need to wait for the next power_save
372cbb3ec25SBjoern A. Zeeb 		 * trigger.
373cbb3ec25SBjoern A. Zeeb 		 */
374cbb3ec25SBjoern A. Zeeb 		goto out;
375cbb3ec25SBjoern A. Zeeb 
376cbb3ec25SBjoern A. Zeeb 	if (time_is_after_jiffies(dev->pm.last_activity + delta)) {
377cbb3ec25SBjoern A. Zeeb 		delta = dev->pm.last_activity + delta - jiffies;
378cbb3ec25SBjoern A. Zeeb 		goto out;
379cbb3ec25SBjoern A. Zeeb 	}
380cbb3ec25SBjoern A. Zeeb 
381cbb3ec25SBjoern A. Zeeb 	if (!mt792x_mcu_fw_pmctrl(dev)) {
382cbb3ec25SBjoern A. Zeeb 		cancel_delayed_work_sync(&mphy->mac_work);
383cbb3ec25SBjoern A. Zeeb 		return;
384cbb3ec25SBjoern A. Zeeb 	}
385cbb3ec25SBjoern A. Zeeb out:
386cbb3ec25SBjoern A. Zeeb 	queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta);
387cbb3ec25SBjoern A. Zeeb }
388cbb3ec25SBjoern A. Zeeb EXPORT_SYMBOL_GPL(mt792x_pm_power_save_work);
389