diff --git a/Documentation/howto/dpdk.rst b/Documentation/howto/dpdk.rst
index dc63f7d..20d8975 100644
--- a/Documentation/howto/dpdk.rst
+++ b/Documentation/howto/dpdk.rst
@@ -342,10 +342,9 @@ Then it can be attached to OVS::
     $ ovs-vsctl add-port br0 dpdkx -- set Interface dpdkx type=dpdk \
         options:dpdk-devargs=0000:01:00.0
 
-It is also possible to detach a port from ovs, the user has to remove the
-port using the del-port command, then it can be detached using::
+Detaching will be performed while processing del-port command::
 
-    $ ovs-appctl netdev-dpdk/detach 0000:01:00.0
+    $ ovs-vsctl del-port dpdkx
 
 This feature is not supported with VFIO and does not work with some NICs.
 For more information please refer to the `DPDK Port Hotplug Framework
diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c
index c8d7108..658a454 100644
--- a/lib/netdev-dpdk.c
+++ b/lib/netdev-dpdk.c
@@ -359,6 +359,9 @@ struct netdev_dpdk {
     /* Device arguments for dpdk ports */
     char *devargs;
 
+    /* If true, device was attached by rte_eth_dev_attach(). */
+    bool attached;
+
     /* In dpdk_list. */
     struct ovs_list list_node OVS_GUARDED_BY(dpdk_mutex);
 
@@ -851,6 +854,7 @@ common_construct(struct netdev *netdev, unsigned int port_no,
     dev->max_packet_len = MTU_TO_FRAME_LEN(dev->mtu);
     ovsrcu_index_init(&dev->vid, -1);
     dev->vhost_reconfigured = false;
+    dev->attached = false;
 
     ovsrcu_init(&dev->qos_conf, NULL);
 
@@ -996,10 +1000,21 @@ static void
 netdev_dpdk_destruct(struct netdev *netdev)
 {
     struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
+    char devname[RTE_ETH_NAME_MAX_LEN];
 
     ovs_mutex_lock(&dpdk_mutex);
 
     rte_eth_dev_stop(dev->port_id);
+
+    if (dev->attached) {
+        rte_eth_dev_close(dev->port_id);
+        if (rte_eth_dev_detach(dev->port_id, devname) < 0) {
+            VLOG_ERR("Device '%s' can not be detached", dev->devargs);
+        } else {
+            VLOG_INFO("Device '%s' detached", devname);
+        }
+    }
+
     free(dev->devargs);
     common_destruct(dev);
 
@@ -1128,6 +1143,7 @@ netdev_dpdk_process_devargs(const char *devargs, char **errp)
         /* Device not found in DPDK, attempt to attach it */
         if (!rte_eth_dev_attach(devargs, &new_port_id)) {
             /* Attach successful */
+            dev->attached = true;
             VLOG_INFO("Device '%s' attached to DPDK", devargs);
         } else {
             /* Attach unsuccessful */
@@ -2436,53 +2452,6 @@ netdev_dpdk_set_admin_state(struct unixctl_conn *conn, int argc,
     unixctl_command_reply(conn, "OK");
 }
 
-static void
-netdev_dpdk_detach(struct unixctl_conn *conn, int argc OVS_UNUSED,
-                   const char *argv[], void *aux OVS_UNUSED)
-{
-    int ret;
-    char *response;
-    uint8_t port_id;
-    char devname[RTE_ETH_NAME_MAX_LEN];
-    struct netdev_dpdk *dev;
-
-    ovs_mutex_lock(&dpdk_mutex);
-
-    if (!rte_eth_dev_count() || rte_eth_dev_get_port_by_name(argv[1],
-                                                             &port_id)) {
-        response = xasprintf("Device '%s' not found in DPDK", argv[1]);
-        goto error;
-    }
-
-    dev = netdev_dpdk_lookup_by_port_id(port_id);
-    if (dev) {
-        response = xasprintf("Device '%s' is being used by interface '%s'. "
-                             "Remove it before detaching",
-                             argv[1], netdev_get_name(&dev->up));
-        goto error;
-    }
-
-    rte_eth_dev_close(port_id);
-
-    ret = rte_eth_dev_detach(port_id, devname);
-    if (ret < 0) {
-        response = xasprintf("Device '%s' can not be detached", argv[1]);
-        goto error;
-    }
-
-    response = xasprintf("Device '%s' has been detached", argv[1]);
-
-    ovs_mutex_unlock(&dpdk_mutex);
-    unixctl_command_reply(conn, response);
-    free(response);
-    return;
-
-error:
-    ovs_mutex_unlock(&dpdk_mutex);
-    unixctl_command_reply_error(conn, response);
-    free(response);
-}
-
 /*
  * Set virtqueue flags so that we do not receive interrupts.
  */
@@ -2758,9 +2727,6 @@ netdev_dpdk_class_init(void)
         unixctl_command_register("netdev-dpdk/set-admin-state",
                                  "[netdev] up|down", 1, 2,
                                  netdev_dpdk_set_admin_state, NULL);
-        unixctl_command_register("netdev-dpdk/detach",
-                                 "pci address of device", 1, 1,
-                                 netdev_dpdk_detach, NULL);
 
         ovsthread_once_done(&once);
     }
