]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
idpf: implement RDMA vport auxiliary dev create, init, and destroy
authorJoshua Hay <joshua.a.hay@intel.com>
Tue, 8 Jul 2025 21:05:51 +0000 (16:05 -0500)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Mon, 14 Jul 2025 17:57:51 +0000 (10:57 -0700)
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>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/idpf/idpf.h
drivers/net/ethernet/intel/idpf/idpf_idc.c
drivers/net/ethernet/intel/idpf/idpf_lib.c
drivers/net/ethernet/intel/idpf/virtchnl2.h
include/linux/net/intel/iidc_rdma_idpf.h

index dd2aa515a31b79c3e1ae8980ca4102078b4dd408..7103cf551bb80dcf1733f8dc23bf3f47c3474ae9 100644 (file)
@@ -281,6 +281,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.
@@ -326,6 +327,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);
@@ -889,5 +892,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_ */
index bc90699f22c50aae7f4922a84433f929df477be2..237dfe1ac06d07ddcbf2a93a4880981edd950677 100644 (file)
@@ -32,6 +32,115 @@ 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:
+       auxiliary_device_uninit(adev);
+err_aux_dev_init:
+       ida_free(&idpf_idc_ida, adev->id);
+err_ida_alloc:
+       vdev_info->adev = NULL;
+       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) {
+               vport->vdev_info = NULL;
+               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
@@ -104,12 +213,60 @@ err_ida_alloc:
  */
 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
@@ -123,7 +280,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);
 
@@ -225,3 +389,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);
+}
index b9e04ea2cbd4e99c761b316fd704a4e5907e5496..30a7beb23155250091ba5583f19a2ae31c056a49 100644 (file)
@@ -1021,6 +1021,8 @@ static void idpf_vport_dealloc(struct idpf_vport *vport)
        struct idpf_adapter *adapter = vport->adapter;
        unsigned int i = vport->idx;
 
+       idpf_idc_deinit_vport_aux_device(vport->vdev_info);
+
        idpf_deinit_mac_addr(vport);
        idpf_vport_stop(vport);
 
index a2881979c7f88100a4ae302d83088346d9356146..82a3c307307ef7fe68cd8727aee51dba58162069 100644 (file)
@@ -575,9 +575,12 @@ VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_queue_reg_chunks);
 /**
  * enum virtchnl2_vport_flags - Vport flags that indicate vport capabilities.
  * @VIRTCHNL2_VPORT_UPLINK_PORT: Representatives of underlying physical ports
+ * @VIRTCHNL2_VPORT_ENABLE_RDMA: RDMA is enabled for this vport
  */
 enum virtchnl2_vport_flags {
        VIRTCHNL2_VPORT_UPLINK_PORT     = BIT(0),
+       /* VIRTCHNL2_VPORT_* bits [1:3] rsvd */
+       VIRTCHNL2_VPORT_ENABLE_RDMA             = BIT(4),
 };
 
 /**
index f2fe1844f660e2b00bd2fc88695d1ba1f1939f92..16c970dd4c6e02e9f02b2f3cd90683e52c428b3b 100644 (file)
@@ -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,