Netdev List
 help / color / mirror / Atom feed
From: Aditya Garg <gargaditya@linux.microsoft.com>
To: kys@microsoft.com, haiyangz@microsoft.com, wei.liu@kernel.org,
	decui@microsoft.com, longli@microsoft.com, andrew+netdev@lunn.ch,
	davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
	pabeni@redhat.com, kotaranov@microsoft.com, horms@kernel.org,
	ernis@linux.microsoft.com, dipayanroy@linux.microsoft.com,
	shradhagupta@linux.microsoft.com, kees@kernel.org,
	sgeorgejohn@microsoft.com, ssengar@linux.microsoft.com,
	gargaditya@linux.microsoft.com, gargaditya@microsoft.com,
	linux-hyperv@vger.kernel.org, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org
Subject: [PATCH net-next 1/2] net: mana: Route ring-buffer access through offset-based helpers
Date: Fri,  7 Aug 2026 13:56:35 -0700	[thread overview]
Message-ID: <20260807210002.1695263-2-gargaditya@linux.microsoft.com> (raw)
In-Reply-To: <20260807210002.1695263-1-gargaditya@linux.microsoft.com>

In preparation for backing GDMA queue memory with a vector of
non-contiguous order-0 coherent pages, route CPU access to a queue's
ring buffer through two new helpers: mana_gd_ring_ptr() returns the CPU
address of a byte offset into the ring, and mana_gd_ring_contig_avail()
the number of bytes left before the ring wraps, so a WQ write that runs
past the end of the ring can be split at that point.

Convert the EQ, CQ and work-request paths to use them.
mana_gd_write_sgl() now takes a byte offset rather than a raw pointer,
so mana_gd_post_work_request() derives the SGL position arithmetically.

While queue memory is contiguous both helpers are simple arithmetic on
the ring base and size, so there is no functional change.

Signed-off-by: Aditya Garg <gargaditya@linux.microsoft.com>
---
 .../net/ethernet/microsoft/mana/gdma_main.c   | 63 ++++++++++++-------
 1 file changed, 39 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
index a38d4bb74621..31a79693db07 100644
--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
+++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
@@ -753,11 +753,24 @@ int mana_schedule_serv_work(struct gdma_context *gc, enum gdma_eqe_type type)
 	return 0;
 }
 
