-/*-
- * BSD LICENSE
- *
- * Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2010-2016 Intel Corporation
*/
#include <sys/queue.h>
#include <rte_log.h>
#include <rte_debug.h>
#include <rte_pci.h>
+#include <rte_bus_pci.h>
#include <rte_atomic.h>
#include <rte_branch_prediction.h>
#include <rte_memory.h>
-#include <rte_memzone.h>
#include <rte_eal.h>
#include <rte_alarm.h>
#include <rte_ether.h>
-#include <rte_ethdev.h>
+#include <rte_ethdev_driver.h>
#include <rte_ethdev_pci.h>
#include <rte_malloc.h>
#include <rte_dev.h>
#include "i40e_rxtx.h"
#include "i40e_ethdev.h"
#include "i40e_pf.h"
-#define I40EVF_VSI_DEFAULT_MSIX_INTR 1
-#define I40EVF_VSI_DEFAULT_MSIX_INTR_LNX 0
/* busy wait delay in msec */
#define I40EVF_BUSY_WAIT_DELAY 10
struct rte_eth_dev_info *dev_info);
static int i40evf_dev_link_update(struct rte_eth_dev *dev,
int wait_to_complete);
-static void i40evf_dev_stats_get(struct rte_eth_dev *dev,
+static int i40evf_dev_stats_get(struct rte_eth_dev *dev,
struct rte_eth_stats *stats);
static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
struct rte_eth_xstat *xstats, unsigned n);
static void i40evf_dev_xstats_reset(struct rte_eth_dev *dev);
static int i40evf_vlan_filter_set(struct rte_eth_dev *dev,
uint16_t vlan_id, int on);
-static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
+static int i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
static void i40evf_dev_close(struct rte_eth_dev *dev);
static int i40evf_dev_reset(struct rte_eth_dev *dev);
static void i40evf_dev_promiscuous_enable(struct rte_eth_dev *dev);
uint32_t vector_id;
int i, err;
- if (rte_intr_allow_others(intr_handle))
- vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR_LNX;
+ if (dev->data->dev_conf.intr_conf.rxq != 0 &&
+ rte_intr_allow_others(intr_handle))
+ vector_id = I40E_RX_VEC_START;
else
vector_id = I40E_MISC_VEC_ID;
static void
i40evf_dev_xstats_reset(struct rte_eth_dev *dev)
{
+ int ret;
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
struct i40e_eth_stats *pstats = NULL;
/* read stat values to clear hardware registers */
- i40evf_query_stats(dev, &pstats);
+ ret = i40evf_query_stats(dev, &pstats);
/* set stats offset base on current values */
- vf->vsi.eth_stats_offset = *pstats;
+ if (ret == 0)
+ vf->vsi.eth_stats_offset = *pstats;
}
static int i40evf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
}
static int
-i40evf_reset_vf(struct i40e_hw *hw)
+i40evf_check_vf_reset_done(struct i40e_hw *hw)
{
int i, reset;
+ for (i = 0; i < MAX_RESET_WAIT_CNT; i++) {
+ reset = I40E_READ_REG(hw, I40E_VFGEN_RSTAT) &
+ I40E_VFGEN_RSTAT_VFR_STATE_MASK;
+ reset = reset >> I40E_VFGEN_RSTAT_VFR_STATE_SHIFT;
+ if (reset == VIRTCHNL_VFR_VFACTIVE ||
+ reset == VIRTCHNL_VFR_COMPLETED)
+ break;
+ rte_delay_ms(50);
+ }
+
+ if (i >= MAX_RESET_WAIT_CNT)
+ return -1;
+
+ return 0;
+}
+static int
+i40evf_reset_vf(struct i40e_hw *hw)
+{
+ int ret;
+
if (i40e_vf_reset(hw) != I40E_SUCCESS) {
PMD_INIT_LOG(ERR, "Reset VF NIC failed");
return -1;
*/
rte_delay_ms(200);
- for (i = 0; i < MAX_RESET_WAIT_CNT; i++) {
- reset = rd32(hw, I40E_VFGEN_RSTAT) &
- I40E_VFGEN_RSTAT_VFR_STATE_MASK;
- reset = reset >> I40E_VFGEN_RSTAT_VFR_STATE_SHIFT;
- if (VIRTCHNL_VFR_COMPLETED == reset || VIRTCHNL_VFR_VFACTIVE == reset)
- break;
- else
- rte_delay_ms(50);
- }
-
- if (i >= MAX_RESET_WAIT_CNT) {
- PMD_INIT_LOG(ERR, "Reset VF NIC failed");
- return -1;
+ ret = i40evf_check_vf_reset_done(hw);
+ if (ret) {
+ PMD_INIT_LOG(ERR, "VF is still resetting");
+ return ret;
}
return 0;
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
uint16_t interval =
- i40e_calc_itr_interval(I40E_QUEUE_ITR_INTERVAL_MAX);
+ i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL, 0);
vf->adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
vf->dev_data = dev->data;
goto err;
}
+ err = i40evf_check_vf_reset_done(hw);
+ if (err)
+ goto err;
+
i40e_init_adminq_parameter(hw);
err = i40e_init_adminq(hw);
if (err) {
PMD_INIT_LOG(ERR, "init_adminq failed");
goto err;
}
+
vf->aq_resp = rte_zmalloc("vf_aq_resp", I40E_AQ_BUF_SZ, 0);
if (!vf->aq_resp) {
PMD_INIT_LOG(ERR, "unable to allocate vf_aq_resp memory");
case VIRTCHNL_EVENT_RESET_IMPENDING:
PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_RESET_IMPENDING event");
_rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_RESET,
- NULL, NULL);
+ NULL);
break;
case VIRTCHNL_EVENT_LINK_CHANGE:
PMD_DRV_LOG(DEBUG, "VIRTCHNL_EVENT_LINK_CHANGE event");
done:
i40evf_enable_irq0(hw);
- rte_intr_enable(dev->intr_handle);
}
static int
return 0;
}
i40e_set_default_ptype_table(eth_dev);
+ i40e_set_default_pctype_table(eth_dev);
rte_eth_copy_pci_info(eth_dev, pci_dev);
- eth_dev->data->dev_flags |= RTE_ETH_DEV_DETACHABLE;
hw->vendor_id = pci_dev->id.vendor_id;
hw->device_id = pci_dev->id.device_id;
*/
static struct rte_pci_driver rte_i40evf_pmd = {
.id_table = pci_id_i40evf_map,
- .drv_flags = RTE_PCI_DRV_NEED_MAPPING,
+ .drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_IOVA_AS_VA,
.probe = eth_i40evf_pci_probe,
.remove = eth_i40evf_pci_remove,
};
/* Apply vlan offload setting */
i40evf_vlan_offload_set(dev, ETH_VLAN_STRIP_MASK);
- return I40E_SUCCESS;
+ return 0;
}
-static void
+static int
i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask)
{
struct rte_eth_conf *dev_conf = &dev->data->dev_conf;
+ struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+
+ if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_VLAN))
+ return -ENOTSUP;
/* Vlan stripping setting */
if (mask & ETH_VLAN_STRIP_MASK) {
else
i40evf_disable_vlan_strip(dev);
}
+
+ return 0;
}
static int
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
uint16_t interval =
- i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL);
+ i40e_calc_itr_interval(RTE_LIBRTE_I40E_ITR_INTERVAL, 0);
uint16_t msix_intr;
msix_intr = intr_handle->intr_vec[queue_id];
dev->data->nb_tx_queues);
/* check and configure queue intr-vector mapping */
- if (dev->data->dev_conf.intr_conf.rxq != 0) {
+ if (rte_intr_cap_multiple(intr_handle) &&
+ dev->data->dev_conf.intr_conf.rxq) {
intr_vector = dev->data->nb_rx_queues;
if (rte_intr_efd_enable(intr_handle, intr_vector))
return -1;
goto err_mac;
}
+ /* When a VF port is bound to VFIO-PCI, only miscellaneous interrupt
+ * is mapped to VFIO vector 0 in i40evf_dev_init( ).
+ * If previous VFIO interrupt mapping set in i40evf_dev_init( ) is
+ * not cleared, it will fail when rte_intr_enable( ) tries to map Rx
+ * queue interrupt to other VFIO vectors.
+ * So clear uio/vfio intr/evevnfd first to avoid failure.
+ */
+ if (dev->data->dev_conf.intr_conf.rxq != 0) {
+ rte_intr_disable(intr_handle);
+ rte_intr_enable(intr_handle);
+ }
+
i40evf_enable_queues_intr(dev);
+
return 0;
err_mac:
new_link.link_duplex = ETH_LINK_FULL_DUPLEX;
new_link.link_status = vf->link_up ? ETH_LINK_UP :
ETH_LINK_DOWN;
+ new_link.link_autoneg =
+ dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED;
i40evf_dev_atomic_write_link_status(dev, &new_link);
dev_info->max_rx_pktlen = I40E_FRAME_SIZE_MAX;
dev_info->hash_key_size = (I40E_VFQF_HKEY_MAX_INDEX + 1) * sizeof(uint32_t);
dev_info->reta_size = ETH_RSS_RETA_SIZE_64;
- dev_info->flow_type_rss_offloads = I40E_RSS_OFFLOAD_ALL;
+ dev_info->flow_type_rss_offloads = vf->adapter->flow_types_mask;
dev_info->max_mac_addrs = I40E_NUM_MACADDR_MAX;
dev_info->rx_offload_capa =
DEV_RX_OFFLOAD_VLAN_STRIP |
DEV_TX_OFFLOAD_IPV4_CKSUM |
DEV_TX_OFFLOAD_UDP_CKSUM |
DEV_TX_OFFLOAD_TCP_CKSUM |
- DEV_TX_OFFLOAD_SCTP_CKSUM;
+ DEV_TX_OFFLOAD_SCTP_CKSUM |
+ DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
+ DEV_TX_OFFLOAD_TCP_TSO |
+ DEV_TX_OFFLOAD_VXLAN_TNL_TSO |
+ DEV_TX_OFFLOAD_GRE_TNL_TSO |
+ DEV_TX_OFFLOAD_IPIP_TNL_TSO |
+ DEV_TX_OFFLOAD_GENEVE_TNL_TSO;
dev_info->default_rxconf = (struct rte_eth_rxconf) {
.rx_thresh = {
};
}
-static void
+static int
i40evf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
int ret;
} else {
PMD_DRV_LOG(ERR, "Get statistics failed");
}
+ return ret;
}
static void
i40evf_hw_rss_hash_set(struct i40e_vf *vf, struct rte_eth_rss_conf *rss_conf)
{
struct i40e_hw *hw = I40E_VF_TO_HW(vf);
- uint64_t rss_hf, hena;
+ uint64_t hena;
int ret;
ret = i40evf_set_rss_key(&vf->vsi, rss_conf->rss_key,
if (ret)
return ret;
- rss_hf = rss_conf->rss_hf;
- hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(0));
- hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(1))) << 32;
- if (hw->mac.type == I40E_MAC_X722)
- hena &= ~I40E_RSS_HENA_ALL_X722;
- else
- hena &= ~I40E_RSS_HENA_ALL;
- hena |= i40e_config_hena(rss_hf, hw->mac.type);
+ hena = i40e_config_hena(vf->adapter, rss_conf->rss_hf);
i40e_write_rx_ctl(hw, I40E_VFQF_HENA(0), (uint32_t)hena);
i40e_write_rx_ctl(hw, I40E_VFQF_HENA(1), (uint32_t)(hena >> 32));
I40EVF_WRITE_FLUSH(hw);
i40evf_disable_rss(struct i40e_vf *vf)
{
struct i40e_hw *hw = I40E_VF_TO_HW(vf);
- uint64_t hena;
- hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(0));
- hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(1))) << 32;
- if (hw->mac.type == I40E_MAC_X722)
- hena &= ~I40E_RSS_HENA_ALL_X722;
- else
- hena &= ~I40E_RSS_HENA_ALL;
- i40e_write_rx_ctl(hw, I40E_VFQF_HENA(0), (uint32_t)hena);
- i40e_write_rx_ctl(hw, I40E_VFQF_HENA(1), (uint32_t)(hena >> 32));
+ i40e_write_rx_ctl(hw, I40E_VFQF_HENA(0), 0);
+ i40e_write_rx_ctl(hw, I40E_VFQF_HENA(1), 0);
I40EVF_WRITE_FLUSH(hw);
}
}
rss_conf = vf->dev_data->dev_conf.rx_adv_conf.rss_conf;
- if ((rss_conf.rss_hf & I40E_RSS_OFFLOAD_ALL) == 0) {
+ if ((rss_conf.rss_hf & vf->adapter->flow_types_mask) == 0) {
i40evf_disable_rss(vf);
PMD_DRV_LOG(DEBUG, "No hash flag is set");
return 0;
{
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- uint64_t rss_hf = rss_conf->rss_hf & I40E_RSS_OFFLOAD_ALL;
+ uint64_t rss_hf = rss_conf->rss_hf & vf->adapter->flow_types_mask;
uint64_t hena;
hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(0));
hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(1))) << 32;
- if (!(hena & ((hw->mac.type == I40E_MAC_X722)
- ? I40E_RSS_HENA_ALL_X722
- : I40E_RSS_HENA_ALL))) { /* RSS disabled */
+
+ if (!(hena & vf->adapter->pctypes_mask)) { /* RSS disabled */
if (rss_hf != 0) /* Enable RSS */
return -EINVAL;
return 0;
hena = (uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(0));
hena |= ((uint64_t)i40e_read_rx_ctl(hw, I40E_VFQF_HENA(1))) << 32;
- rss_conf->rss_hf = i40e_parse_hena(hena);
+ rss_conf->rss_hf = i40e_parse_hena(vf->adapter, hena);
return 0;
}
struct ether_addr *mac_addr)
{
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
if (!is_valid_assigned_ether_addr(mac_addr)) {
PMD_DRV_LOG(ERR, "Tried to set invalid MAC address.");
return;
}
- if (is_same_ether_addr(mac_addr, dev->data->mac_addrs))
- return;
-
if (vf->flags & I40E_FLAG_VF_MAC_BY_PF)
return;
- i40evf_del_mac_addr_by_addr(dev, dev->data->mac_addrs);
+ i40evf_del_mac_addr_by_addr(dev, (struct ether_addr *)hw->mac.addr);
i40evf_add_mac_addr(dev, mac_addr, 0, 0);
+
+ ether_addr_copy(mac_addr, (struct ether_addr *)hw->mac.addr);
}