git: 9d87ca8b9f60 - main - if_bnxt: Add support for HWRM passthrough with multiple DMA buffers

From: Sumit Saxena <ssaxena_at_FreeBSD.org>
Date: Mon, 15 Jun 2026 11:35:38 UTC
The branch main has been updated by ssaxena:

URL: https://cgit.FreeBSD.org/src/commit/?id=9d87ca8b9f60bdec0bbc1733920df250a08beb0c

commit 9d87ca8b9f60bdec0bbc1733920df250a08beb0c
Author:     Sreekanth Reddy <sreekanth.reddy@broadcom.com>
AuthorDate: 2026-06-15 09:49:40 +0000
Commit:     Sumit Saxena <ssaxena@FreeBSD.org>
CommitDate: 2026-06-15 11:34:12 +0000

    if_bnxt: Add support for HWRM passthrough with multiple DMA buffers
    
    Added support for HWRM passthrough commands with multiple DMA buffers.
    
    Also, changed the mgmt_lock to sleepable exclusive lock.
    
    MFC after:      2 weeks
    Reviewed by:    gallatin, ssaxena
    Differential Revision: https://reviews.freebsd.org/D56686
---
 sys/dev/bnxt/bnxt_en/bnxt.h      |  3 ++
 sys/dev/bnxt/bnxt_en/bnxt_mgmt.c | 96 ++++++++++++++++++++++++----------------
 2 files changed, 60 insertions(+), 39 deletions(-)

diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h
index dfbf1d8f03d3..7e58139f1ab6 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt.h
@@ -1397,6 +1397,9 @@ struct bnxt_softc {
 	struct mtx              log_lock; /* logging ops lock */
 	struct callout		time_sync_callout;
 	struct bnxt_bs_trace_info bs_trace[BNXT_CTX_TRACE_BUF_COUNT];
+
+#define MAX_NUM_DMA_INDICATIONS 10
+	struct iflib_dma_info	mgmt_dma_data[MAX_NUM_DMA_INDICATIONS];
 };
 
 struct bnxt_filter_info {
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c
index 0a12bea17ead..edf50ac1432f 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c
@@ -52,7 +52,7 @@ static struct cdevsw bnxt_mgmt_cdevsw = {
 
 /* Global vars */
 static struct cdev *bnxt_mgmt_dev;
-struct mtx		mgmt_lock;
+struct sx	mgmt_lock;
 
 MALLOC_DEFINE(M_BNXT, "bnxt_mgmt_buffer", "buffer for bnxt_mgmt module");
 
@@ -439,11 +439,11 @@ bnxt_mgmt_loader(struct module *m, int what, void *arg)
 			return (error);
 		}
 
-		mtx_init(&mgmt_lock, "BNXT MGMT Lock", NULL, MTX_DEF);
+		sx_init(&mgmt_lock, "BNXT MGMT Lock");
 
 		break;
 	case MOD_UNLOAD:
-		mtx_destroy(&mgmt_lock);
+		sx_destroy(&mgmt_lock);
 		destroy_dev(bnxt_mgmt_dev);
 		break;
 	default:
@@ -526,9 +526,8 @@ bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data,
 	struct bnxt_softc *softc = NULL;
 	struct bnxt_mgmt_req mgmt_req = {};
 	struct bnxt_mgmt_fw_msg msg_temp, *msg, *msg2 = NULL;
-	struct iflib_dma_info dma_data = {};
 	void *user_ptr, *req, *resp;
-	int ret = 0;
+	int ret = 0, num_allocated = 0, i;
 	uint16_t num_ind = 0;
 
 	memcpy(&user_ptr, data, sizeof(user_ptr));
@@ -558,9 +557,10 @@ bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data,
 		return -EINVAL;
 	}
 
-	if (msg_temp.num_dma_indications > 1) {
+	if (msg_temp.num_dma_indications > MAX_NUM_DMA_INDICATIONS) {
 		device_printf(softc->dev, "%s:%d Max num_dma_indications "
-			      "supported is 1\n", __func__, __LINE__);
+			      "supported is %d\n", __func__, __LINE__,
+			      MAX_NUM_DMA_INDICATIONS);
 		return -EINVAL;
 	}
 
@@ -594,43 +594,58 @@ bnxt_mgmt_process_hwrm(struct cdev *dev, u_long cmd, caddr_t data,
 		}
 		msg = msg2;
 
