netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [iwl-next 0/6] Add RDMA support for Intel IPU E2000 in idpf
@ 2025-05-23 17:04 Tatyana Nikolova
  2025-05-23 17:04 ` [iwl-next 1/6] idpf: use reserved RDMA vectors from control plane Tatyana Nikolova
                   ` (5 more replies)
  0 siblings, 6 replies; 13+ messages in thread
From: Tatyana Nikolova @ 2025-05-23 17:04 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, anthony.l.nguyen,
	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.15-rc1 + "Prepare for Intel IPU E2000 (GEN3)" [4]. 
A shared pull request will be sent following review.

Changelog:

Changes since split:
* 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/20250509200712.2911060-1-anthony.l.nguyen@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    | 496 ++++++++++++++++++
 drivers/net/ethernet/intel/idpf/idpf_lib.c    |  93 +++-
 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   |  52 +-
 include/linux/net/intel/iidc_rdma_idpf.h      |  55 ++
 15 files changed, 1104 insertions(+), 71 deletions(-)
 create mode 100644 drivers/net/ethernet/intel/idpf/idpf_idc.c
 create mode 100644 include/linux/net/intel/iidc_rdma_idpf.h

-- 
2.37.3


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

* [iwl-next 1/6] idpf: use reserved RDMA vectors from control plane
  2025-05-23 17:04 [iwl-next 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
@ 2025-05-23 17:04 ` Tatyana Nikolova
  2025-05-25  5:23   ` [Intel-wired-lan] " Paul Menzel
  2025-05-23 17:04 ` [iwl-next 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy Tatyana Nikolova
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Tatyana Nikolova @ 2025-05-23 17:04 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, anthony.l.nguyen, 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>
---
 drivers/net/ethernet/intel/idpf/idpf.h      | 28 +++++++-
 drivers/net/ethernet/intel/idpf/idpf_lib.c  | 74 +++++++++++++++++----
 drivers/net/ethernet/intel/idpf/idpf_txrx.h |  1 +
 drivers/net/ethernet/intel/idpf/virtchnl2.h |  5 +-
 4 files changed, 92 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index 66544faab710..8ef7120e6717 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -489,10 +489,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
@@ -542,10 +543,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;
@@ -609,6 +611,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	|\
@@ -663,6 +676,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 aa755dedb41d..0d5c57502cac 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -87,6 +87,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;
 }
 
 /**
@@ -314,13 +316,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;
 	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);
@@ -331,52 +353,75 @@ int idpf_intr_req(struct idpf_adapter *adapter)
 		return -EAGAIN;
 	}
 
-	min_vectors = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC * default_vports;
+	min_lan_vecs = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC * default_vports;
+	min_vectors = min_lan_vecs + min_rdma_vecs;
 	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",
+		dev_err(&adapter->pdev->dev, "Failed to allocate minimum MSIX vectors required: %d\n",
 			v_actual);
 		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 (v_actual < total_vecs) {
+			dev_warn(&adapter->pdev->dev,
+				 "Warning: not enough vectors available. Defaulting to minimum for RDMA and remaining for LAN.\n");
+			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 = v_actual - 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;
 	}
 
 	idpf_set_mb_vec_id(adapter);
 
-	vecids = kcalloc(total_vecs, sizeof(u16), GFP_KERNEL);
+	vecids = kcalloc(v_actual, 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, v_actual,
 				       &adapter->req_vec_chunks->vchunks);
 	if (num_vec_ids < v_actual) {
 		err = -EINVAL;
 		goto free_vecids;
 	}
 
-	for (vector = 0; vector < v_actual; vector++) {
-		adapter->msix_entries[vector].entry = vecids[vector];
-		adapter->msix_entries[vector].vector =
+	for (i = 0, vector = 0; vector < num_lan_vecs; vector++, i++) {
+		adapter->msix_entries[i].entry = vecids[vector];
+		adapter->msix_entries[i].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);
@@ -398,6 +443,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 b029f566e57c..9cb97397d89b 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 63deb120359c..80c17e4a394e 100644
--- a/drivers/net/ethernet/intel/idpf/virtchnl2.h
+++ b/drivers/net/ethernet/intel/idpf/virtchnl2.h
@@ -473,6 +473,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
@@ -520,7 +522,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.37.3


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

* [iwl-next 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy
  2025-05-23 17:04 [iwl-next 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
  2025-05-23 17:04 ` [iwl-next 1/6] idpf: use reserved RDMA vectors from control plane Tatyana Nikolova
@ 2025-05-23 17:04 ` Tatyana Nikolova
  2025-05-28 10:40   ` Simon Horman
  2025-05-23 17:04 ` [iwl-next 3/6] idpf: implement RDMA vport " Tatyana Nikolova
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Tatyana Nikolova @ 2025-05-23 17:04 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, anthony.l.nguyen, 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 or 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>
---

Changes since split:
- 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 2ce01a0b5898..bde9c893d8a1 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 8ef7120e6717..d72e523067dc 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"
@@ -202,9 +204,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);
 };
 
 /**
@@ -522,6 +527,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
@@ -580,6 +586,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;
@@ -858,5 +865,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 41e4bd49402a..43cf11dc3a37 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_dev.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_dev.c
@@ -148,6 +148,17 @@ static void idpf_trigger_reset(struct idpf_adapter *adapter,
 	       idpf_get_reg_addr(adapter, PFGEN_CTRL));
 }
 
+/**
+ * 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
@@ -168,4 +179,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..56c02bad466c
--- /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;
+
+	privd = kzalloc(sizeof(*privd), GFP_KERNEL);
+	if (!privd) {
+		err = -ENOMEM;
+		goto err_privd_alloc;
+	}
+
+	cdev_info = adapter->cdev_info;
+	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 0d5c57502cac..e1546ae13c88 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1862,6 +1862,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 3d2413b8684f..d10f4676875c 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -897,6 +897,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		|
@@ -3092,6 +3093,7 @@ void idpf_vc_core_deinit(struct idpf_adapter *adapter)
 		idpf_vc_xn_shutdown(adapter->vcxn_mngr);
 
 	idpf_deinit_task(adapter);
+	idpf_idc_deinit_core_aux_device(adapter->cdev_info);
 	idpf_intr_rel(adapter);
 
 	if (remove_in_prog)
@@ -3737,3 +3739,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 83da5d8da56b..4580404052a4 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.h
@@ -66,5 +66,8 @@ int idpf_send_get_stats_msg(struct idpf_vport *vport);
 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);
+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.37.3


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

* [iwl-next 3/6] idpf: implement RDMA vport auxiliary dev create, init, and destroy
  2025-05-23 17:04 [iwl-next 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
  2025-05-23 17:04 ` [iwl-next 1/6] idpf: use reserved RDMA vectors from control plane Tatyana Nikolova
  2025-05-23 17:04 ` [iwl-next 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy Tatyana Nikolova
@ 2025-05-23 17:04 ` Tatyana Nikolova
  2025-05-23 17:04 ` [iwl-next 4/6] idpf: implement remaining IDC RDMA core callbacks and handlers Tatyana Nikolova
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Tatyana Nikolova @ 2025-05-23 17:04 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, anthony.l.nguyen, 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 |  13 +-
 include/linux/net/intel/iidc_rdma_idpf.h    |  19 +++
 5 files changed, 213 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index d72e523067dc..54aaef4da059 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -276,6 +276,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.
@@ -318,6 +319,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);
@@ -869,5 +872,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 56c02bad466c..a869966b5941 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 e1546ae13c88..5c2b7a76db33 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1052,6 +1052,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 80c17e4a394e..673a39e6698d 100644
--- a/drivers/net/ethernet/intel/idpf/virtchnl2.h
+++ b/drivers/net/ethernet/intel/idpf/virtchnl2.h
@@ -562,6 +562,15 @@ struct virtchnl2_queue_reg_chunks {
 };
 VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_queue_reg_chunks);
 
+/**
+ * enum virtchnl2_vport_flags - Vport flags
+ * @VIRTCHNL2_VPORT_ENABLE_RDMA: RDMA is enabled for this vport
+ */
+enum virtchnl2_vport_flags {
+	/* VIRTCHNL2_VPORT_* bits [0:3] rsvd */
+	VIRTCHNL2_VPORT_ENABLE_RDMA             = BIT(4),
+};
+
 /**
  * struct virtchnl2_create_vport - Create vport config info.
  * @vport_type: See enum virtchnl2_vport_type.
@@ -580,7 +589,7 @@ VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_queue_reg_chunks);
  * @max_mtu: Max MTU. CP populates this field on response.
  * @vport_id: Vport id. CP populates this field on response.
  * @default_mac_addr: Default MAC address.
- * @pad: Padding.
+ * @vport_flags: See enum virtchnl2_vport_flags
  * @rx_desc_ids: See VIRTCHNL2_RX_DESC_IDS definitions.
  * @tx_desc_ids: See VIRTCHNL2_TX_DESC_IDS definitions.
  * @pad1: Padding.
@@ -613,7 +622,7 @@ struct virtchnl2_create_vport {
 	__le16 max_mtu;
 	__le32 vport_id;
 	u8 default_mac_addr[ETH_ALEN];
-	__le16 pad;
+	__le16 vport_flags;
 	__le64 rx_desc_ids;
 	__le64 tx_desc_ids;
 	u8 pad1[72];
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.37.3


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

* [iwl-next 4/6] idpf: implement remaining IDC RDMA core callbacks and handlers
  2025-05-23 17:04 [iwl-next 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
                   ` (2 preceding siblings ...)
  2025-05-23 17:04 ` [iwl-next 3/6] idpf: implement RDMA vport " Tatyana Nikolova
@ 2025-05-23 17:04 ` Tatyana Nikolova
  2025-05-23 17:04 ` [iwl-next 5/6] idpf: implement IDC vport aux driver MTU change handler Tatyana Nikolova
  2025-05-23 17:04 ` [iwl-next 6/6] idpf: implement get LAN MMIO memory regions Tatyana Nikolova
  5 siblings, 0 replies; 13+ messages in thread
From: Tatyana Nikolova @ 2025-05-23 17:04 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, anthony.l.nguyen, 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 54aaef4da059..9043a31b0282 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -873,5 +873,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 a869966b5941..a3c50104a3d7 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 5c2b7a76db33..9358dabe852a 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1817,6 +1817,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 d10f4676875c..7bb1059e917f 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -3754,6 +3754,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 673a39e6698d..e6541152ca58 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.37.3


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

* [iwl-next 5/6] idpf: implement IDC vport aux driver MTU change handler
  2025-05-23 17:04 [iwl-next 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
                   ` (3 preceding siblings ...)
  2025-05-23 17:04 ` [iwl-next 4/6] idpf: implement remaining IDC RDMA core callbacks and handlers Tatyana Nikolova
@ 2025-05-23 17:04 ` Tatyana Nikolova
  2025-05-23 17:04 ` [iwl-next 6/6] idpf: implement get LAN MMIO memory regions Tatyana Nikolova
  5 siblings, 0 replies; 13+ messages in thread
From: Tatyana Nikolova @ 2025-05-23 17:04 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, anthony.l.nguyen, 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 9043a31b0282..7b5f2e274cfa 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -874,5 +874,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 a3c50104a3d7..51e54525a2c4 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 9358dabe852a..465d39448fe5 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1945,6 +1945,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:
@@ -1989,9 +1992,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,
@@ -2004,6 +2005,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.37.3


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

* [iwl-next 6/6] idpf: implement get LAN MMIO memory regions
  2025-05-23 17:04 [iwl-next 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
                   ` (4 preceding siblings ...)
  2025-05-23 17:04 ` [iwl-next 5/6] idpf: implement IDC vport aux driver MTU change handler Tatyana Nikolova
@ 2025-05-23 17:04 ` Tatyana Nikolova
  2025-05-28 10:44   ` Simon Horman
  5 siblings, 1 reply; 13+ messages in thread
From: Tatyana Nikolova @ 2025-05-23 17:04 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: jgg, leon, linux-rdma, netdev, kuba, anthony.l.nguyen, 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, 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>
---

Changes since split:
- 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    |  31 +++-
 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, 379 insertions(+), 52 deletions(-)

diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index 7b5f2e274cfa..6eac3ac69c2b 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>
 
@@ -193,7 +194,8 @@ struct idpf_vport_max_q {
  * @trigger_reset: Trigger a reset to occur
  */
 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);
@@ -201,15 +203,25 @@ struct idpf_reg_ops {
 			      enum idpf_flags trig_cause);
 };
 
+#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];
 };
 
 /**
@@ -735,6 +747,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
@@ -745,7 +786,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;
 }
 
 /**
@@ -759,7 +824,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 43cf11dc3a37..be22d0237de2 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_dev.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_dev.c
@@ -9,10 +9,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++) {
@@ -21,22 +24,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;
@@ -129,7 +132,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;
 }
 
@@ -143,9 +146,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));
 }
 
 /**
@@ -181,4 +184,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 51e54525a2c4..29d53b5936a5 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,15 @@ 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 = cdev_info->iidc_priv;
+
 	if (!cdev_info)
 		return;
 
 	idpf_unplug_aux_dev(cdev_info->adev);
 
-	kfree(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 bec4a02c5373..7669f48ce3a1 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_main.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_main.c
@@ -105,15 +105,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;
 
@@ -160,9 +182,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 7bb1059e917f..168e8452c93e 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_virtchnl.c
@@ -898,6 +898,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		|
@@ -919,6 +920,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
@@ -2830,7 +2953,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)
@@ -2990,6 +3113,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 e6541152ca58..087d8e80de26 100644
--- a/drivers/net/ethernet/intel/idpf/virtchnl2.h
+++ b/drivers/net/ethernet/intel/idpf/virtchnl2.h
@@ -69,6 +69,8 @@ enum virtchnl2_op {
 	VIRTCHNL2_OP_ADD_MAC_ADDR		= 535,
 	VIRTCHNL2_OP_DEL_MAC_ADDR		= 536,
 	VIRTCHNL2_OP_CONFIG_PROMISCUOUS_MODE	= 537,
+	/* Opcodes 538 through 548 are reserved. */
+	VIRTCHNL2_OP_GET_LAN_MEMORY_REGIONS     = 549,
 };
 
 /**
@@ -202,7 +204,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),
@@ -1283,4 +1286,30 @@ struct virtchnl2_promisc_info {
 };
 VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_promisc_info);
 
+/**
+ * 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.37.3


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

* Re: [Intel-wired-lan] [iwl-next 1/6] idpf: use reserved RDMA vectors from control plane
  2025-05-23 17:04 ` [iwl-next 1/6] idpf: use reserved RDMA vectors from control plane Tatyana Nikolova
@ 2025-05-25  5:23   ` Paul Menzel
  2025-05-28 21:35     ` Hay, Joshua A
  0 siblings, 1 reply; 13+ messages in thread
From: Paul Menzel @ 2025-05-25  5:23 UTC (permalink / raw)
  To: Tatyana Nikolova
  Cc: intel-wired-lan, jgg, leon, linux-rdma, netdev, kuba,
	anthony.l.nguyen, Joshua Hay

Dear Tatyana,


Thank you for your patch.

Am 23.05.25 um 19:04 schrieb 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.

How can this all be tested? It’d be great if you added the commands and 
outputs.

> 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>
> ---
>   drivers/net/ethernet/intel/idpf/idpf.h      | 28 +++++++-
>   drivers/net/ethernet/intel/idpf/idpf_lib.c  | 74 +++++++++++++++++----
>   drivers/net/ethernet/intel/idpf/idpf_txrx.h |  1 +
>   drivers/net/ethernet/intel/idpf/virtchnl2.h |  5 +-
>   4 files changed, 92 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
> index 66544faab710..8ef7120e6717 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf.h
> +++ b/drivers/net/ethernet/intel/idpf/idpf.h
> @@ -489,10 +489,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
> @@ -542,10 +543,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;
> @@ -609,6 +611,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	|\
> @@ -663,6 +676,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 aa755dedb41d..0d5c57502cac 100644
> --- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
> +++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
> @@ -87,6 +87,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;
>   }
>   
>   /**
> @@ -314,13 +316,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;

Unrelated, but `v_actual` is strangely named, when all other variables 
seem to use vec.

>   	unsigned int vector;
>   	u16 *vecids;
> +	int i;

size_t?

>   
>   	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);
> @@ -331,52 +353,75 @@ int idpf_intr_req(struct idpf_adapter *adapter)
>   		return -EAGAIN;
>   	}
>   
> -	min_vectors = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC * default_vports;
> +	min_lan_vecs = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC * default_vports;
> +	min_vectors = min_lan_vecs + min_rdma_vecs;
>   	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",
> +		dev_err(&adapter->pdev->dev, "Failed to allocate minimum MSIX vectors required: %d\n",
>   			v_actual);
>   		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 (v_actual < total_vecs) {
> +			dev_warn(&adapter->pdev->dev,
> +				 "Warning: not enough vectors available. Defaulting to minimum for RDMA and remaining for LAN.\n");

Also log `v_actual`, `total_vecs` and `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 = v_actual - 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;
>   	}
>   
>   	idpf_set_mb_vec_id(adapter);
>   
> -	vecids = kcalloc(total_vecs, sizeof(u16), GFP_KERNEL);
> +	vecids = kcalloc(v_actual, 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, v_actual,
>   				       &adapter->req_vec_chunks->vchunks);
>   	if (num_vec_ids < v_actual) {
>   		err = -EINVAL;
>   		goto free_vecids;
>   	}
>   
> -	for (vector = 0; vector < v_actual; vector++) {
> -		adapter->msix_entries[vector].entry = vecids[vector];
> -		adapter->msix_entries[vector].vector =
> +	for (i = 0, vector = 0; vector < num_lan_vecs; vector++, i++) {
> +		adapter->msix_entries[i].entry = vecids[vector];
> +		adapter->msix_entries[i].vector =
> +			pci_irq_vector(adapter->pdev, vector);

Excuse my ignorance, but why are two counting variables needed, that 
seem to be identical?

> +	}
> +	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);
> @@ -398,6 +443,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 b029f566e57c..9cb97397d89b 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 63deb120359c..80c17e4a394e 100644
> --- a/drivers/net/ethernet/intel/idpf/virtchnl2.h
> +++ b/drivers/net/ethernet/intel/idpf/virtchnl2.h
> @@ -473,6 +473,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
> @@ -520,7 +522,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);


Kind regards,

Paul


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

* Re: [iwl-next 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy
  2025-05-23 17:04 ` [iwl-next 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy Tatyana Nikolova
@ 2025-05-28 10:40   ` Simon Horman
  2025-05-28 21:35     ` Hay, Joshua A
  0 siblings, 1 reply; 13+ messages in thread
From: Simon Horman @ 2025-05-28 10:40 UTC (permalink / raw)
  To: Tatyana Nikolova
  Cc: intel-wired-lan, jgg, leon, linux-rdma, netdev, kuba,
	anthony.l.nguyen, Joshua Hay

On Fri, May 23, 2025 at 12:04:31PM -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 or 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>

...

> diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c b/drivers/net/ethernet/intel/idpf/idpf_idc.c

...

> +/**
> + * 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;
> +
> +	privd = kzalloc(sizeof(*privd), GFP_KERNEL);
> +	if (!privd) {
> +		err = -ENOMEM;
> +		goto err_privd_alloc;

Hi Joshua, Tatyana, all,

Jumping to err_privd_alloc will free cdev_info.
However cdev_info isn't initialised until a few lines
further down.

Flagged by Smatch.

> +	}
> +
> +	cdev_info = adapter->cdev_info;
> +	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;
> +}

...

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

* Re: [iwl-next 6/6] idpf: implement get LAN MMIO memory regions
  2025-05-23 17:04 ` [iwl-next 6/6] idpf: implement get LAN MMIO memory regions Tatyana Nikolova
@ 2025-05-28 10:44   ` Simon Horman
  2025-05-28 21:35     ` Hay, Joshua A
  0 siblings, 1 reply; 13+ messages in thread
From: Simon Horman @ 2025-05-28 10:44 UTC (permalink / raw)
  To: Tatyana Nikolova
  Cc: intel-wired-lan, jgg, leon, linux-rdma, netdev, kuba,
	anthony.l.nguyen, Joshua Hay

On Fri, May 23, 2025 at 12:04:35PM -0500, Tatyana Nikolova wrote:
> 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, 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>

...

> diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c b/drivers/net/ethernet/intel/idpf/idpf_idc.c

...

> @@ -447,12 +469,15 @@ 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 = cdev_info->iidc_priv;
> +

Hi Joshua, Tatyana, all,

On the line below it is assumed that cdev_info may be NULL.
But on the line above cdev_info is unconditionally dereferenced.
This doesn't seem consistent.

Flagged by Smatch.

>  	if (!cdev_info)
>  		return;
>  
>  	idpf_unplug_aux_dev(cdev_info->adev);
>  
> -	kfree(cdev_info->iidc_priv);
> +	kfree(privd->mapped_mem_regions);
> +	kfree(privd);
>  	kfree(cdev_info);
>  }
>  

...

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

* RE: [Intel-wired-lan] [iwl-next 1/6] idpf: use reserved RDMA vectors from control plane
  2025-05-25  5:23   ` [Intel-wired-lan] " Paul Menzel
@ 2025-05-28 21:35     ` Hay, Joshua A
  0 siblings, 0 replies; 13+ messages in thread
From: Hay, Joshua A @ 2025-05-28 21:35 UTC (permalink / raw)
  To: Paul Menzel, Nikolova, Tatyana E
  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, Nguyen, Anthony L

> -----Original Message-----
> From: Paul Menzel <pmenzel@molgen.mpg.de>
> Sent: Saturday, May 24, 2025 10:24 PM
> 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; Nguyen,
> Anthony L <anthony.l.nguyen@intel.com>; Hay, Joshua A
> <joshua.a.hay@intel.com>
> Subject: Re: [Intel-wired-lan] [iwl-next 1/6] idpf: use reserved RDMA vectors
> from control plane
> 
> Dear Tatyana,
> 
> 
> Thank you for your patch.
> 
> Am 23.05.25 um 19:04 schrieb 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.
> 
> How can this all be tested? It’d be great if you added the commands and
> outputs.

This was tested on a range of hosts/platforms since the number of reserved RDMA vectors is based solely on the device configuration, which is not exposed to the end user.  The user can confirm how many vectors the drivers have after everything is loaded properly though. From the RDMA driver perspective it will either have IDPF_MIN_RDMA_VEC vectors or whatever was provided by the device.

> 
> > 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>
> > ---
> >   drivers/net/ethernet/intel/idpf/idpf.h      | 28 +++++++-
> >   drivers/net/ethernet/intel/idpf/idpf_lib.c  | 74 +++++++++++++++++----
> >   drivers/net/ethernet/intel/idpf/idpf_txrx.h |  1 +
> >   drivers/net/ethernet/intel/idpf/virtchnl2.h |  5 +-
> >   4 files changed, 92 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/net/ethernet/intel/idpf/idpf.h
> b/drivers/net/ethernet/intel/idpf/idpf.h
> > index 66544faab710..8ef7120e6717 100644
> > --- a/drivers/net/ethernet/intel/idpf/idpf.h
> > +++ b/drivers/net/ethernet/intel/idpf/idpf.h
> > @@ -489,10 +489,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
> > @@ -542,10 +543,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;
> > @@ -609,6 +611,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	|\
> > @@ -663,6 +676,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 aa755dedb41d..0d5c57502cac 100644
> > --- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
> > +++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
> > @@ -87,6 +87,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;
> >   }
> >
> >   /**
> > @@ -314,13 +316,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;
> 
> Unrelated, but `v_actual` is strangely named, when all other variables
> seem to use vec.

Good point, I can change it in v2 if that is the ask.

> 
> >   	unsigned int vector;
> >   	u16 *vecids;
> > +	int i;
> 
> size_t?

Sorry, can you please explain why size_t would be preferred here?

> 
> >
> >   	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);
> > @@ -331,52 +353,75 @@ int idpf_intr_req(struct idpf_adapter *adapter)
> >   		return -EAGAIN;
> >   	}
> >
> > -	min_vectors = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC *
> default_vports;
> > +	min_lan_vecs = IDPF_MBX_Q_VEC + IDPF_MIN_Q_VEC *
> default_vports;
> > +	min_vectors = min_lan_vecs + min_rdma_vecs;
> >   	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",
> > +		dev_err(&adapter->pdev->dev, "Failed to allocate minimum
> MSIX vectors required: %d\n",
> >   			v_actual);
> >   		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 (v_actual < total_vecs) {
> > +			dev_warn(&adapter->pdev->dev,
> > +				 "Warning: not enough vectors available.
> Defaulting to minimum for RDMA and remaining for LAN.\n");
> 
> Also log `v_actual`, `total_vecs` and `IDPF_MIN_RDMA_VEC`?

Will add in v2.

> 
> > +			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 = v_actual - 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;
> >   	}
> >
> >   	idpf_set_mb_vec_id(adapter);
> >
> > -	vecids = kcalloc(total_vecs, sizeof(u16), GFP_KERNEL);
> > +	vecids = kcalloc(v_actual, 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, v_actual,
> >   				       &adapter->req_vec_chunks->vchunks);
> >   	if (num_vec_ids < v_actual) {
> >   		err = -EINVAL;
> >   		goto free_vecids;
> >   	}
> >
> > -	for (vector = 0; vector < v_actual; vector++) {
> > -		adapter->msix_entries[vector].entry = vecids[vector];
> > -		adapter->msix_entries[vector].vector =
> > +	for (i = 0, vector = 0; vector < num_lan_vecs; vector++, i++) {
> > +		adapter->msix_entries[i].entry = vecids[vector];
> > +		adapter->msix_entries[i].vector =
> > +			pci_irq_vector(adapter->pdev, vector);
> 
> Excuse my ignorance, but why are two counting variables needed, that
> seem to be identical?

Ah, good catch, will just use vector above.

> 
> > +	}
> > +	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);
> > @@ -398,6 +443,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 b029f566e57c..9cb97397d89b 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 63deb120359c..80c17e4a394e 100644
> > --- a/drivers/net/ethernet/intel/idpf/virtchnl2.h
> > +++ b/drivers/net/ethernet/intel/idpf/virtchnl2.h
> > @@ -473,6 +473,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
> > @@ -520,7 +522,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);
> 
> 
> Kind regards,
> 
> Paul

Thank you! 
Josh


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

* RE: [iwl-next 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy
  2025-05-28 10:40   ` Simon Horman
@ 2025-05-28 21:35     ` Hay, Joshua A
  0 siblings, 0 replies; 13+ messages in thread
From: Hay, Joshua A @ 2025-05-28 21:35 UTC (permalink / raw)
  To: Simon Horman, Nikolova, Tatyana E
  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, Nguyen, Anthony L

> -----Original Message-----
> From: Simon Horman <horms@kernel.org>
> Sent: Wednesday, May 28, 2025 3:41 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; Nguyen,
> Anthony L <anthony.l.nguyen@intel.com>; Hay, Joshua A
> <joshua.a.hay@intel.com>
> Subject: Re: [iwl-next 2/6] idpf: implement core RDMA auxiliary dev create,
> init, and destroy
> 
> On Fri, May 23, 2025 at 12:04:31PM -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 or 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>
> 
> ...
> 
> > diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c
> b/drivers/net/ethernet/intel/idpf/idpf_idc.c
> 
> ...
> 
> > +/**
> > + * 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;
> > +
> > +	privd = kzalloc(sizeof(*privd), GFP_KERNEL);
> > +	if (!privd) {
> > +		err = -ENOMEM;
> > +		goto err_privd_alloc;
> 
> Hi Joshua, Tatyana, all,
> 
> Jumping to err_privd_alloc will free cdev_info.
> However cdev_info isn't initialised until a few lines
> further down.
> 
> Flagged by Smatch.

Ah, right. Will fix in v2.

Thanks,
Josh

> 
> > +	}
> > +
> > +	cdev_info = adapter->cdev_info;
> > +	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;
> > +}
> 
> ...


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

* RE: [iwl-next 6/6] idpf: implement get LAN MMIO memory regions
  2025-05-28 10:44   ` Simon Horman
@ 2025-05-28 21:35     ` Hay, Joshua A
  0 siblings, 0 replies; 13+ messages in thread
From: Hay, Joshua A @ 2025-05-28 21:35 UTC (permalink / raw)
  To: Simon Horman, Nikolova, Tatyana E
  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, Nguyen, Anthony L

> -----Original Message-----
> From: Simon Horman <horms@kernel.org>
> Sent: Wednesday, May 28, 2025 3:44 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; Nguyen,
> Anthony L <anthony.l.nguyen@intel.com>; Hay, Joshua A
> <joshua.a.hay@intel.com>
> Subject: Re: [iwl-next 6/6] idpf: implement get LAN MMIO memory regions
> 
> On Fri, May 23, 2025 at 12:04:35PM -0500, Tatyana Nikolova wrote:
> > 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, 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>
> 
> ...
> 
> > diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c
> b/drivers/net/ethernet/intel/idpf/idpf_idc.c
> 
> ...
> 
> > @@ -447,12 +469,15 @@ 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 = cdev_info->iidc_priv;
> > +
> 
> Hi Joshua, Tatyana, all,
> 
> On the line below it is assumed that cdev_info may be NULL.
> But on the line above cdev_info is unconditionally dereferenced.
> This doesn't seem consistent.
> 
> Flagged by Smatch.

Right, that is a mistake. Will fix in v2. 

Thanks,
Josh

> 
> >  	if (!cdev_info)
> >  		return;
> >
> >  	idpf_unplug_aux_dev(cdev_info->adev);
> >
> > -	kfree(cdev_info->iidc_priv);
> > +	kfree(privd->mapped_mem_regions);
> > +	kfree(privd);
> >  	kfree(cdev_info);
> >  }
> >
> 
> ...

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

end of thread, other threads:[~2025-05-28 21:35 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-23 17:04 [iwl-next 0/6] Add RDMA support for Intel IPU E2000 in idpf Tatyana Nikolova
2025-05-23 17:04 ` [iwl-next 1/6] idpf: use reserved RDMA vectors from control plane Tatyana Nikolova
2025-05-25  5:23   ` [Intel-wired-lan] " Paul Menzel
2025-05-28 21:35     ` Hay, Joshua A
2025-05-23 17:04 ` [iwl-next 2/6] idpf: implement core RDMA auxiliary dev create, init, and destroy Tatyana Nikolova
2025-05-28 10:40   ` Simon Horman
2025-05-28 21:35     ` Hay, Joshua A
2025-05-23 17:04 ` [iwl-next 3/6] idpf: implement RDMA vport " Tatyana Nikolova
2025-05-23 17:04 ` [iwl-next 4/6] idpf: implement remaining IDC RDMA core callbacks and handlers Tatyana Nikolova
2025-05-23 17:04 ` [iwl-next 5/6] idpf: implement IDC vport aux driver MTU change handler Tatyana Nikolova
2025-05-23 17:04 ` [iwl-next 6/6] idpf: implement get LAN MMIO memory regions Tatyana Nikolova
2025-05-28 10:44   ` Simon Horman
2025-05-28 21:35     ` Hay, Joshua A

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).