|
|
|
@@ -567,51 +567,62 @@ int mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
|
|
|
|
struct sk_buff *skb, struct mt76_wcid *wcid,
|
|
|
|
|
struct ieee80211_key_conf *key, bool beacon)
|
|
|
|
|
static void
|
|
|
|
|
mt7915_mac_write_txwi_8023(struct mt7915_dev *dev, __le32 *txwi,
|
|
|
|
|
struct sk_buff *skb, struct mt76_wcid *wcid)
|
|
|
|
|
{
|
|
|
|
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
|
|
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
|
|
|
|
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
|
|
|
|
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
|
|
|
|
struct ieee80211_vif *vif = info->control.vif;
|
|
|
|
|
struct mt76_phy *mphy = &dev->mphy;
|
|
|
|
|
bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY;
|
|
|
|
|
u8 fc_type, fc_stype, p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
|
|
|
|
|
__le16 fc = hdr->frame_control;
|
|
|
|
|
u16 tx_count = 15, seqno = 0;
|
|
|
|
|
|
|
|
|
|
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
|
|
|
|
struct ethhdr *ehdr = (struct ethhdr *)skb->data;
|
|
|
|
|
bool multicast = is_multicast_ether_addr(ehdr->h_dest);
|
|
|
|
|
u8 fc_type, fc_stype;
|
|
|
|
|
bool wmm = false;
|
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
|
|
if (vif) {
|
|
|
|
|
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
|
|
|
|
if (wcid->sta) {
|
|
|
|
|
struct ieee80211_sta *sta;
|
|
|
|
|
|
|
|
|
|
omac_idx = mvif->omac_idx;
|
|
|
|
|
wmm_idx = mvif->wmm_idx;
|
|
|
|
|
sta = container_of((void *)wcid, struct ieee80211_sta, drv_priv);
|
|
|
|
|
wmm = sta->wme;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ext_phy && dev->mt76.phy2)
|
|
|
|
|
mphy = dev->mt76.phy2;
|
|
|
|
|
val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) |
|
|
|
|
|
FIELD_PREP(MT_TXD1_TID, tid);
|
|
|
|
|
|
|
|
|
|
fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
|
|
|
|
|
fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
|
|
|
|
|
if (be16_to_cpu(ehdr->h_proto) >= ETH_P_802_3_MIN)
|
|
|
|
|
val |= MT_TXD1_ETH_802_3;
|
|
|
|
|
|
|
|
|
|
txwi[4] = 0;
|
|
|
|
|
txwi[5] = 0;
|
|
|
|
|
txwi[6] = 0;
|
|
|
|
|
txwi[1] |= cpu_to_le32(val);
|
|
|
|
|
|
|
|
|
|
if (beacon) {
|
|
|
|
|
p_fmt = MT_TX_TYPE_FW;
|
|
|
|
|
q_idx = MT_LMAC_BCN0;
|
|
|
|
|
} else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
|
|
|
|
|
p_fmt = MT_TX_TYPE_CT;
|
|
|
|
|
q_idx = MT_LMAC_ALTX0;
|
|
|
|
|
} else {
|
|
|
|
|
p_fmt = MT_TX_TYPE_CT;
|
|
|
|
|
q_idx = wmm_idx * MT7915_MAX_WMM_SETS +
|
|
|
|
|
mt7915_lmac_mapping(dev, skb_get_queue_mapping(skb));
|
|
|
|
|
}
|
|
|
|
|
fc_type = IEEE80211_FTYPE_DATA >> 2;
|
|
|
|
|
fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0;
|
|
|
|
|
|
|
|
|
|
val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
|
|
|
|
|
FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) |
|
|
|
|
|
FIELD_PREP(MT_TXD2_MULTICAST, multicast);
|
|
|
|
|
|
|
|
|
|
if (multicast)
|
|
|
|
|
val |= MT_TXD2_FIX_RATE;
|
|
|
|
|
|
|
|
|
|
txwi[2] |= cpu_to_le32(val);
|
|
|
|
|
|
|
|
|
|
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
|
|
|
|
|
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype);
|
|
|
|
|
txwi[7] |= cpu_to_le32(val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mt7915_mac_write_txwi_80211(struct mt7915_dev *dev, __le32 *txwi,
|
|
|
|
|
struct sk_buff *skb, struct ieee80211_key_conf *key)
|
|
|
|
|
{
|
|
|
|
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
|
|
|
|
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
|
|
|
|
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
|
|
|
bool multicast = is_multicast_ether_addr(hdr->addr1);
|
|
|
|
|
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
|
|
|
|
|
__le16 fc = hdr->frame_control;
|
|
|
|
|
u8 fc_type, fc_stype;
|
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
|
|
if (ieee80211_is_action(fc) &&
|
|
|
|
|
mgmt->u.action.category == WLAN_CATEGORY_BACK &&
|
|
|
|
@@ -627,6 +638,90 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
|
|
|
|
tid = FIELD_GET(IEEE80211_BAR_CTRL_TID_INFO_MASK, control);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
|
|
|
|
|
FIELD_PREP(MT_TXD1_HDR_INFO,
|
|
|
|
|
ieee80211_get_hdrlen_from_skb(skb) / 2) |
|
|
|
|
|
FIELD_PREP(MT_TXD1_TID, tid);
|
|
|
|
|
txwi[1] |= cpu_to_le32(val);
|
|
|
|
|
|
|
|
|
|
fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2;
|
|
|
|
|
fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4;
|
|
|
|
|
|
|
|
|
|
val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
|
|
|
|
|
FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) |
|
|
|
|
|
FIELD_PREP(MT_TXD2_MULTICAST, multicast);
|
|
|
|
|
|
|
|
|
|
if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) &&
|
|
|
|
|
key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
|
|
|
|
|
val |= MT_TXD2_BIP;
|
|
|
|
|
txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ieee80211_is_data(fc) || multicast)
|
|
|
|
|
val |= MT_TXD2_FIX_RATE;
|
|
|
|
|
|
|
|
|
|
txwi[2] |= cpu_to_le32(val);
|
|
|
|
|
|
|
|
|
|
if (ieee80211_is_beacon(fc)) {
|
|
|
|
|
txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
|
|
|
|
|
txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (info->flags & IEEE80211_TX_CTL_INJECTED) {
|
|
|
|
|
u16 seqno = le16_to_cpu(hdr->seq_ctrl);
|
|
|
|
|
|
|
|
|
|
if (ieee80211_is_back_req(hdr->frame_control)) {
|
|
|
|
|
struct ieee80211_bar *bar;
|
|
|
|
|
|
|
|
|
|
bar = (struct ieee80211_bar *)skb->data;
|
|
|
|
|
seqno = le16_to_cpu(bar->start_seq_num);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = MT_TXD3_SN_VALID |
|
|
|
|
|
FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
|
|
|
|
|
txwi[3] |= cpu_to_le32(val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
|
|
|
|
|
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype);
|
|
|
|
|
txwi[7] |= cpu_to_le32(val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
|
|
|
|
struct sk_buff *skb, struct mt76_wcid *wcid,
|
|
|
|
|
struct ieee80211_key_conf *key, bool beacon)
|
|
|
|
|
{
|
|
|
|
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
|
|
|
struct ieee80211_vif *vif = info->control.vif;
|
|
|
|
|
struct mt76_phy *mphy = &dev->mphy;
|
|
|
|
|
bool ext_phy = info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY;
|
|
|
|
|
u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0;
|
|
|
|
|
bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP;
|
|
|
|
|
u16 tx_count = 15;
|
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
|
|
if (vif) {
|
|
|
|
|
struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;
|
|
|
|
|
|
|
|
|
|
omac_idx = mvif->omac_idx;
|
|
|
|
|
wmm_idx = mvif->wmm_idx;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ext_phy && dev->mt76.phy2)
|
|
|
|
|
mphy = dev->mt76.phy2;
|
|
|
|
|
|
|
|
|
|
if (beacon) {
|
|
|
|
|
p_fmt = MT_TX_TYPE_FW;
|
|
|
|
|
q_idx = MT_LMAC_BCN0;
|
|
|
|
|
} else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) {
|
|
|
|
|
p_fmt = MT_TX_TYPE_CT;
|
|
|
|
|
q_idx = MT_LMAC_ALTX0;
|
|
|
|
|
} else {
|
|
|
|
|
p_fmt = MT_TX_TYPE_CT;
|
|
|
|
|
q_idx = wmm_idx * MT7915_MAX_WMM_SETS +
|
|
|
|
|
mt7915_lmac_mapping(dev, skb_get_queue_mapping(skb));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + MT_TXD_SIZE) |
|
|
|
|
|
FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) |
|
|
|
|
|
FIELD_PREP(MT_TXD0_Q_IDX, q_idx);
|
|
|
|
@@ -634,10 +729,6 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
|
|
|
|
|
|
|
|
|
val = MT_TXD1_LONG_FORMAT |
|
|
|
|
|
FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) |
|
|
|
|
|
FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) |
|
|
|
|
|
FIELD_PREP(MT_TXD1_HDR_INFO,
|
|
|
|
|
ieee80211_get_hdrlen_from_skb(skb) / 2) |
|
|
|
|
|
FIELD_PREP(MT_TXD1_TID, tid) |
|
|
|
|
|
FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx);
|
|
|
|
|
|
|
|
|
|
if (ext_phy && q_idx >= MT_LMAC_ALTX0 && q_idx <= MT_LMAC_BCN0)
|
|
|
|
@@ -645,27 +736,31 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
|
|
|
|
|
|
|
|
|
txwi[1] = cpu_to_le32(val);
|
|
|
|
|
|
|
|
|
|
val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) |
|
|
|
|
|
FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype) |
|
|
|
|
|
FIELD_PREP(MT_TXD2_MULTICAST, multicast);
|
|
|
|
|
if (key) {
|
|
|
|
|
if (multicast && ieee80211_is_robust_mgmt_frame(skb) &&
|
|
|
|
|
key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) {
|
|
|
|
|
val |= MT_TXD2_BIP;
|
|
|
|
|
txwi[3] = 0;
|
|
|
|
|
} else {
|
|
|
|
|
txwi[3] = cpu_to_le32(MT_TXD3_PROTECT_FRAME);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
txwi[3] = 0;
|
|
|
|
|
}
|
|
|
|
|
txwi[2] = cpu_to_le32(val);
|
|
|
|
|
txwi[2] = 0;
|
|
|
|
|
|
|
|
|
|
if (!ieee80211_is_data(fc) || multicast) {
|
|
|
|
|
val = MT_TXD3_SW_POWER_MGMT |
|
|
|
|
|
FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
|
|
|
|
|
if (key)
|
|
|
|
|
val |= MT_TXD3_PROTECT_FRAME;
|
|
|
|
|
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
|
|
|
|
val |= MT_TXD3_NO_ACK;
|
|
|
|
|
|
|
|
|
|
txwi[3] = cpu_to_le32(val);
|
|
|
|
|
txwi[4] = 0;
|
|
|
|
|
txwi[5] = 0;
|
|
|
|
|
txwi[6] = 0;
|
|
|
|
|
txwi[7] = wcid->amsdu ? cpu_to_le32(MT_TXD7_HW_AMSDU) : 0;
|
|
|
|
|
|
|
|
|
|
if (is_8023)
|
|
|
|
|
mt7915_mac_write_txwi_8023(dev, txwi, skb, wcid);
|
|
|
|
|
else
|
|
|
|
|
mt7915_mac_write_txwi_80211(dev, txwi, skb, key);
|
|
|
|
|
|
|
|
|
|
if (txwi[2] & cpu_to_le32(MT_TXD2_FIX_RATE)) {
|
|
|
|
|
u16 rate;
|
|
|
|
|
|
|
|
|
|
/* hardware won't add HTC for mgmt/ctrl frame */
|
|
|
|
|
txwi[2] |= cpu_to_le32(MT_TXD2_FIX_RATE | MT_TXD2_HTC_VLD);
|
|
|
|
|
txwi[2] |= cpu_to_le32(MT_TXD2_HTC_VLD);
|
|
|
|
|
|
|
|
|
|
if (mphy->chandef.chan->band == NL80211_BAND_5GHZ)
|
|
|
|
|
rate = MT7915_5G_RATE_DEFAULT;
|
|
|
|
@@ -677,36 +772,6 @@ void mt7915_mac_write_txwi(struct mt7915_dev *dev, __le32 *txwi,
|
|
|
|
|
txwi[6] |= cpu_to_le32(val);
|
|
|
|
|
txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ieee80211_is_beacon(fc))
|
|
|
|
|
txwi[3] |= cpu_to_le32(MT_TXD3_SW_POWER_MGMT);
|
|
|
|
|
else
|
|
|
|
|
tx_count = 0x1f;
|
|
|
|
|
|
|
|
|
|
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
|
|
|
|
txwi[3] |= cpu_to_le32(MT_TXD3_NO_ACK);
|
|
|
|
|
|
|
|
|
|
val = FIELD_PREP(MT_TXD7_TYPE, fc_type) |
|
|
|
|
|
FIELD_PREP(MT_TXD7_SUB_TYPE, fc_stype);
|
|
|
|
|
if (wcid->amsdu)
|
|
|
|
|
val |= MT_TXD7_HW_AMSDU;
|
|
|
|
|
txwi[7] = cpu_to_le32(val);
|
|
|
|
|
|
|
|
|
|
val = FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count);
|
|
|
|
|
if (info->flags & IEEE80211_TX_CTL_INJECTED) {
|
|
|
|
|
seqno = le16_to_cpu(hdr->seq_ctrl);
|
|
|
|
|
|
|
|
|
|
if (ieee80211_is_back_req(hdr->frame_control)) {
|
|
|
|
|
struct ieee80211_bar *bar;
|
|
|
|
|
|
|
|
|
|
bar = (struct ieee80211_bar *)skb->data;
|
|
|
|
|
seqno = le16_to_cpu(bar->start_seq_num);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val |= MT_TXD3_SN_VALID |
|
|
|
|
|
FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
|
|
|
|
|
}
|
|
|
|
|
txwi[3] |= cpu_to_le32(val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|
|
|
@@ -728,11 +793,11 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|
|
|
|
if (!wcid)
|
|
|
|
|
wcid = &dev->mt76.global_wcid;
|
|
|
|
|
|
|
|
|
|
cb->wcid = wcid->idx;
|
|
|
|
|
|
|
|
|
|
mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, key,
|
|
|
|
|
false);
|
|
|
|
|
|
|
|
|
|
cb->wcid = wcid->idx;
|
|
|
|
|
|
|
|
|
|
txp = (struct mt7915_txp *)(txwi + MT_TXD_SIZE);
|
|
|
|
|
for (i = 0; i < nbuf; i++) {
|
|
|
|
|
txp->buf[i] = cpu_to_le32(tx_info->buf[i + 1].addr);
|
|
|
|
@@ -750,7 +815,8 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
|
|
|
|
|
if (!key)
|
|
|
|
|
txp->flags |= cpu_to_le16(MT_CT_INFO_NONE_CIPHER_FRAME);
|
|
|
|
|
|
|
|
|
|
if (ieee80211_is_mgmt(hdr->frame_control))
|
|
|
|
|
if (!(info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) &&
|
|
|
|
|
ieee80211_is_mgmt(hdr->frame_control))
|
|
|
|
|
txp->flags |= cpu_to_le16(MT_CT_INFO_MGMT_FRAME);
|
|
|
|
|
|
|
|
|
|
if (vif) {
|
|
|
|
@@ -843,7 +909,8 @@ mt7915_tx_complete_status(struct mt76_dev *mdev, struct sk_buff *skb,
|
|
|
|
|
|
|
|
|
|
info->status.tx_time = 0;
|
|
|
|
|
|
|
|
|
|
if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) {
|
|
|
|
|
if (info->flags & (IEEE80211_TX_CTL_REQ_TX_STATUS |
|
|
|
|
|
IEEE80211_TX_CTL_HW_80211_ENCAP)) {
|
|
|
|
|
mt7915_tx_status(sta, hw, info, skb);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|