rtw89_core_get_tx_type() classifies every frame that is neither a management nor a null-data frame as data. Injected control frames such as a 10-byte ACK or 16-byte RTS therefore go through rtw89_core_tx_update_data_info(), which derives a TID and data queue from skb->priority and enables AMPDU/QoS related descriptor fields that make no sense for them. Classify injected non-data frames as management frames. Frames generated by mac80211 itself, such as BlockAckReq, are not affected. In addition, rtw89_core_tx_update_desc_info() reads hdr->seq_ctrl at offset 22 for every frame. Control frames have no sequence control field and are shorter than 24 bytes, so only read hdr->seq_ctrl from non-control frames whose linear header is long enough to carry it. Signed-off-by: Enver Ikromov --- drivers/net/wireless/realtek/rtw89/core.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index 54605f7..7003c24 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -637,12 +637,21 @@ static enum rtw89_core_tx_type rtw89_core_get_tx_type(struct rtw89_dev *rtwdev, struct sk_buff *skb) { + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (void *)skb->data; __le16 fc = hdr->frame_control; if (ieee80211_is_mgmt(fc) || ieee80211_is_any_nullfunc(fc)) return RTW89_CORE_TX_TYPE_MGMT; + /* Injected control frames have no QoS/TID and no data payload, so + * send them through the management path. Control frames built by + * mac80211 itself (e.g. BlockAckReq) keep using the data path. + */ + if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED) && + !ieee80211_is_data(fc)) + return RTW89_CORE_TX_TYPE_MGMT; + return RTW89_CORE_TX_TYPE_DATA; } @@ -1299,7 +1308,7 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev, enum btc_pkt_type pkt_type; bool upd_wlan_hdr = false; bool is_bmc; - u16 seq; + u16 seq = 0; desc_info->pkt_size = skb->len; @@ -1315,7 +1324,10 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev, else if (tx_req->vif) desc_info->mlo = ieee80211_vif_is_mld(tx_req->vif); - seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; + /* control frames (e.g. 10-byte ACK/CTS) have no sequence control */ + if (!ieee80211_is_ctl(hdr->frame_control) && + skb_headlen(skb) >= sizeof(struct ieee80211_hdr_3addr)) + seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; addr_cam = rtw89_get_addr_cam_of(tx_req->rtwvif_link, tx_req->rtwsta_link); if (addr_cam->valid && desc_info->mlo) -- 2.56.0.windows.4