This patch depends on the Port Hotplug Framework.
It implements the eth_dev_uninit functions for rte_em_pmd,
rte_igb_pmd and rte_igbvf_pmd.

Signed-off-by: Bernard Iremonger <bernard.iremonger at intel.com>
---
 lib/librte_pmd_e1000/e1000_ethdev.h |    4 +-
 lib/librte_pmd_e1000/em_ethdev.c    |   36 ++++++++++++++++-
 lib/librte_pmd_e1000/igb_ethdev.c   |   73 +++++++++++++++++++++++++++++++++-
 lib/librte_pmd_e1000/igb_pf.c       |   29 +++++++++++++-
 4 files changed, 135 insertions(+), 7 deletions(-)

diff --git a/lib/librte_pmd_e1000/e1000_ethdev.h 
b/lib/librte_pmd_e1000/e1000_ethdev.h
index c451faa..51720b9 100644
--- a/lib/librte_pmd_e1000/e1000_ethdev.h
+++ b/lib/librte_pmd_e1000/e1000_ethdev.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -298,6 +298,8 @@ void eth_igbvf_tx_init(struct rte_eth_dev *dev);
  */
 void igb_pf_host_init(struct rte_eth_dev *eth_dev);

+void igb_pf_host_uninit(struct rte_eth_dev *eth_dev);
+
 void igb_pf_mbx_process(struct rte_eth_dev *eth_dev);

 int igb_pf_host_configure(struct rte_eth_dev *eth_dev);
diff --git a/lib/librte_pmd_e1000/em_ethdev.c b/lib/librte_pmd_e1000/em_ethdev.c
index 76f45c9..2f68251 100644
--- a/lib/librte_pmd_e1000/em_ethdev.c
+++ b/lib/librte_pmd_e1000/em_ethdev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -280,13 +280,45 @@ eth_em_dev_init(struct rte_eth_dev *eth_dev)
        return (0);
 }

+static int
+eth_em_dev_uninit(struct rte_eth_dev *eth_dev)
+{
+       struct rte_pci_device *pci_dev;
+
+       PMD_INIT_FUNC_TRACE();
+
+       if (eth_dev->pci_dev == NULL)
+               return -EINVAL;
+
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return -EPERM;
+
+       pci_dev = eth_dev->pci_dev;
+
+       eth_dev->dev_ops = NULL;
+       eth_dev->rx_pkt_burst = NULL;
+       eth_dev->tx_pkt_burst = NULL;
+
+       rte_free(eth_dev->data->mac_addrs);
+       eth_dev->data->mac_addrs = NULL;
+
+       /* disable uio intr before callback unregister */
+       rte_intr_disable(&(pci_dev->intr_handle));
+       rte_intr_callback_unregister(&(pci_dev->intr_handle),
+               eth_em_interrupt_handler, (void *)eth_dev);
+
+       return 0;
+}
+
 static struct eth_driver rte_em_pmd = {
        {
                .name = "rte_em_pmd",
                .id_table = pci_id_em_map,
-               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
+               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
+                       RTE_PCI_DRV_DETACHABLE,
        },
        .eth_dev_init = eth_em_dev_init,
+       .eth_dev_uninit = eth_em_dev_uninit,
        .dev_private_size = sizeof(struct e1000_adapter),
 };

diff --git a/lib/librte_pmd_e1000/igb_ethdev.c 
b/lib/librte_pmd_e1000/igb_ethdev.c
index b3892a5..f7e3da6 100644
--- a/lib/librte_pmd_e1000/igb_ethdev.c
+++ b/lib/librte_pmd_e1000/igb_ethdev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -608,6 +608,48 @@ err_late:
        return (error);
 }

