public inbox for linux-rdma@vger.kernel.org
 help / color / mirror / Atom feed
From: Jacob Moroni <jmoroni@google.com>
To: tatyana.e.nikolova@intel.com, krzysztof.czurylo@intel.com
Cc: jgg@ziepe.ca, leon@kernel.org, linux-rdma@vger.kernel.org,
	 Jacob Moroni <jmoroni@google.com>
Subject: [PATCH rdma-next] RDMA/irdma: Convert QP table to xarray
Date: Sun, 18 Jan 2026 01:25:00 +0000	[thread overview]
Message-ID: <20260118012500.681672-1-jmoroni@google.com> (raw)

Some devices can support a very large number of QPs, so convert
the qp_table array into xarray for more efficient memory usage.
This should reduce common-case memory usage by megabytes.

Also, remove the space that was being reserved for the srq table
which doesn't exist.

Tested with KASAN+lockdep and a full cycle of QP/CQ create/destroy
for the entire ID space.

Signed-off-by: Jacob Moroni <jmoroni@google.com>
---
 drivers/infiniband/hw/irdma/cm.c    |  8 ++++----
 drivers/infiniband/hw/irdma/hw.c    | 17 +++++++----------
 drivers/infiniband/hw/irdma/main.h  |  3 +--
 drivers/infiniband/hw/irdma/utils.c | 15 ++++++++++-----
 drivers/infiniband/hw/irdma/verbs.c |  9 +++++++--
 5 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/drivers/infiniband/hw/irdma/cm.c b/drivers/infiniband/hw/irdma/cm.c
index f4f4f92ba..3104f3870 100644
--- a/drivers/infiniband/hw/irdma/cm.c
+++ b/drivers/infiniband/hw/irdma/cm.c
@@ -3448,9 +3448,9 @@ void irdma_cm_disconn(struct irdma_qp *iwqp)
 	if (!work)
 		return;
 