-		ret = iflib_dma_alloc(softc->ctx, msg->dma[0].length, &dma_data,
-				    BUS_DMA_NOWAIT);
-		if (ret) {
-			device_printf(softc->dev, "%s:%d iflib_dma_alloc"
-				      "failed with ret = 0x%x\n", __func__,
-				      __LINE__, ret);
-			ret = -ENOMEM;
-			goto end;
-		}
+		for (i = 0; i < num_ind; i++) {
 
-		if (!(msg->dma[0].read_or_write)) {
-			if (copyin((void *)msg->dma[0].data,
-				   dma_data.idi_vaddr,
-				   msg->dma[0].length)) {
-				device_printf(softc->dev, "%s:%d Failed to copy"
-					      "data from user\n", __func__,
-					      __LINE__);
-				ret = -EFAULT;
+			if (msg->dma[i].length == 0) {
+				device_printf(softc->dev,
+					"%s:%d i:%d Invalid DMA memory length\n",
+					__func__, __LINE__, i);
+				ret = -ENOMEM;
+				goto end;
+			}
+
+			memset(&softc->mgmt_dma_data[i], 0, sizeof(struct iflib_dma_info));
+
+			ret = iflib_dma_alloc(softc->ctx, msg->dma[i].length, &softc->mgmt_dma_data[i],
+				BUS_DMA_WAITOK);
+			if (ret) {
+				device_printf(softc->dev,
+					"%s:%d iflib_dma_alloc failed with ret = 0x%x\n",
+					__func__, __LINE__, ret);
+				ret = -ENOMEM;
 				goto end;
 			}
+
+			num_allocated++;
+			if (!(msg->dma[i].read_or_write)) {
+				if (copyin((void *)msg->dma[i].data,
+				    softc->mgmt_dma_data[i].idi_vaddr,
+				    msg->dma[i].length)) {
+					device_printf(softc->dev,
+						"%s:%d Failed to copy data from user\n",
+						__func__, __LINE__);
+					ret = -EFAULT;
+					goto end;
+				}
+			}
+			dma_ptr = (void *) ((uint64_t) req + msg->dma[i].offset);
+			dmap = dma_ptr;
+			*dmap = htole64(softc->mgmt_dma_data[i].idi_paddr);
 		}
-		dma_ptr = (void *) ((uint64_t) req + msg->dma[0].offset);
-		dmap = dma_ptr;
-		*dmap = htole64(dma_data.idi_paddr);
 	}
 
 	ret = bnxt_hwrm_passthrough(softc, req, msg->len_req, resp, msg->len_resp, msg->timeout);
-	if(ret)
+	if (ret)
 		goto end;
 
-	if (num_ind) {
-		if ((msg->dma[0].read_or_write)) {
-			if (copyout(dma_data.idi_vaddr,
-				    (void *)msg->dma[0].data,
-				    msg->dma[0].length)) {
-				device_printf(softc->dev, "%s:%d Failed to copy data"
-					      "to user\n", __func__, __LINE__);
+	for (i = 0; i < num_ind; i++) {
+		if ((msg->dma[i].read_or_write)) {
+			if (copyout(softc->mgmt_dma_data[i].idi_vaddr,
+			    (void *)msg->dma[i].data,
+			    msg->dma[i].length)) {
+				device_printf(softc->dev,
+					"%s:%d Failed to copy data to user\n",
+					__func__, __LINE__);
 				ret = -EFAULT;
 				goto end;
 			}
@@ -651,8 +666,11 @@ end:
 		free(resp, M_BNXT);
 	if (msg2)
 		free(msg2, M_BNXT);
-	if (dma_data.idi_paddr)
-		iflib_dma_free(&dma_data);
+	if (num_allocated) {
+		for (i = 0; i < num_allocated; i++)
+			if (softc->mgmt_dma_data[i].idi_paddr)
+				iflib_dma_free(&softc->mgmt_dma_data[i]);
+	}
 	return ret;
 }
 
@@ -828,9 +846,9 @@ bnxt_mgmt_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
 		break;
 	case IO_BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM:
 	case IOW_BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM:
-		mtx_lock(&mgmt_lock);
+		sx_xlock(&mgmt_lock);
 		ret = bnxt_mgmt_process_hwrm(dev, cmd, data, flag, td);
-		mtx_unlock(&mgmt_lock);
+		sx_xunlock(&mgmt_lock);
 		break;
 	case IO_BNXT_MGMT_OPCODE_DCB_OPS:
 	case IOW_BNXT_MGMT_OPCODE_DCB_OPS: