2018-01-10 09:17:10 +00:00
|
|
|
/* SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
* Copyright 2008-2017 Cisco Systems, Inc. All rights reserved.
|
2014-11-25 17:26:43 +00:00
|
|
|
* Copyright 2007 Nuova Systems, Inc. All rights reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include <rte_dev.h>
|
|
|
|
#include <rte_pci.h>
|
2017-10-26 10:06:08 +00:00
|
|
|
#include <rte_bus_pci.h>
|
2018-01-22 00:16:22 +00:00
|
|
|
#include <rte_ethdev_driver.h>
|
2017-04-11 15:44:24 +00:00
|
|
|
#include <rte_ethdev_pci.h>
|
2018-04-16 21:49:10 +00:00
|
|
|
#include <rte_kvargs.h>
|
2014-11-25 17:26:43 +00:00
|
|
|
#include <rte_string_fns.h>
|
|
|
|
|
|
|
|
#include "vnic_intr.h"
|
|
|
|
#include "vnic_cq.h"
|
|
|
|
#include "vnic_wq.h"
|
|
|
|
#include "vnic_rq.h"
|
|
|
|
#include "vnic_enet.h"
|
|
|
|
#include "enic.h"
|
|
|
|
|
2018-01-10 09:17:09 +00:00
|
|
|
int enicpmd_logtype_init;
|
|
|
|
int enicpmd_logtype_flow;
|
|
|
|
|
|
|
|
#define ENICPMD_FUNC_TRACE() PMD_INIT_LOG(DEBUG, " >>")
|
2014-11-25 17:26:43 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The set of PCI devices this driver supports
|
|
|
|
*/
|
2016-07-11 14:40:42 +00:00
|
|
|
#define CISCO_PCI_VENDOR_ID 0x1137
|
2015-04-16 23:23:39 +00:00
|
|
|
static const struct rte_pci_id pci_id_enic_map[] = {
|
2016-07-11 14:40:42 +00:00
|
|
|
{ RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET) },
|
|
|
|
{ RTE_PCI_DEVICE(CISCO_PCI_VENDOR_ID, PCI_DEVICE_ID_CISCO_VIC_ENET_VF) },
|
|
|
|
{.vendor_id = 0, /* sentinel */},
|
2014-11-25 17:26:43 +00:00
|
|
|
};
|
|
|
|
|
2018-04-16 21:49:10 +00:00
|
|
|
#define ENIC_DEVARG_DISABLE_OVERLAY "disable-overlay"
|
2018-10-03 20:09:28 +00:00
|
|
|
#define ENIC_DEVARG_ENABLE_AVX2_RX "enable-avx2-rx"
|
2018-06-29 09:29:35 +00:00
|
|
|
#define ENIC_DEVARG_IG_VLAN_REWRITE "ig-vlan-rewrite"
|
2018-03-08 02:46:57 +00:00
|
|
|
|
2018-06-18 12:32:21 +00:00
|
|
|
RTE_INIT(enicpmd_init_log)
|
2018-01-10 09:17:09 +00:00
|
|
|
{
|
2018-01-25 09:01:01 +00:00
|
|
|
enicpmd_logtype_init = rte_log_register("pmd.net.enic.init");
|
2018-01-10 09:17:09 +00:00
|
|
|
if (enicpmd_logtype_init >= 0)
|
|
|
|
rte_log_set_level(enicpmd_logtype_init, RTE_LOG_NOTICE);
|
2018-01-25 09:01:01 +00:00
|
|
|
enicpmd_logtype_flow = rte_log_register("pmd.net.enic.flow");
|
2018-01-10 09:17:09 +00:00
|
|
|
if (enicpmd_logtype_flow >= 0)
|
|
|
|
rte_log_set_level(enicpmd_logtype_flow, RTE_LOG_NOTICE);
|
|
|
|
}
|
|
|
|
|
2015-04-09 09:29:32 +00:00
|
|
|
static int
|
|
|
|
enicpmd_fdir_ctrl_func(struct rte_eth_dev *eth_dev,
|
|
|
|
enum rte_filter_op filter_op, void *arg)
|
2014-11-25 17:26:43 +00:00
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
2015-04-09 09:29:32 +00:00
|
|
|
int ret = 0;
|
2014-11-25 17:26:43 +00:00
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
2015-04-09 09:29:32 +00:00
|
|
|
if (filter_op == RTE_ETH_FILTER_NOP)
|
|
|
|
return 0;
|
2014-11-25 17:26:43 +00:00
|
|
|
|
2015-04-09 09:29:32 +00:00
|
|
|
if (arg == NULL && filter_op != RTE_ETH_FILTER_FLUSH)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
switch (filter_op) {
|
|
|
|
case RTE_ETH_FILTER_ADD:
|
|
|
|
case RTE_ETH_FILTER_UPDATE:
|
|
|
|
ret = enic_fdir_add_fltr(enic,
|
|
|
|
(struct rte_eth_fdir_filter *)arg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RTE_ETH_FILTER_DELETE:
|
|
|
|
ret = enic_fdir_del_fltr(enic,
|
|
|
|
(struct rte_eth_fdir_filter *)arg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RTE_ETH_FILTER_STATS:
|
|
|
|
enic_fdir_stats_get(enic, (struct rte_eth_fdir_stats *)arg);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case RTE_ETH_FILTER_FLUSH:
|
|
|
|
dev_warning(enic, "unsupported operation %u", filter_op);
|
|
|
|
ret = -ENOTSUP;
|
|
|
|
break;
|
2016-09-29 20:56:39 +00:00
|
|
|
case RTE_ETH_FILTER_INFO:
|
|
|
|
enic_fdir_info_get(enic, (struct rte_eth_fdir_info *)arg);
|
|
|
|
break;
|
2015-04-09 09:29:32 +00:00
|
|
|
default:
|
|
|
|
dev_err(enic, "unknown operation %u", filter_op);
|
|
|
|
ret = -EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ret;
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|
|
|
|
|
2015-04-09 09:29:32 +00:00
|
|
|
static int
|
|
|
|
enicpmd_dev_filter_ctrl(struct rte_eth_dev *dev,
|
|
|
|
enum rte_filter_type filter_type,
|
|
|
|
enum rte_filter_op filter_op,
|
|
|
|
void *arg)
|
2014-11-25 17:26:43 +00:00
|
|
|
{
|
2017-05-17 22:38:05 +00:00
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
2014-11-25 17:26:43 +00:00
|
|
|
|
2017-05-17 22:38:05 +00:00
|
|
|
switch (filter_type) {
|
|
|
|
case RTE_ETH_FILTER_GENERIC:
|
|
|
|
if (filter_op != RTE_ETH_FILTER_GET)
|
|
|
|
return -EINVAL;
|
|
|
|
*(const void **)arg = &enic_flow_ops;
|
|
|
|
break;
|
|
|
|
case RTE_ETH_FILTER_FDIR:
|
2015-04-09 09:29:32 +00:00
|
|
|
ret = enicpmd_fdir_ctrl_func(dev, filter_op, arg);
|
2017-05-17 22:38:05 +00:00
|
|
|
break;
|
|
|
|
default:
|
2015-04-09 09:29:32 +00:00
|
|
|
dev_warning(enic, "Filter type (%d) not supported",
|
|
|
|
filter_type);
|
2017-05-17 22:38:05 +00:00
|
|
|
ret = -EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
2015-04-09 09:29:32 +00:00
|
|
|
|
|
|
|
return ret;
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void enicpmd_dev_tx_queue_release(void *txq)
|
|
|
|
{
|
|
|
|
ENICPMD_FUNC_TRACE();
|
2017-09-11 18:58:33 +00:00
|
|
|
|
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
enic_free_wq(txq);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_setup_intr(struct enic *enic)
|
|
|
|
{
|
|
|
|
int ret;
|
2014-12-02 13:38:31 +00:00
|
|
|
unsigned int index;
|
2014-11-25 17:26:43 +00:00
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
|
|
|
|
/* Are we done with the init of all the queues? */
|
|
|
|
for (index = 0; index < enic->cq_count; index++) {
|
|
|
|
if (!enic->cq[index].ctrl)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (enic->cq_count != index)
|
|
|
|
return 0;
|
2016-07-10 21:15:30 +00:00
|
|
|
for (index = 0; index < enic->wq_count; index++) {
|
|
|
|
if (!enic->wq[index].ctrl)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (enic->wq_count != index)
|
|
|
|
return 0;
|
|
|
|
/* check start of packet (SOP) RQs only in case scatter is disabled. */
|
|
|
|
for (index = 0; index < enic->rq_count; index++) {
|
2016-10-12 21:12:03 +00:00
|
|
|
if (!enic->rq[enic_rte_rq_idx_to_sop_idx(index)].ctrl)
|
2016-07-10 21:15:30 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (enic->rq_count != index)
|
|
|
|
return 0;
|
2014-11-25 17:26:43 +00:00
|
|
|
|
|
|
|
ret = enic_alloc_intr_resources(enic);
|
|
|
|
if (ret) {
|
|
|
|
dev_err(enic, "alloc intr failed\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
enic_init_vnic_resources(enic);
|
|
|
|
|
|
|
|
ret = enic_setup_finish(enic);
|
|
|
|
if (ret)
|
|
|
|
dev_err(enic, "setup could not be finished\n");
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_tx_queue_setup(struct rte_eth_dev *eth_dev,
|
|
|
|
uint16_t queue_idx,
|
|
|
|
uint16_t nb_desc,
|
|
|
|
unsigned int socket_id,
|
2018-06-29 09:29:38 +00:00
|
|
|
const struct rte_eth_txconf *tx_conf)
|
2014-11-25 17:26:43 +00:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
2018-06-29 09:29:38 +00:00
|
|
|
struct vnic_wq *wq;
|
2014-11-25 17:26:43 +00:00
|
|
|
|
2017-09-11 18:58:33 +00:00
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return -E_RTE_SECONDARY;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
ENICPMD_FUNC_TRACE();
|
2018-01-23 01:05:28 +00:00
|
|
|
RTE_ASSERT(queue_idx < enic->conf_wq_count);
|
2018-06-29 09:29:38 +00:00
|
|
|
wq = &enic->wq[queue_idx];
|
|
|
|
wq->offloads = tx_conf->offloads |
|
|
|
|
eth_dev->data->dev_conf.txmode.offloads;
|
|
|
|
eth_dev->data->tx_queues[queue_idx] = (void *)wq;
|
2014-11-25 17:26:43 +00:00
|
|
|
|
|
|
|
ret = enic_alloc_wq(enic, queue_idx, socket_id, nb_desc);
|
|
|
|
if (ret) {
|
|
|
|
dev_err(enic, "error in allocating wq\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return enicpmd_dev_setup_intr(enic);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_tx_queue_start(struct rte_eth_dev *eth_dev,
|
|
|
|
uint16_t queue_idx)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
|
|
|
|
enic_start_wq(enic, queue_idx);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_tx_queue_stop(struct rte_eth_dev *eth_dev,
|
|
|
|
uint16_t queue_idx)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
|
|
|
|
ret = enic_stop_wq(enic, queue_idx);
|
|
|
|
if (ret)
|
|
|
|
dev_err(enic, "error in stopping wq %d\n", queue_idx);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_rx_queue_start(struct rte_eth_dev *eth_dev,
|
|
|
|
uint16_t queue_idx)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
|
|
|
|
enic_start_rq(enic, queue_idx);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_rx_queue_stop(struct rte_eth_dev *eth_dev,
|
|
|
|
uint16_t queue_idx)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
|
|
|
|
ret = enic_stop_rq(enic, queue_idx);
|
|
|
|
if (ret)
|
|
|
|
dev_err(enic, "error in stopping rq %d\n", queue_idx);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void enicpmd_dev_rx_queue_release(void *rxq)
|
|
|
|
{
|
|
|
|
ENICPMD_FUNC_TRACE();
|
2017-09-11 18:58:33 +00:00
|
|
|
|
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
enic_free_rq(rxq);
|
|
|
|
}
|
|
|
|
|
2016-09-19 18:50:29 +00:00
|
|
|
static uint32_t enicpmd_dev_rx_queue_count(struct rte_eth_dev *dev,
|
|
|
|
uint16_t rx_queue_id)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(dev);
|
|
|
|
uint32_t queue_count = 0;
|
|
|
|
struct vnic_cq *cq;
|
|
|
|
uint32_t cq_tail;
|
|
|
|
uint16_t cq_idx;
|
|
|
|
int rq_num;
|
|
|
|
|
2016-10-12 21:12:03 +00:00
|
|
|
rq_num = enic_rte_rq_idx_to_sop_idx(rx_queue_id);
|
2016-09-19 18:50:29 +00:00
|
|
|
cq = &enic->cq[enic_cq_rq(enic, rq_num)];
|
|
|
|
cq_idx = cq->to_clean;
|
|
|
|
|
|
|
|
cq_tail = ioread32(&cq->ctrl->cq_tail);
|
|
|
|
|
|
|
|
if (cq_tail < cq_idx)
|
|
|
|
cq_tail += cq->ring.desc_count;
|
|
|
|
|
|
|
|
queue_count = cq_tail - cq_idx;
|
|
|
|
|
|
|
|
return queue_count;
|
|
|
|
}
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
static int enicpmd_dev_rx_queue_setup(struct rte_eth_dev *eth_dev,
|
|
|
|
uint16_t queue_idx,
|
|
|
|
uint16_t nb_desc,
|
|
|
|
unsigned int socket_id,
|
2016-03-04 21:09:00 +00:00
|
|
|
const struct rte_eth_rxconf *rx_conf,
|
2014-11-25 17:26:43 +00:00
|
|
|
struct rte_mempool *mp)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
2017-09-11 18:58:33 +00:00
|
|
|
|
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return -E_RTE_SECONDARY;
|
2018-01-23 01:05:28 +00:00
|
|
|
RTE_ASSERT(enic_rte_rq_idx_to_sop_idx(queue_idx) < enic->conf_rq_count);
|
2016-06-16 19:19:05 +00:00
|
|
|
eth_dev->data->rx_queues[queue_idx] =
|
2016-10-12 21:12:03 +00:00
|
|
|
(void *)&enic->rq[enic_rte_rq_idx_to_sop_idx(queue_idx)];
|
2014-11-25 17:26:43 +00:00
|
|
|
|
2016-10-12 21:22:29 +00:00
|
|
|
ret = enic_alloc_rq(enic, queue_idx, socket_id, mp, nb_desc,
|
|
|
|
rx_conf->rx_free_thresh);
|
2014-11-25 17:26:43 +00:00
|
|
|
if (ret) {
|
|
|
|
dev_err(enic, "error in allocating rq\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return enicpmd_dev_setup_intr(enic);
|
|
|
|
}
|
|
|
|
|
2017-09-01 02:36:28 +00:00
|
|
|
static int enicpmd_vlan_offload_set(struct rte_eth_dev *eth_dev, int mask)
|
2014-11-25 17:26:43 +00:00
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
net/enic: remove VLAN filter handler
VIC does not support VLAN filtering at the moment. The firmware does
accept the filter add/del commands and returns success. But, they are
no-ops. To avoid confusion, remove the filter set handler so the app
sees an error instead of silent failure.
Also during the device configure time, enicpmd_vlan_offload_set would
not print a warning message about unsupported VLAN filtering, because
the caller specifies only ETH_VLAN_STRIP_MASK. This is wrong, as we
should attempt to apply all requested offloads at the configure
time. So, pass all VLAN offload masks, which triggers a warning
message about VLAN filtering, if requested.
Finally, enicpmd_vlan_offload_set should check both mask and
rxmode.offloads, not just mask.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:56 +00:00
|
|
|
uint64_t offloads;
|
2014-11-25 17:26:43 +00:00
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
|
net/enic: remove VLAN filter handler
VIC does not support VLAN filtering at the moment. The firmware does
accept the filter add/del commands and returns success. But, they are
no-ops. To avoid confusion, remove the filter set handler so the app
sees an error instead of silent failure.
Also during the device configure time, enicpmd_vlan_offload_set would
not print a warning message about unsupported VLAN filtering, because
the caller specifies only ETH_VLAN_STRIP_MASK. This is wrong, as we
should attempt to apply all requested offloads at the configure
time. So, pass all VLAN offload masks, which triggers a warning
message about VLAN filtering, if requested.
Finally, enicpmd_vlan_offload_set should check both mask and
rxmode.offloads, not just mask.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:56 +00:00
|
|
|
offloads = eth_dev->data->dev_conf.rxmode.offloads;
|
2014-11-25 17:26:43 +00:00
|
|
|
if (mask & ETH_VLAN_STRIP_MASK) {
|
net/enic: remove VLAN filter handler
VIC does not support VLAN filtering at the moment. The firmware does
accept the filter add/del commands and returns success. But, they are
no-ops. To avoid confusion, remove the filter set handler so the app
sees an error instead of silent failure.
Also during the device configure time, enicpmd_vlan_offload_set would
not print a warning message about unsupported VLAN filtering, because
the caller specifies only ETH_VLAN_STRIP_MASK. This is wrong, as we
should attempt to apply all requested offloads at the configure
time. So, pass all VLAN offload masks, which triggers a warning
message about VLAN filtering, if requested.
Finally, enicpmd_vlan_offload_set should check both mask and
rxmode.offloads, not just mask.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:56 +00:00
|
|
|
if (offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
|
2014-11-25 17:26:43 +00:00
|
|
|
enic->ig_vlan_strip_en = 1;
|
|
|
|
else
|
|
|
|
enic->ig_vlan_strip_en = 0;
|
|
|
|
}
|
|
|
|
|
net/enic: remove VLAN filter handler
VIC does not support VLAN filtering at the moment. The firmware does
accept the filter add/del commands and returns success. But, they are
no-ops. To avoid confusion, remove the filter set handler so the app
sees an error instead of silent failure.
Also during the device configure time, enicpmd_vlan_offload_set would
not print a warning message about unsupported VLAN filtering, because
the caller specifies only ETH_VLAN_STRIP_MASK. This is wrong, as we
should attempt to apply all requested offloads at the configure
time. So, pass all VLAN offload masks, which triggers a warning
message about VLAN filtering, if requested.
Finally, enicpmd_vlan_offload_set should check both mask and
rxmode.offloads, not just mask.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:56 +00:00
|
|
|
if ((mask & ETH_VLAN_FILTER_MASK) &&
|
|
|
|
(offloads & DEV_RX_OFFLOAD_VLAN_FILTER)) {
|
2014-11-25 17:26:43 +00:00
|
|
|
dev_warning(enic,
|
|
|
|
"Configuration of VLAN filter is not supported\n");
|
|
|
|
}
|
|
|
|
|
net/enic: remove VLAN filter handler
VIC does not support VLAN filtering at the moment. The firmware does
accept the filter add/del commands and returns success. But, they are
no-ops. To avoid confusion, remove the filter set handler so the app
sees an error instead of silent failure.
Also during the device configure time, enicpmd_vlan_offload_set would
not print a warning message about unsupported VLAN filtering, because
the caller specifies only ETH_VLAN_STRIP_MASK. This is wrong, as we
should attempt to apply all requested offloads at the configure
time. So, pass all VLAN offload masks, which triggers a warning
message about VLAN filtering, if requested.
Finally, enicpmd_vlan_offload_set should check both mask and
rxmode.offloads, not just mask.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:56 +00:00
|
|
|
if ((mask & ETH_VLAN_EXTEND_MASK) &&
|
|
|
|
(offloads & DEV_RX_OFFLOAD_VLAN_EXTEND)) {
|
2014-11-25 17:26:43 +00:00
|
|
|
dev_warning(enic,
|
|
|
|
"Configuration of extended VLAN is not supported\n");
|
|
|
|
}
|
2017-09-01 02:36:28 +00:00
|
|
|
|
net/enic: allow to change RSS settings
Currently, when more than 1 receive queues are configured, the driver
always enables RSS with the driver's own default hash type, key, and
RETA. The user is unable to change any of the RSS settings. Address
this by implementing the ethdev RSS API as follows.
Correctly report the RETA size, key size, and supported hash types
through rte_eth_dev_info.
During dev_configure(), initialize RSS according to the device's
mq_mode and rss_conf. Start with the default RETA, and use the default
key unless a custom key is provided.
Add the RETA and rss_conf query/set handlers to let the user change
RSS settings after the initial configuration. The hardware is able to
change hash type, key, and RETA individually. So, the handlers change
only the affected settings.
Refactor/rename several functions in order to make their intentions
clear. For example, remove all traces of RSS from
enicpmd_vlan_offload_set() as it is confusing.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:54 +00:00
|
|
|
return enic_set_vlan_strip(enic);
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_configure(struct rte_eth_dev *eth_dev)
|
|
|
|
{
|
|
|
|
int ret;
|
net/enic: remove VLAN filter handler
VIC does not support VLAN filtering at the moment. The firmware does
accept the filter add/del commands and returns success. But, they are
no-ops. To avoid confusion, remove the filter set handler so the app
sees an error instead of silent failure.
Also during the device configure time, enicpmd_vlan_offload_set would
not print a warning message about unsupported VLAN filtering, because
the caller specifies only ETH_VLAN_STRIP_MASK. This is wrong, as we
should attempt to apply all requested offloads at the configure
time. So, pass all VLAN offload masks, which triggers a warning
message about VLAN filtering, if requested.
Finally, enicpmd_vlan_offload_set should check both mask and
rxmode.offloads, not just mask.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:56 +00:00
|
|
|
int mask;
|
2014-11-25 17:26:43 +00:00
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
2017-09-11 18:58:33 +00:00
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return -E_RTE_SECONDARY;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
ret = enic_set_vnic_res(enic);
|
|
|
|
if (ret) {
|
|
|
|
dev_err(enic, "Set vNIC resource num failed, aborting\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-01-10 09:17:03 +00:00
|
|
|
enic->hw_ip_checksum = !!(eth_dev->data->dev_conf.rxmode.offloads &
|
|
|
|
DEV_RX_OFFLOAD_CHECKSUM);
|
net/enic: remove VLAN filter handler
VIC does not support VLAN filtering at the moment. The firmware does
accept the filter add/del commands and returns success. But, they are
no-ops. To avoid confusion, remove the filter set handler so the app
sees an error instead of silent failure.
Also during the device configure time, enicpmd_vlan_offload_set would
not print a warning message about unsupported VLAN filtering, because
the caller specifies only ETH_VLAN_STRIP_MASK. This is wrong, as we
should attempt to apply all requested offloads at the configure
time. So, pass all VLAN offload masks, which triggers a warning
message about VLAN filtering, if requested.
Finally, enicpmd_vlan_offload_set should check both mask and
rxmode.offloads, not just mask.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:56 +00:00
|
|
|
/* All vlan offload masks to apply the current settings */
|
|
|
|
mask = ETH_VLAN_STRIP_MASK |
|
|
|
|
ETH_VLAN_FILTER_MASK |
|
|
|
|
ETH_VLAN_EXTEND_MASK;
|
|
|
|
ret = enicpmd_vlan_offload_set(eth_dev, mask);
|
net/enic: allow to change RSS settings
Currently, when more than 1 receive queues are configured, the driver
always enables RSS with the driver's own default hash type, key, and
RETA. The user is unable to change any of the RSS settings. Address
this by implementing the ethdev RSS API as follows.
Correctly report the RETA size, key size, and supported hash types
through rte_eth_dev_info.
During dev_configure(), initialize RSS according to the device's
mq_mode and rss_conf. Start with the default RETA, and use the default
key unless a custom key is provided.
Add the RETA and rss_conf query/set handlers to let the user change
RSS settings after the initial configuration. The hardware is able to
change hash type, key, and RETA individually. So, the handlers change
only the affected settings.
Refactor/rename several functions in order to make their intentions
clear. For example, remove all traces of RSS from
enicpmd_vlan_offload_set() as it is confusing.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:54 +00:00
|
|
|
if (ret) {
|
|
|
|
dev_err(enic, "Failed to configure VLAN offloads\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Initialize RSS with the default reta and key. If the user key is
|
|
|
|
* given (rx_adv_conf.rss_conf.rss_key), will use that instead of the
|
|
|
|
* default key.
|
|
|
|
*/
|
|
|
|
return enic_init_rss_nic_cfg(enic);
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Start the device.
|
|
|
|
* It returns 0 on success.
|
|
|
|
*/
|
|
|
|
static int enicpmd_dev_start(struct rte_eth_dev *eth_dev)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
2017-09-11 18:58:33 +00:00
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return -E_RTE_SECONDARY;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
return enic_enable(enic);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Stop device: disable rx and tx functions to allow for reconfiguring.
|
|
|
|
*/
|
|
|
|
static void enicpmd_dev_stop(struct rte_eth_dev *eth_dev)
|
|
|
|
{
|
|
|
|
struct rte_eth_link link;
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
2017-09-11 18:58:33 +00:00
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
enic_disable(enic);
|
2018-01-26 02:01:51 +00:00
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
memset(&link, 0, sizeof(link));
|
2018-01-26 02:01:51 +00:00
|
|
|
rte_eth_linkstatus_set(eth_dev, &link);
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Stop device.
|
|
|
|
*/
|
|
|
|
static void enicpmd_dev_close(struct rte_eth_dev *eth_dev)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
enic_remove(enic);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_link_update(struct rte_eth_dev *eth_dev,
|
2014-12-02 13:38:31 +00:00
|
|
|
__rte_unused int wait_to_complete)
|
2014-11-25 17:26:43 +00:00
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
2016-09-19 18:50:10 +00:00
|
|
|
return enic_link_update(enic);
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|
|
|
|
|
2017-10-10 20:20:18 +00:00
|
|
|
static int enicpmd_dev_stats_get(struct rte_eth_dev *eth_dev,
|
2014-11-25 17:26:43 +00:00
|
|
|
struct rte_eth_stats *stats)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
2017-10-10 20:20:18 +00:00
|
|
|
return enic_dev_stats_get(enic, stats);
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void enicpmd_dev_stats_reset(struct rte_eth_dev *eth_dev)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
enic_dev_stats_clear(enic);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void enicpmd_dev_info_get(struct rte_eth_dev *eth_dev,
|
|
|
|
struct rte_eth_dev_info *device_info)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
net/enic: fix resource check failures when bonding devices
The enic PMD was using the same variables in the enic structure to
track two different things. Initially rq_count, wq_count, cq_count,
and intr_count were set to the values obtained from the VIC adapters
as the maximum resources allocated on the VIC, then in
enic_set_vnic_res(), they were set to the counts of resources actually
used, discarding the initial values. The checks in enic_set_vnic_res()
were technically incorrect if it is called more than once on a port,
which happens when using bonding, but were harmless in practice as the
checks couldn't fail on the second call.
The enic rx-scatter patch misunderstood the subtleties of
enic_set_vnic_res(), and naively added a multiply by two to the
rq_count check. This resulted in the rq_count check failing when
enic_set_vnic_res() was called a second time, ie when using bonding.
This patch adds new variables to the enic structure to track the
maximum resources the VIC is configured to provide so that the
information isn't later lost and calls to enic_set_vnic_res() do
the expected thing.
Fixes: 856d7ba7ed22 ("net/enic: support scattered Rx")
Signed-off-by: Nelson Escobar <neescoba@cisco.com>
2016-07-06 23:21:59 +00:00
|
|
|
/* Scattered Rx uses two receive queues per rx queue exposed to dpdk */
|
|
|
|
device_info->max_rx_queues = enic->conf_rq_count / 2;
|
|
|
|
device_info->max_tx_queues = enic->conf_wq_count;
|
2014-11-25 17:26:43 +00:00
|
|
|
device_info->min_rx_bufsize = ENIC_MIN_MTU;
|
2018-03-08 02:46:55 +00:00
|
|
|
/* "Max" mtu is not a typo. HW receives packet sizes up to the
|
|
|
|
* max mtu regardless of the current mtu (vNIC's mtu). vNIC mtu is
|
|
|
|
* a hint to the driver to size receive buffers accordingly so that
|
|
|
|
* larger-than-vnic-mtu packets get truncated.. For DPDK, we let
|
|
|
|
* the user decide the buffer size via rxmode.max_rx_pkt_len, basically
|
|
|
|
* ignoring vNIC mtu.
|
|
|
|
*/
|
|
|
|
device_info->max_rx_pktlen = enic_mtu_to_max_rx_pktlen(enic->max_mtu);
|
2017-01-26 20:12:12 +00:00
|
|
|
device_info->max_mac_addrs = ENIC_MAX_MAC_ADDR;
|
2018-04-16 21:49:10 +00:00
|
|
|
device_info->rx_offload_capa = enic->rx_offload_capa;
|
|
|
|
device_info->tx_offload_capa = enic->tx_offload_capa;
|
2018-06-29 09:29:38 +00:00
|
|
|
device_info->tx_queue_offload_capa = enic->tx_queue_offload_capa;
|
2016-03-04 21:09:00 +00:00
|
|
|
device_info->default_rxconf = (struct rte_eth_rxconf) {
|
|
|
|
.rx_free_thresh = ENIC_DEFAULT_RX_FREE_THRESH
|
|
|
|
};
|
net/enic: allow to change RSS settings
Currently, when more than 1 receive queues are configured, the driver
always enables RSS with the driver's own default hash type, key, and
RETA. The user is unable to change any of the RSS settings. Address
this by implementing the ethdev RSS API as follows.
Correctly report the RETA size, key size, and supported hash types
through rte_eth_dev_info.
During dev_configure(), initialize RSS according to the device's
mq_mode and rss_conf. Start with the default RETA, and use the default
key unless a custom key is provided.
Add the RETA and rss_conf query/set handlers to let the user change
RSS settings after the initial configuration. The hardware is able to
change hash type, key, and RETA individually. So, the handlers change
only the affected settings.
Refactor/rename several functions in order to make their intentions
clear. For example, remove all traces of RSS from
enicpmd_vlan_offload_set() as it is confusing.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:54 +00:00
|
|
|
device_info->reta_size = enic->reta_size;
|
|
|
|
device_info->hash_key_size = enic->hash_key_size;
|
|
|
|
device_info->flow_type_rss_offloads = enic->flow_type_rss_offloads;
|
2018-06-29 09:29:34 +00:00
|
|
|
device_info->rx_desc_lim = (struct rte_eth_desc_lim) {
|
|
|
|
.nb_max = enic->config.rq_desc_count,
|
|
|
|
.nb_min = ENIC_MIN_RQ_DESCS,
|
|
|
|
.nb_align = ENIC_ALIGN_DESCS,
|
|
|
|
};
|
|
|
|
device_info->tx_desc_lim = (struct rte_eth_desc_lim) {
|
|
|
|
.nb_max = enic->config.wq_desc_count,
|
|
|
|
.nb_min = ENIC_MIN_WQ_DESCS,
|
|
|
|
.nb_align = ENIC_ALIGN_DESCS,
|
|
|
|
.nb_seg_max = ENIC_TX_XMIT_MAX,
|
|
|
|
.nb_mtu_seg_max = ENIC_NON_TSO_MAX_DESC,
|
|
|
|
};
|
|
|
|
device_info->default_rxportconf = (struct rte_eth_dev_portconf) {
|
|
|
|
.burst_size = ENIC_DEFAULT_RX_BURST,
|
|
|
|
.ring_size = RTE_MIN(device_info->rx_desc_lim.nb_max,
|
|
|
|
ENIC_DEFAULT_RX_RING_SIZE),
|
|
|
|
.nb_queues = ENIC_DEFAULT_RX_RINGS,
|
|
|
|
};
|
|
|
|
device_info->default_txportconf = (struct rte_eth_dev_portconf) {
|
|
|
|
.burst_size = ENIC_DEFAULT_TX_BURST,
|
|
|
|
.ring_size = RTE_MIN(device_info->tx_desc_lim.nb_max,
|
|
|
|
ENIC_DEFAULT_TX_RING_SIZE),
|
|
|
|
.nb_queues = ENIC_DEFAULT_TX_RINGS,
|
|
|
|
};
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|
|
|
|
|
2016-03-14 20:50:50 +00:00
|
|
|
static const uint32_t *enicpmd_dev_supported_ptypes_get(struct rte_eth_dev *dev)
|
|
|
|
{
|
|
|
|
static const uint32_t ptypes[] = {
|
2016-08-24 19:07:02 +00:00
|
|
|
RTE_PTYPE_L2_ETHER,
|
|
|
|
RTE_PTYPE_L2_ETHER_VLAN,
|
2016-06-14 23:54:05 +00:00
|
|
|
RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
|
|
|
|
RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
|
|
|
|
RTE_PTYPE_L4_TCP,
|
|
|
|
RTE_PTYPE_L4_UDP,
|
|
|
|
RTE_PTYPE_L4_FRAG,
|
|
|
|
RTE_PTYPE_L4_NONFRAG,
|
2016-03-14 20:50:50 +00:00
|
|
|
RTE_PTYPE_UNKNOWN
|
|
|
|
};
|
2018-10-20 08:32:47 +00:00
|
|
|
static const uint32_t ptypes_overlay[] = {
|
|
|
|
RTE_PTYPE_L2_ETHER,
|
|
|
|
RTE_PTYPE_L2_ETHER_VLAN,
|
|
|
|
RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
|
|
|
|
RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
|
|
|
|
RTE_PTYPE_L4_TCP,
|
|
|
|
RTE_PTYPE_L4_UDP,
|
|
|
|
RTE_PTYPE_L4_FRAG,
|
|
|
|
RTE_PTYPE_L4_NONFRAG,
|
|
|
|
RTE_PTYPE_TUNNEL_GRENAT,
|
|
|
|
RTE_PTYPE_INNER_L2_ETHER,
|
|
|
|
RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
|
|
|
|
RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
|
|
|
|
RTE_PTYPE_INNER_L4_TCP,
|
|
|
|
RTE_PTYPE_INNER_L4_UDP,
|
|
|
|
RTE_PTYPE_INNER_L4_FRAG,
|
|
|
|
RTE_PTYPE_INNER_L4_NONFRAG,
|
|
|
|
RTE_PTYPE_UNKNOWN
|
|
|
|
};
|
2016-03-14 20:50:50 +00:00
|
|
|
|
2018-10-20 08:32:47 +00:00
|
|
|
if (dev->rx_pkt_burst != enic_dummy_recv_pkts &&
|
|
|
|
dev->rx_pkt_burst != NULL) {
|
|
|
|
struct enic *enic = pmd_priv(dev);
|
|
|
|
if (enic->overlay_offload)
|
|
|
|
return ptypes_overlay;
|
|
|
|
else
|
|
|
|
return ptypes;
|
|
|
|
}
|
2016-03-14 20:50:50 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
static void enicpmd_dev_promiscuous_enable(struct rte_eth_dev *eth_dev)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
2017-09-11 18:58:33 +00:00
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
ENICPMD_FUNC_TRACE();
|
2017-09-11 18:58:33 +00:00
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
enic->promisc = 1;
|
|
|
|
enic_add_packet_filter(enic);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void enicpmd_dev_promiscuous_disable(struct rte_eth_dev *eth_dev)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
2017-09-11 18:58:33 +00:00
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
enic->promisc = 0;
|
|
|
|
enic_add_packet_filter(enic);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void enicpmd_dev_allmulticast_enable(struct rte_eth_dev *eth_dev)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
2017-09-11 18:58:33 +00:00
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
enic->allmulti = 1;
|
|
|
|
enic_add_packet_filter(enic);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void enicpmd_dev_allmulticast_disable(struct rte_eth_dev *eth_dev)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
2017-09-11 18:58:33 +00:00
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
enic->allmulti = 0;
|
|
|
|
enic_add_packet_filter(enic);
|
|
|
|
}
|
|
|
|
|
2017-05-05 00:40:00 +00:00
|
|
|
static int enicpmd_add_mac_addr(struct rte_eth_dev *eth_dev,
|
2014-11-25 17:26:43 +00:00
|
|
|
struct ether_addr *mac_addr,
|
2014-12-02 13:38:31 +00:00
|
|
|
__rte_unused uint32_t index, __rte_unused uint32_t pool)
|
2014-11-25 17:26:43 +00:00
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
2017-09-11 18:58:33 +00:00
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return -E_RTE_SECONDARY;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
ENICPMD_FUNC_TRACE();
|
2017-05-05 00:40:00 +00:00
|
|
|
return enic_set_mac_address(enic, mac_addr->addr_bytes);
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|
|
|
|
|
2017-01-26 20:12:12 +00:00
|
|
|
static void enicpmd_remove_mac_addr(struct rte_eth_dev *eth_dev, uint32_t index)
|
2014-11-25 17:26:43 +00:00
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
2017-09-11 18:58:33 +00:00
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
ENICPMD_FUNC_TRACE();
|
2018-04-16 09:40:17 +00:00
|
|
|
if (enic_del_mac_address(enic, index))
|
|
|
|
dev_err(enic, "del mac addr failed\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_set_mac_addr(struct rte_eth_dev *eth_dev,
|
|
|
|
struct ether_addr *addr)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
if (rte_eal_process_type() != RTE_PROC_PRIMARY)
|
|
|
|
return -E_RTE_SECONDARY;
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
ret = enic_del_mac_address(enic, 0);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
return enic_set_mac_address(enic, addr->addr_bytes);
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 22:29:28 +00:00
|
|
|
static int enicpmd_mtu_set(struct rte_eth_dev *eth_dev, uint16_t mtu)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
return enic_set_mtu(enic, mtu);
|
|
|
|
}
|
|
|
|
|
net/enic: allow to change RSS settings
Currently, when more than 1 receive queues are configured, the driver
always enables RSS with the driver's own default hash type, key, and
RETA. The user is unable to change any of the RSS settings. Address
this by implementing the ethdev RSS API as follows.
Correctly report the RETA size, key size, and supported hash types
through rte_eth_dev_info.
During dev_configure(), initialize RSS according to the device's
mq_mode and rss_conf. Start with the default RETA, and use the default
key unless a custom key is provided.
Add the RETA and rss_conf query/set handlers to let the user change
RSS settings after the initial configuration. The hardware is able to
change hash type, key, and RETA individually. So, the handlers change
only the affected settings.
Refactor/rename several functions in order to make their intentions
clear. For example, remove all traces of RSS from
enicpmd_vlan_offload_set() as it is confusing.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:54 +00:00
|
|
|
static int enicpmd_dev_rss_reta_query(struct rte_eth_dev *dev,
|
|
|
|
struct rte_eth_rss_reta_entry64
|
|
|
|
*reta_conf,
|
|
|
|
uint16_t reta_size)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(dev);
|
|
|
|
uint16_t i, idx, shift;
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
if (reta_size != ENIC_RSS_RETA_SIZE) {
|
|
|
|
dev_err(enic, "reta_query: wrong reta_size. given=%u expected=%u\n",
|
|
|
|
reta_size, ENIC_RSS_RETA_SIZE);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < reta_size; i++) {
|
|
|
|
idx = i / RTE_RETA_GROUP_SIZE;
|
|
|
|
shift = i % RTE_RETA_GROUP_SIZE;
|
|
|
|
if (reta_conf[idx].mask & (1ULL << shift))
|
|
|
|
reta_conf[idx].reta[shift] = enic_sop_rq_idx_to_rte_idx(
|
|
|
|
enic->rss_cpu.cpu[i / 4].b[i % 4]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_rss_reta_update(struct rte_eth_dev *dev,
|
|
|
|
struct rte_eth_rss_reta_entry64
|
|
|
|
*reta_conf,
|
|
|
|
uint16_t reta_size)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(dev);
|
|
|
|
union vnic_rss_cpu rss_cpu;
|
|
|
|
uint16_t i, idx, shift;
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
if (reta_size != ENIC_RSS_RETA_SIZE) {
|
|
|
|
dev_err(enic, "reta_update: wrong reta_size. given=%u"
|
|
|
|
" expected=%u\n",
|
|
|
|
reta_size, ENIC_RSS_RETA_SIZE);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Start with the current reta and modify it per reta_conf, as we
|
|
|
|
* need to push the entire reta even if we only modify one entry.
|
|
|
|
*/
|
|
|
|
rss_cpu = enic->rss_cpu;
|
|
|
|
for (i = 0; i < reta_size; i++) {
|
|
|
|
idx = i / RTE_RETA_GROUP_SIZE;
|
|
|
|
shift = i % RTE_RETA_GROUP_SIZE;
|
|
|
|
if (reta_conf[idx].mask & (1ULL << shift))
|
|
|
|
rss_cpu.cpu[i / 4].b[i % 4] =
|
|
|
|
enic_rte_rq_idx_to_sop_idx(
|
|
|
|
reta_conf[idx].reta[shift]);
|
|
|
|
}
|
|
|
|
return enic_set_rss_reta(enic, &rss_cpu);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_rss_hash_update(struct rte_eth_dev *dev,
|
|
|
|
struct rte_eth_rss_conf *rss_conf)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
return enic_set_rss_conf(enic, rss_conf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
|
|
|
|
struct rte_eth_rss_conf *rss_conf)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
if (rss_conf == NULL)
|
|
|
|
return -EINVAL;
|
|
|
|
if (rss_conf->rss_key != NULL &&
|
|
|
|
rss_conf->rss_key_len < ENIC_RSS_HASH_KEY_SIZE) {
|
|
|
|
dev_err(enic, "rss_hash_conf_get: wrong rss_key_len. given=%u"
|
|
|
|
" expected=%u+\n",
|
|
|
|
rss_conf->rss_key_len, ENIC_RSS_HASH_KEY_SIZE);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
rss_conf->rss_hf = enic->rss_hf;
|
|
|
|
if (rss_conf->rss_key != NULL) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < ENIC_RSS_HASH_KEY_SIZE; i++) {
|
|
|
|
rss_conf->rss_key[i] =
|
|
|
|
enic->rss_key.key[i / 10].b[i % 10];
|
|
|
|
}
|
|
|
|
rss_conf->rss_key_len = ENIC_RSS_HASH_KEY_SIZE;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-03-08 02:46:57 +00:00
|
|
|
static void enicpmd_dev_rxq_info_get(struct rte_eth_dev *dev,
|
|
|
|
uint16_t rx_queue_id,
|
|
|
|
struct rte_eth_rxq_info *qinfo)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(dev);
|
|
|
|
struct vnic_rq *rq_sop;
|
|
|
|
struct vnic_rq *rq_data;
|
|
|
|
struct rte_eth_rxconf *conf;
|
|
|
|
uint16_t sop_queue_idx;
|
|
|
|
uint16_t data_queue_idx;
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
sop_queue_idx = enic_rte_rq_idx_to_sop_idx(rx_queue_id);
|
|
|
|
data_queue_idx = enic_rte_rq_idx_to_data_idx(rx_queue_id);
|
|
|
|
rq_sop = &enic->rq[sop_queue_idx];
|
|
|
|
rq_data = &enic->rq[data_queue_idx]; /* valid if data_queue_enable */
|
|
|
|
qinfo->mp = rq_sop->mp;
|
|
|
|
qinfo->scattered_rx = rq_sop->data_queue_enable;
|
|
|
|
qinfo->nb_desc = rq_sop->ring.desc_count;
|
|
|
|
if (qinfo->scattered_rx)
|
|
|
|
qinfo->nb_desc += rq_data->ring.desc_count;
|
|
|
|
conf = &qinfo->conf;
|
|
|
|
memset(conf, 0, sizeof(*conf));
|
|
|
|
conf->rx_free_thresh = rq_sop->rx_free_thresh;
|
|
|
|
conf->rx_drop_en = 1;
|
|
|
|
/*
|
|
|
|
* Except VLAN stripping (port setting), all the checksum offloads
|
|
|
|
* are always enabled.
|
|
|
|
*/
|
2018-04-16 21:49:10 +00:00
|
|
|
conf->offloads = enic->rx_offload_capa;
|
2018-03-08 02:46:57 +00:00
|
|
|
if (!enic->ig_vlan_strip_en)
|
|
|
|
conf->offloads &= ~DEV_RX_OFFLOAD_VLAN_STRIP;
|
|
|
|
/* rx_thresh and other fields are not applicable for enic */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void enicpmd_dev_txq_info_get(struct rte_eth_dev *dev,
|
2018-06-29 09:29:32 +00:00
|
|
|
uint16_t tx_queue_id,
|
2018-03-08 02:46:57 +00:00
|
|
|
struct rte_eth_txq_info *qinfo)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(dev);
|
2018-06-29 09:29:32 +00:00
|
|
|
struct vnic_wq *wq = &enic->wq[tx_queue_id];
|
2018-03-08 02:46:57 +00:00
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
2018-06-29 09:29:32 +00:00
|
|
|
qinfo->nb_desc = wq->ring.desc_count;
|
2018-03-08 02:46:57 +00:00
|
|
|
memset(&qinfo->conf, 0, sizeof(qinfo->conf));
|
2018-06-29 09:29:38 +00:00
|
|
|
qinfo->conf.offloads = wq->offloads;
|
2018-03-08 02:46:57 +00:00
|
|
|
/* tx_thresh, and all the other fields are not applicable for enic */
|
|
|
|
}
|
|
|
|
|
2018-03-08 02:46:59 +00:00
|
|
|
static int enicpmd_dev_rx_queue_intr_enable(struct rte_eth_dev *eth_dev,
|
|
|
|
uint16_t rx_queue_id)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
vnic_intr_unmask(&enic->intr[rx_queue_id + ENICPMD_RXQ_INTR_OFFSET]);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_rx_queue_intr_disable(struct rte_eth_dev *eth_dev,
|
|
|
|
uint16_t rx_queue_id)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
vnic_intr_mask(&enic->intr[rx_queue_id + ENICPMD_RXQ_INTR_OFFSET]);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-06-29 09:29:36 +00:00
|
|
|
static int udp_tunnel_common_check(struct enic *enic,
|
|
|
|
struct rte_eth_udp_tunnel *tnl)
|
|
|
|
{
|
|
|
|
if (tnl->prot_type != RTE_TUNNEL_TYPE_VXLAN)
|
|
|
|
return -ENOTSUP;
|
|
|
|
if (!enic->overlay_offload) {
|
|
|
|
PMD_INIT_LOG(DEBUG, " vxlan (overlay offload) is not "
|
|
|
|
"supported\n");
|
|
|
|
return -ENOTSUP;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int update_vxlan_port(struct enic *enic, uint16_t port)
|
|
|
|
{
|
|
|
|
if (vnic_dev_overlay_offload_cfg(enic->vdev,
|
|
|
|
OVERLAY_CFG_VXLAN_PORT_UPDATE,
|
|
|
|
port)) {
|
|
|
|
PMD_INIT_LOG(DEBUG, " failed to update vxlan port\n");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
PMD_INIT_LOG(DEBUG, " updated vxlan port to %u\n", port);
|
|
|
|
enic->vxlan_port = port;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_udp_tunnel_port_add(struct rte_eth_dev *eth_dev,
|
|
|
|
struct rte_eth_udp_tunnel *tnl)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
ret = udp_tunnel_common_check(enic, tnl);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
/*
|
|
|
|
* The NIC has 1 configurable VXLAN port number. "Adding" a new port
|
|
|
|
* number replaces it.
|
|
|
|
*/
|
|
|
|
if (tnl->udp_port == enic->vxlan_port || tnl->udp_port == 0) {
|
|
|
|
PMD_INIT_LOG(DEBUG, " %u is already configured or invalid\n",
|
|
|
|
tnl->udp_port);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
return update_vxlan_port(enic, tnl->udp_port);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int enicpmd_dev_udp_tunnel_port_del(struct rte_eth_dev *eth_dev,
|
|
|
|
struct rte_eth_udp_tunnel *tnl)
|
|
|
|
{
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
ret = udp_tunnel_common_check(enic, tnl);
|
|
|
|
if (ret)
|
|
|
|
return ret;
|
|
|
|
/*
|
|
|
|
* Clear the previously set port number and restore the
|
|
|
|
* hardware default port number. Some drivers disable VXLAN
|
|
|
|
* offloads when there are no configured port numbers. But
|
|
|
|
* enic does not do that as VXLAN is part of overlay offload,
|
|
|
|
* which is tied to inner RSS and TSO.
|
|
|
|
*/
|
|
|
|
if (tnl->udp_port != enic->vxlan_port) {
|
|
|
|
PMD_INIT_LOG(DEBUG, " %u is not a configured vxlan port\n",
|
|
|
|
tnl->udp_port);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
return update_vxlan_port(enic, ENIC_DEFAULT_VXLAN_PORT);
|
|
|
|
}
|
|
|
|
|
2015-04-07 21:21:03 +00:00
|
|
|
static const struct eth_dev_ops enicpmd_eth_dev_ops = {
|
2014-11-25 17:26:43 +00:00
|
|
|
.dev_configure = enicpmd_dev_configure,
|
|
|
|
.dev_start = enicpmd_dev_start,
|
|
|
|
.dev_stop = enicpmd_dev_stop,
|
|
|
|
.dev_set_link_up = NULL,
|
|
|
|
.dev_set_link_down = NULL,
|
|
|
|
.dev_close = enicpmd_dev_close,
|
|
|
|
.promiscuous_enable = enicpmd_dev_promiscuous_enable,
|
|
|
|
.promiscuous_disable = enicpmd_dev_promiscuous_disable,
|
|
|
|
.allmulticast_enable = enicpmd_dev_allmulticast_enable,
|
|
|
|
.allmulticast_disable = enicpmd_dev_allmulticast_disable,
|
|
|
|
.link_update = enicpmd_dev_link_update,
|
|
|
|
.stats_get = enicpmd_dev_stats_get,
|
|
|
|
.stats_reset = enicpmd_dev_stats_reset,
|
|
|
|
.queue_stats_mapping_set = NULL,
|
|
|
|
.dev_infos_get = enicpmd_dev_info_get,
|
2016-03-14 20:50:50 +00:00
|
|
|
.dev_supported_ptypes_get = enicpmd_dev_supported_ptypes_get,
|
2016-06-24 22:29:28 +00:00
|
|
|
.mtu_set = enicpmd_mtu_set,
|
net/enic: remove VLAN filter handler
VIC does not support VLAN filtering at the moment. The firmware does
accept the filter add/del commands and returns success. But, they are
no-ops. To avoid confusion, remove the filter set handler so the app
sees an error instead of silent failure.
Also during the device configure time, enicpmd_vlan_offload_set would
not print a warning message about unsupported VLAN filtering, because
the caller specifies only ETH_VLAN_STRIP_MASK. This is wrong, as we
should attempt to apply all requested offloads at the configure
time. So, pass all VLAN offload masks, which triggers a warning
message about VLAN filtering, if requested.
Finally, enicpmd_vlan_offload_set should check both mask and
rxmode.offloads, not just mask.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:56 +00:00
|
|
|
.vlan_filter_set = NULL,
|
2014-11-25 17:26:43 +00:00
|
|
|
.vlan_tpid_set = NULL,
|
|
|
|
.vlan_offload_set = enicpmd_vlan_offload_set,
|
|
|
|
.vlan_strip_queue_set = NULL,
|
|
|
|
.rx_queue_start = enicpmd_dev_rx_queue_start,
|
|
|
|
.rx_queue_stop = enicpmd_dev_rx_queue_stop,
|
|
|
|
.tx_queue_start = enicpmd_dev_tx_queue_start,
|
|
|
|
.tx_queue_stop = enicpmd_dev_tx_queue_stop,
|
|
|
|
.rx_queue_setup = enicpmd_dev_rx_queue_setup,
|
|
|
|
.rx_queue_release = enicpmd_dev_rx_queue_release,
|
2016-09-19 18:50:29 +00:00
|
|
|
.rx_queue_count = enicpmd_dev_rx_queue_count,
|
2014-11-25 17:26:43 +00:00
|
|
|
.rx_descriptor_done = NULL,
|
|
|
|
.tx_queue_setup = enicpmd_dev_tx_queue_setup,
|
|
|
|
.tx_queue_release = enicpmd_dev_tx_queue_release,
|
2018-03-08 02:46:59 +00:00
|
|
|
.rx_queue_intr_enable = enicpmd_dev_rx_queue_intr_enable,
|
|
|
|
.rx_queue_intr_disable = enicpmd_dev_rx_queue_intr_disable,
|
2018-03-08 02:46:57 +00:00
|
|
|
.rxq_info_get = enicpmd_dev_rxq_info_get,
|
|
|
|
.txq_info_get = enicpmd_dev_txq_info_get,
|
2014-11-25 17:26:43 +00:00
|
|
|
.dev_led_on = NULL,
|
|
|
|
.dev_led_off = NULL,
|
|
|
|
.flow_ctrl_get = NULL,
|
|
|
|
.flow_ctrl_set = NULL,
|
|
|
|
.priority_flow_ctrl_set = NULL,
|
|
|
|
.mac_addr_add = enicpmd_add_mac_addr,
|
|
|
|
.mac_addr_remove = enicpmd_remove_mac_addr,
|
2018-04-16 09:40:17 +00:00
|
|
|
.mac_addr_set = enicpmd_set_mac_addr,
|
2015-04-09 09:29:32 +00:00
|
|
|
.filter_ctrl = enicpmd_dev_filter_ctrl,
|
net/enic: allow to change RSS settings
Currently, when more than 1 receive queues are configured, the driver
always enables RSS with the driver's own default hash type, key, and
RETA. The user is unable to change any of the RSS settings. Address
this by implementing the ethdev RSS API as follows.
Correctly report the RETA size, key size, and supported hash types
through rte_eth_dev_info.
During dev_configure(), initialize RSS according to the device's
mq_mode and rss_conf. Start with the default RETA, and use the default
key unless a custom key is provided.
Add the RETA and rss_conf query/set handlers to let the user change
RSS settings after the initial configuration. The hardware is able to
change hash type, key, and RETA individually. So, the handlers change
only the affected settings.
Refactor/rename several functions in order to make their intentions
clear. For example, remove all traces of RSS from
enicpmd_vlan_offload_set() as it is confusing.
Signed-off-by: Hyong Youb Kim <hyonkim@cisco.com>
Reviewed-by: John Daley <johndale@cisco.com>
2018-03-08 02:46:54 +00:00
|
|
|
.reta_query = enicpmd_dev_rss_reta_query,
|
|
|
|
.reta_update = enicpmd_dev_rss_reta_update,
|
|
|
|
.rss_hash_conf_get = enicpmd_dev_rss_hash_conf_get,
|
|
|
|
.rss_hash_update = enicpmd_dev_rss_hash_update,
|
2018-06-29 09:29:36 +00:00
|
|
|
.udp_tunnel_port_add = enicpmd_dev_udp_tunnel_port_add,
|
|
|
|
.udp_tunnel_port_del = enicpmd_dev_udp_tunnel_port_del,
|
2014-11-25 17:26:43 +00:00
|
|
|
};
|
|
|
|
|
2018-10-03 20:09:28 +00:00
|
|
|
static int enic_parse_zero_one(const char *key,
|
|
|
|
const char *value,
|
|
|
|
void *opaque)
|
2018-04-16 21:49:10 +00:00
|
|
|
{
|
|
|
|
struct enic *enic;
|
2018-10-03 20:09:28 +00:00
|
|
|
bool b;
|
2018-04-16 21:49:10 +00:00
|
|
|
|
|
|
|
enic = (struct enic *)opaque;
|
|
|
|
if (strcmp(value, "0") == 0) {
|
2018-10-03 20:09:28 +00:00
|
|
|
b = false;
|
2018-04-16 21:49:10 +00:00
|
|
|
} else if (strcmp(value, "1") == 0) {
|
2018-10-03 20:09:28 +00:00
|
|
|
b = true;
|
2018-04-16 21:49:10 +00:00
|
|
|
} else {
|
2018-10-03 20:09:28 +00:00
|
|
|
dev_err(enic, "Invalid value for %s"
|
|
|
|
": expected=0|1 given=%s\n", key, value);
|
2018-04-16 21:49:10 +00:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
2018-10-03 20:09:28 +00:00
|
|
|
if (strcmp(key, ENIC_DEVARG_DISABLE_OVERLAY) == 0)
|
|
|
|
enic->disable_overlay = b;
|
|
|
|
if (strcmp(key, ENIC_DEVARG_ENABLE_AVX2_RX) == 0)
|
|
|
|
enic->enable_avx2_rx = b;
|
2018-04-16 21:49:10 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-06-29 09:29:35 +00:00
|
|
|
static int enic_parse_ig_vlan_rewrite(__rte_unused const char *key,
|
|
|
|
const char *value,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
struct enic *enic;
|
|
|
|
|
|
|
|
enic = (struct enic *)opaque;
|
|
|
|
if (strcmp(value, "trunk") == 0) {
|
|
|
|
/* Trunk mode: always tag */
|
|
|
|
enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_DEFAULT_TRUNK;
|
|
|
|
} else if (strcmp(value, "untag") == 0) {
|
|
|
|
/* Untag default VLAN mode: untag if VLAN = default VLAN */
|
|
|
|
enic->ig_vlan_rewrite_mode =
|
|
|
|
IG_VLAN_REWRITE_MODE_UNTAG_DEFAULT_VLAN;
|
|
|
|
} else if (strcmp(value, "priority") == 0) {
|
|
|
|
/*
|
|
|
|
* Priority-tag default VLAN mode: priority tag (VLAN header
|
|
|
|
* with ID=0) if VLAN = default
|
|
|
|
*/
|
|
|
|
enic->ig_vlan_rewrite_mode =
|
|
|
|
IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN;
|
|
|
|
} else if (strcmp(value, "pass") == 0) {
|
|
|
|
/* Pass through mode: do not touch tags */
|
|
|
|
enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PASS_THRU;
|
|
|
|
} else {
|
|
|
|
dev_err(enic, "Invalid value for " ENIC_DEVARG_IG_VLAN_REWRITE
|
|
|
|
": expected=trunk|untag|priority|pass given=%s\n",
|
|
|
|
value);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-04-16 21:49:10 +00:00
|
|
|
static int enic_check_devargs(struct rte_eth_dev *dev)
|
|
|
|
{
|
|
|
|
static const char *const valid_keys[] = {
|
2018-06-29 09:29:35 +00:00
|
|
|
ENIC_DEVARG_DISABLE_OVERLAY,
|
2018-10-03 20:09:28 +00:00
|
|
|
ENIC_DEVARG_ENABLE_AVX2_RX,
|
2018-06-29 09:29:35 +00:00
|
|
|
ENIC_DEVARG_IG_VLAN_REWRITE,
|
|
|
|
NULL};
|
2018-04-16 21:49:10 +00:00
|
|
|
struct enic *enic = pmd_priv(dev);
|
|
|
|
struct rte_kvargs *kvlist;
|
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
|
|
|
|
enic->disable_overlay = false;
|
2018-10-03 20:09:28 +00:00
|
|
|
enic->enable_avx2_rx = false;
|
2018-06-29 09:29:35 +00:00
|
|
|
enic->ig_vlan_rewrite_mode = IG_VLAN_REWRITE_MODE_PASS_THRU;
|
2018-04-16 21:49:10 +00:00
|
|
|
if (!dev->device->devargs)
|
|
|
|
return 0;
|
|
|
|
kvlist = rte_kvargs_parse(dev->device->devargs->args, valid_keys);
|
|
|
|
if (!kvlist)
|
|
|
|
return -EINVAL;
|
|
|
|
if (rte_kvargs_process(kvlist, ENIC_DEVARG_DISABLE_OVERLAY,
|
2018-10-03 20:09:28 +00:00
|
|
|
enic_parse_zero_one, enic) < 0 ||
|
|
|
|
rte_kvargs_process(kvlist, ENIC_DEVARG_ENABLE_AVX2_RX,
|
|
|
|
enic_parse_zero_one, enic) < 0 ||
|
2018-06-29 09:29:35 +00:00
|
|
|
rte_kvargs_process(kvlist, ENIC_DEVARG_IG_VLAN_REWRITE,
|
|
|
|
enic_parse_ig_vlan_rewrite, enic) < 0) {
|
2018-04-16 21:49:10 +00:00
|
|
|
rte_kvargs_free(kvlist);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
rte_kvargs_free(kvlist);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
struct enic *enicpmd_list_head = NULL;
|
|
|
|
/* Initialize the driver
|
|
|
|
* It returns 0 on success.
|
|
|
|
*/
|
2015-03-05 18:24:59 +00:00
|
|
|
static int eth_enicpmd_dev_init(struct rte_eth_dev *eth_dev)
|
2014-11-25 17:26:43 +00:00
|
|
|
{
|
|
|
|
struct rte_pci_device *pdev;
|
|
|
|
struct rte_pci_addr *addr;
|
|
|
|
struct enic *enic = pmd_priv(eth_dev);
|
2018-04-16 21:49:10 +00:00
|
|
|
int err;
|
2014-11-25 17:26:43 +00:00
|
|
|
|
|
|
|
ENICPMD_FUNC_TRACE();
|
|
|
|
|
2015-04-14 14:23:55 +00:00
|
|
|
enic->port_id = eth_dev->data->port_id;
|
2014-11-25 17:26:43 +00:00
|
|
|
enic->rte_dev = eth_dev;
|
|
|
|
eth_dev->dev_ops = &enicpmd_eth_dev_ops;
|
2016-03-04 21:09:00 +00:00
|
|
|
eth_dev->rx_pkt_burst = &enic_recv_pkts;
|
2016-06-03 00:22:49 +00:00
|
|
|
eth_dev->tx_pkt_burst = &enic_xmit_pkts;
|
2018-01-23 01:05:29 +00:00
|
|
|
eth_dev->tx_pkt_prepare = &enic_prep_pkts;
|
2014-11-25 17:26:43 +00:00
|
|
|
|
2017-05-15 10:24:03 +00:00
|
|
|
pdev = RTE_ETH_DEV_TO_PCI(eth_dev);
|
2015-11-03 13:01:56 +00:00
|
|
|
rte_eth_copy_pci_info(eth_dev, pdev);
|
2014-11-25 17:26:43 +00:00
|
|
|
enic->pdev = pdev;
|
|
|
|
addr = &pdev->addr;
|
|
|
|
|
|
|
|
snprintf(enic->bdf_name, ENICPMD_BDF_LENGTH, "%04x:%02x:%02x.%x",
|
|
|
|
addr->domain, addr->bus, addr->devid, addr->function);
|
|
|
|
|
2018-04-16 21:49:10 +00:00
|
|
|
err = enic_check_devargs(eth_dev);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2014-11-25 17:26:43 +00:00
|
|
|
return enic_probe(enic);
|
|
|
|
}
|
|
|
|
|
2017-04-11 15:44:24 +00:00
|
|
|
static int eth_enic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
|
|
|
|
struct rte_pci_device *pci_dev)
|
|
|
|
{
|
|
|
|
return rte_eth_dev_pci_generic_probe(pci_dev, sizeof(struct enic),
|
|
|
|
eth_enicpmd_dev_init);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eth_enic_pci_remove(struct rte_pci_device *pci_dev)
|
|
|
|
{
|
|
|
|
return rte_eth_dev_pci_generic_remove(pci_dev, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct rte_pci_driver rte_enic_pmd = {
|
|
|
|
.id_table = pci_id_enic_map,
|
2018-09-26 02:54:18 +00:00
|
|
|
.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC |
|
|
|
|
RTE_PCI_DRV_IOVA_AS_VA,
|
2017-04-11 15:44:24 +00:00
|
|
|
.probe = eth_enic_pci_probe,
|
|
|
|
.remove = eth_enic_pci_remove,
|
2014-11-25 17:26:43 +00:00
|
|
|
};
|
|
|
|
|
2017-04-11 15:44:24 +00:00
|
|
|
RTE_PMD_REGISTER_PCI(net_enic, rte_enic_pmd);
|
2016-10-10 05:43:15 +00:00
|
|
|
RTE_PMD_REGISTER_PCI_TABLE(net_enic, pci_id_enic_map);
|
2017-05-20 13:12:37 +00:00
|
|
|
RTE_PMD_REGISTER_KMOD_DEP(net_enic, "* igb_uio | uio_pci_generic | vfio-pci");
|
2018-04-16 21:49:10 +00:00
|
|
|
RTE_PMD_REGISTER_PARAM_STRING(net_enic,
|
2018-06-29 09:29:35 +00:00
|
|
|
ENIC_DEVARG_DISABLE_OVERLAY "=0|1 "
|
2018-10-03 20:09:28 +00:00
|
|
|
ENIC_DEVARG_ENABLE_AVX2_RX "=0|1 "
|
2018-06-29 09:29:35 +00:00
|
|
|
ENIC_DEVARG_IG_VLAN_REWRITE "=trunk|untag|priority|pass");
|