[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20230407081021.30952-8-gautam.dawar@amd.com>
Date: Fri, 7 Apr 2023 13:40:08 +0530
From: Gautam Dawar <gautam.dawar@....com>
To: <linux-net-drivers@....com>, <jasowang@...hat.com>,
Edward Cree <ecree.xilinx@...il.com>,
Martin Habets <habetsm.xilinx@...il.com>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
"Jakub Kicinski" <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
Richard Cochran <richardcochran@...il.com>,
<linux-kernel@...r.kernel.org>, <netdev@...r.kernel.org>
CC: <eperezma@...hat.com>, <harpreet.anand@....com>,
<tanuj.kamde@....com>, <koushik.dutta@....com>,
Gautam Dawar <gautam.dawar@....com>
Subject: [PATCH net-next v4 07/14] sfc: implement vdpa device config operations
vDPA config operations can be broadly categorized in to either
virtqueue operations, device operations or DMA operations.
This patch implements most of the device level config operations.
Signed-off-by: Gautam Dawar <gautam.dawar@....com>
---
drivers/net/ethernet/sfc/ef100_vdpa.h | 14 +++
drivers/net/ethernet/sfc/ef100_vdpa_ops.c | 131 ++++++++++++++++++++++
2 files changed, 145 insertions(+)
diff --git a/drivers/net/ethernet/sfc/ef100_vdpa.h b/drivers/net/ethernet/sfc/ef100_vdpa.h
index 1101b30f56e7..dcf4a8156415 100644
--- a/drivers/net/ethernet/sfc/ef100_vdpa.h
+++ b/drivers/net/ethernet/sfc/ef100_vdpa.h
@@ -20,6 +20,18 @@
/* Max queue pairs currently supported */
#define EF100_VDPA_MAX_QUEUES_PAIRS 1
+/* Device ID of a virtio net device */
+#define EF100_VDPA_VIRTIO_NET_DEVICE_ID VIRTIO_ID_NET
+
+/* Vendor ID of Xilinx vDPA NIC */
+#define EF100_VDPA_VENDOR_ID PCI_VENDOR_ID_XILINX
+
+/* Max number of Buffers supported in the virtqueue */
+#define EF100_VDPA_VQ_NUM_MAX_SIZE 512
+
+/* Alignment requirement of the Virtqueue */
+#define EF100_VDPA_VQ_ALIGN 4096
+
/**
* enum ef100_vdpa_nic_state - possible states for a vDPA NIC
*
@@ -60,6 +72,7 @@ enum ef100_vdpa_vq_type {
* @net_config: virtio_net_config data
* @mac_address: mac address of interface associated with this vdpa device
* @mac_configured: true after MAC address is configured
+ * @cfg_cb: callback for config change
*/
struct ef100_vdpa_nic {
struct vdpa_device vdpa_dev;
@@ -75,6 +88,7 @@ struct ef100_vdpa_nic {
struct virtio_net_config net_config;
u8 *mac_address;
bool mac_configured;
+ struct vdpa_callback cfg_cb;
};
int ef100_vdpa_init(struct efx_probe_data *probe_data);
diff --git a/drivers/net/ethernet/sfc/ef100_vdpa_ops.c b/drivers/net/ethernet/sfc/ef100_vdpa_ops.c
index f1ce011adc43..a2364ef9f492 100644
--- a/drivers/net/ethernet/sfc/ef100_vdpa_ops.c
+++ b/drivers/net/ethernet/sfc/ef100_vdpa_ops.c
@@ -9,12 +9,131 @@
#include <linux/vdpa.h>
#include "ef100_vdpa.h"
+#include "mcdi_vdpa.h"
static struct ef100_vdpa_nic *get_vdpa_nic(struct vdpa_device *vdev)
{
return container_of(vdev, struct ef100_vdpa_nic, vdpa_dev);
}
+static u32 ef100_vdpa_get_vq_align(struct vdpa_device *vdev)
+{
+ return EF100_VDPA_VQ_ALIGN;
+}
+
+static u64 ef100_vdpa_get_device_features(struct vdpa_device *vdev)
+{
+ struct ef100_vdpa_nic *vdpa_nic = get_vdpa_nic(vdev);
+ u64 features;
+ int rc;
+
+ rc = efx_vdpa_get_features(vdpa_nic->efx,
+ EF100_VDPA_DEVICE_TYPE_NET, &features);
+ if (rc) {
+ dev_err(&vdev->dev, "%s: MCDI get features error:%d\n",
+ __func__, rc);
+ /* Returning 0 as value of features will lead to failure
+ * of feature negotiation.
+ */
+ return 0;
+ }
+
+ features |= BIT_ULL(VIRTIO_NET_F_MAC);
+ return features;
+}
+
+static int ef100_vdpa_set_driver_features(struct vdpa_device *vdev,
+ u64 features)
+{
+ struct ef100_vdpa_nic *vdpa_nic = get_vdpa_nic(vdev);
+ u64 verify_features;
+ int rc;
+
+ mutex_lock(&vdpa_nic->lock);
+ verify_features = features & ~BIT_ULL(VIRTIO_NET_F_MAC);
+ rc = efx_vdpa_verify_features(vdpa_nic->efx,
+ EF100_VDPA_DEVICE_TYPE_NET,
+ verify_features);
+ if (rc) {
+ dev_err(&vdev->dev, "%s: MCDI verify features error:%d\n",
+ __func__, rc);
+ goto err;
+ }
+
+ vdpa_nic->features = features;
+err:
+ mutex_unlock(&vdpa_nic->lock);
+ return rc;
+}
+
+static u64 ef100_vdpa_get_driver_features(struct vdpa_device *vdev)
+{
+ struct ef100_vdpa_nic *vdpa_nic = get_vdpa_nic(vdev);
+
+ return vdpa_nic->features;
+}
+
+static void ef100_vdpa_set_config_cb(struct vdpa_device *vdev,
+ struct vdpa_callback *cb)
+{
+ struct ef100_vdpa_nic *vdpa_nic = get_vdpa_nic(vdev);
+
+ if (cb)
+ vdpa_nic->cfg_cb = *cb;
+}
+
+static u16 ef100_vdpa_get_vq_num_max(struct vdpa_device *vdev)
+{
+ return EF100_VDPA_VQ_NUM_MAX_SIZE;
+}
+
+static u32 ef100_vdpa_get_device_id(struct vdpa_device *vdev)
+{
+ return EF100_VDPA_VIRTIO_NET_DEVICE_ID;
+}
+
+static u32 ef100_vdpa_get_vendor_id(struct vdpa_device *vdev)
+{
+ return EF100_VDPA_VENDOR_ID;
+}
+
+static size_t ef100_vdpa_get_config_size(struct vdpa_device *vdev)
+{
+ return sizeof(struct virtio_net_config);
+}
+
+static void ef100_vdpa_get_config(struct vdpa_device *vdev,
+ unsigned int offset,
+ void *buf, unsigned int len)
+{
+ struct ef100_vdpa_nic *vdpa_nic = get_vdpa_nic(vdev);
+
+ /* Avoid the possibility of wrap-up after the sum exceeds U32_MAX */
+ if (WARN_ON(((u64)offset + len) > sizeof(struct virtio_net_config))) {
+ dev_err(&vdev->dev,
+ "%s: Offset + len exceeds config size\n", __func__);
+ return;
+ }
+ memcpy(buf, (u8 *)&vdpa_nic->net_config + offset, len);
+}
+
+static void ef100_vdpa_set_config(struct vdpa_device *vdev, unsigned int offset,
+ const void *buf, unsigned int len)
+{
+ struct ef100_vdpa_nic *vdpa_nic = get_vdpa_nic(vdev);
+
+ /* Avoid the possibility of wrap-up after the sum exceeds U32_MAX */
+ if (WARN_ON(((u64)offset + len) > sizeof(vdpa_nic->net_config))) {
+ dev_err(&vdev->dev,
+ "%s: Offset + len exceeds config size\n", __func__);
+ return;
+ }
+
+ memcpy((u8 *)&vdpa_nic->net_config + offset, buf, len);
+ if (is_valid_ether_addr(vdpa_nic->mac_address))
+ vdpa_nic->mac_configured = true;
+}
+
static void ef100_vdpa_free(struct vdpa_device *vdev)
{
struct ef100_vdpa_nic *vdpa_nic = get_vdpa_nic(vdev);
@@ -26,5 +145,17 @@ static void ef100_vdpa_free(struct vdpa_device *vdev)
}
const struct vdpa_config_ops ef100_vdpa_config_ops = {
+ .get_vq_align = ef100_vdpa_get_vq_align,
+ .get_device_features = ef100_vdpa_get_device_features,
+ .set_driver_features = ef100_vdpa_set_driver_features,
+ .get_driver_features = ef100_vdpa_get_driver_features,
+ .set_config_cb = ef100_vdpa_set_config_cb,
+ .get_vq_num_max = ef100_vdpa_get_vq_num_max,
+ .get_device_id = ef100_vdpa_get_device_id,
+ .get_vendor_id = ef100_vdpa_get_vendor_id,
+ .get_config_size = ef100_vdpa_get_config_size,
+ .get_config = ef100_vdpa_get_config,
+ .set_config = ef100_vdpa_set_config,
+ .get_generation = NULL,
.free = ef100_vdpa_free,
};
--
2.30.1
Powered by blists - more mailing lists