+/* Return the CPU address of byte @offset within a queue's ring buffer. */
+static void *mana_gd_ring_ptr(const struct gdma_queue *q, u32 offset)
+{
+	return q->queue_mem_ptr + offset;
+}
+
+/* Number of bytes from @offset to the end of the ring buffer, i.e. the point
+ * at which ring access wraps back to the start.
+ */
+static u32 mana_gd_ring_contig_avail(const struct gdma_queue *q, u32 offset)
+{
+	return q->queue_size - offset;
+}
+
 static void mana_gd_process_eqe(struct gdma_queue *eq)
 {
 	u32 head = eq->head % (eq->queue_size / GDMA_EQE_SIZE);
 	struct gdma_context *gc = eq->gdma_dev->gdma_context;
-	struct gdma_eqe *eq_eqe_ptr = eq->queue_mem_ptr;
 	union gdma_eqe_info eqe_info;
 	enum gdma_eqe_type type;
 	struct gdma_event event;
@@ -765,7 +778,7 @@ static void mana_gd_process_eqe(struct gdma_queue *eq)
 	struct gdma_eqe *eqe;
 	u32 cq_id;
 
-	eqe = &eq_eqe_ptr[head];
+	eqe = mana_gd_ring_ptr(eq, head * sizeof(*eqe));
 	eqe_info.as_uint32 = eqe->eqe_info;
 	type = eqe_info.type;
 
@@ -829,7 +842,6 @@ static void mana_gd_process_eq_events(void *arg)
 {
 	u32 owner_bits, new_bits, old_bits;
 	union gdma_eqe_info eqe_info;
-	struct gdma_eqe *eq_eqe_ptr;
 	struct gdma_queue *eq = arg;
 	struct gdma_context *gc;
 	struct gdma_eqe *eqe;
@@ -839,11 +851,10 @@ static void mana_gd_process_eq_events(void *arg)
 	gc = eq->gdma_dev->gdma_context;
 
 	num_eqe = eq->queue_size / GDMA_EQE_SIZE;
-	eq_eqe_ptr = eq->queue_mem_ptr;
 
 	/* Process up to 5 EQEs at a time, and update the HW head. */
 	for (i = 0; i < 5; i++) {
-		eqe = &eq_eqe_ptr[eq->head % num_eqe];
+		eqe = mana_gd_ring_ptr(eq, (eq->head % num_eqe) * sizeof(*eqe));
 		eqe_info.as_uint32 = eqe->eqe_info;
 		owner_bits = eqe_info.owner_bits;
 
@@ -1508,7 +1519,7 @@ u8 *mana_gd_get_wqe_ptr(const struct gdma_queue *wq, u32 wqe_offset)
 
 	WARN_ON_ONCE((offset + GDMA_WQE_BU_SIZE) > wq->queue_size);
 
-	return wq->queue_mem_ptr + offset;
+	return mana_gd_ring_ptr(wq, offset);
 }
 
 static u32 mana_gd_write_client_oob(const struct gdma_wqe_request *wqe_req,
@@ -1554,27 +1565,24 @@ static u32 mana_gd_write_client_oob(const struct gdma_wqe_request *wqe_req,
 	return sizeof(header) + client_oob_size;
 }
 
-static void mana_gd_write_sgl(struct gdma_queue *wq, u8 *wqe_ptr,
+static void mana_gd_write_sgl(struct gdma_queue *wq, u32 sgl_offset,
 			      const struct gdma_wqe_request *wqe_req)
 {
+	u32 size_to_end = mana_gd_ring_contig_avail(wq, sgl_offset);
 	u32 sgl_size = sizeof(struct gdma_sge) * wqe_req->num_sge;
 	const u8 *address = (u8 *)wqe_req->sgl;
-	u8 *base_ptr, *end_ptr;
-	u32 size_to_end;
-
-	base_ptr = wq->queue_mem_ptr;
-	end_ptr = base_ptr + wq->queue_size;
-	size_to_end = (u32)(end_ptr - wqe_ptr);
 
 	if (size_to_end < sgl_size) {
-		memcpy(wqe_ptr, address, size_to_end);
+		memcpy(mana_gd_ring_ptr(wq, sgl_offset), address, size_to_end);
 
-		wqe_ptr = base_ptr;
 		address += size_to_end;
 		sgl_size -= size_to_end;
+		sgl_offset += size_to_end;
+		if (sgl_offset == wq->queue_size)
+			sgl_offset = 0;
 	}
 
-	memcpy(wqe_ptr, address, sgl_size);
+	memcpy(mana_gd_ring_ptr(wq, sgl_offset), address, sgl_size);
 }
 
 int mana_gd_post_work_request(struct gdma_queue *wq,
@@ -1584,8 +1592,12 @@ int mana_gd_post_work_request(struct gdma_queue *wq,
 	u32 client_oob_size = wqe_req->inline_oob_size;
 	u32 sgl_data_size;
 	u32 max_wqe_size;
+	u32 wqe_offset;
+	u32 sgl_offset;
 	u32 wqe_size;
+	u32 oob_len;
 	u8 *wqe_ptr;
+	u32 head;
 
 	if (wqe_req->num_sge == 0)
 		return -EINVAL;
@@ -1617,13 +1629,17 @@ int mana_gd_post_work_request(struct gdma_queue *wq,
 	if (wqe_info)
 		wqe_info->wqe_size_in_bu = wqe_size / GDMA_WQE_BU_SIZE;
 
-	wqe_ptr = mana_gd_get_wqe_ptr(wq, wq->head);
-	wqe_ptr += mana_gd_write_client_oob(wqe_req, wq->type, client_oob_size,
-					    sgl_data_size, wqe_ptr);
-	if (wqe_ptr >= (u8 *)wq->queue_mem_ptr + wq->queue_size)
-		wqe_ptr -= wq->queue_size;
+	head = wq->head;
+	wqe_offset = (head * GDMA_WQE_BU_SIZE) & (wq->queue_size - 1);
+	wqe_ptr = mana_gd_get_wqe_ptr(wq, head);
+	oob_len = mana_gd_write_client_oob(wqe_req, wq->type, client_oob_size,
+					   sgl_data_size, wqe_ptr);
+
+	sgl_offset = wqe_offset + oob_len;
+	if (sgl_offset >= wq->queue_size)
+		sgl_offset -= wq->queue_size;
 
-	mana_gd_write_sgl(wq, wqe_ptr, wqe_req);
+	mana_gd_write_sgl(wq, sgl_offset, wqe_req);
 
 	wq->head += wqe_size / GDMA_WQE_BU_SIZE;
 
@@ -1653,11 +1669,10 @@ int mana_gd_post_and_ring(struct gdma_queue *queue,
 static int mana_gd_read_cqe(struct gdma_queue *cq, struct gdma_comp *comp)
 {
 	unsigned int num_cqe = cq->queue_size / sizeof(struct gdma_cqe);
-	struct gdma_cqe *cq_cqe = cq->queue_mem_ptr;
 	u32 owner_bits, new_bits, old_bits;
 	struct gdma_cqe *cqe;
 
-	cqe = &cq_cqe[cq->head % num_cqe];
+	cqe = mana_gd_ring_ptr(cq, (cq->head % num_cqe) * sizeof(*cqe));
 	owner_bits = cqe->cqe_info.owner_bits;
 
 	old_bits = (cq->head / num_cqe - 1) & GDMA_CQE_OWNER_MASK;
-- 
2.43.0


  reply	other threads:[~2026-08-07 21:00 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-07 20:56 [PATCH net-next 0/2] net: mana: Avoid DMA queue allocation failure under memory fragmentation Aditya Garg
2026-08-07 20:56 ` Aditya Garg [this message]
2026-08-07 20:56 ` [PATCH net-next 2/2] net: mana: Fall back to scattered pages for GDMA queues Aditya Garg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260807210002.1695263-2-gargaditya@linux.microsoft.com \
    --to=gargaditya@linux.microsoft.com \
    --cc=andrew+netdev@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=decui@microsoft.com \
    --cc=dipayanroy@linux.microsoft.com \
    --cc=edumazet@google.com \
    --cc=ernis@linux.microsoft.com \
    --cc=gargaditya@microsoft.com \
    --cc=haiyangz@microsoft.com \
    --cc=horms@kernel.org \
    --cc=kees@kernel.org \
    --cc=kotaranov@microsoft.com \
    --cc=kuba@kernel.org \
    --cc=kys@microsoft.com \
    --cc=linux-hyperv@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=longli@microsoft.com \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=sgeorgejohn@microsoft.com \
    --cc=shradhagupta@linux.microsoft.com \
    --cc=ssengar@linux.microsoft.com \
    --cc=wei.liu@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox