Add module parameter to enable hw_tx_amsdu. Signed-off-by: Ryder Lee <ryder.lee@xxxxxxxxxxxx> Signed-off-by: Shayne Chen <shayne.chen@xxxxxxxxxxxx> Tested-by: Chih-Min Chen <chih-min.chen@xxxxxxxxxxxx> Tested-by: Evelyn Tsai <evelyn.tsai@xxxxxxxxxxxx> Suggested-by: Yiwei Chung <yiwei.chung@xxxxxxxxxxxx> Suggested-by: YF Luo <yf.luo@xxxxxxxxxxxx> --- .../net/wireless/mediatek/mt76/mt7915/init.c | 5 ++- .../net/wireless/mediatek/mt76/mt7915/mac.c | 4 +- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 40 +++++++++++++++++++ .../net/wireless/mediatek/mt76/mt7915/mcu.h | 20 ++++++++++ .../wireless/mediatek/mt76/mt7915/mt7915.h | 1 + .../net/wireless/mediatek/mt76/mt7915/pci.c | 8 ++++ 6 files changed, 76 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index cba9dfb83e19..59b3ffae7917 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -236,7 +236,10 @@ mt7915_init_wiphy(struct ieee80211_hw *hw) ieee80211_hw_set(hw, HAS_RATE_CONTROL); - hw->max_tx_fragments = 4; + if (phy->dev->hw_tx_amsdu) + hw->max_tx_fragments = 1; + else + hw->max_tx_fragments = 4; } static void diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c index 349215dd417c..f0604bb6d644 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c @@ -524,7 +524,9 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi, txwi[7] = cpu_to_le32(val); val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); - if (ieee80211_is_data_qos(fc)) { + if (dev->hw_tx_amsdu && ieee80211_is_data_qos(fc)) { + txwi[7] |= MT_TXD7_HW_AMSDU; + } else if (ieee80211_is_data_qos(fc)) { seqno = IEEE80211_SEQ_TO_SN(le16_to_cpu(hdr->seq_ctrl)); val |= MT_TXD3_SN_VALID; } else if (ieee80211_is_back_req(fc)) { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 59cd50db2ecf..5e70f7f24fb7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -85,6 +85,8 @@ struct mt7915_fw_region { #define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id) #define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id) +#define HW_TX_AMSDU_MAX_NUM 8 + static enum mt7915_cipher_type mt7915_mcu_get_cipher(int cipher) { @@ -786,6 +788,23 @@ mt7915_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, ra->fast_interval = cpu_to_le32(100); } +static void +mt7915_mcu_bss_hw_amsdu_tlv(struct sk_buff *skb) +{ +#define TXD_CMP_MAP1 GENMASK(15, 0) +#define TXD_CMP_MAP2 (GENMASK(31, 0) & ~BIT(23)) + struct bss_info_hw_amsdu *amsdu; + struct tlv *tlv; + + tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_HW_AMSDU, sizeof(*amsdu)); + + amsdu = (struct bss_info_hw_amsdu *)tlv; + amsdu->cmp_bitmap_0 = cpu_to_le32(TXD_CMP_MAP1); + amsdu->cmp_bitmap_1 = cpu_to_le32(TXD_CMP_MAP2); + amsdu->trig_thres = cpu_to_le16(2); + amsdu->enable = true; +} + static void mt7915_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt7915_vif *mvif) { @@ -861,6 +880,9 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, mt7915_mcu_bss_bmc_tlv(skb, phy); mt7915_mcu_bss_ra_tlv(skb, vif, phy); + if (phy->dev->hw_tx_amsdu) + mt7915_mcu_bss_hw_amsdu_tlv(skb); + if (mvif->omac_idx > HW_BSSID_MAX) mt7915_mcu_bss_ext_tlv(skb, mvif); else @@ -1145,6 +1167,24 @@ mt7915_mcu_sta_tlv(struct mt7915_dev *dev, struct sk_buff *skb, tlv = mt7915_mcu_add_tlv(skb, STA_REC_HT, sizeof(*ht)); ht = (struct sta_rec_ht *)tlv; ht->ht_cap = cpu_to_le16(sta->ht_cap.cap); + + /* starec hw amsdu */ + if (dev->hw_tx_amsdu) { + struct sta_rec_amsdu *amsdu; + int max_amsdu_len = sta->max_amsdu_len; + + tlv = mt7915_mcu_add_tlv(skb, STA_REC_HW_AMSDU, + sizeof(*amsdu)); + amsdu = (struct sta_rec_amsdu *)tlv; + amsdu->max_amsdu_num = HW_TX_AMSDU_MAX_NUM; + amsdu->amsdu_en = true; + + if (sta->max_rc_amsdu_len) + max_amsdu_len = min_t(int, max_amsdu_len, + sta->max_rc_amsdu_len); + + amsdu->max_mpdu_size = max_amsdu_len; + } } /* starec vht */ diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index d9c9aab7e6dc..867cab7cf145 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -396,6 +396,16 @@ struct bss_info_ra { __le32 fast_interval; } __packed; +struct bss_info_hw_amsdu { + __le16 tag; + __le16 len; + __le32 cmp_bitmap_0; + __le32 cmp_bitmap_1; + __le16 trig_thres; + u8 enable; + u8 rsv; +} __packed; + struct bss_info_bcn { __le16 tag; __le16 len; @@ -659,6 +669,15 @@ struct sta_rec_ba { __le16 winsize; } __packed; +struct sta_rec_amsdu { + __le16 tag; + __le16 len; + u8 max_amsdu_num; + u8 max_mpdu_size; + u8 amsdu_en; + u8 rsv; +} __packed; + struct sec_key { u8 cipher_id; u8 cipher_len; @@ -796,6 +815,7 @@ enum { sizeof(struct sta_rec_ba) + \ sizeof(struct sta_rec_vht) + \ sizeof(struct tlv) + \ + sizeof(struct sta_rec_amsdu) + \ sizeof(struct sta_rec_sec) + \ sizeof(struct sta_rec_ra) + \ MT7915_WTBL_UPDATE_MAX_SIZE) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h index b502bcc985ec..7f569a7a0c9b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -167,6 +167,7 @@ struct mt7915_dev { u8 mac_work_count; bool fw_debug; + bool hw_tx_amsdu; }; enum { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c index d349561e4598..75f72ae104db 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/pci.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/pci.c @@ -12,6 +12,10 @@ #include "mac.h" #include "../trace.h" +static bool hw_tx_amsdu; +module_param_named(enable_hw_tx_amsdu, hw_tx_amsdu, bool, 0644); +MODULE_PARM_DESC(enable_hw_tx_amsdu, "enable Hardware Tx AMSDU"); + static const struct pci_device_id mt7915_pci_device_table[] = { { PCI_DEVICE(0x14c3, 0x7915) }, { }, @@ -149,6 +153,10 @@ static int mt7915_pci_probe(struct pci_dev *pdev, (mt7915_l1_rr(dev, MT_HW_REV) & 0xff); dev_dbg(mdev->dev, "ASIC revision: %04x\n", mdev->rev); + /* TODO: more hw capabilities */ + if (hw_tx_amsdu) + dev->hw_tx_amsdu = true; + /* master switch of PCIe tnterrupt enable */ mt7915_l1_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff); -- 2.18.0