mt76: add mt76x2_mac_common to mt76x2-common module
authorLorenzo Bianconi <lorenzo.bianconi@redhat.com>
Tue, 31 Jul 2018 08:09:14 +0000 (10:09 +0200)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 2 Aug 2018 18:48:08 +0000 (21:48 +0300)
Move mac related code shared between mt76x2 and mt76x2u in
mt76x2-common module

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/mediatek/mt76/Makefile
drivers/net/wireless/mediatek/mt76/mt76x2.h
drivers/net/wireless/mediatek/mt76/mt76x2_init.c
drivers/net/wireless/mediatek/mt76/mt76x2_mac.c
drivers/net/wireless/mediatek/mt76/mt76x2_mac_common.c [new file with mode: 0644]
drivers/net/wireless/mediatek/mt76/mt76x2_phy.c

index e1226aae82fa3f42f5b9c06abcce92a9a2563d5f..bedb671200ea09fe15453c03c705a05ed0358ff0 100644 (file)
@@ -8,7 +8,7 @@ mt76-y := \
 CFLAGS_trace.o := -I$(src)
 
 mt76x2-common-y := \
-       mt76x2_eeprom.o mt76x2_tx_common.o
+       mt76x2_eeprom.o mt76x2_tx_common.o mt76x2_mac_common.o
 
 mt76x2e-y := \
        mt76x2_pci.o mt76x2_dma.o \
index af9259cd6d423d6bc38bde1f1749aaeb1589e8cc..6c5dd106057d82364b82002bbc32c062c3fa0e64 100644 (file)
@@ -235,7 +235,7 @@ void mt76x2_phy_set_antenna(struct mt76x2_dev *dev);
 int mt76x2_phy_start(struct mt76x2_dev *dev);
 int mt76x2_phy_set_channel(struct mt76x2_dev *dev,
                         struct cfg80211_chan_def *chandef);
-int mt76x2_phy_get_rssi(struct mt76x2_dev *dev, s8 rssi, int chain);
+int mt76x2_mac_get_rssi(struct mt76x2_dev *dev, s8 rssi, int chain);
 void mt76x2_phy_calibrate(struct work_struct *work);
 void mt76x2_phy_set_txpower(struct mt76x2_dev *dev);
 
@@ -282,4 +282,9 @@ void mt76x2_tx_set_txpwr_auto(struct mt76x2_dev *dev, s8 txpwr);
 
 int mt76x2_insert_hdr_pad(struct sk_buff *skb);
 
+bool mt76x2_mac_load_tx_status(struct mt76x2_dev *dev,
+                              struct mt76x2_tx_status *stat);
+void mt76x2_send_tx_status(struct mt76x2_dev *dev,
+                          struct mt76x2_tx_status *stat, u8 *update);
+
 #endif
index d3eedd9c59b78278fbd717fee6827136cf8ac983..309e55cf347ca455797fa40b43b39f5a750371f0 100644 (file)
@@ -338,41 +338,6 @@ int mt76x2_mac_start(struct mt76x2_dev *dev)
        return 0;
 }
 
-void mt76x2_mac_stop(struct mt76x2_dev *dev, bool force)
-{
-       bool stopped = false;
-       u32 rts_cfg;
-       int i;
-
-       mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
-
-       rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG);
-       mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT);
-
-       /* Wait for MAC to become idle */
-       for (i = 0; i < 300; i++) {
-               if ((mt76_rr(dev, MT_MAC_STATUS) &
-                    (MT_MAC_STATUS_RX | MT_MAC_STATUS_TX)) ||
-                   mt76_rr(dev, MT_BBP(IBI, 12))) {
-                       udelay(1);
-                       continue;
-               }
-
-               stopped = true;
-               break;
-       }
-
-       if (force && !stopped) {
-               mt76_set(dev, MT_BBP(CORE, 4), BIT(1));
-               mt76_clear(dev, MT_BBP(CORE, 4), BIT(1));
-
-               mt76_set(dev, MT_BBP(CORE, 4), BIT(0));
-               mt76_clear(dev, MT_BBP(CORE, 4), BIT(0));
-       }
-
-       mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg);
-}
-
 void mt76x2_mac_resume(struct mt76x2_dev *dev)
 {
        mt76_wr(dev, MT_MAC_SYS_CTRL,
index 010c1cbfcd6ceb444c8c498f1b3ea6fb68235b3a..23cf437d14f96cbe3d39cd3fcb3a81ba4ae5b9a6 100644 (file)
@@ -28,535 +28,6 @@ void mt76x2_mac_set_bssid(struct mt76x2_dev *dev, u8 idx, const u8 *addr)
                       get_unaligned_le16(addr + 4));
 }
 