-	spin_lock_irqsave(&iwdev->rf->qptable_lock, flags);
-	if (!iwdev->rf->qp_table[iwqp->ibqp.qp_num]) {
-		spin_unlock_irqrestore(&iwdev->rf->qptable_lock, flags);
+	xa_lock_irqsave(&iwdev->rf->qp_xa, flags);
+	if (!xa_load(&iwdev->rf->qp_xa, iwqp->ibqp.qp_num)) {
+		xa_unlock_irqrestore(&iwdev->rf->qp_xa, flags);
 		ibdev_dbg(&iwdev->ibdev,
 			  "CM: qp_id %d is already freed\n",
 			  iwqp->ibqp.qp_num);
@@ -3458,7 +3458,7 @@ void irdma_cm_disconn(struct irdma_qp *iwqp)
 		return;
 	}
 	irdma_qp_add_ref(&iwqp->ibqp);
-	spin_unlock_irqrestore(&iwdev->rf->qptable_lock, flags);
+	xa_unlock_irqrestore(&iwdev->rf->qp_xa, flags);
 
 	work->iwqp = iwqp;
 	INIT_WORK(&work->work, irdma_disconnect_worker);
diff --git a/drivers/infiniband/hw/irdma/hw.c b/drivers/infiniband/hw/irdma/hw.c
index 31c67b753..d01fcba7f 100644
--- a/drivers/infiniband/hw/irdma/hw.c
+++ b/drivers/infiniband/hw/irdma/hw.c
@@ -313,11 +313,10 @@ static void irdma_process_aeq(struct irdma_pci_f *rf)
 			  info->iwarp_state, info->ae_src);
 
 		if (info->qp) {
-			spin_lock_irqsave(&rf->qptable_lock, flags);
-			iwqp = rf->qp_table[info->qp_cq_id];
+			xa_lock_irqsave(&rf->qp_xa, flags);
+			iwqp = xa_load(&rf->qp_xa, info->qp_cq_id);
 			if (!iwqp) {
-				spin_unlock_irqrestore(&rf->qptable_lock,
-						       flags);
+				xa_unlock_irqrestore(&rf->qp_xa, flags);
 				if (info->ae_id == IRDMA_AE_QP_SUSPEND_COMPLETE) {
 					atomic_dec(&iwdev->vsi.qp_suspend_reqs);
 					wake_up(&iwdev->suspend_wq);
@@ -328,7 +327,7 @@ static void irdma_process_aeq(struct irdma_pci_f *rf)
 				continue;
 			}
 			irdma_qp_add_ref(&iwqp->ibqp);
-			spin_unlock_irqrestore(&rf->qptable_lock, flags);
+			xa_unlock_irqrestore(&rf->qp_xa, flags);
 			qp = &iwqp->sc_qp;
 			spin_lock_irqsave(&iwqp->lock, flags);
 			iwqp->hw_tcp_state = info->tcp_state;
@@ -1701,6 +1700,7 @@ static void irdma_del_init_mem(struct irdma_pci_f *rf)
 	dev->hmc_info->sd_table.sd_entry = NULL;
 	vfree(rf->mem_rsrc);
 	rf->mem_rsrc = NULL;
+	xa_destroy(&rf->qp_xa);
 	dma_free_coherent(rf->hw.device, rf->obj_mem.size, rf->obj_mem.va,
 			  rf->obj_mem.pa);
 	rf->obj_mem.va = NULL;
@@ -2091,13 +2091,12 @@ static void irdma_set_hw_rsrc(struct irdma_pci_f *rf)
 	rf->allocated_ahs = &rf->allocated_pds[BITS_TO_LONGS(rf->max_pd)];
 	rf->allocated_mcgs = &rf->allocated_ahs[BITS_TO_LONGS(rf->max_ah)];
 	rf->allocated_arps = &rf->allocated_mcgs[BITS_TO_LONGS(rf->max_mcg)];
-	rf->qp_table = (struct irdma_qp **)
+	rf->cq_table = (struct irdma_cq **)
 		(&rf->allocated_arps[BITS_TO_LONGS(rf->arp_table_size)]);
-	rf->cq_table = (struct irdma_cq **)(&rf->qp_table[rf->max_qp]);
 
+	xa_init_flags(&rf->qp_xa, XA_FLAGS_LOCK_IRQ);
 	spin_lock_init(&rf->rsrc_lock);
 	spin_lock_init(&rf->arp_lock);
-	spin_lock_init(&rf->qptable_lock);
 	spin_lock_init(&rf->cqtable_lock);
 	spin_lock_init(&rf->qh_list_lock);
 }
@@ -2119,9 +2118,7 @@ static u32 irdma_calc_mem_rsrc_size(struct irdma_pci_f *rf)
 	rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->arp_table_size);
 	rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_ah);
 	rsrc_size += sizeof(unsigned long) * BITS_TO_LONGS(rf->max_mcg);
-	rsrc_size += sizeof(struct irdma_qp **) * rf->max_qp;
 	rsrc_size += sizeof(struct irdma_cq **) * rf->max_cq;
-	rsrc_size += sizeof(struct irdma_srq **) * rf->max_srq;
 
 	return rsrc_size;
 }
