* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <sys/queue.h>
#include <stdio.h>
#include <errno.h>
#include <stdint.h>
#include <rte_alarm.h>
#include <rte_dev.h>
#include <rte_eth_ctrl.h>
+#include <rte_tailq.h>
#include "i40e_logs.h"
#include "base/i40e_prototype.h"
#include "i40e_pf.h"
#include "i40e_regs.h"
+#define ETH_I40E_FLOATING_VEB_ARG "enable_floating_veb"
+#define ETH_I40E_FLOATING_VEB_LIST_ARG "floating_veb_list"
+
#define I40E_CLEAR_PXE_WAIT_MS 200
/* Maximun number of capability elements */
static int i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev,
uint16_t queue_id);
-static int i40e_get_reg_length(struct rte_eth_dev *dev);
-
static int i40e_get_regs(struct rte_eth_dev *dev,
struct rte_dev_reg_info *regs);
static int i40e_dev_mtu_set(struct rte_eth_dev *dev, uint16_t mtu);
static const struct rte_pci_id pci_id_i40e_map[] = {
-#define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)},
-#include "rte_pci_dev_ids.h"
-{ .vendor_id = 0, /* sentinel */ },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_XL710) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QEMU) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_B) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_C) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_A) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_B) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_C) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_20G_KR2) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_20G_KR2_A) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T4) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_B) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_25G_SFP28) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_X722_A0) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_KX_X722) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_X722) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_X722) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_1G_BASE_T_X722) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_10G_BASE_T_X722) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_SFP_I_X722) },
+ { RTE_PCI_DEVICE(I40E_INTEL_VENDOR_ID, I40E_DEV_ID_QSFP_I_X722) },
+ { .vendor_id = 0, /* sentinel */ },
};
static const struct eth_dev_ops i40e_eth_dev_ops = {
.timesync_adjust_time = i40e_timesync_adjust_time,
.timesync_read_time = i40e_timesync_read_time,
.timesync_write_time = i40e_timesync_write_time,
- .get_reg_length = i40e_get_reg_length,
.get_reg = i40e_get_regs,
.get_eeprom_length = i40e_get_eeprom_length,
.get_eeprom = i40e_get_eeprom,
.init = rte_i40e_pmd_init,
};
-PMD_REGISTER_DRIVER(rte_i40e_driver);
+PMD_REGISTER_DRIVER(rte_i40e_driver, i40e);
+DRIVER_REGISTER_PCI_TABLE(i40e, pci_id_i40e_map);
/*
* Initialize registers for flexible payload, which should be set by NVM.
" frames from VSIs.");
}
+static int
+floating_veb_list_handler(__rte_unused const char *key,
+ const char *floating_veb_value,
+ void *opaque)
+{
+ int idx = 0;
+ unsigned int count = 0;
+ char *end = NULL;
+ int min, max;
+ bool *vf_floating_veb = opaque;
+
+ while (isblank(*floating_veb_value))
+ floating_veb_value++;
+
+ /* Reset floating VEB configuration for VFs */
+ for (idx = 0; idx < I40E_MAX_VF; idx++)
+ vf_floating_veb[idx] = false;
+
+ min = I40E_MAX_VF;
+ do {
+ while (isblank(*floating_veb_value))
+ floating_veb_value++;
+ if (*floating_veb_value == '\0')
+ return -1;
+ errno = 0;
+ idx = strtoul(floating_veb_value, &end, 10);
+ if (errno || end == NULL)
+ return -1;
+ while (isblank(*end))
+ end++;
+ if (*end == '-') {
+ min = idx;
+ } else if ((*end == ';') || (*end == '\0')) {
+ max = idx;
+ if (min == I40E_MAX_VF)
+ min = idx;
+ if (max >= I40E_MAX_VF)
+ max = I40E_MAX_VF - 1;
+ for (idx = min; idx <= max; idx++) {
+ vf_floating_veb[idx] = true;
+ count++;
+ }
+ min = I40E_MAX_VF;
+ } else {
+ return -1;
+ }
+ floating_veb_value = end + 1;
+ } while (*end != '\0');
+
+ if (count == 0)
+ return -1;
+
+ return 0;
+}
+
+static void
+config_vf_floating_veb(struct rte_devargs *devargs,
+ uint16_t floating_veb,
+ bool *vf_floating_veb)
+{
+ struct rte_kvargs *kvlist;
+ int i;
+ const char *floating_veb_list = ETH_I40E_FLOATING_VEB_LIST_ARG;
+
+ if (!floating_veb)
+ return;
+ /* All the VFs attach to the floating VEB by default
+ * when the floating VEB is enabled.
+ */
+ for (i = 0; i < I40E_MAX_VF; i++)
+ vf_floating_veb[i] = true;
+
+ if (devargs == NULL)
+ return;
+
+ kvlist = rte_kvargs_parse(devargs->args, NULL);
+ if (kvlist == NULL)
+ return;
+
+ if (!rte_kvargs_count(kvlist, floating_veb_list)) {
+ rte_kvargs_free(kvlist);
+ return;
+ }
+ /* When the floating_veb_list parameter exists, all the VFs
+ * will attach to the legacy VEB firstly, then configure VFs
+ * to the floating VEB according to the floating_veb_list.
+ */
+ if (rte_kvargs_process(kvlist, floating_veb_list,
+ floating_veb_list_handler,
+ vf_floating_veb) < 0) {
+ rte_kvargs_free(kvlist);
+ return;
+ }
+ rte_kvargs_free(kvlist);
+}
+
+static int
+i40e_check_floating_handler(__rte_unused const char *key,
+ const char *value,
+ __rte_unused void *opaque)
+{
+ if (strcmp(value, "1"))
+ return -1;
+
+ return 0;
+}
+
+static int
+is_floating_veb_supported(struct rte_devargs *devargs)
+{
+ struct rte_kvargs *kvlist;
+ const char *floating_veb_key = ETH_I40E_FLOATING_VEB_ARG;
+
+ if (devargs == NULL)
+ return 0;
+
+ kvlist = rte_kvargs_parse(devargs->args, NULL);
+ if (kvlist == NULL)
+ return 0;
+
+ if (!rte_kvargs_count(kvlist, floating_veb_key)) {
+ rte_kvargs_free(kvlist);
+ return 0;
+ }
+ /* Floating VEB is enabled when there's key-value:
+ * enable_floating_veb=1
+ */
+ if (rte_kvargs_process(kvlist, floating_veb_key,
+ i40e_check_floating_handler, NULL) < 0) {
+ rte_kvargs_free(kvlist);
+ return 0;
+ }
+ rte_kvargs_free(kvlist);
+
+ return 1;
+}
+
+static void
+config_floating_veb(struct rte_eth_dev *dev)
+{
+ struct rte_pci_device *pci_dev = dev->pci_dev;
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+
+ memset(pf->floating_veb_list, 0, sizeof(pf->floating_veb_list));
+
+ if (hw->aq.fw_maj_ver >= FLOATING_VEB_SUPPORTED_FW_MAJ) {
+ pf->floating_veb = is_floating_veb_supported(pci_dev->devargs);
+ config_vf_floating_veb(pci_dev->devargs, pf->floating_veb,
+ pf->floating_veb_list);
+ } else {
+ pf->floating_veb = false;
+ }
+}
+
static int
eth_i40e_dev_init(struct rte_eth_dev *dev)
{
((hw->nvm.version >> 4) & 0xff),
(hw->nvm.version & 0xf), hw->nvm.eetrack);
+ /* Need the special FW version to support floating VEB */
+ config_floating_veb(dev);
/* Clear PXE mode */
i40e_clear_pxe_mode(hw);
snprintf(xstats_names[count].name,
sizeof(xstats_names[count].name),
"%s", rte_i40e_stats_strings[i].name);
- xstats_names[count].id = count;
count++;
}
snprintf(xstats_names[count].name,
sizeof(xstats_names[count].name),
"%s", rte_i40e_hw_port_strings[i].name);
- xstats_names[count].id = count;
count++;
}
sizeof(xstats_names[count].name),
"rx_priority%u_%s", prio,
rte_i40e_rxq_prio_strings[i].name);
- xstats_names[count].id = count;
count++;
}
}
sizeof(xstats_names[count].name),
"tx_priority%u_%s", prio,
rte_i40e_txq_prio_strings[i].name);
- xstats_names[count].id = count;
count++;
}
}
/* Get stats from i40e_eth_stats struct */
for (i = 0; i < I40E_NB_ETH_XSTATS; i++) {
- xstats[count].id = count;
xstats[count].value = *(uint64_t *)(((char *)&hw_stats->eth) +
rte_i40e_stats_strings[i].offset);
count++;
/* Get individiual stats from i40e_hw_port struct */
for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) {
- xstats[count].id = count;
xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
rte_i40e_hw_port_strings[i].offset);
count++;
for (i = 0; i < I40E_NB_RXQ_PRIO_XSTATS; i++) {
for (prio = 0; prio < 8; prio++) {
- xstats[count].id = count;
xstats[count].value =
*(uint64_t *)(((char *)hw_stats) +
rte_i40e_rxq_prio_strings[i].offset +
for (i = 0; i < I40E_NB_TXQ_PRIO_XSTATS; i++) {
for (prio = 0; prio < 8; prio++) {
- xstats[count].id = count;
xstats[count].value =
*(uint64_t *)(((char *)hw_stats) +
rte_i40e_txq_prio_strings[i].offset +
if (i40e_is_40G_device(hw->device_id))
/* For XL710 */
- dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G;
+ dev_info->speed_capa = ETH_LINK_SPEED_40G;
else
/* For X710 */
- dev_info->speed_capa = ETH_LINK_SPEED_10G | ETH_LINK_SPEED_40G;
+ dev_info->speed_capa = ETH_LINK_SPEED_1G | ETH_LINK_SPEED_10G;
}
static int
int ret;
/* If VMDQ not enabled or configured, return */
- if (pool != 0 && (!(pf->flags | I40E_FLAG_VMDQ) || !pf->nb_cfg_vmdq_vsi)) {
+ if (pool != 0 && (!(pf->flags & I40E_FLAG_VMDQ) ||
+ !pf->nb_cfg_vmdq_vsi)) {
PMD_DRV_LOG(ERR, "VMDQ not %s, can't set mac to pool %u",
- pf->flags | I40E_FLAG_VMDQ ? "configured" : "enabled",
+ pf->flags & I40E_FLAG_VMDQ ? "configured" : "enabled",
pool);
return;
}
vsi = pf->main_vsi;
else {
/* No VMDQ pool enabled or configured */
- if (!(pf->flags | I40E_FLAG_VMDQ) ||
+ if (!(pf->flags & I40E_FLAG_VMDQ) ||
(i > pf->nb_cfg_vmdq_vsi)) {
PMD_DRV_LOG(ERR, "No VMDQ pool enabled"
"/configured");
static int
i40e_set_rss_lut(struct i40e_vsi *vsi, uint8_t *lut, uint16_t lut_size)
{
- struct i40e_pf *pf = I40E_VSI_TO_PF(vsi);
- struct i40e_hw *hw = I40E_VSI_TO_HW(vsi);
+ struct i40e_pf *pf;
+ struct i40e_hw *hw;
int ret;
if (!vsi || !lut)
return -EINVAL;
+ pf = I40E_VSI_TO_PF(vsi);
+ hw = I40E_VSI_TO_HW(vsi);
+
if (pf->flags & I40E_FLAG_RSS_AQ_CAPABLE) {
ret = i40e_aq_set_rss_lut(hw, vsi->vsi_id, TRUE,
lut, lut_size);
struct i40e_pf *pf;
struct i40e_hw *hw;
struct i40e_vsi_list *vsi_list;
+ void *temp;
int ret;
struct i40e_mac_filter *f;
uint16_t user_param = vsi->user_param;
/* VSI has child to attach, release child first */
if (vsi->veb) {
- TAILQ_FOREACH(vsi_list, &vsi->veb->head, list) {
+ TAILQ_FOREACH_SAFE(vsi_list, &vsi->veb->head, list, temp) {
if (i40e_vsi_release(vsi_list->vsi) != I40E_SUCCESS)
return -1;
- TAILQ_REMOVE(&vsi->veb->head, vsi_list, list);
}
i40e_veb_release(vsi->veb);
}
if (vsi->floating_veb) {
- TAILQ_FOREACH(vsi_list, &vsi->floating_veb->head, list) {
+ TAILQ_FOREACH_SAFE(vsi_list, &vsi->floating_veb->head, list, temp) {
if (i40e_vsi_release(vsi_list->vsi) != I40E_SUCCESS)
return -1;
- TAILQ_REMOVE(&vsi->floating_veb->head, vsi_list, list);
}
}
/* Remove all macvlan filters of the VSI */
i40e_vsi_remove_all_macvlan_filter(vsi);
- TAILQ_FOREACH(f, &vsi->mac_list, next)
+ TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp)
rte_free(f);
if (vsi->type != I40E_VSI_MAIN &&
{
int i, num;
struct i40e_mac_filter *f;
+ void *temp;
struct i40e_mac_filter_info *mac_filter;
enum rte_mac_filter_type desired_filter;
int ret = I40E_SUCCESS;
i = 0;
/* Remove all existing mac */
- TAILQ_FOREACH(f, &vsi->mac_list, next) {
+ TAILQ_FOREACH_SAFE(f, &vsi->mac_list, next, temp) {
mac_filter[i] = f->mac_info;
ret = i40e_vsi_delete_mac(vsi, &f->mac_info.mac_addr);
if (ret) {
mask &= ~(1UL << i);
/* Bit set indicats the coresponding flow type is supported */
g_cfg->valid_bit_mask[0] |= (1UL << i);
+ /* if flowtype is invalid, continue */
+ if (!I40E_VALID_FLOW(i))
+ continue;
pctype = i40e_flowtype_to_pctype(i);
reg = i40e_read_rx_ctl(hw, I40E_GLQF_HSYM(pctype));
if (reg & I40E_GLQF_HSYM_SYMH_ENA_MASK)
if (!(mask0 & (1UL << i)))
continue;
mask0 &= ~(1UL << i);
+ /* if flowtype is invalid, continue */
+ if (!I40E_VALID_FLOW(i))
+ continue;
pctype = i40e_flowtype_to_pctype(i);
reg = (g_cfg->sym_hash_enable_mask[0] & (1UL << i)) ?
I40E_GLQF_HSYM_SYMH_ENA_MASK : 0;
return -EINVAL;
}
- pctype = i40e_flowtype_to_pctype(conf->flow_type);
- if (pctype == 0 || pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD) {
- PMD_DRV_LOG(ERR, "Not supported flow type (%u)",
- conf->flow_type);
+ if (!I40E_VALID_FLOW(conf->flow_type)) {
+ PMD_DRV_LOG(ERR, "invalid flow_type input.");
return -EINVAL;
}
-
+ pctype = i40e_flowtype_to_pctype(conf->flow_type);
ret = i40e_parse_input_set(&input_set, pctype, conf->field,
conf->inset_size);
if (ret) {
return -EINVAL;
}
- pctype = i40e_flowtype_to_pctype(conf->flow_type);
- if (pctype == 0 || pctype > I40E_FILTER_PCTYPE_L2_PAYLOAD) {
- PMD_DRV_LOG(ERR, "Not supported flow type (%u)",
- conf->flow_type);
+ if (!I40E_VALID_FLOW(conf->flow_type)) {
+ PMD_DRV_LOG(ERR, "invalid flow_type input.");
return -EINVAL;
}
+ pctype = i40e_flowtype_to_pctype(conf->flow_type);
ret = i40e_parse_input_set(&input_set, pctype, conf->field,
conf->inset_size);
if (ret) {
return 0;
}
-static int i40e_get_reg_length(__rte_unused struct rte_eth_dev *dev)
-{
- /* Highest base addr + 32-bit word */
- return I40E_GLGEN_STAT_CLEAR + 4;
-}
-
static int i40e_get_regs(struct rte_eth_dev *dev,
struct rte_dev_reg_info *regs)
{
uint32_t reg_idx, arr_idx, arr_idx2, reg_offset;
const struct i40e_reg_info *reg_info;
+ if (ptr_data == NULL) {
+ regs->length = I40E_GLGEN_STAT_CLEAR + 4;
+ regs->width = sizeof(uint32_t);
+ return 0;
+ }
+
/* The first few registers have to be read using AQ operations */
reg_idx = 0;
while (i40e_regs_adminq[reg_idx].name) {