intel-wired-lan.osuosl.org archive mirror
 help / color / mirror / Atom feed
* [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf
@ 2025-06-12 21:59 Tatyana Nikolova
  2025-06-12 21:59 ` [Intel-wired-lan] [iwl-next v2 1/6] idpf: use reserved RDMA vectors from control plane Tatyana Nikolova
                   ` (6 more replies)
  0 siblings, 7 replies; 11+ messages in thread
From: Tatyana Nikolova @ 2025-06-12 21:59 UTC (permalink / raw)
  To: intel-wired-lan; +Cc: jgg, leon, linux-rdma, netdev, kuba, Tatyana Nikolova

This idpf patch series is the second part of the staged submission
for introducing RDMA RoCEv2 support for the IPU E2000 line of products,
referred to as GEN3.

To support RDMA GEN3 devices, the idpf driver uses
common definitions of the IIDC interface and implements
specific device functionality in iidc_rdma_idpf.h.

The IPU model can host one or more logical network endpoints called
vPorts per PCI function that are flexibly associated with a physical
port or an internal communication port.

Other features as it pertains to GEN3 devices include:
* MMIO learning
* RDMA capability negotiation
* RDMA vectors discovery between idpf and control plane

These patches are split from the submission
"Add RDMA support for Intel IPU E2000 (GEN3)" [1]
and are based on 6.16-rc1. A shared pull request for net-next and
rdma-next will be sent following review.

Changelog:

v2:
* Minor improvements like variable rename, logging,
remove a redundant variable, etc.
* A couple of cdev_info fixes to properly free it in
error path and not to dereference it before NULL check.

Changes since split (v1) at [4]:
* Replace core dev_ops with exported symbols
* Align with new header split scheme (iidc_rdma.h common header
and iidc_rdma_idpf.h specific header)
* Align with new naming scheme (idc_rdma -> iidc_rdma)
* The idpf patches are submitted separately from the ice and
irdma changes.

At [3]:
* Reduce required minimum RDMA vectors to 2

At [2]:
* RDMA vector number adjustment
* Fix unplugging vport auxiliary device twice
* General cleanup and minor improvements

[1] https://lore.kernel.org/all/20240724233917.704-1-tatyana.e.nikolova@intel.com/
[2] https://lore.kernel.org/all/20240824031924.421-1-tatyana.e.nikolova@intel.com/
[3] https://lore.kernel.org/all/20250207194931.1569-1-tatyana.e.nikolova@intel.com/
[4] https://lore.kernel.org/all/20250523170435.668-1-tatyana.e.nikolova@intel.com/ 

Joshua Hay (6):
  idpf: use reserved RDMA vectors from control plane
  idpf: implement core RDMA auxiliary dev create, init, and destroy
  idpf: implement RDMA vport auxiliary dev create, init, and destroy
  idpf: implement remaining IDC RDMA core callbacks and handlers
  idpf: implement IDC vport aux driver MTU change handler
  idpf: implement get LAN MMIO memory regions

 drivers/net/ethernet/intel/idpf/Makefile      |   1 +
 drivers/net/ethernet/intel/idpf/idpf.h        | 117 ++++-
 .../net/ethernet/intel/idpf/idpf_controlq.c   |  14 +-
 .../net/ethernet/intel/idpf/idpf_controlq.h   |  19 +-
 drivers/net/ethernet/intel/idpf/idpf_dev.c    |  49 +-
 drivers/net/ethernet/intel/idpf/idpf_idc.c    | 497 ++++++++++++++++++
 drivers/net/ethernet/intel/idpf/idpf_lib.c    | 102 +++-
 drivers/net/ethernet/intel/idpf/idpf_main.c   |  32 +-
 drivers/net/ethernet/intel/idpf/idpf_mem.h    |   8 +-
 drivers/net/ethernet/intel/idpf/idpf_txrx.h   |   1 +
 drivers/net/ethernet/intel/idpf/idpf_vf_dev.c |  45 +-
 .../net/ethernet/intel/idpf/idpf_virtchnl.c   | 190 ++++++-
 .../net/ethernet/intel/idpf/idpf_virtchnl.h   |   3 +
 drivers/net/ethernet/intel/idpf/virtchnl2.h   |  42 +-
 include/linux/net/intel/iidc_rdma_idpf.h      |  55 ++
 15 files changed, 1102 insertions(+), 73 deletions(-)
 create mode 100644 drivers/net/ethernet/intel/idpf/idpf_idc.c
 create mode 100644 include/linux/net/intel/iidc_rdma_idpf.h

-- 
2.31.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [Intel-wired-lan] [iwl-next v2 1/6] idpf: use reserved RDMA vectors from control plane
  2025-06-12 21:59 [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
@ 2025-06-12 21:59 ` Tatyana Nikolova
  2025-06-12 21:59 ` [Intel-wired-lan] [iwl-next v2 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy Tatyana Nikolova
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Tatyana Nikolova @ 2025-06-12 21:59 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, Joshua Hay, Tatyana Nikolova

From: Joshua Hay <joshua.a.hay@intel.com>

Fetch the number of reserved RDMA vectors from the control plane.
Adjust the number of reserved LAN vectors if necessary. Adjust the
minimum number of vectors the OS should reserve to include RDMA; and
fail if the OS cannot reserve enough vectors for the minimum number of
LAN and RDMA vectors required. Create a separate msix table for the
reserved RDMA vectors, which will just get handed off to the RDMA core
device to do with what it will.

Reviewed-by: Madhu Chittim <madhu.chittim@intel.com>
Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
---

v2:
- s/v_actual/actual_vecs
- Log requested, available, and minimum vectors in warning msg
- Remove unnecessary newline from rdma_msix_entries kcalloc
- Don't use redundant iterator for msix_entries

 drivers/net/ethernet/intel/idpf/idpf.h      | 28 ++++++-
 drivers/net/ethernet/intel/idpf/idpf_lib.c  | 83 ++++++++++++++++-----
 drivers/net/ethernet/intel/idpf/idpf_txrx.h |  1 +
 drivers/net/ethernet/intel/idpf/virtchnl2.h |  5 +-
 4 files changed, 97 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index 1e812c3f62f9..d9f06764aba0 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -507,10 +507,11 @@ struct idpf_vc_xn_manager;
  * @flags: See enum idpf_flags
  * @reset_reg: See struct idpf_reset_reg
  * @hw: Device access data
- * @num_req_msix: Requested number of MSIX vectors
  * @num_avail_msix: Available number of MSIX vectors
  * @num_msix_entries: Number of entries in MSIX table
  * @msix_entries: MSIX table
+ * @num_rdma_msix_entries: Available number of MSIX vectors for RDMA
+ * @rdma_msix_entries: RDMA MSIX table
  * @req_vec_chunks: Requested vector chunk data
  * @mb_vector: Mailbox vector data
  * @vector_stack: Stack to store the msix vector indexes
@@ -561,10 +562,11 @@ struct idpf_adapter {
 	DECLARE_BITMAP(flags, IDPF_FLAGS_NBITS);
 	struct idpf_reset_reg reset_reg;
 	struct idpf_hw hw;
-	u16 num_req_msix;
 	u16 num_avail_msix;
 	u16 num_msix_entries;
 	struct msix_entry *msix_entries;
+	u16 num_rdma_msix_entries;
+	struct msix_entry *rdma_msix_entries;
 	struct virtchnl2_alloc_vectors *req_vec_chunks;
 	struct idpf_q_vector mb_vector;
 	struct idpf_vector_lifo vector_stack;
@@ -630,6 +632,17 @@ static inline int idpf_is_queue_model_split(u16 q_model)
 bool idpf_is_capability_ena(struct idpf_adapter *adapter, bool all,
 			    enum idpf_cap_field field, u64 flag);
 
+/**
+ * idpf_is_rdma_cap_ena - Determine if RDMA is supported
+ * @adapter: private data struct
+ *
+ * Return: true if RDMA capability is enabled, false otherwise
+ */
+static inline bool idpf_is_rdma_cap_ena(struct idpf_adapter *adapter)
+{
+	return idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_RDMA);
+}
+
 #define IDPF_CAP_RSS (\
 	VIRTCHNL2_CAP_RSS_IPV4_TCP	|\
 	VIRTCHNL2_CAP_RSS_IPV4_TCP	|\
@@ -682,6 +695,17 @@ static inline u16 idpf_get_reserved_vecs(struct idpf_adapter *adapter)
 	return le16_to_cpu(adapter->caps.num_allocated_vectors);
 }
 
+/**
+ * idpf_get_reserved_rdma_vecs - Get reserved RDMA vectors
+ * @adapter: private data struct
+ *
+ * Return: number of vectors reserved for RDMA
+ */
+static inline u16 idpf_get_reserved_rdma_vecs(struct idpf_adapter *adapter)
+{
+	return le16_to_cpu(adapter->caps.num_rdma_allocated_vectors);
+}
+
 /**
  * idpf_get_default_vports - Get default number of vports
  * @adapter: private data struct
diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index 4eb20ec2accb..71d1577ca9e4 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -88,6 +88,8 @@ void idpf_intr_rel(struct idpf_adapter *adapter)
 	idpf_deinit_vector_stack(adapter);
 	kfree(adapter->msix_entries);
 	adapter->msix_entries = NULL;
+	kfree(adapter->rdma_msix_entries);
+	adapter->rdma_msix_entries = NULL;
 }
 
 /**
@@ -299,13 +301,33 @@ int idpf_req_rel_vector_indexes(struct idpf_adapter *adapter,
  */
 int idpf_intr_req(struct idpf_adapter *adapter)
 {
+	u16 num_lan_vecs, min_lan_vecs, num_rdma_vecs = 0, min_rdma_vecs = 0;
 	u16 default_vports = idpf_get_default_vports(adapter);
 	int num_q_vecs, total_vecs, num_vec_ids;
-	int min_vectors, v_actual, err;
+	int min_vectors, actual_vecs, err;
 	unsigned int vector;
 	u16 *vecids;
+	int i;
 
 	total_vecs = idpf_get_reserved_vecs(adapter);
+	num_lan_vecs = total_vecs;
+	if (idpf_is_rdma_cap_ena(adapter)) {
+		num_rdma_vecs = idpf_get_reserved_rdma_vecs(adapter);
+		min_rdma_vecs = IDPF_MIN_RDMA_VEC;
+
+		if (!num_rdma_vecs) {
+			/* If idpf_get_reserved_rdma_vecs is 0, vectors are
+			 * pulled from the LAN pool.
+			 */
+			num_rdma_vecs = min_rdma_vecs;
+		} else if (num_rdma_vecs < min_rdma_vecs) {
+			dev_err(&adapter->pdev->dev,
+				"Not enough vectors reserved for RDMA (min: %u, current: %u)\n",
+				min_rdma_vecs, num_rdma_vecs);
+			return -EINVAL;
+		}
+	}
+
 	num_q_vecs = total_vecs - IDPF_MBX_Q_VEC;
 
 	err = idpf_send_alloc_vectors_msg(adapter, num_q_vecs);
@@ -316,52 +338,76 @@ int idpf_intr_req(struct idpf_adapter *adapter)
 		return -EAGAIN;
 	}
 
-	min_vectors = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC * default_vports;
-	v_actual = pci_alloc_irq_vectors(adapter->pdev, min_vectors,
-					 total_vecs, PCI_IRQ_MSIX);
-	if (v_actual < min_vectors) {
-		dev_err(&adapter->pdev->dev, "Failed to allocate MSIX vectors: %d\n",
-			v_actual);
+	min_lan_vecs = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC * default_vports;
+	min_vectors = min_lan_vecs + min_rdma_vecs;
+	actual_vecs = pci_alloc_irq_vectors(adapter->pdev, min_vectors,
+					    total_vecs, PCI_IRQ_MSIX);
+	if (actual_vecs < min_vectors) {
+		dev_err(&adapter->pdev->dev, "Failed to allocate minimum MSIX vectors required: %d\n",
+			actual_vecs);
 		err = -EAGAIN;
 		goto send_dealloc_vecs;
 	}
 
-	adapter->msix_entries = kcalloc(v_actual, sizeof(struct msix_entry),
-					GFP_KERNEL);
+	if (idpf_is_rdma_cap_ena(adapter)) {
+		if (actual_vecs < total_vecs) {
+			dev_warn(&adapter->pdev->dev,
+				 "Warning: %d vectors requested, only %d available. Defaulting to minimum (%d) for RDMA and remaining for LAN.\n",
+				 total_vecs, actual_vecs, IDPF_MIN_RDMA_VEC);
+			num_rdma_vecs = IDPF_MIN_RDMA_VEC;
+		}
 
+		adapter->rdma_msix_entries = kcalloc(num_rdma_vecs,
+						     sizeof(struct msix_entry),
+						     GFP_KERNEL);
+		if (!adapter->rdma_msix_entries) {
+			err = -ENOMEM;
+			goto free_irq;
+		}
+	}
+
+	num_lan_vecs = actual_vecs - num_rdma_vecs;
+	adapter->msix_entries = kcalloc(num_lan_vecs, sizeof(struct msix_entry),
+					GFP_KERNEL);
 	if (!adapter->msix_entries) {
 		err = -ENOMEM;
-		goto free_irq;
+		goto free_rdma_msix;
 	}
 
 	adapter->mb_vector.v_idx = le16_to_cpu(adapter->caps.mailbox_vector_id);
 
-	vecids = kcalloc(total_vecs, sizeof(u16), GFP_KERNEL);
+	vecids = kcalloc(actual_vecs, sizeof(u16), GFP_KERNEL);
 	if (!vecids) {
 		err = -ENOMEM;
 		goto free_msix;
 	}
 
-	num_vec_ids = idpf_get_vec_ids(adapter, vecids, total_vecs,
+	num_vec_ids = idpf_get_vec_ids(adapter, vecids, actual_vecs,
 				       &adapter->req_vec_chunks->vchunks);
-	if (num_vec_ids < v_actual) {
+	if (num_vec_ids < actual_vecs) {
 		err = -EINVAL;
 		goto free_vecids;
 	}
 
-	for (vector = 0; vector < v_actual; vector++) {
+	for (vector = 0; vector < num_lan_vecs; vector++) {
 		adapter->msix_entries[vector].entry = vecids[vector];
 		adapter->msix_entries[vector].vector =
 			pci_irq_vector(adapter->pdev, vector);
 	}
+	for (i = 0; i < num_rdma_vecs; vector++, i++) {
+		adapter->rdma_msix_entries[i].entry = vecids[vector];
+		adapter->rdma_msix_entries[i].vector =
+			pci_irq_vector(adapter->pdev, vector);
+	}
 
-	adapter->num_req_msix = total_vecs;
-	adapter->num_msix_entries = v_actual;
 	/* 'num_avail_msix' is used to distribute excess vectors to the vports
 	 * after considering the minimum vectors required per each default
 	 * vport
 	 */
-	adapter->num_avail_msix = v_actual - min_vectors;
+	adapter->num_avail_msix = num_lan_vecs - min_lan_vecs;
+	adapter->num_msix_entries = num_lan_vecs;
+	if (idpf_is_rdma_cap_ena(adapter))
+		adapter->num_rdma_msix_entries = num_rdma_vecs;
 
 	/* Fill MSIX vector lifo stack with vector indexes */
 	err = idpf_init_vector_stack(adapter);
@@ -383,6 +429,9 @@ int idpf_intr_req(struct idpf_adapter *adapter)
 free_msix:
 	kfree(adapter->msix_entries);
 	adapter->msix_entries = NULL;
+free_rdma_msix:
+	kfree(adapter->rdma_msix_entries);
+	adapter->rdma_msix_entries = NULL;
 free_irq:
 	pci_free_irq_vectors(adapter->pdev);
 send_dealloc_vecs:
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
index 36a0f828a6f8..281de655a813 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
@@ -57,6 +57,7 @@
 /* Default vector sharing */
 #define IDPF_MBX_Q_VEC		1
 #define IDPF_MIN_Q_VEC		1
+#define IDPF_MIN_RDMA_VEC	2
 
 #define IDPF_DFLT_TX_Q_DESC_COUNT		512
 #define IDPF_DFLT_TX_COMPLQ_DESC_COUNT		512
diff --git a/drivers/net/ethernet/intel/idpf/virtchnl2.h b/drivers/net/ethernet/intel/idpf/virtchnl2.h
index 11b8f6f05799..a2881979c7f8 100644
--- a/drivers/net/ethernet/intel/idpf/virtchnl2.h
+++ b/drivers/net/ethernet/intel/idpf/virtchnl2.h
@@ -483,6 +483,8 @@ VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_version_info);
  *			segment offload.
  * @max_hdr_buf_per_lso: Max number of header buffers that can be used for
  *			 an LSO.
+ * @num_rdma_allocated_vectors: Maximum number of allocated RDMA vectors for
+ *				the device.
  * @pad1: Padding for future extensions.
  *
  * Dataplane driver sends this message to CP to negotiate capabilities and
@@ -530,7 +532,8 @@ struct virtchnl2_get_capabilities {
 	__le32 device_type;
 	u8 min_sso_packet_len;
 	u8 max_hdr_buf_per_lso;
-	u8 pad1[10];
+	__le16 num_rdma_allocated_vectors;
+	u8 pad1[8];
 };
 VIRTCHNL2_CHECK_STRUCT_LEN(80, virtchnl2_get_capabilities);
 
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Intel-wired-lan] [iwl-next v2 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy
  2025-06-12 21:59 [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
  2025-06-12 21:59 ` [Intel-wired-lan] [iwl-next v2 1/6] idpf: use reserved RDMA vectors from control plane Tatyana Nikolova
@ 2025-06-12 21:59 ` Tatyana Nikolova
  2025-08-06 12:02   ` Larysa Zaremba
  2025-06-12 21:59 ` [Intel-wired-lan] [iwl-next v2 3/6] idpf: implement RDMA vport " Tatyana Nikolova
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 11+ messages in thread
From: Tatyana Nikolova @ 2025-06-12 21:59 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, Joshua Hay, Tatyana Nikolova

From: Joshua Hay <joshua.a.hay@intel.com>

Add the initial idpf_idc.c file with the functions to kick off the IDC
initialization, create and initialize a core RDMA auxiliary device, and
destroy said device.

The RDMA core has a dependency on the vports being created by the
control plane before it can be initialized. Therefore, once all the
vports are up after a hard reset (either during driver load a function
level reset), the core RDMA device info will be created. It is populated
with the function type (as distinguished by the IDC initialization
function pointer), the core idc_ops function points (just stubs for
now), the reserved RDMA MSIX table, and various other info the core RDMA
auxiliary driver will need. It is then plugged on to the bus.

During a function level reset or driver unload, the device will be
unplugged from the bus and destroyed.

Reviewed-by: Madhu Chittim <madhu.chittim@intel.com>
Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
---

v2:
- initialize cdev_info earlier to properly free it in error path

Changes since split (v1):
- replace core dev_ops with exported symbols
- align with new header split scheme (idc_rdma->iidc_rdma and
  iidc_rdma_idpf specific header)

[3]:
- use signed ret value from ida_alloc and only assign
  unsigned id if no err
- capitalize some abbreviations
- add missing field descriptions

 drivers/net/ethernet/intel/idpf/Makefile      |   1 +
 drivers/net/ethernet/intel/idpf/idpf.h        |  11 +
 drivers/net/ethernet/intel/idpf/idpf_dev.c    |  13 +
 drivers/net/ethernet/intel/idpf/idpf_idc.c    | 223 ++++++++++++++++++
 drivers/net/ethernet/intel/idpf/idpf_lib.c    |   4 +
 drivers/net/ethernet/intel/idpf/idpf_vf_dev.c |  13 +
 .../net/ethernet/intel/idpf/idpf_virtchnl.c   |  20 ++
 .../net/ethernet/intel/idpf/idpf_virtchnl.h   |   3 +
 include/linux/net/intel/iidc_rdma_idpf.h      |  28 +++
 9 files changed, 316 insertions(+)
 create mode 100644 drivers/net/ethernet/intel/idpf/idpf_idc.c
 create mode 100644 include/linux/net/intel/iidc_rdma_idpf.h

diff --git a/drivers/net/ethernet/intel/idpf/Makefile b/drivers/net/ethernet/intel/idpf/Makefile
index 83ac5e296382..4ef4b2b5e37a 100644
--- a/drivers/net/ethernet/intel/idpf/Makefile
+++ b/drivers/net/ethernet/intel/idpf/Makefile
@@ -10,6 +10,7 @@ idpf-y := \
 	idpf_controlq_setup.o	\
 	idpf_dev.o		\
 	idpf_ethtool.o		\
+	idpf_idc.o		\
 	idpf_lib.o		\
 	idpf_main.o		\
 	idpf_txrx.o		\
diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index d9f06764aba0..6b1cc55e34a3 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -17,6 +17,8 @@ struct idpf_vport_max_q;
 #include <linux/sctp.h>
 #include <linux/ethtool_netlink.h>
 #include <net/gro.h>
+#include <linux/net/intel/iidc_rdma.h>
+#include <linux/net/intel/iidc_rdma_idpf.h>
 
 #include "virtchnl2.h"
 #include "idpf_txrx.h"
@@ -206,9 +208,12 @@ struct idpf_reg_ops {
 /**
  * struct idpf_dev_ops - Device specific operations
  * @reg_ops: Register operations
+ * @idc_init: IDC initialization
  */
 struct idpf_dev_ops {
 	struct idpf_reg_ops reg_ops;
+
+	int (*idc_init)(struct idpf_adapter *adapter);
 };
 
 /**
@@ -540,6 +545,7 @@ struct idpf_vc_xn_manager;
  * @caps: Negotiated capabilities with device
  * @vcxn_mngr: Virtchnl transaction manager
  * @dev_ops: See idpf_dev_ops
+ * @cdev_info: IDC core device info pointer
  * @num_vfs: Number of allocated VFs through sysfs. PF does not directly talk
  *	     to VFs but is used to initialize them
  * @crc_enable: Enable CRC insertion offload
@@ -599,6 +605,7 @@ struct idpf_adapter {
 	struct idpf_vc_xn_manager *vcxn_mngr;
 
 	struct idpf_dev_ops dev_ops;
+	struct iidc_rdma_core_dev_info *cdev_info;
 	int num_vfs;
 	bool crc_enable;
 	bool req_tx_splitq;
@@ -877,5 +884,9 @@ int idpf_sriov_configure(struct pci_dev *pdev, int num_vfs);
 
 u8 idpf_vport_get_hsplit(const struct idpf_vport *vport);
 bool idpf_vport_set_hsplit(const struct idpf_vport *vport, u8 val);
+int idpf_idc_init(struct idpf_adapter *adapter);
+int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
+			       enum iidc_function_type ftype);
+void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info);
 
 #endif /* !_IDPF_H_ */
diff --git a/drivers/net/ethernet/intel/idpf/idpf_dev.c b/drivers/net/ethernet/intel/idpf/idpf_dev.c
index 3fae81f1f988..dd227a4368fb 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_dev.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_dev.c
@@ -161,6 +161,17 @@ static void idpf_ptp_reg_init(const struct idpf_adapter *adapter)
 	adapter->ptp->cmd.exec_cmd_mask = PF_GLTSYN_CMD_SYNC_EXEC_CMD_M;
 }
 
+/**
+ * idpf_idc_register - register for IDC callbacks
+ * @adapter: Driver specific private structure
+ *
+ * Return: 0 on success or error code on failure.
+ */
+static int idpf_idc_register(struct idpf_adapter *adapter)
+{
+	return idpf_idc_init_aux_core_dev(adapter, IIDC_FUNCTION_TYPE_PF);
+}
+
 /**
  * idpf_reg_ops_init - Initialize register API function pointers
  * @adapter: Driver specific private structure
@@ -182,4 +193,6 @@ static void idpf_reg_ops_init(struct idpf_adapter *adapter)
 void idpf_dev_ops_init(struct idpf_adapter *adapter)
 {
 	idpf_reg_ops_init(adapter);
+
+	adapter->dev_ops.idc_init = idpf_idc_register;
 }
diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c b/drivers/net/ethernet/intel/idpf/idpf_idc.c
new file mode 100644
index 000000000000..5550802a3a7d
--- /dev/null
+++ b/drivers/net/ethernet/intel/idpf/idpf_idc.c
@@ -0,0 +1,223 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2025 Intel Corporation */
+
+#include "idpf.h"
+#include "idpf_virtchnl.h"
+
+static DEFINE_IDA(idpf_idc_ida);
+
+#define IDPF_IDC_MAX_ADEV_NAME_LEN	15
+
+/**
+ * idpf_idc_init - Called to initialize IDC
+ * @adapter: driver private data structure
+ *
+ * Return: 0 on success or cap not enabled, error code on failure.
+ */
+int idpf_idc_init(struct idpf_adapter *adapter)
+{
+	int err;
+
+	if (!idpf_is_rdma_cap_ena(adapter) ||
+	    !adapter->dev_ops.idc_init)
+		return 0;
+
+	err = adapter->dev_ops.idc_init(adapter);
+	if (err)
+		dev_err(&adapter->pdev->dev, "failed to initialize idc: %d\n",
+			err);
+
+	return err;
+}
+
+/**
+ * idpf_core_adev_release - function to be mapped to aux dev's release op
+ * @dev: pointer to device to free
+ */
+static void idpf_core_adev_release(struct device *dev)
+{
+	struct iidc_rdma_core_auxiliary_dev *iadev;
+
+	iadev = container_of(dev, struct iidc_rdma_core_auxiliary_dev, adev.dev);
+	kfree(iadev);
+	iadev = NULL;
+}
+
+/* idpf_plug_core_aux_dev - allocate and register an Auxiliary device
+ * @cdev_info: IDC core device info pointer
+ *
+ * Return: 0 on success or error code on failure.
+ */
+static int idpf_plug_core_aux_dev(struct iidc_rdma_core_dev_info *cdev_info)
+{
+	struct iidc_rdma_core_auxiliary_dev *iadev;
+	char name[IDPF_IDC_MAX_ADEV_NAME_LEN];
+	struct auxiliary_device *adev;
+	int ret;
+
+	iadev = kzalloc(sizeof(*iadev), GFP_KERNEL);
+	if (!iadev)
+		return -ENOMEM;
+
+	adev = &iadev->adev;
+	cdev_info->adev = adev;
+	iadev->cdev_info = cdev_info;
+
+	ret = ida_alloc(&idpf_idc_ida, GFP_KERNEL);
+	if (ret < 0) {
+		pr_err("failed to allocate unique device ID for Auxiliary driver\n");
+		goto err_ida_alloc;
+	}
+	adev->id = ret;
+	adev->dev.release = idpf_core_adev_release;
+	adev->dev.parent = &cdev_info->pdev->dev;
+	sprintf(name, "%04x.rdma.core", cdev_info->pdev->vendor);
+	adev->name = name;
+
+	ret = auxiliary_device_init(adev);
+	if (ret)
+		goto err_aux_dev_init;
+
+	ret = auxiliary_device_add(adev);
+	if (ret)
+		goto err_aux_dev_add;
+
+	return 0;
+
+err_aux_dev_add:
+	cdev_info->adev = NULL;
+	auxiliary_device_uninit(adev);
+err_aux_dev_init:
+	ida_free(&idpf_idc_ida, adev->id);
+err_ida_alloc:
+	kfree(iadev);
+
+	return ret;
+}
+
+/* idpf_unplug_aux_dev - unregister and free an Auxiliary device
+ * @adev: auxiliary device struct
+ */
+static void idpf_unplug_aux_dev(struct auxiliary_device *adev)
+{
+	auxiliary_device_delete(adev);
+	auxiliary_device_uninit(adev);
+
+	ida_free(&idpf_idc_ida, adev->id);
+}
+
+/**
+ * idpf_idc_vport_dev_ctrl - Called by an Auxiliary Driver
+ * @cdev_info: IDC core device info pointer
+ * @up: RDMA core driver status
+ *
+ * This callback function is accessed by an Auxiliary Driver to indicate
+ * whether core driver is ready to support vport driver load or if vport
+ * drivers need to be taken down.
+ *
+ * Return: 0 on success or error code on failure.
+ */
+int idpf_idc_vport_dev_ctrl(struct iidc_rdma_core_dev_info *cdev_info, bool up)
+{
+	return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(idpf_idc_vport_dev_ctrl);
+
+/**
+ * idpf_idc_request_reset - Called by an Auxiliary Driver
+ * @cdev_info: IDC core device info pointer
+ * @reset_type: function, core or other
+ *
+ * This callback function is accessed by an Auxiliary Driver to request a reset
+ * on the Auxiliary Device.
+ *
+ * Return: 0 on success or error code on failure.
+ */
+int idpf_idc_request_reset(struct iidc_rdma_core_dev_info *cdev_info,
+			   enum iidc_rdma_reset_type __always_unused reset_type)
+{
+	return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(idpf_idc_request_reset);
+
+/**
+ * idpf_idc_init_msix_data - initialize MSIX data for the cdev_info structure
+ * @adapter: driver private data structure
+ */
+static void
+idpf_idc_init_msix_data(struct idpf_adapter *adapter)
+{
+	struct iidc_rdma_core_dev_info *cdev_info;
+	struct iidc_rdma_priv_dev_info *privd;
+
+	if (!adapter->rdma_msix_entries)
+		return;
+
+	cdev_info = adapter->cdev_info;
+	privd = cdev_info->iidc_priv;
+
+	privd->msix_entries = adapter->rdma_msix_entries;
+	privd->msix_count = adapter->num_rdma_msix_entries;
+}
+
+/**
+ * idpf_idc_init_aux_core_dev - initialize Auxiliary Device(s)
+ * @adapter: driver private data structure
+ * @ftype: PF or VF
+ *
+ * Return: 0 on success or error code on failure.
+ */
+int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
+			       enum iidc_function_type ftype)
+{
+	struct iidc_rdma_core_dev_info *cdev_info;
+	struct iidc_rdma_priv_dev_info *privd;
+	int err;
+
+	adapter->cdev_info = kzalloc(sizeof(*cdev_info), GFP_KERNEL);
+	if (!adapter->cdev_info)
+		return -ENOMEM;
+	cdev_info = adapter->cdev_info;
+
+	privd = kzalloc(sizeof(*privd), GFP_KERNEL);
+	if (!privd) {
+		err = -ENOMEM;
+		goto err_privd_alloc;
+	}
+
+	cdev_info->iidc_priv = privd;
+	cdev_info->pdev = adapter->pdev;
+	cdev_info->rdma_protocol = IIDC_RDMA_PROTOCOL_ROCEV2;
+	privd->ftype = ftype;
+
+	idpf_idc_init_msix_data(adapter);
+
+	err = idpf_plug_core_aux_dev(cdev_info);
+	if (err)
+		goto err_plug_aux_dev;
+
+	return 0;
+
+err_plug_aux_dev:
+	kfree(privd);
+err_privd_alloc:
+	kfree(cdev_info);
+	adapter->cdev_info = NULL;
+
+	return err;
+}
+
+/**
+ * idpf_idc_deinit_core_aux_device - de-initialize Auxiliary Device(s)
+ * @cdev_info: IDC core device info pointer
+ */
+void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info)
+{
+	if (!cdev_info)
+		return;
+
+	idpf_unplug_aux_dev(cdev_info->adev);
+
+	kfree(cdev_info->iidc_priv);
+	kfree(cdev_info);
+}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index 71d1577ca9e4..2c9fda5783f8 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1834,6 +1834,10 @@ static int idpf_init_hard_reset(struct idpf_adapter *adapter)
 unlock_mutex:
 	mutex_unlock(&adapter->vport_ctrl_lock);
 
+	/* Wait until all vports are created to init RDMA CORE AUX */
+	if (!err)
+		err = idpf_idc_init(adapter);
+
 	return err;
 }
 
diff --git a/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c b/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
index aba828abcb17..2f84bd596ae4 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
@@ -147,6 +147,17 @@ static void idpf_vf_trigger_reset(struct idpf_adapter *adapter,
 		idpf_send_mb_msg(adapter, VIRTCHNL2_OP_RESET_VF, 0, NULL, 0);
 }
 
+/**
+ * idpf_idc_vf_register - register for IDC callbacks
+ * @adapter: Driver specific private structure
+ *
+ * Return: 0 on success or error code on failure.
+ */
+static int idpf_idc_vf_register(struct idpf_adapter *adapter)
+{
+	return idpf_idc_init_aux_core_dev(adapter, IIDC_FUNCTION_TYPE_VF);
+}
+
 /**
  * idpf_vf_reg_ops_init - Initialize register API function pointers
  * @adapter: Driver specific private structure
@@ -167,4 +178,6 @@ static void idpf_vf_reg_ops_init(struct idpf_adapter *adapter)
 void idpf_vf_dev_ops_init(struct idpf_adapter *adapter)
 {
 	idpf_vf_reg_ops_init(adapter);
+
+	adapter->dev_ops.idc_init = idpf_idc_vf_register;
 }
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
index 24febaaa8fbb..c6fa4644fd3c 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -868,6 +868,7 @@ static int idpf_send_get_caps_msg(struct idpf_adapter *adapter)
 
 	caps.other_caps =
 		cpu_to_le64(VIRTCHNL2_CAP_SRIOV			|
+			    VIRTCHNL2_CAP_RDMA                  |
 			    VIRTCHNL2_CAP_MACFILTER		|
 			    VIRTCHNL2_CAP_SPLITQ_QSCHED		|
 			    VIRTCHNL2_CAP_PROMISC		|
@@ -3070,6 +3071,7 @@ void idpf_vc_core_deinit(struct idpf_adapter *adapter)
 
 	idpf_ptp_release(adapter);
 	idpf_deinit_task(adapter);
+	idpf_idc_deinit_core_aux_device(adapter->cdev_info);
 	idpf_intr_rel(adapter);
 
 	if (remove_in_prog)
@@ -3728,3 +3730,21 @@ int idpf_set_promiscuous(struct idpf_adapter *adapter,
 
 	return reply_sz < 0 ? reply_sz : 0;
 }
+
+/**
+ * idpf_idc_rdma_vc_send_sync - virtchnl send callback for IDC registered drivers
+ * @cdev_info: IDC core device info pointer
+ * @send_msg: message to send
+ * @msg_size: size of message to send
+ * @recv_msg: message to populate on reception of response
+ * @recv_len: length of message copied into recv_msg or 0 on error
+ *
+ * Return: 0 on success or error code on failure.
+ */
+int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info *cdev_info,
+			       u8 *send_msg, u16 msg_size,
+			       u8 *recv_msg, u16 *recv_len)
+{
+	return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL_GPL(idpf_idc_rdma_vc_send_sync);
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
index 77578206bada..7bae09483aed 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
@@ -151,5 +151,8 @@ int idpf_send_set_sriov_vfs_msg(struct idpf_adapter *adapter, u16 num_vfs);
 int idpf_send_get_set_rss_key_msg(struct idpf_vport *vport, bool get);
 int idpf_send_get_set_rss_lut_msg(struct idpf_vport *vport, bool get);
 void idpf_vc_xn_shutdown(struct idpf_vc_xn_manager *vcxn_mngr);
+int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info *cdev_info,
+			       u8 *send_msg, u16 msg_size,
+			       u8 *recv_msg, u16 *recv_len);
 
 #endif /* _IDPF_VIRTCHNL_H_ */
diff --git a/include/linux/net/intel/iidc_rdma_idpf.h b/include/linux/net/intel/iidc_rdma_idpf.h
new file mode 100644
index 000000000000..f2fe1844f660
--- /dev/null
+++ b/include/linux/net/intel/iidc_rdma_idpf.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2025 Intel Corporation. */
+
+#ifndef _IIDC_RDMA_IDPF_H_
+#define _IIDC_RDMA_IDPF_H_
+
+#include <linux/auxiliary_bus.h>
+
+/* struct to be populated by core LAN PCI driver */
+enum iidc_function_type {
+	IIDC_FUNCTION_TYPE_PF,
+	IIDC_FUNCTION_TYPE_VF,
+};
+
+struct iidc_rdma_priv_dev_info {
+	struct msix_entry *msix_entries;
+	u16 msix_count; /* How many vectors are reserved for this device */
+	enum iidc_function_type ftype;
+};
+
+int idpf_idc_vport_dev_ctrl(struct iidc_rdma_core_dev_info *cdev_info, bool up);
+int idpf_idc_request_reset(struct iidc_rdma_core_dev_info *cdev_info,
+			   enum iidc_rdma_reset_type __always_unused reset_type);
+int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info *cdev_info,
+			       u8 *send_msg, u16 msg_size,
+			       u8 *recv_msg, u16 *recv_len);
+
+#endif /* _IIDC_RDMA_IDPF_H_ */
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Intel-wired-lan] [iwl-next v2 3/6] idpf: implement RDMA vport auxiliary dev create, init, and destroy
  2025-06-12 21:59 [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
  2025-06-12 21:59 ` [Intel-wired-lan] [iwl-next v2 1/6] idpf: use reserved RDMA vectors from control plane Tatyana Nikolova
  2025-06-12 21:59 ` [Intel-wired-lan] [iwl-next v2 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy Tatyana Nikolova
@ 2025-06-12 21:59 ` Tatyana Nikolova
  2025-06-12 22:00 ` [Intel-wired-lan] [iwl-next v2 4/6] idpf: implement remaining IDC RDMA core callbacks and handlers Tatyana Nikolova
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Tatyana Nikolova @ 2025-06-12 21:59 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, Joshua Hay, Tatyana Nikolova

From: Joshua Hay <joshua.a.hay@intel.com>

Implement the functions to create, initialize, and destroy an RDMA vport
auxiliary device. The vport aux dev creation is dependent on the
core aux device to call idpf_idc_vport_dev_ctrl to signal that it is
ready for vport aux devices. Implement that core callback to either
create and initialize the vport aux dev or deinitialize.

RDMA vport aux dev creation is also dependent on the control plane to
tell us the vport is RDMA enabled. Add a flag in the create vport
message to signal individual vport RDMA capabilities.

Reviewed-by: Madhu Chittim <madhu.chittim@intel.com>
Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
---

Changes since split:
- align with new header naming and split
- use signed ret value from ida_alloc and only assign
  unsigned id if no err
- capitalize some abbreviations
- add missing field descriptions
- remove unnecessary casts

[2]:
- Guard against unplugging vport aux dev twice. This is possible if
irdma is unloaded and then idpf is unloaded. irdma calls
idpf_idc_vport_dev_down during its unload which calls unplug. Set the
adev to NULL in dev_down, so that the following call to
deinit_vport_aux_device during idpf unload will return early from
unplug.

 drivers/net/ethernet/intel/idpf/idpf.h      |   4 +
 drivers/net/ethernet/intel/idpf/idpf_idc.c  | 178 +++++++++++++++++++-
 drivers/net/ethernet/intel/idpf/idpf_lib.c  |   2 +
 drivers/net/ethernet/intel/idpf/virtchnl2.h |   3 +
 include/linux/net/intel/iidc_rdma_idpf.h    |  19 +++
 5 files changed, 205 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index 6b1cc55e34a3..52a3ec88e615 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -280,6 +280,7 @@ struct idpf_port_stats {
  *	      group will yield total number of RX queues.
  * @rxq_model: Splitq queue or single queue queuing model
  * @rx_ptype_lkup: Lookup table for ptypes on RX
+ * @vdev_info: IDC vport device info pointer
  * @adapter: back pointer to associated adapter
  * @netdev: Associated net_device. Each vport should have one and only one
  *	    associated netdev.
@@ -325,6 +326,8 @@ struct idpf_vport {
 	u32 rxq_model;
 	struct libeth_rx_pt *rx_ptype_lkup;
 
+	struct iidc_rdma_vport_dev_info *vdev_info;
+
 	struct idpf_adapter *adapter;
 	struct net_device *netdev;
 	DECLARE_BITMAP(flags, IDPF_VPORT_FLAGS_NBITS);
@@ -888,5 +891,6 @@ int idpf_idc_init(struct idpf_adapter *adapter);
 int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
 			       enum iidc_function_type ftype);
 void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info);
+void idpf_idc_deinit_vport_aux_device(struct iidc_rdma_vport_dev_info *vdev_info);
 
 #endif /* !_IDPF_H_ */
diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c b/drivers/net/ethernet/intel/idpf/idpf_idc.c
index 5550802a3a7d..dfdf4fa287ab 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_idc.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_idc.c
@@ -30,6 +30,113 @@ int idpf_idc_init(struct idpf_adapter *adapter)
 	return err;
 }
 
+/**
+ * idpf_vport_adev_release - function to be mapped to aux dev's release op
+ * @dev: pointer to device to free
+ */
+static void idpf_vport_adev_release(struct device *dev)
+{
+	struct iidc_rdma_vport_auxiliary_dev *iadev;
+
+	iadev = container_of(dev, struct iidc_rdma_vport_auxiliary_dev, adev.dev);
+	kfree(iadev);
+	iadev = NULL;
+}
+
+/* idpf_plug_vport_aux_dev - allocate and register a vport Auxiliary device
+ * @cdev_info: IDC core device info pointer
+ * @vdev_info: IDC vport device info pointer
+ *
+ * Return: 0 on success or error code on failure.
+ */
+static int idpf_plug_vport_aux_dev(struct iidc_rdma_core_dev_info *cdev_info,
+				   struct iidc_rdma_vport_dev_info *vdev_info)
+{
+	struct iidc_rdma_vport_auxiliary_dev *iadev;
+	char name[IDPF_IDC_MAX_ADEV_NAME_LEN];
+	struct auxiliary_device *adev;
+	int ret;
+
+	iadev = kzalloc(sizeof(*iadev), GFP_KERNEL);
+	if (!iadev)
+		return -ENOMEM;
+
+	adev = &iadev->adev;
+	vdev_info->adev = &iadev->adev;
+	iadev->vdev_info = vdev_info;
+
+	ret = ida_alloc(&idpf_idc_ida, GFP_KERNEL);
+	if (ret < 0) {
+		pr_err("failed to allocate unique device ID for Auxiliary driver\n");
+		goto err_ida_alloc;
+	}
+	adev->id = ret;
+	adev->dev.release = idpf_vport_adev_release;
+	adev->dev.parent = &cdev_info->pdev->dev;
+	sprintf(name, "%04x.rdma.vdev", cdev_info->pdev->vendor);
+	adev->name = name;
+
+	ret = auxiliary_device_init(adev);
+	if (ret)
+		goto err_aux_dev_init;
+
+	ret = auxiliary_device_add(adev);
+	if (ret)
+		goto err_aux_dev_add;
+
+	return 0;
+
+err_aux_dev_add:
+	vdev_info->adev = NULL;
+	auxiliary_device_uninit(adev);
+err_aux_dev_init:
+	ida_free(&idpf_idc_ida, adev->id);
+err_ida_alloc:
+	kfree(iadev);
+
+	return ret;
+}
+
+/**
+ * idpf_idc_init_aux_vport_dev - initialize vport Auxiliary Device(s)
+ * @vport: virtual port data struct
+ *
+ * Return: 0 on success or error code on failure.
+ */
+static int idpf_idc_init_aux_vport_dev(struct idpf_vport *vport)
+{
+	struct idpf_adapter *adapter = vport->adapter;
+	struct iidc_rdma_vport_dev_info *vdev_info;
+	struct iidc_rdma_core_dev_info *cdev_info;
+	struct virtchnl2_create_vport *vport_msg;
+	int err;
+
+	vport_msg = (struct virtchnl2_create_vport *)
+				adapter->vport_params_recvd[vport->idx];
+
+	if (!(le16_to_cpu(vport_msg->vport_flags) & VIRTCHNL2_VPORT_ENABLE_RDMA))
+		return 0;
+
+	vport->vdev_info = kzalloc(sizeof(*vdev_info), GFP_KERNEL);
+	if (!vport->vdev_info)
+		return -ENOMEM;
+
+	cdev_info = vport->adapter->cdev_info;
+
+	vdev_info = vport->vdev_info;
+	vdev_info->vport_id = vport->vport_id;
+	vdev_info->netdev = vport->netdev;
+	vdev_info->core_adev = cdev_info->adev;
+
+	err = idpf_plug_vport_aux_dev(cdev_info, vdev_info);
+	if (err) {
+		kfree(vdev_info);
+		return err;
+	}
+
+	return 0;
+}
+
 /**
  * idpf_core_adev_release - function to be mapped to aux dev's release op
  * @dev: pointer to device to free
@@ -100,12 +207,60 @@ static int idpf_plug_core_aux_dev(struct iidc_rdma_core_dev_info *cdev_info)
  */
 static void idpf_unplug_aux_dev(struct auxiliary_device *adev)
 {
+	if (!adev)
+		return;
+
 	auxiliary_device_delete(adev);
 	auxiliary_device_uninit(adev);
 
 	ida_free(&idpf_idc_ida, adev->id);
 }
 
+/**
+ * idpf_idc_vport_dev_up - called when CORE is ready for vport aux devs
+ * @adapter: private data struct
+ *
+ * Return: 0 on success or error code on failure.
+ */
+static int idpf_idc_vport_dev_up(struct idpf_adapter *adapter)
+{
+	int i, err = 0;
+
+	for (i = 0; i < adapter->num_alloc_vports; i++) {
+		struct idpf_vport *vport = adapter->vports[i];
+
+		if (!vport)
+			continue;
+
+		if (!vport->vdev_info)
+			err = idpf_idc_init_aux_vport_dev(vport);
+		else
+			err = idpf_plug_vport_aux_dev(vport->adapter->cdev_info,
+						      vport->vdev_info);
+	}
+
+	return err;
+}
+
+/**
+ * idpf_idc_vport_dev_down - called CORE is leaving vport aux dev support state
+ * @adapter: private data struct
+ */
+static void idpf_idc_vport_dev_down(struct idpf_adapter *adapter)
+{
+	int i;
+
+	for (i = 0; i < adapter->num_alloc_vports; i++) {
+		struct idpf_vport *vport = adapter->vports[i];
+
+		if (!vport)
+			continue;
+
+		idpf_unplug_aux_dev(vport->vdev_info->adev);
+		vport->vdev_info->adev = NULL;
+	}
+}
+
 /**
  * idpf_idc_vport_dev_ctrl - Called by an Auxiliary Driver
  * @cdev_info: IDC core device info pointer
@@ -119,7 +274,14 @@ static void idpf_unplug_aux_dev(struct auxiliary_device *adev)
  */
 int idpf_idc_vport_dev_ctrl(struct iidc_rdma_core_dev_info *cdev_info, bool up)
 {
-	return -EOPNOTSUPP;
+	struct idpf_adapter *adapter = pci_get_drvdata(cdev_info->pdev);
+
+	if (up)
+		return idpf_idc_vport_dev_up(adapter);
+
+	idpf_idc_vport_dev_down(adapter);
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(idpf_idc_vport_dev_ctrl);
 
@@ -221,3 +383,17 @@ void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info)
 	kfree(cdev_info->iidc_priv);
 	kfree(cdev_info);
 }
+
+/**
+ * idpf_idc_deinit_vport_aux_device - de-initialize Auxiliary Device(s)
+ * @vdev_info: IDC vport device info pointer
+ */
+void idpf_idc_deinit_vport_aux_device(struct iidc_rdma_vport_dev_info *vdev_info)
+{
+	if (!vdev_info)
+		return;
+
+	idpf_unplug_aux_dev(vdev_info->adev);
+
+	kfree(vdev_info);
+}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index 2c9fda5783f8..b0efd763a7e0 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1021,6 +1021,8 @@ static void idpf_vport_dealloc(struct idpf_vport *vport)
 	struct idpf_adapter *adapter = vport->adapter;
 	unsigned int i = vport->idx;
 
+	idpf_idc_deinit_vport_aux_device(vport->vdev_info);
+
 	idpf_deinit_mac_addr(vport);
 	idpf_vport_stop(vport);
 
diff --git a/drivers/net/ethernet/intel/idpf/virtchnl2.h b/drivers/net/ethernet/intel/idpf/virtchnl2.h
index a2881979c7f8..82a3c307307e 100644
--- a/drivers/net/ethernet/intel/idpf/virtchnl2.h
+++ b/drivers/net/ethernet/intel/idpf/virtchnl2.h
@@ -575,9 +575,12 @@ VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_queue_reg_chunks);
 /**
  * enum virtchnl2_vport_flags - Vport flags that indicate vport capabilities.
  * @VIRTCHNL2_VPORT_UPLINK_PORT: Representatives of underlying physical ports
+ * @VIRTCHNL2_VPORT_ENABLE_RDMA: RDMA is enabled for this vport
  */
 enum virtchnl2_vport_flags {
 	VIRTCHNL2_VPORT_UPLINK_PORT	= BIT(0),
+	/* VIRTCHNL2_VPORT_* bits [1:3] rsvd */
+	VIRTCHNL2_VPORT_ENABLE_RDMA             = BIT(4),
 };
 
 /**
diff --git a/include/linux/net/intel/iidc_rdma_idpf.h b/include/linux/net/intel/iidc_rdma_idpf.h
index f2fe1844f660..16c970dd4c6e 100644
--- a/include/linux/net/intel/iidc_rdma_idpf.h
+++ b/include/linux/net/intel/iidc_rdma_idpf.h
@@ -6,6 +6,25 @@
 
 #include <linux/auxiliary_bus.h>
 
+/* struct to be populated by core LAN PCI driver */
+struct iidc_rdma_vport_dev_info {
+	struct auxiliary_device *adev;
+	struct auxiliary_device *core_adev;
+	struct net_device *netdev;
+	u16 vport_id;
+};
+
+struct iidc_rdma_vport_auxiliary_dev {
+	struct auxiliary_device adev;
+	struct iidc_rdma_vport_dev_info *vdev_info;
+};
+
+struct iidc_rdma_vport_auxiliary_drv {
+	struct auxiliary_driver adrv;
+	void (*event_handler)(struct iidc_rdma_vport_dev_info *vdev,
+			      struct iidc_rdma_event *event);
+};
+
 /* struct to be populated by core LAN PCI driver */
 enum iidc_function_type {
 	IIDC_FUNCTION_TYPE_PF,
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Intel-wired-lan] [iwl-next v2 4/6] idpf: implement remaining IDC RDMA core callbacks and handlers
  2025-06-12 21:59 [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
                   ` (2 preceding siblings ...)
  2025-06-12 21:59 ` [Intel-wired-lan] [iwl-next v2 3/6] idpf: implement RDMA vport " Tatyana Nikolova
@ 2025-06-12 22:00 ` Tatyana Nikolova
  2025-06-12 22:00 ` [Intel-wired-lan] [iwl-next v2 5/6] idpf: implement IDC vport aux driver MTU change handler Tatyana Nikolova
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Tatyana Nikolova @ 2025-06-12 22:00 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, Joshua Hay, Tatyana Nikolova

From: Joshua Hay <joshua.a.hay@intel.com>

Implement the idpf_idc_request_reset and idpf_idc_rdma_vc_send_sync
callbacks for the rdma core auxiliary driver to issue reset events to
the idpf and send (synchronous) virtchnl messages to the control plane
respectively.

Implement and plumb the reset handler for the opposite flow as well,
i.e. when the idpf is resetiing and needs to notify the rdma core
auxiliary driver.

Reviewed-by: Madhu Chittim <madhu.chittim@intel.com>
Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
---

Changes since split:
- align with new header naming

[3]:
- remove unnecessary iadrv NULL check

 drivers/net/ethernet/intel/idpf/idpf.h        |  1 +
 drivers/net/ethernet/intel/idpf/idpf_idc.c    | 43 ++++++++++++++++++-
 drivers/net/ethernet/intel/idpf/idpf_lib.c    |  2 +
 .../net/ethernet/intel/idpf/idpf_virtchnl.c   | 23 +++++++++-
 drivers/net/ethernet/intel/idpf/virtchnl2.h   |  3 +-
 5 files changed, 69 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index 52a3ec88e615..e74b0f3012eb 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -892,5 +892,6 @@ int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
 			       enum iidc_function_type ftype);
 void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info);
 void idpf_idc_deinit_vport_aux_device(struct iidc_rdma_vport_dev_info *vdev_info);
+void idpf_idc_issue_reset_event(struct iidc_rdma_core_dev_info *cdev_info);
 
 #endif /* !_IDPF_H_ */
diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c b/drivers/net/ethernet/intel/idpf/idpf_idc.c
index dfdf4fa287ab..7401e41a5d28 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_idc.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_idc.c
@@ -216,6 +216,38 @@ static void idpf_unplug_aux_dev(struct auxiliary_device *adev)
 	ida_free(&idpf_idc_ida, adev->id);
 }
 
+/**
+ * idpf_idc_issue_reset_event - Function to handle reset IDC event
+ * @cdev_info: IDC core device info pointer
+ */
+void idpf_idc_issue_reset_event(struct iidc_rdma_core_dev_info *cdev_info)
+{
+	enum iidc_rdma_event_type event_type = IIDC_RDMA_EVENT_WARN_RESET;
+	struct iidc_rdma_core_auxiliary_drv *iadrv;
+	struct iidc_rdma_event event = { };
+	struct auxiliary_device *adev;
+
+	if (!cdev_info)
+		/* RDMA is not enabled */
+		return;
+
+	set_bit(event_type, event.type);
+
+	device_lock(&cdev_info->adev->dev);
+
+	adev = cdev_info->adev;
+	if (!adev || !adev->dev.driver)
+		goto unlock;
+
+	iadrv = container_of(adev->dev.driver,
+			     struct iidc_rdma_core_auxiliary_drv,
+			     adrv.driver);
+	if (iadrv->event_handler)
+		iadrv->event_handler(cdev_info, &event);
+unlock:
+	device_unlock(&cdev_info->adev->dev);
+}
+
 /**
  * idpf_idc_vport_dev_up - called when CORE is ready for vport aux devs
  * @adapter: private data struct
@@ -298,7 +330,16 @@ EXPORT_SYMBOL_GPL(idpf_idc_vport_dev_ctrl);
 int idpf_idc_request_reset(struct iidc_rdma_core_dev_info *cdev_info,
 			   enum iidc_rdma_reset_type __always_unused reset_type)
 {
-	return -EOPNOTSUPP;
+	struct idpf_adapter *adapter = pci_get_drvdata(cdev_info->pdev);
+
+	if (!idpf_is_reset_in_prog(adapter)) {
+		set_bit(IDPF_HR_FUNC_RESET, adapter->flags);
+		queue_delayed_work(adapter->vc_event_wq,
+				   &adapter->vc_event_task,
+				   msecs_to_jiffies(10));
+	}
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(idpf_idc_request_reset);
 
diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index b0efd763a7e0..53392c01e03c 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1789,6 +1789,8 @@ static int idpf_init_hard_reset(struct idpf_adapter *adapter)
 	} else if (test_and_clear_bit(IDPF_HR_FUNC_RESET, adapter->flags)) {
 		bool is_reset = idpf_is_reset_detected(adapter);
 
+		idpf_idc_issue_reset_event(adapter->cdev_info);
+
 		idpf_set_vport_state(adapter);
 		idpf_vc_core_deinit(adapter);
 		if (!is_reset)
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
index c6fa4644fd3c..7a277ba3c44d 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -3745,6 +3745,27 @@ int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info *cdev_info,
 			       u8 *send_msg, u16 msg_size,
 			       u8 *recv_msg, u16 *recv_len)
 {
-	return -EOPNOTSUPP;
+	struct idpf_adapter *adapter = pci_get_drvdata(cdev_info->pdev);
+	struct idpf_vc_xn_params xn_params = { };
+	ssize_t reply_sz;
+	u16 recv_size;
+
+	if (!recv_msg || !recv_len || msg_size > IDPF_CTLQ_MAX_BUF_LEN)
+		return -EINVAL;
+
+	recv_size = min_t(u16, *recv_len, IDPF_CTLQ_MAX_BUF_LEN);
+	*recv_len = 0;
+	xn_params.vc_op = VIRTCHNL2_OP_RDMA;
+	xn_params.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC;
+	xn_params.send_buf.iov_base = send_msg;
+	xn_params.send_buf.iov_len = msg_size;
+	xn_params.recv_buf.iov_base = recv_msg;
+	xn_params.recv_buf.iov_len = recv_size;
+	reply_sz = idpf_vc_xn_exec(adapter, &xn_params);
+	if (reply_sz < 0)
+		return reply_sz;
+	*recv_len = reply_sz;
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(idpf_idc_rdma_vc_send_sync);
diff --git a/drivers/net/ethernet/intel/idpf/virtchnl2.h b/drivers/net/ethernet/intel/idpf/virtchnl2.h
index 82a3c307307e..b82218d20909 100644
--- a/drivers/net/ethernet/intel/idpf/virtchnl2.h
+++ b/drivers/net/ethernet/intel/idpf/virtchnl2.h
@@ -62,8 +62,9 @@ enum virtchnl2_op {
 	VIRTCHNL2_OP_GET_PTYPE_INFO		= 526,
 	/* Opcode 527 and 528 are reserved for VIRTCHNL2_OP_GET_PTYPE_ID and
 	 * VIRTCHNL2_OP_GET_PTYPE_INFO_RAW.
-	 * Opcodes 529, 530, 531, 532 and 533 are reserved.
 	 */
+	VIRTCHNL2_OP_RDMA			= 529,
+	/* Opcodes 530 through 533 are reserved. */
 	VIRTCHNL2_OP_LOOPBACK			= 534,
 	VIRTCHNL2_OP_ADD_MAC_ADDR		= 535,
 	VIRTCHNL2_OP_DEL_MAC_ADDR		= 536,
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Intel-wired-lan] [iwl-next v2 5/6] idpf: implement IDC vport aux driver MTU change handler
  2025-06-12 21:59 [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
                   ` (3 preceding siblings ...)
  2025-06-12 22:00 ` [Intel-wired-lan] [iwl-next v2 4/6] idpf: implement remaining IDC RDMA core callbacks and handlers Tatyana Nikolova
@ 2025-06-12 22:00 ` Tatyana Nikolova
  2025-06-12 22:00 ` [Intel-wired-lan] [iwl-next v2 6/6] idpf: implement get LAN MMIO memory regions Tatyana Nikolova
  2025-06-13  7:21 ` [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Paul Menzel
  6 siblings, 0 replies; 11+ messages in thread
From: Tatyana Nikolova @ 2025-06-12 22:00 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, Joshua Hay, Tatyana Nikolova

From: Joshua Hay <joshua.a.hay@intel.com>

The only event an RDMA vport aux driver cares about right now is an MTU
change on its underlying vport. Implement and plumb the handler to
signal the pre MTU change event and post MTU change events to the RDMA
vport aux driver.

Reviewed-by: Madhu Chittim <madhu.chittim@intel.com>
Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
---

Changes since split:
- align with iidc_rdma header naming

[3]:
- add missing break statement
- remove unnecessary iadrv NULL check

 drivers/net/ethernet/intel/idpf/idpf.h     |  2 ++
 drivers/net/ethernet/intel/idpf/idpf_idc.c | 31 ++++++++++++++++++++++
 drivers/net/ethernet/intel/idpf/idpf_lib.c | 11 +++++---
 3 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index e74b0f3012eb..f1bb10ae34b3 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -893,5 +893,7 @@ int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
 void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info);
 void idpf_idc_deinit_vport_aux_device(struct iidc_rdma_vport_dev_info *vdev_info);
 void idpf_idc_issue_reset_event(struct iidc_rdma_core_dev_info *cdev_info);
+void idpf_idc_vdev_mtu_event(struct iidc_rdma_vport_dev_info *vdev_info,
+			     enum iidc_rdma_event_type event_type);
 
 #endif /* !_IDPF_H_ */
diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c b/drivers/net/ethernet/intel/idpf/idpf_idc.c
index 7401e41a5d28..15907341e0bb 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_idc.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_idc.c
@@ -137,6 +137,37 @@ static int idpf_idc_init_aux_vport_dev(struct idpf_vport *vport)
 	return 0;
 }
 
+/**
+ * idpf_idc_vdev_mtu_event - Function to handle IDC vport mtu change events
+ * @vdev_info: IDC vport device info pointer
+ * @event_type: type of event to pass to handler
+ */
+void idpf_idc_vdev_mtu_event(struct iidc_rdma_vport_dev_info *vdev_info,
+			     enum iidc_rdma_event_type event_type)
+{
+	struct iidc_rdma_vport_auxiliary_drv *iadrv;
+	struct iidc_rdma_event event = { };
+	struct auxiliary_device *adev;
+
+	if (!vdev_info)
+		/* RDMA is not enabled */
+		return;
+
+	set_bit(event_type, event.type);
+
+	device_lock(&vdev_info->adev->dev);
+	adev = vdev_info->adev;
+	if (!adev || !adev->dev.driver)
+		goto unlock;
+	iadrv = container_of(adev->dev.driver,
+			     struct iidc_rdma_vport_auxiliary_drv,
+			     adrv.driver);
+	if (iadrv->event_handler)
+		iadrv->event_handler(vdev_info, &event);
+unlock:
+	device_unlock(&vdev_info->adev->dev);
+}
+
 /**
  * idpf_core_adev_release - function to be mapped to aux dev's release op
  * @dev: pointer to device to free
diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index 53392c01e03c..c0cd05529d33 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1925,6 +1925,9 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
 		idpf_vport_calc_num_q_desc(new_vport);
 		break;
 	case IDPF_SR_MTU_CHANGE:
+		idpf_idc_vdev_mtu_event(vport->vdev_info,
+					IIDC_RDMA_EVENT_BEFORE_MTU_CHANGE);
+		break;
 	case IDPF_SR_RSC_CHANGE:
 		break;
 	default:
@@ -1969,9 +1972,7 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
 	if (current_state == __IDPF_VPORT_UP)
 		err = idpf_vport_open(vport);
 
-	kfree(new_vport);
-
-	return err;
+	goto free_vport;
 
 err_reset:
 	idpf_send_add_queues_msg(vport, vport->num_txq, vport->num_complq,
@@ -1984,6 +1985,10 @@ int idpf_initiate_soft_reset(struct idpf_vport *vport,
 free_vport:
 	kfree(new_vport);
 
+	if (reset_cause == IDPF_SR_MTU_CHANGE)
+		idpf_idc_vdev_mtu_event(vport->vdev_info,
+					IIDC_RDMA_EVENT_AFTER_MTU_CHANGE);
+
 	return err;
 }
 
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [Intel-wired-lan] [iwl-next v2 6/6] idpf: implement get LAN MMIO memory regions
  2025-06-12 21:59 [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
                   ` (4 preceding siblings ...)
  2025-06-12 22:00 ` [Intel-wired-lan] [iwl-next v2 5/6] idpf: implement IDC vport aux driver MTU change handler Tatyana Nikolova
@ 2025-06-12 22:00 ` Tatyana Nikolova
  2025-06-13  7:21 ` [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Paul Menzel
  6 siblings, 0 replies; 11+ messages in thread
From: Tatyana Nikolova @ 2025-06-12 22:00 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, Joshua Hay, Tatyana Nikolova

From: Joshua Hay <joshua.a.hay@intel.com>

The RDMA driver needs to map its own MMIO regions for the sake of
performance, meaning the IDPF needs to avoid mapping portions of the BAR
space. However, to be HW agnostic, the IDPF cannot assume where
these are and must avoid mapping hard coded regions as much as possible.

The IDPF maps the bare minimum to load and communicate with the
control plane, i.e., the mailbox registers and the reset state
registers. Because of how and when mailbox reigster offsets are
initialized, it is easier to adjust the existing defines to be relative
to the mailbox region starting address. Use a specific mailbox register
write function that uses these relative offsets. The reset state
register addresses are calculated the same way as for other registers,
described below.

The IDPF then calls a new virtchnl op to fetch a list of MMIO regions
that it should map. The addresses for the registers in these regions are
calculated by determining what region the register resides in, adjusting
the offset to be relative to that region, and then adding the
register's offset to that region's mapped address.

If the new virtchnl op is not supported, the IDPF will fallback to
mapping the whole bar. However, it will still map them as separate
regions outside the mailbox and reset state registers. This way we can
use the same logic in both cases to access the MMIO space.

Reviewed-by: Madhu Chittim <madhu.chittim@intel.com>
Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
---

v2:
- Don't dereference cdev_info before NULL check in deinit_core_aux_device

Changes since split (v1):
- use struct resource to track mbx and rstat offsets
- minor cleanup, added more comments, and more explanation in commit
  msg, s/addr/vaddr
- align with header naming, add idpf specific memory region support to
  idpf specific header

[3]:
- header cleanup

 drivers/net/ethernet/intel/idpf/idpf.h        |  71 ++++++++-
 .../net/ethernet/intel/idpf/idpf_controlq.c   |  14 +-
 .../net/ethernet/intel/idpf/idpf_controlq.h   |  19 ++-
 drivers/net/ethernet/intel/idpf/idpf_dev.c    |  36 +++--
 drivers/net/ethernet/intel/idpf/idpf_idc.c    |  32 +++-
 drivers/net/ethernet/intel/idpf/idpf_main.c   |  32 +++-
 drivers/net/ethernet/intel/idpf/idpf_mem.h    |   8 +-
 drivers/net/ethernet/intel/idpf/idpf_vf_dev.c |  32 ++--
 .../net/ethernet/intel/idpf/idpf_virtchnl.c   | 149 +++++++++++++++++-
 drivers/net/ethernet/intel/idpf/virtchnl2.h   |  31 +++-
 include/linux/net/intel/iidc_rdma_idpf.h      |   8 +
 11 files changed, 380 insertions(+), 52 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index f1bb10ae34b3..8c93fbcb41bb 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -17,6 +17,7 @@ struct idpf_vport_max_q;
 #include <linux/sctp.h>
 #include <linux/ethtool_netlink.h>
 #include <net/gro.h>
+#include <linux/ioport.h>
 #include <linux/net/intel/iidc_rdma.h>
 #include <linux/net/intel/iidc_rdma_idpf.h>
 
@@ -196,7 +197,8 @@ struct idpf_vport_max_q {
  * @ptp_reg_init: PTP register initialization
  */
 struct idpf_reg_ops {
-	void (*ctlq_reg_init)(struct idpf_ctlq_create_info *cq);
+	void (*ctlq_reg_init)(struct idpf_adapter *adapter,
+			      struct idpf_ctlq_create_info *cq);
 	int (*intr_reg_init)(struct idpf_vport *vport);
 	void (*mb_intr_reg_init)(struct idpf_adapter *adapter);
 	void (*reset_reg_init)(struct idpf_adapter *adapter);
@@ -205,15 +207,25 @@ struct idpf_reg_ops {
 	void (*ptp_reg_init)(const struct idpf_adapter *adapter);
 };
 
+#define IDPF_MMIO_REG_NUM_STATIC	2
+#define IDPF_PF_MBX_REGION_SZ		4096
+#define IDPF_PF_RSTAT_REGION_SZ		2048
+#define IDPF_VF_MBX_REGION_SZ		10240
+#define IDPF_VF_RSTAT_REGION_SZ		2048
+
 /**
  * struct idpf_dev_ops - Device specific operations
  * @reg_ops: Register operations
  * @idc_init: IDC initialization
+ * @static_reg_info: array of mailbox and rstat register info
  */
 struct idpf_dev_ops {
 	struct idpf_reg_ops reg_ops;
 
 	int (*idc_init)(struct idpf_adapter *adapter);
+
+	/* static_reg_info[0] is mailbox region, static_reg_info[1] is rstat */
+	struct resource static_reg_info[IDPF_MMIO_REG_NUM_STATIC];
 };
 
 /**
@@ -754,6 +766,35 @@ static inline u8 idpf_get_min_tx_pkt_len(struct idpf_adapter *adapter)
 	return pkt_len ? pkt_len : IDPF_TX_MIN_PKT_LEN;
 }
 
+/**
+ * idpf_get_mbx_reg_addr - Get BAR0 mailbox register address
+ * @adapter: private data struct
+ * @reg_offset: register offset value
+ *
+ * Return: BAR0 mailbox register address based on register offset.
+ */
+static inline void __iomem *idpf_get_mbx_reg_addr(struct idpf_adapter *adapter,
+						  resource_size_t reg_offset)
+{
+	return adapter->hw.mbx.vaddr + reg_offset;
+}
+
+/**
+ * idpf_get_rstat_reg_addr - Get BAR0 rstat register address
+ * @adapter: private data struct
+ * @reg_offset: register offset value
+ *
+ * Return: BAR0 rstat register address based on register offset.
+ */
+static inline
+void __iomem *idpf_get_rstat_reg_addr(struct idpf_adapter *adapter,
+				      resource_size_t reg_offset)
+{
+	reg_offset -= adapter->dev_ops.static_reg_info[1].start;
+
+	return adapter->hw.rstat.vaddr + reg_offset;
+}
+
 /**
  * idpf_get_reg_addr - Get BAR0 register address
  * @adapter: private data struct
@@ -764,7 +805,31 @@ static inline u8 idpf_get_min_tx_pkt_len(struct idpf_adapter *adapter)
 static inline void __iomem *idpf_get_reg_addr(struct idpf_adapter *adapter,
 					      resource_size_t reg_offset)
 {
-	return (void __iomem *)(adapter->hw.hw_addr + reg_offset);
+	struct idpf_hw *hw = &adapter->hw;
+
+	for (int i = 0; i < hw->num_lan_regs; i++) {
+		struct idpf_mmio_reg *region = &hw->lan_regs[i];
+
+		if (reg_offset >= region->addr_start &&
+		    reg_offset < (region->addr_start + region->addr_len)) {
+			/*
+			 * Convert the offset so that it is relative to the
+			 * start of the region.  Then add the base address of
+			 * the region to get the final address.
+			 */
+			reg_offset -= region->addr_start;
+
+			return region->vaddr + reg_offset;
+		}
+	}
+
+	/* It's impossible to hit this case with offsets from the CP. But if we
+	 * do for any other reason, the kernel will panic on that register
+	 * access. Might as well do it here to make it clear what's happening.
+	 */
+	BUG();
+
+	return NULL;
 }
 
 /**
@@ -778,7 +843,7 @@ static inline bool idpf_is_reset_detected(struct idpf_adapter *adapter)
 	if (!adapter->hw.arq)
 		return true;
 
-	return !(readl(idpf_get_reg_addr(adapter, adapter->hw.arq->reg.len)) &
+	return !(readl(idpf_get_mbx_reg_addr(adapter, adapter->hw.arq->reg.len)) &
 		 adapter->hw.arq->reg.len_mask);
 }
 
diff --git a/drivers/net/ethernet/intel/idpf/idpf_controlq.c b/drivers/net/ethernet/intel/idpf/idpf_controlq.c
index b28991dd1870..9c5c628eb469 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_controlq.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_controlq.c
@@ -36,19 +36,19 @@ static void idpf_ctlq_init_regs(struct idpf_hw *hw, struct idpf_ctlq_info *cq,
 {
 	/* Update tail to post pre-allocated buffers for rx queues */
 	if (is_rxq)
-		wr32(hw, cq->reg.tail, (u32)(cq->ring_size - 1));
+		idpf_mbx_wr32(hw, cq->reg.tail, (u32)(cq->ring_size - 1));
 
 	/* For non-Mailbox control queues only TAIL need to be set */
 	if (cq->q_id != -1)
 		return;
 
 	/* Clear Head for both send or receive */
-	wr32(hw, cq->reg.head, 0);
+	idpf_mbx_wr32(hw, cq->reg.head, 0);
 
 	/* set starting point */
-	wr32(hw, cq->reg.bal, lower_32_bits(cq->desc_ring.pa));
-	wr32(hw, cq->reg.bah, upper_32_bits(cq->desc_ring.pa));
-	wr32(hw, cq->reg.len, (cq->ring_size | cq->reg.len_ena_mask));
+	idpf_mbx_wr32(hw, cq->reg.bal, lower_32_bits(cq->desc_ring.pa));
+	idpf_mbx_wr32(hw, cq->reg.bah, upper_32_bits(cq->desc_ring.pa));
+	idpf_mbx_wr32(hw, cq->reg.len, (cq->ring_size | cq->reg.len_ena_mask));
 }
 
 /**
@@ -329,7 +329,7 @@ int idpf_ctlq_send(struct idpf_hw *hw, struct idpf_ctlq_info *cq,
 	 */
 	dma_wmb();
 
-	wr32(hw, cq->reg.tail, cq->next_to_use);
+	idpf_mbx_wr32(hw, cq->reg.tail, cq->next_to_use);
 
 err_unlock:
 	mutex_unlock(&cq->cq_lock);
@@ -521,7 +521,7 @@ int idpf_ctlq_post_rx_buffs(struct idpf_hw *hw, struct idpf_ctlq_info *cq,
 
 		dma_wmb();
 
-		wr32(hw, cq->reg.tail, cq->next_to_post);
+		idpf_mbx_wr32(hw, cq->reg.tail, cq->next_to_post);
 	}
 
 	mutex_unlock(&cq->cq_lock);
diff --git a/drivers/net/ethernet/intel/idpf/idpf_controlq.h b/drivers/net/ethernet/intel/idpf/idpf_controlq.h
index c1aba09e9856..c882428edc24 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_controlq.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_controlq.h
@@ -94,12 +94,27 @@ struct idpf_mbxq_desc {
 	u32 pf_vf_id;		/* used by CP when sending to PF */
 };
 
+/*
+ * Max number of MMIO regions not including the mailbox and rstat regions in
+ * the fallback case when the whole bar is mapped.
+ */
+#define IDPF_MMIO_MAP_FALLBACK_MAX_REMAINING		3
+
+struct idpf_mmio_reg {
+	void __iomem *vaddr;
+	resource_size_t addr_start;
+	resource_size_t addr_len;
+};
+
 /* Define the driver hardware struct to replace other control structs as needed
  * Align to ctlq_hw_info
  */
 struct idpf_hw {
-	void __iomem *hw_addr;
-	resource_size_t hw_addr_len;
+	struct idpf_mmio_reg mbx;
+	struct idpf_mmio_reg rstat;
+	/* Array of remaining LAN BAR regions */
+	int num_lan_regs;
+	struct idpf_mmio_reg *lan_regs;
 
 	struct idpf_adapter *back;
 
diff --git a/drivers/net/ethernet/intel/idpf/idpf_dev.c b/drivers/net/ethernet/intel/idpf/idpf_dev.c
index dd227a4368fb..bfa60f7d43de 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_dev.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_dev.c
@@ -10,10 +10,13 @@
 
 /**
  * idpf_ctlq_reg_init - initialize default mailbox registers
+ * @adapter: adapter structure
  * @cq: pointer to the array of create control queues
  */
-static void idpf_ctlq_reg_init(struct idpf_ctlq_create_info *cq)
+static void idpf_ctlq_reg_init(struct idpf_adapter *adapter,
+			       struct idpf_ctlq_create_info *cq)
 {
+	resource_size_t mbx_start = adapter->dev_ops.static_reg_info[0].start;
 	int i;
 
 	for (i = 0; i < IDPF_NUM_DFLT_MBX_Q; i++) {
@@ -22,22 +25,22 @@ static void idpf_ctlq_reg_init(struct idpf_ctlq_create_info *cq)
 		switch (ccq->type) {
 		case IDPF_CTLQ_TYPE_MAILBOX_TX:
 			/* set head and tail registers in our local struct */
-			ccq->reg.head = PF_FW_ATQH;
-			ccq->reg.tail = PF_FW_ATQT;
-			ccq->reg.len = PF_FW_ATQLEN;
-			ccq->reg.bah = PF_FW_ATQBAH;
-			ccq->reg.bal = PF_FW_ATQBAL;
+			ccq->reg.head = PF_FW_ATQH - mbx_start;
+			ccq->reg.tail = PF_FW_ATQT - mbx_start;
+			ccq->reg.len = PF_FW_ATQLEN - mbx_start;
+			ccq->reg.bah = PF_FW_ATQBAH - mbx_start;
+			ccq->reg.bal = PF_FW_ATQBAL - mbx_start;
 			ccq->reg.len_mask = PF_FW_ATQLEN_ATQLEN_M;
 			ccq->reg.len_ena_mask = PF_FW_ATQLEN_ATQENABLE_M;
 			ccq->reg.head_mask = PF_FW_ATQH_ATQH_M;
 			break;
 		case IDPF_CTLQ_TYPE_MAILBOX_RX:
 			/* set head and tail registers in our local struct */
-			ccq->reg.head = PF_FW_ARQH;
-			ccq->reg.tail = PF_FW_ARQT;
-			ccq->reg.len = PF_FW_ARQLEN;
-			ccq->reg.bah = PF_FW_ARQBAH;
-			ccq->reg.bal = PF_FW_ARQBAL;
+			ccq->reg.head = PF_FW_ARQH - mbx_start;
+			ccq->reg.tail = PF_FW_ARQT - mbx_start;
+			ccq->reg.len = PF_FW_ARQLEN - mbx_start;
+			ccq->reg.bah = PF_FW_ARQBAH - mbx_start;
+			ccq->reg.bal = PF_FW_ARQBAL - mbx_start;
 			ccq->reg.len_mask = PF_FW_ARQLEN_ARQLEN_M;
 			ccq->reg.len_ena_mask = PF_FW_ARQLEN_ARQENABLE_M;
 			ccq->reg.head_mask = PF_FW_ARQH_ARQH_M;
@@ -130,7 +133,7 @@ static int idpf_intr_reg_init(struct idpf_vport *vport)
  */
 static void idpf_reset_reg_init(struct idpf_adapter *adapter)
 {
-	adapter->reset_reg.rstat = idpf_get_reg_addr(adapter, PFGEN_RSTAT);
+	adapter->reset_reg.rstat = idpf_get_rstat_reg_addr(adapter, PFGEN_RSTAT);
 	adapter->reset_reg.rstat_m = PFGEN_RSTAT_PFR_STATE_M;
 }
 
@@ -144,9 +147,9 @@ static void idpf_trigger_reset(struct idpf_adapter *adapter,
 {
 	u32 reset_reg;
 
-	reset_reg = readl(idpf_get_reg_addr(adapter, PFGEN_CTRL));
+	reset_reg = readl(idpf_get_rstat_reg_addr(adapter, PFGEN_CTRL));
 	writel(reset_reg | PFGEN_CTRL_PFSWR,
-	       idpf_get_reg_addr(adapter, PFGEN_CTRL));
+	       idpf_get_rstat_reg_addr(adapter, PFGEN_CTRL));
 }
 
 /**
@@ -195,4 +198,9 @@ void idpf_dev_ops_init(struct idpf_adapter *adapter)
 	idpf_reg_ops_init(adapter);
 
 	adapter->dev_ops.idc_init = idpf_idc_register;
+
+	resource_set_range(&adapter->dev_ops.static_reg_info[0],
+			   PF_FW_BASE, IDPF_PF_MBX_REGION_SZ);
+	resource_set_range(&adapter->dev_ops.static_reg_info[1],
+			   PFGEN_RTRIG, IDPF_PF_RSTAT_REGION_SZ);
 }
diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c b/drivers/net/ethernet/intel/idpf/idpf_idc.c
index 15907341e0bb..3f53f9dcebd8 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_idc.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_idc.c
@@ -406,7 +406,7 @@ int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
 {
 	struct iidc_rdma_core_dev_info *cdev_info;
 	struct iidc_rdma_priv_dev_info *privd;
-	int err;
+	int err, i;
 
 	adapter->cdev_info = kzalloc(sizeof(*cdev_info), GFP_KERNEL);
 	if (!adapter->cdev_info)
@@ -424,14 +424,36 @@ int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
 	cdev_info->rdma_protocol = IIDC_RDMA_PROTOCOL_ROCEV2;
 	privd->ftype = ftype;
 
+	privd->mapped_mem_regions =
+		kcalloc(adapter->hw.num_lan_regs,
+			sizeof(struct iidc_rdma_lan_mapped_mem_region),
+			GFP_KERNEL);
+	if (!privd->mapped_mem_regions) {
+		err = -ENOMEM;
+		goto err_plug_aux_dev;
+	}
+
+	privd->num_memory_regions = cpu_to_le16(adapter->hw.num_lan_regs);
+	for (i = 0; i < adapter->hw.num_lan_regs; i++) {
+		privd->mapped_mem_regions[i].region_addr =
+			adapter->hw.lan_regs[i].vaddr;
+		privd->mapped_mem_regions[i].size =
+			cpu_to_le64(adapter->hw.lan_regs[i].addr_len);
+		privd->mapped_mem_regions[i].start_offset =
+			cpu_to_le64(adapter->hw.lan_regs[i].addr_start);
+	}
+
 	idpf_idc_init_msix_data(adapter);
 
 	err = idpf_plug_core_aux_dev(cdev_info);
 	if (err)
-		goto err_plug_aux_dev;
+		goto err_free_mem_regions;
 
 	return 0;
 
+err_free_mem_regions:
+	kfree(privd->mapped_mem_regions);
+	privd->mapped_mem_regions = NULL;
 err_plug_aux_dev:
 	kfree(privd);
 err_privd_alloc:
@@ -447,12 +469,16 @@ int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
  */
 void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info)
 {
+	struct iidc_rdma_priv_dev_info *privd;
+
 	if (!cdev_info)
 		return;
 
 	idpf_unplug_aux_dev(cdev_info->adev);
 
-	kfree(cdev_info->iidc_priv);
+	privd = cdev_info->iidc_priv;
+	kfree(privd->mapped_mem_regions);
+	kfree(privd);
 	kfree(cdev_info);
 }
 
diff --git a/drivers/net/ethernet/intel/idpf/idpf_main.c b/drivers/net/ethernet/intel/idpf/idpf_main.c
index 0efd9c0c7a90..204d9cfc05b4 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_main.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_main.c
@@ -106,15 +106,37 @@ static void idpf_shutdown(struct pci_dev *pdev)
  */
 static int idpf_cfg_hw(struct idpf_adapter *adapter)
 {
+	resource_size_t res_start, mbx_start, rstat_start;
 	struct pci_dev *pdev = adapter->pdev;
 	struct idpf_hw *hw = &adapter->hw;
+	struct device *dev = &pdev->dev;
+	long len;
+
+	res_start = pci_resource_start(pdev, 0);
+
+	/* Map mailbox space for virtchnl communication */
+	mbx_start = res_start + adapter->dev_ops.static_reg_info[0].start;
+	len = resource_size(&adapter->dev_ops.static_reg_info[0]);
+	hw->mbx.vaddr = devm_ioremap(dev, mbx_start, len);
+	if (!hw->mbx.vaddr) {
+		pci_err(pdev, "failed to allocate BAR0 mbx region\n");
+
+		return -ENOMEM;
+	}
+	hw->mbx.addr_start = adapter->dev_ops.static_reg_info[0].start;
+	hw->mbx.addr_len = len;
 
-	hw->hw_addr = pcim_iomap_table(pdev)[0];
-	if (!hw->hw_addr) {
-		pci_err(pdev, "failed to allocate PCI iomap table\n");
+	/* Map rstat space for resets */
+	rstat_start = res_start + adapter->dev_ops.static_reg_info[1].start;
+	len = resource_size(&adapter->dev_ops.static_reg_info[1]);
+	hw->rstat.vaddr = devm_ioremap(dev, rstat_start, len);
+	if (!hw->rstat.vaddr) {
+		pci_err(pdev, "failed to allocate BAR0 rstat region\n");
 
 		return -ENOMEM;
 	}
+	hw->rstat.addr_start = adapter->dev_ops.static_reg_info[1].start;
+	hw->rstat.addr_len = len;
 
 	hw->back = adapter;
 
@@ -161,9 +183,9 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (err)
 		goto err_free;
 
-	err = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
+	err = pci_request_mem_regions(pdev, pci_name(pdev));
 	if (err) {
-		pci_err(pdev, "pcim_iomap_regions failed %pe\n", ERR_PTR(err));
+		pci_err(pdev, "pci_request_mem_regions failed %pe\n", ERR_PTR(err));
 
 		goto err_free;
 	}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_mem.h b/drivers/net/ethernet/intel/idpf/idpf_mem.h
index b21a04fccf0f..2aaabdc02dd2 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_mem.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_mem.h
@@ -12,9 +12,9 @@ struct idpf_dma_mem {
 	size_t size;
 };
 
-#define wr32(a, reg, value)	writel((value), ((a)->hw_addr + (reg)))
-#define rd32(a, reg)		readl((a)->hw_addr + (reg))
-#define wr64(a, reg, value)	writeq((value), ((a)->hw_addr + (reg)))
-#define rd64(a, reg)		readq((a)->hw_addr + (reg))
+#define idpf_mbx_wr32(a, reg, value)	writel((value), ((a)->mbx.vaddr + (reg)))
+#define idpf_mbx_rd32(a, reg)		readl((a)->mbx.vaddr + (reg))
+#define idpf_mbx_wr64(a, reg, value)	writeq((value), ((a)->mbx.vaddr + (reg)))
+#define idpf_mbx_rd64(a, reg)		readq((a)->mbx.vaddr + (reg))
 
 #endif /* _IDPF_MEM_H_ */
diff --git a/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c b/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
index 2f84bd596ae4..259d50fded67 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
@@ -9,10 +9,13 @@
 
 /**
  * idpf_vf_ctlq_reg_init - initialize default mailbox registers
+ * @adapter: adapter structure
  * @cq: pointer to the array of create control queues
  */
-static void idpf_vf_ctlq_reg_init(struct idpf_ctlq_create_info *cq)
+static void idpf_vf_ctlq_reg_init(struct idpf_adapter *adapter,
+				  struct idpf_ctlq_create_info *cq)
 {
+	resource_size_t mbx_start = adapter->dev_ops.static_reg_info[0].start;
 	int i;
 
 	for (i = 0; i < IDPF_NUM_DFLT_MBX_Q; i++) {
@@ -21,22 +24,22 @@ static void idpf_vf_ctlq_reg_init(struct idpf_ctlq_create_info *cq)
 		switch (ccq->type) {
 		case IDPF_CTLQ_TYPE_MAILBOX_TX:
 			/* set head and tail registers in our local struct */
-			ccq->reg.head = VF_ATQH;
-			ccq->reg.tail = VF_ATQT;
-			ccq->reg.len = VF_ATQLEN;
-			ccq->reg.bah = VF_ATQBAH;
-			ccq->reg.bal = VF_ATQBAL;
+			ccq->reg.head = VF_ATQH - mbx_start;
+			ccq->reg.tail = VF_ATQT - mbx_start;
+			ccq->reg.len = VF_ATQLEN - mbx_start;
+			ccq->reg.bah = VF_ATQBAH - mbx_start;
+			ccq->reg.bal = VF_ATQBAL - mbx_start;
 			ccq->reg.len_mask = VF_ATQLEN_ATQLEN_M;
 			ccq->reg.len_ena_mask = VF_ATQLEN_ATQENABLE_M;
 			ccq->reg.head_mask = VF_ATQH_ATQH_M;
 			break;
 		case IDPF_CTLQ_TYPE_MAILBOX_RX:
 			/* set head and tail registers in our local struct */
-			ccq->reg.head = VF_ARQH;
-			ccq->reg.tail = VF_ARQT;
-			ccq->reg.len = VF_ARQLEN;
-			ccq->reg.bah = VF_ARQBAH;
-			ccq->reg.bal = VF_ARQBAL;
+			ccq->reg.head = VF_ARQH - mbx_start;
+			ccq->reg.tail = VF_ARQT - mbx_start;
+			ccq->reg.len = VF_ARQLEN - mbx_start;
+			ccq->reg.bah = VF_ARQBAH - mbx_start;
+			ccq->reg.bal = VF_ARQBAL - mbx_start;
 			ccq->reg.len_mask = VF_ARQLEN_ARQLEN_M;
 			ccq->reg.len_ena_mask = VF_ARQLEN_ARQENABLE_M;
 			ccq->reg.head_mask = VF_ARQH_ARQH_M;
@@ -129,7 +132,7 @@ static int idpf_vf_intr_reg_init(struct idpf_vport *vport)
  */
 static void idpf_vf_reset_reg_init(struct idpf_adapter *adapter)
 {
-	adapter->reset_reg.rstat = idpf_get_reg_addr(adapter, VFGEN_RSTAT);
+	adapter->reset_reg.rstat = idpf_get_rstat_reg_addr(adapter, VFGEN_RSTAT);
 	adapter->reset_reg.rstat_m = VFGEN_RSTAT_VFR_STATE_M;
 }
 
@@ -180,4 +183,9 @@ void idpf_vf_dev_ops_init(struct idpf_adapter *adapter)
 	idpf_vf_reg_ops_init(adapter);
 
 	adapter->dev_ops.idc_init = idpf_idc_vf_register;
+
+	resource_set_range(&adapter->dev_ops.static_reg_info[0],
+			   VF_BASE, IDPF_VF_MBX_REGION_SZ);
+	resource_set_range(&adapter->dev_ops.static_reg_info[1],
+			   VFGEN_RSTAT, IDPF_VF_RSTAT_REGION_SZ);
 }
diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
index 7a277ba3c44d..84eee86d70eb 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -869,6 +869,7 @@ static int idpf_send_get_caps_msg(struct idpf_adapter *adapter)
 	caps.other_caps =
 		cpu_to_le64(VIRTCHNL2_CAP_SRIOV			|
 			    VIRTCHNL2_CAP_RDMA                  |
+			    VIRTCHNL2_CAP_LAN_MEMORY_REGIONS	|
 			    VIRTCHNL2_CAP_MACFILTER		|
 			    VIRTCHNL2_CAP_SPLITQ_QSCHED		|
 			    VIRTCHNL2_CAP_PROMISC		|
@@ -891,6 +892,128 @@ static int idpf_send_get_caps_msg(struct idpf_adapter *adapter)
 	return 0;
 }
 
+/**
+ * idpf_send_get_lan_memory_regions - Send virtchnl get LAN memory regions msg
+ * @adapter: Driver specific private struct
+ *
+ * Return: 0 on success or error code on failure.
+ */
+static int idpf_send_get_lan_memory_regions(struct idpf_adapter *adapter)
+{
+	struct virtchnl2_get_lan_memory_regions *rcvd_regions __free(kfree);
+	struct idpf_vc_xn_params xn_params = {
+		.vc_op = VIRTCHNL2_OP_GET_LAN_MEMORY_REGIONS,
+		.recv_buf.iov_len = IDPF_CTLQ_MAX_BUF_LEN,
+		.timeout_ms = IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC,
+	};
+	int num_regions, size;
+	struct idpf_hw *hw;
+	ssize_t reply_sz;
+	int err = 0;
+
+	rcvd_regions = kzalloc(IDPF_CTLQ_MAX_BUF_LEN, GFP_KERNEL);
+	if (!rcvd_regions)
+		return -ENOMEM;
+
+	xn_params.recv_buf.iov_base = rcvd_regions;
+	reply_sz = idpf_vc_xn_exec(adapter, &xn_params);
+	if (reply_sz < 0)
+		return reply_sz;
+
+	num_regions = le16_to_cpu(rcvd_regions->num_memory_regions);
+	size = struct_size(rcvd_regions, mem_reg, num_regions);
+	if (reply_sz < size)
+		return -EIO;
+
+	if (size > IDPF_CTLQ_MAX_BUF_LEN)
+		return -EINVAL;
+
+	hw = &adapter->hw;
+	hw->lan_regs = kcalloc(num_regions, sizeof(*hw->lan_regs), GFP_KERNEL);
+	if (!hw->lan_regs)
+		return -ENOMEM;
+
+	for (int i = 0; i < num_regions; i++) {
+		hw->lan_regs[i].addr_len =
+			le64_to_cpu(rcvd_regions->mem_reg[i].size);
+		hw->lan_regs[i].addr_start =
+			le64_to_cpu(rcvd_regions->mem_reg[i].start_offset);
+	}
+	hw->num_lan_regs = num_regions;
+
+	return err;
+}
+
+/**
+ * idpf_calc_remaining_mmio_regs - calculate MMIO regions outside mbx and rstat
+ * @adapter: Driver specific private structure
+ *
+ * Called when idpf_send_get_lan_memory_regions is not supported. This will
+ * calculate the offsets and sizes for the regions before, in between, and
+ * after the mailbox and rstat MMIO mappings.
+ *
+ * Return: 0 on success or error code on failure.
+ */
+static int idpf_calc_remaining_mmio_regs(struct idpf_adapter *adapter)
+{
+	struct resource *rstat_reg = &adapter->dev_ops.static_reg_info[1];
+	struct resource *mbx_reg = &adapter->dev_ops.static_reg_info[0];
+	struct idpf_hw *hw = &adapter->hw;
+
+	hw->num_lan_regs = IDPF_MMIO_MAP_FALLBACK_MAX_REMAINING;
+	hw->lan_regs = kcalloc(hw->num_lan_regs, sizeof(*hw->lan_regs),
+			       GFP_KERNEL);
+	if (!hw->lan_regs)
+		return -ENOMEM;
+
+	/* Region preceding mailbox */
+	hw->lan_regs[0].addr_start = 0;
+	hw->lan_regs[0].addr_len = mbx_reg->start;
+	/* Region between mailbox and rstat */
+	hw->lan_regs[1].addr_start = mbx_reg->end + 1;
+	hw->lan_regs[1].addr_len = rstat_reg->start -
+					hw->lan_regs[1].addr_start;
+	/* Region after rstat */
+	hw->lan_regs[2].addr_start = rstat_reg->end + 1;
+	hw->lan_regs[2].addr_len = pci_resource_len(adapter->pdev, 0) -
+					hw->lan_regs[2].addr_start;
+
+	return 0;
+}
+
+/**
+ * idpf_map_lan_mmio_regs - map remaining LAN BAR regions
+ * @adapter: Driver specific private structure
+ *
+ * Return: 0 on success or error code on failure.
+ */
+static int idpf_map_lan_mmio_regs(struct idpf_adapter *adapter)
+{
+	struct pci_dev *pdev = adapter->pdev;
+	struct idpf_hw *hw = &adapter->hw;
+	resource_size_t res_start;
+
+	res_start = pci_resource_start(pdev, 0);
+
+	for (int i = 0; i < hw->num_lan_regs; i++) {
+		resource_size_t start;
+		long len;
+
+		len = hw->lan_regs[i].addr_len;
+		if (!len)
+			continue;
+		start = hw->lan_regs[i].addr_start + res_start;
+
+		hw->lan_regs[i].vaddr = devm_ioremap(&pdev->dev, start, len);
+		if (!hw->lan_regs[i].vaddr) {
+			pci_err(pdev, "failed to allocate BAR0 region\n");
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+
 /**
  * idpf_vport_alloc_max_qs - Allocate max queues for a vport
  * @adapter: Driver specific private structure
@@ -2802,7 +2925,7 @@ int idpf_init_dflt_mbx(struct idpf_adapter *adapter)
 	struct idpf_hw *hw = &adapter->hw;
 	int err;
 
-	adapter->dev_ops.reg_ops.ctlq_reg_init(ctlq_info);
+	adapter->dev_ops.reg_ops.ctlq_reg_init(adapter, ctlq_info);
 
 	err = idpf_ctlq_init(hw, IDPF_NUM_DFLT_MBX_Q, ctlq_info);
 	if (err)
@@ -2962,6 +3085,30 @@ int idpf_vc_core_init(struct idpf_adapter *adapter)
 		msleep(task_delay);
 	}
 
+	if (idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_LAN_MEMORY_REGIONS)) {
+		err = idpf_send_get_lan_memory_regions(adapter);
+		if (err) {
+			dev_err(&adapter->pdev->dev, "Failed to get LAN memory regions: %d\n",
+				err);
+			return -EINVAL;
+		}
+	} else {
+		/* Fallback to mapping the remaining regions of the entire BAR */
+		err = idpf_calc_remaining_mmio_regs(adapter);
+		if (err) {
+			dev_err(&adapter->pdev->dev, "Failed to allocate BAR0 region(s): %d\n",
+				err);
+			return -ENOMEM;
+		}
+	}
+
+	err = idpf_map_lan_mmio_regs(adapter);
+	if (err) {
+		dev_err(&adapter->pdev->dev, "Failed to map BAR0 region(s): %d\n",
+			err);
+		return -ENOMEM;
+	}
+
 	pci_sriov_set_totalvfs(adapter->pdev, idpf_get_max_vfs(adapter));
 	num_max_vports = idpf_get_max_vports(adapter);
 	adapter->max_vports = num_max_vports;
diff --git a/drivers/net/ethernet/intel/idpf/virtchnl2.h b/drivers/net/ethernet/intel/idpf/virtchnl2.h
index b82218d20909..870e1de5755f 100644
--- a/drivers/net/ethernet/intel/idpf/virtchnl2.h
+++ b/drivers/net/ethernet/intel/idpf/virtchnl2.h
@@ -69,6 +69,7 @@ enum virtchnl2_op {
 	VIRTCHNL2_OP_ADD_MAC_ADDR		= 535,
 	VIRTCHNL2_OP_DEL_MAC_ADDR		= 536,
 	VIRTCHNL2_OP_CONFIG_PROMISCUOUS_MODE	= 537,
+	/* Opcodes 538 through 540 are reserved. */
 
 	/* TimeSync opcodes */
 	VIRTCHNL2_OP_PTP_GET_CAPS			= 541,
@@ -79,6 +80,7 @@ enum virtchnl2_op {
 	VIRTCHNL2_OP_PTP_ADJ_DEV_CLK_FINE		= 546,
 	VIRTCHNL2_OP_PTP_ADJ_DEV_CLK_TIME		= 547,
 	VIRTCHNL2_OP_PTP_GET_VPORT_TX_TSTAMP_CAPS	= 548,
+	VIRTCHNL2_OP_GET_LAN_MEMORY_REGIONS		= 549,
 };
 
 /**
@@ -212,7 +214,8 @@ enum virtchnl2_cap_other {
 	VIRTCHNL2_CAP_RX_FLEX_DESC		= BIT_ULL(17),
 	VIRTCHNL2_CAP_PTYPE			= BIT_ULL(18),
 	VIRTCHNL2_CAP_LOOPBACK			= BIT_ULL(19),
-	/* Other capability 20 is reserved */
+	/* Other capability 20-21 is reserved */
+	VIRTCHNL2_CAP_LAN_MEMORY_REGIONS	= BIT_ULL(22),
 
 	/* this must be the last capability */
 	VIRTCHNL2_CAP_OEM			= BIT_ULL(63),
@@ -1587,4 +1590,30 @@ struct virtchnl2_ptp_adj_dev_clk_time {
 };
 VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_ptp_adj_dev_clk_time);
 
+/**
+ * struct virtchnl2_mem_region - MMIO memory region
+ * @start_offset: starting offset of the MMIO memory region
+ * @size: size of the MMIO memory region
+ */
+struct virtchnl2_mem_region {
+	__le64 start_offset;
+	__le64 size;
+};
+VIRTCHNL2_CHECK_STRUCT_LEN(16, virtchnl2_mem_region);
+
+/**
+ * struct virtchnl2_get_lan_memory_regions - List of LAN MMIO memory regions
+ * @num_memory_regions: number of memory regions
+ * @pad: Padding
+ * @mem_reg: List with memory region info
+ *
+ * PF/VF sends this message to learn what LAN MMIO memory regions it should map.
+ */
+struct virtchnl2_get_lan_memory_regions {
+	__le16 num_memory_regions;
+	u8 pad[6];
+	struct virtchnl2_mem_region mem_reg[];
+};
+VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_get_lan_memory_regions);
+
 #endif /* _VIRTCHNL_2_H_ */
diff --git a/include/linux/net/intel/iidc_rdma_idpf.h b/include/linux/net/intel/iidc_rdma_idpf.h
index 16c970dd4c6e..bab697e18fd6 100644
--- a/include/linux/net/intel/iidc_rdma_idpf.h
+++ b/include/linux/net/intel/iidc_rdma_idpf.h
@@ -31,10 +31,18 @@ enum iidc_function_type {
 	IIDC_FUNCTION_TYPE_VF,
 };
 
+struct iidc_rdma_lan_mapped_mem_region {
+	u8 __iomem *region_addr;
+	__le64 size;
+	__le64 start_offset;
+};
+
 struct iidc_rdma_priv_dev_info {
 	struct msix_entry *msix_entries;
 	u16 msix_count; /* How many vectors are reserved for this device */
 	enum iidc_function_type ftype;
+	__le16 num_memory_regions;
+	struct iidc_rdma_lan_mapped_mem_region *mapped_mem_regions;
 };
 
 int idpf_idc_vport_dev_ctrl(struct iidc_rdma_core_dev_info *cdev_info, bool up);
-- 
2.31.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf
  2025-06-12 21:59 [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
                   ` (5 preceding siblings ...)
  2025-06-12 22:00 ` [Intel-wired-lan] [iwl-next v2 6/6] idpf: implement get LAN MMIO memory regions Tatyana Nikolova
@ 2025-06-13  7:21 ` Paul Menzel
  2025-07-08 20:40   ` Nikolova, Tatyana E
  6 siblings, 1 reply; 11+ messages in thread
From: Paul Menzel @ 2025-06-13  7:21 UTC (permalink / raw)
  To: Tatyana Nikolova; +Cc: intel-wired-lan, jgg, leon, linux-rdma, netdev, kuba

Dear Tatyana,


Thank you for this patch series.


Am 12.06.25 um 23:59 schrieb Tatyana Nikolova:
> This idpf patch series is the second part of the staged submission
> for introducing RDMA RoCEv2 support for the IPU E2000 line of products,
> referred to as GEN3.
> 
> To support RDMA GEN3 devices, the idpf driver uses
> common definitions of the IIDC interface and implements
> specific device functionality in iidc_rdma_idpf.h.

This could be re-flowed for longer lines.

> The IPU model can host one or more logical network endpoints called
> vPorts per PCI function that are flexibly associated with a physical
> port or an internal communication port.
> 
> Other features as it pertains to GEN3 devices include:
> * MMIO learning
> * RDMA capability negotiation
> * RDMA vectors discovery between idpf and control plane
> 
> These patches are split from the submission
> "Add RDMA support for Intel IPU E2000 (GEN3)" [1]
> and are based on 6.16-rc1. A shared pull request for net-next and
> rdma-next will be sent following review.

Still mention the datasheet?

Also, it’d be great to have a paragraph on how this was tested.

> Changelog:
> 
> v2:
> * Minor improvements like variable rename, logging,
> remove a redundant variable, etc.
> * A couple of cdev_info fixes to properly free it in
> error path and not to dereference it before NULL check.
> 
> Changes since split (v1) at [4]:
> * Replace core dev_ops with exported symbols
> * Align with new header split scheme (iidc_rdma.h common header
> and iidc_rdma_idpf.h specific header)
> * Align with new naming scheme (idc_rdma -> iidc_rdma)
> * The idpf patches are submitted separately from the ice and
> irdma changes.
> 
> At [3]:
> * Reduce required minimum RDMA vectors to 2
> 
> At [2]:
> * RDMA vector number adjustment
> * Fix unplugging vport auxiliary device twice
> * General cleanup and minor improvements
> 
> [1] https://lore.kernel.org/all/20240724233917.704-1-tatyana.e.nikolova@intel.com/
> [2] https://lore.kernel.org/all/20240824031924.421-1-tatyana.e.nikolova@intel.com/
> [3] https://lore.kernel.org/all/20250207194931.1569-1-tatyana.e.nikolova@intel.com/
> [4] https://lore.kernel.org/all/20250523170435.668-1-tatyana.e.nikolova@intel.com/
> 
> Joshua Hay (6):
>    idpf: use reserved RDMA vectors from control plane
>    idpf: implement core RDMA auxiliary dev create, init, and destroy
>    idpf: implement RDMA vport auxiliary dev create, init, and destroy
>    idpf: implement remaining IDC RDMA core callbacks and handlers
>    idpf: implement IDC vport aux driver MTU change handler
>    idpf: implement get LAN MMIO memory regions
> 
>   drivers/net/ethernet/intel/idpf/Makefile      |   1 +
>   drivers/net/ethernet/intel/idpf/idpf.h        | 117 ++++-
>   .../net/ethernet/intel/idpf/idpf_controlq.c   |  14 +-
>   .../net/ethernet/intel/idpf/idpf_controlq.h   |  19 +-
>   drivers/net/ethernet/intel/idpf/idpf_dev.c    |  49 +-
>   drivers/net/ethernet/intel/idpf/idpf_idc.c    | 497 ++++++++++++++++++
>   drivers/net/ethernet/intel/idpf/idpf_lib.c    | 102 +++-
>   drivers/net/ethernet/intel/idpf/idpf_main.c   |  32 +-
>   drivers/net/ethernet/intel/idpf/idpf_mem.h    |   8 +-
>   drivers/net/ethernet/intel/idpf/idpf_txrx.h   |   1 +
>   drivers/net/ethernet/intel/idpf/idpf_vf_dev.c |  45 +-
>   .../net/ethernet/intel/idpf/idpf_virtchnl.c   | 190 ++++++-
>   .../net/ethernet/intel/idpf/idpf_virtchnl.h   |   3 +
>   drivers/net/ethernet/intel/idpf/virtchnl2.h   |  42 +-
>   include/linux/net/intel/iidc_rdma_idpf.h      |  55 ++
>   15 files changed, 1102 insertions(+), 73 deletions(-)
>   create mode 100644 drivers/net/ethernet/intel/idpf/idpf_idc.c
>   create mode 100644 include/linux/net/intel/iidc_rdma_idpf.h


Kind regards,

Paul

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf
  2025-06-13  7:21 ` [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Paul Menzel
@ 2025-07-08 20:40   ` Nikolova, Tatyana E
  0 siblings, 0 replies; 11+ messages in thread
From: Nikolova, Tatyana E @ 2025-07-08 20:40 UTC (permalink / raw)
  To: Paul Menzel
  Cc: intel-wired-lan@lists.osuosl.org, jgg@nvidia.com, leon@kernel.org,
	linux-rdma@vger.kernel.org, netdev@vger.kernel.org,
	kuba@kernel.org



> -----Original Message-----
> From: Paul Menzel <pmenzel@molgen.mpg.de>
> Sent: Friday, June 13, 2025 2:21 AM
> To: Nikolova, Tatyana E <tatyana.e.nikolova@intel.com>
> Cc: intel-wired-lan@lists.osuosl.org; jgg@nvidia.com; leon@kernel.org; linux-
> rdma@vger.kernel.org; netdev@vger.kernel.org; kuba@kernel.org
> Subject: Re: [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU
> E2000 in idpf
> 
> Dear Tatyana,
> 
> 
> Thank you for this patch series.
Thank you for reviewing it.

> 
> 
> Am 12.06.25 um 23:59 schrieb Tatyana Nikolova:
> > This idpf patch series is the second part of the staged submission for
> > introducing RDMA RoCEv2 support for the IPU E2000 line of products,
> > referred to as GEN3.
> >
> > To support RDMA GEN3 devices, the idpf driver uses common definitions
> > of the IIDC interface and implements specific device functionality in
> > iidc_rdma_idpf.h.
> 
> This could be re-flowed for longer lines.
Okay.

> 
> > The IPU model can host one or more logical network endpoints called
> > vPorts per PCI function that are flexibly associated with a physical
> > port or an internal communication port.
> >
> > Other features as it pertains to GEN3 devices include:
> > * MMIO learning
> > * RDMA capability negotiation
> > * RDMA vectors discovery between idpf and control plane
> >
> > These patches are split from the submission "Add RDMA support for
> > Intel IPU E2000 (GEN3)" [1] and are based on 6.16-rc1. A shared pull
> > request for net-next and rdma-next will be sent following review.
> 
> Still mention the datasheet?
Intel has not published the E2000 datasheet at this time.

> 
> Also, it’d be great to have a paragraph on how this was tested.
Will add.

> 
> > Changelog:
> >
> > v2:
> > * Minor improvements like variable rename, logging, remove a redundant
> > variable, etc.
> > * A couple of cdev_info fixes to properly free it in error path and
> > not to dereference it before NULL check.
> >
> > Changes since split (v1) at [4]:
> > * Replace core dev_ops with exported symbols
> > * Align with new header split scheme (iidc_rdma.h common header and
> > iidc_rdma_idpf.h specific header)
> > * Align with new naming scheme (idc_rdma -> iidc_rdma)
> > * The idpf patches are submitted separately from the ice and irdma
> > changes.
> >
> > At [3]:
> > * Reduce required minimum RDMA vectors to 2
> >
> > At [2]:
> > * RDMA vector number adjustment
> > * Fix unplugging vport auxiliary device twice
> > * General cleanup and minor improvements
> >
> > [1]
> > https://lore.kernel.org/all/20240724233917.704-1-tatyana.e.nikolova@in
> > tel.com/ [2]
> > https://lore.kernel.org/all/20240824031924.421-1-tatyana.e.nikolova@in
> > tel.com/ [3]
> > https://lore.kernel.org/all/20250207194931.1569-1-tatyana.e.nikolova@i
> > ntel.com/ [4]
> > https://lore.kernel.org/all/20250523170435.668-1-tatyana.e.nikolova@in
> > tel.com/
> >
> > Joshua Hay (6):
> >    idpf: use reserved RDMA vectors from control plane
> >    idpf: implement core RDMA auxiliary dev create, init, and destroy
> >    idpf: implement RDMA vport auxiliary dev create, init, and destroy
> >    idpf: implement remaining IDC RDMA core callbacks and handlers
> >    idpf: implement IDC vport aux driver MTU change handler
> >    idpf: implement get LAN MMIO memory regions
> >
> >   drivers/net/ethernet/intel/idpf/Makefile      |   1 +
> >   drivers/net/ethernet/intel/idpf/idpf.h        | 117 ++++-
> >   .../net/ethernet/intel/idpf/idpf_controlq.c   |  14 +-
> >   .../net/ethernet/intel/idpf/idpf_controlq.h   |  19 +-
> >   drivers/net/ethernet/intel/idpf/idpf_dev.c    |  49 +-
> >   drivers/net/ethernet/intel/idpf/idpf_idc.c    | 497 ++++++++++++++++++
> >   drivers/net/ethernet/intel/idpf/idpf_lib.c    | 102 +++-
> >   drivers/net/ethernet/intel/idpf/idpf_main.c   |  32 +-
> >   drivers/net/ethernet/intel/idpf/idpf_mem.h    |   8 +-
> >   drivers/net/ethernet/intel/idpf/idpf_txrx.h   |   1 +
> >   drivers/net/ethernet/intel/idpf/idpf_vf_dev.c |  45 +-
> >   .../net/ethernet/intel/idpf/idpf_virtchnl.c   | 190 ++++++-
> >   .../net/ethernet/intel/idpf/idpf_virtchnl.h   |   3 +
> >   drivers/net/ethernet/intel/idpf/virtchnl2.h   |  42 +-
> >   include/linux/net/intel/iidc_rdma_idpf.h      |  55 ++
> >   15 files changed, 1102 insertions(+), 73 deletions(-)
> >   create mode 100644 drivers/net/ethernet/intel/idpf/idpf_idc.c
> >   create mode 100644 include/linux/net/intel/iidc_rdma_idpf.h
> 
> 
> Kind regards,
> 
> Paul

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Intel-wired-lan] [iwl-next v2 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy
  2025-06-12 21:59 ` [Intel-wired-lan] [iwl-next v2 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy Tatyana Nikolova
@ 2025-08-06 12:02   ` Larysa Zaremba
  2025-08-08 17:06     ` Hay, Joshua A
  0 siblings, 1 reply; 11+ messages in thread
From: Larysa Zaremba @ 2025-08-06 12:02 UTC (permalink / raw)
  To: Tatyana Nikolova, anthony.l.nguyen
  Cc: intel-wired-lan, jgg, leon, linux-rdma, netdev, kuba, Joshua Hay

On Thu, Jun 12, 2025 at 04:59:58PM -0500, Tatyana Nikolova wrote:
> From: Joshua Hay <joshua.a.hay@intel.com>
> 
> Add the initial idpf_idc.c file with the functions to kick off the IDC
> initialization, create and initialize a core RDMA auxiliary device, and
> destroy said device.
> 
> The RDMA core has a dependency on the vports being created by the
> control plane before it can be initialized. Therefore, once all the
> vports are up after a hard reset (either during driver load a function
> level reset), the core RDMA device info will be created. It is populated
> with the function type (as distinguished by the IDC initialization
> function pointer), the core idc_ops function points (just stubs for
> now), the reserved RDMA MSIX table, and various other info the core RDMA
> auxiliary driver will need. It is then plugged on to the bus.
> 
> During a function level reset or driver unload, the device will be
> unplugged from the bus and destroyed.

Hello,

I am developing some changes using the current dev-queue and have noticed the 
following KASAN warning when doing rmmod idpf without any of my changes on top.

[  +6.231036] ==================================================================
[  +0.000065] BUG: KASAN: slab-use-after-free in idpf_idc_deinit_core_aux_device+0xf5/0x110 [idpf]
[  +0.000059] Read of size 4 at addr ff11001086758ae8 by task rmmod/2025

[  +0.000046] CPU: 40 UID: 0 PID: 2025 Comm: rmmod Not tainted 6.16.0-korg-netnext-standard+ #30 PREEMPT(full)
[  +0.000010] Hardware name: Intel Corporation M50CYP2SBSTD/M50CYP2SBSTD, BIOS SE5C620.86B.01.01.0008.2305172341 05/17/2023
[  +0.000005] Call Trace:
[  +0.000003]  <TASK>
[  +0.000003]  dump_stack_lvl+0x5f/0x80
[  +0.000016]  print_report+0xd1/0x640
[  +0.000014]  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
[  +0.000012]  ? kasan_complete_mode_report_info+0x64/0x200
[  +0.000009]  kasan_report+0xe5/0x120
[  +0.000007]  ? idpf_idc_deinit_core_aux_device+0xf5/0x110 [idpf]
[  +0.000017]  ? idpf_idc_deinit_core_aux_device+0xf5/0x110 [idpf]
[  +0.000016]  __asan_report_load4_noabort+0x18/0x20
[  +0.000010]  idpf_idc_deinit_core_aux_device+0xf5/0x110 [idpf]
[  +0.000014]  idpf_vc_core_deinit+0xbf/0x3a0 [idpf]
[  +0.000019]  idpf_remove+0xb0/0x7f0 [idpf]
[  +0.000017]  ? __kasan_check_write+0x18/0x20
[  +0.000009]  pci_device_remove+0xad/0x1d0
[  +0.000013]  device_remove+0xc4/0x170
[  +0.000012]  device_release_driver_internal+0x37e/0x540
[  +0.000011]  driver_detach+0xc7/0x1a0
[  +0.000008]  bus_remove_driver+0x127/0x2a0
[  +0.000008]  driver_unregister+0x71/0xa0
[  +0.000008]  pci_unregister_driver+0x2d/0x250
[  +0.000009]  idpf_driver_exit+0x14/0xe60 [idpf]
[  +0.000014]  __do_sys_delete_module.isra.0+0x2b7/0x500
[  +0.000012]  ? __pfx___do_sys_delete_module.isra.0+0x10/0x10
[  +0.000011]  __x64_sys_delete_module+0x35/0x50
[  +0.000008]  x64_sys_call+0x5c3/0x20d0
[  +0.000011]  do_syscall_64+0x7a/0x320
[  +0.000008]  ? clear_bhb_loop+0x60/0xb0
[  +0.000006]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[  +0.000006] RIP: 0033:0x7f6c41b34abb
[  +0.000015] Code: 73 01 c3 48 8b 0d 55 13 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 b0 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 25 13 0c 00 f7 d8 64 89 01 48
[  +0.000006] RSP: 002b:00007ffe4797b118 EFLAGS: 00000206 ORIG_RAX: 00000000000000b0
[  +0.000010] RAX: ffffffffffffffda RBX: 000055cbd564f700 RCX: 00007f6c41b34abb
[  +0.000005] RDX: 0000000000000000 RSI: 0000000000000800 RDI: 000055cbd564f768
[  +0.000004] RBP: 00007ffe4797b140 R08: 1999999999999999 R09: 0000000000000000
[  +0.000005] R10: 00007f6c41ba5ac0 R11: 0000000000000206 R12: 0000000000000000
[  +0.000004] R13: 00007ffe4797b3a0 R14: 000055cbd564f700 R15: 0000000000000000
[  +0.000007]  </TASK>

[  +0.008179] Allocated by task 416:
[  +0.001205]  kasan_save_stack+0x3d/0x60
[  +0.000021]  kasan_save_track+0x18/0x40
[  +0.000011]  kasan_save_alloc_info+0x3b/0x50
[  +0.000013]  __kasan_kmalloc+0xb7/0xc0
[  +0.000010]  __kmalloc_cache_noprof+0x1ca/0x450
[  +0.000016]  idpf_idc_init_aux_core_dev+0x4f9/0xc80 [idpf]
[  +0.000027]  idpf_idc_register+0x14/0x20 [idpf]
[  +0.000025]  idpf_idc_init+0x5c/0xd0 [idpf]
[  +0.000025]  idpf_vc_event_task+0x658/0xdd0 [idpf]
[  +0.000026]  process_one_work+0x67b/0x1030
[  +0.000014]  worker_thread+0x65b/0xf40
[  +0.000009]  kthread+0x3a3/0x860
[  +0.000010]  ret_from_fork+0x24c/0x420
[  +0.000016]  ret_from_fork_asm+0x1a/0x30

[  +0.001183] Freed by task 2025:
[  +0.001070]  kasan_save_stack+0x3d/0x60
[  +0.000010]  kasan_save_track+0x18/0x40
[  +0.000007]  kasan_save_free_info+0x3f/0x60
[  +0.000008]  __kasan_slab_free+0x56/0x70
[  +0.000007]  kfree+0x12a/0x3d0
[  +0.000010]  idpf_core_adev_release+0x12/0x20 [idpf]
[  +0.000017]  device_release+0xa1/0x220
[  +0.000010]  kobject_put+0x18e/0x4f0
[  +0.000013]  put_device+0x17/0x30
[  +0.000006]  idpf_idc_deinit_core_aux_device+0x54/0x110 [idpf]
[  +0.000016]  idpf_vc_core_deinit+0xbf/0x3a0 [idpf]
[  +0.000018]  idpf_remove+0xb0/0x7f0 [idpf]
[  +0.000017]  pci_device_remove+0xad/0x1d0
[  +0.000011]  device_remove+0xc4/0x170
[  +0.000010]  device_release_driver_internal+0x37e/0x540
[  +0.000009]  driver_detach+0xc7/0x1a0
[  +0.000007]  bus_remove_driver+0x127/0x2a0
[  +0.000007]  driver_unregister+0x71/0xa0
[  +0.000008]  pci_unregister_driver+0x2d/0x250
[  +0.000008]  idpf_driver_exit+0x14/0xe60 [idpf]
[  +0.000017]  __do_sys_delete_module.isra.0+0x2b7/0x500
[  +0.000012]  __x64_sys_delete_module+0x35/0x50
[  +0.000008]  x64_sys_call+0x5c3/0x20d0
[  +0.000010]  do_syscall_64+0x7a/0x320
[  +0.000010]  entry_SYSCALL_64_after_hwframe+0x76/0x7e

[  +0.000749] The buggy address belongs to the object at ff11001086758800
               which belongs to the cache kmalloc-1k of size 1024
[  +0.001509] The buggy address is located 744 bytes inside of
               freed 1024-byte region [ff11001086758800, ff11001086758c00)

[  +0.002163] The buggy address belongs to the physical page:
[  +0.000739] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x1086758
[  +0.000010] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[  +0.000006] flags: 0x6fffc0000000040(head|node=1|zone=2|lastcpupid=0x3fff)
[  +0.000009] page_type: f5(slab)
[  +0.000009] raw: 06fffc0000000040 ff11000100038dc0 dead000000000122 0000000000000000
[  +0.000007] raw: 0000000000000000 0000000080100010 00000000f5000000 0000000000000000
[  +0.000006] head: 06fffc0000000040 ff11000100038dc0 dead000000000122 0000000000000000
[  +0.000006] head: 0000000000000000 0000000080100010 00000000f5000000 0000000000000000
[  +0.000006] head: 06fffc0000000003 ffd400004219d601 00000000ffffffff 00000000ffffffff
[  +0.000006] head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000008
[  +0.000004] page dumped because: kasan: bad access detected

[  +0.000732] Memory state around the buggy address:
[  +0.000744]  ff11001086758980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  +0.000764]  ff11001086758a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  +0.000750] >ff11001086758a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  +0.000735]                                                           ^
[  +0.000756]  ff11001086758b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  +0.000641]  ff11001086758b80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[  +0.000513] ==================================================================
[  +0.001104] Disabling lock debugging due to kernel taint

