lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20251218091050.55047-8-15927021679@163.com>
Date: Thu, 18 Dec 2025 17:09:47 +0800
From: Xiong Weimin <15927021679@....com>
To: "Michael S . Tsirkin" <mst@...hat.com>,
	David Hildenbrand <david@...hat.com>,
	Jason Wang <jasowang@...hat.com>,
	Stefano Garzarella <sgarzare@...hat.com>,
	Thomas Monjalon <thomas@...jalon.net>,
	David Marchand <david.marchand@...hat.com>,
	Luca Boccassi <bluca@...ian.org>,
	Kevin Traynor <ktraynor@...hat.com>,
	Christian Ehrhardt <christian.ehrhardt@...onical.com>,
	Xuan Zhuo <xuanzhuo@...ux.alibaba.com>,
	Eugenio Pérez <eperezma@...hat.com>,
	Xueming Li <xuemingl@...dia.com>,
	Maxime Coquelin <maxime.coquelin@...hat.com>,
	Chenbo Xia <chenbox@...dia.com>,
	Bruce Richardson <bruce.richardson@...el.com>
Cc: kvm@...r.kernel.org,
	virtualization@...ts.linux.dev,
	netdev@...r.kernel.org,
	xiongweimin <xiongweimin@...inos.cn>
Subject: [PATCH 07/10] drivers/infiniband/hw/virtio: Implement Completion Queue (CQ) polling support

From: xiongweimin <xiongweimin@...inos.cn>

This commit adds CQ polling support to the virtio RDMA driver:

1. Completion queue processing:
   - Retrieves CQEs from virtqueue and converts to ib_wc
   - Implements buffer recycling to avoid memory leaks
   - Handles all standard WC fields including imm_data and flags

2. Key optimizations:
   - IRQ-safe locking for virtqueue operations
   - Batch processing with virtqueue_kick optimization
   - Atomic buffer re-addition to avoid allocation overhead

Signed-off-by: Xiong Weimin <xiongweimin@...inos.cn>
---
 .../drivers/infiniband/hw/virtio/vrdma_ib.c   | 77 ++++++++++++++++++-
 1 file changed, 76 insertions(+), 1 deletion(-)

diff --git a/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.c b/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.c
index 2d9a612f3..705d18b55 100644
--- a/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.c
+++ b/linux-6.16.8/drivers/infiniband/hw/virtio/vrdma_ib.c
@@ -2141,6 +2141,80 @@ static int vrdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
 	return rc;
 }
 
+/**
+ * vrdma_poll_cq - Poll a completion queue for work completions
+ * @ibcq:	Completion queue to poll
+ * @num_entries:	Maximum number of entries to return
+ * @wc:		User-provided array of work completions
+ *
+ * Retrieves completed CQEs from the virtqueue and fills ib_wc structures.
+ * Each consumed CQE buffer is returned to the backend via inbuf.
+ *
+ * Context: Process context (may sleep during virtqueue refill).
+ * Return:
+ * * Number of completed WCs filled (>= 0)
+ * * Does not return negative values (per IB spec)
+ */
+static int vrdma_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
+{
+	struct vrdma_cq *vcq = to_vcq(ibcq);
+	struct vrdma_cqe *cqe;
+	unsigned long flags;
+	unsigned int len;
+	int i = 0;
+	struct scatterlist sg;
+
+	spin_lock_irqsave(&vcq->lock, flags);
+
+	while (i < num_entries) {
+		/* Dequeue one CQE from used ring */
+		cqe = virtqueue_get_buf(vcq->vq->vq, &len);
+		if (!cqe) {
+			break; /* No more completions available */
+		}
+
+		/* Copy CQE fields into ib_wc */
+		wc[i].wr_id = cqe->wr_id;
+		wc[i].status = cqe->status;
+		wc[i].opcode = cqe->opcode;
+		wc[i].vendor_err = cqe->vendor_err;
+		wc[i].byte_len = cqe->byte_len;
+
+		/* TODO: Set wc[i].qp - requires storing QP pointer at send time */
+		// wc[i].qp = container_of(...);
+
+		wc[i].ex.imm_data = cqe->ex.imm_data;
+		wc[i].src_qp = cqe->src_qp;
+		wc[i].slid = cqe->slid;
+		wc[i].wc_flags = cqe->wc_flags;
+		wc[i].pkey_index = cqe->pkey_index;
+		wc[i].sl = cqe->sl;
+		wc[i].dlid_path_bits = cqe->dlid_path_bits;
+		wc[i].port_num = cqe->port_num;
+
+		/* Re-add the CQE buffer to the available list for reuse */
+		sg_init_one(&sg, cqe, sizeof(*cqe));
+		if (virtqueue_add_inbuf(vcq->vq->vq, &sg, 1, cqe, GFP_ATOMIC) != 0) {
+			dev_warn(&vcq->vq->vq->vdev->dev,
+				 "Failed to re-add CQE buffer to vq %p\n", vcq->vq->vq);
+			/* Leak this buffer? Better to warn than crash */
+		}
+
+		i++;
+	}
+
+	/*
+	 * Kick the virtqueue if needed so host can see returned buffers.
+	 * This ensures backend knows which CQE slots are free.
+	 */
+	if (i > 0)
+		virtqueue_kick(vcq->vq->vq);
+
+	spin_unlock_irqrestore(&vcq->lock, flags);
+
+	return i; /* Return number of polled completions */
+}
+
 static const struct ib_device_ops vrdma_dev_ops = {
 	.owner = THIS_MODULE,
 	.uverbs_abi_ver = VIRTIO_RDMA_ABI_VERSION,
@@ -2171,7 +2245,8 @@ static const struct ib_device_ops vrdma_dev_ops = {
 	.mmap = vrdma_mmap,
 	.mmap_free = vrdma_mmap_free,
 	.modify_port = vrdma_modify_port,
-	.modify_qp = vrdma_modify_qp,			
+	.modify_qp = vrdma_modify_qp,
+	.poll_cq = vrdma_poll_cq,			
 };
 
 /**
-- 
2.43.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