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