diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index befe68d..8c780ac 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -127,6 +127,71 @@ sfc_check_conf(struct sfc_adapter *sa)
 }
 
 int
+sfc_start(struct sfc_adapter *sa)
+{
+	int rc;
+
+	sfc_log_init(sa, "entry");
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	switch (sa->state) {
+	case SFC_ADAPTER_CONFIGURED:
+		break;
+	case SFC_ADAPTER_STARTED:
+		sfc_info(sa, "already started");
+		return 0;
+	default:
+		rc = EINVAL;
+		goto fail_bad_state;
+	}
+
+	sa->state = SFC_ADAPTER_STARTING;
+
+	sfc_log_init(sa, "init nic");
+	rc = efx_nic_init(sa->nic);
+	if (rc != 0)
+		goto fail_nic_init;
+
+	sa->state = SFC_ADAPTER_STARTED;
+	sfc_log_init(sa, "done");
+	return 0;
+
+fail_nic_init:
+	sa->state = SFC_ADAPTER_CONFIGURED;
+fail_bad_state:
+	sfc_log_init(sa, "failed %d", rc);
+	return rc;
+}
+
+void
+sfc_stop(struct sfc_adapter *sa)
+{
+	sfc_log_init(sa, "entry");
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	switch (sa->state) {
+	case SFC_ADAPTER_STARTED:
+		break;
+	case SFC_ADAPTER_CONFIGURED:
+		sfc_info(sa, "already stopped");
+		return;
+	default:
+		sfc_err(sa, "stop in unexpected state %u", sa->state);
+		SFC_ASSERT(B_FALSE);
+		return;
+	}
+
+	sa->state = SFC_ADAPTER_STOPPING;
+
+	efx_nic_fini(sa->nic);
+
+	sa->state = SFC_ADAPTER_CONFIGURED;
+	sfc_log_init(sa, "done");
+}
+
+int
 sfc_configure(struct sfc_adapter *sa)
 {
 	int rc;
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index c664fb6..4b16b40 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -64,6 +64,20 @@ extern "C" {
  *	V			|.dev_close
  * +---------------+------------+
  * |  CONFIGURED   |
+ * +---------------+<-----------+
+ *	|.dev_start		|
+ *	V			|
+ * +---------------+		|
+ * |   STARTING    |------------^
+ * +---------------+ failed	|
+ *	|success		|
+ *	|		+---------------+
+ *	|		|   STOPPING    |
+ *	|		+---------------+
+ *	|			^
+ *	V			|.dev_stop
+ * +---------------+------------+
+ * |    STARTED    |
  * +---------------+
  */
 enum sfc_adapter_state {
@@ -72,6 +86,9 @@ enum sfc_adapter_state {
 	SFC_ADAPTER_CONFIGURING,
 	SFC_ADAPTER_CONFIGURED,
 	SFC_ADAPTER_CLOSING,
+	SFC_ADAPTER_STARTING,
+	SFC_ADAPTER_STARTED,
+	SFC_ADAPTER_STOPPING,
 
 	SFC_ADAPTER_NSTATES
 };
@@ -158,6 +175,8 @@ void sfc_dma_free(const struct sfc_adapter *sa, efsys_mem_t *esmp);
 
 int sfc_attach(struct sfc_adapter *sa);
 void sfc_detach(struct sfc_adapter *sa);
+int sfc_start(struct sfc_adapter *sa);
+void sfc_stop(struct sfc_adapter *sa);
 
 int sfc_mcdi_init(struct sfc_adapter *sa);
 void sfc_mcdi_fini(struct sfc_adapter *sa);
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index ca46b7d..3d22654 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -81,6 +81,37 @@ sfc_dev_configure(struct rte_eth_dev *dev)
 	return -rc;
 }
 
+static int
+sfc_dev_start(struct rte_eth_dev *dev)
+{
+	struct sfc_adapter *sa = dev->data->dev_private;
+	int rc;
+
+	sfc_log_init(sa, "entry");
+
+	sfc_adapter_lock(sa);
+	rc = sfc_start(sa);
+	sfc_adapter_unlock(sa);
+
+	sfc_log_init(sa, "done %d", rc);
+	SFC_ASSERT(rc >= 0);
+	return -rc;
+}
+
+static void
+sfc_dev_stop(struct rte_eth_dev *dev)
+{
+	struct sfc_adapter *sa = dev->data->dev_private;
+
+	sfc_log_init(sa, "entry");
+
+	sfc_adapter_lock(sa);
+	sfc_stop(sa);
+	sfc_adapter_unlock(sa);
+
+	sfc_log_init(sa, "done");
+}
+
 static void
 sfc_dev_close(struct rte_eth_dev *dev)
 {
@@ -90,6 +121,10 @@ sfc_dev_close(struct rte_eth_dev *dev)
 
 	sfc_adapter_lock(sa);
 	switch (sa->state) {
+	case SFC_ADAPTER_STARTED:
+		sfc_stop(sa);
+		SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED);
+		/* FALLTHROUGH */
 	case SFC_ADAPTER_CONFIGURED:
 		sfc_close(sa);
 		SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED);
@@ -107,6 +142,8 @@ sfc_dev_close(struct rte_eth_dev *dev)
 
 static const struct eth_dev_ops sfc_eth_dev_ops = {
 	.dev_configure			= sfc_dev_configure,
+	.dev_start			= sfc_dev_start,
+	.dev_stop			= sfc_dev_stop,
 	.dev_close			= sfc_dev_close,
 	.dev_infos_get			= sfc_dev_infos_get,
 };
