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);
.allmulticast_disable = i40evf_dev_allmulticast_disable,
.link_update = i40evf_dev_link_update,
.stats_get = i40evf_dev_stats_get,
+ .stats_reset = i40evf_dev_xstats_reset,
.xstats_get = i40evf_dev_xstats_get,
.xstats_get_names = i40evf_dev_xstats_get_names,
.xstats_reset = i40evf_dev_xstats_reset,
pver = (struct virtchnl_version_info *)args.out_buffer;
vf->version_major = pver->major;
vf->version_minor = pver->minor;
- if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
- PMD_DRV_LOG(INFO, "Peer is DPDK PF host");
- else if ((vf->version_major == VIRTCHNL_VERSION_MAJOR) &&
+ if ((vf->version_major == VIRTCHNL_VERSION_MAJOR) &&
(vf->version_minor <= VIRTCHNL_VERSION_MINOR))
PMD_DRV_LOG(INFO, "Peer is Linux PF host");
else {
len = sizeof(struct virtchnl_vf_resource) +
I40E_MAX_VF_VSI * sizeof(struct virtchnl_vsi_resource);
- (void)rte_memcpy(vf->vf_res, args.out_buffer,
+ rte_memcpy(vf->vf_res, args.out_buffer,
RTE_MIN(args.out_size, len));
i40e_vf_parse_hw_config(hw, vf->vf_res);
uint32_t vector_id;
int i, err;
- if (rte_intr_allow_others(intr_handle)) {
- if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
- vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR;
- else
- vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR_LNX;
- } else {
+ if (rte_intr_allow_others(intr_handle))
+ vector_id = I40EVF_VSI_DEFAULT_MSIX_INTR_LNX;
+ else
vector_id = I40E_MISC_VEC_ID;
- }
map_info = (struct virtchnl_irq_map_info *)cmd_buffer;
map_info->num_vectors = 1;
int err;
struct vf_cmd_info args;
- if (i40e_validate_mac_addr(addr->addr_bytes) != I40E_SUCCESS) {
+ if (is_zero_ether_addr(addr)) {
PMD_DRV_LOG(ERR, "Invalid mac:%x:%x:%x:%x:%x:%x",
addr->addr_bytes[0], addr->addr_bytes[1],
addr->addr_bytes[2], addr->addr_bytes[3],
list = (struct virtchnl_ether_addr_list *)cmd_buffer;
list->vsi_id = vf->vsi_res->vsi_id;
list->num_elements = 1;
- (void)rte_memcpy(list->list[0].addr, addr->addr_bytes,
+ rte_memcpy(list->list[0].addr, addr->addr_bytes,
sizeof(addr->addr_bytes));
args.ops = VIRTCHNL_OP_ADD_ETH_ADDR;
list = (struct virtchnl_ether_addr_list *)cmd_buffer;
list->vsi_id = vf->vsi_res->vsi_id;
list->num_elements = 1;
- (void)rte_memcpy(list->list[0].addr, addr->addr_bytes,
+ rte_memcpy(list->list[0].addr, addr->addr_bytes,
sizeof(addr->addr_bytes));
args.ops = VIRTCHNL_OP_DEL_ETH_ADDR;
}
static int
-i40evf_update_stats(struct rte_eth_dev *dev, struct i40e_eth_stats **pstats)
+i40evf_query_stats(struct rte_eth_dev *dev, struct i40e_eth_stats **pstats)
{
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
struct virtchnl_queue_select q_stats;
return 0;
}
-static int
-i40evf_get_statistics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+static void
+i40evf_stat_update_48(uint64_t *offset,
+ uint64_t *stat)
{
- int ret;
- struct i40e_eth_stats *pstats = NULL;
+ if (*stat >= *offset)
+ *stat = *stat - *offset;
+ else
+ *stat = (uint64_t)((*stat +
+ ((uint64_t)1 << I40E_48_BIT_WIDTH)) - *offset);
- ret = i40evf_update_stats(dev, &pstats);
- if (ret != 0)
- return 0;
+ *stat &= I40E_48_BIT_MASK;
+}
- stats->ipackets = pstats->rx_unicast + pstats->rx_multicast +
- pstats->rx_broadcast;
- stats->opackets = pstats->tx_broadcast + pstats->tx_multicast +
- pstats->tx_unicast;
- stats->imissed = pstats->rx_discards;
- stats->oerrors = pstats->tx_errors + pstats->tx_discards;
- stats->ibytes = pstats->rx_bytes;
- stats->obytes = pstats->tx_bytes;
+static void
+i40evf_stat_update_32(uint64_t *offset,
+ uint64_t *stat)
+{
+ if (*stat >= *offset)
+ *stat = (uint64_t)(*stat - *offset);
+ else
+ *stat = (uint64_t)((*stat +
+ ((uint64_t)1 << I40E_32_BIT_WIDTH)) - *offset);
+}
- return 0;
+static void
+i40evf_update_stats(struct i40e_vsi *vsi,
+ struct i40e_eth_stats *nes)
+{
+ struct i40e_eth_stats *oes = &vsi->eth_stats_offset;
+
+ i40evf_stat_update_48(&oes->rx_bytes,
+ &nes->rx_bytes);
+ i40evf_stat_update_48(&oes->rx_unicast,
+ &nes->rx_unicast);
+ i40evf_stat_update_48(&oes->rx_multicast,
+ &nes->rx_multicast);
+ i40evf_stat_update_48(&oes->rx_broadcast,
+ &nes->rx_broadcast);
+ i40evf_stat_update_32(&oes->rx_discards,
+ &nes->rx_discards);
+ i40evf_stat_update_32(&oes->rx_unknown_protocol,
+ &nes->rx_unknown_protocol);
+ i40evf_stat_update_48(&oes->tx_bytes,
+ &nes->tx_bytes);
+ i40evf_stat_update_48(&oes->tx_unicast,
+ &nes->tx_unicast);
+ i40evf_stat_update_48(&oes->tx_multicast,
+ &nes->tx_multicast);
+ i40evf_stat_update_48(&oes->tx_broadcast,
+ &nes->tx_broadcast);
+ i40evf_stat_update_32(&oes->tx_errors, &nes->tx_errors);
+ i40evf_stat_update_32(&oes->tx_discards, &nes->tx_discards);
}
static void
struct i40e_eth_stats *pstats = NULL;
/* read stat values to clear hardware registers */
- i40evf_update_stats(dev, &pstats);
+ i40evf_query_stats(dev, &pstats);
/* set stats offset base on current values */
- vf->vsi.eth_stats_offset = vf->vsi.eth_stats;
+ vf->vsi.eth_stats_offset = *pstats;
}
static int i40evf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
int ret;
unsigned i;
struct i40e_eth_stats *pstats = NULL;
+ struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+ struct i40e_vsi *vsi = &vf->vsi;
if (n < I40EVF_NB_XSTATS)
return I40EVF_NB_XSTATS;
- ret = i40evf_update_stats(dev, &pstats);
+ ret = i40evf_query_stats(dev, &pstats);
if (ret != 0)
return 0;
if (!xstats)
return 0;
+ i40evf_update_stats(vsi, pstats);
+
/* loop over xstats array and values from pstats */
for (i = 0; i < I40EVF_NB_XSTATS; i++) {
xstats[i].id = i;
}
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;
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) {
/* VF reset, shutdown admin queue and initialize again */
if (i40e_shutdown_adminq(hw) != I40E_SUCCESS) {
PMD_INIT_LOG(ERR, "i40e_shutdown_adminq failed");
- return -1;
+ goto err;
}
i40e_init_adminq_parameter(hw);
if (i40e_init_adminq(hw) != I40E_SUCCESS) {
PMD_INIT_LOG(ERR, "init_adminq failed");
- return -1;
+ 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");
- goto err_aq;
+ goto err_aq;
}
if (i40evf_check_api_version(dev) != 0) {
PMD_INIT_LOG(ERR, "check_api version failed");
- goto err_aq;
+ goto err_api;
}
bufsz = sizeof(struct virtchnl_vf_resource) +
(I40E_MAX_VF_VSI * sizeof(struct virtchnl_vsi_resource));
vf->vf_res = rte_zmalloc("vf_res", bufsz, 0);
if (!vf->vf_res) {
PMD_INIT_LOG(ERR, "unable to allocate vf_res memory");
- goto err_aq;
+ goto err_api;
}
if (i40evf_get_vf_resource(dev) != 0) {
if (hw->mac.type == I40E_MAC_X722_VF)
vf->flags = I40E_FLAG_RSS_AQ_CAPABLE;
vf->vsi.vsi_id = vf->vsi_res->vsi_id;
- vf->vsi.type = (enum i40e_vsi_type)vf->vsi_res->vsi_type;
+
+ switch (vf->vsi_res->vsi_type) {
+ case VIRTCHNL_VSI_SRIOV:
+ vf->vsi.type = I40E_VSI_SRIOV;
+ break;
+ default:
+ vf->vsi.type = I40E_VSI_TYPE_UNKNOWN;
+ break;
+ }
vf->vsi.nb_qps = vf->vsi_res->num_queue_pairs;
vf->vsi.adapter = I40E_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
else
eth_random_addr(hw->mac.addr); /* Generate a random one */
- /* If the PF host is not DPDK, set the interval of ITR0 to max*/
- if (vf->version_major != I40E_DPDK_VERSION_MAJOR) {
- I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01,
- (I40E_ITR_INDEX_DEFAULT <<
- I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT) |
- (interval <<
- I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT));
- I40EVF_WRITE_FLUSH(hw);
- }
+ I40E_WRITE_REG(hw, I40E_VFINT_DYN_CTL01,
+ (I40E_ITR_INDEX_DEFAULT <<
+ I40E_VFINT_DYN_CTL0_ITR_INDX_SHIFT) |
+ (interval <<
+ I40E_VFINT_DYN_CTL0_INTERVAL_SHIFT));
+ I40EVF_WRITE_FLUSH(hw);
return 0;
err_alloc:
rte_free(vf->vf_res);
+ vf->vsi_res = NULL;
+err_api:
+ rte_free(vf->aq_resp);
err_aq:
i40e_shutdown_adminq(hw); /* ignore error */
err:
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;
*/
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,
};
static inline void
i40evf_enable_queues_intr(struct rte_eth_dev *dev)
{
- 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);
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
return;
}
- if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
- /* To support DPDK PF host */
- I40E_WRITE_REG(hw,
- I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR - 1),
- I40E_VFINT_DYN_CTLN1_INTENA_MASK |
- I40E_VFINT_DYN_CTLN_CLEARPBA_MASK);
- /* If host driver is kernel driver, do nothing.
- * Interrupt 0 is used for rx packets, but don't set
- * I40E_VFINT_DYN_CTL01,
- * because it is already done in i40evf_enable_irq0.
- */
-
I40EVF_WRITE_FLUSH(hw);
}
static inline void
i40evf_disable_queues_intr(struct rte_eth_dev *dev)
{
- 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);
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
return;
}
- if (vf->version_major == I40E_DPDK_VERSION_MAJOR)
- I40E_WRITE_REG(hw,
- I40E_VFINT_DYN_CTLN1(I40EVF_VSI_DEFAULT_MSIX_INTR
- - 1),
- 0);
- /* If host driver is kernel driver, do nothing.
- * Interrupt 0 is used for rx packets, but don't zero
- * I40E_VFINT_DYN_CTL01,
- * because interrupt 0 is also used for adminq processing.
- */
-
I40EVF_WRITE_FLUSH(hw);
}
addr = &dev->data->mac_addrs[i];
if (is_zero_ether_addr(addr))
continue;
- (void)rte_memcpy(list->list[j].addr, addr->addr_bytes,
+ rte_memcpy(list->list[j].addr, addr->addr_bytes,
sizeof(addr->addr_bytes));
PMD_DRV_LOG(DEBUG, "add/rm mac:%x:%x:%x:%x:%x:%x",
addr->addr_bytes[0], addr->addr_bytes[1],
{
struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
struct rte_intr_handle *intr_handle = &pci_dev->intr_handle;
- struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
PMD_INIT_FUNC_TRACE();
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 |
};
}
-static void
+static int
i40evf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
- if (i40evf_get_statistics(dev, stats))
+ int ret;
+ struct i40e_eth_stats *pstats = NULL;
+ struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+ struct i40e_vsi *vsi = &vf->vsi;
+
+ ret = i40evf_query_stats(dev, &pstats);
+ if (ret == 0) {
+ i40evf_update_stats(vsi, pstats);
+
+ stats->ipackets = pstats->rx_unicast + pstats->rx_multicast +
+ pstats->rx_broadcast;
+ stats->opackets = pstats->tx_broadcast + pstats->tx_multicast +
+ pstats->tx_unicast;
+ stats->imissed = pstats->rx_discards;
+ stats->oerrors = pstats->tx_errors + pstats->tx_discards;
+ stats->ibytes = pstats->rx_bytes;
+ stats->obytes = pstats->tx_bytes;
+ } 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;
}