diff --git a/doc/guides/vdpadevs/features/sfc.ini b/doc/guides/vdpadevs/features/sfc.ini
index 71b6158..700d061 100644
--- a/doc/guides/vdpadevs/features/sfc.ini
+++ b/doc/guides/vdpadevs/features/sfc.ini
@@ -4,6 +4,16 @@
 ; Refer to default.ini for the full list of available driver features.
 ;
 [Features]
+csum			= Y
+guest csum		= Y
+host tso4		= Y
+host tso6		= Y
+version 1		= Y
+mrg rxbuf		= Y
+any layout		= Y
+in_order		= Y
+proto host notifier	= Y
+IOMMU platform		= Y
 Linux			= Y
 x86-64			= Y
 Usage doc		= Y
diff --git a/drivers/common/sfc_efx/efsys.h b/drivers/common/sfc_efx/efsys.h
index d133d61..37ec6b9 100644
--- a/drivers/common/sfc_efx/efsys.h
+++ b/drivers/common/sfc_efx/efsys.h
@@ -187,7 +187,7 @@
 
 #define EFSYS_OPT_MAE 1
 
-#define EFSYS_OPT_VIRTIO 0
+#define EFSYS_OPT_VIRTIO 1
 
 /* ID */
 
diff --git a/drivers/common/sfc_efx/version.map b/drivers/common/sfc_efx/version.map
index 642a62e..ec86220 100644
--- a/drivers/common/sfc_efx/version.map
+++ b/drivers/common/sfc_efx/version.map
@@ -247,6 +247,16 @@ INTERNAL {
 	efx_txq_nbufs;
 	efx_txq_size;
 
+	efx_virtio_fini;
+	efx_virtio_get_doorbell_offset;
+	efx_virtio_get_features;
+	efx_virtio_init;
+	efx_virtio_qcreate;
+	efx_virtio_qdestroy;
+	efx_virtio_qstart;
+	efx_virtio_qstop;
+	efx_virtio_verify_features;
+
 	sfc_efx_dev_class_get;
 	sfc_efx_family;
 
diff --git a/drivers/vdpa/sfc/sfc_vdpa.c b/drivers/vdpa/sfc/sfc_vdpa.c
index b7eca56..ccbd243 100644
--- a/drivers/vdpa/sfc/sfc_vdpa.c
+++ b/drivers/vdpa/sfc/sfc_vdpa.c
@@ -43,6 +43,26 @@ struct sfc_vdpa_adapter *
 	return found ? sva : NULL;
 }
 
