From: Bernard Iremonger Date: Fri, 3 Jul 2015 14:38:26 +0000 (+0100) Subject: e1000: support port hotplug X-Git-Tag: spdx-start~8698 X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=b9eee2cb8c291d9063297c8a36d042eb59190ae9;p=dpdk.git e1000: support port hotplug 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 Acked-by: Helin Zhang --- diff --git a/drivers/net/e1000/e1000_ethdev.h b/drivers/net/e1000/e1000_ethdev.h index c451faa556..ee8b87278d 100644 --- a/drivers/net/e1000/e1000_ethdev.h +++ b/drivers/net/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 @@ -229,8 +229,12 @@ struct e1000_adapter { struct e1000_vfta shadow_vfta; struct e1000_vf_info *vfdata; struct e1000_filter_info filter; + bool stopped; }; +#define E1000_DEV_PRIVATE(adapter) \ + ((struct e1000_adapter *)adapter) + #define E1000_DEV_PRIVATE_TO_HW(adapter) \ (&((struct e1000_adapter *)adapter)->hw) @@ -337,4 +341,6 @@ uint16_t eth_em_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t eth_em_recv_scattered_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts); +void igb_pf_host_uninit(struct rte_eth_dev *dev); + #endif /* _E1000_ETHDEV_H_ */ diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c index a306c55331..dfabb158ca 100644 --- a/drivers/net/e1000/em_ethdev.c +++ b/drivers/net/e1000/em_ethdev.c @@ -224,6 +224,8 @@ static int eth_em_dev_init(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(eth_dev->data->dev_private); struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); struct e1000_vfta * shadow_vfta = @@ -246,6 +248,7 @@ eth_em_dev_init(struct rte_eth_dev *eth_dev) hw->hw_addr = (void *)pci_dev->mem_resource[0].addr; hw->device_id = pci_dev->id.device_id; + adapter->stopped = 0; /* For ICH8 support we'll need to map the flash memory BAR */ @@ -285,13 +288,47 @@ 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; + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(eth_dev->data->dev_private); + + PMD_INIT_FUNC_TRACE(); + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return -EPERM; + + pci_dev = eth_dev->pci_dev; + + if (adapter->stopped == 0) + eth_em_close(eth_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 = { .pci_drv = { .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), }; @@ -451,6 +488,8 @@ em_set_pba(struct e1000_hw *hw) static int eth_em_start(struct rte_eth_dev *dev) { + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(dev->data->dev_private); struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); int ret, mask; @@ -570,6 +609,8 @@ eth_em_start(struct rte_eth_dev *dev) } } + adapter->stopped = 0; + PMD_INIT_LOG(DEBUG, "<<"); return (0); @@ -613,8 +654,11 @@ static void eth_em_close(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(dev->data->dev_private); eth_em_stop(dev); + adapter->stopped = 1; e1000_phy_hw_reset(hw); em_release_manageability(hw); em_hw_control_release(hw); diff --git a/drivers/net/e1000/em_rxtx.c b/drivers/net/e1000/em_rxtx.c index 38f5c3b732..6a5410c986 100644 --- a/drivers/net/e1000/em_rxtx.c +++ b/drivers/net/e1000/em_rxtx.c @@ -1513,6 +1513,18 @@ em_dev_clear_queues(struct rte_eth_dev *dev) em_reset_rx_queue(rxq); } } + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + eth_em_rx_queue_release(dev->data->rx_queues[i]); + dev->data->rx_queues[i] = NULL; + } + dev->data->nb_rx_queues = 0; + + for (i = 0; i < dev->data->nb_tx_queues; i++) { + eth_em_tx_queue_release(dev->data->tx_queues[i]); + dev->data->tx_queues[i] = NULL; + } + dev->data->nb_tx_queues = 0; } /* diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c index 6a0c55c856..1b9f69afb9 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -510,9 +510,12 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev) struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); struct e1000_vfta * shadow_vfta = - E1000_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private); + E1000_DEV_PRIVATE_TO_VFTA(eth_dev->data->dev_private); struct e1000_filter_info *filter_info = E1000_DEV_PRIVATE_TO_FILTER_INFO(eth_dev->data->dev_private); + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(eth_dev->data->dev_private); + uint32_t ctrl_ext; pci_dev = eth_dev->pci_dev; @@ -615,6 +618,7 @@ eth_igb_dev_init(struct rte_eth_dev *eth_dev) goto err_late; } hw->mac.get_link_status = 1; + adapter->stopped = 0; /* Indicate SOL/IDER usage */ if (e1000_check_reset_block(hw) < 0) { @@ -659,6 +663,46 @@ 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; + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(eth_dev->data->dev_private); + + PMD_INIT_FUNC_TRACE(); + + 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; + + if (adapter->stopped == 0) + eth_igb_close(eth_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 */ @@ -666,6 +710,8 @@ static int eth_igbvf_dev_init(struct rte_eth_dev *eth_dev) { struct rte_pci_device *pci_dev; + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(eth_dev->data->dev_private); struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(eth_dev->data->dev_private); int diag; @@ -690,6 +736,7 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev) hw->device_id = pci_dev->id.device_id; hw->vendor_id = pci_dev->id.vendor_id; hw->hw_addr = (void *)pci_dev->mem_resource[0].addr; + adapter->stopped = 0; /* Initialize the shared code (base driver) */ diag = e1000_setup_init_funcs(hw, TRUE); @@ -730,13 +777,39 @@ eth_igbvf_dev_init(struct rte_eth_dev *eth_dev) return 0; } +static int +eth_igbvf_dev_uninit(struct rte_eth_dev *eth_dev) +{ + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(eth_dev->data->dev_private); + + PMD_INIT_FUNC_TRACE(); + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return -EPERM; + + if (adapter->stopped == 0) + igbvf_dev_close(eth_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; + + return 0; +} + static struct eth_driver rte_igb_pmd = { .pci_drv = { .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), }; @@ -747,9 +820,10 @@ static struct eth_driver rte_igbvf_pmd = { .pci_drv = { .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), }; @@ -803,6 +877,8 @@ eth_igb_start(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(dev->data->dev_private); int ret, i, mask; uint32_t ctrl_ext; @@ -831,6 +907,7 @@ eth_igb_start(struct rte_eth_dev *dev) PMD_INIT_LOG(ERR, "Unable to initialize the hardware"); return (-EIO); } + adapter->stopped = 0; E1000_WRITE_REG(hw, E1000_VET, ETHER_TYPE_VLAN << 16 | ETHER_TYPE_VLAN); @@ -1037,9 +1114,13 @@ static void eth_igb_close(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(dev->data->dev_private); struct rte_eth_link link; eth_igb_stop(dev); + adapter->stopped = 1; + e1000_phy_hw_reset(hw); igb_release_manageability(hw); igb_hw_control_release(hw); @@ -2282,11 +2363,14 @@ igbvf_dev_start(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(dev->data->dev_private); int ret; PMD_INIT_FUNC_TRACE(); hw->mac.ops.reset_hw(hw); + adapter->stopped = 0; /* Set all vfta */ igbvf_set_vfta_all(dev,1); @@ -2324,12 +2408,15 @@ static void igbvf_dev_close(struct rte_eth_dev *dev) { struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct e1000_adapter *adapter = + E1000_DEV_PRIVATE(dev->data->dev_private); PMD_INIT_FUNC_TRACE(); e1000_reset_hw(hw); igbvf_dev_stop(dev); + adapter->stopped = 1; } static int igbvf_set_vfta(struct e1000_hw *hw, uint16_t vid, bool on) diff --git a/drivers/net/e1000/igb_pf.c b/drivers/net/e1000/igb_pf.c index 6a4d210fad..26c2960eb1 100644 --- a/drivers/net/e1000/igb_pf.c +++ b/drivers/net/e1000/igb_pf.c @@ -127,6 +127,28 @@ void igb_pf_host_init(struct rte_eth_dev *eth_dev) return; } +void igb_pf_host_uninit(struct rte_eth_dev *dev) +{ + struct e1000_vf_info **vfinfo; + uint16_t vf_num; + + PMD_INIT_FUNC_TRACE(); + + vfinfo = E1000_DEV_PRIVATE_TO_P_VFDATA(dev->data->dev_private); + + RTE_ETH_DEV_SRIOV(dev).active = 0; + RTE_ETH_DEV_SRIOV(dev).nb_q_per_pool = 0; + RTE_ETH_DEV_SRIOV(dev).def_vmdq_idx = 0; + RTE_ETH_DEV_SRIOV(dev).def_pool_q_idx = 0; + + vf_num = dev_num_vf(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) { diff --git a/drivers/net/e1000/igb_rxtx.c b/drivers/net/e1000/igb_rxtx.c index 165144c944..3fee735346 100644 --- a/drivers/net/e1000/igb_rxtx.c +++ b/drivers/net/e1000/igb_rxtx.c @@ -1602,6 +1602,18 @@ igb_dev_clear_queues(struct rte_eth_dev *dev) igb_reset_rx_queue(rxq); } } + + for (i = 0; i < dev->data->nb_rx_queues; i++) { + eth_igb_rx_queue_release(dev->data->rx_queues[i]); + dev->data->rx_queues[i] = NULL; + } + dev->data->nb_rx_queues = 0; + + for (i = 0; i < dev->data->nb_tx_queues; i++) { + eth_igb_tx_queue_release(dev->data->tx_queues[i]); + dev->data->tx_queues[i] = NULL; + } + dev->data->nb_tx_queues = 0; } /**