@@ -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
@@ -525,7 +525,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)) {
@@ -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,18 @@ 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;
+
+ 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;
+ amsdu->max_mpdu_size = sta->max_amsdu_len;
+ }
}
/* starec vht */
@@ -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)
@@ -167,6 +167,7 @@ struct mt7915_dev {
u8 mac_work_count;
bool fw_debug;
+ bool hw_tx_amsdu;
};
enum {
@@ -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) },
{ },
@@ -150,6 +154,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);