-static int
-mt76x2_mac_process_rate(struct mt76_rx_status *status, u16 rate)
-{
-       u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate);
-
-       switch (FIELD_GET(MT_RXWI_RATE_PHY, rate)) {
-       case MT_PHY_TYPE_OFDM:
-               if (idx >= 8)
-                       idx = 0;
-
-               if (status->band == NL80211_BAND_2GHZ)
-                       idx += 4;
-
-               status->rate_idx = idx;
-               return 0;
-       case MT_PHY_TYPE_CCK:
-               if (idx >= 8) {
-                       idx -= 8;
-                       status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
-               }
-
-               if (idx >= 4)
-                       idx = 0;
-
-               status->rate_idx = idx;
-               return 0;
-       case MT_PHY_TYPE_HT_GF:
-               status->enc_flags |= RX_ENC_FLAG_HT_GF;
-               /* fall through */
-       case MT_PHY_TYPE_HT:
-               status->encoding = RX_ENC_HT;
-               status->rate_idx = idx;
-               break;
-       case MT_PHY_TYPE_VHT:
-               status->encoding = RX_ENC_VHT;
-               status->rate_idx = FIELD_GET(MT_RATE_INDEX_VHT_IDX, idx);
-               status->nss = FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (rate & MT_RXWI_RATE_LDPC)
-               status->enc_flags |= RX_ENC_FLAG_LDPC;
-
-       if (rate & MT_RXWI_RATE_SGI)
-               status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
-
-       if (rate & MT_RXWI_RATE_STBC)
-               status->enc_flags |= 1 << RX_ENC_FLAG_STBC_SHIFT;
-
-       switch (FIELD_GET(MT_RXWI_RATE_BW, rate)) {
-       case MT_PHY_BW_20:
-               break;
-       case MT_PHY_BW_40:
-               status->bw = RATE_INFO_BW_40;
-               break;
-       case MT_PHY_BW_80:
-               status->bw = RATE_INFO_BW_80;
-               break;
-       default:
-               break;
-       }
-
-       return 0;
-}
-
-static __le16
-mt76x2_mac_tx_rate_val(struct mt76x2_dev *dev,
-                      const struct ieee80211_tx_rate *rate, u8 *nss_val)
-{
-       u16 rateval;
-       u8 phy, rate_idx;
-       u8 nss = 1;
-       u8 bw = 0;
-
-       if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
-               rate_idx = rate->idx;
-               nss = 1 + (rate->idx >> 4);
-               phy = MT_PHY_TYPE_VHT;
-               if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
-                       bw = 2;
-               else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-                       bw = 1;
-       } else if (rate->flags & IEEE80211_TX_RC_MCS) {
-               rate_idx = rate->idx;
-               nss = 1 + (rate->idx >> 3);
-               phy = MT_PHY_TYPE_HT;
-               if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD)
-                       phy = MT_PHY_TYPE_HT_GF;
-               if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-                       bw = 1;
-       } else {
-               const struct ieee80211_rate *r;
-               int band = dev->mt76.chandef.chan->band;
-               u16 val;
-
-               r = &mt76_hw(dev)->wiphy->bands[band]->bitrates[rate->idx];
-               if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-                       val = r->hw_value_short;
-               else
-                       val = r->hw_value;
-
-               phy = val >> 8;
-               rate_idx = val & 0xff;
-               bw = 0;
-       }
-
-       rateval = FIELD_PREP(MT_RXWI_RATE_INDEX, rate_idx);
-       rateval |= FIELD_PREP(MT_RXWI_RATE_PHY, phy);
-       rateval |= FIELD_PREP(MT_RXWI_RATE_BW, bw);
-       if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
-               rateval |= MT_RXWI_RATE_SGI;
-
-       *nss_val = nss;
-       return cpu_to_le16(rateval);
-}
-
-void mt76x2_mac_wcid_set_drop(struct mt76x2_dev *dev, u8 idx, bool drop)
-{
-       u32 val = mt76_rr(dev, MT_WCID_DROP(idx));
-       u32 bit = MT_WCID_DROP_MASK(idx);
-
-       /* prevent unnecessary writes */
-       if ((val & bit) != (bit * drop))
-               mt76_wr(dev, MT_WCID_DROP(idx), (val & ~bit) | (bit * drop));
-}
-
-void mt76x2_mac_wcid_set_rate(struct mt76x2_dev *dev, struct mt76_wcid *wcid,
-                             const struct ieee80211_tx_rate *rate)
-{
-       spin_lock_bh(&dev->mt76.lock);
-       wcid->tx_rate = mt76x2_mac_tx_rate_val(dev, rate, &wcid->tx_rate_nss);
-       wcid->tx_rate_set = true;
-       spin_unlock_bh(&dev->mt76.lock);
-}
-
-void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
-                          struct sk_buff *skb, struct mt76_wcid *wcid,
-                          struct ieee80211_sta *sta, int len)
-{
-       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-       struct ieee80211_tx_rate *rate = &info->control.rates[0];
-       struct ieee80211_key_conf *key = info->control.hw_key;
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-       u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2));
-       u16 txwi_flags = 0;
-       u8 nss;
-       s8 txpwr_adj, max_txpwr_adj;
-       u8 ccmp_pn[8];
-
-       memset(txwi, 0, sizeof(*txwi));
-
-       if (wcid)
-               txwi->wcid = wcid->idx;
-       else
-               txwi->wcid = 0xff;
-
-       txwi->pktid = 1;
-
-       if (wcid && wcid->sw_iv && key) {
-               u64 pn = atomic64_inc_return(&key->tx_pn);
-               ccmp_pn[0] = pn;
-               ccmp_pn[1] = pn >> 8;
-               ccmp_pn[2] = 0;
-               ccmp_pn[3] = 0x20 | (key->keyidx << 6);
-               ccmp_pn[4] = pn >> 16;
-               ccmp_pn[5] = pn >> 24;
-               ccmp_pn[6] = pn >> 32;
-               ccmp_pn[7] = pn >> 40;
-               txwi->iv = *((__le32 *)&ccmp_pn[0]);
-               txwi->eiv = *((__le32 *)&ccmp_pn[1]);
-       }
-
-       spin_lock_bh(&dev->mt76.lock);
-       if (wcid && (rate->idx < 0 || !rate->count)) {
-               txwi->rate = wcid->tx_rate;
-               max_txpwr_adj = wcid->max_txpwr_adj;
-               nss = wcid->tx_rate_nss;
-       } else {
-               txwi->rate = mt76x2_mac_tx_rate_val(dev, rate, &nss);
-               max_txpwr_adj = mt76x2_tx_get_max_txpwr_adj(dev, rate);
-       }
-       spin_unlock_bh(&dev->mt76.lock);
-
-       txpwr_adj = mt76x2_tx_get_txpwr_adj(dev, dev->txpower_conf,
-                                           max_txpwr_adj);
-       txwi->ctl2 = FIELD_PREP(MT_TX_PWR_ADJ, txpwr_adj);
-
-       if (mt76xx_rev(dev) >= MT76XX_REV_E4)
-               txwi->txstream = 0x13;
-       else if (mt76xx_rev(dev) >= MT76XX_REV_E3 &&
-                !(txwi->rate & cpu_to_le16(rate_ht_mask)))
-               txwi->txstream = 0x93;
-
-       if (info->flags & IEEE80211_TX_CTL_LDPC)
-               txwi->rate |= cpu_to_le16(MT_RXWI_RATE_LDPC);
-       if ((info->flags & IEEE80211_TX_CTL_STBC) && nss == 1)
-               txwi->rate |= cpu_to_le16(MT_RXWI_RATE_STBC);
-       if (nss > 1 && sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC)
-               txwi_flags |= MT_TXWI_FLAGS_MMPS;
-       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
-               txwi->ack_ctl |= MT_TXWI_ACK_CTL_REQ;
-       if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
-               txwi->ack_ctl |= MT_TXWI_ACK_CTL_NSEQ;
-       if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
-               txwi->pktid |= MT_TXWI_PKTID_PROBE;
-       if ((info->flags & IEEE80211_TX_CTL_AMPDU) && sta) {
-               u8 ba_size = IEEE80211_MIN_AMPDU_BUF;
-
-               ba_size <<= sta->ht_cap.ampdu_factor;
-               ba_size = min_t(int, 63, ba_size - 1);
-               if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
-                       ba_size = 0;
-               txwi->ack_ctl |= FIELD_PREP(MT_TXWI_ACK_CTL_BA_WINDOW, ba_size);
-
-               txwi_flags |= MT_TXWI_FLAGS_AMPDU |
-                        FIELD_PREP(MT_TXWI_FLAGS_MPDU_DENSITY,
-                                   sta->ht_cap.ampdu_density);
-       }
-
-       if (ieee80211_is_probe_resp(hdr->frame_control) ||
-           ieee80211_is_beacon(hdr->frame_control))
-               txwi_flags |= MT_TXWI_FLAGS_TS;
-
-       txwi->flags |= cpu_to_le16(txwi_flags);
-       txwi->len_ctl = cpu_to_le16(len);
-}
-
-static void mt76x2_remove_hdr_pad(struct sk_buff *skb, int len)
-{
-       int hdrlen;
-
-       if (!len)
-               return;
-
-       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-       memmove(skb->data + len, skb->data, hdrlen);
-       skb_pull(skb, len);
-}
-
-static struct mt76x2_sta *
-mt76x2_rx_get_sta(struct mt76x2_dev *dev, u8 idx)
-{
-       struct mt76_wcid *wcid;
-
-       if (idx >= ARRAY_SIZE(dev->wcid))
-               return NULL;
-
-       wcid = rcu_dereference(dev->wcid[idx]);
-       if (!wcid)
-               return NULL;
-
-       return container_of(wcid, struct mt76x2_sta, wcid);
-}
-
-static struct mt76_wcid *
-mt76x2_rx_get_sta_wcid(struct mt76x2_dev *dev, struct mt76x2_sta *sta, bool unicast)
-{
-       if (!sta)
-               return NULL;
-
-       if (unicast)
-               return &sta->wcid;
-       else
-               return &sta->vif->group_wcid;
-}
-
-int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb,
-                         void *rxi)
-{
-       struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb;
-       struct mt76x2_rxwi *rxwi = rxi;
-       struct mt76x2_sta *sta;
-       u32 rxinfo = le32_to_cpu(rxwi->rxinfo);
-       u32 ctl = le32_to_cpu(rxwi->ctl);
-       u16 rate = le16_to_cpu(rxwi->rate);
-       u16 tid_sn = le16_to_cpu(rxwi->tid_sn);
-       bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST);
-       int pad_len = 0;
-       u8 pn_len;
-       u8 wcid;
-       int len;
-
-       if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
-               return -EINVAL;
-
-       if (rxinfo & MT_RXINFO_L2PAD)
-               pad_len += 2;
-
-       if (rxinfo & MT_RXINFO_DECRYPT) {
-               status->flag |= RX_FLAG_DECRYPTED;
-               status->flag |= RX_FLAG_MMIC_STRIPPED;
-               status->flag |= RX_FLAG_MIC_STRIPPED;
-               status->flag |= RX_FLAG_IV_STRIPPED;
-       }
-
-       wcid = FIELD_GET(MT_RXWI_CTL_WCID, ctl);
-       sta = mt76x2_rx_get_sta(dev, wcid);
-       status->wcid = mt76x2_rx_get_sta_wcid(dev, sta, unicast);
-
-       len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
-       pn_len = FIELD_GET(MT_RXINFO_PN_LEN, rxinfo);
-       if (pn_len) {
-               int offset = ieee80211_get_hdrlen_from_skb(skb) + pad_len;
-               u8 *data = skb->data + offset;
-
-               status->iv[0] = data[7];
-               status->iv[1] = data[6];
-               status->iv[2] = data[5];
-               status->iv[3] = data[4];
-               status->iv[4] = data[1];
-               status->iv[5] = data[0];
-
-               /*
-                * Driver CCMP validation can't deal with fragments.
-                * Let mac80211 take care of it.
-                */
-               if (rxinfo & MT_RXINFO_FRAG) {
-                       status->flag &= ~RX_FLAG_IV_STRIPPED;
-               } else {
-                       pad_len += pn_len << 2;
-                       len -= pn_len << 2;
-               }
-       }
-
-       mt76x2_remove_hdr_pad(skb, pad_len);
-
-       if ((rxinfo & MT_RXINFO_BA) && !(rxinfo & MT_RXINFO_NULL))
-               status->aggr = true;
-
-       if (WARN_ON_ONCE(len > skb->len))
-               return -EINVAL;
-
-       pskb_trim(skb, len);
-       status->chains = BIT(0) | BIT(1);
-       status->chain_signal[0] = mt76x2_phy_get_rssi(dev, rxwi->rssi[0], 0);
-       status->chain_signal[1] = mt76x2_phy_get_rssi(dev, rxwi->rssi[1], 1);
-       status->signal = max(status->chain_signal[0], status->chain_signal[1]);
-       status->freq = dev->mt76.chandef.chan->center_freq;
-       status->band = dev->mt76.chandef.chan->band;
-
-       status->tid = FIELD_GET(MT_RXWI_TID, tid_sn);
-       status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn);
-
-       if (sta) {
-               ewma_signal_add(&sta->rssi, status->signal);
-               sta->inactive_count = 0;
-       }
-
-       return mt76x2_mac_process_rate(status, rate);
-}
-
-static int
-mt76x2_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate,
-                          enum nl80211_band band)
-{
-       u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate);
-
-       txrate->idx = 0;
-       txrate->flags = 0;
-       txrate->count = 1;
-
-       switch (FIELD_GET(MT_RXWI_RATE_PHY, rate)) {
-       case MT_PHY_TYPE_OFDM:
-               if (band == NL80211_BAND_2GHZ)
-                       idx += 4;
-
-               txrate->idx = idx;
-               return 0;
-       case MT_PHY_TYPE_CCK:
-               if (idx >= 8)
-                       idx -= 8;
-
-               txrate->idx = idx;
-               return 0;
-       case MT_PHY_TYPE_HT_GF:
-               txrate->flags |= IEEE80211_TX_RC_GREEN_FIELD;
-               /* fall through */
-       case MT_PHY_TYPE_HT:
-               txrate->flags |= IEEE80211_TX_RC_MCS;
-               txrate->idx = idx;
-               break;
-       case MT_PHY_TYPE_VHT:
-               txrate->flags |= IEEE80211_TX_RC_VHT_MCS;
-               txrate->idx = idx;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       switch (FIELD_GET(MT_RXWI_RATE_BW, rate)) {
-       case MT_PHY_BW_20:
-               break;
-       case MT_PHY_BW_40:
-               txrate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
-               break;
-       case MT_PHY_BW_80:
-               txrate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (rate & MT_RXWI_RATE_SGI)
-               txrate->flags |= IEEE80211_TX_RC_SHORT_GI;
-
-       return 0;
-}
-
-static void
-mt76x2_mac_fill_tx_status(struct mt76x2_dev *dev,
-                         struct ieee80211_tx_info *info,
-                         struct mt76x2_tx_status *st, int n_frames)
-{
-       struct ieee80211_tx_rate *rate = info->status.rates;
-       int cur_idx, last_rate;
-       int i;
-
-       if (!n_frames)
-               return;
-
-       last_rate = min_t(int, st->retry, IEEE80211_TX_MAX_RATES - 1);
-       mt76x2_mac_process_tx_rate(&rate[last_rate], st->rate,
-                                dev->mt76.chandef.chan->band);
-       if (last_rate < IEEE80211_TX_MAX_RATES - 1)
-               rate[last_rate + 1].idx = -1;
-
-       cur_idx = rate[last_rate].idx + last_rate;
-       for (i = 0; i <= last_rate; i++) {
-               rate[i].flags = rate[last_rate].flags;
-               rate[i].idx = max_t(int, 0, cur_idx - i);
-               rate[i].count = 1;
-       }
-       rate[last_rate].count = st->retry + 1 - last_rate;
-
-       info->status.ampdu_len = n_frames;
-       info->status.ampdu_ack_len = st->success ? n_frames : 0;
-
-       if (st->pktid & MT_TXWI_PKTID_PROBE)
-               info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
-
-       if (st->aggr)
-               info->flags |= IEEE80211_TX_CTL_AMPDU |
-                              IEEE80211_TX_STAT_AMPDU;
-
-       if (!st->ack_req)
-               info->flags |= IEEE80211_TX_CTL_NO_ACK;
-       else if (st->success)
-               info->flags |= IEEE80211_TX_STAT_ACK;
-}
-
-static void
-mt76x2_send_tx_status(struct mt76x2_dev *dev, struct mt76x2_tx_status *stat,
-                     u8 *update)
-{
-       struct ieee80211_tx_info info = {};
-       struct ieee80211_sta *sta = NULL;
-       struct mt76_wcid *wcid = NULL;
-       struct mt76x2_sta *msta = NULL;
-
-       rcu_read_lock();
-       if (stat->wcid < ARRAY_SIZE(dev->wcid))
-               wcid = rcu_dereference(dev->wcid[stat->wcid]);
-
-       if (wcid) {
-               void *priv;
-
-               priv = msta = container_of(wcid, struct mt76x2_sta, wcid);
-               sta = container_of(priv, struct ieee80211_sta,
-                                  drv_priv);
-       }
-
-       if (msta && stat->aggr) {
-               u32 stat_val, stat_cache;
-
-               stat_val = stat->rate;
-               stat_val |= ((u32) stat->retry) << 16;
-               stat_cache = msta->status.rate;
-               stat_cache |= ((u32) msta->status.retry) << 16;
-
-               if (*update == 0 && stat_val == stat_cache &&
-                   stat->wcid == msta->status.wcid && msta->n_frames < 32) {
-                       msta->n_frames++;
-                       goto out;
-               }
-
-               mt76x2_mac_fill_tx_status(dev, &info, &msta->status,
-                                         msta->n_frames);
-
-               msta->status = *stat;
-               msta->n_frames = 1;
-               *update = 0;
-       } else {
-               mt76x2_mac_fill_tx_status(dev, &info, stat, 1);
-               *update = 1;
-       }
-
-       ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info);
-
-out:
-       rcu_read_unlock();
-}
-
-static bool
-mt76x2_mac_load_tx_status(struct mt76x2_dev *dev,
-                         struct mt76x2_tx_status *stat)
-{
-       u32 stat1, stat2;
-
-       stat2 = mt76_rr(dev, MT_TX_STAT_FIFO_EXT);
-       stat1 = mt76_rr(dev, MT_TX_STAT_FIFO);
-
-       stat->valid = !!(stat1 & MT_TX_STAT_FIFO_VALID);
-       if (!stat->valid)
-               return false;
-
-       stat->success = !!(stat1 & MT_TX_STAT_FIFO_SUCCESS);
-       stat->aggr = !!(stat1 & MT_TX_STAT_FIFO_AGGR);
-       stat->ack_req = !!(stat1 & MT_TX_STAT_FIFO_ACKREQ);
-       stat->wcid = FIELD_GET(MT_TX_STAT_FIFO_WCID, stat1);
-       stat->rate = FIELD_GET(MT_TX_STAT_FIFO_RATE, stat1);
-
-       stat->retry = FIELD_GET(MT_TX_STAT_FIFO_EXT_RETRY, stat2);
-       stat->pktid = FIELD_GET(MT_TX_STAT_FIFO_EXT_PKTID, stat2);
-
-       return true;
-}
-
 void mt76x2_mac_poll_tx_status(struct mt76x2_dev *dev, bool irq)
 {
        struct mt76x2_tx_status stat = {};
@@ -625,104 +96,6 @@ void mt76x2_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue *q,
                dev_kfree_skb_any(e->skb);
 }
 
