Broadcast and multicast packets in high queue should be transmitted
all at once during DTIM. But without proper settings, hardware fails
to recognize that there are multiple packets and fetches only one.
Fix this by signaling hardware with more data bit set when there are
packets in the high queue.
Signed-off-by: Po-Hao Huang <phhuang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Kalle Valo <kvalo@kernel.org>
Link: https://lore.kernel.org/r/20230616125540.36877-3-pkshih@realtek.com
        const struct rtw_chip_info *chip = rtwdev->chip;
 
        mutex_lock(&rtwdev->mutex);
+       rtw_write32_set(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD);
        rtwdev->ap_active = true;
        rtw_store_op_chan(rtwdev, true);
        chip->ops->phy_calibration(rtwdev);
        struct rtw_dev *rtwdev = hw->priv;
 
        mutex_lock(&rtwdev->mutex);
+       rtw_write32_clr(rtwdev, REG_TCR, BIT_TCR_UPDATE_HGQMD);
        rtwdev->ap_active = false;
        if (!rtw_core_check_sta_active(rtwdev))
                rtw_clear_op_chan(rtwdev);
 
 #define REG_TCR                        0x0604
 #define BIT_PWRMGT_HWDATA_EN   BIT(7)
 #define BIT_TCR_UPDATE_TIMIE   BIT(5)
+#define BIT_TCR_UPDATE_HGQMD   BIT(4)
 #define REG_RCR                        0x0608
 #define BIT_APP_FCS            BIT(31)
 #define BIT_APP_MIC            BIT(30)
 
 void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb)
 {
        struct rtw_tx_desc *tx_desc = (struct rtw_tx_desc *)skb->data;
+       bool more_data = false;
+
+       if (pkt_info->qsel == TX_DESC_QSEL_HIGH)
+               more_data = true;
 
        tx_desc->w0 = le32_encode_bits(pkt_info->tx_pkt_size, RTW_TX_DESC_W0_TXPKTSIZE) |
                      le32_encode_bits(pkt_info->offset, RTW_TX_DESC_W0_OFFSET) |
        tx_desc->w1 = le32_encode_bits(pkt_info->qsel, RTW_TX_DESC_W1_QSEL) |
                      le32_encode_bits(pkt_info->rate_id, RTW_TX_DESC_W1_RATE_ID) |
                      le32_encode_bits(pkt_info->sec_type, RTW_TX_DESC_W1_SEC_TYPE) |
-                     le32_encode_bits(pkt_info->pkt_offset, RTW_TX_DESC_W1_PKT_OFFSET);
+                     le32_encode_bits(pkt_info->pkt_offset, RTW_TX_DESC_W1_PKT_OFFSET) |
+                     le32_encode_bits(more_data, RTW_TX_DESC_W1_MORE_DATA);
 
        tx_desc->w2 = le32_encode_bits(pkt_info->ampdu_en, RTW_TX_DESC_W2_AGG_EN) |
                      le32_encode_bits(pkt_info->report, RTW_TX_DESC_W2_SPE_RPT) |
 
 #define RTW_TX_DESC_W1_RATE_ID GENMASK(20, 16)
 #define RTW_TX_DESC_W1_SEC_TYPE GENMASK(23, 22)
 #define RTW_TX_DESC_W1_PKT_OFFSET GENMASK(28, 24)
+#define RTW_TX_DESC_W1_MORE_DATA BIT(29)
 #define RTW_TX_DESC_W2_AGG_EN BIT(12)
 #define RTW_TX_DESC_W2_SPE_RPT BIT(19)
 #define RTW_TX_DESC_W2_AMPDU_DEN GENMASK(22, 20)
 
 
        if (unlikely(ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)))
                qsel = TX_DESC_QSEL_MGMT;
+       else if (is_broadcast_ether_addr(hdr->addr1) ||
+                is_multicast_ether_addr(hdr->addr1))
+               qsel = TX_DESC_QSEL_HIGH;
        else if (skb_get_queue_mapping(skb) <= IEEE80211_AC_BK)
                qsel = skb->priority;
        else