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