+struct sfc_vdpa_ops_data *
+sfc_vdpa_get_data_by_dev(struct rte_vdpa_device *vdpa_dev)
+{
+	bool found = false;
+	struct sfc_vdpa_adapter *sva;
+
+	pthread_mutex_lock(&sfc_vdpa_adapter_list_lock);
+
+	TAILQ_FOREACH(sva, &sfc_vdpa_adapter_list, next) {
+		if (vdpa_dev == sva->ops_data->vdpa_dev) {
+			found = true;
+			break;
+		}
+	}
+
+	pthread_mutex_unlock(&sfc_vdpa_adapter_list_lock);
+
+	return found ? sva->ops_data : NULL;
+}
+
 static int
 sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
 {
diff --git a/drivers/vdpa/sfc/sfc_vdpa.h b/drivers/vdpa/sfc/sfc_vdpa.h
index 046f25d..c10c3d3 100644
--- a/drivers/vdpa/sfc/sfc_vdpa.h
+++ b/drivers/vdpa/sfc/sfc_vdpa.h
@@ -60,6 +60,8 @@ struct sfc_vdpa_adapter {
 
 struct sfc_vdpa_adapter *
 sfc_vdpa_get_adapter_by_dev(struct rte_pci_device *pdev);
+struct sfc_vdpa_ops_data *
+sfc_vdpa_get_data_by_dev(struct rte_vdpa_device *vdpa_dev);
 
 int
 sfc_vdpa_hw_init(struct sfc_vdpa_adapter *sva);
diff --git a/drivers/vdpa/sfc/sfc_vdpa_hw.c b/drivers/vdpa/sfc/sfc_vdpa_hw.c
index 7c256ff..7a67bd8 100644
--- a/drivers/vdpa/sfc/sfc_vdpa_hw.c
+++ b/drivers/vdpa/sfc/sfc_vdpa_hw.c
@@ -278,10 +278,20 @@
 	if (rc != 0)
 		goto fail_estimate_rsrc_limits;
 
+	sfc_vdpa_log_init(sva, "init virtio");
+	rc = efx_virtio_init(enp);
+	if (rc != 0) {
+		sfc_vdpa_err(sva, "virtio init failed: %s", rte_strerror(rc));
+		goto fail_virtio_init;
+	}
+
 	sfc_vdpa_log_init(sva, "done");
 
 	return 0;
 
+fail_virtio_init:
+	efx_nic_fini(enp);
+
 fail_estimate_rsrc_limits:
 fail_nic_reset:
 	efx_nic_unprobe(enp);
@@ -310,6 +320,9 @@
 
 	sfc_vdpa_log_init(sva, "entry");
 
+	sfc_vdpa_log_init(sva, "virtio fini");
+	efx_virtio_fini(enp);
+
 	sfc_vdpa_log_init(sva, "unprobe nic");
 	efx_nic_unprobe(enp);
 
diff --git a/drivers/vdpa/sfc/sfc_vdpa_ops.c b/drivers/vdpa/sfc/sfc_vdpa_ops.c
index 71696be..5750944 100644
--- a/drivers/vdpa/sfc/sfc_vdpa_ops.c
+++ b/drivers/vdpa/sfc/sfc_vdpa_ops.c
@@ -3,17 +3,31 @@
  * Copyright(c) 2020-2021 Xilinx, Inc.
  */
 
+#include <rte_errno.h>
 #include <rte_malloc.h>
 #include <rte_vdpa.h>
 #include <rte_vdpa_dev.h>
 #include <rte_vhost.h>
 
+#include "efx.h"
 #include "sfc_vdpa_ops.h"
 #include "sfc_vdpa.h"
 
-/* Dummy functions for mandatory vDPA ops to pass vDPA device registration.
- * In subsequent patches these ops would be implemented.
+/* These protocol features are needed to enable notifier ctrl */
+#define SFC_VDPA_PROTOCOL_FEATURES \
+		((1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
+		 (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \
+		 (1ULL << VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD) | \
+		 (1ULL << VHOST_USER_PROTOCOL_F_HOST_NOTIFIER) | \
+		 (1ULL << VHOST_USER_PROTOCOL_F_LOG_SHMFD))
+
+/*
+ * Set of features which are enabled by default.
+ * Protocol feature bit is needed to enable notification notifier ctrl.
  */
+#define SFC_VDPA_DEFAULT_FEATURES \
+		(1ULL << VHOST_USER_F_PROTOCOL_FEATURES)
+
 static int
 sfc_vdpa_get_queue_num(struct rte_vdpa_device *vdpa_dev, uint32_t *queue_num)
 {
@@ -24,22 +38,67 @@
 }
 
 static int
+sfc_vdpa_get_device_features(struct sfc_vdpa_ops_data *ops_data)
+{
+	int rc;
+	uint64_t dev_features;
+	efx_nic_t *nic;
+
+	nic = sfc_vdpa_adapter_by_dev_handle(ops_data->dev_handle)->nic;
+
+	rc = efx_virtio_get_features(nic, EFX_VIRTIO_DEVICE_TYPE_NET,
+				     &dev_features);
+	if (rc != 0) {
+		sfc_vdpa_err(ops_data->dev_handle,
+			     "could not read device feature: %s",
+			     rte_strerror(rc));
+		return rc;
+	}
+
+	ops_data->dev_features = dev_features;
+
+	sfc_vdpa_info(ops_data->dev_handle,
+		      "device supported virtio features : 0x%" PRIx64,
+		      ops_data->dev_features);
+
+	return 0;
+}
+
+static int
 sfc_vdpa_get_features(struct rte_vdpa_device *vdpa_dev, uint64_t *features)
 {
-	RTE_SET_USED(vdpa_dev);
-	RTE_SET_USED(features);
+	struct sfc_vdpa_ops_data *ops_data;
 
-	return -1;
+	ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
+	if (ops_data == NULL)
+		return -1;
+
+	*features = ops_data->drv_features;
+
+	sfc_vdpa_info(ops_data->dev_handle,
+		      "vDPA ops get_feature :: features : 0x%" PRIx64,
+		      *features);
+
+	return 0;
 }
 
 static int
 sfc_vdpa_get_protocol_features(struct rte_vdpa_device *vdpa_dev,
 			       uint64_t *features)
 {
-	RTE_SET_USED(vdpa_dev);
-	RTE_SET_USED(features);
+	struct sfc_vdpa_ops_data *ops_data;
 
-	return -1;
+	ops_data = sfc_vdpa_get_data_by_dev(vdpa_dev);
+	if (ops_data == NULL)
+		return -1;
+
+	*features = SFC_VDPA_PROTOCOL_FEATURES;
+
+	sfc_vdpa_info(ops_data->dev_handle,
+		      "vDPA ops get_protocol_feature :: features : 0x%" PRIx64,
+		      *features);
+
+	return 0;
 }
 
 static int
@@ -91,6 +150,7 @@ struct sfc_vdpa_ops_data *
 {
 	struct sfc_vdpa_ops_data *ops_data;
 	struct rte_pci_device *pci_dev;
+	int rc;
 
 	/* Create vDPA ops context */
 	ops_data = rte_zmalloc("vdpa", sizeof(struct sfc_vdpa_ops_data), 0);
@@ -111,10 +171,25 @@ struct sfc_vdpa_ops_data *
 		goto fail_register_device;
 	}
 
+	/* Read supported device features */
+	sfc_vdpa_log_init(dev_handle, "get device feature");
+	rc = sfc_vdpa_get_device_features(ops_data);
+	if (rc != 0)
+		goto fail_get_dev_feature;
+
+	/* Driver features are superset of device supported feature
+	 * and any additional features supported by the driver.
+	 */
+	ops_data->drv_features =
+		ops_data->dev_features | SFC_VDPA_DEFAULT_FEATURES;
+
 	ops_data->state = SFC_VDPA_STATE_INITIALIZED;
 
 	return ops_data;
 
+fail_get_dev_feature:
+	rte_vdpa_unregister_device(ops_data->vdpa_dev);
+
 fail_register_device:
 	rte_free(ops_data);
 	return NULL;
diff --git a/drivers/vdpa/sfc/sfc_vdpa_ops.h b/drivers/vdpa/sfc/sfc_vdpa_ops.h
index 817b302..21cbb73 100644
--- a/drivers/vdpa/sfc/sfc_vdpa_ops.h
+++ b/drivers/vdpa/sfc/sfc_vdpa_ops.h
@@ -26,6 +26,9 @@ struct sfc_vdpa_ops_data {
 	struct rte_vdpa_device		*vdpa_dev;
 	enum sfc_vdpa_context		vdpa_context;
 	enum sfc_vdpa_state		state;
+
+	uint64_t			dev_features;
+	uint64_t			drv_features;
 };
 
 struct sfc_vdpa_ops_data *
