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 "enic_compat.h"
|
2018-01-22 00:16:22 +00:00
|
|
|
#include "rte_ethdev_driver.h"
|
2014-11-25 17:26:43 +00:00
|
|
|
#include "wq_enet_desc.h"
|
|
|
|
#include "rq_enet_desc.h"
|
|
|
|
#include "cq_enet_desc.h"
|
|
|
|
#include "vnic_resource.h"
|
|
|
|
#include "vnic_enet.h"
|
|
|
|
#include "vnic_dev.h"
|
|
|
|
#include "vnic_wq.h"
|
|
|
|
#include "vnic_rq.h"
|
|
|
|
#include "vnic_cq.h"
|
|
|
|
#include "vnic_intr.h"
|
|
|
|
#include "vnic_stats.h"
|
|
|
|
#include "vnic_nic.h"
|
|
|
|
#include "vnic_rss.h"
|
|
|
|
#include "enic_res.h"
|
|
|
|
#include "enic.h"
|
|
|
|
|
|
|
|
int enic_get_vnic_config(struct enic *enic)
|
|
|
|
{
|
|
|
|
struct vnic_enet_config *c = &enic->config;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = vnic_dev_get_mac_addr(enic->vdev, enic->mac_addr);
|
|
|
|
if (err) {
|
|
|
|
dev_err(enic_get_dev(enic),
|
|
|
|
"Error getting MAC addr, %d\n", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2016-09-29 20:56:39 +00:00
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
#define GET_CONFIG(m) \
|
|
|
|
do { \
|
|
|
|
err = vnic_dev_spec(enic->vdev, \
|
|
|
|
offsetof(struct vnic_enet_config, m), \
|
|
|
|
sizeof(c->m), &c->m); \
|
|
|
|
if (err) { \
|
|
|
|
dev_err(enic_get_dev(enic), \
|
|
|
|
"Error getting %s, %d\n", #m, err); \
|
|
|
|
return err; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
GET_CONFIG(flags);
|
|
|
|
GET_CONFIG(wq_desc_count);
|
|
|
|
GET_CONFIG(rq_desc_count);
|
|
|
|
GET_CONFIG(mtu);
|
|
|
|
GET_CONFIG(intr_timer_type);
|
|
|
|
GET_CONFIG(intr_mode);
|
|
|
|
GET_CONFIG(intr_timer_usec);
|
|
|
|
GET_CONFIG(loop_tag);
|
|
|
|
GET_CONFIG(num_arfs);
|
2016-06-24 22:29:27 +00:00
|
|
|
GET_CONFIG(max_pkt_size);
|
|
|
|
|
|
|
|
/* max packet size is only defined in newer VIC firmware
|
|
|
|
* and will be 0 for legacy firmware and VICs
|
|
|
|
*/
|
2017-02-03 01:18:40 +00:00
|
|
|
if (c->max_pkt_size > ENIC_DEFAULT_RX_MAX_PKT_SIZE)
|
2016-06-24 22:29:27 +00:00
|
|
|
enic->max_mtu = c->max_pkt_size - (ETHER_HDR_LEN + 4);
|
|
|
|
else
|
2017-02-03 01:18:40 +00:00
|
|
|
enic->max_mtu = ENIC_DEFAULT_RX_MAX_PKT_SIZE
|
|
|
|
- (ETHER_HDR_LEN + 4);
|
2016-06-24 22:29:27 +00:00
|
|
|
if (c->mtu == 0)
|
|
|
|
c->mtu = 1500;
|
|
|
|
|
|
|
|
enic->rte_dev->data->mtu = min_t(u16, enic->max_mtu,
|
|
|
|
max_t(u16, ENIC_MIN_MTU, c->mtu));
|
2014-11-25 17:26:43 +00:00
|
|
|
|
2016-09-29 20:56:39 +00:00
|
|
|
enic->adv_filters = vnic_dev_capable_adv_filters(enic->vdev);
|
|
|
|
dev_info(enic, "Advanced Filters %savailable\n", ((enic->adv_filters)
|
|
|
|
? "" : "not "));
|
|
|
|
|
net/enic: flow API for NICs with advanced filters enabled
Flow support for 1300 series adapters with the 'Advanced Filter'
mode enabled via the UCS management interface. This enables:
Attributes: ingress
Items: Outer eth, ipv4, ipv6, udp, sctp, tcp, vxlan. Inner eth, ipv4,
ipv6, udp, tcp.
Actions: queue, and void
Selectors: 'is', 'spec' and 'mask'. 'last' is not supported
Signed-off-by: John Daley <johndale@cisco.com>
Reviewed-by: Nelson Escobar <neescoba@cisco.com>
2017-05-17 22:38:06 +00:00
|
|
|
err = vnic_dev_capable_filter_mode(enic->vdev, &enic->flow_filter_mode,
|
2018-04-04 23:54:54 +00:00
|
|
|
&enic->filter_actions);
|
net/enic: flow API for NICs with advanced filters enabled
Flow support for 1300 series adapters with the 'Advanced Filter'
mode enabled via the UCS management interface. This enables:
Attributes: ingress
Items: Outer eth, ipv4, ipv6, udp, sctp, tcp, vxlan. Inner eth, ipv4,
ipv6, udp, tcp.
Actions: queue, and void
Selectors: 'is', 'spec' and 'mask'. 'last' is not supported
Signed-off-by: John Daley <johndale@cisco.com>
Reviewed-by: Nelson Escobar <neescoba@cisco.com>
2017-05-17 22:38:06 +00:00
|
|
|
if (err) {
|
|
|
|
dev_err(enic_get_dev(enic),
|
|
|
|
"Error getting filter modes, %d\n", err);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2018-04-04 23:54:54 +00:00
|
|
|
dev_info(enic, "Flow api filter mode: %s Actions: %s%s%s\n",
|
net/enic: flow API for NICs with advanced filters enabled
Flow support for 1300 series adapters with the 'Advanced Filter'
mode enabled via the UCS management interface. This enables:
Attributes: ingress
Items: Outer eth, ipv4, ipv6, udp, sctp, tcp, vxlan. Inner eth, ipv4,
ipv6, udp, tcp.
Actions: queue, and void
Selectors: 'is', 'spec' and 'mask'. 'last' is not supported
Signed-off-by: John Daley <johndale@cisco.com>
Reviewed-by: Nelson Escobar <neescoba@cisco.com>
2017-05-17 22:38:06 +00:00
|
|
|
((enic->flow_filter_mode == FILTER_DPDK_1) ? "DPDK" :
|
|
|
|
((enic->flow_filter_mode == FILTER_USNIC_IP) ? "USNIC" :
|
|
|
|
((enic->flow_filter_mode == FILTER_IPV4_5TUPLE) ? "5TUPLE" :
|
|
|
|
"NONE"))),
|
2018-04-04 23:54:54 +00:00
|
|
|
((enic->filter_actions & FILTER_ACTION_RQ_STEERING_FLAG) ?
|
|
|
|
"steer " : ""),
|
|
|
|
((enic->filter_actions & FILTER_ACTION_FILTER_ID_FLAG) ?
|
|
|
|
"tag " : ""),
|
|
|
|
((enic->filter_actions & FILTER_ACTION_DROP_FLAG) ?
|
|
|
|
"drop " : ""));
|
net/enic: flow API for NICs with advanced filters enabled
Flow support for 1300 series adapters with the 'Advanced Filter'
mode enabled via the UCS management interface. This enables:
Attributes: ingress
Items: Outer eth, ipv4, ipv6, udp, sctp, tcp, vxlan. Inner eth, ipv4,
ipv6, udp, tcp.
Actions: queue, and void
Selectors: 'is', 'spec' and 'mask'. 'last' is not supported
Signed-off-by: John Daley <johndale@cisco.com>
Reviewed-by: Nelson Escobar <neescoba@cisco.com>
2017-05-17 22:38:06 +00:00
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
c->wq_desc_count =
|
|
|
|
min_t(u32, ENIC_MAX_WQ_DESCS,
|
|
|
|
max_t(u32, ENIC_MIN_WQ_DESCS,
|
|
|
|
c->wq_desc_count));
|
|
|
|
c->wq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */
|
|
|
|
|
|
|
|
c->rq_desc_count =
|
|
|
|
min_t(u32, ENIC_MAX_RQ_DESCS,
|
|
|
|
max_t(u32, ENIC_MIN_RQ_DESCS,
|
|
|
|
c->rq_desc_count));
|
|
|
|
c->rq_desc_count &= 0xffffffe0; /* must be aligned to groups of 32 */
|
|
|
|
|
|
|
|
c->intr_timer_usec = min_t(u32, c->intr_timer_usec,
|
|
|
|
vnic_dev_get_intr_coal_timer_max(enic->vdev));
|
|
|
|
|
|
|
|
dev_info(enic_get_dev(enic),
|
|
|
|
"vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x "
|
2016-06-24 22:29:27 +00:00
|
|
|
"wq/rq %d/%d mtu %d, max mtu:%d\n",
|
2014-11-25 17:26:43 +00:00
|
|
|
enic->mac_addr[0], enic->mac_addr[1], enic->mac_addr[2],
|
|
|
|
enic->mac_addr[3], enic->mac_addr[4], enic->mac_addr[5],
|
2016-06-24 22:29:27 +00:00
|
|
|
c->wq_desc_count, c->rq_desc_count,
|
|
|
|
enic->rte_dev->data->mtu, enic->max_mtu);
|
2014-11-25 17:26:43 +00:00
|
|
|
dev_info(enic_get_dev(enic), "vNIC csum tx/rx %s/%s "
|
|
|
|
"rss %s intr mode %s type %s timer %d usec "
|
|
|
|
"loopback tag 0x%04x\n",
|
|
|
|
ENIC_SETTING(enic, TXCSUM) ? "yes" : "no",
|
|
|
|
ENIC_SETTING(enic, RXCSUM) ? "yes" : "no",
|
|
|
|
ENIC_SETTING(enic, RSS) ? "yes" : "no",
|
|
|
|
c->intr_mode == VENET_INTR_MODE_INTX ? "INTx" :
|
|
|
|
c->intr_mode == VENET_INTR_MODE_MSI ? "MSI" :
|
|
|
|
c->intr_mode == VENET_INTR_MODE_ANY ? "any" :
|
|
|
|
"unknown",
|
|
|
|
c->intr_timer_type == VENET_INTR_TYPE_MIN ? "min" :
|
|
|
|
c->intr_timer_type == VENET_INTR_TYPE_IDLE ? "idle" :
|
|
|
|
"unknown",
|
|
|
|
c->intr_timer_usec,
|
|
|
|
c->loop_tag);
|
|
|
|
|
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
|
|
|
/* RSS settings from vNIC */
|
|
|
|
enic->reta_size = ENIC_RSS_RETA_SIZE;
|
|
|
|
enic->hash_key_size = ENIC_RSS_HASH_KEY_SIZE;
|
|
|
|
enic->flow_type_rss_offloads = 0;
|
|
|
|
if (ENIC_SETTING(enic, RSSHASH_IPV4))
|
|
|
|
enic->flow_type_rss_offloads |= ETH_RSS_IPV4;
|
|
|
|
if (ENIC_SETTING(enic, RSSHASH_TCPIPV4))
|
|
|
|
enic->flow_type_rss_offloads |= ETH_RSS_NONFRAG_IPV4_TCP;
|
|
|
|
if (ENIC_SETTING(enic, RSSHASH_IPV6))
|
|
|
|
enic->flow_type_rss_offloads |= ETH_RSS_IPV6;
|
|
|
|
if (ENIC_SETTING(enic, RSSHASH_TCPIPV6))
|
|
|
|
enic->flow_type_rss_offloads |= ETH_RSS_NONFRAG_IPV6_TCP;
|
|
|
|
if (ENIC_SETTING(enic, RSSHASH_IPV6_EX))
|
|
|
|
enic->flow_type_rss_offloads |= ETH_RSS_IPV6_EX;
|
|
|
|
if (ENIC_SETTING(enic, RSSHASH_TCPIPV6_EX))
|
|
|
|
enic->flow_type_rss_offloads |= ETH_RSS_IPV6_TCP_EX;
|
2018-04-04 23:54:52 +00:00
|
|
|
if (vnic_dev_capable_udp_rss(enic->vdev)) {
|
|
|
|
enic->flow_type_rss_offloads |=
|
|
|
|
ETH_RSS_NONFRAG_IPV4_UDP | ETH_RSS_NONFRAG_IPV6_UDP;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
/* Zero offloads if RSS is not enabled */
|
|
|
|
if (!ENIC_SETTING(enic, RSS))
|
|
|
|
enic->flow_type_rss_offloads = 0;
|
|
|
|
|
2018-04-16 21:49:10 +00:00
|
|
|
enic->vxlan = ENIC_SETTING(enic, VXLAN) &&
|
|
|
|
vnic_dev_capable_vxlan(enic->vdev);
|
|
|
|
/*
|
|
|
|
* Default hardware capabilities. enic_dev_init() may add additional
|
|
|
|
* flags if it enables overlay offloads.
|
|
|
|
*/
|
|
|
|
enic->tx_offload_capa =
|
|
|
|
DEV_TX_OFFLOAD_VLAN_INSERT |
|
|
|
|
DEV_TX_OFFLOAD_IPV4_CKSUM |
|
|
|
|
DEV_TX_OFFLOAD_UDP_CKSUM |
|
|
|
|
DEV_TX_OFFLOAD_TCP_CKSUM |
|
|
|
|
DEV_TX_OFFLOAD_TCP_TSO;
|
|
|
|
enic->rx_offload_capa =
|
|
|
|
DEV_RX_OFFLOAD_VLAN_STRIP |
|
|
|
|
DEV_RX_OFFLOAD_IPV4_CKSUM |
|
|
|
|
DEV_RX_OFFLOAD_UDP_CKSUM |
|
|
|
|
DEV_RX_OFFLOAD_TCP_CKSUM;
|
|
|
|
enic->tx_offload_mask =
|
|
|
|
PKT_TX_VLAN_PKT |
|
|
|
|
PKT_TX_IP_CKSUM |
|
|
|
|
PKT_TX_L4_MASK |
|
|
|
|
PKT_TX_TCP_SEG;
|
|
|
|
|
2014-11-25 17:26:43 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int enic_add_vlan(struct enic *enic, u16 vlanid)
|
|
|
|
{
|
|
|
|
u64 a0 = vlanid, a1 = 0;
|
|
|
|
int wait = 1000;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = vnic_dev_cmd(enic->vdev, CMD_VLAN_ADD, &a0, &a1, wait);
|
|
|
|
if (err)
|
|
|
|
dev_err(enic_get_dev(enic), "Can't add vlan id, %d\n", err);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
int enic_del_vlan(struct enic *enic, u16 vlanid)
|
|
|
|
{
|
|
|
|
u64 a0 = vlanid, a1 = 0;
|
|
|
|
int wait = 1000;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = vnic_dev_cmd(enic->vdev, CMD_VLAN_DEL, &a0, &a1, wait);
|
|
|
|
if (err)
|
|
|
|
dev_err(enic_get_dev(enic), "Can't delete vlan id, %d\n", err);
|
|
|
|
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
int enic_set_nic_cfg(struct enic *enic, u8 rss_default_cpu, u8 rss_hash_type,
|
|
|
|
u8 rss_hash_bits, u8 rss_base_cpu, u8 rss_enable, u8 tso_ipid_split_en,
|
|
|
|
u8 ig_vlan_strip_en)
|
|
|
|
{
|
|
|
|
u64 a0, a1;
|
|
|
|
u32 nic_cfg;
|
|
|
|
int wait = 1000;
|
|
|
|
|
|
|
|
vnic_set_nic_cfg(&nic_cfg, rss_default_cpu,
|
|
|
|
rss_hash_type, rss_hash_bits, rss_base_cpu,
|
|
|
|
rss_enable, tso_ipid_split_en, ig_vlan_strip_en);
|
|
|
|
|
|
|
|
a0 = nic_cfg;
|
|
|
|
a1 = 0;
|
|
|
|
|
|
|
|
return vnic_dev_cmd(enic->vdev, CMD_NIC_CFG, &a0, &a1, wait);
|
|
|
|
}
|
|
|
|
|
|
|
|
int enic_set_rss_key(struct enic *enic, dma_addr_t key_pa, u64 len)
|
|
|
|
{
|
|
|
|
u64 a0 = (u64)key_pa, a1 = len;
|
|
|
|
int wait = 1000;
|
|
|
|
|
|
|
|
return vnic_dev_cmd(enic->vdev, CMD_RSS_KEY, &a0, &a1, wait);
|
|
|
|
}
|
|
|
|
|
|
|
|
int enic_set_rss_cpu(struct enic *enic, dma_addr_t cpu_pa, u64 len)
|
|
|
|
{
|
|
|
|
u64 a0 = (u64)cpu_pa, a1 = len;
|
|
|
|
int wait = 1000;
|
|
|
|
|
|
|
|
return vnic_dev_cmd(enic->vdev, CMD_RSS_CPU, &a0, &a1, wait);
|
|
|
|
}
|
|
|
|
|
|
|
|
void enic_free_vnic_resources(struct enic *enic)
|
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
for (i = 0; i < enic->wq_count; i++)
|
|
|
|
vnic_wq_free(&enic->wq[i]);
|
2016-06-16 19:19:05 +00:00
|
|
|
for (i = 0; i < enic_vnic_rq_count(enic); i++)
|
|
|
|
if (enic->rq[i].in_use)
|
|
|
|
vnic_rq_free(&enic->rq[i]);
|
2014-11-25 17:26:43 +00:00
|
|
|
for (i = 0; i < enic->cq_count; i++)
|
|
|
|
vnic_cq_free(&enic->cq[i]);
|
2018-03-08 02:46:59 +00:00
|
|
|
for (i = 0; i < enic->intr_count; i++)
|
|
|
|
vnic_intr_free(&enic->intr[i]);
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void enic_get_res_counts(struct enic *enic)
|
|
|
|
{
|
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
|
|
|
enic->conf_wq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_WQ);
|
|
|
|
enic->conf_rq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_RQ);
|
|
|
|
enic->conf_cq_count = vnic_dev_get_res_count(enic->vdev, RES_TYPE_CQ);
|
|
|
|
enic->conf_intr_count = vnic_dev_get_res_count(enic->vdev,
|
2014-11-25 17:26:43 +00:00
|
|
|
RES_TYPE_INTR_CTRL);
|
|
|
|
|
|
|
|
dev_info(enic_get_dev(enic),
|
|
|
|
"vNIC resources avail: wq %d rq %d cq %d intr %d\n",
|
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
|
|
|
enic->conf_wq_count, enic->conf_rq_count,
|
|
|
|
enic->conf_cq_count, enic->conf_intr_count);
|
2014-11-25 17:26:43 +00:00
|
|
|
}
|