X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Ftxgbe%2Ftxgbe_ethdev_vf.c;h=896da8a88770a714ecb46fff91b419e22ff13f61;hb=b37ed6def36798342172f298516c5fc6d0d8e070;hp=b1573100e0188c11d2552498d8273e192fddaff9;hpb=aa1ae7941e716671277c1fe00807a77ddc6a6a60;p=dpdk.git diff --git a/drivers/net/txgbe/txgbe_ethdev_vf.c b/drivers/net/txgbe/txgbe_ethdev_vf.c index b1573100e0..896da8a887 100644 --- a/drivers/net/txgbe/txgbe_ethdev_vf.c +++ b/drivers/net/txgbe/txgbe_ethdev_vf.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2015-2020 + * Copyright(c) 2015-2020 Beijing WangXun Technology Co., Ltd. + * Copyright(c) 2010-2017 Intel Corporation */ #include @@ -9,19 +10,52 @@ #include #include #include +#include #include "txgbe_logs.h" #include "base/txgbe.h" #include "txgbe_ethdev.h" #include "txgbe_rxtx.h" +#include "txgbe_regs_group.h" + +static const struct reg_info txgbevf_regs_general[] = { + {TXGBE_VFRST, 1, 1, "TXGBE_VFRST"}, + {TXGBE_VFSTATUS, 1, 1, "TXGBE_VFSTATUS"}, + {TXGBE_VFMBCTL, 1, 1, "TXGBE_VFMAILBOX"}, + {TXGBE_VFMBX, 16, 4, "TXGBE_VFMBX"}, + {TXGBE_VFPBWRAP, 1, 1, "TXGBE_VFPBWRAP"}, + {0, 0, 0, ""} +}; + +static const struct reg_info txgbevf_regs_interrupt[] = { + {0, 0, 0, ""} +}; + +static const struct reg_info txgbevf_regs_rxdma[] = { + {0, 0, 0, ""} +}; + +static const struct reg_info txgbevf_regs_tx[] = { + {0, 0, 0, ""} +}; + +/* VF registers */ +static const struct reg_info *txgbevf_regs[] = { + txgbevf_regs_general, + txgbevf_regs_interrupt, + txgbevf_regs_rxdma, + txgbevf_regs_tx, + NULL}; static int txgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats, unsigned int n); 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); @@ -29,6 +63,8 @@ static int txgbevf_dev_stats_reset(struct rte_eth_dev *dev); static int txgbevf_vlan_offload_config(struct rte_eth_dev *dev, int mask); static void txgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on); static void txgbevf_configure_msix(struct rte_eth_dev *dev); +static int txgbevf_dev_promiscuous_enable(struct rte_eth_dev *dev); +static int txgbevf_dev_promiscuous_disable(struct rte_eth_dev *dev); static void txgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index); static void txgbevf_dev_interrupt_handler(void *param); @@ -36,8 +72,8 @@ static void txgbevf_dev_interrupt_handler(void *param); * The set of PCI devices this driver supports (for VF) */ static const struct rte_pci_id pci_id_txgbevf_map[] = { - { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_RAPTOR_VF) }, - { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_RAPTOR_VF_HV) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_SP1000_VF) }, + { RTE_PCI_DEVICE(PCI_VENDOR_ID_WANGXUN, TXGBE_DEV_ID_WX1820_VF) }, { .vendor_id = 0, /* sentinel */ }, }; @@ -246,13 +282,8 @@ eth_txgbevf_dev_init(struct rte_eth_dev *eth_dev) } PMD_INIT_LOG(INFO, "\tVF MAC address not assigned by Host PF"); PMD_INIT_LOG(INFO, "\tAssign randomly generated MAC address " - "%02x:%02x:%02x:%02x:%02x:%02x", - perm_addr->addr_bytes[0], - perm_addr->addr_bytes[1], - perm_addr->addr_bytes[2], - perm_addr->addr_bytes[3], - perm_addr->addr_bytes[4], - perm_addr->addr_bytes[5]); + RTE_ETHER_ADDR_PRT_FMT, + RTE_ETHER_ADDR_BYTES(perm_addr)); } /* Copy the permanent MAC address */ @@ -265,6 +296,9 @@ eth_txgbevf_dev_init(struct rte_eth_dev *eth_dev) return -EIO; } + /* enter promiscuous mode */ + txgbevf_dev_promiscuous_enable(eth_dev); + rte_intr_callback_register(intr_handle, txgbevf_dev_interrupt_handler, eth_dev); rte_intr_enable(intr_handle); @@ -568,18 +602,170 @@ 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; + hw->dev_start = 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; + hw->dev_start = false; + + 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); /** @@ -602,7 +788,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) @@ -617,7 +820,7 @@ static void txgbevf_set_vfta_all(struct rte_eth_dev *dev, bool on) mask = 1; for (j = 0; j < 32; j++) { if (vfta & mask) - txgbe_set_vfta(hw, (i << 5) + j, 0, + hw->mac.set_vfta(hw, (i << 5) + j, 0, on, false); mask <<= 1; } @@ -833,14 +1036,8 @@ txgbevf_add_mac_addr(struct rte_eth_dev *dev, struct rte_ether_addr *mac_addr, err = txgbevf_set_uc_addr_vf(hw, 2, mac_addr->addr_bytes); if (err != 0) PMD_DRV_LOG(ERR, "Unable to add MAC address " - "%02x:%02x:%02x:%02x:%02x:%02x - err=%d", - mac_addr->addr_bytes[0], - mac_addr->addr_bytes[1], - mac_addr->addr_bytes[2], - mac_addr->addr_bytes[3], - mac_addr->addr_bytes[4], - mac_addr->addr_bytes[5], - err); + RTE_ETHER_ADDR_PRT_FMT " - err=%d", + RTE_ETHER_ADDR_BYTES(mac_addr), err); return err; } @@ -882,15 +1079,9 @@ txgbevf_remove_mac_addr(struct rte_eth_dev *dev, uint32_t index) if (err != 0) PMD_DRV_LOG(ERR, "Adding again MAC address " - "%02x:%02x:%02x:%02x:%02x:%02x failed " + RTE_ETHER_ADDR_PRT_FMT " failed " "err=%d", - mac_addr->addr_bytes[0], - mac_addr->addr_bytes[1], - mac_addr->addr_bytes[2], - mac_addr->addr_bytes[3], - mac_addr->addr_bytes[4], - mac_addr->addr_bytes[5], - err); + RTE_ETHER_ADDR_BYTES(mac_addr), err); } } @@ -905,6 +1096,170 @@ txgbevf_set_default_mac_addr(struct rte_eth_dev *dev, return 0; } +static int +txgbevf_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu) +{ + struct txgbe_hw *hw; + uint32_t max_frame = mtu + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN; + struct rte_eth_dev_data *dev_data = dev->data; + + hw = TXGBE_DEV_HW(dev); + + if (mtu < RTE_ETHER_MIN_MTU || + max_frame > RTE_ETHER_MAX_JUMBO_FRAME_LEN) + return -EINVAL; + + /* If device is started, refuse mtu that requires the support of + * scattered packets when this feature has not been enabled before. + */ + if (dev_data->dev_started && !dev_data->scattered_rx && + (max_frame + 2 * TXGBE_VLAN_TAG_SIZE > + dev->data->min_rx_buf_size - RTE_PKTMBUF_HEADROOM)) { + PMD_INIT_LOG(ERR, "Stop port first."); + return -EINVAL; + } + + /* + * When supported by the underlying PF driver, use the TXGBE_VF_SET_MTU + * request of the version 2.0 of the mailbox API. + * For now, use the TXGBE_VF_SET_LPE request of the version 1.0 + * of the mailbox API. + */ + if (txgbevf_rlpml_set_vf(hw, max_frame)) + return -EINVAL; + + /* update max frame size */ + dev->data->dev_conf.rxmode.max_rx_pkt_len = max_frame; + return 0; +} + +static int +txgbevf_get_reg_length(struct rte_eth_dev *dev __rte_unused) +{ + int count = 0; + int g_ind = 0; + const struct reg_info *reg_group; + + while ((reg_group = txgbevf_regs[g_ind++])) + count += txgbe_regs_group_count(reg_group); + + return count; +} + +static int +txgbevf_get_regs(struct rte_eth_dev *dev, + struct rte_dev_reg_info *regs) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + uint32_t *data = regs->data; + int g_ind = 0; + int count = 0; + const struct reg_info *reg_group; + + if (data == NULL) { + regs->length = txgbevf_get_reg_length(dev); + regs->width = sizeof(uint32_t); + return 0; + } + + /* Support only full register dump */ + if (regs->length == 0 || + regs->length == (uint32_t)txgbevf_get_reg_length(dev)) { + regs->version = hw->mac.type << 24 | hw->revision_id << 16 | + hw->device_id; + while ((reg_group = txgbevf_regs[g_ind++])) + count += txgbe_read_regs_group(dev, &data[count], + reg_group); + return 0; + } + + return -ENOTSUP; +} + +static int +txgbevf_dev_promiscuous_enable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + int ret; + + switch (hw->mac.update_xcast_mode(hw, TXGBEVF_XCAST_MODE_PROMISC)) { + case 0: + ret = 0; + break; + case TXGBE_ERR_FEATURE_NOT_SUPPORTED: + ret = -ENOTSUP; + break; + default: + ret = -EAGAIN; + break; + } + + return ret; +} + +static int +txgbevf_dev_promiscuous_disable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + int ret; + + switch (hw->mac.update_xcast_mode(hw, TXGBEVF_XCAST_MODE_NONE)) { + case 0: + ret = 0; + break; + case TXGBE_ERR_FEATURE_NOT_SUPPORTED: + ret = -ENOTSUP; + break; + default: + ret = -EAGAIN; + break; + } + + return ret; +} + +static int +txgbevf_dev_allmulticast_enable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + int ret; + + switch (hw->mac.update_xcast_mode(hw, TXGBEVF_XCAST_MODE_ALLMULTI)) { + case 0: + ret = 0; + break; + case TXGBE_ERR_FEATURE_NOT_SUPPORTED: + ret = -ENOTSUP; + break; + default: + ret = -EAGAIN; + break; + } + + return ret; +} + +static int +txgbevf_dev_allmulticast_disable(struct rte_eth_dev *dev) +{ + struct txgbe_hw *hw = TXGBE_DEV_HW(dev); + int ret; + + switch (hw->mac.update_xcast_mode(hw, TXGBEVF_XCAST_MODE_MULTI)) { + case 0: + ret = 0; + break; + case TXGBE_ERR_FEATURE_NOT_SUPPORTED: + ret = -ENOTSUP; + break; + default: + ret = -EAGAIN; + break; + } + + return ret; +} + static void txgbevf_mbx_process(struct rte_eth_dev *dev) { struct txgbe_hw *hw = TXGBE_DEV_HW(dev); @@ -973,23 +1328,44 @@ 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, .mac_addr_remove = txgbevf_remove_mac_addr, + .set_mc_addr_list = txgbe_dev_set_mc_addr_list, .rxq_info_get = txgbe_rxq_info_get, .txq_info_get = txgbe_txq_info_get, .mac_addr_set = txgbevf_set_default_mac_addr, + .get_reg = txgbevf_get_regs, + .reta_update = txgbe_dev_rss_reta_update, + .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);