xref: /linux/drivers/net/wireless/mediatek/mt7601u/mac.c (revision d6869352cb3c3cf3450637a52349e2e87c1354aa)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
4  * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
5  */
6 
7 #include "mt7601u.h"
8 #include "trace.h"
9 #include <linux/etherdevice.h>
10 
11 void mt7601u_set_macaddr(struct mt7601u_dev *dev, const u8 *addr)
12 {
13 	ether_addr_copy(dev->macaddr, addr);
14 
15 	if (!is_valid_ether_addr(dev->macaddr)) {
16 		eth_random_addr(dev->macaddr);
17 		dev_info(dev->dev,
18 			 "Invalid MAC address, using random address %pM\n",
19 			 dev->macaddr);
20 	}
21 
22 	mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->macaddr));
23 	mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dev->macaddr + 4) |
24 		FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff));
25 }
26 
27 static void
28 mt76_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate)
29 {
30 	u8 idx = FIELD_GET(MT_TXWI_RATE_MCS, rate);
31 
32 	txrate->idx = 0;
33 	txrate->flags = 0;
34 	txrate->count = 1;
35 
36 	switch (FIELD_GET(MT_TXWI_RATE_PHY_MODE, rate)) {
37 	case MT_PHY_TYPE_OFDM:
38 		txrate->idx = idx + 4;
39 		return;
40 	case MT_PHY_TYPE_CCK:
41 		if (idx >= 8)
42 			idx -= 8;
43 
44 		txrate->idx = idx;
45 		return;
46 	case MT_PHY_TYPE_HT_GF:
47 		txrate->flags |= IEEE80211_TX_RC_GREEN_FIELD;
48 		/* fall through */
49 	case MT_PHY_TYPE_HT:
50 		txrate->flags |= IEEE80211_TX_RC_MCS;
51 		txrate->idx = idx;
52 		break;
53 	default:
54 		WARN_ON(1);
55 		return;
56 	}
57 
58 	if (FIELD_GET(MT_TXWI_RATE_BW, rate) == MT_PHY_BW_40)
59 		txrate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
60 
61 	if (rate & MT_TXWI_RATE_SGI)
62 		txrate->flags |= IEEE80211_TX_RC_SHORT_GI;
63 }
64 
65 static void
66 mt76_mac_fill_tx_status(struct mt7601u_dev *dev, struct ieee80211_tx_info *info,
67 			struct mt76_tx_status *st)
68 {
69 	struct ieee80211_tx_rate *rate = info->status.rates;
70 	int cur_idx, last_rate;
71 	int i;
72 
73 	last_rate = min_t(int, st->retry, IEEE80211_TX_MAX_RATES - 1);
74 	mt76_mac_process_tx_rate(&rate[last_rate], st->rate);
75 	if (last_rate < IEEE80211_TX_MAX_RATES - 1)
76 		rate[last_rate + 1].idx = -1;
77 
78 	cur_idx = rate[last_rate].idx + st->retry;
79 	for (i = 0; i <= last_rate; i++) {
80 		rate[i].flags = rate[last_rate].flags;
81 		rate[i].idx = max_t(int, 0, cur_idx - i);
82 		rate[i].count = 1;
83 	}
84 
85 	if (last_rate > 0)
86 		rate[last_rate - 1].count = st->retry + 1 - last_rate;
87 
88 	info->status.ampdu_len = 1;
89 	info->status.ampdu_ack_len = st->success;
90 
91 	if (st->is_probe)
92 		info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
93 
94 	if (st->aggr)
95 		info->flags |= IEEE80211_TX_CTL_AMPDU |
96 			       IEEE80211_TX_STAT_AMPDU;
97 
98 	if (!st->ack_req)
99 		info->flags |= IEEE80211_TX_CTL_NO_ACK;
100 	else if (st->success)
101 		info->flags |= IEEE80211_TX_STAT_ACK;
102 }
103 
104 u16 mt76_mac_tx_rate_val(struct mt7601u_dev *dev,
105 			 const struct ieee80211_tx_rate *rate, u8 *nss_val)
106 {
107 	u16 rateval;
108 	u8 phy, rate_idx;
109 	u8 nss = 1;
110 	u8 bw = 0;
111 
112 	if (rate->flags & IEEE80211_TX_RC_MCS) {
113 		rate_idx = rate->idx;
114 		nss = 1 + (rate->idx >> 3);
115 		phy = MT_PHY_TYPE_HT;
116 		if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD)
117 			phy = MT_PHY_TYPE_HT_GF;
118 		if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
119 			bw = 1;
120 	} else {
121 		const struct ieee80211_rate *r;
122 		int band = dev->chandef.chan->band;
123 		u16 val;
124 
125 		r = &dev->hw->wiphy->bands[band]->bitrates[rate->idx];
126 		if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
127 			val = r->hw_value_short;
128 		else
129 			val = r->hw_value;
130 
131 		phy = val >> 8;
132 		rate_idx = val & 0xff;
133 		bw = 0;
134 	}
135 
136 	rateval = FIELD_PREP(MT_RXWI_RATE_MCS, rate_idx);
137 	rateval |= FIELD_PREP(MT_RXWI_RATE_PHY, phy);
138 	rateval |= FIELD_PREP(MT_RXWI_RATE_BW, bw);
139 	if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
140 		rateval |= MT_RXWI_RATE_SGI;
141 
142 	*nss_val = nss;
143 	return rateval;
144 }
145 
146 void mt76_mac_wcid_set_rate(struct mt7601u_dev *dev, struct mt76_wcid *wcid,
147 			    const struct ieee80211_tx_rate *rate)
148 {
149 	unsigned long flags;
150 
151 	spin_lock_irqsave(&dev->lock, flags);
152 	wcid->tx_rate = mt76_mac_tx_rate_val(dev, rate, &wcid->tx_rate_nss);
153 	wcid->tx_rate_set = true;
154 	spin_unlock_irqrestore(&dev->lock, flags);
155 }
156 
157 struct mt76_tx_status mt7601u_mac_fetch_tx_status(struct mt7601u_dev *dev)
158 {
159 	struct mt76_tx_status stat = {};
160 	u32 val;
161 
162 	val = mt7601u_rr(dev, MT_TX_STAT_FIFO);
163 	stat.valid = !!(val & MT_TX_STAT_FIFO_VALID);
164 	stat.success = !!(val & MT_TX_STAT_FIFO_SUCCESS);
165 	stat.aggr = !!(val & MT_TX_STAT_FIFO_AGGR);
166 	stat.ack_req = !!(val & MT_TX_STAT_FIFO_ACKREQ);
167 	stat.pktid = FIELD_GET(MT_TX_STAT_FIFO_PID_TYPE, val);
168 	stat.wcid = FIELD_GET(MT_TX_STAT_FIFO_WCID, val);
169 	stat.rate = FIELD_GET(MT_TX_STAT_FIFO_RATE, val);
170 
171 	return stat;
172 }
173 
174 void mt76_send_tx_status(struct mt7601u_dev *dev, struct mt76_tx_status *stat)
175 {
176 	struct ieee80211_tx_info info = {};
177 	struct ieee80211_sta *sta = NULL;
178 	struct mt76_wcid *wcid = NULL;
179 	void *msta;
180 
181 	rcu_read_lock();
182 	if (stat->wcid < ARRAY_SIZE(dev->wcid))
183 		wcid = rcu_dereference(dev->wcid[stat->wcid]);
184 
185 	if (wcid) {
186 		msta = container_of(wcid, struct mt76_sta, wcid);
187 		sta = container_of(msta, struct ieee80211_sta,
188 				   drv_priv);
189 	}
190 
191 	mt76_mac_fill_tx_status(dev, &info, stat);
192 
193 	spin_lock_bh(&dev->mac_lock);
194 	ieee80211_tx_status_noskb(dev->hw, sta, &info);
195 	spin_unlock_bh(&dev->mac_lock);
196 
197 	rcu_read_unlock();
198 }
199 
200 void mt7601u_mac_set_protection(struct mt7601u_dev *dev, bool legacy_prot,
201 				int ht_mode)
202 {
203 	int mode = ht_mode & IEEE80211_HT_OP_MODE_PROTECTION;
204 	bool non_gf = !!(ht_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
205 	u32 prot[6];
206 	bool ht_rts[4] = {};
207 	int i;
208 
209 	prot[0] = MT_PROT_NAV_SHORT |
210 		  MT_PROT_TXOP_ALLOW_ALL |
211 		  MT_PROT_RTS_THR_EN;
212 	prot[1] = prot[0];
213 	if (legacy_prot)
214 		prot[1] |= MT_PROT_CTRL_CTS2SELF;
215 
216 	prot[2] = prot[4] = MT_PROT_NAV_SHORT | MT_PROT_TXOP_ALLOW_BW20;
217 	prot[3] = prot[5] = MT_PROT_NAV_SHORT | MT_PROT_TXOP_ALLOW_ALL;
218 
219 	if (legacy_prot) {
220 		prot[2] |= MT_PROT_RATE_CCK_11;
221 		prot[3] |= MT_PROT_RATE_CCK_11;
222 		prot[4] |= MT_PROT_RATE_CCK_11;
223 		prot[5] |= MT_PROT_RATE_CCK_11;
224 	} else {
225 		prot[2] |= MT_PROT_RATE_OFDM_24;
226 		prot[3] |= MT_PROT_RATE_DUP_OFDM_24;
227 		prot[4] |= MT_PROT_RATE_OFDM_24;
228 		prot[5] |= MT_PROT_RATE_DUP_OFDM_24;
229 	}
230 
231 	switch (mode) {
232 	case IEEE80211_HT_OP_MODE_PROTECTION_NONE:
233 		break;
234 
235 	case IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER:
236 		ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
237 		break;
238 
239 	case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ:
240 		ht_rts[1] = ht_rts[3] = true;
241 		break;
242 
243 	case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED:
244 		ht_rts[0] = ht_rts[1] = ht_rts[2] = ht_rts[3] = true;
245 		break;
246 	}
247 
248 	if (non_gf)
249 		ht_rts[2] = ht_rts[3] = true;
250 
251 	for (i = 0; i < 4; i++)
252 		if (ht_rts[i])
253 			prot[i + 2] |= MT_PROT_CTRL_RTS_CTS;
254 
255 	for (i = 0; i < 6; i++)
256 		mt7601u_wr(dev, MT_CCK_PROT_CFG + i * 4, prot[i]);
257 }
258 
259 void mt7601u_mac_set_short_preamble(struct mt7601u_dev *dev, bool short_preamb)
260 {
261 	if (short_preamb)
262 		mt76_set(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);
263 	else
264 		mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);
265 }
266 
267 void mt7601u_mac_config_tsf(struct mt7601u_dev *dev, bool enable, int interval)
268 {
269 	u32 val = mt7601u_rr(dev, MT_BEACON_TIME_CFG);
270 
271 	val &= ~(MT_BEACON_TIME_CFG_TIMER_EN |
272 		 MT_BEACON_TIME_CFG_SYNC_MODE |
273 		 MT_BEACON_TIME_CFG_TBTT_EN);
274 
275 	if (!enable) {
276 		mt7601u_wr(dev, MT_BEACON_TIME_CFG, val);
277 		return;
278 	}
279 
280 	val &= ~MT_BEACON_TIME_CFG_INTVAL;
281 	val |= FIELD_PREP(MT_BEACON_TIME_CFG_INTVAL, interval << 4) |
282 		MT_BEACON_TIME_CFG_TIMER_EN |
283 		MT_BEACON_TIME_CFG_SYNC_MODE |
284 		MT_BEACON_TIME_CFG_TBTT_EN;
285 }
286 
287 static void mt7601u_check_mac_err(struct mt7601u_dev *dev)
288 {
289 	u32 val = mt7601u_rr(dev, 0x10f4);
290 
291 	if (!(val & BIT(29)) || !(val & (BIT(7) | BIT(5))))
292 		return;
293 
294 	dev_err(dev->dev, "Error: MAC specific condition occurred\n");
295 
296 	mt76_set(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
297 	udelay(10);
298 	mt76_clear(dev, MT_MAC_SYS_CTRL, MT_MAC_SYS_CTRL_RESET_CSR);
299 }
300 
301 void mt7601u_mac_work(struct work_struct *work)
302 {
303 	struct mt7601u_dev *dev = container_of(work, struct mt7601u_dev,
304 					       mac_work.work);
305 	struct {
306 		u32 addr_base;
307 		u32 span;
308 		u64 *stat_base;
309 	} spans[] = {
310 		{ MT_RX_STA_CNT0,	3,	dev->stats.rx_stat },
311 		{ MT_TX_STA_CNT0,	3,	dev->stats.tx_stat },
312 		{ MT_TX_AGG_STAT,	1,	dev->stats.aggr_stat },
313 		{ MT_MPDU_DENSITY_CNT,	1,	dev->stats.zero_len_del },
314 		{ MT_TX_AGG_CNT_BASE0,	8,	&dev->stats.aggr_n[0] },
315 		{ MT_TX_AGG_CNT_BASE1,	8,	&dev->stats.aggr_n[16] },
316 	};
317 	u32 sum, n;
318 	int i, j, k;
319 
320 	/* Note: using MCU_RANDOM_READ is actually slower then reading all the
321 	 *	 registers by hand.  MCU takes ca. 20ms to complete read of 24
322 	 *	 registers while reading them one by one will takes roughly
323 	 *	 24*200us =~ 5ms.
324 	 */
325 
326 	k = 0;
327 	n = 0;
328 	sum = 0;
329 	for (i = 0; i < ARRAY_SIZE(spans); i++)
330 		for (j = 0; j < spans[i].span; j++) {
331 			u32 val = mt7601u_rr(dev, spans[i].addr_base + j * 4);
332 
333 			spans[i].stat_base[j * 2] += val & 0xffff;
334 			spans[i].stat_base[j * 2 + 1] += val >> 16;
335 
336 			/* Calculate average AMPDU length */
337 			if (spans[i].addr_base != MT_TX_AGG_CNT_BASE0 &&
338 			    spans[i].addr_base != MT_TX_AGG_CNT_BASE1)
339 				continue;
340 
341 			n += (val >> 16) + (val & 0xffff);
342 			sum += (val & 0xffff) * (1 + k * 2) +
343 				(val >> 16) * (2 + k * 2);
344 			k++;
345 		}
346 
347 	atomic_set(&dev->avg_ampdu_len, n ? DIV_ROUND_CLOSEST(sum, n) : 1);
348 
349 	mt7601u_check_mac_err(dev);
350 
351 	ieee80211_queue_delayed_work(dev->hw, &dev->mac_work, 10 * HZ);
352 }
353 
354 void
355 mt7601u_mac_wcid_setup(struct mt7601u_dev *dev, u8 idx, u8 vif_idx, u8 *mac)
356 {
357 	u8 zmac[ETH_ALEN] = {};
358 	u32 attr;
359 
360 	attr = FIELD_PREP(MT_WCID_ATTR_BSS_IDX, vif_idx & 7) |
361 	       FIELD_PREP(MT_WCID_ATTR_BSS_IDX_EXT, !!(vif_idx & 8));
362 
363 	mt76_wr(dev, MT_WCID_ATTR(idx), attr);
364 
365 	if (mac)
366 		memcpy(zmac, mac, sizeof(zmac));
367 
368 	mt7601u_addr_wr(dev, MT_WCID_ADDR(idx), zmac);
369 }
370 
371 void mt7601u_mac_set_ampdu_factor(struct mt7601u_dev *dev)
372 {
373 	struct ieee80211_sta *sta;
374 	struct mt76_wcid *wcid;
375 	void *msta;
376 	u8 min_factor = 3;
377 	int i;
378 
379 	rcu_read_lock();
380 	for (i = 0; i < ARRAY_SIZE(dev->wcid); i++) {
381 		wcid = rcu_dereference(dev->wcid[i]);
382 		if (!wcid)
383 			continue;
384 
385 		msta = container_of(wcid, struct mt76_sta, wcid);
386 		sta = container_of(msta, struct ieee80211_sta, drv_priv);
387 
388 		min_factor = min(min_factor, sta->ht_cap.ampdu_factor);
389 	}
390 	rcu_read_unlock();
391 
392 	mt7601u_wr(dev, MT_MAX_LEN_CFG, 0xa0fff |
393 		   FIELD_PREP(MT_MAX_LEN_CFG_AMPDU, min_factor));
394 }
395 
396 static void
397 mt76_mac_process_rate(struct ieee80211_rx_status *status, u16 rate)
398 {
399 	u8 idx = FIELD_GET(MT_RXWI_RATE_MCS, rate);
400 
401 	switch (FIELD_GET(MT_RXWI_RATE_PHY, rate)) {
402 	case MT_PHY_TYPE_OFDM:
403 		if (WARN_ON(idx >= 8))
404 			idx = 0;
405 		idx += 4;
406 
407 		status->rate_idx = idx;
408 		return;
409 	case MT_PHY_TYPE_CCK:
410 		if (idx >= 8) {
411 			idx -= 8;
412 			status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
413 		}
414 
415 		if (WARN_ON(idx >= 4))
416 			idx = 0;
417 
418 		status->rate_idx = idx;
419 		return;
420 	case MT_PHY_TYPE_HT_GF:
421 		status->enc_flags |= RX_ENC_FLAG_HT_GF;
422 		/* fall through */
423 	case MT_PHY_TYPE_HT:
424 		status->encoding = RX_ENC_HT;
425 		status->rate_idx = idx;
426 		break;
427 	default:
428 		WARN_ON(1);
429 		return;
430 	}
431 
432 	if (rate & MT_RXWI_RATE_SGI)
433 		status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
434 
435 	if (rate & MT_RXWI_RATE_STBC)
436 		status->enc_flags |= 1 << RX_ENC_FLAG_STBC_SHIFT;
437 
438 	if (rate & MT_RXWI_RATE_BW)
439 		status->bw = RATE_INFO_BW_40;
440 }
441 
442 static void
443 mt7601u_rx_monitor_beacon(struct mt7601u_dev *dev, struct mt7601u_rxwi *rxwi,
444 			  u16 rate, int rssi)
445 {
446 	dev->bcn_freq_off = rxwi->freq_off;
447 	dev->bcn_phy_mode = FIELD_GET(MT_RXWI_RATE_PHY, rate);
448 	ewma_rssi_add(&dev->avg_rssi, -rssi);
449 }
450 
451 static int
452 mt7601u_rx_is_our_beacon(struct mt7601u_dev *dev, u8 *data)
453 {
454 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data;
455 
456 	return ieee80211_is_beacon(hdr->frame_control) &&
457 		ether_addr_equal(hdr->addr2, dev->ap_bssid);
458 }
459 
460 u32 mt76_mac_process_rx(struct mt7601u_dev *dev, struct sk_buff *skb,
461 			u8 *data, void *rxi)
462 {
463 	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
464 	struct mt7601u_rxwi *rxwi = rxi;
465 	u32 len, ctl = le32_to_cpu(rxwi->ctl);
466 	u16 rate = le16_to_cpu(rxwi->rate);
467 	int rssi;
468 
469 	len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
470 	if (len < 10)
471 		return 0;
472 
473 	if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_DECRYPT)) {
474 		status->flag |= RX_FLAG_DECRYPTED;
475 		status->flag |= RX_FLAG_MMIC_STRIPPED;
476 		status->flag |= RX_FLAG_MIC_STRIPPED;
477 		status->flag |= RX_FLAG_ICV_STRIPPED;
478 		status->flag |= RX_FLAG_IV_STRIPPED;
479 	}
480 	/* let mac80211 take care of PN validation since apparently
481 	 * the hardware does not support it
482 	 */
483 	if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_PN_LEN))
484 		status->flag &= ~RX_FLAG_IV_STRIPPED;
485 
486 	status->chains = BIT(0);
487 	rssi = mt7601u_phy_get_rssi(dev, rxwi, rate);
488 	status->chain_signal[0] = status->signal = rssi;
489 	status->freq = dev->chandef.chan->center_freq;
490 	status->band = dev->chandef.chan->band;
491 
492 	mt76_mac_process_rate(status, rate);
493 
494 	spin_lock_bh(&dev->con_mon_lock);
495 	if (mt7601u_rx_is_our_beacon(dev, data))
496 		mt7601u_rx_monitor_beacon(dev, rxwi, rate, rssi);
497 	else if (rxwi->rxinfo & cpu_to_le32(MT_RXINFO_U2M))
498 		ewma_rssi_add(&dev->avg_rssi, -rssi);
499 	spin_unlock_bh(&dev->con_mon_lock);
500 
501 	return len;
502 }
503 
504 static enum mt76_cipher_type
505 mt76_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
506 {
507 	memset(key_data, 0, 32);
508 	if (!key)
509 		return MT_CIPHER_NONE;
510 
511 	if (key->keylen > 32)
512 		return MT_CIPHER_NONE;
513 
514 	memcpy(key_data, key->key, key->keylen);
515 
516 	switch (key->cipher) {
517 	case WLAN_CIPHER_SUITE_WEP40:
518 		return MT_CIPHER_WEP40;
519 	case WLAN_CIPHER_SUITE_WEP104:
520 		return MT_CIPHER_WEP104;
521 	case WLAN_CIPHER_SUITE_TKIP:
522 		return MT_CIPHER_TKIP;
523 	case WLAN_CIPHER_SUITE_CCMP:
524 		return MT_CIPHER_AES_CCMP;
525 	default:
526 		return MT_CIPHER_NONE;
527 	}
528 }
529 
530 int mt76_mac_wcid_set_key(struct mt7601u_dev *dev, u8 idx,
531 			  struct ieee80211_key_conf *key)
532 {
533 	enum mt76_cipher_type cipher;
534 	u8 key_data[32];
535 	u8 iv_data[8];
536 	u32 val;
537 
538 	cipher = mt76_mac_get_key_info(key, key_data);
539 	if (cipher == MT_CIPHER_NONE && key)
540 		return -EINVAL;
541 
542 	trace_set_key(dev, idx);
543 
544 	mt7601u_wr_copy(dev, MT_WCID_KEY(idx), key_data, sizeof(key_data));
545 
546 	memset(iv_data, 0, sizeof(iv_data));
547 	if (key) {
548 		iv_data[3] = key->keyidx << 6;
549 		if (cipher >= MT_CIPHER_TKIP) {
550 			/* Note: start with 1 to comply with spec,
551 			 *	 (see comment on common/cmm_wpa.c:4291).
552 			 */
553 			iv_data[0] |= 1;
554 			iv_data[3] |= 0x20;
555 		}
556 	}
557 	mt7601u_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data));
558 
559 	val = mt7601u_rr(dev, MT_WCID_ATTR(idx));
560 	val &= ~MT_WCID_ATTR_PKEY_MODE & ~MT_WCID_ATTR_PKEY_MODE_EXT;
561 	val |= FIELD_PREP(MT_WCID_ATTR_PKEY_MODE, cipher & 7) |
562 	       FIELD_PREP(MT_WCID_ATTR_PKEY_MODE_EXT, cipher >> 3);
563 	val &= ~MT_WCID_ATTR_PAIRWISE;
564 	val |= MT_WCID_ATTR_PAIRWISE *
565 		!!(key && key->flags & IEEE80211_KEY_FLAG_PAIRWISE);
566 	mt7601u_wr(dev, MT_WCID_ATTR(idx), val);
567 
568 	return 0;
569 }
570 
571 int mt76_mac_shared_key_setup(struct mt7601u_dev *dev, u8 vif_idx, u8 key_idx,
572 			      struct ieee80211_key_conf *key)
573 {
574 	enum mt76_cipher_type cipher;
575 	u8 key_data[32];
576 	u32 val;
577 
578 	cipher = mt76_mac_get_key_info(key, key_data);
579 	if (cipher == MT_CIPHER_NONE && key)
580 		return -EINVAL;
581 
582 	trace_set_shared_key(dev, vif_idx, key_idx);
583 
584 	mt7601u_wr_copy(dev, MT_SKEY(vif_idx, key_idx),
585 			key_data, sizeof(key_data));
586 
587 	val = mt76_rr(dev, MT_SKEY_MODE(vif_idx));
588 	val &= ~(MT_SKEY_MODE_MASK << MT_SKEY_MODE_SHIFT(vif_idx, key_idx));
589 	val |= cipher << MT_SKEY_MODE_SHIFT(vif_idx, key_idx);
590 	mt76_wr(dev, MT_SKEY_MODE(vif_idx), val);
591 
592 	return 0;
593 }
594