diff --git a/drivers/infiniband/hw/irdma/main.h b/drivers/infiniband/hw/irdma/main.h
index d320d1a22..6fd3dbef1 100644
--- a/drivers/infiniband/hw/irdma/main.h
+++ b/drivers/infiniband/hw/irdma/main.h
@@ -321,9 +321,8 @@ struct irdma_pci_f {
 	struct irdma_arp_entry *arp_table;
 	spinlock_t arp_lock; /*protect ARP table access*/
 	spinlock_t rsrc_lock; /* protect HW resource array access */
-	spinlock_t qptable_lock; /*protect QP table access*/
 	spinlock_t cqtable_lock; /*protect CQ table access*/
-	struct irdma_qp **qp_table;
+	struct xarray qp_xa;
 	struct irdma_cq **cq_table;
 	spinlock_t qh_list_lock; /* protect mc_qht_list */
 	struct mc_table_list mc_qht_list;
diff --git a/drivers/infiniband/hw/irdma/utils.c b/drivers/infiniband/hw/irdma/utils.c
index 08b23e24e..34e332ba1 100644
--- a/drivers/infiniband/hw/irdma/utils.c
+++ b/drivers/infiniband/hw/irdma/utils.c
@@ -798,15 +798,15 @@ void irdma_qp_rem_ref(struct ib_qp *ibqp)
 	u32 qp_num;
 	unsigned long flags;
 
-	spin_lock_irqsave(&iwdev->rf->qptable_lock, flags);
+	xa_lock_irqsave(&iwdev->rf->qp_xa, flags);
 	if (!refcount_dec_and_test(&iwqp->refcnt)) {
-		spin_unlock_irqrestore(&iwdev->rf->qptable_lock, flags);
+		xa_unlock_irqrestore(&iwdev->rf->qp_xa, flags);
 		return;
 	}
 
 	qp_num = iwqp->ibqp.qp_num;
-	iwdev->rf->qp_table[qp_num] = NULL;
-	spin_unlock_irqrestore(&iwdev->rf->qptable_lock, flags);
+	__xa_erase(&iwdev->rf->qp_xa, qp_num);
+	xa_unlock_irqrestore(&iwdev->rf->qp_xa, flags);
 	complete(&iwqp->free_qp);
 }
 
@@ -849,11 +849,16 @@ struct ib_device *to_ibdev(struct irdma_sc_dev *dev)
 struct ib_qp *irdma_get_qp(struct ib_device *device, int qpn)
 {
 	struct irdma_device *iwdev = to_iwdev(device);
+	struct irdma_qp *iqp;
 
 	if (qpn < IW_FIRST_QPN || qpn >= iwdev->rf->max_qp)
 		return NULL;
 
-	return &iwdev->rf->qp_table[qpn]->ibqp;
+	iqp = xa_load(&iwdev->rf->qp_xa, qpn);
+	if (!iqp)
+		return NULL;
+
+	return &iqp->ibqp;
 }
 
 /**
diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c
index cf8d19150..9d80388f4 100644
--- a/drivers/infiniband/hw/irdma/verbs.c
+++ b/drivers/infiniband/hw/irdma/verbs.c
@@ -1104,7 +1104,13 @@ static int irdma_create_qp(struct ib_qp *ibqp,
 	spin_lock_init(&iwqp->lock);
 	spin_lock_init(&iwqp->sc_qp.pfpdu.lock);
 	iwqp->sig_all = init_attr->sq_sig_type == IB_SIGNAL_ALL_WR;
-	rf->qp_table[qp_num] = iwqp;
+	init_completion(&iwqp->free_qp);
+
+	err_code = xa_err(xa_store_irq(&rf->qp_xa, qp_num, iwqp, GFP_KERNEL));
+	if (err_code) {
+		irdma_destroy_qp(&iwqp->ibqp, udata);
+		return err_code;
+	}
 
 	if (udata) {
 		/* GEN_1 legacy support with libi40iw does not have expanded uresp struct */
@@ -1129,7 +1135,6 @@ static int irdma_create_qp(struct ib_qp *ibqp,
 		}
 	}
 
-	init_completion(&iwqp->free_qp);
 	return 0;
 
 error:
-- 
2.52.0.457.g6b5491de43-goog


             reply	other threads:[~2026-01-18  1:25 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-18  1:25 Jacob Moroni [this message]
2026-01-19 12:53 ` [PATCH rdma-next] RDMA/irdma: Convert QP table to xarray Czurylo, Krzysztof
2026-01-19 15:56   ` Jacob Moroni
2026-01-20 18:58     ` Jason Gunthorpe

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=20260118012500.681672-1-jmoroni@google.com \
    --to=jmoroni@google.com \
    --cc=jgg@ziepe.ca \
    --cc=krzysztof.czurylo@intel.com \
    --cc=leon@kernel.org \
    --cc=linux-rdma@vger.kernel.org \
    --cc=tatyana.e.nikolova@intel.com \
    /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