brintos

brintos / linux-shallow public Read only

0
0
Text · 14.7 KiB · ca9cf62 Raw
594 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*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 11void 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 27static void28mt76_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		fallthrough;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 65static void66mt76_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 104u16 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		else129			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 146void 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 157struct 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 174void 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 200void 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 259void 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	else264		mt76_clear(dev, MT_AUTO_RSP_CFG, MT_AUTO_RSP_PREAMB_SHORT);265}266 267void 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 287static 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 301void 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 the321	 *	 registers by hand.  MCU takes ca. 20ms to complete read of 24322	 *	 registers while reading them one by one will takes roughly323	 *	 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 354void355mt7601u_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 371void 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->deflink.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 396static void397mt76_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		fallthrough;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 442static void443mt7601u_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 451static int452mt7601u_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 460u32 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 apparently481	 * the hardware does not support it482	 */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 504static enum mt76_cipher_type505mt76_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 530int 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 571int 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