diff --git a/drivers/net/sfc/sfc.c b/drivers/net/sfc/sfc.c
index 2a17d26..cbb14d7 100644
--- a/drivers/net/sfc/sfc.c
+++ b/drivers/net/sfc/sfc.c
@@ -82,6 +82,35 @@ sfc_dma_free(const struct sfc_adapter *sa, efsys_mem_t *esmp)
 	memset(esmp, 0, sizeof(*esmp));
 }
 
+int
+sfc_configure(struct sfc_adapter *sa)
+{
+	sfc_log_init(sa, "entry");
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED);
+	sa->state = SFC_ADAPTER_CONFIGURING;
+
+	sa->state = SFC_ADAPTER_CONFIGURED;
+	sfc_log_init(sa, "done");
+	return 0;
+}
+
+void
+sfc_close(struct sfc_adapter *sa)
+{
+	sfc_log_init(sa, "entry");
+
+	SFC_ASSERT(sfc_adapter_is_locked(sa));
+
+	SFC_ASSERT(sa->state == SFC_ADAPTER_CONFIGURED);
+	sa->state = SFC_ADAPTER_CLOSING;
+
+	sa->state = SFC_ADAPTER_INITIALIZED;
+	sfc_log_init(sa, "done");
+}
+
 static int
 sfc_mem_bar_init(struct sfc_adapter *sa)
 {
diff --git a/drivers/net/sfc/sfc.h b/drivers/net/sfc/sfc.h
index b9a0b0b..c664fb6 100644
--- a/drivers/net/sfc/sfc.h
+++ b/drivers/net/sfc/sfc.h
@@ -50,11 +50,28 @@ extern "C" {
  *	V			|
  * +---------------+------------+
  * |  INITIALIZED  |
+ * +---------------+<-----------+
+ *	|.dev_configure		|
+ *	V			|
+ * +---------------+		|
+ * |  CONFIGURING  |------------^
+ * +---------------+ failed	|
+ *	|success		|
+ *	|		+---------------+
+ *	|		|    CLOSING    |
+ *	|		+---------------+
+ *	|			^
+ *	V			|.dev_close
+ * +---------------+------------+
+ * |  CONFIGURED   |
  * +---------------+
  */
 enum sfc_adapter_state {
 	SFC_ADAPTER_UNINITIALIZED = 0,
 	SFC_ADAPTER_INITIALIZED,
+	SFC_ADAPTER_CONFIGURING,
+	SFC_ADAPTER_CONFIGURED,
+	SFC_ADAPTER_CLOSING,
 
 	SFC_ADAPTER_NSTATES
 };
@@ -78,11 +95,10 @@ struct sfc_mcdi {
 /* Adapter private data */
 struct sfc_adapter {
 	/*
-	 * PMD setup and configuration is not thread safe.
-	 * Since it is not performance sensitive, it is better to guarantee
-	 * thread-safety and add device level lock.
-	 * Adapter control operations which change its state should
-	 * acquire the lock.
+	 * PMD setup and configuration is not thread safe. Since it is not
+	 * performance sensitive, it is better to guarantee thread-safety
+	 * and add device level lock. Adapter control operations which
+	 * change its state should acquire the lock.
 	 */
 	rte_spinlock_t			lock;
 	enum sfc_adapter_state		state;
@@ -146,6 +162,9 @@ void sfc_detach(struct sfc_adapter *sa);
 int sfc_mcdi_init(struct sfc_adapter *sa);
 void sfc_mcdi_fini(struct sfc_adapter *sa);
 
+int sfc_configure(struct sfc_adapter *sa);
+void sfc_close(struct sfc_adapter *sa);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/drivers/net/sfc/sfc_ethdev.c b/drivers/net/sfc/sfc_ethdev.c
index 381f90c..ca46b7d 100644
--- a/drivers/net/sfc/sfc_ethdev.c
+++ b/drivers/net/sfc/sfc_ethdev.c
@@ -49,7 +49,65 @@ sfc_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
 	sfc_log_init(sa, "entry");
 }
 
+static int
+sfc_dev_configure(struct rte_eth_dev *dev)
+{
+	struct rte_eth_dev_data *dev_data = dev->data;
+	struct sfc_adapter *sa = dev_data->dev_private;
+	int rc;
+
+	sfc_log_init(sa, "entry n_rxq=%u n_txq=%u",
+		     dev_data->nb_rx_queues, dev_data->nb_tx_queues);
+
+	sfc_adapter_lock(sa);
+	switch (sa->state) {
+	case SFC_ADAPTER_CONFIGURED:
+		sfc_close(sa);
+		SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED);
+		/* FALLTHROUGH */
+	case SFC_ADAPTER_INITIALIZED:
+		rc = sfc_configure(sa);
+		break;
+	default:
+		sfc_err(sa, "unexpected adapter state %u to configure",
+			sa->state);
+		rc = EINVAL;
+		break;
+	}
+	sfc_adapter_unlock(sa);
+
+	sfc_log_init(sa, "done %d", rc);
+	SFC_ASSERT(rc >= 0);
+	return -rc;
+}
+
+static void
+sfc_dev_close(struct rte_eth_dev *dev)
+{
+	struct sfc_adapter *sa = dev->data->dev_private;
+
+	sfc_log_init(sa, "entry");
+
+	sfc_adapter_lock(sa);
+	switch (sa->state) {
+	case SFC_ADAPTER_CONFIGURED:
+		sfc_close(sa);
+		SFC_ASSERT(sa->state == SFC_ADAPTER_INITIALIZED);
+		/* FALLTHROUGH */
+	case SFC_ADAPTER_INITIALIZED:
+		break;
+	default:
+		sfc_err(sa, "unexpected adapter state %u on close", sa->state);
+		break;
+	}
+	sfc_adapter_unlock(sa);
+
+	sfc_log_init(sa, "done");
+}
+
 static const struct eth_dev_ops sfc_eth_dev_ops = {
+	.dev_configure			= sfc_dev_configure,
+	.dev_close			= sfc_dev_close,
 	.dev_infos_get			= sfc_dev_infos_get,
 };
 