> 
> Reviewed-by: Madhu Chittim <madhu.chittim@intel.com>
> Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
> Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
> ---
> 
> v2:
> - initialize cdev_info earlier to properly free it in error path
> 
> Changes since split (v1):
> - replace core dev_ops with exported symbols
> - align with new header split scheme (idc_rdma->iidc_rdma and
>   iidc_rdma_idpf specific header)
> 
> [3]:
> - use signed ret value from ida_alloc and only assign
>   unsigned id if no err
> - capitalize some abbreviations
> - add missing field descriptions
> 
>  drivers/net/ethernet/intel/idpf/Makefile      |   1 +
>  drivers/net/ethernet/intel/idpf/idpf.h        |  11 +
>  drivers/net/ethernet/intel/idpf/idpf_dev.c    |  13 +
>  drivers/net/ethernet/intel/idpf/idpf_idc.c    | 223 ++++++++++++++++++
>  drivers/net/ethernet/intel/idpf/idpf_lib.c    |   4 +
>  drivers/net/ethernet/intel/idpf/idpf_vf_dev.c |  13 +
>  .../net/ethernet/intel/idpf/idpf_virtchnl.c   |  20 ++
>  .../net/ethernet/intel/idpf/idpf_virtchnl.h   |   3 +
>  include/linux/net/intel/iidc_rdma_idpf.h      |  28 +++
>  9 files changed, 316 insertions(+)
>  create mode 100644 drivers/net/ethernet/intel/idpf/idpf_idc.c
>  create mode 100644 include/linux/net/intel/iidc_rdma_idpf.h
> 
> diff --git a/drivers/net/ethernet/intel/idpf/Makefile b/drivers/net/ethernet/intel/idpf/Makefile
> index 83ac5e296382..4ef4b2b5e37a 100644
> --- a/drivers/net/ethernet/intel/idpf/Makefile
> +++ b/drivers/net/ethernet/intel/idpf/Makefile
> @@ -10,6 +10,7 @@ idpf-y := \
>  	idpf_controlq_setup.o	\
>  	idpf_dev.o		\
>  	idpf_ethtool.o		\
> +	idpf_idc.o		\
>  	idpf_lib.o		\
>  	idpf_main.o		\
>  	idpf_txrx.o		\
> diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
> index d9f06764aba0..6b1cc55e34a3 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf.h
> +++ b/drivers/net/ethernet/intel/idpf/idpf.h
> @@ -17,6 +17,8 @@ struct idpf_vport_max_q;
>  #include <linux/sctp.h>
>  #include <linux/ethtool_netlink.h>
>  #include <net/gro.h>
> +#include <linux/net/intel/iidc_rdma.h>
> +#include <linux/net/intel/iidc_rdma_idpf.h>
>  
>  #include "virtchnl2.h"
>  #include "idpf_txrx.h"
> @@ -206,9 +208,12 @@ struct idpf_reg_ops {
>  /**
>   * struct idpf_dev_ops - Device specific operations
>   * @reg_ops: Register operations
> + * @idc_init: IDC initialization
>   */
>  struct idpf_dev_ops {
>  	struct idpf_reg_ops reg_ops;
> +
> +	int (*idc_init)(struct idpf_adapter *adapter);
>  };
>  
>  /**
> @@ -540,6 +545,7 @@ struct idpf_vc_xn_manager;
>   * @caps: Negotiated capabilities with device
>   * @vcxn_mngr: Virtchnl transaction manager
>   * @dev_ops: See idpf_dev_ops
> + * @cdev_info: IDC core device info pointer
>   * @num_vfs: Number of allocated VFs through sysfs. PF does not directly talk
>   *	     to VFs but is used to initialize them
>   * @crc_enable: Enable CRC insertion offload
> @@ -599,6 +605,7 @@ struct idpf_adapter {
>  	struct idpf_vc_xn_manager *vcxn_mngr;
>  
>  	struct idpf_dev_ops dev_ops;
> +	struct iidc_rdma_core_dev_info *cdev_info;
>  	int num_vfs;
>  	bool crc_enable;
>  	bool req_tx_splitq;
> @@ -877,5 +884,9 @@ int idpf_sriov_configure(struct pci_dev *pdev, int num_vfs);
>  
>  u8 idpf_vport_get_hsplit(const struct idpf_vport *vport);
>  bool idpf_vport_set_hsplit(const struct idpf_vport *vport, u8 val);
> +int idpf_idc_init(struct idpf_adapter *adapter);
> +int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
> +			       enum iidc_function_type ftype);
> +void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info);
>  
>  #endif /* !_IDPF_H_ */
> diff --git a/drivers/net/ethernet/intel/idpf/idpf_dev.c b/drivers/net/ethernet/intel/idpf/idpf_dev.c
> index 3fae81f1f988..dd227a4368fb 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_dev.c
> +++ b/drivers/net/ethernet/intel/idpf/idpf_dev.c
> @@ -161,6 +161,17 @@ static void idpf_ptp_reg_init(const struct idpf_adapter *adapter)
>  	adapter->ptp->cmd.exec_cmd_mask = PF_GLTSYN_CMD_SYNC_EXEC_CMD_M;
>  }
>  
> +/**
> + * idpf_idc_register - register for IDC callbacks
> + * @adapter: Driver specific private structure
> + *
> + * Return: 0 on success or error code on failure.
> + */
> +static int idpf_idc_register(struct idpf_adapter *adapter)
> +{
> +	return idpf_idc_init_aux_core_dev(adapter, IIDC_FUNCTION_TYPE_PF);
> +}
> +
>  /**
>   * idpf_reg_ops_init - Initialize register API function pointers
>   * @adapter: Driver specific private structure
> @@ -182,4 +193,6 @@ static void idpf_reg_ops_init(struct idpf_adapter *adapter)
>  void idpf_dev_ops_init(struct idpf_adapter *adapter)
>  {
>  	idpf_reg_ops_init(adapter);
> +
> +	adapter->dev_ops.idc_init = idpf_idc_register;
>  }
> diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c b/drivers/net/ethernet/intel/idpf/idpf_idc.c
> new file mode 100644
> index 000000000000..5550802a3a7d
> --- /dev/null
> +++ b/drivers/net/ethernet/intel/idpf/idpf_idc.c
> @@ -0,0 +1,223 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright (C) 2025 Intel Corporation */
> +
> +#include "idpf.h"
> +#include "idpf_virtchnl.h"
> +
> +static DEFINE_IDA(idpf_idc_ida);
> +
> +#define IDPF_IDC_MAX_ADEV_NAME_LEN	15
> +
> +/**
> + * idpf_idc_init - Called to initialize IDC
> + * @adapter: driver private data structure
> + *
> + * Return: 0 on success or cap not enabled, error code on failure.
> + */
> +int idpf_idc_init(struct idpf_adapter *adapter)
> +{
> +	int err;
> +
> +	if (!idpf_is_rdma_cap_ena(adapter) ||
> +	    !adapter->dev_ops.idc_init)
> +		return 0;
> +
> +	err = adapter->dev_ops.idc_init(adapter);
> +	if (err)
> +		dev_err(&adapter->pdev->dev, "failed to initialize idc: %d\n",
> +			err);
> +
> +	return err;
> +}
> +
> +/**
> + * idpf_core_adev_release - function to be mapped to aux dev's release op
> + * @dev: pointer to device to free
> + */
> +static void idpf_core_adev_release(struct device *dev)
> +{
> +	struct iidc_rdma_core_auxiliary_dev *iadev;
> +
> +	iadev = container_of(dev, struct iidc_rdma_core_auxiliary_dev, adev.dev);
> +	kfree(iadev);
> +	iadev = NULL;
> +}
> +
> +/* idpf_plug_core_aux_dev - allocate and register an Auxiliary device
> + * @cdev_info: IDC core device info pointer
> + *
> + * Return: 0 on success or error code on failure.
> + */
> +static int idpf_plug_core_aux_dev(struct iidc_rdma_core_dev_info *cdev_info)
> +{
> +	struct iidc_rdma_core_auxiliary_dev *iadev;
> +	char name[IDPF_IDC_MAX_ADEV_NAME_LEN];
> +	struct auxiliary_device *adev;
> +	int ret;
> +
> +	iadev = kzalloc(sizeof(*iadev), GFP_KERNEL);
> +	if (!iadev)
> +		return -ENOMEM;
> +
> +	adev = &iadev->adev;
> +	cdev_info->adev = adev;
> +	iadev->cdev_info = cdev_info;
> +
> +	ret = ida_alloc(&idpf_idc_ida, GFP_KERNEL);
> +	if (ret < 0) {
> +		pr_err("failed to allocate unique device ID for Auxiliary driver\n");
> +		goto err_ida_alloc;
> +	}
> +	adev->id = ret;
> +	adev->dev.release = idpf_core_adev_release;
> +	adev->dev.parent = &cdev_info->pdev->dev;
> +	sprintf(name, "%04x.rdma.core", cdev_info->pdev->vendor);
> +	adev->name = name;
> +
> +	ret = auxiliary_device_init(adev);
> +	if (ret)
> +		goto err_aux_dev_init;
> +
> +	ret = auxiliary_device_add(adev);
> +	if (ret)
> +		goto err_aux_dev_add;
> +
> +	return 0;
> +
> +err_aux_dev_add:
> +	cdev_info->adev = NULL;
> +	auxiliary_device_uninit(adev);
> +err_aux_dev_init:
> +	ida_free(&idpf_idc_ida, adev->id);
> +err_ida_alloc:
> +	kfree(iadev);
> +
> +	return ret;
> +}
> +
> +/* idpf_unplug_aux_dev - unregister and free an Auxiliary device
> + * @adev: auxiliary device struct
> + */
> +static void idpf_unplug_aux_dev(struct auxiliary_device *adev)
> +{
> +	auxiliary_device_delete(adev);
> +	auxiliary_device_uninit(adev);
> +
> +	ida_free(&idpf_idc_ida, adev->id);
> +}
> +
> +/**
> + * idpf_idc_vport_dev_ctrl - Called by an Auxiliary Driver
> + * @cdev_info: IDC core device info pointer
> + * @up: RDMA core driver status
> + *
> + * This callback function is accessed by an Auxiliary Driver to indicate
> + * whether core driver is ready to support vport driver load or if vport
> + * drivers need to be taken down.
> + *
> + * Return: 0 on success or error code on failure.
> + */
> +int idpf_idc_vport_dev_ctrl(struct iidc_rdma_core_dev_info *cdev_info, bool up)
> +{
> +	return -EOPNOTSUPP;
> +}
> +EXPORT_SYMBOL_GPL(idpf_idc_vport_dev_ctrl);
> +
> +/**
> + * idpf_idc_request_reset - Called by an Auxiliary Driver
> + * @cdev_info: IDC core device info pointer
> + * @reset_type: function, core or other
> + *
> + * This callback function is accessed by an Auxiliary Driver to request a reset
> + * on the Auxiliary Device.
> + *
> + * Return: 0 on success or error code on failure.
> + */
> +int idpf_idc_request_reset(struct iidc_rdma_core_dev_info *cdev_info,
> +			   enum iidc_rdma_reset_type __always_unused reset_type)
> +{
> +	return -EOPNOTSUPP;
> +}
> +EXPORT_SYMBOL_GPL(idpf_idc_request_reset);
> +
> +/**
> + * idpf_idc_init_msix_data - initialize MSIX data for the cdev_info structure
> + * @adapter: driver private data structure
> + */
> +static void
> +idpf_idc_init_msix_data(struct idpf_adapter *adapter)
> +{
> +	struct iidc_rdma_core_dev_info *cdev_info;
> +	struct iidc_rdma_priv_dev_info *privd;
> +
> +	if (!adapter->rdma_msix_entries)
> +		return;
> +
> +	cdev_info = adapter->cdev_info;
> +	privd = cdev_info->iidc_priv;
> +
> +	privd->msix_entries = adapter->rdma_msix_entries;
> +	privd->msix_count = adapter->num_rdma_msix_entries;
> +}
> +
> +/**
> + * idpf_idc_init_aux_core_dev - initialize Auxiliary Device(s)
> + * @adapter: driver private data structure
> + * @ftype: PF or VF
> + *
> + * Return: 0 on success or error code on failure.
> + */
> +int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
> +			       enum iidc_function_type ftype)
> +{
> +	struct iidc_rdma_core_dev_info *cdev_info;
> +	struct iidc_rdma_priv_dev_info *privd;
> +	int err;
> +
> +	adapter->cdev_info = kzalloc(sizeof(*cdev_info), GFP_KERNEL);
> +	if (!adapter->cdev_info)
> +		return -ENOMEM;
> +	cdev_info = adapter->cdev_info;
> +
> +	privd = kzalloc(sizeof(*privd), GFP_KERNEL);
> +	if (!privd) {
> +		err = -ENOMEM;
> +		goto err_privd_alloc;
> +	}
> +
> +	cdev_info->iidc_priv = privd;
> +	cdev_info->pdev = adapter->pdev;
> +	cdev_info->rdma_protocol = IIDC_RDMA_PROTOCOL_ROCEV2;
> +	privd->ftype = ftype;
> +
> +	idpf_idc_init_msix_data(adapter);
> +
> +	err = idpf_plug_core_aux_dev(cdev_info);
> +	if (err)
> +		goto err_plug_aux_dev;
> +
> +	return 0;
> +
> +err_plug_aux_dev:
> +	kfree(privd);
> +err_privd_alloc:
> +	kfree(cdev_info);
> +	adapter->cdev_info = NULL;
> +
> +	return err;
> +}
> +
> +/**
> + * idpf_idc_deinit_core_aux_device - de-initialize Auxiliary Device(s)
> + * @cdev_info: IDC core device info pointer
> + */
> +void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info)
> +{
> +	if (!cdev_info)
> +		return;
> +
> +	idpf_unplug_aux_dev(cdev_info->adev);
> +
> +	kfree(cdev_info->iidc_priv);
> +	kfree(cdev_info);
> +}
> diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
> index 71d1577ca9e4..2c9fda5783f8 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
> +++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
> @@ -1834,6 +1834,10 @@ static int idpf_init_hard_reset(struct idpf_adapter *adapter)
>  unlock_mutex:
>  	mutex_unlock(&adapter->vport_ctrl_lock);
>  
> +	/* Wait until all vports are created to init RDMA CORE AUX */
> +	if (!err)
> +		err = idpf_idc_init(adapter);
> +
>  	return err;
>  }
>  
> diff --git a/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c b/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
> index aba828abcb17..2f84bd596ae4 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
> +++ b/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
> @@ -147,6 +147,17 @@ static void idpf_vf_trigger_reset(struct idpf_adapter *adapter,
>  		idpf_send_mb_msg(adapter, VIRTCHNL2_OP_RESET_VF, 0, NULL, 0);
>  }
>  
> +/**
> + * idpf_idc_vf_register - register for IDC callbacks
> + * @adapter: Driver specific private structure
> + *
> + * Return: 0 on success or error code on failure.
> + */
> +static int idpf_idc_vf_register(struct idpf_adapter *adapter)
> +{
> +	return idpf_idc_init_aux_core_dev(adapter, IIDC_FUNCTION_TYPE_VF);
> +}
> +
>  /**
>   * idpf_vf_reg_ops_init - Initialize register API function pointers
>   * @adapter: Driver specific private structure
> @@ -167,4 +178,6 @@ static void idpf_vf_reg_ops_init(struct idpf_adapter *adapter)
>  void idpf_vf_dev_ops_init(struct idpf_adapter *adapter)
>  {
>  	idpf_vf_reg_ops_init(adapter);
> +
> +	adapter->dev_ops.idc_init = idpf_idc_vf_register;
>  }
> diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
> index 24febaaa8fbb..c6fa4644fd3c 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
> +++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
> @@ -868,6 +868,7 @@ static int idpf_send_get_caps_msg(struct idpf_adapter *adapter)
>  
>  	caps.other_caps =
>  		cpu_to_le64(VIRTCHNL2_CAP_SRIOV			|
> +			    VIRTCHNL2_CAP_RDMA                  |
>  			    VIRTCHNL2_CAP_MACFILTER		|
>  			    VIRTCHNL2_CAP_SPLITQ_QSCHED		|
>  			    VIRTCHNL2_CAP_PROMISC		|
> @@ -3070,6 +3071,7 @@ void idpf_vc_core_deinit(struct idpf_adapter *adapter)
>  
>  	idpf_ptp_release(adapter);
>  	idpf_deinit_task(adapter);
> +	idpf_idc_deinit_core_aux_device(adapter->cdev_info);
>  	idpf_intr_rel(adapter);
>  
>  	if (remove_in_prog)
> @@ -3728,3 +3730,21 @@ int idpf_set_promiscuous(struct idpf_adapter *adapter,
>  
>  	return reply_sz < 0 ? reply_sz : 0;
>  }
> +
> +/**
> + * idpf_idc_rdma_vc_send_sync - virtchnl send callback for IDC registered drivers
> + * @cdev_info: IDC core device info pointer
> + * @send_msg: message to send
> + * @msg_size: size of message to send
> + * @recv_msg: message to populate on reception of response
> + * @recv_len: length of message copied into recv_msg or 0 on error
> + *
> + * Return: 0 on success or error code on failure.
> + */
> +int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info *cdev_info,
> +			       u8 *send_msg, u16 msg_size,
> +			       u8 *recv_msg, u16 *recv_len)
> +{
> +	return -EOPNOTSUPP;
> +}
> +EXPORT_SYMBOL_GPL(idpf_idc_rdma_vc_send_sync);
> diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
> index 77578206bada..7bae09483aed 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
> +++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
> @@ -151,5 +151,8 @@ int idpf_send_set_sriov_vfs_msg(struct idpf_adapter *adapter, u16 num_vfs);
>  int idpf_send_get_set_rss_key_msg(struct idpf_vport *vport, bool get);
>  int idpf_send_get_set_rss_lut_msg(struct idpf_vport *vport, bool get);
>  void idpf_vc_xn_shutdown(struct idpf_vc_xn_manager *vcxn_mngr);
> +int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info *cdev_info,
> +			       u8 *send_msg, u16 msg_size,
> +			       u8 *recv_msg, u16 *recv_len);
>  
>  #endif /* _IDPF_VIRTCHNL_H_ */
> diff --git a/include/linux/net/intel/iidc_rdma_idpf.h b/include/linux/net/intel/iidc_rdma_idpf.h
> new file mode 100644
> index 000000000000..f2fe1844f660
> --- /dev/null
> +++ b/include/linux/net/intel/iidc_rdma_idpf.h
> @@ -0,0 +1,28 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Copyright (C) 2025 Intel Corporation. */
> +
> +#ifndef _IIDC_RDMA_IDPF_H_
> +#define _IIDC_RDMA_IDPF_H_
> +
> +#include <linux/auxiliary_bus.h>
> +
> +/* struct to be populated by core LAN PCI driver */
> +enum iidc_function_type {
> +	IIDC_FUNCTION_TYPE_PF,
> +	IIDC_FUNCTION_TYPE_VF,
> +};
> +
> +struct iidc_rdma_priv_dev_info {
> +	struct msix_entry *msix_entries;
> +	u16 msix_count; /* How many vectors are reserved for this device */
> +	enum iidc_function_type ftype;
> +};
> +
> +int idpf_idc_vport_dev_ctrl(struct iidc_rdma_core_dev_info *cdev_info, bool up);
> +int idpf_idc_request_reset(struct iidc_rdma_core_dev_info *cdev_info,
> +			   enum iidc_rdma_reset_type __always_unused reset_type);
> +int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info *cdev_info,
> +			       u8 *send_msg, u16 msg_size,
> +			       u8 *recv_msg, u16 *recv_len);
> +
> +#endif /* _IIDC_RDMA_IDPF_H_ */
> -- 
> 2.31.1
> 
> 

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [Intel-wired-lan] [iwl-next v2 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy
  2025-08-06 12:02   ` Larysa Zaremba
@ 2025-08-08 17:06     ` Hay, Joshua A
  0 siblings, 0 replies; 11+ messages in thread
From: Hay, Joshua A @ 2025-08-08 17:06 UTC (permalink / raw)
  To: Zaremba, Larysa, Nikolova, Tatyana E, Nguyen, Anthony L
  Cc: intel-wired-lan@lists.osuosl.org, jgg@nvidia.com, leon@kernel.org,
	linux-rdma@vger.kernel.org, netdev@vger.kernel.org,
	kuba@kernel.org

> Hello,
> 
> I am developing some changes using the current dev-queue and have noticed
> the
> following KASAN warning when doing rmmod idpf without any of my changes
> on top.

Hi Larysa,

Thanks for finding this. I have a fix and will send it out as soon as it passes internal review.

Josh 
> 
> [  +6.231036]
> ==================================================================
> [  +0.000065] BUG: KASAN: slab-use-after-free in
> idpf_idc_deinit_core_aux_device+0xf5/0x110 [idpf]
> [  +0.000059] Read of size 4 at addr ff11001086758ae8 by task rmmod/2025
> 
> [  +0.000046] CPU: 40 UID: 0 PID: 2025 Comm: rmmod Not tainted 6.16.0-
> korg-netnext-standard+ #30 PREEMPT(full)
> [  +0.000010] Hardware name: Intel Corporation
> M50CYP2SBSTD/M50CYP2SBSTD, BIOS
> SE5C620.86B.01.01.0008.2305172341 05/17/2023
> [  +0.000005] Call Trace:
> [  +0.000003]  <TASK>
> [  +0.000003]  dump_stack_lvl+0x5f/0x80
> [  +0.000016]  print_report+0xd1/0x640
> [  +0.000014]  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
> [  +0.000012]  ? kasan_complete_mode_report_info+0x64/0x200
> [  +0.000009]  kasan_report+0xe5/0x120
> [  +0.000007]  ? idpf_idc_deinit_core_aux_device+0xf5/0x110 [idpf]
> [  +0.000017]  ? idpf_idc_deinit_core_aux_device+0xf5/0x110 [idpf]
> [  +0.000016]  __asan_report_load4_noabort+0x18/0x20
> [  +0.000010]  idpf_idc_deinit_core_aux_device+0xf5/0x110 [idpf]
> [  +0.000014]  idpf_vc_core_deinit+0xbf/0x3a0 [idpf]
> [  +0.000019]  idpf_remove+0xb0/0x7f0 [idpf]
> [  +0.000017]  ? __kasan_check_write+0x18/0x20
> [  +0.000009]  pci_device_remove+0xad/0x1d0
> [  +0.000013]  device_remove+0xc4/0x170
> [  +0.000012]  device_release_driver_internal+0x37e/0x540
> [  +0.000011]  driver_detach+0xc7/0x1a0
> [  +0.000008]  bus_remove_driver+0x127/0x2a0
> [  +0.000008]  driver_unregister+0x71/0xa0
> [  +0.000008]  pci_unregister_driver+0x2d/0x250
> [  +0.000009]  idpf_driver_exit+0x14/0xe60 [idpf]
> [  +0.000014]  __do_sys_delete_module.isra.0+0x2b7/0x500
> [  +0.000012]  ? __pfx___do_sys_delete_module.isra.0+0x10/0x10
> [  +0.000011]  __x64_sys_delete_module+0x35/0x50
> [  +0.000008]  x64_sys_call+0x5c3/0x20d0
> [  +0.000011]  do_syscall_64+0x7a/0x320
> [  +0.000008]  ? clear_bhb_loop+0x60/0xb0
> [  +0.000006]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
> [  +0.000006] RIP: 0033:0x7f6c41b34abb
> [  +0.000015] Code: 73 01 c3 48 8b 0d 55 13 0c 00 f7 d8 64 89 01 48 83 c8 ff
> c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 b0 00 00 00 0f 05 <48> 3d
> 01 f0 ff ff 73 01 c3 48 8b 0d 25 13 0c 00 f7 d8 64 89 01 48
> [  +0.000006] RSP: 002b:00007ffe4797b118 EFLAGS: 00000206 ORIG_RAX:
> 00000000000000b0
> [  +0.000010] RAX: ffffffffffffffda RBX: 000055cbd564f700 RCX:
> 00007f6c41b34abb
> [  +0.000005] RDX: 0000000000000000 RSI: 0000000000000800 RDI:
> 000055cbd564f768
> [  +0.000004] RBP: 00007ffe4797b140 R08: 1999999999999999 R09:
> 0000000000000000
> [  +0.000005] R10: 00007f6c41ba5ac0 R11: 0000000000000206 R12:
> 0000000000000000
> [  +0.000004] R13: 00007ffe4797b3a0 R14: 000055cbd564f700 R15:
> 0000000000000000
> [  +0.000007]  </TASK>
> 
> [  +0.008179] Allocated by task 416:
> [  +0.001205]  kasan_save_stack+0x3d/0x60
> [  +0.000021]  kasan_save_track+0x18/0x40
> [  +0.000011]  kasan_save_alloc_info+0x3b/0x50
> [  +0.000013]  __kasan_kmalloc+0xb7/0xc0
> [  +0.000010]  __kmalloc_cache_noprof+0x1ca/0x450
> [  +0.000016]  idpf_idc_init_aux_core_dev+0x4f9/0xc80 [idpf]
> [  +0.000027]  idpf_idc_register+0x14/0x20 [idpf]
> [  +0.000025]  idpf_idc_init+0x5c/0xd0 [idpf]
> [  +0.000025]  idpf_vc_event_task+0x658/0xdd0 [idpf]
> [  +0.000026]  process_one_work+0x67b/0x1030
> [  +0.000014]  worker_thread+0x65b/0xf40
> [  +0.000009]  kthread+0x3a3/0x860
> [  +0.000010]  ret_from_fork+0x24c/0x420
> [  +0.000016]  ret_from_fork_asm+0x1a/0x30
> 
> [  +0.001183] Freed by task 2025:
> [  +0.001070]  kasan_save_stack+0x3d/0x60
> [  +0.000010]  kasan_save_track+0x18/0x40
> [  +0.000007]  kasan_save_free_info+0x3f/0x60
> [  +0.000008]  __kasan_slab_free+0x56/0x70
> [  +0.000007]  kfree+0x12a/0x3d0
> [  +0.000010]  idpf_core_adev_release+0x12/0x20 [idpf]
> [  +0.000017]  device_release+0xa1/0x220
> [  +0.000010]  kobject_put+0x18e/0x4f0
> [  +0.000013]  put_device+0x17/0x30
> [  +0.000006]  idpf_idc_deinit_core_aux_device+0x54/0x110 [idpf]
> [  +0.000016]  idpf_vc_core_deinit+0xbf/0x3a0 [idpf]
> [  +0.000018]  idpf_remove+0xb0/0x7f0 [idpf]
> [  +0.000017]  pci_device_remove+0xad/0x1d0
> [  +0.000011]  device_remove+0xc4/0x170
> [  +0.000010]  device_release_driver_internal+0x37e/0x540
> [  +0.000009]  driver_detach+0xc7/0x1a0
> [  +0.000007]  bus_remove_driver+0x127/0x2a0
> [  +0.000007]  driver_unregister+0x71/0xa0
> [  +0.000008]  pci_unregister_driver+0x2d/0x250
> [  +0.000008]  idpf_driver_exit+0x14/0xe60 [idpf]
> [  +0.000017]  __do_sys_delete_module.isra.0+0x2b7/0x500
> [  +0.000012]  __x64_sys_delete_module+0x35/0x50
> [  +0.000008]  x64_sys_call+0x5c3/0x20d0
> [  +0.000010]  do_syscall_64+0x7a/0x320
> [  +0.000010]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
> 
> [  +0.000749] The buggy address belongs to the object at ff11001086758800
>                which belongs to the cache kmalloc-1k of size 1024
> [  +0.001509] The buggy address is located 744 bytes inside of
>                freed 1024-byte region [ff11001086758800, ff11001086758c00)
> 
> [  +0.002163] The buggy address belongs to the physical page:
> [  +0.000739] page: refcount:0 mapcount:0 mapping:0000000000000000
> index:0x0 pfn:0x1086758
> [  +0.000010] head: order:3 mapcount:0 entire_mapcount:0
> nr_pages_mapped:0 pincount:0
> [  +0.000006] flags:
> 0x6fffc0000000040(head|node=1|zone=2|lastcpupid=0x3fff)
> [  +0.000009] page_type: f5(slab)
> [  +0.000009] raw: 06fffc0000000040 ff11000100038dc0
> dead000000000122 0000000000000000
> [  +0.000007] raw: 0000000000000000 0000000080100010
> 00000000f5000000 0000000000000000
> [  +0.000006] head: 06fffc0000000040 ff11000100038dc0
> dead000000000122 0000000000000000
> [  +0.000006] head: 0000000000000000 0000000080100010
> 00000000f5000000 0000000000000000
> [  +0.000006] head: 06fffc0000000003 ffd400004219d601 00000000ffffffff
> 00000000ffffffff
> [  +0.000006] head: ffffffffffffffff 0000000000000000 00000000ffffffff
> 0000000000000008
> [  +0.000004] page dumped because: kasan: bad access detected
> 
> [  +0.000732] Memory state around the buggy address:
> [  +0.000744]  ff11001086758980: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> [  +0.000764]  ff11001086758a00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> [  +0.000750] >ff11001086758a80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> [  +0.000735]                                                           ^
> [  +0.000756]  ff11001086758b00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> [  +0.000641]  ff11001086758b80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
> [  +0.000513]
> ==================================================================
> [  +0.001104] Disabling lock debugging due to kernel taint
> 
> >
> > Reviewed-by: Madhu Chittim <madhu.chittim@intel.com>
> > Signed-off-by: Joshua Hay <joshua.a.hay@intel.com>
> > Signed-off-by: Tatyana Nikolova <tatyana.e.nikolova@intel.com>
> > ---
> >
> > v2:
> > - initialize cdev_info earlier to properly free it in error path
> >
> > Changes since split (v1):
> > - replace core dev_ops with exported symbols
> > - align with new header split scheme (idc_rdma->iidc_rdma and
> >   iidc_rdma_idpf specific header)
> >
> > [3]:
> > - use signed ret value from ida_alloc and only assign
> >   unsigned id if no err
> > - capitalize some abbreviations
> > - add missing field descriptions
> >
> >  drivers/net/ethernet/intel/idpf/Makefile      |   1 +
> >  drivers/net/ethernet/intel/idpf/idpf.h        |  11 +
> >  drivers/net/ethernet/intel/idpf/idpf_dev.c    |  13 +
> >  drivers/net/ethernet/intel/idpf/idpf_idc.c    | 223 ++++++++++++++++++
> >  drivers/net/ethernet/intel/idpf/idpf_lib.c    |   4 +
> >  drivers/net/ethernet/intel/idpf/idpf_vf_dev.c |  13 +
> >  .../net/ethernet/intel/idpf/idpf_virtchnl.c   |  20 ++
> >  .../net/ethernet/intel/idpf/idpf_virtchnl.h   |   3 +
> >  include/linux/net/intel/iidc_rdma_idpf.h      |  28 +++
> >  9 files changed, 316 insertions(+)
> >  create mode 100644 drivers/net/ethernet/intel/idpf/idpf_idc.c
> >  create mode 100644 include/linux/net/intel/iidc_rdma_idpf.h
> >
> > diff --git a/drivers/net/ethernet/intel/idpf/Makefile
> b/drivers/net/ethernet/intel/idpf/Makefile
> > index 83ac5e296382..4ef4b2b5e37a 100644
> > --- a/drivers/net/ethernet/intel/idpf/Makefile
> > +++ b/drivers/net/ethernet/intel/idpf/Makefile
> > @@ -10,6 +10,7 @@ idpf-y := \
> >  	idpf_controlq_setup.o	\
> >  	idpf_dev.o		\
> >  	idpf_ethtool.o		\
> > +	idpf_idc.o		\
> >  	idpf_lib.o		\
> >  	idpf_main.o		\
> >  	idpf_txrx.o		\
> > diff --git a/drivers/net/ethernet/intel/idpf/idpf.h
> b/drivers/net/ethernet/intel/idpf/idpf.h
> > index d9f06764aba0..6b1cc55e34a3 100644
> > --- a/drivers/net/ethernet/intel/idpf/idpf.h
> > +++ b/drivers/net/ethernet/intel/idpf/idpf.h
> > @@ -17,6 +17,8 @@ struct idpf_vport_max_q;
> >  #include <linux/sctp.h>
> >  #include <linux/ethtool_netlink.h>
> >  #include <net/gro.h>
> > +#include <linux/net/intel/iidc_rdma.h>
> > +#include <linux/net/intel/iidc_rdma_idpf.h>
> >
> >  #include "virtchnl2.h"
> >  #include "idpf_txrx.h"
> > @@ -206,9 +208,12 @@ struct idpf_reg_ops {
> >  /**
> >   * struct idpf_dev_ops - Device specific operations
> >   * @reg_ops: Register operations
> > + * @idc_init: IDC initialization
> >   */
> >  struct idpf_dev_ops {
> >  	struct idpf_reg_ops reg_ops;
> > +
> > +	int (*idc_init)(struct idpf_adapter *adapter);
> >  };
> >
> >  /**
> > @@ -540,6 +545,7 @@ struct idpf_vc_xn_manager;
> >   * @caps: Negotiated capabilities with device
> >   * @vcxn_mngr: Virtchnl transaction manager
> >   * @dev_ops: See idpf_dev_ops
> > + * @cdev_info: IDC core device info pointer
> >   * @num_vfs: Number of allocated VFs through sysfs. PF does not directly
> talk
> >   *	     to VFs but is used to initialize them
> >   * @crc_enable: Enable CRC insertion offload
> > @@ -599,6 +605,7 @@ struct idpf_adapter {
> >  	struct idpf_vc_xn_manager *vcxn_mngr;
> >
> >  	struct idpf_dev_ops dev_ops;
> > +	struct iidc_rdma_core_dev_info *cdev_info;
> >  	int num_vfs;
> >  	bool crc_enable;
> >  	bool req_tx_splitq;
> > @@ -877,5 +884,9 @@ int idpf_sriov_configure(struct pci_dev *pdev, int
> num_vfs);
> >
> >  u8 idpf_vport_get_hsplit(const struct idpf_vport *vport);
> >  bool idpf_vport_set_hsplit(const struct idpf_vport *vport, u8 val);
> > +int idpf_idc_init(struct idpf_adapter *adapter);
> > +int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
> > +			       enum iidc_function_type ftype);
> > +void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info
> *cdev_info);
> >
> >  #endif /* !_IDPF_H_ */
> > diff --git a/drivers/net/ethernet/intel/idpf/idpf_dev.c
> b/drivers/net/ethernet/intel/idpf/idpf_dev.c
> > index 3fae81f1f988..dd227a4368fb 100644
> > --- a/drivers/net/ethernet/intel/idpf/idpf_dev.c
> > +++ b/drivers/net/ethernet/intel/idpf/idpf_dev.c
> > @@ -161,6 +161,17 @@ static void idpf_ptp_reg_init(const struct
> idpf_adapter *adapter)
> >  	adapter->ptp->cmd.exec_cmd_mask =
> PF_GLTSYN_CMD_SYNC_EXEC_CMD_M;
> >  }
> >
> > +/**
> > + * idpf_idc_register - register for IDC callbacks
> > + * @adapter: Driver specific private structure
> > + *
> > + * Return: 0 on success or error code on failure.
> > + */
> > +static int idpf_idc_register(struct idpf_adapter *adapter)
> > +{
> > +	return idpf_idc_init_aux_core_dev(adapter,
> IIDC_FUNCTION_TYPE_PF);
> > +}
> > +
> >  /**
> >   * idpf_reg_ops_init - Initialize register API function pointers
> >   * @adapter: Driver specific private structure
> > @@ -182,4 +193,6 @@ static void idpf_reg_ops_init(struct idpf_adapter
> *adapter)
> >  void idpf_dev_ops_init(struct idpf_adapter *adapter)
> >  {
> >  	idpf_reg_ops_init(adapter);
> > +
> > +	adapter->dev_ops.idc_init = idpf_idc_register;
> >  }
> > diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c
> b/drivers/net/ethernet/intel/idpf/idpf_idc.c
> > new file mode 100644
> > index 000000000000..5550802a3a7d
> > --- /dev/null
> > +++ b/drivers/net/ethernet/intel/idpf/idpf_idc.c
> > @@ -0,0 +1,223 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/* Copyright (C) 2025 Intel Corporation */
> > +
> > +#include "idpf.h"
> > +#include "idpf_virtchnl.h"
> > +
> > +static DEFINE_IDA(idpf_idc_ida);
> > +
> > +#define IDPF_IDC_MAX_ADEV_NAME_LEN	15
> > +
> > +/**
> > + * idpf_idc_init - Called to initialize IDC
> > + * @adapter: driver private data structure
> > + *
> > + * Return: 0 on success or cap not enabled, error code on failure.
> > + */
> > +int idpf_idc_init(struct idpf_adapter *adapter)
> > +{
> > +	int err;
> > +
> > +	if (!idpf_is_rdma_cap_ena(adapter) ||
> > +	    !adapter->dev_ops.idc_init)
> > +		return 0;
> > +
> > +	err = adapter->dev_ops.idc_init(adapter);
> > +	if (err)
> > +		dev_err(&adapter->pdev->dev, "failed to initialize idc: %d\n",
> > +			err);
> > +
> > +	return err;
> > +}
> > +
> > +/**
> > + * idpf_core_adev_release - function to be mapped to aux dev's release op
> > + * @dev: pointer to device to free
> > + */
> > +static void idpf_core_adev_release(struct device *dev)
> > +{
> > +	struct iidc_rdma_core_auxiliary_dev *iadev;
> > +
> > +	iadev = container_of(dev, struct iidc_rdma_core_auxiliary_dev,
> adev.dev);
> > +	kfree(iadev);
> > +	iadev = NULL;
> > +}
> > +
> > +/* idpf_plug_core_aux_dev - allocate and register an Auxiliary device
> > + * @cdev_info: IDC core device info pointer
> > + *
> > + * Return: 0 on success or error code on failure.
> > + */
> > +static int idpf_plug_core_aux_dev(struct iidc_rdma_core_dev_info
> *cdev_info)
> > +{
> > +	struct iidc_rdma_core_auxiliary_dev *iadev;
> > +	char name[IDPF_IDC_MAX_ADEV_NAME_LEN];
> > +	struct auxiliary_device *adev;
> > +	int ret;
> > +
> > +	iadev = kzalloc(sizeof(*iadev), GFP_KERNEL);
> > +	if (!iadev)
> > +		return -ENOMEM;
> > +
> > +	adev = &iadev->adev;
> > +	cdev_info->adev = adev;
> > +	iadev->cdev_info = cdev_info;
> > +
> > +	ret = ida_alloc(&idpf_idc_ida, GFP_KERNEL);
> > +	if (ret < 0) {
> > +		pr_err("failed to allocate unique device ID for Auxiliary
> driver\n");
> > +		goto err_ida_alloc;
> > +	}
> > +	adev->id = ret;
> > +	adev->dev.release = idpf_core_adev_release;
> > +	adev->dev.parent = &cdev_info->pdev->dev;
> > +	sprintf(name, "%04x.rdma.core", cdev_info->pdev->vendor);
> > +	adev->name = name;
> > +
> > +	ret = auxiliary_device_init(adev);
> > +	if (ret)
> > +		goto err_aux_dev_init;
> > +
> > +	ret = auxiliary_device_add(adev);
> > +	if (ret)
> > +		goto err_aux_dev_add;
> > +
> > +	return 0;
> > +
> > +err_aux_dev_add:
> > +	cdev_info->adev = NULL;
> > +	auxiliary_device_uninit(adev);
> > +err_aux_dev_init:
> > +	ida_free(&idpf_idc_ida, adev->id);
> > +err_ida_alloc:
> > +	kfree(iadev);
> > +
> > +	return ret;
> > +}
> > +
> > +/* idpf_unplug_aux_dev - unregister and free an Auxiliary device
> > + * @adev: auxiliary device struct
> > + */
> > +static void idpf_unplug_aux_dev(struct auxiliary_device *adev)
> > +{
> > +	auxiliary_device_delete(adev);
> > +	auxiliary_device_uninit(adev);
> > +
> > +	ida_free(&idpf_idc_ida, adev->id);
> > +}
> > +
> > +/**
> > + * idpf_idc_vport_dev_ctrl - Called by an Auxiliary Driver
> > + * @cdev_info: IDC core device info pointer
> > + * @up: RDMA core driver status
> > + *
> > + * This callback function is accessed by an Auxiliary Driver to indicate
> > + * whether core driver is ready to support vport driver load or if vport
> > + * drivers need to be taken down.
> > + *
> > + * Return: 0 on success or error code on failure.
> > + */
> > +int idpf_idc_vport_dev_ctrl(struct iidc_rdma_core_dev_info *cdev_info,
> bool up)
> > +{
> > +	return -EOPNOTSUPP;
> > +}
> > +EXPORT_SYMBOL_GPL(idpf_idc_vport_dev_ctrl);
> > +
> > +/**
> > + * idpf_idc_request_reset - Called by an Auxiliary Driver
> > + * @cdev_info: IDC core device info pointer
> > + * @reset_type: function, core or other
> > + *
> > + * This callback function is accessed by an Auxiliary Driver to request a reset
> > + * on the Auxiliary Device.
> > + *
> > + * Return: 0 on success or error code on failure.
> > + */
> > +int idpf_idc_request_reset(struct iidc_rdma_core_dev_info *cdev_info,
> > +			   enum iidc_rdma_reset_type __always_unused
> reset_type)
> > +{
> > +	return -EOPNOTSUPP;
> > +}
> > +EXPORT_SYMBOL_GPL(idpf_idc_request_reset);
> > +
> > +/**
> > + * idpf_idc_init_msix_data - initialize MSIX data for the cdev_info structure
> > + * @adapter: driver private data structure
> > + */
> > +static void
> > +idpf_idc_init_msix_data(struct idpf_adapter *adapter)
> > +{
> > +	struct iidc_rdma_core_dev_info *cdev_info;
> > +	struct iidc_rdma_priv_dev_info *privd;
> > +
> > +	if (!adapter->rdma_msix_entries)
> > +		return;
> > +
> > +	cdev_info = adapter->cdev_info;
> > +	privd = cdev_info->iidc_priv;
> > +
> > +	privd->msix_entries = adapter->rdma_msix_entries;
> > +	privd->msix_count = adapter->num_rdma_msix_entries;
> > +}
> > +
> > +/**
> > + * idpf_idc_init_aux_core_dev - initialize Auxiliary Device(s)
> > + * @adapter: driver private data structure
> > + * @ftype: PF or VF
> > + *
> > + * Return: 0 on success or error code on failure.
> > + */
> > +int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
> > +			       enum iidc_function_type ftype)
> > +{
> > +	struct iidc_rdma_core_dev_info *cdev_info;
> > +	struct iidc_rdma_priv_dev_info *privd;
> > +	int err;
> > +
> > +	adapter->cdev_info = kzalloc(sizeof(*cdev_info), GFP_KERNEL);
> > +	if (!adapter->cdev_info)
> > +		return -ENOMEM;
> > +	cdev_info = adapter->cdev_info;
> > +
> > +	privd = kzalloc(sizeof(*privd), GFP_KERNEL);
> > +	if (!privd) {
> > +		err = -ENOMEM;
> > +		goto err_privd_alloc;
> > +	}
> > +
> > +	cdev_info->iidc_priv = privd;
> > +	cdev_info->pdev = adapter->pdev;
> > +	cdev_info->rdma_protocol = IIDC_RDMA_PROTOCOL_ROCEV2;
> > +	privd->ftype = ftype;
> > +
> > +	idpf_idc_init_msix_data(adapter);
> > +
> > +	err = idpf_plug_core_aux_dev(cdev_info);
> > +	if (err)
> > +		goto err_plug_aux_dev;
> > +
> > +	return 0;
> > +
> > +err_plug_aux_dev:
> > +	kfree(privd);
> > +err_privd_alloc:
> > +	kfree(cdev_info);
> > +	adapter->cdev_info = NULL;
> > +
> > +	return err;
> > +}
> > +
> > +/**
> > + * idpf_idc_deinit_core_aux_device - de-initialize Auxiliary Device(s)
> > + * @cdev_info: IDC core device info pointer
> > + */
> > +void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info
> *cdev_info)
> > +{
> > +	if (!cdev_info)
> > +		return;
> > +
> > +	idpf_unplug_aux_dev(cdev_info->adev);
> > +
> > +	kfree(cdev_info->iidc_priv);
> > +	kfree(cdev_info);
> > +}
> > diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c
> b/drivers/net/ethernet/intel/idpf/idpf_lib.c
> > index 71d1577ca9e4..2c9fda5783f8 100644
> > --- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
> > +++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
> > @@ -1834,6 +1834,10 @@ static int idpf_init_hard_reset(struct
> idpf_adapter *adapter)
> >  unlock_mutex:
> >  	mutex_unlock(&adapter->vport_ctrl_lock);
> >
> > +	/* Wait until all vports are created to init RDMA CORE AUX */
> > +	if (!err)
> > +		err = idpf_idc_init(adapter);
> > +
> >  	return err;
> >  }
> >
> > diff --git a/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
> b/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
> > index aba828abcb17..2f84bd596ae4 100644
> > --- a/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
> > +++ b/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
> > @@ -147,6 +147,17 @@ static void idpf_vf_trigger_reset(struct
> idpf_adapter *adapter,
> >  		idpf_send_mb_msg(adapter, VIRTCHNL2_OP_RESET_VF, 0,
> NULL, 0);
> >  }
> >
> > +/**
> > + * idpf_idc_vf_register - register for IDC callbacks
> > + * @adapter: Driver specific private structure
> > + *
> > + * Return: 0 on success or error code on failure.
> > + */
> > +static int idpf_idc_vf_register(struct idpf_adapter *adapter)
> > +{
> > +	return idpf_idc_init_aux_core_dev(adapter,
> IIDC_FUNCTION_TYPE_VF);
> > +}
> > +
> >  /**
> >   * idpf_vf_reg_ops_init - Initialize register API function pointers
> >   * @adapter: Driver specific private structure
> > @@ -167,4 +178,6 @@ static void idpf_vf_reg_ops_init(struct idpf_adapter
> *adapter)
> >  void idpf_vf_dev_ops_init(struct idpf_adapter *adapter)
> >  {
> >  	idpf_vf_reg_ops_init(adapter);
> > +
> > +	adapter->dev_ops.idc_init = idpf_idc_vf_register;
> >  }
> > diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
> b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
> > index 24febaaa8fbb..c6fa4644fd3c 100644
> > --- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
> > +++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
> > @@ -868,6 +868,7 @@ static int idpf_send_get_caps_msg(struct
> idpf_adapter *adapter)
> >
> >  	caps.other_caps =
> >  		cpu_to_le64(VIRTCHNL2_CAP_SRIOV			|
> > +			    VIRTCHNL2_CAP_RDMA                  |
> >  			    VIRTCHNL2_CAP_MACFILTER		|
> >  			    VIRTCHNL2_CAP_SPLITQ_QSCHED		|
> >  			    VIRTCHNL2_CAP_PROMISC		|
> > @@ -3070,6 +3071,7 @@ void idpf_vc_core_deinit(struct idpf_adapter
> *adapter)
> >
> >  	idpf_ptp_release(adapter);
> >  	idpf_deinit_task(adapter);
> > +	idpf_idc_deinit_core_aux_device(adapter->cdev_info);
> >  	idpf_intr_rel(adapter);
> >
> >  	if (remove_in_prog)
> > @@ -3728,3 +3730,21 @@ int idpf_set_promiscuous(struct idpf_adapter
> *adapter,
> >
> >  	return reply_sz < 0 ? reply_sz : 0;
> >  }
> > +
> > +/**
> > + * idpf_idc_rdma_vc_send_sync - virtchnl send callback for IDC registered
> drivers
> > + * @cdev_info: IDC core device info pointer
> > + * @send_msg: message to send
> > + * @msg_size: size of message to send
> > + * @recv_msg: message to populate on reception of response
> > + * @recv_len: length of message copied into recv_msg or 0 on error
> > + *
> > + * Return: 0 on success or error code on failure.
> > + */
> > +int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info
> *cdev_info,
> > +			       u8 *send_msg, u16 msg_size,
> > +			       u8 *recv_msg, u16 *recv_len)
> > +{
> > +	return -EOPNOTSUPP;
> > +}
> > +EXPORT_SYMBOL_GPL(idpf_idc_rdma_vc_send_sync);
> > diff --git a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
> b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
> > index 77578206bada..7bae09483aed 100644
> > --- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
> > +++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
> > @@ -151,5 +151,8 @@ int idpf_send_set_sriov_vfs_msg(struct
> idpf_adapter *adapter, u16 num_vfs);
> >  int idpf_send_get_set_rss_key_msg(struct idpf_vport *vport, bool get);
> >  int idpf_send_get_set_rss_lut_msg(struct idpf_vport *vport, bool get);
> >  void idpf_vc_xn_shutdown(struct idpf_vc_xn_manager *vcxn_mngr);
> > +int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info
> *cdev_info,
> > +			       u8 *send_msg, u16 msg_size,
> > +			       u8 *recv_msg, u16 *recv_len);
> >
> >  #endif /* _IDPF_VIRTCHNL_H_ */
> > diff --git a/include/linux/net/intel/iidc_rdma_idpf.h
> b/include/linux/net/intel/iidc_rdma_idpf.h
> > new file mode 100644
> > index 000000000000..f2fe1844f660
> > --- /dev/null
> > +++ b/include/linux/net/intel/iidc_rdma_idpf.h
> > @@ -0,0 +1,28 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/* Copyright (C) 2025 Intel Corporation. */
> > +
> > +#ifndef _IIDC_RDMA_IDPF_H_
> > +#define _IIDC_RDMA_IDPF_H_
> > +
> > +#include <linux/auxiliary_bus.h>
> > +
> > +/* struct to be populated by core LAN PCI driver */
> > +enum iidc_function_type {
> > +	IIDC_FUNCTION_TYPE_PF,
> > +	IIDC_FUNCTION_TYPE_VF,
> > +};
> > +
> > +struct iidc_rdma_priv_dev_info {
> > +	struct msix_entry *msix_entries;
> > +	u16 msix_count; /* How many vectors are reserved for this device */
> > +	enum iidc_function_type ftype;
> > +};
> > +
> > +int idpf_idc_vport_dev_ctrl(struct iidc_rdma_core_dev_info *cdev_info,
> bool up);
> > +int idpf_idc_request_reset(struct iidc_rdma_core_dev_info *cdev_info,
> > +			   enum iidc_rdma_reset_type __always_unused
> reset_type);
> > +int idpf_idc_rdma_vc_send_sync(struct iidc_rdma_core_dev_info
> *cdev_info,
> > +			       u8 *send_msg, u16 msg_size,
> > +			       u8 *recv_msg, u16 *recv_len);
> > +
> > +#endif /* _IIDC_RDMA_IDPF_H_ */
> > --
> > 2.31.1
> >
> >

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2025-08-08 17:14 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-12 21:59 [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
2025-06-12 21:59 ` [Intel-wired-lan] [iwl-next v2 1/6] idpf: use reserved RDMA vectors from control plane Tatyana Nikolova
2025-06-12 21:59 ` [Intel-wired-lan] [iwl-next v2 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy Tatyana Nikolova
2025-08-06 12:02   ` Larysa Zaremba
2025-08-08 17:06     ` Hay, Joshua A
2025-06-12 21:59 ` [Intel-wired-lan] [iwl-next v2 3/6] idpf: implement RDMA vport " Tatyana Nikolova
2025-06-12 22:00 ` [Intel-wired-lan] [iwl-next v2 4/6] idpf: implement remaining IDC RDMA core callbacks and handlers Tatyana Nikolova
2025-06-12 22:00 ` [Intel-wired-lan] [iwl-next v2 5/6] idpf: implement IDC vport aux driver MTU change handler Tatyana Nikolova
2025-06-12 22:00 ` [Intel-wired-lan] [iwl-next v2 6/6] idpf: implement get LAN MMIO memory regions Tatyana Nikolova
2025-06-13  7:21 ` [Intel-wired-lan] [iwl-next v2 0/6] Add RDMA support for Intel IPU E2000 in idpf Paul Menzel
2025-07-08 20:40   ` Nikolova, Tatyana E

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).