-static enum mt76x2_cipher_type
-mt76x2_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
-{
-       memset(key_data, 0, 32);
-       if (!key)
-               return MT_CIPHER_NONE;
-
-       if (key->keylen > 32)
-               return MT_CIPHER_NONE;
-
-       memcpy(key_data, key->key, key->keylen);
-
-       switch (key->cipher) {
-       case WLAN_CIPHER_SUITE_WEP40:
-               return MT_CIPHER_WEP40;
-       case WLAN_CIPHER_SUITE_WEP104:
-               return MT_CIPHER_WEP104;
-       case WLAN_CIPHER_SUITE_TKIP:
-               return MT_CIPHER_TKIP;
-       case WLAN_CIPHER_SUITE_CCMP:
-               return MT_CIPHER_AES_CCMP;
-       default:
-               return MT_CIPHER_NONE;
-       }
-}
-
-void mt76x2_mac_wcid_setup(struct mt76x2_dev *dev, u8 idx, u8 vif_idx, u8 *mac)
-{
-       struct mt76_wcid_addr addr = {};
-       u32 attr;
-
-       attr = FIELD_PREP(MT_WCID_ATTR_BSS_IDX, vif_idx & 7) |
-              FIELD_PREP(MT_WCID_ATTR_BSS_IDX_EXT, !!(vif_idx & 8));
-
-       mt76_wr(dev, MT_WCID_ATTR(idx), attr);
-
-       mt76_wr(dev, MT_WCID_TX_RATE(idx), 0);
-       mt76_wr(dev, MT_WCID_TX_RATE(idx) + 4, 0);
-
-       if (idx >= 128)
-               return;
-
-       if (mac)
-               memcpy(addr.macaddr, mac, ETH_ALEN);
-
-       mt76_wr_copy(dev, MT_WCID_ADDR(idx), &addr, sizeof(addr));
-}
-
-int mt76x2_mac_wcid_set_key(struct mt76x2_dev *dev, u8 idx,
-                           struct ieee80211_key_conf *key)
-{
-       enum mt76x2_cipher_type cipher;
-       u8 key_data[32];
-       u8 iv_data[8];
-
-       cipher = mt76x2_mac_get_key_info(key, key_data);
-       if (cipher == MT_CIPHER_NONE && key)
-               return -EOPNOTSUPP;
-
-       mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PKEY_MODE, cipher);
-       mt76_wr_copy(dev, MT_WCID_KEY(idx), key_data, sizeof(key_data));
-
-       memset(iv_data, 0, sizeof(iv_data));
-       if (key) {
-               mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PAIRWISE,
-                              !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
-               iv_data[3] = key->keyidx << 6;
-               if (cipher >= MT_CIPHER_TKIP)
-                       iv_data[3] |= 0x20;
-       }
-
-       mt76_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data));
-
-       return 0;
-}
-
-int mt76x2_mac_shared_key_setup(struct mt76x2_dev *dev, u8 vif_idx, u8 key_idx,
-                             struct ieee80211_key_conf *key)
-{
-       enum mt76x2_cipher_type cipher;
-       u8 key_data[32];
-       u32 val;
-
-       cipher = mt76x2_mac_get_key_info(key, key_data);
-       if (cipher == MT_CIPHER_NONE && key)
-               return -EOPNOTSUPP;
-
-       val = mt76_rr(dev, MT_SKEY_MODE(vif_idx));
-       val &= ~(MT_SKEY_MODE_MASK << MT_SKEY_MODE_SHIFT(vif_idx, key_idx));
-       val |= cipher << MT_SKEY_MODE_SHIFT(vif_idx, key_idx);
-       mt76_wr(dev, MT_SKEY_MODE(vif_idx), val);
-
-       mt76_wr_copy(dev, MT_SKEY(vif_idx, key_idx), key_data,
-                    sizeof(key_data));
-
-       return 0;
-}
-
 static int
 mt76_write_beacon(struct mt76x2_dev *dev, int offset, struct sk_buff *skb)
 {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mac_common.c b/drivers/net/wireless/mediatek/mt76/mt76x2_mac_common.c
new file mode 100644 (file)
index 0000000..6542644
--- /dev/null
@@ -0,0 +1,699 @@
+/*
+ * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
+ * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "mt76x2.h"
+
+void mt76x2_mac_stop(struct mt76x2_dev *dev, bool force)
+{
+       bool stopped = false;
+       u32 rts_cfg;
+       int i;
+
+       mt76_wr(dev, MT_MAC_SYS_CTRL, 0);
+
+       rts_cfg = mt76_rr(dev, MT_TX_RTS_CFG);
+       mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg & ~MT_TX_RTS_CFG_RETRY_LIMIT);
+
+       /* Wait for MAC to become idle */
+       for (i = 0; i < 300; i++) {
+               if ((mt76_rr(dev, MT_MAC_STATUS) &
+                    (MT_MAC_STATUS_RX | MT_MAC_STATUS_TX)) ||
+                   mt76_rr(dev, MT_BBP(IBI, 12))) {
+                       udelay(1);
+                       continue;
+               }
+
+               stopped = true;
+               break;
+       }
+
+       if (force && !stopped) {
+               mt76_set(dev, MT_BBP(CORE, 4), BIT(1));
+               mt76_clear(dev, MT_BBP(CORE, 4), BIT(1));
+
+               mt76_set(dev, MT_BBP(CORE, 4), BIT(0));
+               mt76_clear(dev, MT_BBP(CORE, 4), BIT(0));
+       }
+
+       mt76_wr(dev, MT_TX_RTS_CFG, rts_cfg);
+}
+EXPORT_SYMBOL_GPL(mt76x2_mac_stop);
+
+bool mt76x2_mac_load_tx_status(struct mt76x2_dev *dev,
+                              struct mt76x2_tx_status *stat)
+{
+       u32 stat1, stat2;
+
+       stat2 = mt76_rr(dev, MT_TX_STAT_FIFO_EXT);
+       stat1 = mt76_rr(dev, MT_TX_STAT_FIFO);
+
+       stat->valid = !!(stat1 & MT_TX_STAT_FIFO_VALID);
+       if (!stat->valid)
+               return false;
+
+       stat->success = !!(stat1 & MT_TX_STAT_FIFO_SUCCESS);
+       stat->aggr = !!(stat1 & MT_TX_STAT_FIFO_AGGR);
+       stat->ack_req = !!(stat1 & MT_TX_STAT_FIFO_ACKREQ);
+       stat->wcid = FIELD_GET(MT_TX_STAT_FIFO_WCID, stat1);
+       stat->rate = FIELD_GET(MT_TX_STAT_FIFO_RATE, stat1);
+
+       stat->retry = FIELD_GET(MT_TX_STAT_FIFO_EXT_RETRY, stat2);
+       stat->pktid = FIELD_GET(MT_TX_STAT_FIFO_EXT_PKTID, stat2);
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(mt76x2_mac_load_tx_status);
+
+static int
+mt76x2_mac_process_tx_rate(struct ieee80211_tx_rate *txrate, u16 rate,
+                          enum nl80211_band band)
+{
+       u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate);
+
+       txrate->idx = 0;
+       txrate->flags = 0;
+       txrate->count = 1;
+
+       switch (FIELD_GET(MT_RXWI_RATE_PHY, rate)) {
+       case MT_PHY_TYPE_OFDM:
+               if (band == NL80211_BAND_2GHZ)
+                       idx += 4;
+
+               txrate->idx = idx;
+               return 0;
+       case MT_PHY_TYPE_CCK:
+               if (idx >= 8)
+                       idx -= 8;
+
+               txrate->idx = idx;
+               return 0;
+       case MT_PHY_TYPE_HT_GF:
+               txrate->flags |= IEEE80211_TX_RC_GREEN_FIELD;
+               /* fall through */
+       case MT_PHY_TYPE_HT:
+               txrate->flags |= IEEE80211_TX_RC_MCS;
+               txrate->idx = idx;
+               break;
+       case MT_PHY_TYPE_VHT:
+               txrate->flags |= IEEE80211_TX_RC_VHT_MCS;
+               txrate->idx = idx;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       switch (FIELD_GET(MT_RXWI_RATE_BW, rate)) {
+       case MT_PHY_BW_20:
+               break;
+       case MT_PHY_BW_40:
+               txrate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+               break;
+       case MT_PHY_BW_80:
+               txrate->flags |= IEEE80211_TX_RC_80_MHZ_WIDTH;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (rate & MT_RXWI_RATE_SGI)
+               txrate->flags |= IEEE80211_TX_RC_SHORT_GI;
+
+       return 0;
+}
+
+static void
+mt76x2_mac_fill_tx_status(struct mt76x2_dev *dev,
+                         struct ieee80211_tx_info *info,
+                         struct mt76x2_tx_status *st, int n_frames)
+{
+       struct ieee80211_tx_rate *rate = info->status.rates;
+       int cur_idx, last_rate;
+       int i;
+
+       if (!n_frames)
+               return;
+
+       last_rate = min_t(int, st->retry, IEEE80211_TX_MAX_RATES - 1);
+       mt76x2_mac_process_tx_rate(&rate[last_rate], st->rate,
+                                dev->mt76.chandef.chan->band);
+       if (last_rate < IEEE80211_TX_MAX_RATES - 1)
+               rate[last_rate + 1].idx = -1;
+
+       cur_idx = rate[last_rate].idx + last_rate;
+       for (i = 0; i <= last_rate; i++) {
+               rate[i].flags = rate[last_rate].flags;
+               rate[i].idx = max_t(int, 0, cur_idx - i);
+               rate[i].count = 1;
+       }
+       rate[last_rate].count = st->retry + 1 - last_rate;
+
+       info->status.ampdu_len = n_frames;
+       info->status.ampdu_ack_len = st->success ? n_frames : 0;
+
+       if (st->pktid & MT_TXWI_PKTID_PROBE)
+               info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
+
+       if (st->aggr)
+               info->flags |= IEEE80211_TX_CTL_AMPDU |
+                              IEEE80211_TX_STAT_AMPDU;
+
+       if (!st->ack_req)
+               info->flags |= IEEE80211_TX_CTL_NO_ACK;
+       else if (st->success)
+               info->flags |= IEEE80211_TX_STAT_ACK;
+}
+
+void mt76x2_send_tx_status(struct mt76x2_dev *dev,
+                          struct mt76x2_tx_status *stat, u8 *update)
+{
+       struct ieee80211_tx_info info = {};
+       struct ieee80211_sta *sta = NULL;
+       struct mt76_wcid *wcid = NULL;
+       struct mt76x2_sta *msta = NULL;
+
+       rcu_read_lock();
+       if (stat->wcid < ARRAY_SIZE(dev->wcid))
+               wcid = rcu_dereference(dev->wcid[stat->wcid]);
+
+       if (wcid) {
+               void *priv;
+
+               priv = msta = container_of(wcid, struct mt76x2_sta, wcid);
+               sta = container_of(priv, struct ieee80211_sta,
+                                  drv_priv);
+       }
+
+       if (msta && stat->aggr) {
+               u32 stat_val, stat_cache;
+
+               stat_val = stat->rate;
+               stat_val |= ((u32) stat->retry) << 16;
+               stat_cache = msta->status.rate;
+               stat_cache |= ((u32) msta->status.retry) << 16;
+
+               if (*update == 0 && stat_val == stat_cache &&
+                   stat->wcid == msta->status.wcid && msta->n_frames < 32) {
+                       msta->n_frames++;
+                       goto out;
+               }
+
+               mt76x2_mac_fill_tx_status(dev, &info, &msta->status,
+                                         msta->n_frames);
+
+               msta->status = *stat;
+               msta->n_frames = 1;
+               *update = 0;
+       } else {
+               mt76x2_mac_fill_tx_status(dev, &info, stat, 1);
+               *update = 1;
+       }
+
+       ieee80211_tx_status_noskb(mt76_hw(dev), sta, &info);
+
+out:
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(mt76x2_send_tx_status);
+
+static enum mt76x2_cipher_type
+mt76x2_mac_get_key_info(struct ieee80211_key_conf *key, u8 *key_data)
+{
+       memset(key_data, 0, 32);
+       if (!key)
+               return MT_CIPHER_NONE;
+
+       if (key->keylen > 32)
+               return MT_CIPHER_NONE;
+
+       memcpy(key_data, key->key, key->keylen);
+
+       switch (key->cipher) {
+       case WLAN_CIPHER_SUITE_WEP40:
+               return MT_CIPHER_WEP40;
+       case WLAN_CIPHER_SUITE_WEP104:
+               return MT_CIPHER_WEP104;
+       case WLAN_CIPHER_SUITE_TKIP:
+               return MT_CIPHER_TKIP;
+       case WLAN_CIPHER_SUITE_CCMP:
+               return MT_CIPHER_AES_CCMP;
+       default:
+               return MT_CIPHER_NONE;
+       }
+}
+
+int mt76x2_mac_shared_key_setup(struct mt76x2_dev *dev, u8 vif_idx, u8 key_idx,
+                               struct ieee80211_key_conf *key)
+{
+       enum mt76x2_cipher_type cipher;
+       u8 key_data[32];
+       u32 val;
+
+       cipher = mt76x2_mac_get_key_info(key, key_data);
+       if (cipher == MT_CIPHER_NONE && key)
+               return -EOPNOTSUPP;
+
+       val = mt76_rr(dev, MT_SKEY_MODE(vif_idx));
+       val &= ~(MT_SKEY_MODE_MASK << MT_SKEY_MODE_SHIFT(vif_idx, key_idx));
+       val |= cipher << MT_SKEY_MODE_SHIFT(vif_idx, key_idx);
+       mt76_wr(dev, MT_SKEY_MODE(vif_idx), val);
+
+       mt76_wr_copy(dev, MT_SKEY(vif_idx, key_idx), key_data,
+                    sizeof(key_data));
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mt76x2_mac_shared_key_setup);
+
+int mt76x2_mac_wcid_set_key(struct mt76x2_dev *dev, u8 idx,
+                           struct ieee80211_key_conf *key)
+{
+       enum mt76x2_cipher_type cipher;
+       u8 key_data[32];
+       u8 iv_data[8];
+
+       cipher = mt76x2_mac_get_key_info(key, key_data);
+       if (cipher == MT_CIPHER_NONE && key)
+               return -EOPNOTSUPP;
+
+       mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PKEY_MODE, cipher);
+       mt76_wr_copy(dev, MT_WCID_KEY(idx), key_data, sizeof(key_data));
+
+       memset(iv_data, 0, sizeof(iv_data));
+       if (key) {
+               mt76_rmw_field(dev, MT_WCID_ATTR(idx), MT_WCID_ATTR_PAIRWISE,
+                              !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
+               iv_data[3] = key->keyidx << 6;
+               if (cipher >= MT_CIPHER_TKIP)
+                       iv_data[3] |= 0x20;
+       }
+
+       mt76_wr_copy(dev, MT_WCID_IV(idx), iv_data, sizeof(iv_data));
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mt76x2_mac_wcid_set_key);
+
+static __le16
+mt76x2_mac_tx_rate_val(struct mt76x2_dev *dev,
+                      const struct ieee80211_tx_rate *rate, u8 *nss_val)
+{
+       u16 rateval;
+       u8 phy, rate_idx;
+       u8 nss = 1;
+       u8 bw = 0;
+
+       if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
+               rate_idx = rate->idx;
+               nss = 1 + (rate->idx >> 4);
+               phy = MT_PHY_TYPE_VHT;
+               if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+                       bw = 2;
+               else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+                       bw = 1;
+       } else if (rate->flags & IEEE80211_TX_RC_MCS) {
+               rate_idx = rate->idx;
+               nss = 1 + (rate->idx >> 3);
+               phy = MT_PHY_TYPE_HT;
+               if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD)
+                       phy = MT_PHY_TYPE_HT_GF;
+               if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+                       bw = 1;
+       } else {
+               const struct ieee80211_rate *r;
+               int band = dev->mt76.chandef.chan->band;
+               u16 val;
+
+               r = &mt76_hw(dev)->wiphy->bands[band]->bitrates[rate->idx];
+               if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
+                       val = r->hw_value_short;
+               else
+                       val = r->hw_value;
+
+               phy = val >> 8;
+               rate_idx = val & 0xff;
+               bw = 0;
+       }
+
+       rateval = FIELD_PREP(MT_RXWI_RATE_INDEX, rate_idx);
+       rateval |= FIELD_PREP(MT_RXWI_RATE_PHY, phy);
+       rateval |= FIELD_PREP(MT_RXWI_RATE_BW, bw);
+       if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+               rateval |= MT_RXWI_RATE_SGI;
+
+       *nss_val = nss;
+       return cpu_to_le16(rateval);
+}
+
+void mt76x2_mac_wcid_set_rate(struct mt76x2_dev *dev, struct mt76_wcid *wcid,
+                             const struct ieee80211_tx_rate *rate)
+{
+       spin_lock_bh(&dev->mt76.lock);
+       wcid->tx_rate = mt76x2_mac_tx_rate_val(dev, rate, &wcid->tx_rate_nss);
+       wcid->tx_rate_set = true;
+       spin_unlock_bh(&dev->mt76.lock);
+}
+EXPORT_SYMBOL_GPL(mt76x2_mac_wcid_set_rate);
+
+void mt76x2_mac_write_txwi(struct mt76x2_dev *dev, struct mt76x2_txwi *txwi,
+                          struct sk_buff *skb, struct mt76_wcid *wcid,
+                          struct ieee80211_sta *sta, int len)
+{
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+       struct ieee80211_tx_rate *rate = &info->control.rates[0];
+       struct ieee80211_key_conf *key = info->control.hw_key;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+       u16 rate_ht_mask = FIELD_PREP(MT_RXWI_RATE_PHY, BIT(1) | BIT(2));
+       u16 txwi_flags = 0;
+       u8 nss;
+       s8 txpwr_adj, max_txpwr_adj;
+       u8 ccmp_pn[8];
+
+       memset(txwi, 0, sizeof(*txwi));
+
+       if (wcid)
+               txwi->wcid = wcid->idx;
+       else
+               txwi->wcid = 0xff;
+
+       txwi->pktid = 1;
+
+       if (wcid && wcid->sw_iv && key) {
+               u64 pn = atomic64_inc_return(&key->tx_pn);
+               ccmp_pn[0] = pn;
+               ccmp_pn[1] = pn >> 8;
+               ccmp_pn[2] = 0;
+               ccmp_pn[3] = 0x20 | (key->keyidx << 6);
+               ccmp_pn[4] = pn >> 16;
+               ccmp_pn[5] = pn >> 24;
+               ccmp_pn[6] = pn >> 32;
+               ccmp_pn[7] = pn >> 40;
+               txwi->iv = *((__le32 *)&ccmp_pn[0]);
+               txwi->eiv = *((__le32 *)&ccmp_pn[1]);
+       }
+
+       spin_lock_bh(&dev->mt76.lock);
+       if (wcid && (rate->idx < 0 || !rate->count)) {
+               txwi->rate = wcid->tx_rate;
+               max_txpwr_adj = wcid->max_txpwr_adj;
+               nss = wcid->tx_rate_nss;
+       } else {
+               txwi->rate = mt76x2_mac_tx_rate_val(dev, rate, &nss);
+               max_txpwr_adj = mt76x2_tx_get_max_txpwr_adj(dev, rate);
+       }
+       spin_unlock_bh(&dev->mt76.lock);
+
+       txpwr_adj = mt76x2_tx_get_txpwr_adj(dev, dev->txpower_conf,
+                                           max_txpwr_adj);
+       txwi->ctl2 = FIELD_PREP(MT_TX_PWR_ADJ, txpwr_adj);
+
+       if (mt76xx_rev(dev) >= MT76XX_REV_E4)
+               txwi->txstream = 0x13;
+       else if (mt76xx_rev(dev) >= MT76XX_REV_E3 &&
+                !(txwi->rate & cpu_to_le16(rate_ht_mask)))
+               txwi->txstream = 0x93;
+
+       if (info->flags & IEEE80211_TX_CTL_LDPC)
+               txwi->rate |= cpu_to_le16(MT_RXWI_RATE_LDPC);
+       if ((info->flags & IEEE80211_TX_CTL_STBC) && nss == 1)
+               txwi->rate |= cpu_to_le16(MT_RXWI_RATE_STBC);
+       if (nss > 1 && sta && sta->smps_mode == IEEE80211_SMPS_DYNAMIC)
+               txwi_flags |= MT_TXWI_FLAGS_MMPS;
+       if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
+               txwi->ack_ctl |= MT_TXWI_ACK_CTL_REQ;
+       if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+               txwi->ack_ctl |= MT_TXWI_ACK_CTL_NSEQ;
+       if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
+               txwi->pktid |= MT_TXWI_PKTID_PROBE;
+       if ((info->flags & IEEE80211_TX_CTL_AMPDU) && sta) {
+               u8 ba_size = IEEE80211_MIN_AMPDU_BUF;
+
+               ba_size <<= sta->ht_cap.ampdu_factor;
+               ba_size = min_t(int, 63, ba_size - 1);
+               if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
+                       ba_size = 0;
+               txwi->ack_ctl |= FIELD_PREP(MT_TXWI_ACK_CTL_BA_WINDOW, ba_size);
+
+               txwi_flags |= MT_TXWI_FLAGS_AMPDU |
+                        FIELD_PREP(MT_TXWI_FLAGS_MPDU_DENSITY,
+                                   sta->ht_cap.ampdu_density);
+       }
+
+       if (ieee80211_is_probe_resp(hdr->frame_control) ||
+           ieee80211_is_beacon(hdr->frame_control))
+               txwi_flags |= MT_TXWI_FLAGS_TS;
+
+       txwi->flags |= cpu_to_le16(txwi_flags);
+       txwi->len_ctl = cpu_to_le16(len);
+}
+EXPORT_SYMBOL_GPL(mt76x2_mac_write_txwi);
+
+void mt76x2_mac_wcid_set_drop(struct mt76x2_dev *dev, u8 idx, bool drop)
+{
+       u32 val = mt76_rr(dev, MT_WCID_DROP(idx));
+       u32 bit = MT_WCID_DROP_MASK(idx);
+
+       /* prevent unnecessary writes */
+       if ((val & bit) != (bit * drop))
+               mt76_wr(dev, MT_WCID_DROP(idx), (val & ~bit) | (bit * drop));
+}
+EXPORT_SYMBOL_GPL(mt76x2_mac_wcid_set_drop);
+
+void mt76x2_mac_wcid_setup(struct mt76x2_dev *dev, u8 idx, u8 vif_idx, u8 *mac)
+{
+       struct mt76_wcid_addr addr = {};
+       u32 attr;
+
+       attr = FIELD_PREP(MT_WCID_ATTR_BSS_IDX, vif_idx & 7) |
+              FIELD_PREP(MT_WCID_ATTR_BSS_IDX_EXT, !!(vif_idx & 8));
+
+       mt76_wr(dev, MT_WCID_ATTR(idx), attr);
+
+       mt76_wr(dev, MT_WCID_TX_RATE(idx), 0);
+       mt76_wr(dev, MT_WCID_TX_RATE(idx) + 4, 0);
+
+       if (idx >= 128)
+               return;
+
+       if (mac)
+               memcpy(addr.macaddr, mac, ETH_ALEN);
+
+       mt76_wr_copy(dev, MT_WCID_ADDR(idx), &addr, sizeof(addr));
+}
+EXPORT_SYMBOL_GPL(mt76x2_mac_wcid_setup);
+
+static int
+mt76x2_mac_process_rate(struct mt76_rx_status *status, u16 rate)
+{
+       u8 idx = FIELD_GET(MT_RXWI_RATE_INDEX, rate);
+
+       switch (FIELD_GET(MT_RXWI_RATE_PHY, rate)) {
+       case MT_PHY_TYPE_OFDM:
+               if (idx >= 8)
+                       idx = 0;
+
+               if (status->band == NL80211_BAND_2GHZ)
+                       idx += 4;
+
+               status->rate_idx = idx;
+               return 0;
+       case MT_PHY_TYPE_CCK:
+               if (idx >= 8) {
+                       idx -= 8;
+                       status->enc_flags |= RX_ENC_FLAG_SHORTPRE;
+               }
+
+               if (idx >= 4)
+                       idx = 0;
+
+               status->rate_idx = idx;
+               return 0;
+       case MT_PHY_TYPE_HT_GF:
+               status->enc_flags |= RX_ENC_FLAG_HT_GF;
+               /* fall through */
+       case MT_PHY_TYPE_HT:
+               status->encoding = RX_ENC_HT;
+               status->rate_idx = idx;
+               break;
+       case MT_PHY_TYPE_VHT:
+               status->encoding = RX_ENC_VHT;
+               status->rate_idx = FIELD_GET(MT_RATE_INDEX_VHT_IDX, idx);
+               status->nss = FIELD_GET(MT_RATE_INDEX_VHT_NSS, idx) + 1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (rate & MT_RXWI_RATE_LDPC)
+               status->enc_flags |= RX_ENC_FLAG_LDPC;
+
+       if (rate & MT_RXWI_RATE_SGI)
+               status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+
+       if (rate & MT_RXWI_RATE_STBC)
+               status->enc_flags |= 1 << RX_ENC_FLAG_STBC_SHIFT;
+
+       switch (FIELD_GET(MT_RXWI_RATE_BW, rate)) {
+       case MT_PHY_BW_20:
+               break;
+       case MT_PHY_BW_40:
+               status->bw = RATE_INFO_BW_40;
+               break;
+       case MT_PHY_BW_80:
+               status->bw = RATE_INFO_BW_80;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void mt76x2_remove_hdr_pad(struct sk_buff *skb, int len)
+{
+       int hdrlen;
+
+       if (!len)
+               return;
+
+       hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+       memmove(skb->data + len, skb->data, hdrlen);
+       skb_pull(skb, len);
+}
+
+int mt76x2_mac_get_rssi(struct mt76x2_dev *dev, s8 rssi, int chain)
+{
+       struct mt76x2_rx_freq_cal *cal = &dev->cal.rx;
+
+       rssi += cal->rssi_offset[chain];
+       rssi -= cal->lna_gain;
+
+       return rssi;
+}
+
+static struct mt76x2_sta *
+mt76x2_rx_get_sta(struct mt76x2_dev *dev, u8 idx)
+{
+       struct mt76_wcid *wcid;
+
+       if (idx >= ARRAY_SIZE(dev->wcid))
+               return NULL;
+
+       wcid = rcu_dereference(dev->wcid[idx]);
+       if (!wcid)
+               return NULL;
+
+       return container_of(wcid, struct mt76x2_sta, wcid);
+}
+
+static struct mt76_wcid *
+mt76x2_rx_get_sta_wcid(struct mt76x2_dev *dev, struct mt76x2_sta *sta,
+                      bool unicast)
+{
+       if (!sta)
+               return NULL;
+
+       if (unicast)
+               return &sta->wcid;
+       else
+               return &sta->vif->group_wcid;
+}
+
+int mt76x2_mac_process_rx(struct mt76x2_dev *dev, struct sk_buff *skb,
+                         void *rxi)
+{
+       struct mt76_rx_status *status = (struct mt76_rx_status *) skb->cb;
+       struct mt76x2_rxwi *rxwi = rxi;
+       struct mt76x2_sta *sta;
+       u32 rxinfo = le32_to_cpu(rxwi->rxinfo);
+       u32 ctl = le32_to_cpu(rxwi->ctl);
+       u16 rate = le16_to_cpu(rxwi->rate);
+       u16 tid_sn = le16_to_cpu(rxwi->tid_sn);
+       bool unicast = rxwi->rxinfo & cpu_to_le32(MT_RXINFO_UNICAST);
+       int pad_len = 0;
+       u8 pn_len;
+       u8 wcid;
+       int len;
+
+       if (!test_bit(MT76_STATE_RUNNING, &dev->mt76.state))
+               return -EINVAL;
+
+       if (rxinfo & MT_RXINFO_L2PAD)
+               pad_len += 2;
+
+       if (rxinfo & MT_RXINFO_DECRYPT) {
+               status->flag |= RX_FLAG_DECRYPTED;
+               status->flag |= RX_FLAG_MMIC_STRIPPED;
+               status->flag |= RX_FLAG_MIC_STRIPPED;
+               status->flag |= RX_FLAG_IV_STRIPPED;
+       }
+
+       wcid = FIELD_GET(MT_RXWI_CTL_WCID, ctl);
+       sta = mt76x2_rx_get_sta(dev, wcid);
+       status->wcid = mt76x2_rx_get_sta_wcid(dev, sta, unicast);
+
+       len = FIELD_GET(MT_RXWI_CTL_MPDU_LEN, ctl);
+       pn_len = FIELD_GET(MT_RXINFO_PN_LEN, rxinfo);
+       if (pn_len) {
+               int offset = ieee80211_get_hdrlen_from_skb(skb) + pad_len;
+               u8 *data = skb->data + offset;
+
+               status->iv[0] = data[7];
+               status->iv[1] = data[6];
+               status->iv[2] = data[5];
+               status->iv[3] = data[4];
+               status->iv[4] = data[1];
+               status->iv[5] = data[0];
+
+               /*
+                * Driver CCMP validation can't deal with fragments.
+                * Let mac80211 take care of it.
+                */
+               if (rxinfo & MT_RXINFO_FRAG) {
+                       status->flag &= ~RX_FLAG_IV_STRIPPED;
+               } else {
+                       pad_len += pn_len << 2;
+                       len -= pn_len << 2;
+               }
+       }
+
+       mt76x2_remove_hdr_pad(skb, pad_len);
+
+       if ((rxinfo & MT_RXINFO_BA) && !(rxinfo & MT_RXINFO_NULL))
+               status->aggr = true;
+
+       if (WARN_ON_ONCE(len > skb->len))
+               return -EINVAL;
+
+       pskb_trim(skb, len);
+       status->chains = BIT(0) | BIT(1);
+       status->chain_signal[0] = mt76x2_mac_get_rssi(dev, rxwi->rssi[0], 0);
+       status->chain_signal[1] = mt76x2_mac_get_rssi(dev, rxwi->rssi[1], 1);
+       status->signal = max(status->chain_signal[0], status->chain_signal[1]);
+       status->freq = dev->mt76.chandef.chan->center_freq;
+       status->band = dev->mt76.chandef.chan->band;
+
+       status->tid = FIELD_GET(MT_RXWI_TID, tid_sn);
+       status->seqno = FIELD_GET(MT_RXWI_SN, tid_sn);
+
+       if (sta) {
+               ewma_signal_add(&sta->rssi, status->signal);
+               sta->inactive_count = 0;
+       }
+
+       return mt76x2_mac_process_rate(status, rate);
+}
+EXPORT_SYMBOL_GPL(mt76x2_mac_process_rx);
index 9a7b50f0005d6ce1381196891b9497a51e65cb1e..962505bf8fbb38554679425e485b6c1540427f15 100644 (file)
@@ -63,16 +63,6 @@ mt76x2_tx_power_mask(u8 v1, u8 v2, u8 v3, u8 v4)
        return val;
 }
 
-int mt76x2_phy_get_rssi(struct mt76x2_dev *dev, s8 rssi, int chain)
-{
-       struct mt76x2_rx_freq_cal *cal = &dev->cal.rx;
-
-       rssi += cal->rssi_offset[chain];
-       rssi -= cal->lna_gain;
-
-       return rssi;
-}
-
 static void
 mt76x2_add_rate_power_offset(struct mt76_rate_power *r, int offset)
 {