Path: blob/main/sys/contrib/dev/mediatek/mt76/mt7615/mac.c
48526 views
// SPDX-License-Identifier: ISC1/* Copyright (C) 2019 MediaTek Inc.2*3* Author: Ryder Lee <[email protected]>4* Roy Luo <[email protected]>5* Felix Fietkau <[email protected]>6* Lorenzo Bianconi <[email protected]>7*/89#include <linux/devcoredump.h>10#include <linux/etherdevice.h>11#include <linux/timekeeping.h>12#if defined(__FreeBSD__)13#include <linux/delay.h>14#endif15#include "mt7615.h"16#include "../trace.h"17#include "../dma.h"18#include "mt7615_trace.h"19#include "mac.h"20#include "mcu.h"2122#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)2324static const struct mt7615_dfs_radar_spec etsi_radar_specs = {25.pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },26.radar_pattern = {27[5] = { 1, 0, 6, 32, 28, 0, 17, 990, 5010, 1, 1 },28[6] = { 1, 0, 9, 32, 28, 0, 27, 615, 5010, 1, 1 },29[7] = { 1, 0, 15, 32, 28, 0, 27, 240, 445, 1, 1 },30[8] = { 1, 0, 12, 32, 28, 0, 42, 240, 510, 1, 1 },31[9] = { 1, 1, 0, 0, 0, 0, 14, 2490, 3343, 0, 0, 12, 32, 28 },32[10] = { 1, 1, 0, 0, 0, 0, 14, 2490, 3343, 0, 0, 15, 32, 24 },33[11] = { 1, 1, 0, 0, 0, 0, 14, 823, 2510, 0, 0, 18, 32, 28 },34[12] = { 1, 1, 0, 0, 0, 0, 14, 823, 2510, 0, 0, 27, 32, 24 },35},36};3738static const struct mt7615_dfs_radar_spec fcc_radar_specs = {39.pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },40.radar_pattern = {41[0] = { 1, 0, 9, 32, 28, 0, 13, 508, 3076, 1, 1 },42[1] = { 1, 0, 12, 32, 28, 0, 17, 140, 240, 1, 1 },43[2] = { 1, 0, 8, 32, 28, 0, 22, 190, 510, 1, 1 },44[3] = { 1, 0, 6, 32, 28, 0, 32, 190, 510, 1, 1 },45[4] = { 1, 0, 9, 255, 28, 0, 13, 323, 343, 1, 32 },46},47};4849static const struct mt7615_dfs_radar_spec jp_radar_specs = {50.pulse_th = { 110, -10, -80, 40, 5200, 128, 5200 },51.radar_pattern = {52[0] = { 1, 0, 8, 32, 28, 0, 13, 508, 3076, 1, 1 },53[1] = { 1, 0, 12, 32, 28, 0, 17, 140, 240, 1, 1 },54[2] = { 1, 0, 8, 32, 28, 0, 22, 190, 510, 1, 1 },55[3] = { 1, 0, 6, 32, 28, 0, 32, 190, 510, 1, 1 },56[4] = { 1, 0, 9, 32, 28, 0, 13, 323, 343, 1, 32 },57[13] = { 1, 0, 8, 32, 28, 0, 14, 3836, 3856, 1, 1 },58[14] = { 1, 0, 8, 32, 28, 0, 14, 3990, 4010, 1, 1 },59},60};6162static enum mt76_cipher_type63mt7615_mac_get_cipher(int cipher)64{65switch (cipher) {66case WLAN_CIPHER_SUITE_WEP40:67return MT_CIPHER_WEP40;68case WLAN_CIPHER_SUITE_WEP104:69return MT_CIPHER_WEP104;70case WLAN_CIPHER_SUITE_TKIP:71return MT_CIPHER_TKIP;72case WLAN_CIPHER_SUITE_AES_CMAC:73return MT_CIPHER_BIP_CMAC_128;74case WLAN_CIPHER_SUITE_CCMP:75return MT_CIPHER_AES_CCMP;76case WLAN_CIPHER_SUITE_CCMP_256:77return MT_CIPHER_CCMP_256;78case WLAN_CIPHER_SUITE_GCMP:79return MT_CIPHER_GCMP;80case WLAN_CIPHER_SUITE_GCMP_256:81return MT_CIPHER_GCMP_256;82case WLAN_CIPHER_SUITE_SMS4:83return MT_CIPHER_WAPI;84default:85return MT_CIPHER_NONE;86}87}8889static struct mt76_wcid *mt7615_rx_get_wcid(struct mt7615_dev *dev,90u8 idx, bool unicast)91{92struct mt7615_sta *sta;93struct mt76_wcid *wcid;9495wcid = mt76_wcid_ptr(dev, idx);96if (unicast || !wcid)97return wcid;9899if (!wcid->sta)100return NULL;101102sta = container_of(wcid, struct mt7615_sta, wcid);103if (!sta->vif)104return NULL;105106return &sta->vif->sta.wcid;107}108109void mt7615_mac_reset_counters(struct mt7615_phy *phy)110{111struct mt7615_dev *dev = phy->dev;112int i;113114for (i = 0; i < 4; i++) {115mt76_rr(dev, MT_TX_AGG_CNT(0, i));116mt76_rr(dev, MT_TX_AGG_CNT(1, i));117}118119memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats));120phy->mt76->survey_time = ktime_get_boottime();121122/* reset airtime counters */123mt76_rr(dev, MT_MIB_SDR9(0));124mt76_rr(dev, MT_MIB_SDR9(1));125126mt76_rr(dev, MT_MIB_SDR36(0));127mt76_rr(dev, MT_MIB_SDR36(1));128129mt76_rr(dev, MT_MIB_SDR37(0));130mt76_rr(dev, MT_MIB_SDR37(1));131132mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR);133mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0, MT_WF_RMAC_MIB_RXTIME_CLR);134}135136void mt7615_mac_set_timing(struct mt7615_phy *phy)137{138s16 coverage_class = phy->coverage_class;139struct mt7615_dev *dev = phy->dev;140bool ext_phy = phy != &dev->phy;141u32 val, reg_offset;142u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |143FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);144u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |145FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);146int sifs, offset;147bool is_5ghz = phy->mt76->chandef.chan->band == NL80211_BAND_5GHZ;148149if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))150return;151152if (is_5ghz)153sifs = 16;154else155sifs = 10;156157if (ext_phy) {158coverage_class = max_t(s16, dev->phy.coverage_class,159coverage_class);160mt76_set(dev, MT_ARB_SCR,161MT_ARB_SCR_TX1_DISABLE | MT_ARB_SCR_RX1_DISABLE);162} else {163struct mt7615_phy *phy_ext = mt7615_ext_phy(dev);164165if (phy_ext)166coverage_class = max_t(s16, phy_ext->coverage_class,167coverage_class);168mt76_set(dev, MT_ARB_SCR,169MT_ARB_SCR_TX0_DISABLE | MT_ARB_SCR_RX0_DISABLE);170}171udelay(1);172173offset = 3 * coverage_class;174reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |175FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);176mt76_wr(dev, MT_TMAC_CDTR, cck + reg_offset);177mt76_wr(dev, MT_TMAC_ODTR, ofdm + reg_offset);178179mt76_wr(dev, MT_TMAC_ICR(ext_phy),180FIELD_PREP(MT_IFS_EIFS, 360) |181FIELD_PREP(MT_IFS_RIFS, 2) |182FIELD_PREP(MT_IFS_SIFS, sifs) |183FIELD_PREP(MT_IFS_SLOT, phy->slottime));184185if (phy->slottime < 20 || is_5ghz)186val = MT7615_CFEND_RATE_DEFAULT;187else188val = MT7615_CFEND_RATE_11B;189190mt76_rmw_field(dev, MT_AGG_ACR(ext_phy), MT_AGG_ACR_CFEND_RATE, val);191if (ext_phy)192mt76_clear(dev, MT_ARB_SCR,193MT_ARB_SCR_TX1_DISABLE | MT_ARB_SCR_RX1_DISABLE);194else195mt76_clear(dev, MT_ARB_SCR,196MT_ARB_SCR_TX0_DISABLE | MT_ARB_SCR_RX0_DISABLE);197198}199200static void201mt7615_get_status_freq_info(struct mt7615_dev *dev, struct mt76_phy *mphy,202struct mt76_rx_status *status, u8 chfreq)203{204if (!test_bit(MT76_HW_SCANNING, &mphy->state) &&205!test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) &&206!test_bit(MT76_STATE_ROC, &mphy->state)) {207status->freq = mphy->chandef.chan->center_freq;208status->band = mphy->chandef.chan->band;209return;210}211212status->band = chfreq <= 14 ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;213status->freq = ieee80211_channel_to_frequency(chfreq, status->band);214}215216static void mt7615_mac_fill_tm_rx(struct mt7615_phy *phy, __le32 *rxv)217{218#ifdef CONFIG_NL80211_TESTMODE219u32 rxv1 = le32_to_cpu(rxv[0]);220u32 rxv3 = le32_to_cpu(rxv[2]);221u32 rxv4 = le32_to_cpu(rxv[3]);222u32 rxv5 = le32_to_cpu(rxv[4]);223u8 cbw = FIELD_GET(MT_RXV1_FRAME_MODE, rxv1);224u8 mode = FIELD_GET(MT_RXV1_TX_MODE, rxv1);225s16 foe = FIELD_GET(MT_RXV5_FOE, rxv5);226u32 foe_const = (BIT(cbw + 1) & 0xf) * 10000;227228if (!mode) {229/* CCK */230foe &= ~BIT(11);231foe *= 1000;232foe >>= 11;233} else {234if (foe > 2048)235foe -= 4096;236237foe = (foe * foe_const) >> 15;238}239240phy->test.last_freq_offset = foe;241phy->test.last_rcpi[0] = FIELD_GET(MT_RXV4_RCPI0, rxv4);242phy->test.last_rcpi[1] = FIELD_GET(MT_RXV4_RCPI1, rxv4);243phy->test.last_rcpi[2] = FIELD_GET(MT_RXV4_RCPI2, rxv4);244phy->test.last_rcpi[3] = FIELD_GET(MT_RXV4_RCPI3, rxv4);245phy->test.last_ib_rssi[0] = FIELD_GET(MT_RXV3_IB_RSSI, rxv3);246phy->test.last_wb_rssi[0] = FIELD_GET(MT_RXV3_WB_RSSI, rxv3);247#endif248}249250/* The HW does not translate the mac header to 802.3 for mesh point */251static int mt7615_reverse_frag0_hdr_trans(struct sk_buff *skb, u16 hdr_gap)252{253struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;254struct ethhdr *eth_hdr = (struct ethhdr *)(skb->data + hdr_gap);255struct mt7615_sta *msta = (struct mt7615_sta *)status->wcid;256__le32 *rxd = (__le32 *)skb->data;257struct ieee80211_sta *sta;258struct ieee80211_vif *vif;259struct ieee80211_hdr hdr;260u16 frame_control;261262if (le32_get_bits(rxd[1], MT_RXD1_NORMAL_ADDR_TYPE) !=263MT_RXD1_NORMAL_U2M)264return -EINVAL;265266if (!(le32_to_cpu(rxd[0]) & MT_RXD0_NORMAL_GROUP_4))267return -EINVAL;268269if (!msta || !msta->vif)270return -EINVAL;271272sta = container_of((void *)msta, struct ieee80211_sta, drv_priv);273vif = container_of((void *)msta->vif, struct ieee80211_vif, drv_priv);274275/* store the info from RXD and ethhdr to avoid being overridden */276frame_control = le32_get_bits(rxd[4], MT_RXD4_FRAME_CONTROL);277hdr.frame_control = cpu_to_le16(frame_control);278hdr.seq_ctrl = cpu_to_le16(le32_get_bits(rxd[6], MT_RXD6_SEQ_CTRL));279hdr.duration_id = 0;280281ether_addr_copy(hdr.addr1, vif->addr);282ether_addr_copy(hdr.addr2, sta->addr);283switch (frame_control & (IEEE80211_FCTL_TODS |284IEEE80211_FCTL_FROMDS)) {285case 0:286ether_addr_copy(hdr.addr3, vif->bss_conf.bssid);287break;288case IEEE80211_FCTL_FROMDS:289ether_addr_copy(hdr.addr3, eth_hdr->h_source);290break;291case IEEE80211_FCTL_TODS:292ether_addr_copy(hdr.addr3, eth_hdr->h_dest);293break;294case IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS:295ether_addr_copy(hdr.addr3, eth_hdr->h_dest);296ether_addr_copy(hdr.addr4, eth_hdr->h_source);297break;298default:299break;300}301302skb_pull(skb, hdr_gap + sizeof(struct ethhdr) - 2);303if (eth_hdr->h_proto == cpu_to_be16(ETH_P_AARP) ||304eth_hdr->h_proto == cpu_to_be16(ETH_P_IPX))305ether_addr_copy(skb_push(skb, ETH_ALEN), bridge_tunnel_header);306else if (be16_to_cpu(eth_hdr->h_proto) >= ETH_P_802_3_MIN)307ether_addr_copy(skb_push(skb, ETH_ALEN), rfc1042_header);308else309skb_pull(skb, 2);310311if (ieee80211_has_order(hdr.frame_control))312memcpy(skb_push(skb, IEEE80211_HT_CTL_LEN), &rxd[7],313IEEE80211_HT_CTL_LEN);314315if (ieee80211_is_data_qos(hdr.frame_control)) {316__le16 qos_ctrl;317318qos_ctrl = cpu_to_le16(le32_get_bits(rxd[6], MT_RXD6_QOS_CTL));319memcpy(skb_push(skb, IEEE80211_QOS_CTL_LEN), &qos_ctrl,320IEEE80211_QOS_CTL_LEN);321}322323if (ieee80211_has_a4(hdr.frame_control))324memcpy(skb_push(skb, sizeof(hdr)), &hdr, sizeof(hdr));325else326memcpy(skb_push(skb, sizeof(hdr) - 6), &hdr, sizeof(hdr) - 6);327328status->flag &= ~(RX_FLAG_RADIOTAP_HE | RX_FLAG_RADIOTAP_HE_MU);329return 0;330}331332static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)333{334struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;335struct mt76_phy *mphy = &dev->mt76.phy;336struct mt7615_phy *phy = &dev->phy;337struct ieee80211_supported_band *sband;338struct ieee80211_hdr *hdr;339struct mt7615_phy *phy2;340__le32 *rxd = (__le32 *)skb->data;341u32 rxd0 = le32_to_cpu(rxd[0]);342u32 rxd1 = le32_to_cpu(rxd[1]);343u32 rxd2 = le32_to_cpu(rxd[2]);344u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM;345u32 csum_status = *(u32 *)skb->cb;346bool unicast, hdr_trans, remove_pad, insert_ccmp_hdr = false;347u16 hdr_gap;348int phy_idx;349int i, idx;350u8 chfreq, amsdu_info, qos_ctl = 0;351u16 seq_ctrl = 0;352__le16 fc = 0;353354memset(status, 0, sizeof(*status));355356chfreq = FIELD_GET(MT_RXD1_NORMAL_CH_FREQ, rxd1);357358phy2 = dev->mt76.phys[MT_BAND1] ? dev->mt76.phys[MT_BAND1]->priv : NULL;359if (!phy2)360phy_idx = 0;361else if (phy2->chfreq == phy->chfreq)362phy_idx = -1;363else if (phy->chfreq == chfreq)364phy_idx = 0;365else if (phy2->chfreq == chfreq)366phy_idx = 1;367else368phy_idx = -1;369370if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR)371return -EINVAL;372373hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS;374if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_CM))375return -EINVAL;376377/* ICV error or CCMP/BIP/WPI MIC error */378if (rxd2 & MT_RXD2_NORMAL_ICV_ERR)379status->flag |= RX_FLAG_ONLY_MONITOR;380381unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M;382idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2);383status->wcid = mt7615_rx_get_wcid(dev, idx, unicast);384385if (status->wcid) {386struct mt7615_sta *msta;387388msta = container_of(status->wcid, struct mt7615_sta, wcid);389mt76_wcid_add_poll(&dev->mt76, &msta->wcid);390}391392if (mt76_is_mmio(&dev->mt76) && (rxd0 & csum_mask) == csum_mask &&393!(csum_status & (BIT(0) | BIT(2) | BIT(3))))394skb->ip_summed = CHECKSUM_UNNECESSARY;395396if (rxd2 & MT_RXD2_NORMAL_FCS_ERR)397status->flag |= RX_FLAG_FAILED_FCS_CRC;398399if (rxd2 & MT_RXD2_NORMAL_TKIP_MIC_ERR)400status->flag |= RX_FLAG_MMIC_ERROR;401402if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 &&403!(rxd2 & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) {404status->flag |= RX_FLAG_DECRYPTED;405status->flag |= RX_FLAG_IV_STRIPPED;406status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED;407}408409remove_pad = rxd1 & MT_RXD1_NORMAL_HDR_OFFSET;410411if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR)412return -EINVAL;413414rxd += 4;415if (rxd0 & MT_RXD0_NORMAL_GROUP_4) {416u32 v0 = le32_to_cpu(rxd[0]);417u32 v2 = le32_to_cpu(rxd[2]);418419fc = cpu_to_le16(FIELD_GET(MT_RXD4_FRAME_CONTROL, v0));420qos_ctl = FIELD_GET(MT_RXD6_QOS_CTL, v2);421seq_ctrl = FIELD_GET(MT_RXD6_SEQ_CTRL, v2);422423rxd += 4;424if ((u8 *)rxd - skb->data >= skb->len)425return -EINVAL;426}427428if (rxd0 & MT_RXD0_NORMAL_GROUP_1) {429u8 *data = (u8 *)rxd;430431if (status->flag & RX_FLAG_DECRYPTED) {432switch (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2)) {433case MT_CIPHER_AES_CCMP:434case MT_CIPHER_CCMP_CCX:435case MT_CIPHER_CCMP_256:436insert_ccmp_hdr =437FIELD_GET(MT_RXD2_NORMAL_FRAG, rxd2);438fallthrough;439case MT_CIPHER_TKIP:440case MT_CIPHER_TKIP_NO_MIC:441case MT_CIPHER_GCMP:442case MT_CIPHER_GCMP_256:443status->iv[0] = data[5];444status->iv[1] = data[4];445status->iv[2] = data[3];446status->iv[3] = data[2];447status->iv[4] = data[1];448status->iv[5] = data[0];449break;450default:451break;452}453}454rxd += 4;455if ((u8 *)rxd - skb->data >= skb->len)456return -EINVAL;457}458459if (rxd0 & MT_RXD0_NORMAL_GROUP_2) {460status->timestamp = le32_to_cpu(rxd[0]);461status->flag |= RX_FLAG_MACTIME_START;462463if (!(rxd2 & (MT_RXD2_NORMAL_NON_AMPDU_SUB |464MT_RXD2_NORMAL_NON_AMPDU))) {465status->flag |= RX_FLAG_AMPDU_DETAILS;466467/* all subframes of an A-MPDU have the same timestamp */468if (phy->rx_ampdu_ts != status->timestamp) {469if (!++phy->ampdu_ref)470phy->ampdu_ref++;471}472phy->rx_ampdu_ts = status->timestamp;473474status->ampdu_ref = phy->ampdu_ref;475}476477rxd += 2;478if ((u8 *)rxd - skb->data >= skb->len)479return -EINVAL;480}481482if (rxd0 & MT_RXD0_NORMAL_GROUP_3) {483u32 rxdg5 = le32_to_cpu(rxd[5]);484485/*486* If both PHYs are on the same channel and we don't have a WCID,487* we need to figure out which PHY this packet was received on.488* On the primary PHY, the noise value for the chains belonging to the489* second PHY will be set to the noise value of the last packet from490* that PHY.491*/492if (phy_idx < 0) {493int first_chain = ffs(phy2->mt76->chainmask) - 1;494495phy_idx = ((rxdg5 >> (first_chain * 8)) & 0xff) == 0;496}497}498499if (phy_idx == 1 && phy2) {500mphy = dev->mt76.phys[MT_BAND1];501phy = phy2;502status->phy_idx = phy_idx;503}504505if (!mt7615_firmware_offload(dev) && chfreq != phy->chfreq)506return -EINVAL;507508mt7615_get_status_freq_info(dev, mphy, status, chfreq);509if (status->band == NL80211_BAND_5GHZ)510sband = &mphy->sband_5g.sband;511else512sband = &mphy->sband_2g.sband;513514if (!test_bit(MT76_STATE_RUNNING, &mphy->state))515return -EINVAL;516517if (!sband->channels)518return -EINVAL;519520if (rxd0 & MT_RXD0_NORMAL_GROUP_3) {521u32 rxdg0 = le32_to_cpu(rxd[0]);522u32 rxdg1 = le32_to_cpu(rxd[1]);523u32 rxdg3 = le32_to_cpu(rxd[3]);524u8 stbc = FIELD_GET(MT_RXV1_HT_STBC, rxdg0);525bool cck = false;526527i = FIELD_GET(MT_RXV1_TX_RATE, rxdg0);528switch (FIELD_GET(MT_RXV1_TX_MODE, rxdg0)) {529case MT_PHY_TYPE_CCK:530cck = true;531fallthrough;532case MT_PHY_TYPE_OFDM:533i = mt76_get_rate(&dev->mt76, sband, i, cck);534break;535case MT_PHY_TYPE_HT_GF:536case MT_PHY_TYPE_HT:537status->encoding = RX_ENC_HT;538if (i > 31)539return -EINVAL;540break;541case MT_PHY_TYPE_VHT:542status->nss = FIELD_GET(MT_RXV2_NSTS, rxdg1) + 1;543status->encoding = RX_ENC_VHT;544break;545default:546return -EINVAL;547}548status->rate_idx = i;549550switch (FIELD_GET(MT_RXV1_FRAME_MODE, rxdg0)) {551case MT_PHY_BW_20:552break;553case MT_PHY_BW_40:554status->bw = RATE_INFO_BW_40;555break;556case MT_PHY_BW_80:557status->bw = RATE_INFO_BW_80;558break;559case MT_PHY_BW_160:560status->bw = RATE_INFO_BW_160;561break;562default:563return -EINVAL;564}565566if (rxdg0 & MT_RXV1_HT_SHORT_GI)567status->enc_flags |= RX_ENC_FLAG_SHORT_GI;568if (rxdg0 & MT_RXV1_HT_AD_CODE)569status->enc_flags |= RX_ENC_FLAG_LDPC;570571status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc;572573status->chains = mphy->antenna_mask;574status->chain_signal[0] = to_rssi(MT_RXV4_RCPI0, rxdg3);575status->chain_signal[1] = to_rssi(MT_RXV4_RCPI1, rxdg3);576status->chain_signal[2] = to_rssi(MT_RXV4_RCPI2, rxdg3);577status->chain_signal[3] = to_rssi(MT_RXV4_RCPI3, rxdg3);578579mt7615_mac_fill_tm_rx(mphy->priv, rxd);580581rxd += 6;582if ((u8 *)rxd - skb->data >= skb->len)583return -EINVAL;584}585586amsdu_info = FIELD_GET(MT_RXD1_NORMAL_PAYLOAD_FORMAT, rxd1);587status->amsdu = !!amsdu_info;588if (status->amsdu) {589status->first_amsdu = amsdu_info == MT_RXD1_FIRST_AMSDU_FRAME;590status->last_amsdu = amsdu_info == MT_RXD1_LAST_AMSDU_FRAME;591}592593hdr_gap = (u8 *)rxd - skb->data + 2 * remove_pad;594if (hdr_trans && ieee80211_has_morefrags(fc)) {595if (mt7615_reverse_frag0_hdr_trans(skb, hdr_gap))596return -EINVAL;597hdr_trans = false;598} else {599int pad_start = 0;600601skb_pull(skb, hdr_gap);602if (!hdr_trans && status->amsdu) {603pad_start = ieee80211_get_hdrlen_from_skb(skb);604} else if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_HDR_TRANS_ERROR)) {605/*606* When header translation failure is indicated,607* the hardware will insert an extra 2-byte field608* containing the data length after the protocol609* type field. This happens either when the LLC-SNAP610* pattern did not match, or if a VLAN header was611* detected.612*/613pad_start = 12;614if (get_unaligned_be16(skb->data + pad_start) == ETH_P_8021Q)615pad_start += 4;616else617pad_start = 0;618}619620if (pad_start) {621memmove(skb->data + 2, skb->data, pad_start);622skb_pull(skb, 2);623}624}625626if (insert_ccmp_hdr && !hdr_trans) {627u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1);628629mt76_insert_ccmp_hdr(skb, key_id);630}631632if (!hdr_trans) {633hdr = (struct ieee80211_hdr *)skb->data;634fc = hdr->frame_control;635if (ieee80211_is_data_qos(fc)) {636seq_ctrl = le16_to_cpu(hdr->seq_ctrl);637qos_ctl = *ieee80211_get_qos_ctl(hdr);638}639} else {640status->flag |= RX_FLAG_8023;641}642643if (!status->wcid || !ieee80211_is_data_qos(fc))644return 0;645646status->aggr = unicast &&647!ieee80211_is_qos_nullfunc(fc);648status->qos_ctl = qos_ctl;649status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl);650651return 0;652}653654static u16655mt7615_mac_tx_rate_val(struct mt7615_dev *dev,656struct mt76_phy *mphy,657const struct ieee80211_tx_rate *rate,658bool stbc, u8 *bw)659{660u8 phy, nss, rate_idx;661u16 rateval = 0;662663*bw = 0;664665if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {666rate_idx = ieee80211_rate_get_vht_mcs(rate);667nss = ieee80211_rate_get_vht_nss(rate);668phy = MT_PHY_TYPE_VHT;669if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)670*bw = 1;671else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)672*bw = 2;673else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)674*bw = 3;675} else if (rate->flags & IEEE80211_TX_RC_MCS) {676rate_idx = rate->idx;677nss = 1 + (rate->idx >> 3);678phy = MT_PHY_TYPE_HT;679if (rate->flags & IEEE80211_TX_RC_GREEN_FIELD)680phy = MT_PHY_TYPE_HT_GF;681if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)682*bw = 1;683} else {684const struct ieee80211_rate *r;685int band = mphy->chandef.chan->band;686u16 val;687688nss = 1;689r = &mphy->hw->wiphy->bands[band]->bitrates[rate->idx];690if (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)691val = r->hw_value_short;692else693val = r->hw_value;694695phy = val >> 8;696rate_idx = val & 0xff;697}698699if (stbc && nss == 1) {700nss++;701rateval |= MT_TX_RATE_STBC;702}703704rateval |= (FIELD_PREP(MT_TX_RATE_IDX, rate_idx) |705FIELD_PREP(MT_TX_RATE_MODE, phy) |706FIELD_PREP(MT_TX_RATE_NSS, nss - 1));707708return rateval;709}710711int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi,712struct sk_buff *skb, struct mt76_wcid *wcid,713struct ieee80211_sta *sta, int pid,714struct ieee80211_key_conf *key,715enum mt76_txq_id qid, bool beacon)716{717struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;718u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;719struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);720struct ieee80211_tx_rate *rate = &info->control.rates[0];721u8 phy_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2;722bool multicast = is_multicast_ether_addr(hdr->addr1);723struct ieee80211_vif *vif = info->control.vif;724bool is_mmio = mt76_is_mmio(&dev->mt76);725u32 val, sz_txd = is_mmio ? MT_TXD_SIZE : MT_USB_TXD_SIZE;726struct mt76_phy *mphy = &dev->mphy;727__le16 fc = hdr->frame_control;728int tx_count = 8;729u16 seqno = 0;730731if (vif) {732struct mt76_vif_link *mvif = (struct mt76_vif_link *)vif->drv_priv;733734omac_idx = mvif->omac_idx;735wmm_idx = mvif->wmm_idx;736}737738if (sta) {739struct mt7615_sta *msta = (struct mt7615_sta *)sta->drv_priv;740741tx_count = msta->rate_count;742}743744if (phy_idx && dev->mt76.phys[MT_BAND1])745mphy = dev->mt76.phys[MT_BAND1];746747fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;748fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;749750if (beacon) {751p_fmt = MT_TX_TYPE_FW;752q_idx = phy_idx ? MT_LMAC_BCN1 : MT_LMAC_BCN0;753} else if (qid >= MT_TXQ_PSD) {754p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;755q_idx = phy_idx ? MT_LMAC_ALTX1 : MT_LMAC_ALTX0;756} else {757p_fmt = is_mmio ? MT_TX_TYPE_CT : MT_TX_TYPE_SF;758q_idx = wmm_idx * MT7615_MAX_WMM_SETS +759mt7615_lmac_mapping(dev, skb_get_queue_mapping(skb));760}761762val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) |763FIELD_PREP(MT_TXD0_P_IDX, MT_TX_PORT_IDX_LMAC) |764FIELD_PREP(MT_TXD0_Q_IDX, q_idx);765txwi[0] = cpu_to_le32(val);766767val = MT_TXD1_LONG_FORMAT |768FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |769FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |770FIELD_PREP(MT_TXD1_HDR_INFO,771ieee80211_get_hdrlen_from_skb(skb) / 2) |772FIELD_PREP(MT_TXD1_TID,773skb->priority & IEEE80211_QOS_CTL_TID_MASK) |774FIELD_PREP(MT_TXD1_PKT_FMT, p_fmt) |775FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);776txwi[1] = cpu_to_le32(val);777778val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |779FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) |780FIELD_PREP(MT_TXD2_MULTICAST, multicast);781if (key) {782if (multicast && ieee80211_is_robust_mgmt_frame(skb) &&783key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {784val |= MT_TXD2_BIP;785txwi[3] = 0;786} else {787txwi[3] = cpu_to_le32(MT_TXD3_PROTECT_FRAME);788}789} else {790txwi[3] = 0;791}792txwi[2] = cpu_to_le32(val);793794if (!(info->flags & IEEE80211_TX_CTL_AMPDU))795txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE);796797txwi[4] = 0;798txwi[6] = 0;799800if (rate->idx >= 0 && rate->count &&801!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)) {802bool stbc = info->flags & IEEE80211_TX_CTL_STBC;803u8 bw;804u16 rateval = mt7615_mac_tx_rate_val(dev, mphy, rate, stbc,805&bw);806807txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE);808809val = MT_TXD6_FIXED_BW |810FIELD_PREP(MT_TXD6_BW, bw) |811FIELD_PREP(MT_TXD6_TX_RATE, rateval);812txwi[6] |= cpu_to_le32(val);813814if (rate->flags & IEEE80211_TX_RC_SHORT_GI)815txwi[6] |= cpu_to_le32(MT_TXD6_SGI);816817if (info->flags & IEEE80211_TX_CTL_LDPC)818txwi[6] |= cpu_to_le32(MT_TXD6_LDPC);819820if (!(rate->flags & (IEEE80211_TX_RC_MCS |821IEEE80211_TX_RC_VHT_MCS)))822txwi[2] |= cpu_to_le32(MT_TXD2_BA_DISABLE);823824tx_count = rate->count;825}826827if (!ieee80211_is_beacon(fc)) {828struct ieee80211_hw *hw = mt76_hw(dev);829830val = MT_TXD5_TX_STATUS_HOST | FIELD_PREP(MT_TXD5_PID, pid);831if (!ieee80211_hw_check(hw, SUPPORTS_PS))832val |= MT_TXD5_SW_POWER_MGMT;833txwi[5] = cpu_to_le32(val);834} else {835txwi[5] = 0;836/* use maximum tx count for beacons */837tx_count = 0x1f;838}839840val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);841if (info->flags & IEEE80211_TX_CTL_INJECTED) {842seqno = le16_to_cpu(hdr->seq_ctrl);843844if (ieee80211_is_back_req(hdr->frame_control)) {845struct ieee80211_bar *bar;846847bar = (struct ieee80211_bar *)skb->data;848seqno = le16_to_cpu(bar->start_seq_num);849}850851val |= MT_TXD3_SN_VALID |852FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));853}854855txwi[3] |= cpu_to_le32(val);856857if (info->flags & IEEE80211_TX_CTL_NO_ACK)858txwi[3] |= cpu_to_le32(MT_TXD3_NO_ACK);859860val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |861FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype) |862FIELD_PREP(MT_TXD7_SPE_IDX, 0x18);863txwi[7] = cpu_to_le32(val);864if (!is_mmio) {865val = FIELD_PREP(MT_TXD8_L_TYPE, fc_type) |866FIELD_PREP(MT_TXD8_L_SUB_TYPE, fc_stype);867txwi[8] = cpu_to_le32(val);868}869870return 0;871}872EXPORT_SYMBOL_GPL(mt7615_mac_write_txwi);873874bool mt7615_mac_wtbl_update(struct mt7615_dev *dev, int idx, u32 mask)875{876mt76_rmw(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_WLAN_IDX,877FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, idx) | mask);878879return mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY,8800, 5000);881}882883void mt7615_mac_sta_poll(struct mt7615_dev *dev)884{885static const u8 ac_to_tid[4] = {886[IEEE80211_AC_BE] = 0,887[IEEE80211_AC_BK] = 1,888[IEEE80211_AC_VI] = 4,889[IEEE80211_AC_VO] = 6890};891static const u8 hw_queue_map[] = {892[IEEE80211_AC_BK] = 0,893[IEEE80211_AC_BE] = 1,894[IEEE80211_AC_VI] = 2,895[IEEE80211_AC_VO] = 3,896};897struct ieee80211_sta *sta;898struct mt7615_sta *msta;899u32 addr, tx_time[4], rx_time[4];900struct list_head sta_poll_list;901int i;902903INIT_LIST_HEAD(&sta_poll_list);904spin_lock_bh(&dev->mt76.sta_poll_lock);905list_splice_init(&dev->mt76.sta_poll_list, &sta_poll_list);906spin_unlock_bh(&dev->mt76.sta_poll_lock);907908while (!list_empty(&sta_poll_list)) {909bool clear = false;910911msta = list_first_entry(&sta_poll_list, struct mt7615_sta,912wcid.poll_list);913914spin_lock_bh(&dev->mt76.sta_poll_lock);915list_del_init(&msta->wcid.poll_list);916spin_unlock_bh(&dev->mt76.sta_poll_lock);917918addr = mt7615_mac_wtbl_addr(dev, msta->wcid.idx) + 19 * 4;919920for (i = 0; i < 4; i++, addr += 8) {921u32 tx_last = msta->airtime_ac[i];922u32 rx_last = msta->airtime_ac[i + 4];923924msta->airtime_ac[i] = mt76_rr(dev, addr);925msta->airtime_ac[i + 4] = mt76_rr(dev, addr + 4);926tx_time[i] = msta->airtime_ac[i] - tx_last;927rx_time[i] = msta->airtime_ac[i + 4] - rx_last;928929if ((tx_last | rx_last) & BIT(30))930clear = true;931}932933if (clear) {934mt7615_mac_wtbl_update(dev, msta->wcid.idx,935MT_WTBL_UPDATE_ADM_COUNT_CLEAR);936memset(msta->airtime_ac, 0, sizeof(msta->airtime_ac));937}938939if (!msta->wcid.sta)940continue;941942sta = container_of((void *)msta, struct ieee80211_sta,943drv_priv);944for (i = 0; i < 4; i++) {945u32 tx_cur = tx_time[i];946u32 rx_cur = rx_time[hw_queue_map[i]];947u8 tid = ac_to_tid[i];948949if (!tx_cur && !rx_cur)950continue;951952ieee80211_sta_register_airtime(sta, tid, tx_cur,953rx_cur);954}955}956}957EXPORT_SYMBOL_GPL(mt7615_mac_sta_poll);958959static void960mt7615_mac_update_rate_desc(struct mt7615_phy *phy, struct mt7615_sta *sta,961struct ieee80211_tx_rate *probe_rate,962struct ieee80211_tx_rate *rates,963struct mt7615_rate_desc *rd)964{965struct mt7615_dev *dev = phy->dev;966struct mt76_phy *mphy = phy->mt76;967struct ieee80211_tx_rate *ref;968bool rateset, stbc = false;969int n_rates = sta->n_rates;970u8 bw, bw_prev;971int i, j;972973for (i = n_rates; i < 4; i++)974rates[i] = rates[n_rates - 1];975976rateset = !(sta->rate_set_tsf & BIT(0));977memcpy(sta->rateset[rateset].rates, rates,978sizeof(sta->rateset[rateset].rates));979if (probe_rate) {980sta->rateset[rateset].probe_rate = *probe_rate;981ref = &sta->rateset[rateset].probe_rate;982} else {983sta->rateset[rateset].probe_rate.idx = -1;984ref = &sta->rateset[rateset].rates[0];985}986987rates = sta->rateset[rateset].rates;988for (i = 0; i < ARRAY_SIZE(sta->rateset[rateset].rates); i++) {989/*990* We don't support switching between short and long GI991* within the rate set. For accurate tx status reporting, we992* need to make sure that flags match.993* For improved performance, avoid duplicate entries by994* decrementing the MCS index if necessary995*/996if ((ref->flags ^ rates[i].flags) & IEEE80211_TX_RC_SHORT_GI)997rates[i].flags ^= IEEE80211_TX_RC_SHORT_GI;998999for (j = 0; j < i; j++) {1000if (rates[i].idx != rates[j].idx)1001continue;1002if ((rates[i].flags ^ rates[j].flags) &1003(IEEE80211_TX_RC_40_MHZ_WIDTH |1004IEEE80211_TX_RC_80_MHZ_WIDTH |1005IEEE80211_TX_RC_160_MHZ_WIDTH))1006continue;10071008if (!rates[i].idx)1009continue;10101011rates[i].idx--;1012}1013}10141015rd->val[0] = mt7615_mac_tx_rate_val(dev, mphy, &rates[0], stbc, &bw);1016bw_prev = bw;10171018if (probe_rate) {1019rd->probe_val = mt7615_mac_tx_rate_val(dev, mphy, probe_rate,1020stbc, &bw);1021if (bw)1022rd->bw_idx = 1;1023else1024bw_prev = 0;1025} else {1026rd->probe_val = rd->val[0];1027}10281029rd->val[1] = mt7615_mac_tx_rate_val(dev, mphy, &rates[1], stbc, &bw);1030if (bw_prev) {1031rd->bw_idx = 3;1032bw_prev = bw;1033}10341035rd->val[2] = mt7615_mac_tx_rate_val(dev, mphy, &rates[2], stbc, &bw);1036if (bw_prev) {1037rd->bw_idx = 5;1038bw_prev = bw;1039}10401041rd->val[3] = mt7615_mac_tx_rate_val(dev, mphy, &rates[3], stbc, &bw);1042if (bw_prev)1043rd->bw_idx = 7;10441045rd->rateset = rateset;1046rd->bw = bw;1047}10481049static int1050mt7615_mac_queue_rate_update(struct mt7615_phy *phy, struct mt7615_sta *sta,1051struct ieee80211_tx_rate *probe_rate,1052struct ieee80211_tx_rate *rates)1053{1054struct mt7615_dev *dev = phy->dev;1055struct mt7615_wtbl_rate_desc *wrd;10561057if (work_pending(&dev->rate_work))1058return -EBUSY;10591060wrd = kzalloc(sizeof(*wrd), GFP_ATOMIC);1061if (!wrd)1062return -ENOMEM;10631064wrd->sta = sta;1065mt7615_mac_update_rate_desc(phy, sta, probe_rate, rates,1066&wrd->rate);1067list_add_tail(&wrd->node, &dev->wrd_head);1068queue_work(dev->mt76.wq, &dev->rate_work);10691070return 0;1071}10721073u32 mt7615_mac_get_sta_tid_sn(struct mt7615_dev *dev, int wcid, u8 tid)1074{1075u32 addr, val, val2;1076u8 offset;10771078addr = mt7615_mac_wtbl_addr(dev, wcid) + 11 * 4;10791080offset = tid * 12;1081addr += 4 * (offset / 32);1082offset %= 32;10831084val = mt76_rr(dev, addr);1085val >>= offset;10861087if (offset > 20) {1088addr += 4;1089val2 = mt76_rr(dev, addr);1090val |= val2 << (32 - offset);1091}10921093return val & GENMASK(11, 0);1094}10951096void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,1097struct ieee80211_tx_rate *probe_rate,1098struct ieee80211_tx_rate *rates)1099{1100int wcid = sta->wcid.idx, n_rates = sta->n_rates;1101struct mt7615_dev *dev = phy->dev;1102struct mt7615_rate_desc rd;1103u32 w5, w27, addr;1104u16 idx = sta->vif->mt76.omac_idx;11051106if (!mt76_is_mmio(&dev->mt76)) {1107mt7615_mac_queue_rate_update(phy, sta, probe_rate, rates);1108return;1109}11101111if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000))1112return;11131114memset(&rd, 0, sizeof(struct mt7615_rate_desc));1115mt7615_mac_update_rate_desc(phy, sta, probe_rate, rates, &rd);11161117addr = mt7615_mac_wtbl_addr(dev, wcid);1118w27 = mt76_rr(dev, addr + 27 * 4);1119w27 &= ~MT_WTBL_W27_CC_BW_SEL;1120w27 |= FIELD_PREP(MT_WTBL_W27_CC_BW_SEL, rd.bw);11211122w5 = mt76_rr(dev, addr + 5 * 4);1123w5 &= ~(MT_WTBL_W5_BW_CAP | MT_WTBL_W5_CHANGE_BW_RATE |1124MT_WTBL_W5_MPDU_OK_COUNT |1125MT_WTBL_W5_MPDU_FAIL_COUNT |1126MT_WTBL_W5_RATE_IDX);1127w5 |= FIELD_PREP(MT_WTBL_W5_BW_CAP, rd.bw) |1128FIELD_PREP(MT_WTBL_W5_CHANGE_BW_RATE,1129rd.bw_idx ? rd.bw_idx - 1 : 7);11301131mt76_wr(dev, MT_WTBL_RIUCR0, w5);11321133mt76_wr(dev, MT_WTBL_RIUCR1,1134FIELD_PREP(MT_WTBL_RIUCR1_RATE0, rd.probe_val) |1135FIELD_PREP(MT_WTBL_RIUCR1_RATE1, rd.val[0]) |1136FIELD_PREP(MT_WTBL_RIUCR1_RATE2_LO, rd.val[1]));11371138mt76_wr(dev, MT_WTBL_RIUCR2,1139FIELD_PREP(MT_WTBL_RIUCR2_RATE2_HI, rd.val[1] >> 8) |1140FIELD_PREP(MT_WTBL_RIUCR2_RATE3, rd.val[1]) |1141FIELD_PREP(MT_WTBL_RIUCR2_RATE4, rd.val[2]) |1142FIELD_PREP(MT_WTBL_RIUCR2_RATE5_LO, rd.val[2]));11431144mt76_wr(dev, MT_WTBL_RIUCR3,1145FIELD_PREP(MT_WTBL_RIUCR3_RATE5_HI, rd.val[2] >> 4) |1146FIELD_PREP(MT_WTBL_RIUCR3_RATE6, rd.val[3]) |1147FIELD_PREP(MT_WTBL_RIUCR3_RATE7, rd.val[3]));11481149mt76_wr(dev, MT_WTBL_UPDATE,1150FIELD_PREP(MT_WTBL_UPDATE_WLAN_IDX, wcid) |1151MT_WTBL_UPDATE_RATE_UPDATE |1152MT_WTBL_UPDATE_TX_COUNT_CLEAR);11531154mt76_wr(dev, addr + 27 * 4, w27);11551156idx = idx > HW_BSSID_MAX ? HW_BSSID_0 : idx;1157addr = idx > 1 ? MT_LPON_TCR2(idx): MT_LPON_TCR0(idx);11581159mt76_rmw(dev, addr, MT_LPON_TCR_MODE, MT_LPON_TCR_READ); /* TSF read */1160sta->rate_set_tsf = mt76_rr(dev, MT_LPON_UTTR0) & ~BIT(0);1161sta->rate_set_tsf |= rd.rateset;11621163if (!(sta->wcid.tx_info & MT_WCID_TX_INFO_SET))1164mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000);11651166sta->rate_count = 2 * MT7615_RATE_RETRY * n_rates;1167sta->wcid.tx_info |= MT_WCID_TX_INFO_SET;1168sta->rate_probe = !!probe_rate;1169}1170EXPORT_SYMBOL_GPL(mt7615_mac_set_rates);11711172void mt7615_mac_enable_rtscts(struct mt7615_dev *dev,1173struct ieee80211_vif *vif, bool enable)1174{1175struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv;1176u32 addr;11771178addr = mt7615_mac_wtbl_addr(dev, mvif->sta.wcid.idx) + 3 * 4;11791180if (enable)1181mt76_set(dev, addr, MT_WTBL_W3_RTS);1182else1183mt76_clear(dev, addr, MT_WTBL_W3_RTS);1184}1185EXPORT_SYMBOL_GPL(mt7615_mac_enable_rtscts);11861187static int1188mt7615_mac_wtbl_update_key(struct mt7615_dev *dev, struct mt76_wcid *wcid,1189struct ieee80211_key_conf *key,1190enum mt76_cipher_type cipher, u16 cipher_mask)1191{1192u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx) + 30 * 4;1193u8 data[32] = {};11941195if (key->keylen > sizeof(data))1196return -EINVAL;11971198mt76_rr_copy(dev, addr, data, sizeof(data));1199if (cipher == MT_CIPHER_TKIP) {1200/* Rx/Tx MIC keys are swapped */1201memcpy(data, key->key, 16);1202memcpy(data + 16, key->key + 24, 8);1203memcpy(data + 24, key->key + 16, 8);1204} else {1205if (cipher_mask == BIT(cipher))1206memcpy(data, key->key, key->keylen);1207else if (cipher != MT_CIPHER_BIP_CMAC_128)1208memcpy(data, key->key, 16);1209if (cipher == MT_CIPHER_BIP_CMAC_128)1210memcpy(data + 16, key->key, 16);1211}12121213mt76_wr_copy(dev, addr, data, sizeof(data));12141215return 0;1216}12171218static int1219mt7615_mac_wtbl_update_pk(struct mt7615_dev *dev, struct mt76_wcid *wcid,1220enum mt76_cipher_type cipher, u16 cipher_mask,1221int keyidx)1222{1223u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx), w0, w1;12241225if (!mt76_poll(dev, MT_WTBL_UPDATE, MT_WTBL_UPDATE_BUSY, 0, 5000))1226return -ETIMEDOUT;12271228w0 = mt76_rr(dev, addr);1229w1 = mt76_rr(dev, addr + 4);12301231if (cipher_mask)1232w0 |= MT_WTBL_W0_RX_KEY_VALID;1233else1234w0 &= ~(MT_WTBL_W0_RX_KEY_VALID | MT_WTBL_W0_KEY_IDX);1235if (cipher_mask & BIT(MT_CIPHER_BIP_CMAC_128))1236w0 |= MT_WTBL_W0_RX_IK_VALID;1237else1238w0 &= ~MT_WTBL_W0_RX_IK_VALID;12391240if (cipher != MT_CIPHER_BIP_CMAC_128 || cipher_mask == BIT(cipher)) {1241w0 &= ~MT_WTBL_W0_KEY_IDX;1242w0 |= FIELD_PREP(MT_WTBL_W0_KEY_IDX, keyidx);1243}12441245mt76_wr(dev, MT_WTBL_RICR0, w0);1246mt76_wr(dev, MT_WTBL_RICR1, w1);12471248if (!mt7615_mac_wtbl_update(dev, wcid->idx,1249MT_WTBL_UPDATE_RXINFO_UPDATE))1250return -ETIMEDOUT;12511252return 0;1253}12541255static void1256mt7615_mac_wtbl_update_cipher(struct mt7615_dev *dev, struct mt76_wcid *wcid,1257enum mt76_cipher_type cipher, u16 cipher_mask)1258{1259u32 addr = mt7615_mac_wtbl_addr(dev, wcid->idx);12601261if (cipher == MT_CIPHER_BIP_CMAC_128 &&1262cipher_mask & ~BIT(MT_CIPHER_BIP_CMAC_128))1263return;12641265mt76_rmw(dev, addr + 2 * 4, MT_WTBL_W2_KEY_TYPE,1266FIELD_PREP(MT_WTBL_W2_KEY_TYPE, cipher));1267}12681269int __mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,1270struct mt76_wcid *wcid,1271struct ieee80211_key_conf *key)1272{1273enum mt76_cipher_type cipher;1274u16 cipher_mask = wcid->cipher;1275int err;12761277cipher = mt7615_mac_get_cipher(key->cipher);1278if (cipher == MT_CIPHER_NONE)1279return -EOPNOTSUPP;12801281cipher_mask |= BIT(cipher);1282mt7615_mac_wtbl_update_cipher(dev, wcid, cipher, cipher_mask);1283err = mt7615_mac_wtbl_update_key(dev, wcid, key, cipher, cipher_mask);1284if (err < 0)1285return err;12861287err = mt7615_mac_wtbl_update_pk(dev, wcid, cipher, cipher_mask,1288key->keyidx);1289if (err < 0)1290return err;12911292wcid->cipher = cipher_mask;12931294return 0;1295}12961297int mt7615_mac_wtbl_set_key(struct mt7615_dev *dev,1298struct mt76_wcid *wcid,1299struct ieee80211_key_conf *key)1300{1301int err;13021303spin_lock_bh(&dev->mt76.lock);1304err = __mt7615_mac_wtbl_set_key(dev, wcid, key);1305spin_unlock_bh(&dev->mt76.lock);13061307return err;1308}13091310static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta,1311struct ieee80211_tx_info *info, __le32 *txs_data)1312{1313struct ieee80211_supported_band *sband;1314struct mt7615_rate_set *rs;1315struct mt76_phy *mphy;1316int first_idx = 0, last_idx;1317int i, idx, count;1318bool fixed_rate, ack_timeout;1319bool ampdu, cck = false;1320bool rs_idx;1321u32 rate_set_tsf;1322u32 final_rate, final_rate_flags, final_nss, txs;13231324txs = le32_to_cpu(txs_data[1]);1325ampdu = txs & MT_TXS1_AMPDU;13261327txs = le32_to_cpu(txs_data[3]);1328count = FIELD_GET(MT_TXS3_TX_COUNT, txs);1329last_idx = FIELD_GET(MT_TXS3_LAST_TX_RATE, txs);13301331txs = le32_to_cpu(txs_data[0]);1332fixed_rate = txs & MT_TXS0_FIXED_RATE;1333final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs);1334ack_timeout = txs & MT_TXS0_ACK_TIMEOUT;13351336if (!ampdu && (txs & MT_TXS0_RTS_TIMEOUT))1337return false;13381339if (txs & MT_TXS0_QUEUE_TIMEOUT)1340return false;13411342if (!ack_timeout)1343info->flags |= IEEE80211_TX_STAT_ACK;13441345info->status.ampdu_len = 1;1346info->status.ampdu_ack_len = !!(info->flags &1347IEEE80211_TX_STAT_ACK);13481349if (ampdu || (info->flags & IEEE80211_TX_CTL_AMPDU))1350info->flags |= IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_CTL_AMPDU;13511352first_idx = max_t(int, 0, last_idx - (count - 1) / MT7615_RATE_RETRY);13531354if (fixed_rate) {1355info->status.rates[0].count = count;1356i = 0;1357goto out;1358}13591360rate_set_tsf = READ_ONCE(sta->rate_set_tsf);1361rs_idx = !((u32)(le32_get_bits(txs_data[4], MT_TXS4_F0_TIMESTAMP) -1362rate_set_tsf) < 1000000);1363rs_idx ^= rate_set_tsf & BIT(0);1364rs = &sta->rateset[rs_idx];13651366if (!first_idx && rs->probe_rate.idx >= 0) {1367info->status.rates[0] = rs->probe_rate;13681369spin_lock_bh(&dev->mt76.lock);1370if (sta->rate_probe) {1371struct mt7615_phy *phy = &dev->phy;13721373if (sta->wcid.phy_idx && dev->mt76.phys[MT_BAND1])1374phy = dev->mt76.phys[MT_BAND1]->priv;13751376mt7615_mac_set_rates(phy, sta, NULL, sta->rates);1377}1378spin_unlock_bh(&dev->mt76.lock);1379} else {1380info->status.rates[0] = rs->rates[first_idx / 2];1381}1382info->status.rates[0].count = 0;13831384for (i = 0, idx = first_idx; count && idx <= last_idx; idx++) {1385struct ieee80211_tx_rate *cur_rate;1386int cur_count;13871388cur_rate = &rs->rates[idx / 2];1389cur_count = min_t(int, MT7615_RATE_RETRY, count);1390count -= cur_count;13911392if (idx && (cur_rate->idx != info->status.rates[i].idx ||1393cur_rate->flags != info->status.rates[i].flags)) {1394i++;1395if (i == ARRAY_SIZE(info->status.rates)) {1396i--;1397break;1398}13991400info->status.rates[i] = *cur_rate;1401info->status.rates[i].count = 0;1402}14031404info->status.rates[i].count += cur_count;1405}14061407out:1408final_rate_flags = info->status.rates[i].flags;14091410switch (FIELD_GET(MT_TX_RATE_MODE, final_rate)) {1411case MT_PHY_TYPE_CCK:1412cck = true;1413fallthrough;1414case MT_PHY_TYPE_OFDM:1415mphy = &dev->mphy;1416if (sta->wcid.phy_idx && dev->mt76.phys[MT_BAND1])1417mphy = dev->mt76.phys[MT_BAND1];14181419if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)1420sband = &mphy->sband_5g.sband;1421else1422sband = &mphy->sband_2g.sband;1423final_rate &= MT_TX_RATE_IDX;1424final_rate = mt76_get_rate(&dev->mt76, sband, final_rate,1425cck);1426final_rate_flags = 0;1427break;1428case MT_PHY_TYPE_HT_GF:1429case MT_PHY_TYPE_HT:1430final_rate_flags |= IEEE80211_TX_RC_MCS;1431final_rate &= MT_TX_RATE_IDX;1432if (final_rate > 31)1433return false;1434break;1435case MT_PHY_TYPE_VHT:1436final_nss = FIELD_GET(MT_TX_RATE_NSS, final_rate);14371438if ((final_rate & MT_TX_RATE_STBC) && final_nss)1439final_nss--;14401441final_rate_flags |= IEEE80211_TX_RC_VHT_MCS;1442final_rate = (final_rate & MT_TX_RATE_IDX) | (final_nss << 4);1443break;1444default:1445return false;1446}14471448info->status.rates[i].idx = final_rate;1449info->status.rates[i].flags = final_rate_flags;14501451return true;1452}14531454static bool mt7615_mac_add_txs_skb(struct mt7615_dev *dev,1455struct mt7615_sta *sta, int pid,1456__le32 *txs_data)1457{1458struct mt76_dev *mdev = &dev->mt76;1459struct sk_buff_head list;1460struct sk_buff *skb;14611462if (pid < MT_PACKET_ID_FIRST)1463return false;14641465trace_mac_txdone(mdev, sta->wcid.idx, pid);14661467mt76_tx_status_lock(mdev, &list);1468skb = mt76_tx_status_skb_get(mdev, &sta->wcid, pid, &list);1469if (skb) {1470struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);14711472if (!mt7615_fill_txs(dev, sta, info, txs_data)) {1473info->status.rates[0].count = 0;1474info->status.rates[0].idx = -1;1475}14761477mt76_tx_status_skb_done(mdev, skb, &list);1478}1479mt76_tx_status_unlock(mdev, &list);14801481return !!skb;1482}14831484static void mt7615_mac_add_txs(struct mt7615_dev *dev, void *data)1485{1486struct ieee80211_tx_info info = {};1487struct ieee80211_sta *sta = NULL;1488struct mt7615_sta *msta = NULL;1489struct mt76_wcid *wcid;1490struct mt76_phy *mphy = &dev->mt76.phy;1491__le32 *txs_data = data;1492u8 wcidx;1493u8 pid;14941495pid = le32_get_bits(txs_data[0], MT_TXS0_PID);1496wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID);14971498if (pid == MT_PACKET_ID_NO_ACK)1499return;15001501if (wcidx >= MT7615_WTBL_SIZE)1502return;15031504rcu_read_lock();15051506wcid = mt76_wcid_ptr(dev, wcidx);1507if (!wcid)1508goto out;15091510msta = container_of(wcid, struct mt7615_sta, wcid);1511sta = wcid_to_sta(wcid);1512mt76_wcid_add_poll(&dev->mt76, &msta->wcid);15131514if (mt7615_mac_add_txs_skb(dev, msta, pid, txs_data))1515goto out;15161517if (wcidx >= MT7615_WTBL_STA || !sta)1518goto out;15191520if (wcid->phy_idx && dev->mt76.phys[MT_BAND1])1521mphy = dev->mt76.phys[MT_BAND1];15221523if (mt7615_fill_txs(dev, msta, &info, txs_data)) {1524spin_lock_bh(&dev->mt76.rx_lock);1525ieee80211_tx_status_noskb(mphy->hw, sta, &info);1526spin_unlock_bh(&dev->mt76.rx_lock);1527}15281529out:1530rcu_read_unlock();1531}15321533static void1534mt7615_txwi_free(struct mt7615_dev *dev, struct mt76_txwi_cache *txwi)1535{1536struct mt76_dev *mdev = &dev->mt76;1537__le32 *txwi_data;1538u32 val;1539u8 wcid;15401541mt76_connac_txp_skb_unmap(mdev, txwi);1542if (!txwi->skb)1543goto out;15441545txwi_data = (__le32 *)mt76_get_txwi_ptr(mdev, txwi);1546val = le32_to_cpu(txwi_data[1]);1547wcid = FIELD_GET(MT_TXD1_WLAN_IDX, val);1548mt76_tx_complete_skb(mdev, wcid, txwi->skb);15491550out:1551txwi->skb = NULL;1552mt76_put_txwi(mdev, txwi);1553}15541555static void1556mt7615_mac_tx_free_token(struct mt7615_dev *dev, u16 token)1557{1558struct mt76_dev *mdev = &dev->mt76;1559struct mt76_txwi_cache *txwi;15601561trace_mac_tx_free(dev, token);1562txwi = mt76_token_put(mdev, token);1563if (!txwi)1564return;15651566mt7615_txwi_free(dev, txwi);1567}15681569#if defined(__linux__)1570static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len)1571#elif defined(__FreeBSD__)1572static void mt7615_mac_tx_free(struct mt7615_dev *dev, u8 *data, int len)1573#endif1574{1575#if defined(__linux__)1576struct mt76_connac_tx_free *free = data;1577#elif defined(__FreeBSD__)1578struct mt76_connac_tx_free *free = (void *)data;1579#endif1580void *tx_token = data + sizeof(*free);1581void *end = data + len;1582u8 i, count;15831584mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_PSD], false);1585if (is_mt7615(&dev->mt76)) {1586mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[MT_TXQ_BE], false);1587} else {1588for (i = 0; i < IEEE80211_NUM_ACS; i++)1589mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], false);1590}15911592count = le16_get_bits(free->ctrl, MT_TX_FREE_MSDU_ID_CNT);1593if (is_mt7615(&dev->mt76)) {1594__le16 *token = tx_token;15951596if (WARN_ON_ONCE((void *)&token[count] > end))1597return;15981599for (i = 0; i < count; i++)1600mt7615_mac_tx_free_token(dev, le16_to_cpu(token[i]));1601} else {1602__le32 *token = tx_token;16031604if (WARN_ON_ONCE((void *)&token[count] > end))1605return;16061607for (i = 0; i < count; i++)1608mt7615_mac_tx_free_token(dev, le32_to_cpu(token[i]));1609}16101611rcu_read_lock();1612mt7615_mac_sta_poll(dev);1613rcu_read_unlock();16141615mt76_worker_schedule(&dev->mt76.tx_worker);1616}16171618bool mt7615_rx_check(struct mt76_dev *mdev, void *data, int len)1619{1620struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);1621__le32 *rxd = (__le32 *)data;1622__le32 *end = (__le32 *)&rxd[len / 4];1623enum rx_pkt_type type;16241625type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);16261627switch (type) {1628case PKT_TYPE_TXRX_NOTIFY:1629mt7615_mac_tx_free(dev, data, len);1630return false;1631case PKT_TYPE_TXS:1632for (rxd++; rxd + 7 <= end; rxd += 7)1633mt7615_mac_add_txs(dev, rxd);1634return false;1635default:1636return true;1637}1638}1639EXPORT_SYMBOL_GPL(mt7615_rx_check);16401641void mt7615_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,1642struct sk_buff *skb, u32 *info)1643{1644struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76);1645__le32 *rxd = (__le32 *)skb->data;1646__le32 *end = (__le32 *)&skb->data[skb->len];1647enum rx_pkt_type type;1648u16 flag;16491650type = le32_get_bits(rxd[0], MT_RXD0_PKT_TYPE);1651flag = le32_get_bits(rxd[0], MT_RXD0_PKT_FLAG);1652if (type == PKT_TYPE_RX_EVENT && flag == 0x1)1653type = PKT_TYPE_NORMAL_MCU;16541655switch (type) {1656case PKT_TYPE_TXS:1657for (rxd++; rxd + 7 <= end; rxd += 7)1658mt7615_mac_add_txs(dev, rxd);1659dev_kfree_skb(skb);1660break;1661case PKT_TYPE_TXRX_NOTIFY:1662mt7615_mac_tx_free(dev, skb->data, skb->len);1663dev_kfree_skb(skb);1664break;1665case PKT_TYPE_RX_EVENT:1666mt7615_mcu_rx_event(dev, skb);1667break;1668case PKT_TYPE_NORMAL_MCU:1669case PKT_TYPE_NORMAL:1670if (!mt7615_mac_fill_rx(dev, skb)) {1671mt76_rx(&dev->mt76, q, skb);1672return;1673}1674fallthrough;1675default:1676dev_kfree_skb(skb);1677break;1678}1679}1680EXPORT_SYMBOL_GPL(mt7615_queue_rx_skb);16811682static void1683mt7615_mac_set_sensitivity(struct mt7615_phy *phy, int val, bool ofdm)1684{1685struct mt7615_dev *dev = phy->dev;1686bool ext_phy = phy != &dev->phy;16871688if (is_mt7663(&dev->mt76)) {1689if (ofdm)1690mt76_rmw(dev, MT7663_WF_PHY_MIN_PRI_PWR(ext_phy),1691MT_WF_PHY_PD_OFDM_MASK(0),1692MT_WF_PHY_PD_OFDM(0, val));1693else1694mt76_rmw(dev, MT7663_WF_PHY_RXTD_CCK_PD(ext_phy),1695MT_WF_PHY_PD_CCK_MASK(ext_phy),1696MT_WF_PHY_PD_CCK(ext_phy, val));1697return;1698}16991700if (ofdm)1701mt76_rmw(dev, MT_WF_PHY_MIN_PRI_PWR(ext_phy),1702MT_WF_PHY_PD_OFDM_MASK(ext_phy),1703MT_WF_PHY_PD_OFDM(ext_phy, val));1704else1705mt76_rmw(dev, MT_WF_PHY_RXTD_CCK_PD(ext_phy),1706MT_WF_PHY_PD_CCK_MASK(ext_phy),1707MT_WF_PHY_PD_CCK(ext_phy, val));1708}17091710static void1711mt7615_mac_set_default_sensitivity(struct mt7615_phy *phy)1712{1713/* ofdm */1714mt7615_mac_set_sensitivity(phy, 0x13c, true);1715/* cck */1716mt7615_mac_set_sensitivity(phy, 0x92, false);17171718phy->ofdm_sensitivity = -98;1719phy->cck_sensitivity = -110;1720phy->last_cca_adj = jiffies;1721}17221723void mt7615_mac_set_scs(struct mt7615_phy *phy, bool enable)1724{1725struct mt7615_dev *dev = phy->dev;1726bool ext_phy = phy != &dev->phy;1727u32 reg, mask;17281729mt7615_mutex_acquire(dev);17301731if (phy->scs_en == enable)1732goto out;17331734if (is_mt7663(&dev->mt76)) {1735reg = MT7663_WF_PHY_MIN_PRI_PWR(ext_phy);1736mask = MT_WF_PHY_PD_BLK(0);1737} else {1738reg = MT_WF_PHY_MIN_PRI_PWR(ext_phy);1739mask = MT_WF_PHY_PD_BLK(ext_phy);1740}17411742if (enable) {1743mt76_set(dev, reg, mask);1744if (is_mt7622(&dev->mt76)) {1745mt76_set(dev, MT_MIB_M0_MISC_CR(0), 0x7 << 8);1746mt76_set(dev, MT_MIB_M0_MISC_CR(0), 0x7);1747}1748} else {1749mt76_clear(dev, reg, mask);1750}17511752mt7615_mac_set_default_sensitivity(phy);1753phy->scs_en = enable;17541755out:1756mt7615_mutex_release(dev);1757}17581759void mt7615_mac_enable_nf(struct mt7615_dev *dev, bool ext_phy)1760{1761u32 rxtd, reg;17621763if (is_mt7663(&dev->mt76))1764reg = MT7663_WF_PHY_R0_PHYMUX_5;1765else1766reg = MT_WF_PHY_R0_PHYMUX_5(ext_phy);17671768if (ext_phy)1769rxtd = MT_WF_PHY_RXTD2(10);1770else1771rxtd = MT_WF_PHY_RXTD(12);17721773mt76_set(dev, rxtd, BIT(18) | BIT(29));1774mt76_set(dev, reg, 0x5 << 12);1775}17761777void mt7615_mac_cca_stats_reset(struct mt7615_phy *phy)1778{1779struct mt7615_dev *dev = phy->dev;1780bool ext_phy = phy != &dev->phy;1781u32 reg;17821783if (is_mt7663(&dev->mt76))1784reg = MT7663_WF_PHY_R0_PHYMUX_5;1785else1786reg = MT_WF_PHY_R0_PHYMUX_5(ext_phy);17871788/* reset PD and MDRDY counters */1789mt76_clear(dev, reg, GENMASK(22, 20));1790mt76_set(dev, reg, BIT(22) | BIT(20));1791}17921793static void1794mt7615_mac_adjust_sensitivity(struct mt7615_phy *phy,1795u32 rts_err_rate, bool ofdm)1796{1797struct mt7615_dev *dev = phy->dev;1798int false_cca = ofdm ? phy->false_cca_ofdm : phy->false_cca_cck;1799bool ext_phy = phy != &dev->phy;1800s16 def_th = ofdm ? -98 : -110;1801bool update = false;1802s8 *sensitivity;1803int signal;18041805sensitivity = ofdm ? &phy->ofdm_sensitivity : &phy->cck_sensitivity;1806signal = mt76_get_min_avg_rssi(&dev->mt76, ext_phy);1807if (!signal) {1808mt7615_mac_set_default_sensitivity(phy);1809return;1810}18111812signal = min(signal, -72);1813if (false_cca > 500) {1814if (rts_err_rate > MT_FRAC(40, 100))1815return;18161817/* decrease coverage */1818if (*sensitivity == def_th && signal > -90) {1819*sensitivity = -90;1820update = true;1821} else if (*sensitivity + 2 < signal) {1822*sensitivity += 2;1823update = true;1824}1825} else if ((false_cca > 0 && false_cca < 50) ||1826rts_err_rate > MT_FRAC(60, 100)) {1827/* increase coverage */1828if (*sensitivity - 2 >= def_th) {1829*sensitivity -= 2;1830update = true;1831}1832}18331834if (*sensitivity > signal) {1835*sensitivity = signal;1836update = true;1837}18381839if (update) {1840u16 val = ofdm ? *sensitivity * 2 + 512 : *sensitivity + 256;18411842mt7615_mac_set_sensitivity(phy, val, ofdm);1843phy->last_cca_adj = jiffies;1844}1845}18461847static void1848mt7615_mac_scs_check(struct mt7615_phy *phy)1849{1850struct mt7615_dev *dev = phy->dev;1851struct mib_stats *mib = &phy->mib;1852u32 val, rts_err_rate = 0;1853u32 mdrdy_cck, mdrdy_ofdm, pd_cck, pd_ofdm;1854bool ext_phy = phy != &dev->phy;18551856if (!phy->scs_en)1857return;18581859if (is_mt7663(&dev->mt76))1860val = mt76_rr(dev, MT7663_WF_PHY_R0_PHYCTRL_STS0(ext_phy));1861else1862val = mt76_rr(dev, MT_WF_PHY_R0_PHYCTRL_STS0(ext_phy));1863pd_cck = FIELD_GET(MT_WF_PHYCTRL_STAT_PD_CCK, val);1864pd_ofdm = FIELD_GET(MT_WF_PHYCTRL_STAT_PD_OFDM, val);18651866if (is_mt7663(&dev->mt76))1867val = mt76_rr(dev, MT7663_WF_PHY_R0_PHYCTRL_STS5(ext_phy));1868else1869val = mt76_rr(dev, MT_WF_PHY_R0_PHYCTRL_STS5(ext_phy));1870mdrdy_cck = FIELD_GET(MT_WF_PHYCTRL_STAT_MDRDY_CCK, val);1871mdrdy_ofdm = FIELD_GET(MT_WF_PHYCTRL_STAT_MDRDY_OFDM, val);18721873phy->false_cca_ofdm = pd_ofdm - mdrdy_ofdm;1874phy->false_cca_cck = pd_cck - mdrdy_cck;1875mt7615_mac_cca_stats_reset(phy);18761877if (mib->rts_cnt + mib->rts_retries_cnt)1878rts_err_rate = MT_FRAC(mib->rts_retries_cnt,1879mib->rts_cnt + mib->rts_retries_cnt);18801881/* cck */1882mt7615_mac_adjust_sensitivity(phy, rts_err_rate, false);1883/* ofdm */1884mt7615_mac_adjust_sensitivity(phy, rts_err_rate, true);18851886if (time_after(jiffies, phy->last_cca_adj + 10 * HZ))1887mt7615_mac_set_default_sensitivity(phy);1888}18891890static u81891mt7615_phy_get_nf(struct mt7615_dev *dev, int idx)1892{1893static const u8 nf_power[] = { 92, 89, 86, 83, 80, 75, 70, 65, 60, 55, 52 };1894u32 reg, val, sum = 0, n = 0;1895int i;18961897if (is_mt7663(&dev->mt76))1898reg = MT7663_WF_PHY_RXTD(20);1899else1900reg = idx ? MT_WF_PHY_RXTD2(17) : MT_WF_PHY_RXTD(20);19011902for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) {1903val = mt76_rr(dev, reg);1904sum += val * nf_power[i];1905n += val;1906}19071908if (!n)1909return 0;19101911return sum / n;1912}19131914static void1915mt7615_phy_update_channel(struct mt76_phy *mphy, int idx)1916{1917struct mt7615_dev *dev = container_of(mphy->dev, struct mt7615_dev, mt76);1918struct mt7615_phy *phy = mphy->priv;1919struct mt76_channel_state *state;1920u64 busy_time, tx_time, rx_time, obss_time;1921u32 obss_reg = idx ? MT_WF_RMAC_MIB_TIME6 : MT_WF_RMAC_MIB_TIME5;1922int nf;19231924busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx),1925MT_MIB_SDR9_BUSY_MASK);1926tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx),1927MT_MIB_SDR36_TXTIME_MASK);1928rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx),1929MT_MIB_SDR37_RXTIME_MASK);1930obss_time = mt76_get_field(dev, obss_reg, MT_MIB_OBSSTIME_MASK);19311932nf = mt7615_phy_get_nf(dev, idx);1933if (!phy->noise)1934phy->noise = nf << 4;1935else if (nf)1936phy->noise += nf - (phy->noise >> 4);19371938state = mphy->chan_state;1939state->cc_busy += busy_time;1940state->cc_tx += tx_time;1941state->cc_rx += rx_time + obss_time;1942state->cc_bss_rx += rx_time;1943state->noise = -(phy->noise >> 4);1944}19451946static void mt7615_update_survey(struct mt7615_dev *dev)1947{1948struct mt76_dev *mdev = &dev->mt76;1949struct mt76_phy *mphy_ext = mdev->phys[MT_BAND1];1950ktime_t cur_time;19511952/* MT7615 can only update both phys simultaneously1953* since some reisters are shared across bands.1954*/19551956mt7615_phy_update_channel(&mdev->phy, 0);1957if (mphy_ext)1958mt7615_phy_update_channel(mphy_ext, 1);19591960cur_time = ktime_get_boottime();19611962mt76_update_survey_active_time(&mdev->phy, cur_time);1963if (mphy_ext)1964mt76_update_survey_active_time(mphy_ext, cur_time);19651966/* reset obss airtime */1967mt76_set(dev, MT_WF_RMAC_MIB_TIME0, MT_WF_RMAC_MIB_RXTIME_CLR);1968}19691970void mt7615_update_channel(struct mt76_phy *mphy)1971{1972struct mt7615_dev *dev = container_of(mphy->dev, struct mt7615_dev, mt76);19731974if (mt76_connac_pm_wake(&dev->mphy, &dev->pm))1975return;19761977mt7615_update_survey(dev);1978mt76_connac_power_save_sched(&dev->mphy, &dev->pm);1979}1980EXPORT_SYMBOL_GPL(mt7615_update_channel);19811982static void1983mt7615_mac_update_mib_stats(struct mt7615_phy *phy)1984{1985struct mt7615_dev *dev = phy->dev;1986struct mib_stats *mib = &phy->mib;1987bool ext_phy = phy != &dev->phy;1988int i, aggr = 0;1989u32 val, val2;19901991mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(ext_phy),1992MT_MIB_SDR3_FCS_ERR_MASK);19931994val = mt76_get_field(dev, MT_MIB_SDR14(ext_phy),1995MT_MIB_AMPDU_MPDU_COUNT);1996if (val) {1997val2 = mt76_get_field(dev, MT_MIB_SDR15(ext_phy),1998MT_MIB_AMPDU_ACK_COUNT);1999mib->aggr_per = 1000 * (val - val2) / val;2000}20012002for (i = 0; i < 4; i++) {2003val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, i));2004mib->ba_miss_cnt += FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val);2005mib->ack_fail_cnt += FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK,2006val);20072008val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i));2009mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val);2010mib->rts_retries_cnt += FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK,2011val);20122013val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i));2014phy->mt76->aggr_stats[aggr++] += val & 0xffff;2015phy->mt76->aggr_stats[aggr++] += val >> 16;2016}2017}20182019void mt7615_pm_wake_work(struct work_struct *work)2020{2021struct mt7615_dev *dev;2022struct mt76_phy *mphy;20232024dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev,2025pm.wake_work);2026mphy = dev->phy.mt76;20272028if (!mt7615_mcu_set_drv_ctrl(dev)) {2029struct mt76_dev *mdev = &dev->mt76;2030int i;20312032if (mt76_is_sdio(mdev)) {2033mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);2034mt76_worker_schedule(&mdev->sdio.txrx_worker);2035} else {2036local_bh_disable();2037mt76_for_each_q_rx(mdev, i)2038napi_schedule(&mdev->napi[i]);2039local_bh_enable();2040mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);2041mt76_queue_tx_cleanup(dev, mdev->q_mcu[MT_MCUQ_WM],2042false);2043}20442045if (test_bit(MT76_STATE_RUNNING, &mphy->state)) {2046unsigned long timeout;20472048timeout = mt7615_get_macwork_timeout(dev);2049ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,2050timeout);2051}2052}20532054ieee80211_wake_queues(mphy->hw);2055wake_up(&dev->pm.wait);2056}20572058void mt7615_pm_power_save_work(struct work_struct *work)2059{2060struct mt7615_dev *dev;2061unsigned long delta;20622063dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev,2064pm.ps_work.work);20652066delta = dev->pm.idle_timeout;2067if (test_bit(MT76_HW_SCANNING, &dev->mphy.state) ||2068test_bit(MT76_HW_SCHED_SCANNING, &dev->mphy.state))2069goto out;20702071if (mutex_is_locked(&dev->mt76.mutex))2072/* if mt76 mutex is held we should not put the device2073* to sleep since we are currently accessing device2074* register map. We need to wait for the next power_save2075* trigger.2076*/2077goto out;20782079if (time_is_after_jiffies(dev->pm.last_activity + delta)) {2080delta = dev->pm.last_activity + delta - jiffies;2081goto out;2082}20832084if (!mt7615_mcu_set_fw_ctrl(dev))2085return;2086out:2087queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta);2088}20892090void mt7615_mac_work(struct work_struct *work)2091{2092struct mt7615_phy *phy;2093struct mt76_phy *mphy;2094unsigned long timeout;20952096mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,2097mac_work.work);2098phy = mphy->priv;20992100mt7615_mutex_acquire(phy->dev);21012102mt7615_update_survey(phy->dev);2103if (++mphy->mac_work_count == 5) {2104mphy->mac_work_count = 0;21052106mt7615_mac_update_mib_stats(phy);2107mt7615_mac_scs_check(phy);2108}21092110mt7615_mutex_release(phy->dev);21112112mt76_tx_status_check(mphy->dev, false);21132114timeout = mt7615_get_macwork_timeout(phy->dev);2115ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work, timeout);2116}21172118void mt7615_tx_token_put(struct mt7615_dev *dev)2119{2120struct mt76_txwi_cache *txwi;2121int id;21222123spin_lock_bh(&dev->mt76.token_lock);2124idr_for_each_entry(&dev->mt76.token, txwi, id)2125mt7615_txwi_free(dev, txwi);2126spin_unlock_bh(&dev->mt76.token_lock);2127idr_destroy(&dev->mt76.token);2128}2129EXPORT_SYMBOL_GPL(mt7615_tx_token_put);21302131static void mt7615_dfs_stop_radar_detector(struct mt7615_phy *phy)2132{2133struct mt7615_dev *dev = phy->dev;21342135if (phy->rdd_state & BIT(0))2136mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 0,2137MT_RX_SEL0, 0);2138if (phy->rdd_state & BIT(1))2139mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_STOP, 1,2140MT_RX_SEL0, 0);2141}21422143static int mt7615_dfs_start_rdd(struct mt7615_dev *dev, int chain)2144{2145int err;21462147err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_START, chain,2148MT_RX_SEL0, 0);2149if (err < 0)2150return err;21512152return mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_DET_MODE, chain,2153MT_RX_SEL0, 1);2154}21552156static int mt7615_dfs_start_radar_detector(struct mt7615_phy *phy)2157{2158struct cfg80211_chan_def *chandef = &phy->mt76->chandef;2159struct mt7615_dev *dev = phy->dev;2160bool ext_phy = phy != &dev->phy;2161int err;21622163/* start CAC */2164err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_START, ext_phy,2165MT_RX_SEL0, 0);2166if (err < 0)2167return err;21682169err = mt7615_dfs_start_rdd(dev, ext_phy);2170if (err < 0)2171return err;21722173phy->rdd_state |= BIT(ext_phy);21742175if (chandef->width == NL80211_CHAN_WIDTH_160 ||2176chandef->width == NL80211_CHAN_WIDTH_80P80) {2177err = mt7615_dfs_start_rdd(dev, 1);2178if (err < 0)2179return err;21802181phy->rdd_state |= BIT(1);2182}21832184return 0;2185}21862187static int2188mt7615_dfs_init_radar_specs(struct mt7615_phy *phy)2189{2190const struct mt7615_dfs_radar_spec *radar_specs;2191struct mt7615_dev *dev = phy->dev;2192int err, i, lpn = 500;21932194switch (dev->mt76.region) {2195case NL80211_DFS_FCC:2196radar_specs = &fcc_radar_specs;2197lpn = 8;2198break;2199case NL80211_DFS_ETSI:2200radar_specs = &etsi_radar_specs;2201break;2202case NL80211_DFS_JP:2203radar_specs = &jp_radar_specs;2204break;2205default:2206return -EINVAL;2207}22082209/* avoid FCC radar detection in non-FCC region */2210err = mt7615_mcu_set_fcc5_lpn(dev, lpn);2211if (err < 0)2212return err;22132214for (i = 0; i < ARRAY_SIZE(radar_specs->radar_pattern); i++) {2215err = mt7615_mcu_set_radar_th(dev, i,2216&radar_specs->radar_pattern[i]);2217if (err < 0)2218return err;2219}22202221return mt7615_mcu_set_pulse_th(dev, &radar_specs->pulse_th);2222}22232224int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy)2225{2226struct cfg80211_chan_def *chandef = &phy->mt76->chandef;2227struct mt7615_dev *dev = phy->dev;2228bool ext_phy = phy != &dev->phy;2229enum mt76_dfs_state dfs_state, prev_state;2230int err;22312232if (is_mt7663(&dev->mt76))2233return 0;22342235prev_state = phy->mt76->dfs_state;2236dfs_state = mt76_phy_dfs_state(phy->mt76);2237if ((chandef->chan->flags & IEEE80211_CHAN_RADAR) &&2238dfs_state < MT_DFS_STATE_CAC)2239dfs_state = MT_DFS_STATE_ACTIVE;22402241if (prev_state == dfs_state)2242return 0;22432244if (dfs_state == MT_DFS_STATE_DISABLED)2245goto stop;22462247if (prev_state <= MT_DFS_STATE_DISABLED) {2248err = mt7615_dfs_init_radar_specs(phy);2249if (err < 0)2250return err;22512252err = mt7615_dfs_start_radar_detector(phy);2253if (err < 0)2254return err;22552256phy->mt76->dfs_state = MT_DFS_STATE_CAC;2257}22582259if (dfs_state == MT_DFS_STATE_CAC)2260return 0;22612262err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_CAC_END,2263ext_phy, MT_RX_SEL0, 0);2264if (err < 0) {2265phy->mt76->dfs_state = MT_DFS_STATE_UNKNOWN;2266return err;2267}22682269phy->mt76->dfs_state = MT_DFS_STATE_ACTIVE;2270return 0;22712272stop:2273err = mt76_connac_mcu_rdd_cmd(&dev->mt76, RDD_NORMAL_START, ext_phy,2274MT_RX_SEL0, 0);2275if (err < 0)2276return err;22772278mt7615_dfs_stop_radar_detector(phy);2279phy->mt76->dfs_state = MT_DFS_STATE_DISABLED;22802281return 0;2282}22832284int mt7615_mac_set_beacon_filter(struct mt7615_phy *phy,2285struct ieee80211_vif *vif,2286bool enable)2287{2288struct mt7615_dev *dev = phy->dev;2289bool ext_phy = phy != &dev->phy;2290int err;22912292if (!mt7615_firmware_offload(dev))2293return -EOPNOTSUPP;22942295switch (vif->type) {2296case NL80211_IFTYPE_MONITOR:2297return 0;2298case NL80211_IFTYPE_MESH_POINT:2299case NL80211_IFTYPE_ADHOC:2300case NL80211_IFTYPE_AP:2301if (enable)2302phy->n_beacon_vif++;2303else2304phy->n_beacon_vif--;2305fallthrough;2306default:2307break;2308}23092310err = mt7615_mcu_set_bss_pm(dev, vif, !phy->n_beacon_vif);2311if (err)2312return err;23132314if (phy->n_beacon_vif) {2315vif->driver_flags &= ~IEEE80211_VIF_BEACON_FILTER;2316mt76_clear(dev, MT_WF_RFCR(ext_phy),2317MT_WF_RFCR_DROP_OTHER_BEACON);2318} else {2319vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;2320mt76_set(dev, MT_WF_RFCR(ext_phy),2321MT_WF_RFCR_DROP_OTHER_BEACON);2322}23232324return 0;2325}23262327void mt7615_coredump_work(struct work_struct *work)2328{2329struct mt7615_dev *dev;2330char *dump, *data;23312332dev = (struct mt7615_dev *)container_of(work, struct mt7615_dev,2333coredump.work.work);23342335if (time_is_after_jiffies(dev->coredump.last_activity +23364 * MT76_CONNAC_COREDUMP_TIMEOUT)) {2337queue_delayed_work(dev->mt76.wq, &dev->coredump.work,2338MT76_CONNAC_COREDUMP_TIMEOUT);2339return;2340}23412342dump = vzalloc(MT76_CONNAC_COREDUMP_SZ);2343data = dump;23442345while (true) {2346struct sk_buff *skb;23472348spin_lock_bh(&dev->mt76.lock);2349skb = __skb_dequeue(&dev->coredump.msg_list);2350spin_unlock_bh(&dev->mt76.lock);23512352if (!skb)2353break;23542355skb_pull(skb, sizeof(struct mt7615_mcu_rxd));2356if (!dump || data + skb->len - dump > MT76_CONNAC_COREDUMP_SZ) {2357dev_kfree_skb(skb);2358continue;2359}23602361memcpy(data, skb->data, skb->len);2362data += skb->len;23632364dev_kfree_skb(skb);2365}23662367if (dump)2368dev_coredumpv(dev->mt76.dev, dump, MT76_CONNAC_COREDUMP_SZ,2369GFP_KERNEL);2370}237123722373