diff options
author | Stanislaw Gruszka <sgruszka@redhat.com> | 2018-07-31 08:40:52 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@codeaurora.org> | 2018-08-02 14:50:45 -0400 |
commit | a774434981372fc583dfdf39a4094b3f0e3c4677 (patch) | |
tree | 7f402e2edd2654ca41f1797fed8ddaef7a79bc45 | |
parent | 7b4859026ccd47fb1fb48394123fda08d4f30bd6 (diff) |
mt76x0: mac files
Add mac files of mt76x0 driver.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt76x0/mac.c | 660 | ||||
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt76x0/mac.h | 154 |
2 files changed, 814 insertions, 0 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c new file mode 100644 index 000000000000..7b32777c06e9 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.c | |||
@@ -0,0 +1,660 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> | ||
3 | * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl> | ||
4 | * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 | ||
8 | * as published by the Free Software Foundation | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include "mt76x0.h" | ||
17 | #include "trace.h" | ||
18 | #include <linux/etherdevice.h> | ||
19 | |||
20 | static void | ||
21 | mt76_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate, | ||
22 | enum nl80211_band band) | ||
23 | { | ||
24 | u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate); | ||
25 | |||
26 | txrate->idx = 0; | ||
27 | txrate->flags = 0; | ||
28 | txrate->count = 1; | ||
29 | |||
30 | switch (FIELD_GET(MT_RXWI_RATE_PHY, rate)) { | ||
31 | case MT_PHY_TYPE_OFDM: | ||
32 | if (band == NL80211_BAND_2GHZ) | ||
33 | idx += 4; | ||
34 | |||
35 | txrate->idx = idx; | ||
36 | return; | ||
37 | case MT_PHY_TYPE_CCK: | ||
38 | if (idx >= 8) | ||
39 | idx -= 8; | ||
40 | |||
41 | txrate->idx = idx; | ||
42 | return; | ||
43 | case MT_PHY_TYPE_HT_GF: | ||
44 | txrate->flags |= IEEE80211_TX_RC_GREEN_FIELD; | ||
45 | /* fall through */ | ||
46 | case MT_PHY_TYPE_HT: | ||
47 | txrate->flags |= IEEE80211_TX_RC_MCS; | ||
48 | txrate->idx = idx; | ||
49 | break; | ||
50 | case MT_PHY_TYPE_VHT: | ||
51 | txrate->flags |= IEEE80211_TX_RC_VHT_MCS; | ||
52 | txrate->idx = idx; | ||
53 | break; | ||
54 | default: | ||
55 | WARN_ON(1); | ||
56 | return; | ||
57 | } | ||
58 | |||
59 | switch (FIELD_GET(MT_RXWI_RATE_BW, rate)) { | ||
60 | case MT_PHY_BW_20: | ||
61 | break; | ||
62 | case MT_PHY_BW_40: | ||
63 | txrate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | ||
64 | break; | ||
65 | case MT_PHY_BW_80: | ||
66 | txrate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH; | ||
67 | break; | ||
68 | default: | ||
69 | WARN_ON(1); | ||
70 | return; | ||
71 | } | ||
72 | |||
73 | if (rate & MT_RXWI_RATE_SGI) | ||
74 | txrate->flags |= IEEE80211_TX_RC_SHORT_GI; | ||
75 | } | ||
76 | |||
77 | static void | ||
78 | mt76_mac_fill_tx_status(struct mt76x0_dev *dev, struct ieee80211_tx_info *info, | ||
79 | struct mt76_tx_status *st, int n_frames) | ||
80 | { | ||
81 | struct ieee80211_tx_rate *rate = info->status.rates; | ||
82 | int cur_idx, last_rate; | ||
83 | int i; | ||
84 | |||
85 | if (!n_frames) | ||
86 | return; | ||
87 | |||
88 | last_rate = min_t(int, st->retry, IEEE80211_TX_MAX_RATES - 1); | ||
89 | mt76_mac_process_tx_rate(&rate[last_rate], st->rate, | ||
90 | dev->mt76.chandef.chan->band); | ||
91 | if (last_rate < IEEE80211_TX_MAX_RATES - 1) | ||
92 | rate[last_rate + 1].idx = -1; | ||
93 | |||
94 | cur_idx = rate[last_rate].idx + last_rate; | ||
95 | for (i = 0; i <= last_rate; i++) { | ||
96 | rate[i].flags = rate[last_rate].flags; | ||
97 | rate[i].idx = max_t(int, 0, cur_idx - i); | ||
98 | rate[i].count = 1; | ||
99 | } | ||
100 | |||
101 | rate[last_rate - 1].count = st->retry + 1 - last_rate; | ||
102 | |||
103 | info->status.ampdu_len = n_frames; | ||
104 | info->status.ampdu_ack_len = st->success ? n_frames : 0; | ||
105 | |||
106 | if (st->pktid & MT_TXWI_PKTID_PROBE) | ||
107 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | ||
108 | |||
109 | if (st->aggr) | ||
110 | info->flags |= IEEE80211_TX_CTL_AMPDU | | ||
111 | IEEE80211_TX_STAT_AMPDU; | ||
112 | |||
113 | if (!st->ack_req) | ||
114 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
115 | else if (st->success) | ||
116 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
117 | } | ||
118 | |||
119 | u16 mt76_mac_tx_rate_val(struct mt76x0_dev *dev, | ||
120 | const struct ieee80211_tx_rate *rate, u8 *nss_val) | ||
121 | { | ||
122 | u16 rateval; | ||
123 | u8 phy, rate_idx; | ||
124 | u8 nss = 1; | ||
125 | u8 bw = 0; | ||
126 | |||
127 | if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { | ||
128 | rate_idx = rate->idx; | ||
129 | nss = 1 + (rate->idx >> 4); | ||
130 | phy = MT_PHY_TYPE_VHT; | ||
131 | if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) | ||
132 | bw = 2; | ||
133 | else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
134 | bw = 1; | ||
135 | } else if (rate->flags & IEEE80211_TX_RC_MCS) { | ||
136 | rate_idx = rate->idx; | ||
137 | nss = 1 + (rate->idx >> 3); | ||
138 | phy = MT_PHY_TYPE_HT; | ||
139 | if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD) | ||
140 | phy = MT_PHY_TYPE_HT_GF; | ||
141 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
142 | bw = 1; | ||
143 | } else { | ||
144 | const struct ieee80211_rate *r; | ||
145 | int band = dev->mt76.chandef.chan->band; | ||
146 | u16 val; | ||
147 | |||
148 | r = &dev->mt76.hw->wiphy->bands[band]->bitrates[rate->idx]; | ||
149 | if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | ||
150 | val = r->hw_value_short; | ||
151 | else | ||
152 | val = r->hw_value; | ||
153 | |||
154 | phy = val >> 8; | ||
155 | rate_idx = val & 0xff; | ||
156 | bw = 0; | ||
157 | } | ||
158 | |||
159 | rateval = FIELD_PREP(MT_RXWI_RATE_INDEX, rate_idx); | ||
160 | rateval |= FIELD_PREP(MT_RXWI_RATE_PHY, phy); | ||
161 | rateval |= FIELD_PREP(MT_RXWI_RATE_BW, bw); | ||
162 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) | ||
163 | rateval |= MT_RXWI_RATE_SGI; | ||
164 | |||
165 | *nss_val = nss; | ||
166 | return cpu_to_le16(rateval); | ||
167 | } | ||
168 | |||
169 | void mt76_mac_wcid_set_rate(struct mt76x0_dev *dev, struct mt76_wcid *wcid, | ||
170 | const struct ieee80211_tx_rate *rate) | ||
171 | { | ||
172 | unsigned long flags; | ||
173 | |||
174 | spin_lock_irqsave(&dev->mt76.lock, flags); | ||
175 | wcid->tx_rate = mt76_mac_tx_rate_val(dev, rate, &wcid->tx_rate_nss); | ||
176 | wcid->tx_rate_set = true; | ||
177 | spin_unlock_irqrestore(&dev->mt76.lock, flags); | ||
178 | } | ||
179 | |||
180 | struct mt76_tx_status mt76x0_mac_fetch_tx_status(struct mt76x0_dev *dev) | ||
181 | { | ||
182 | struct mt76_tx_status stat = {}; | ||
183 | u32 stat2, stat1; | ||
184 | |||
185 | stat2 = mt76_rr(dev, MT_TX_STAT_FIFO_EXT); | ||
186 | stat1 = mt76_rr(dev, MT_TX_STAT_FIFO); | ||
187 | |||
188 | stat.valid = !!(stat1 & MT_TX_STAT_FIFO_VALID); | ||
189 | stat.success = !!(stat1 & MT_TX_STAT_FIFO_SUCCESS); | ||
190 | stat.aggr = !!(stat1 & MT_TX_STAT_FIFO_AGGR); | ||
191 | stat.ack_req = !!(stat1 & MT_TX_STAT_FIFO_ACKREQ); | ||
192 | stat.wcid = FIELD_GET(MT_TX_STAT_FIFO_WCID, stat1); | ||
193 | stat.rate = FIELD_GET(MT_TX_STAT_FIFO_RATE, stat1); | ||
194 | |||
195 | stat.retry = FIELD_GET(MT_TX_STAT_FIFO_EXT_RETRY, stat2); | ||
196 | stat.pktid = FIELD_GET(MT_TX_STAT_FIFO_EXT_PKTID, stat2); | ||
197 | |||
198 | return stat; | ||
199 | } | ||
200 | |||
201 | void mt76_send_tx_status(struct mt76x0_dev *dev, struct mt76_tx_status *stat, u8 *update) | ||
202 | { | ||
203 | struct ieee80211_tx_info info = {}; | ||
204 | struct ieee80211_sta *sta = NULL; | ||
205 | struct mt76_wcid *wcid = NULL; | ||
206 | struct mt76_sta *msta = NULL; | ||
207 | |||
208 | rcu_read_lock(); | ||
209 | if (stat->wcid < ARRAY_SIZE(dev->wcid)) | ||
210 | wcid = rcu_dereference(dev->wcid[stat->wcid]); | ||
211 | |||
212 | if (wcid) { | ||
213 | void *priv; | ||
214 | priv = msta = container_of(wcid, struct mt76_sta, wcid); | ||
215 | sta = container_of(priv, struct ieee80211_sta, drv_priv); | ||
216 | } | ||
217 | |||
218 | if (msta && stat->aggr) { | ||
219 | u32 stat_val, stat_cache; | ||
220 | |||
221 | stat_val = stat->rate; | ||
222 | stat_val |= ((u32) stat->retry) << 16; | ||
223 | stat_cache = msta->status.rate; | ||
224 | stat_cache |= ((u32) msta->status.retry) << 16; | ||
225 | |||
226 | if (*update == 0 && stat_val == stat_cache && | ||
227 | stat->wcid == msta->status.wcid && msta->n_frames < 32) { | ||
228 | msta->n_frames++; | ||
229 | goto out; | ||
230 | } | ||
231 | |||
232 | mt76_mac_fill_tx_status(dev, &info, &msta->status, | ||
233 | msta->n_frames); | ||
234 | msta->status = *stat; | ||
235 | msta->n_frames = 1; | ||
236 | *update = 0; | ||
237 | } else { | ||
238 | mt76_mac_fill_tx_status(dev, &info, stat, 1); | ||
239 | *update = 1; | ||
240 | } | ||
241 | |||
242 | spin_lock_bh(&dev->mac_lock); | ||
243 | ieee80211_tx_status_noskb(dev->mt76.hw, sta, &info); | ||
244 | spin_unlock_bh(&dev->mac_lock); | ||
245 | out: | ||
246 | rcu_read_unlock(); | ||
247 | } | ||
248 | |||
249 | void mt76x0_mac_set_protection(struct mt76x0_dev *dev, bool legacy_prot, | ||
250 | int ht_mode) | ||
251 | { | ||
252 | int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION; | ||
253 | bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); | ||
254 | u32 prot[6]; | ||
255 | bool ht_rts[4] = {}; | ||
256 | int i; | ||
257 | |||
258 | prot[0] = MT_PROT_NAV_SHORT | | ||
259 | MT_PROT_TXOP_ALLOW_ALL | | ||
260 | MT_PROT_RTS_THR_EN; | ||
261 | prot[1] = prot[0]; | ||
262 | if (legacy_prot) | ||
263 | prot[1] |= MT_PROT_CTRL_CTS2SELF; | ||
264 | |||
265 | prot[2] = prot[4] = MT_PROT_NAV_SHORT | MT_PROT_TXOP_ALLOW_BW20; | ||
266 | prot[3] = prot[5] = MT_PROT_NAV_SHORT | MT_PROT_TXOP_ALLOW_ALL; | ||
267 | |||
268 | if (legacy_prot) { | ||
269 | prot[2] |= MT_PROT_RATE_CCK_11; | ||
270 | prot[3] |= MT_PROT_RATE_CCK_11; | ||
271 | prot[4] |= MT_PROT_RATE_CCK_11; | ||
272 | prot[5] |= MT_PROT_RATE_CCK_11; | ||
273 | } else { | ||
274 | prot[2] |= MT_PROT_RATE_OFDM_24; | ||
275 | prot[3] |= MT_PROT_RATE_DUP_OFDM_24; | ||
276 | prot[4] |= MT_PROT_RATE_OFDM_24; | ||
277 | prot[5] |= MT_PROT_RATE_DUP_OFDM_24; | ||
278 | } | ||
279 | |||
280 | switch (mode) { | ||
281 | case IEEE80211_HT_OP_MODE_PROTECTION_NONE: | ||
282 | break; | ||
283 | |||
284 | case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER: | ||
285 | ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true; | ||
286 | break; | ||
287 | |||
288 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | ||
289 | ht_rts[1] = ht_rts[3] = true; | ||
290 | break; | ||
291 | |||
292 | case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: | ||
293 | ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true; | ||
294 | break; | ||
295 | } | ||
296 | |||
297 | if (non_gf) | ||
298 | ht_rts[2] = ht_rts[3] = true; | ||
299 | |||
300 | for (i = 0; i < 4; i++) | ||
301 | if (ht_rts[i]) | ||
302 | prot[i + 2] |= MT_PROT_CTRL_RTS_CTS; | ||
303 | |||
304 | for (i = 0; i < 6; i++) | ||
305 | mt76_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]); | ||
306 | } | ||
307 | |||
308 | void mt76x0_mac_set_short_preamble(struct mt76x0_dev *dev, bool short_preamb) | ||
309 | { | ||
310 | if (short_preamb) | ||
311 | mt76_set(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT); | ||
312 | else | ||
313 | mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT); | ||
314 | } | ||
315 | |||
316 | void mt76x0_mac_config_tsf(struct mt76x0_dev *dev, bool enable, int interval) | ||
317 | { | ||
318 | u32 val = mt76_rr(dev, MT_BEACON_TIME_CFG); | ||
319 | |||
320 | val &= ~(MT_BEACON_TIME_CFG_TIMER_EN | | ||
321 | MT_BEACON_TIME_CFG_SYNC_MODE | | ||
322 | MT_BEACON_TIME_CFG_TBTT_EN); | ||
323 | |||
324 | if (!enable) { | ||
325 | mt76_wr(dev, MT_BEACON_TIME_CFG, val); | ||
326 | return; | ||
327 | } | ||
328 | |||
329 | val &= ~MT_BEACON_TIME_CFG_INTVAL; | ||
330 | val |= FIELD_PREP(MT_BEACON_TIME_CFG_INTVAL, interval << 4) | | ||
331 | MT_BEACON_TIME_CFG_TIMER_EN | | ||
332 | MT_BEACON_TIME_CFG_SYNC_MODE | | ||
333 | MT_BEACON_TIME_CFG_TBTT_EN; | ||
334 | } | ||
335 | |||
336 | static void mt76x0_check_mac_err(struct mt76x0_dev *dev) | ||
337 | { | ||
338 | u32 val = mt76_rr(dev, 0x10f4); | ||
339 | |||
340 | if (!(val & BIT(29)) || !(val & (BIT(7) | BIT(5)))) | ||
341 | return; | ||
342 | |||
343 | dev_err(dev->mt76.dev, "Error: MAC specific condition occurred\n"); | ||
344 | |||
345 | mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR); | ||
346 | udelay(10); | ||
347 | mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR); | ||
348 | } | ||
349 | void mt76x0_mac_work(struct work_struct *work) | ||
350 | { | ||
351 | struct mt76x0_dev *dev = container_of(work, struct mt76x0_dev, | ||
352 | mac_work.work); | ||
353 | struct { | ||
354 | u32 addr_base; | ||
355 | u32 span; | ||
356 | u64 *stat_base; | ||
357 | } spans[] = { | ||
358 | { MT_RX_STA_CNT0, 3, dev->stats.rx_stat }, | ||
359 | { MT_TX_STA_CNT0, 3, dev->stats.tx_stat }, | ||
360 | { MT_TX_AGG_STAT, 1, dev->stats.aggr_stat }, | ||
361 | { MT_MPDU_DENSITY_CNT, 1, dev->stats.zero_len_del }, | ||
362 | { MT_TX_AGG_CNT_BASE0, 8, &dev->stats.aggr_n[0] }, | ||
363 | { MT_TX_AGG_CNT_BASE1, 8, &dev->stats.aggr_n[16] }, | ||
364 | }; | ||
365 | u32 sum, n; | ||
366 | int i, j, k; | ||
367 | |||
368 | /* Note: using MCU_RANDOM_READ is actually slower then reading all the | ||
369 | * registers by hand. MCU takes ca. 20ms to complete read of 24 | ||
370 | * registers while reading them one by one will takes roughly | ||
371 | * 24*200us =~ 5ms. | ||
372 | */ | ||
373 | |||
374 | k = 0; | ||
375 | n = 0; | ||
376 | sum = 0; | ||
377 | for (i = 0; i < ARRAY_SIZE(spans); i++) | ||
378 | for (j = 0; j < spans[i].span; j++) { | ||
379 | u32 val = mt76_rr(dev, spans[i].addr_base + j * 4); | ||
380 | |||
381 | spans[i].stat_base[j * 2] += val & 0xffff; | ||
382 | spans[i].stat_base[j * 2 + 1] += val >> 16; | ||
383 | |||
384 | /* Calculate average AMPDU length */ | ||
385 | if (spans[i].addr_base != MT_TX_AGG_CNT_BASE0 && | ||
386 | spans[i].addr_base != MT_TX_AGG_CNT_BASE1) | ||
387 | continue; | ||
388 | |||
389 | n += (val >> 16) + (val & 0xffff); | ||
390 | sum += (val & 0xffff) * (1 + k * 2) + | ||
391 | (val >> 16) * (2 + k * 2); | ||
392 | k++; | ||
393 | } | ||
394 | |||
395 | atomic_set(&dev->avg_ampdu_len, n ? DIV_ROUND_CLOSEST(sum, n) : 1); | ||
396 | |||
397 | mt76x0_check_mac_err(dev); | ||
398 | |||
399 | ieee80211_queue_delayed_work(dev->mt76.hw, &dev->mac_work, 10 * HZ); | ||
400 | } | ||
401 | |||
402 | void | ||
403 | mt76x0_mac_wcid_setup(struct mt76x0_dev *dev, u8 idx, u8 vif_idx, u8 *mac) | ||
404 | { | ||
405 | u8 zmac[ETH_ALEN] = {}; | ||
406 | u32 attr; | ||
407 | |||
408 | attr = FIELD_PREP(MT_WCID_ATTR_BSS_IDX, vif_idx & 7) | | ||
409 | FIELD_PREP(MT_WCID_ATTR_BSS_IDX_EXT, !!(vif_idx & 8)); | ||
410 | |||
411 | mt76_wr(dev, MT_WCID_ATTR(idx), attr); | ||
412 | |||
413 | if (mac) | ||
414 | memcpy(zmac, mac, sizeof(zmac)); | ||
415 | |||
416 | mt76x0_addr_wr(dev, MT_WCID_ADDR(idx), zmac); | ||
417 | } | ||
418 | |||
419 | void mt76x0_mac_set_ampdu_factor(struct mt76x0_dev *dev) | ||
420 | { | ||
421 | struct ieee80211_sta *sta; | ||
422 | struct mt76_wcid *wcid; | ||
423 | void *msta; | ||
424 | u8 min_factor = 3; | ||
425 | int i; | ||
426 | |||
427 | return; | ||
428 | |||
429 | rcu_read_lock(); | ||
430 | for (i = 0; i < ARRAY_SIZE(dev->wcid); i++) { | ||
431 | wcid = rcu_dereference(dev->wcid[i]); | ||
432 | if (!wcid) | ||
433 | continue; | ||
434 | |||
435 | msta = container_of(wcid, struct mt76_sta, wcid); | ||
436 | sta = container_of(msta, struct ieee80211_sta, drv_priv); | ||
437 | |||
438 | min_factor = min(min_factor, sta->ht_cap.ampdu_factor); | ||
439 | } | ||
440 | rcu_read_unlock(); | ||
441 | |||
442 | mt76_wr(dev, MT_MAX_LEN_CFG, 0xa0fff | | ||
443 | FIELD_PREP(MT_MAX_LEN_CFG_AMPDU, min_factor)); | ||
444 | } | ||
445 | |||
446 | static void | ||
447 | mt76_mac_process_rate(struct ieee80211_rx_status *status, u16 rate) | ||
448 | { | ||
449 | u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate); | ||
450 | |||
451 | switch (FIELD_GET(MT_RXWI_RATE_PHY, rate)) { | ||
452 | case MT_PHY_TYPE_OFDM: | ||
453 | if (idx >= 8) | ||
454 | idx = 0; | ||
455 | |||
456 | if (status->band == NL80211_BAND_2GHZ) | ||
457 | idx += 4; | ||
458 | |||
459 | status->rate_idx = idx; | ||
460 | return; | ||
461 | case MT_PHY_TYPE_CCK: | ||
462 | if (idx >= 8) { | ||
463 | idx -= 8; | ||
464 | status->enc_flags |= RX_ENC_FLAG_SHORTPRE; | ||
465 | } | ||
466 | |||
467 | if (idx >= 4) | ||
468 | idx = 0; | ||
469 | |||
470 | status->rate_idx = idx; | ||
471 | return; | ||
472 | case MT_PHY_TYPE_HT_GF: | ||
473 | status->enc_flags |= RX_ENC_FLAG_HT_GF; | ||
474 | /* fall through */ | ||
475 | case MT_PHY_TYPE_HT: | ||
476 | status->encoding = RX_ENC_HT; | ||
477 | status->rate_idx = idx; | ||
478 | break; | ||
479 | case MT_PHY_TYPE_VHT: | ||
480 | status->encoding = RX_ENC_VHT; | ||
481 | status->rate_idx = FIELD_GET(MT_RATE_INDEX_VHT_IDX, idx); | ||
482 | status->nss = FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1; | ||
483 | break; | ||
484 | default: | ||
485 | WARN_ON(1); | ||
486 | return; | ||
487 | } | ||
488 | |||
489 | if (rate & MT_RXWI_RATE_LDPC) | ||
490 | status->enc_flags |= RX_ENC_FLAG_LDPC; | ||
491 | |||
492 | if (rate & MT_RXWI_RATE_SGI) | ||
493 | status->enc_flags |= RX_ENC_FLAG_SHORT_GI; | ||
494 | |||
495 | if (rate & MT_RXWI_RATE_STBC) | ||
496 | status->enc_flags |= 1 << RX_ENC_FLAG_STBC_SHIFT; | ||
497 | |||
498 | switch (FIELD_GET(MT_RXWI_RATE_BW, rate)) { | ||
499 | case MT_PHY_BW_20: | ||
500 | break; | ||
501 | case MT_PHY_BW_40: | ||
502 | status->bw = RATE_INFO_BW_40; | ||
503 | break; | ||
504 | case MT_PHY_BW_80: | ||
505 | status->bw = RATE_INFO_BW_80; | ||
506 | break; | ||
507 | default: | ||
508 | WARN_ON(1); | ||
509 | break; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | static void | ||
514 | mt76x0_rx_monitor_beacon(struct mt76x0_dev *dev, struct mt76x0_rxwi *rxwi, | ||
515 | u16 rate, int rssi) | ||
516 | { | ||
517 | dev->bcn_phy_mode = FIELD_GET(MT_RXWI_RATE_PHY, rate); | ||
518 | dev->avg_rssi = ((dev->avg_rssi * 15) / 16 + (rssi << 8)) / 256; | ||
519 | } | ||
520 | |||
521 | static int | ||
522 | mt76x0_rx_is_our_beacon(struct mt76x0_dev *dev, u8 *data) | ||
523 | { | ||
524 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data; | ||
525 | |||
526 | return ieee80211_is_beacon(hdr->frame_control) && | ||
527 | ether_addr_equal(hdr->addr2, dev->ap_bssid); | ||
528 | } | ||
529 | |||
530 | u32 mt76_mac_process_rx(struct mt76x0_dev *dev, struct sk_buff *skb, | ||
531 | u8 *data, void *rxi) | ||
532 | { | ||
533 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
534 | struct mt76x0_rxwi *rxwi = rxi; | ||
535 | u32 len, ctl = le32_to_cpu(rxwi->ctl); | ||
536 | u16 rate = le16_to_cpu(rxwi->rate); | ||
537 | int rssi; | ||
538 | |||
539 | len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl); | ||
540 | if (WARN_ON(len < 10)) | ||
541 | return 0; | ||
542 | |||
543 | if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) { | ||
544 | status->flag |= RX_FLAG_DECRYPTED; | ||
545 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; | ||
546 | } | ||
547 | |||
548 | status->chains = BIT(0); | ||
549 | rssi = mt76x0_phy_get_rssi(dev, rxwi); | ||
550 | status->chain_signal[0] = status->signal = rssi; | ||
551 | status->freq = dev->mt76.chandef.chan->center_freq; | ||
552 | status->band = dev->mt76.chandef.chan->band; | ||
553 | |||
554 | mt76_mac_process_rate(status, rate); | ||
555 | |||
556 | spin_lock_bh(&dev->con_mon_lock); | ||
557 | if (mt76x0_rx_is_our_beacon(dev, data)) { | ||
558 | mt76x0_rx_monitor_beacon(dev, rxwi, rate, rssi); | ||
559 | } else if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_U2M)) { | ||
560 | if (dev->avg_rssi == 0) | ||
561 | dev->avg_rssi = rssi; | ||
562 | else | ||
563 | dev->avg_rssi = (dev->avg_rssi * 15) / 16 + rssi / 16; | ||
564 | |||
565 | } | ||
566 | spin_unlock_bh(&dev->con_mon_lock); | ||
567 | |||
568 | return len; | ||
569 | } | ||
570 | |||
571 | static enum mt76_cipher_type | ||
572 | mt76_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data) | ||
573 | { | ||
574 | memset(key_data, 0, 32); | ||
575 | if (!key) | ||
576 | return MT_CIPHER_NONE; | ||
577 | |||
578 | if (key->keylen > 32) | ||
579 | return MT_CIPHER_NONE; | ||
580 | |||
581 | memcpy(key_data, key->key, key->keylen); | ||
582 | |||
583 | switch (key->cipher) { | ||
584 | case WLAN_CIPHER_SUITE_WEP40: | ||
585 | return MT_CIPHER_WEP40; | ||
586 | case WLAN_CIPHER_SUITE_WEP104: | ||
587 | return MT_CIPHER_WEP104; | ||
588 | case WLAN_CIPHER_SUITE_TKIP: | ||
589 | return MT_CIPHER_TKIP; | ||
590 | case WLAN_CIPHER_SUITE_CCMP: | ||
591 | return MT_CIPHER_AES_CCMP; | ||
592 | default: | ||
593 | return MT_CIPHER_NONE; | ||
594 | } | ||
595 | } | ||
596 | |||
597 | int mt76_mac_wcid_set_key(struct mt76x0_dev *dev, u8 idx, | ||
598 | struct ieee80211_key_conf *key) | ||
599 | { | ||
600 | enum mt76_cipher_type cipher; | ||
601 | u8 key_data[32]; | ||
602 | u8 iv_data[8]; | ||
603 | u32 val; | ||
604 | |||
605 | cipher = mt76_mac_get_key_info(key, key_data); | ||
606 | if (cipher == MT_CIPHER_NONE && key) | ||
607 | return -EINVAL; | ||
608 | |||
609 | trace_set_key(&dev->mt76, idx); | ||
610 | |||
611 | mt76_wr_copy(dev, MT_WCID_KEY(idx), key_data, sizeof(key_data)); | ||
612 | |||
613 | memset(iv_data, 0, sizeof(iv_data)); | ||
614 | if (key) { | ||
615 | iv_data[3] = key->keyidx << 6; | ||
616 | if (cipher >= MT_CIPHER_TKIP) { | ||
617 | /* Note: start with 1 to comply with spec, | ||
618 | * (see comment on common/cmm_wpa.c:4291). | ||
619 | */ | ||
620 | iv_data[0] |= 1; | ||
621 | iv_data[3] |= 0x20; | ||
622 | } | ||
623 | } | ||
624 | mt76_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data)); | ||
625 | |||
626 | val = mt76_rr(dev, MT_WCID_ATTR(idx)); | ||
627 | val &= ~MT_WCID_ATTR_PKEY_MODE & ~MT_WCID_ATTR_PKEY_MODE_EXT; | ||
628 | val |= FIELD_PREP(MT_WCID_ATTR_PKEY_MODE, cipher & 7) | | ||
629 | FIELD_PREP(MT_WCID_ATTR_PKEY_MODE_EXT, cipher >> 3); | ||
630 | val &= ~MT_WCID_ATTR_PAIRWISE; | ||
631 | val |= MT_WCID_ATTR_PAIRWISE * | ||
632 | !!(key && key->flags & IEEE80211_KEY_FLAG_PAIRWISE); | ||
633 | mt76_wr(dev, MT_WCID_ATTR(idx), val); | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | int mt76_mac_shared_key_setup(struct mt76x0_dev *dev, u8 vif_idx, u8 key_idx, | ||
639 | struct ieee80211_key_conf *key) | ||
640 | { | ||
641 | enum mt76_cipher_type cipher; | ||
642 | u8 key_data[32]; | ||
643 | u32 val; | ||
644 | |||
645 | cipher = mt76_mac_get_key_info(key, key_data); | ||
646 | if (cipher == MT_CIPHER_NONE && key) | ||
647 | return -EINVAL; | ||
648 | |||
649 | trace_set_shared_key(&dev->mt76, vif_idx, key_idx); | ||
650 | |||
651 | mt76_wr_copy(dev, MT_SKEY(vif_idx, key_idx), | ||
652 | key_data, sizeof(key_data)); | ||
653 | |||
654 | val = mt76_rr(dev, MT_SKEY_MODE(vif_idx)); | ||
655 | val &= ~(MT_SKEY_MODE_MASK << MT_SKEY_MODE_SHIFT(vif_idx, key_idx)); | ||
656 | val |= cipher << MT_SKEY_MODE_SHIFT(vif_idx, key_idx); | ||
657 | mt76_wr(dev, MT_SKEY_MODE(vif_idx), val); | ||
658 | |||
659 | return 0; | ||
660 | } | ||
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/mac.h b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.h new file mode 100644 index 000000000000..947eba253553 --- /dev/null +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/mac.h | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> | ||
3 | * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | */ | ||
14 | |||
15 | #ifndef __MT76_MAC_H | ||
16 | #define __MT76_MAC_H | ||
17 | |||
18 | /* Note: values in original "RSSI" and "SNR" fields are not actually what they | ||
19 | * are called for MT76X0U, names used by this driver are educated guesses | ||
20 | * (see vendor mac/ral_omac.c). | ||
21 | */ | ||
22 | struct mt76x0_rxwi { | ||
23 | __le32 rxinfo; | ||
24 | |||
25 | __le32 ctl; | ||
26 | |||
27 | __le16 tid_sn; | ||
28 | __le16 rate; | ||
29 | |||
30 | s8 rssi[4]; | ||
31 | |||
32 | __le32 bbp_rxinfo[4]; | ||
33 | } __packed __aligned(4); | ||
34 | |||
35 | #define MT_RXINFO_BA BIT(0) | ||
36 | #define MT_RXINFO_DATA BIT(1) | ||
37 | #define MT_RXINFO_NULL BIT(2) | ||
38 | #define MT_RXINFO_FRAG BIT(3) | ||
39 | #define MT_RXINFO_U2M BIT(4) | ||
40 | #define MT_RXINFO_MULTICAST BIT(5) | ||
41 | #define MT_RXINFO_BROADCAST BIT(6) | ||
42 | #define MT_RXINFO_MYBSS BIT(7) | ||
43 | #define MT_RXINFO_CRCERR BIT(8) | ||
44 | #define MT_RXINFO_ICVERR BIT(9) | ||
45 | #define MT_RXINFO_MICERR BIT(10) | ||
46 | #define MT_RXINFO_AMSDU BIT(11) | ||
47 | #define MT_RXINFO_HTC BIT(12) | ||
48 | #define MT_RXINFO_RSSI BIT(13) | ||
49 | #define MT_RXINFO_L2PAD BIT(14) | ||
50 | #define MT_RXINFO_AMPDU BIT(15) | ||
51 | #define MT_RXINFO_DECRYPT BIT(16) | ||
52 | #define MT_RXINFO_BSSIDX3 BIT(17) | ||
53 | #define MT_RXINFO_WAPI_KEY BIT(18) | ||
54 | #define MT_RXINFO_PN_LEN GENMASK(21, 19) | ||
55 | #define MT_RXINFO_SW_PKT_80211 BIT(22) | ||
56 | #define MT_RXINFO_TCP_SUM_BYPASS BIT(28) | ||
57 | #define MT_RXINFO_IP_SUM_BYPASS BIT(29) | ||
58 | #define MT_RXINFO_TCP_SUM_ERR BIT(30) | ||
59 | #define MT_RXINFO_IP_SUM_ERR BIT(31) | ||
60 | |||
61 | #define MT_RXWI_CTL_WCID GENMASK(7, 0) | ||
62 | #define MT_RXWI_CTL_KEY_IDX GENMASK(9, 8) | ||
63 | #define MT_RXWI_CTL_BSS_IDX GENMASK(12, 10) | ||
64 | #define MT_RXWI_CTL_UDF GENMASK(15, 13) | ||
65 | #define MT_RXWI_CTL_MPDU_LEN GENMASK(27, 16) | ||
66 | #define MT_RXWI_CTL_TID GENMASK(31, 28) | ||
67 | |||
68 | #define MT_RXWI_FRAG GENMASK(3, 0) | ||
69 | #define MT_RXWI_SN GENMASK(15, 4) | ||
70 | |||
71 | #define MT_RXWI_RATE_INDEX GENMASK(5, 0) | ||
72 | #define MT_RXWI_RATE_LDPC BIT(6) | ||
73 | #define MT_RXWI_RATE_BW GENMASK(8, 7) | ||
74 | #define MT_RXWI_RATE_SGI BIT(9) | ||
75 | #define MT_RXWI_RATE_STBC BIT(10) | ||
76 | #define MT_RXWI_RATE_LDPC_ETXBF BIT(11) | ||
77 | #define MT_RXWI_RATE_SND BIT(12) | ||
78 | #define MT_RXWI_RATE_PHY GENMASK(15, 13) | ||
79 | |||
80 | #define MT_RATE_INDEX_VHT_IDX GENMASK(3, 0) | ||
81 | #define MT_RATE_INDEX_VHT_NSS GENMASK(5, 4) | ||
82 | |||
83 | #define MT_RXWI_GAIN_RSSI_VAL GENMASK(5, 0) | ||
84 | #define MT_RXWI_GAIN_RSSI_LNA_ID GENMASK(7, 6) | ||
85 | #define MT_RXWI_ANT_AUX_LNA BIT(7) | ||
86 | |||
87 | #define MT_RXWI_EANT_ENC_ANT_ID GENMASK(7, 0) | ||
88 | |||
89 | enum mt76_phy_bandwidth { | ||
90 | MT_PHY_BW_20, | ||
91 | MT_PHY_BW_40, | ||
92 | MT_PHY_BW_80, | ||
93 | }; | ||
94 | |||
95 | struct mt76_txwi { | ||
96 | __le16 flags; | ||
97 | __le16 rate_ctl; | ||
98 | u8 ack_ctl; | ||
99 | u8 wcid; | ||
100 | __le16 len_ctl; | ||
101 | __le32 iv; | ||
102 | __le32 eiv; | ||
103 | u8 aid; | ||
104 | u8 txstream; | ||
105 | u8 ctl2; | ||
106 | u8 pktid; | ||
107 | } __packed __aligned(4); | ||
108 | |||
109 | #define MT_TXWI_FLAGS_FRAG BIT(0) | ||
110 | #define MT_TXWI_FLAGS_MMPS BIT(1) | ||
111 | #define MT_TXWI_FLAGS_CFACK BIT(2) | ||
112 | #define MT_TXWI_FLAGS_TS BIT(3) | ||
113 | #define MT_TXWI_FLAGS_AMPDU BIT(4) | ||
114 | #define MT_TXWI_FLAGS_MPDU_DENSITY GENMASK(7, 5) | ||
115 | #define MT_TXWI_FLAGS_TXOP GENMASK(9, 8) | ||
116 | #define MT_TXWI_FLAGS_CWMIN GENMASK(12, 10) | ||
117 | #define MT_TXWI_FLAGS_NO_RATE_FALLBACK BIT(13) | ||
118 | #define MT_TXWI_FLAGS_TX_RPT BIT(14) | ||
119 | #define MT_TXWI_FLAGS_TX_RATE_LUT BIT(15) | ||
120 | |||
121 | #define MT_TXWI_RATE_MCS GENMASK(6, 0) | ||
122 | #define MT_TXWI_RATE_BW BIT(7) | ||
123 | #define MT_TXWI_RATE_SGI BIT(8) | ||
124 | #define MT_TXWI_RATE_STBC GENMASK(10, 9) | ||
125 | #define MT_TXWI_RATE_PHY_MODE GENMASK(15, 14) | ||
126 | |||
127 | #define MT_TXWI_ACK_CTL_REQ BIT(0) | ||
128 | #define MT_TXWI_ACK_CTL_NSEQ BIT(1) | ||
129 | #define MT_TXWI_ACK_CTL_BA_WINDOW GENMASK(7, 2) | ||
130 | |||
131 | #define MT_TXWI_LEN_BYTE_CNT GENMASK(11, 0) | ||
132 | |||
133 | #define MT_TXWI_CTL_TX_POWER_ADJ GENMASK(3, 0) | ||
134 | #define MT_TXWI_CTL_CHAN_CHECK_PKT BIT(4) | ||
135 | #define MT_TXWI_CTL_PIFS_REV BIT(6) | ||
136 | |||
137 | #define MT_TXWI_PKTID_PROBE BIT(7) | ||
138 | |||
139 | u32 mt76_mac_process_rx(struct mt76x0_dev *dev, struct sk_buff *skb, | ||
140 | u8 *data, void *rxi); | ||
141 | int mt76_mac_wcid_set_key(struct mt76x0_dev *dev, u8 idx, | ||
142 | struct ieee80211_key_conf *key); | ||
143 | void mt76_mac_wcid_set_rate(struct mt76x0_dev *dev, struct mt76_wcid *wcid, | ||
144 | const struct ieee80211_tx_rate *rate); | ||
145 | |||
146 | int mt76_mac_shared_key_setup(struct mt76x0_dev *dev, u8 vif_idx, u8 key_idx, | ||
147 | struct ieee80211_key_conf *key); | ||
148 | u16 mt76_mac_tx_rate_val(struct mt76x0_dev *dev, | ||
149 | const struct ieee80211_tx_rate *rate, u8 *nss_val); | ||
150 | struct mt76_tx_status | ||
151 | mt76x0_mac_fetch_tx_status(struct mt76x0_dev *dev); | ||
152 | void mt76_send_tx_status(struct mt76x0_dev *dev, struct mt76_tx_status *stat, u8 *update); | ||
153 | |||
154 | #endif | ||