diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7915/mac.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 258 |
1 files changed, 137 insertions, 121 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index e5a258958ac9..7a9759fb79d8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -317,11 +317,18 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) __le32 *rxd = (__le32 *)skb->data; __le32 *rxv = NULL; u32 mode = 0; + u32 rxd0 = le32_to_cpu(rxd[0]); u32 rxd1 = le32_to_cpu(rxd[1]); u32 rxd2 = le32_to_cpu(rxd[2]); u32 rxd3 = le32_to_cpu(rxd[3]); + u32 rxd4 = le32_to_cpu(rxd[4]); + u32 csum_mask = MT_RXD0_NORMAL_IP_SUM | MT_RXD0_NORMAL_UDP_TCP_SUM; bool unicast, insert_ccmp_hdr = false; - u8 remove_pad; + u8 remove_pad, amsdu_info; + bool hdr_trans; + u16 seq_ctrl = 0; + u8 qos_ctl = 0; + __le16 fc = 0; int i, idx; memset(status, 0, sizeof(*status)); @@ -338,8 +345,12 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) if (!test_bit(MT76_STATE_RUNNING, &mphy->state)) return -EINVAL; + if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR) + return -EINVAL; + unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M; idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1); + hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS; status->wcid = mt7915_rx_get_wcid(dev, idx, unicast); if (status->wcid) { @@ -362,6 +373,9 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) if (!sband->channels) return -EINVAL; + if ((rxd0 & csum_mask) == csum_mask) + skb->ip_summed = CHECKSUM_UNNECESSARY; + if (rxd1 & MT_RXD1_NORMAL_FCS_ERR) status->flag |= RX_FLAG_FAILED_FCS_CRC; @@ -375,19 +389,6 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) status->flag |= RX_FLAG_MMIC_STRIPPED | RX_FLAG_MIC_STRIPPED; } - if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { - status->flag |= RX_FLAG_AMPDU_DETAILS; - - /* all subframes of an A-MPDU have the same timestamp */ - if (phy->rx_ampdu_ts != rxd[14]) { - if (!++phy->ampdu_ref) - phy->ampdu_ref++; - } - phy->rx_ampdu_ts = rxd[14]; - - status->ampdu_ref = phy->ampdu_ref; - } - remove_pad = FIELD_GET(MT_RXD2_NORMAL_HDR_OFFSET, rxd2); if (rxd2 & MT_RXD2_NORMAL_MAX_LEN_ERROR) @@ -395,6 +396,13 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) rxd += 6; if (rxd1 & MT_RXD1_NORMAL_GROUP_4) { + u32 v0 = le32_to_cpu(rxd[0]); + u32 v2 = le32_to_cpu(rxd[2]); + + fc = cpu_to_le16(FIELD_GET(MT_RXD6_FRAME_CONTROL, v0)); + qos_ctl = FIELD_GET(MT_RXD8_QOS_CTL, v2); + seq_ctrl = FIELD_GET(MT_RXD8_SEQ_CTRL, v2); + rxd += 4; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; @@ -419,6 +427,22 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) } if (rxd1 & MT_RXD1_NORMAL_GROUP_2) { + status->timestamp = le32_to_cpu(rxd[0]); + status->flag |= RX_FLAG_MACTIME_START; + + if (!(rxd2 & MT_RXD2_NORMAL_NON_AMPDU)) { + status->flag |= RX_FLAG_AMPDU_DETAILS; + + /* all subframes of an A-MPDU have the same timestamp */ + if (phy->rx_ampdu_ts != status->timestamp) { + if (!++phy->ampdu_ref) + phy->ampdu_ref++; + } + phy->rx_ampdu_ts = status->timestamp; + + status->ampdu_ref = phy->ampdu_ref; + } + rxd += 2; if ((u8 *)rxd - skb->data >= skb->len) return -EINVAL; @@ -541,23 +565,47 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb) skb_pull(skb, (u8 *)rxd - skb->data + 2 * remove_pad); - if (insert_ccmp_hdr) { + amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4); + status->amsdu = !!amsdu_info; + if (status->amsdu) { + status->first_amsdu = amsdu_info == MT_RXD4_FIRST_AMSDU_FRAME; + status->last_amsdu = amsdu_info == MT_RXD4_LAST_AMSDU_FRAME; + if (!hdr_trans) { + memmove(skb->data + 2, skb->data, + ieee80211_get_hdrlen_from_skb(skb)); + skb_pull(skb, 2); + } + } + + if (insert_ccmp_hdr && !hdr_trans) { u8 key_id = FIELD_GET(MT_RXD1_NORMAL_KEY_ID, rxd1); mt76_insert_ccmp_hdr(skb, key_id); } + if (!hdr_trans) { + hdr = mt76_skb_get_hdr(skb); + fc = hdr->frame_control; + if (ieee80211_is_data_qos(fc)) { + seq_ctrl = le16_to_cpu(hdr->seq_ctrl); + qos_ctl = *ieee80211_get_qos_ctl(hdr); + } + } else { + status->flag &= ~(RX_FLAG_RADIOTAP_HE | + RX_FLAG_RADIOTAP_HE_MU); + status->flag |= RX_FLAG_8023; + } + if (rxv && status->flag & RX_FLAG_RADIOTAP_HE) mt7915_mac_decode_he_radiotap(skb, status, rxv, mode); - hdr = mt76_skb_get_hdr(skb); - if (!status->wcid || !ieee80211_is_data_qos(hdr->frame_control)) + if (!status->wcid || !ieee80211_is_data_qos(fc)) return 0; status->aggr = unicast && - !ieee80211_is_qos_nullfunc(hdr->frame_control); - status->tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; - status->seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); + !ieee80211_is_qos_nullfunc(fc); + status->qos_ctl = qos_ctl; + status->seqno = IEEE80211_SEQ_TO_SN(seq_ctrl); return 0; } @@ -613,19 +661,18 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi, { #ifdef CONFIG_NL80211_TESTMODE struct mt76_testmode_data *td = &phy->mt76->test; + const struct ieee80211_rate *r; + u8 bw, mode, nss = td->tx_rate_nss; u8 rate_idx = td->tx_rate_idx; - u8 nss = td->tx_rate_nss; - u8 bw, mode; u16 rateval = 0; u32 val; + bool cck = false; + int band; if (skb != phy->mt76->test.tx_skb) return; switch (td->tx_rate_mode) { - case MT76_TM_TX_MODE_CCK: - mode = MT_PHY_TYPE_CCK; - break; case MT76_TM_TX_MODE_HT: nss = 1 + (rate_idx >> 3); mode = MT_PHY_TYPE_HT; @@ -645,7 +692,20 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi, case MT76_TM_TX_MODE_HE_MU: mode = MT_PHY_TYPE_HE_MU; break; + case MT76_TM_TX_MODE_CCK: + cck = true; + fallthrough; case MT76_TM_TX_MODE_OFDM: + band = phy->mt76->chandef.chan->band; + if (band == NL80211_BAND_2GHZ && !cck) + rate_idx += 4; + + r = &phy->mt76->hw->wiphy->bands[band]->bitrates[rate_idx]; + val = cck ? r->hw_value_short : r->hw_value; + + mode = val >> 8; + rate_idx = val & 0xff; + break; default: mode = MT_PHY_TYPE_OFDM; break; @@ -700,9 +760,10 @@ mt7915_mac_write_txwi_tm(struct mt7915_phy *phy, __le32 *txwi, if (mode >= MT_PHY_TYPE_HE_SU) val |= FIELD_PREP(MT_TXD6_HELTF, td->tx_ltf); - if (td->tx_rate_ldpc || bw > 0) + if (td->tx_rate_ldpc || (bw > 0 && mode >= MT_PHY_TYPE_HE_SU)) val |= MT_TXD6_LDPC; + txwi[3] &= ~cpu_to_le32(MT_TXD3_SN_VALID); txwi[6] |= cpu_to_le32(val); txwi[7] |= cpu_to_le32(FIELD_PREP(MT_TXD7_SPE_IDX, phy->test.spe_idx)); @@ -913,26 +974,6 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, mt7915_mac_write_txwi_tm(mphy->priv, txwi, skb); } -static void -mt7915_set_tx_blocked(struct mt7915_dev *dev, bool blocked) -{ - struct mt76_phy *mphy = &dev->mphy, *mphy2 = dev->mt76.phy2; - struct mt76_queue *q, *q2 = NULL; - - q = mphy->q_tx[0]; - if (blocked == q->blocked) - return; - - q->blocked = blocked; - if (mphy2) { - q2 = mphy2->q_tx[0]; - q2->blocked = blocked; - } - - if (!blocked) - mt76_worker_schedule(&dev->mt76.tx_worker); -} - int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, enum mt76_txq_id qid, struct mt76_wcid *wcid, struct ieee80211_sta *sta, @@ -985,15 +1026,7 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size); t->skb = tx_info->skb; - spin_lock_bh(&dev->token_lock); - id = idr_alloc(&dev->token, t, 0, MT7915_TOKEN_SIZE, GFP_ATOMIC); - if (id >= 0) - dev->token_count++; - - if (dev->token_count >= MT7915_TOKEN_SIZE - MT7915_TOKEN_FREE_THR) - mt7915_set_tx_blocked(dev, true); - spin_unlock_bh(&dev->token_lock); - + id = mt76_token_consume(mdev, &t); if (id < 0) return id; @@ -1091,7 +1124,7 @@ void mt7915_txp_skb_unmap(struct mt76_dev *dev, int i; txp = mt7915_txwi_to_txp(dev, t); - for (i = 1; i < txp->nbuf; i++) + for (i = 0; i < txp->nbuf; i++) dma_unmap_single(dev->dev, le32_to_cpu(txp->buf[i]), le16_to_cpu(txp->len[i]), DMA_TO_DEVICE); } @@ -1157,15 +1190,7 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb) msdu = FIELD_GET(MT_TX_FREE_MSDU_ID, info); stat = FIELD_GET(MT_TX_FREE_STATUS, info); - spin_lock_bh(&dev->token_lock); - txwi = idr_remove(&dev->token, msdu); - if (txwi) - dev->token_count--; - if (dev->token_count < MT7915_TOKEN_SIZE - MT7915_TOKEN_FREE_THR && - dev->mphy.q_tx[0]->blocked) - wake = true; - spin_unlock_bh(&dev->token_lock); - + txwi = mt76_token_release(mdev, msdu, &wake); if (!txwi) continue; @@ -1195,11 +1220,8 @@ void mt7915_mac_tx_free(struct mt7915_dev *dev, struct sk_buff *skb) mt7915_mac_sta_poll(dev); - if (wake) { - spin_lock_bh(&dev->token_lock); - mt7915_set_tx_blocked(dev, false); - spin_unlock_bh(&dev->token_lock); - } + if (wake) + mt76_set_tx_blocked(&dev->mt76, false); mt76_worker_schedule(&dev->mt76.tx_worker); @@ -1228,10 +1250,7 @@ void mt7915_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e) struct mt7915_txp *txp; txp = mt7915_txwi_to_txp(mdev, e->txwi); - - spin_lock_bh(&dev->token_lock); - t = idr_remove(&dev->token, le16_to_cpu(txp->token)); - spin_unlock_bh(&dev->token_lock); + t = mt76_token_put(mdev, le16_to_cpu(txp->token)); e->skb = t ? t->skb : NULL; } @@ -1252,8 +1271,8 @@ void mt7915_mac_cca_stats_reset(struct mt7915_phy *phy) bool ext_phy = phy != &dev->phy; u32 reg = MT_WF_PHY_RX_CTRL1(ext_phy); - mt7915_l2_clear(dev, reg, MT_WF_PHY_RX_CTRL1_STSCNT_EN); - mt7915_l2_set(dev, reg, BIT(11) | BIT(9)); + mt76_clear(dev, reg, MT_WF_PHY_RX_CTRL1_STSCNT_EN); + mt76_set(dev, reg, BIT(11) | BIT(9)); } void mt7915_mac_reset_counters(struct mt7915_phy *phy) @@ -1346,12 +1365,12 @@ void mt7915_mac_set_timing(struct mt7915_phy *phy) void mt7915_mac_enable_nf(struct mt7915_dev *dev, bool ext_phy) { - mt7915_l2_set(dev, MT_WF_PHY_RXTD12(ext_phy), - MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY | - MT_WF_PHY_RXTD12_IRPI_SW_CLR); + mt76_set(dev, MT_WF_PHY_RXTD12(ext_phy), + MT_WF_PHY_RXTD12_IRPI_SW_CLR_ONLY | + MT_WF_PHY_RXTD12_IRPI_SW_CLR); - mt7915_l2_set(dev, MT_WF_PHY_RX_CTRL1(ext_phy), - FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5)); + mt76_set(dev, MT_WF_PHY_RX_CTRL1(ext_phy), + FIELD_PREP(MT_WF_PHY_RX_CTRL1_IPI_EN, 0x5)); } static u8 @@ -1366,7 +1385,7 @@ mt7915_phy_get_nf(struct mt7915_phy *phy, int idx) u32 reg = MT_WF_IRPI(nss + (idx << dev->dbdc_support)); for (i = 0; i < ARRAY_SIZE(nf_power); i++, reg += 4) { - val = mt7915_l2_rr(dev, reg); + val = mt76_rr(dev, reg); sum += val * nf_power[i]; n += val; } @@ -1470,9 +1489,8 @@ mt7915_update_beacons(struct mt7915_dev *dev) } static void -mt7915_dma_reset(struct mt7915_phy *phy) +mt7915_dma_reset(struct mt7915_dev *dev) { - struct mt7915_dev *dev = phy->dev; struct mt76_phy *mphy_ext = dev->mt76.phy2; u32 hif1_ofs = MT_WFDMA1_PCIE1_BASE - MT_WFDMA1_BASE; int i; @@ -1489,18 +1507,22 @@ mt7915_dma_reset(struct mt7915_phy *phy) (MT_WFDMA1_GLO_CFG_TX_DMA_EN | MT_WFDMA1_GLO_CFG_RX_DMA_EN)); } + usleep_range(1000, 2000); - mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_WA], true); for (i = 0; i < __MT_TXQ_MAX; i++) { - mt76_queue_tx_cleanup(dev, phy->mt76->q_tx[i], true); + mt76_queue_tx_cleanup(dev, dev->mphy.q_tx[i], true); if (mphy_ext) mt76_queue_tx_cleanup(dev, mphy_ext->q_tx[i], true); } - mt76_for_each_q_rx(&dev->mt76, i) { + for (i = 0; i < __MT_MCUQ_MAX; i++) + mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[i], true); + + mt76_for_each_q_rx(&dev->mt76, i) mt76_queue_rx_reset(dev, i); - } + + mt76_tx_status_check(&dev->mt76, NULL, true); /* re-init prefetch settings after reset */ mt7915_dma_prefetch(dev); @@ -1524,8 +1546,8 @@ void mt7915_tx_token_put(struct mt7915_dev *dev) struct mt76_txwi_cache *txwi; int id; - spin_lock_bh(&dev->token_lock); - idr_for_each_entry(&dev->token, txwi, id) { + spin_lock_bh(&dev->mt76.token_lock); + idr_for_each_entry(&dev->mt76.token, txwi, id) { mt7915_txp_skb_unmap(&dev->mt76, txwi); if (txwi->skb) { struct ieee80211_hw *hw; @@ -1534,10 +1556,10 @@ void mt7915_tx_token_put(struct mt7915_dev *dev) ieee80211_free_txskb(hw, txwi->skb); } mt76_put_txwi(&dev->mt76, txwi); - dev->token_count--; + dev->mt76.token_count--; } - spin_unlock_bh(&dev->token_lock); - idr_destroy(&dev->token); + spin_unlock_bh(&dev->mt76.token_lock); + idr_destroy(&dev->mt76.token); } /* system error recovery */ @@ -1562,9 +1584,10 @@ void mt7915_mac_reset_work(struct work_struct *work) set_bit(MT76_MCU_RESET, &dev->mphy.state); wake_up(&dev->mt76.mcu.wait); cancel_delayed_work_sync(&dev->mphy.mac_work); - if (phy2) + if (phy2) { + set_bit(MT76_RESET, &phy2->mt76->state); cancel_delayed_work_sync(&phy2->mt76->mac_work); - + } /* lock/unlock all queues to ensure that no tx is pending */ mt76_txq_schedule_all(&dev->mphy); if (ext_phy) @@ -1580,11 +1603,11 @@ void mt7915_mac_reset_work(struct work_struct *work) mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED); - mt7915_tx_token_put(dev); - idr_init(&dev->token); - if (mt7915_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) { - mt7915_dma_reset(&dev->phy); + mt7915_dma_reset(dev); + + mt7915_tx_token_put(dev); + idr_init(&dev->mt76.token); mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_INIT); mt7915_wait_reset_state(dev, MT_MCU_CMD_RECOVERY_DONE); @@ -1592,6 +1615,8 @@ void mt7915_mac_reset_work(struct work_struct *work) clear_bit(MT76_MCU_RESET, &dev->mphy.state); clear_bit(MT76_RESET, &dev->mphy.state); + if (phy2) + clear_bit(MT76_RESET, &phy2->mt76->state); mt76_worker_enable(&dev->mt76.tx_worker); napi_enable(&dev->mt76.tx_napi); @@ -1633,39 +1658,30 @@ mt7915_mac_update_mib_stats(struct mt7915_phy *phy) bool ext_phy = phy != &dev->phy; int i, aggr0, aggr1; - memset(mib, 0, sizeof(*mib)); - - mib->fcs_err_cnt = mt76_get_field(dev, MT_MIB_SDR3(ext_phy), - MT_MIB_SDR3_FCS_ERR_MASK); + mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(ext_phy), + MT_MIB_SDR3_FCS_ERR_MASK); aggr0 = ext_phy ? ARRAY_SIZE(dev->mt76.aggr_stats) / 2 : 0; for (i = 0, aggr1 = aggr0 + 4; i < 4; i++) { - u32 val, val2; + u32 val; val = mt76_rr(dev, MT_MIB_MB_SDR1(ext_phy, i)); - - val2 = FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val); - if (val2 > mib->ack_fail_cnt) - mib->ack_fail_cnt = val2; - - val2 = FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); - if (val2 > mib->ba_miss_cnt) - mib->ba_miss_cnt = val2; + mib->ba_miss_cnt += FIELD_GET(MT_MIB_BA_MISS_COUNT_MASK, val); + mib->ack_fail_cnt += + FIELD_GET(MT_MIB_ACK_FAIL_COUNT_MASK, val); val = mt76_rr(dev, MT_MIB_MB_SDR0(ext_phy, i)); - val2 = FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); - if (val2 > mib->rts_retries_cnt) { - mib->rts_cnt = FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); - mib->rts_retries_cnt = val2; - } + mib->rts_cnt += FIELD_GET(MT_MIB_RTS_COUNT_MASK, val); + mib->rts_retries_cnt += + FIELD_GET(MT_MIB_RTS_RETRIES_COUNT_MASK, val); val = mt76_rr(dev, MT_TX_AGG_CNT(ext_phy, i)); - val2 = mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i)); - dev->mt76.aggr_stats[aggr0++] += val & 0xffff; dev->mt76.aggr_stats[aggr0++] += val >> 16; - dev->mt76.aggr_stats[aggr1++] += val2 & 0xffff; - dev->mt76.aggr_stats[aggr1++] += val2 >> 16; + + val = mt76_rr(dev, MT_TX_AGG_CNT2(ext_phy, i)); + dev->mt76.aggr_stats[aggr1++] += val & 0xffff; + dev->mt76.aggr_stats[aggr1++] += val >> 16; } } |