Merge branch 'ionic-fix-completion-descriptor-access'

Eric Joyner says:

====================
ionic: fix completion descriptor access

The first patch adds the missing dma_rmb() between the completion
publish checks and the reads of the descriptor payloads, suggested by
the Sashiko review from [1] for the second patch.

The second locates the completion within its slot from cq->desc_size
rather than a fixed stride, which is necessary when IONIC_Q_F_2X_CQ_DESC
(double-sized completion descriptors) is used (e.g. for hardware
timestamps).

[1] https://lore.kernel.org/netdev/20260507155928.2537928-1-kuba@kernel.org/
====================

Link: https://patch.msgid.link/20260811195039.1315045-1-eric.joyner@amd.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2026-08-17 12:58:48 -07:00
2 changed files with 22 additions and 13 deletions

View File

@@ -269,6 +269,8 @@ bool ionic_notifyq_service(struct ionic_cq *cq)
if ((s64)(eid - lif->last_eid) <= 0)
return false;
dma_rmb();
lif->last_eid = eid;
dev_dbg(lif->ionic->dev, "notifyq event:\n");
@@ -314,6 +316,8 @@ bool ionic_adminq_service(struct ionic_cq *cq)
if (!color_match(comp->color, cq->done_color))
return false;
dma_rmb();
/* check for empty queue */
if (q->tail_idx == q->head_idx)
return false;

View File

@@ -701,11 +701,7 @@ static void ionic_rx_clean(struct ionic_queue *q,
__le64 *cq_desc_hwstamp;
u64 hwstamp;
cq_desc_hwstamp =
(void *)comp +
qcq->cq.desc_size -
sizeof(struct ionic_rxq_comp) -
IONIC_HWSTAMP_CQ_NEGOFFSET;
cq_desc_hwstamp = (void *)comp - IONIC_HWSTAMP_CQ_NEGOFFSET;
hwstamp = le64_to_cpu(*cq_desc_hwstamp);
@@ -729,11 +725,18 @@ static bool __ionic_rx_service(struct ionic_cq *cq, struct bpf_prog *xdp_prog)
struct ionic_queue *q = cq->bound_q;
struct ionic_rxq_comp *comp;
comp = &((struct ionic_rxq_comp *)cq->base)[cq->tail_idx];
if (likely(cq->desc_size == sizeof(*comp)))
comp = &((struct ionic_rxq_comp *)cq->base)[cq->tail_idx];
else
comp = cq->base +
cq->desc_size * cq->tail_idx +
cq->desc_size - sizeof(*comp);
if (!color_match(comp->pkt_type_color, cq->done_color))
return false;
dma_rmb();
/* check for empty queue */
if (q->tail_idx == q->head_idx)
return false;
@@ -1180,7 +1183,6 @@ static void ionic_tx_clean(struct ionic_queue *q,
bool in_napi)
{
struct ionic_tx_stats *stats = q_to_tx_stats(q);
struct ionic_qcq *qcq = q_to_qcq(q);
struct sk_buff *skb;
if (desc_info->xdpf) {
@@ -1205,11 +1207,7 @@ static void ionic_tx_clean(struct ionic_queue *q,
__le64 *cq_desc_hwstamp;
u64 hwstamp;
cq_desc_hwstamp =
(void *)comp +
qcq->cq.desc_size -
sizeof(struct ionic_txq_comp) -
IONIC_HWSTAMP_CQ_NEGOFFSET;
cq_desc_hwstamp = (void *)comp - IONIC_HWSTAMP_CQ_NEGOFFSET;
hwstamp = le64_to_cpu(*cq_desc_hwstamp);
@@ -1244,11 +1242,18 @@ static bool ionic_tx_service(struct ionic_cq *cq,
unsigned int pkts = 0;
u16 index;
comp = &((struct ionic_txq_comp *)cq->base)[cq->tail_idx];
if (likely(cq->desc_size == sizeof(*comp)))
comp = &((struct ionic_txq_comp *)cq->base)[cq->tail_idx];
else
comp = cq->base +
cq->desc_size * cq->tail_idx +
cq->desc_size - sizeof(*comp);
if (!color_match(comp->color, cq->done_color))
return false;
dma_rmb();
/* clean the related q entries, there could be
* several q entries completed for each cq completion
*/