X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fnet%2Ftxgbe%2Ftxgbe_ethdev_vf.c;h=63a45d32c12a555e815851d1d26c500a719dd4e6;hb=9f1b1fbbdd483836f30004ce5db3b99080ebf718;hp=bc373f0526c1bbbece9978df0a169f8d72181be5;hpb=66ffac9a80477609c17e461728374f99c7120f52;p=dpdk.git diff --git a/drivers/net/txgbe/txgbe_ethdev_vf.c b/drivers/net/txgbe/txgbe_ethdev_vf.c index bc373f0526..63a45d32c1 100644 --- a/drivers/net/txgbe/txgbe_ethdev_vf.c +++ b/drivers/net/txgbe/txgbe_ethdev_vf.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "txgbe_logs.h" #include "base/txgbe.h" @@ -50,8 +51,10 @@ static int txgbevf_dev_xstats_get(struct rte_eth_dev *dev, static int txgbevf_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info); static int txgbevf_dev_configure(struct rte_eth_dev *dev); +static int txgbevf_dev_start(struct rte_eth_dev *dev); static int txgbevf_dev_link_update(struct rte_eth_dev *dev, int wait_to_complete); +static int txgbevf_dev_stop(struct rte_eth_dev *dev); static int txgbevf_dev_close(struct rte_eth_dev *dev); static void txgbevf_intr_disable(struct rte_eth_dev *dev); static void txgbevf_intr_enable(struct rte_eth_dev *dev); @@ -603,18 +606,168 @@ txgbevf_dev_configure(struct rte_eth_dev *dev) return 0; } +static int +txgbevf_dev_start(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t intr_vector = 0; + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + + int err, mask = 0; + + PMD_INIT_FUNC_TRACE(); + + /* Stop the link setup handler before resetting the HW. */ + rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler, dev); + + err = hw->mac.reset_hw(hw); + if (err) { + PMD_INIT_LOG(ERR, "Unable to reset vf hardware (%d)", err); + return err; + } + hw->mac.get_link_status = true; + + /* negotiate mailbox API version to use with the PF. */ + txgbevf_negotiate_api(hw); + + txgbevf_dev_tx_init(dev); + + /* This can fail when allocating mbufs for descriptor rings */ + err = txgbevf_dev_rx_init(dev); + + /** + * In this case, reuses the MAC address assigned by VF + * initialization. + */ + if (err != 0 && err != TXGBE_ERR_INVALID_MAC_ADDR) { + PMD_INIT_LOG(ERR, "Unable to initialize RX hardware (%d)", err); + txgbe_dev_clear_queues(dev); + return err; + } + + /* Set vfta */ + txgbevf_set_vfta_all(dev, 1); + + /* Set HW strip */ + mask = ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK | + ETH_VLAN_EXTEND_MASK; + err = txgbevf_vlan_offload_config(dev, mask); + if (err) { + PMD_INIT_LOG(ERR, "Unable to set VLAN offload (%d)", err); + txgbe_dev_clear_queues(dev); + return err; + } + + txgbevf_dev_rxtx_start(dev); + + /* check and configure queue intr-vector mapping */ + if (rte_intr_cap_multiple(intr_handle) && + dev->data->dev_conf.intr_conf.rxq) { + /* According to datasheet, only vector 0/1/2 can be used, + * now only one vector is used for Rx queue + */ + intr_vector = 1; + if (rte_intr_efd_enable(intr_handle, intr_vector)) + return -1; + } + + if (rte_intr_dp_is_en(intr_handle) && !intr_handle->intr_vec) { + intr_handle->intr_vec = + rte_zmalloc("intr_vec", + dev->data->nb_rx_queues * sizeof(int), 0); + if (intr_handle->intr_vec == NULL) { + PMD_INIT_LOG(ERR, "Failed to allocate %d rx_queues" + " intr_vec", dev->data->nb_rx_queues); + return -ENOMEM; + } + } + txgbevf_configure_msix(dev); + + /* When a VF port is bound to VFIO-PCI, only miscellaneous interrupt + * is mapped to VFIO vector 0 in eth_txgbevf_dev_init( ). + * If previous VFIO interrupt mapping setting in eth_txgbevf_dev_init( ) + * is not cleared, it will fail when following rte_intr_enable( ) tries + * to map Rx queue interrupt to other VFIO vectors. + * So clear uio/vfio intr/evevnfd first to avoid failure. + */ + rte_intr_disable(intr_handle); + + rte_intr_enable(intr_handle); + + /* Re-enable interrupt for VF */ + txgbevf_intr_enable(dev); + + /* + * Update link status right before return, because it may + * start link configuration process in a separate thread. + */ + txgbevf_dev_link_update(dev, 0); + + hw->adapter_stopped = false; + + return 0; +} + +static int +txgbevf_dev_stop(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + struct txgbe_adapter *adapter = TXGBE_DEV_ADAPTER(dev); + struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); + struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + + if (hw->adapter_stopped) + return 0; + + PMD_INIT_FUNC_TRACE(); + + rte_eal_alarm_cancel(txgbe_dev_setup_link_alarm_handler, dev); + + txgbevf_intr_disable(dev); + + hw->adapter_stopped = 1; + hw->mac.stop_hw(hw); + + /* + * Clear what we set, but we still keep shadow_vfta to + * restore after device starts + */ + txgbevf_set_vfta_all(dev, 0); + + /* Clear stored conf */ + dev->data->scattered_rx = 0; + + txgbe_dev_clear_queues(dev); + + /* Clean datapath event and queue/vec mapping */ + rte_intr_efd_disable(intr_handle); + if (intr_handle->intr_vec != NULL) { + rte_free(intr_handle->intr_vec); + intr_handle->intr_vec = NULL; + } + + adapter->rss_reta_updated = 0; + + return 0; +} + static int txgbevf_dev_close(struct rte_eth_dev *dev) { struct txgbe_hw *hw = TXGBE_DEV_HW(dev); struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev); struct rte_intr_handle *intr_handle = &pci_dev->intr_handle; + int ret; + PMD_INIT_FUNC_TRACE(); if (rte_eal_process_type() != RTE_PROC_PRIMARY) return 0; hw->mac.reset_hw(hw); + ret = txgbevf_dev_stop(dev); + txgbe_dev_free_queues(dev); /** @@ -637,7 +790,24 @@ txgbevf_dev_close(struct rte_eth_dev *dev) rte_intr_callback_unregister(intr_handle, txgbevf_dev_interrupt_handler, dev); - return 0; + return ret; +} + +/* + * Reset VF device + */ +static int +txgbevf_dev_reset(struct rte_eth_dev *dev) +{ + int ret; + + ret = eth_txgbevf_dev_uninit(dev); + if (ret) + return ret; + + ret = eth_txgbevf_dev_init(dev); + + return ret; } static void txgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on) @@ -1170,21 +1340,30 @@ txgbevf_dev_interrupt_handler(void *param) */ static const struct eth_dev_ops txgbevf_eth_dev_ops = { .dev_configure = txgbevf_dev_configure, + .dev_start = txgbevf_dev_start, + .dev_stop = txgbevf_dev_stop, .link_update = txgbevf_dev_link_update, .stats_get = txgbevf_dev_stats_get, .xstats_get = txgbevf_dev_xstats_get, .stats_reset = txgbevf_dev_stats_reset, .xstats_reset = txgbevf_dev_stats_reset, .xstats_get_names = txgbevf_dev_xstats_get_names, + .dev_close = txgbevf_dev_close, + .dev_reset = txgbevf_dev_reset, .promiscuous_enable = txgbevf_dev_promiscuous_enable, .promiscuous_disable = txgbevf_dev_promiscuous_disable, .allmulticast_enable = txgbevf_dev_allmulticast_enable, .allmulticast_disable = txgbevf_dev_allmulticast_disable, .dev_infos_get = txgbevf_dev_info_get, + .dev_supported_ptypes_get = txgbe_dev_supported_ptypes_get, .mtu_set = txgbevf_dev_set_mtu, .vlan_filter_set = txgbevf_vlan_filter_set, .vlan_strip_queue_set = txgbevf_vlan_strip_queue_set, .vlan_offload_set = txgbevf_vlan_offload_set, + .rx_queue_setup = txgbe_dev_rx_queue_setup, + .rx_queue_release = txgbe_dev_rx_queue_release, + .tx_queue_setup = txgbe_dev_tx_queue_setup, + .tx_queue_release = txgbe_dev_tx_queue_release, .rx_queue_intr_enable = txgbevf_dev_rx_queue_intr_enable, .rx_queue_intr_disable = txgbevf_dev_rx_queue_intr_disable, .mac_addr_add = txgbevf_add_mac_addr, @@ -1198,6 +1377,7 @@ static const struct eth_dev_ops txgbevf_eth_dev_ops = { .reta_query = txgbe_dev_rss_reta_query, .rss_hash_update = txgbe_dev_rss_hash_update, .rss_hash_conf_get = txgbe_dev_rss_hash_conf_get, + .tx_done_cleanup = txgbe_dev_tx_done_cleanup, }; RTE_PMD_REGISTER_PCI(net_txgbe_vf, rte_txgbevf_pmd);