root/drivers/net/wireless/mediatek/mt7601u/mac.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mt7601u_set_macaddr
  2. mt76_mac_process_tx_rate
  3. mt76_mac_fill_tx_status
  4. mt76_mac_tx_rate_val
  5. mt76_mac_wcid_set_rate
  6. mt7601u_mac_fetch_tx_status
  7. mt76_send_tx_status
  8. mt7601u_mac_set_protection
  9. mt7601u_mac_set_short_preamble
  10. mt7601u_mac_config_tsf
  11. mt7601u_check_mac_err
  12. mt7601u_mac_work
  13. mt7601u_mac_wcid_setup
  14. mt7601u_mac_set_ampdu_factor
  15. mt76_mac_process_rate
  16. mt7601u_rx_monitor_beacon
  17. mt7601u_rx_is_our_beacon
  18. mt76_mac_process_rx
  19. mt76_mac_get_key_info
  20. mt76_mac_wcid_set_key
  21. mt76_mac_shared_key_setup

   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 }

/* [<][>][^][v][top][bottom][index][help] */