summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf.h4
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_idc.c180
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_lib.c2
-rw-r--r--drivers/net/ethernet/intel/idpf/virtchnl2.h3
-rw-r--r--include/linux/net/intel/iidc_rdma_idpf.h19
5 files changed, 207 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/idpf/idpf.h b/drivers/net/ethernet/intel/idpf/idpf.h
index dd2aa515a31b..7103cf551bb8 100644
--- a/drivers/net/ethernet/intel/idpf/idpf.h
+++ b/drivers/net/ethernet/intel/idpf/idpf.h
@@ -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_ */
diff --git a/drivers/net/ethernet/intel/idpf/idpf_idc.c b/drivers/net/ethernet/intel/idpf/idpf_idc.c
index bc90699f22c5..237dfe1ac06d 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_idc.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_idc.c
@@ -33,6 +33,115 @@ int idpf_idc_init(struct idpf_adapter *adapter)
}
/**
+ * 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,6 +213,9 @@ err_ida_alloc:
*/
static void idpf_unplug_aux_dev(struct auxiliary_device *adev)
{
+ if (!adev)
+ return;
+
auxiliary_device_delete(adev);
auxiliary_device_uninit(adev);
@@ -111,6 +223,51 @@ static void idpf_unplug_aux_dev(struct auxiliary_device *adev)
}
/**
+ * 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
* @up: RDMA core driver status
@@ -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);
+}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_lib.c b/drivers/net/ethernet/intel/idpf/idpf_lib.c
index b9e04ea2cbd4..30a7beb23155 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_lib.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_lib.c
@@ -1021,6 +1021,8 @@ static void idpf_vport_dealloc(struct idpf_vport *vport)
struct idpf_adapter *adapter = vport->adapter;
unsigned int i = vport->idx;
+ idpf_idc_deinit_vport_aux_device(vport->vdev_info);
+
idpf_deinit_mac_addr(vport);
idpf_vport_stop(vport);
diff --git a/drivers/net/ethernet/intel/idpf/virtchnl2.h b/drivers/net/ethernet/intel/idpf/virtchnl2.h
index a2881979c7f8..82a3c307307e 100644
--- a/drivers/net/ethernet/intel/idpf/virtchnl2.h
+++ b/drivers/net/ethernet/intel/idpf/virtchnl2.h
@@ -575,9 +575,12 @@ VIRTCHNL2_CHECK_STRUCT_LEN(8, virtchnl2_queue_reg_chunks);
/**
* enum virtchnl2_vport_flags - Vport flags that indicate vport capabilities.
* @VIRTCHNL2_VPORT_UPLINK_PORT: Representatives of underlying physical ports
+ * @VIRTCHNL2_VPORT_ENABLE_RDMA: RDMA is enabled for this vport
*/
enum virtchnl2_vport_flags {
VIRTCHNL2_VPORT_UPLINK_PORT = BIT(0),
+ /* VIRTCHNL2_VPORT_* bits [1:3] rsvd */
+ VIRTCHNL2_VPORT_ENABLE_RDMA = BIT(4),
};
/**
diff --git a/include/linux/net/intel/iidc_rdma_idpf.h b/include/linux/net/intel/iidc_rdma_idpf.h
index f2fe1844f660..16c970dd4c6e 100644
--- a/include/linux/net/intel/iidc_rdma_idpf.h
+++ b/include/linux/net/intel/iidc_rdma_idpf.h
@@ -7,6 +7,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,
IIDC_FUNCTION_TYPE_VF,