Do not use bitmask in mt76_wed_rro_ind DMA descriptor in order to not break endianness. This patch is based on the following series: https://lore.kernel.org/linux-wireless/20250909-mt7996-rro-rework-v5-0-7d66f6eb7795@kernel.org/T/#m8b488004d69036cd3672b9eeca8005a937ec0313 Fixes: 950d0abb5cd94 ("wifi: mt76: mt7996: add wed rx support") Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/dma.c | 9 ++++++-- drivers/net/wireless/mediatek/mt76/mt76.h | 17 ++++++++------- .../net/wireless/mediatek/mt76/mt7996/mac.c | 21 ++++++++++++------- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c index 5dc093b21838..1fa7de1d2c45 100644 --- a/drivers/net/wireless/mediatek/mt76/dma.c +++ b/drivers/net/wireless/mediatek/mt76/dma.c @@ -194,6 +194,8 @@ mt76_dma_queue_magic_cnt_init(struct mt76_dev *dev, struct mt76_queue *q) q->magic_cnt = 0; if (mt76_queue_is_wed_rro_ind(q)) { struct mt76_wed_rro_desc *rro_desc; + u32 data1 = FIELD_PREP(RRO_IND_DATA1_MAGIC_CNT_MASK, + MT_DMA_WED_IND_CMD_CNT - 1); int i; rro_desc = (struct mt76_wed_rro_desc *)q->desc; @@ -201,7 +203,7 @@ mt76_dma_queue_magic_cnt_init(struct mt76_dev *dev, struct mt76_queue *q) struct mt76_wed_rro_ind *cmd; cmd = (struct mt76_wed_rro_ind *)&rro_desc[i]; - cmd->magic_cnt = MT_DMA_WED_IND_CMD_CNT - 1; + cmd->data1 = cpu_to_le32(data1); } } else if (mt76_queue_is_wed_rro_rxdmad_c(q)) { struct mt76_rro_rxdmad_c *dmad = (void *)q->desc; @@ -582,12 +584,15 @@ mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush, if (mt76_queue_is_wed_rro_ind(q)) { struct mt76_wed_rro_ind *cmd; + u8 magic_cnt; if (flush) goto done; cmd = q->entry[idx].buf; - if (cmd->magic_cnt != q->magic_cnt) + magic_cnt = FIELD_GET(RRO_IND_DATA1_MAGIC_CNT_MASK, + le32_to_cpu(cmd->data1)); + if (magic_cnt != q->magic_cnt) return NULL; if (q->tail == q->ndesc - 1) diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index a78d663ee91d..eede0c0fe2b9 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -415,15 +415,16 @@ struct mt76_txq { bool aggr; }; +/* data0 */ +#define RRO_IND_DATA0_IND_REASON_MASK GENMASK(31, 28) +#define RRO_IND_DATA0_START_SEQ_MASK GENMASK(27, 16) +#define RRO_IND_DATA0_SEQ_ID_MASK GENMASK(11, 0) +/* data1 */ +#define RRO_IND_DATA1_MAGIC_CNT_MASK GENMASK(31, 29) +#define RRO_IND_DATA1_IND_COUNT_MASK GENMASK(12, 0) struct mt76_wed_rro_ind { - u32 se_id : 12; - u32 rsv : 4; - u32 start_sn : 12; - u32 ind_reason : 4; - u32 ind_cnt : 13; - u32 win_sz : 3; - u32 rsv2 : 13; - u32 magic_cnt : 3; + __le32 data0; + __le32 data1; }; struct mt76_txwi_cache { diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index ed10e45b21a4..5b43678e6556 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1822,11 +1822,17 @@ void mt7996_rro_rx_process(struct mt76_dev *mdev, void *data) { struct mt7996_dev *dev = container_of(mdev, struct mt7996_dev, mt76); struct mt76_wed_rro_ind *cmd = (struct mt76_wed_rro_ind *)data; + u32 cmd_data0 = le32_to_cpu(cmd->data0); + u32 cmd_data1 = le32_to_cpu(cmd->data1); + u8 ind_reason = FIELD_GET(RRO_IND_DATA0_IND_REASON_MASK, cmd_data0); + u16 start_seq = FIELD_GET(RRO_IND_DATA0_START_SEQ_MASK, cmd_data0); + u16 seq_id = FIELD_GET(RRO_IND_DATA0_SEQ_ID_MASK, cmd_data0); + u16 ind_count = FIELD_GET(RRO_IND_DATA1_IND_COUNT_MASK, cmd_data1); struct mt7996_msdu_page_info *pinfo = NULL; struct mt7996_msdu_page *p = NULL; int i, seq_num = 0; - for (i = 0; i < cmd->ind_cnt; i++) { + for (i = 0; i < ind_count; i++) { struct mt7996_wed_rro_addr *e; struct mt76_rx_status *status; struct mt7996_rro_hif *rxd; @@ -1841,8 +1847,8 @@ void mt7996_rro_rx_process(struct mt76_dev *mdev, void *data) void *buf; bool ls; - seq_num = FIELD_GET(MT996_RRO_SN_MASK, cmd->start_sn + i); - e = mt7996_rro_addr_elem_get(dev, cmd->se_id, seq_num); + seq_num = FIELD_GET(MT996_RRO_SN_MASK, start_seq + i); + e = mt7996_rro_addr_elem_get(dev, seq_id, seq_num); data = le32_to_cpu(e->data); signature = FIELD_GET(WED_RRO_ADDR_SIGNATURE_MASK, data); if (signature != (seq_num / MT7996_RRO_WINDOW_MAX_LEN)) { @@ -1930,7 +1936,7 @@ void mt7996_rro_rx_process(struct mt76_dev *mdev, void *data) skb_mark_for_recycle(skb); __skb_put(skb, len); - if (cmd->ind_reason == 1 || cmd->ind_reason == 2) { + if (ind_reason == 1 || ind_reason == 2) { dev_kfree_skb(skb); goto next_page; } @@ -1941,7 +1947,7 @@ void mt7996_rro_rx_process(struct mt76_dev *mdev, void *data) } status = (struct mt76_rx_status *)skb->cb; - if (cmd->se_id != MT7996_RRO_MAX_SESSION) + if (seq_id != MT7996_RRO_MAX_SESSION) status->aggr = true; mt7996_queue_rx_skb(mdev, qid, skb, &info); @@ -1965,7 +1971,7 @@ void mt7996_rro_rx_process(struct mt76_dev *mdev, void *data) if ((i + 1) % 4 == 0) mt76_wr(dev, MT_RRO_ACK_SN_CTRL, FIELD_PREP(MT_RRO_ACK_SN_CTRL_SESSION_MASK, - cmd->se_id) | + seq_id) | FIELD_PREP(MT_RRO_ACK_SN_CTRL_SN_MASK, seq_num)); if (p) { @@ -1977,8 +1983,7 @@ void mt7996_rro_rx_process(struct mt76_dev *mdev, void *data) /* Update ack_seq_num for remaining addr_elem */ if (i % 4) mt76_wr(dev, MT_RRO_ACK_SN_CTRL, - FIELD_PREP(MT_RRO_ACK_SN_CTRL_SESSION_MASK, - cmd->se_id) | + FIELD_PREP(MT_RRO_ACK_SN_CTRL_SESSION_MASK, seq_id) | FIELD_PREP(MT_RRO_ACK_SN_CTRL_SN_MASK, seq_num)); } -- 2.51.0