+static int
+eth_igb_dev_uninit(struct rte_eth_dev *eth_dev)
+{
+       struct rte_pci_device *pci_dev;
+       struct e1000_hw *hw;
+
+       PMD_INIT_FUNC_TRACE();
+
+       if ((eth_dev == NULL) ||
+               (eth_dev->data == NULL) ||
+               (eth_dev->data->dev_private == NULL) ||
+               (eth_dev->pci_dev == NULL))
+               return -EINVAL;
+
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return -EPERM;
+
+       hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private);
+       pci_dev = eth_dev->pci_dev;
+
+       eth_dev->dev_ops = NULL;
+       eth_dev->rx_pkt_burst = NULL;
+       eth_dev->tx_pkt_burst = NULL;
+
+       /* Reset any pending lock */
+       igb_reset_swfw_lock(hw);
+
+       rte_free(eth_dev->data->mac_addrs);
+       eth_dev->data->mac_addrs = NULL;
+
+       /* uninitialize PF if max_vfs not zero */
+       igb_pf_host_uninit(eth_dev);
+
+       /* disable uio intr before callback unregister */
+       rte_intr_disable(&(pci_dev->intr_handle));
+       rte_intr_callback_unregister(&(pci_dev->intr_handle),
+               eth_igb_interrupt_handler, (void *)eth_dev);
+
+       return 0;
+}
+
+
 /*
  * Virtual Function device init
  */
@@ -679,13 +721,37 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev)
        return 0;
 }

+static int
+eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev)
+{
+       PMD_INIT_FUNC_TRACE();
+
+       if ((eth_dev == NULL) ||
+               (eth_dev->data == NULL))
+               return -EINVAL;
+
+       if (rte_eal_process_type() != RTE_PROC_PRIMARY)
+               return -EPERM;
+
+       eth_dev->dev_ops = NULL;
+       eth_dev->rx_pkt_burst = NULL;
+       eth_dev->tx_pkt_burst = NULL;
+
+       rte_free(eth_dev->data->mac_addrs);
+       eth_dev->data->mac_addrs = NULL;
+
+       return 0;
+}
+
 static struct eth_driver rte_igb_pmd = {
        {
                .name = "rte_igb_pmd",
                .id_table = pci_id_igb_map,
-               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
+               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
+                       RTE_PCI_DRV_DETACHABLE,
        },
        .eth_dev_init = eth_igb_dev_init,
+       .eth_dev_uninit = eth_igb_dev_uninit,
        .dev_private_size = sizeof(struct e1000_adapter),
 };

@@ -696,9 +762,10 @@ static struct eth_driver rte_igbvf_pmd = {
        {
                .name = "rte_igbvf_pmd",
                .id_table = pci_id_igbvf_map,
-               .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+               .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_DETACHABLE,
        },
        .eth_dev_init = eth_igbvf_dev_init,
+       .eth_dev_uninit = eth_igbvf_dev_uninit,
        .dev_private_size = sizeof(struct e1000_adapter),
 };

diff --git a/lib/librte_pmd_e1000/igb_pf.c b/lib/librte_pmd_e1000/igb_pf.c
index bc3816a..8c0b764 100644
--- a/lib/librte_pmd_e1000/igb_pf.c
+++ b/lib/librte_pmd_e1000/igb_pf.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -127,6 +127,33 @@ void igb_pf_host_init(struct rte_eth_dev *eth_dev)
        return;
 }

+void igb_pf_host_uninit(struct rte_eth_dev *eth_dev)
+{
+       struct e1000_vf_info **vfinfo;
+       uint16_t vf_num;
+
+       PMD_INIT_FUNC_TRACE();
+
+       if ((eth_dev == NULL) ||
+               (eth_dev->data == NULL) ||
+               (eth_dev->data->dev_private == NULL))
+               return;
+
+       vfinfo = E1000_DEV_PRIVATE_TO_P_VFDATA(eth_dev->data->dev_private);
+
+       RTE_ETH_DEV_SRIOV(eth_dev).active = 0;
+       RTE_ETH_DEV_SRIOV(eth_dev).nb_q_per_pool = 0;
+       RTE_ETH_DEV_SRIOV(eth_dev).def_vmdq_idx = 0;
+       RTE_ETH_DEV_SRIOV(eth_dev).def_pool_q_idx = 0;
+
+       vf_num = dev_num_vf(eth_dev);
+       if (vf_num == 0)
+               return;
+
+       rte_free(*vfinfo);
+       *vfinfo = NULL;
+}
+
 #define E1000_RAH_POOLSEL_SHIFT    (18)
 int igb_pf_host_configure(struct rte_eth_dev *eth_dev)
 {
-- 
1.7.4.1

Reply via email to