git: 9c067b844f85 - main - enic: Cisco VIC driver
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 06 Feb 2023 16:49:32 UTC
The branch main has been updated by ambrisko: URL: https://cgit.FreeBSD.org/src/commit/?id=9c067b844f85a224f0416e6eb46ba3ef82aec5c4 commit 9c067b844f85a224f0416e6eb46ba3ef82aec5c4 Author: Doug Ambrisko <ambrisko@FreeBSD.org> AuthorDate: 2023-01-27 23:46:17 +0000 Commit: Doug Ambrisko <ambrisko@FreeBSD.org> CommitDate: 2023-02-06 16:46:02 +0000 enic: Cisco VIC driver This driver is based of the enic (Cisco VIC) DPDK driver. It provides basic ethernet functionality. Has been run with various VIC cards to do UEFI PXE boot with NFS root. --- share/man/man4/Makefile | 1 + share/man/man4/enic.4 | 90 +++ sys/conf/files.amd64 | 8 + sys/dev/enic/cq_desc.h | 97 +++ sys/dev/enic/cq_enet_desc.h | 244 +++++++ sys/dev/enic/enic.h | 406 +++++++++++ sys/dev/enic/enic_compat.h | 65 ++ sys/dev/enic/enic_res.c | 212 ++++++ sys/dev/enic/enic_res.h | 73 ++ sys/dev/enic/enic_txrx.c | 485 +++++++++++++ sys/dev/enic/if_enic.c | 1583 ++++++++++++++++++++++++++++++++++++++++++ sys/dev/enic/rq_enet_desc.h | 46 ++ sys/dev/enic/vnic_cq.c | 45 ++ sys/dev/enic/vnic_cq.h | 164 +++++ sys/dev/enic/vnic_dev.c | 1039 +++++++++++++++++++++++++++ sys/dev/enic/vnic_dev.h | 170 +++++ sys/dev/enic/vnic_devcmd.h | 1182 +++++++++++++++++++++++++++++++ sys/dev/enic/vnic_enet.h | 66 ++ sys/dev/enic/vnic_intr.c | 49 ++ sys/dev/enic/vnic_intr.h | 100 +++ sys/dev/enic/vnic_nic.h | 60 ++ sys/dev/enic/vnic_resource.h | 67 ++ sys/dev/enic/vnic_rq.c | 97 +++ sys/dev/enic/vnic_rq.h | 142 ++++ sys/dev/enic/vnic_rss.h | 32 + sys/dev/enic/vnic_stats.h | 56 ++ sys/dev/enic/vnic_wq.c | 89 +++ sys/dev/enic/vnic_wq.h | 108 +++ sys/dev/enic/wq_enet_desc.h | 84 +++ sys/modules/Makefile | 2 + sys/modules/enic/Makefile | 19 + 31 files changed, 6881 insertions(+) diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile index 1c7703bdaeb2..897c72d43baf 100644 --- a/share/man/man4/Makefile +++ b/share/man/man4/Makefile @@ -143,6 +143,7 @@ MAN= aac.4 \ em.4 \ ena.4 \ enc.4 \ + enic.4 \ epair.4 \ est.4 \ et.4 \ diff --git a/share/man/man4/enic.4 b/share/man/man4/enic.4 new file mode 100644 index 000000000000..d33df8515f3e --- /dev/null +++ b/share/man/man4/enic.4 @@ -0,0 +1,90 @@ +.\" Copyright 2008-2017 Cisco Systems, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd Sept 7, 2022 +.Dt ENIC 4 +.Os +.Sh NAME +.Nm enic +.Nd "VIC Ethernet NIC driver" +.Sh SYNOPSIS +To compile this driver into the kernel, +place the following lines in your +kernel configuration file: +.Bd -ragged -offset indent +.Cd "device iflib" +.Cd "device enic" +.Ed +.Pp +To load the driver as a module at run-time, +run the following command as root: +.Bd -literal -offset indent +kldload if_enic +.Ed +.Pp +To load the driver as a +module at boot time, place the following lines in +.Xr loader.conf 5 : +.Bd -literal -offset indent +if_enic_load="YES" +.Ed +.Sh DESCRIPTION +The +.Nm +driver provides support for Cisco Virtual Interface Card. Support +is limited to basic network connectivity. Media is controlled by the +NIC itself since there can be multiple virtual PCI NIC devices exposed +to the PCI bus. +.Sh HARDWARE +The +.Nm +driver should supports all known Cisco VIC cards. +.Sh CONFIGURATION +The +.Nm +network interface is configured using +.Xr ifconfig 8 +and the +.Xr sysctl 8 +tree at +.Dv dev.enic.<N> . +All configurable entries are also tunables, and can be put directly into the +.Xr loader.conf 5 +for persistent configuration. +.Sh SEE ALSO +.Xr ifconfig 8 +.Sh HISTORY +The +.Nm +device driver first appeared in +.Fx 14.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Cisco UCS team +based of the DPDK driver. diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index f0fba5a88869..75be68543394 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -119,6 +119,14 @@ dev/axgbe/xgbe-txrx.c optional axp dev/axgbe/xgbe_osdep.c optional axp dev/axgbe/xgbe-i2c.c optional axp dev/axgbe/xgbe-phy-v2.c optional axp +dev/enic/enic_res.c optional enic +dev/enic/enic_txrx.c optional enic +dev/enic/if_enic.c optional enic +dev/enic/vnic_cq.c optional enic +dev/enic/vnic_dev.c optional enic +dev/enic/vnic_intr.c optional enic +dev/enic/vnic_rq.c optional enic +dev/enic/vnic_wq.c optional enic dev/hyperv/vmbus/amd64/hyperv_machdep.c optional hyperv dev/hyperv/vmbus/amd64/vmbus_vector.S optional hyperv dev/iavf/if_iavf_iflib.c optional iavf pci \ diff --git a/sys/dev/enic/cq_desc.h b/sys/dev/enic/cq_desc.h new file mode 100644 index 000000000000..ae8847c6d9a1 --- /dev/null +++ b/sys/dev/enic/cq_desc.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + */ + +#ifndef _CQ_DESC_H_ +#define _CQ_DESC_H_ + +/* + * Completion queue descriptor types + */ +enum cq_desc_types { + CQ_DESC_TYPE_WQ_ENET = 0, + CQ_DESC_TYPE_DESC_COPY = 1, + CQ_DESC_TYPE_WQ_EXCH = 2, + CQ_DESC_TYPE_RQ_ENET = 3, + CQ_DESC_TYPE_RQ_FCP = 4, + CQ_DESC_TYPE_IOMMU_MISS = 5, + CQ_DESC_TYPE_SGL = 6, + CQ_DESC_TYPE_CLASSIFIER = 7, + CQ_DESC_TYPE_TEST = 127, +}; + +/* Completion queue descriptor: 16B + * + * All completion queues have this basic layout. The + * type_specfic area is unique for each completion + * queue type. + */ +struct cq_desc { + __le16 completed_index; + __le16 q_number; + u8 type_specfic[11]; + u8 type_color; +}; + +#define CQ_DESC_TYPE_BITS 4 +#define CQ_DESC_TYPE_MASK ((1 << CQ_DESC_TYPE_BITS) - 1) +#define CQ_DESC_COLOR_MASK 1 +#define CQ_DESC_COLOR_SHIFT 7 +#define CQ_DESC_COLOR_MASK_NOSHIFT 0x80 +#define CQ_DESC_Q_NUM_BITS 10 +#define CQ_DESC_Q_NUM_MASK ((1 << CQ_DESC_Q_NUM_BITS) - 1) +#define CQ_DESC_COMP_NDX_BITS 12 +#define CQ_DESC_COMP_NDX_MASK ((1 << CQ_DESC_COMP_NDX_BITS) - 1) + +static inline void cq_color_enc(struct cq_desc *desc, const u8 color) +{ + if (color) + desc->type_color |= (1 << CQ_DESC_COLOR_SHIFT); + else + desc->type_color &= ~(1 << CQ_DESC_COLOR_SHIFT); +} + +static inline void cq_desc_enc(struct cq_desc *desc, + const u8 type, const u8 color, const u16 q_number, + const u16 completed_index) +{ + desc->type_color = (type & CQ_DESC_TYPE_MASK) | + ((color & CQ_DESC_COLOR_MASK) << CQ_DESC_COLOR_SHIFT); + desc->q_number = cpu_to_le16(q_number & CQ_DESC_Q_NUM_MASK); + desc->completed_index = cpu_to_le16(completed_index & + CQ_DESC_COMP_NDX_MASK); +} + +static inline void cq_desc_dec(const struct cq_desc *desc_arg, + u8 *type, u8 *color, u16 *q_number, u16 *completed_index) +{ + const struct cq_desc *desc = desc_arg; + const u8 type_color = desc->type_color; + + *color = (type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK; + + /* + * Make sure color bit is read from desc *before* other fields + * are read from desc. Hardware guarantees color bit is last + * bit (byte) written. Adding the rmb() prevents the compiler + * and/or CPU from reordering the reads which would potentially + * result in reading stale values. + */ + + rmb(); + + *type = type_color & CQ_DESC_TYPE_MASK; + *q_number = le16_to_cpu(desc->q_number) & CQ_DESC_Q_NUM_MASK; + *completed_index = le16_to_cpu(desc->completed_index) & + CQ_DESC_COMP_NDX_MASK; +} + +static inline void cq_color_dec(const struct cq_desc *desc_arg, u8 *color) +{ + volatile const struct cq_desc *desc = desc_arg; + + *color = (desc->type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK; +} + +#endif /* _CQ_DESC_H_ */ diff --git a/sys/dev/enic/cq_enet_desc.h b/sys/dev/enic/cq_enet_desc.h new file mode 100644 index 000000000000..5ced63cb1613 --- /dev/null +++ b/sys/dev/enic/cq_enet_desc.h @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + */ + +#ifndef _CQ_ENET_DESC_H_ +#define _CQ_ENET_DESC_H_ + +#include "cq_desc.h" + +/* Ethernet completion queue descriptor: 16B */ +struct cq_enet_wq_desc { + __le16 completed_index; + __le16 q_number; + u8 reserved[11]; + u8 type_color; +}; + +static inline void cq_enet_wq_desc_enc(struct cq_enet_wq_desc *desc, + u8 type, u8 color, u16 q_number, u16 completed_index) +{ + cq_desc_enc((struct cq_desc *)desc, type, + color, q_number, completed_index); +} + +static inline void cq_enet_wq_desc_dec(struct cq_enet_wq_desc *desc, + u8 *type, u8 *color, u16 *q_number, u16 *completed_index) +{ + cq_desc_dec((struct cq_desc *)desc, type, + color, q_number, completed_index); +} + +/* Completion queue descriptor: Ethernet receive queue, 16B */ +struct cq_enet_rq_desc { + __le16 completed_index_flags; + __le16 q_number_rss_type_flags; + __le32 rss_hash; + __le16 bytes_written_flags; + __le16 vlan; + __le16 checksum_fcoe; + u8 flags; + u8 type_color; +}; + +/* Completion queue descriptor: Ethernet receive queue, 16B */ +struct cq_enet_rq_clsf_desc { + __le16 completed_index_flags; + __le16 q_number_rss_type_flags; + __le16 filter_id; + __le16 lif; + __le16 bytes_written_flags; + __le16 vlan; + __le16 checksum_fcoe; + u8 flags; + u8 type_color; +}; + +#define CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT (0x1 << 12) +#define CQ_ENET_RQ_DESC_FLAGS_FCOE (0x1 << 13) +#define CQ_ENET_RQ_DESC_FLAGS_EOP (0x1 << 14) +#define CQ_ENET_RQ_DESC_FLAGS_SOP (0x1 << 15) + +#define CQ_ENET_RQ_DESC_RSS_TYPE_BITS 4 +#define CQ_ENET_RQ_DESC_RSS_TYPE_MASK \ + ((1 << CQ_ENET_RQ_DESC_RSS_TYPE_BITS) - 1) +#define CQ_ENET_RQ_DESC_RSS_TYPE_NONE 0 +#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv4 1 +#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv4 2 +#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv6 3 +#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6 4 +#define CQ_ENET_RQ_DESC_RSS_TYPE_IPv6_EX 5 +#define CQ_ENET_RQ_DESC_RSS_TYPE_TCP_IPv6_EX 6 + +#define CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC (0x1 << 14) + +#define CQ_ENET_RQ_DESC_BYTES_WRITTEN_BITS 14 +#define CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK \ + ((1 << CQ_ENET_RQ_DESC_BYTES_WRITTEN_BITS) - 1) +#define CQ_ENET_RQ_DESC_FLAGS_TRUNCATED (0x1 << 14) +#define CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED (0x1 << 15) + +#define CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_BITS 12 +#define CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_MASK \ + ((1 << CQ_ENET_RQ_DESC_VLAN_TCI_VLAN_BITS) - 1) +#define CQ_ENET_RQ_DESC_VLAN_TCI_CFI_MASK (0x1 << 12) +#define CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_BITS 3 +#define CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_MASK \ + ((1 << CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_BITS) - 1) +#define CQ_ENET_RQ_DESC_VLAN_TCI_USER_PRIO_SHIFT 13 + +#define CQ_ENET_RQ_DESC_FCOE_SOF_BITS 8 +#define CQ_ENET_RQ_DESC_FCOE_SOF_MASK \ + ((1 << CQ_ENET_RQ_DESC_FCOE_SOF_BITS) - 1) +#define CQ_ENET_RQ_DESC_FCOE_EOF_BITS 8 +#define CQ_ENET_RQ_DESC_FCOE_EOF_MASK \ + ((1 << CQ_ENET_RQ_DESC_FCOE_EOF_BITS) - 1) +#define CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT 8 + +#define CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK (0x1 << 0) +#define CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK (0x1 << 0) +#define CQ_ENET_RQ_DESC_FLAGS_UDP (0x1 << 1) +#define CQ_ENET_RQ_DESC_FCOE_ENC_ERROR (0x1 << 1) +#define CQ_ENET_RQ_DESC_FLAGS_TCP (0x1 << 2) +#define CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK (0x1 << 3) +#define CQ_ENET_RQ_DESC_FLAGS_IPV6 (0x1 << 4) +#define CQ_ENET_RQ_DESC_FLAGS_IPV4 (0x1 << 5) +#define CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT (0x1 << 6) +#define CQ_ENET_RQ_DESC_FLAGS_FCS_OK (0x1 << 7) + +static inline void cq_enet_rq_desc_enc(struct cq_enet_rq_desc *desc, + u8 type, u8 color, u16 q_number, u16 completed_index, + u8 ingress_port, u8 fcoe, u8 eop, u8 sop, u8 rss_type, u8 csum_not_calc, + u32 rss_hash, u16 bytes_written, u8 packet_error, u8 vlan_stripped, + u16 vlan, u16 checksum, u8 fcoe_sof, u8 fcoe_fc_crc_ok, + u8 fcoe_enc_error, u8 fcoe_eof, u8 tcp_udp_csum_ok, u8 udp, u8 tcp, + u8 ipv4_csum_ok, u8 ipv6, u8 ipv4, u8 ipv4_fragment, u8 fcs_ok) +{ + cq_desc_enc((struct cq_desc *)desc, type, + color, q_number, completed_index); + + desc->completed_index_flags |= cpu_to_le16( + (ingress_port ? CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT : 0) | + (fcoe ? CQ_ENET_RQ_DESC_FLAGS_FCOE : 0) | + (eop ? CQ_ENET_RQ_DESC_FLAGS_EOP : 0) | + (sop ? CQ_ENET_RQ_DESC_FLAGS_SOP : 0)); + + desc->q_number_rss_type_flags |= cpu_to_le16( + ((rss_type & CQ_ENET_RQ_DESC_RSS_TYPE_MASK) << + CQ_DESC_Q_NUM_BITS) | + (csum_not_calc ? CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC : 0)); + + desc->rss_hash = cpu_to_le32(rss_hash); + + desc->bytes_written_flags = cpu_to_le16( + (bytes_written & CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK) | + (packet_error ? CQ_ENET_RQ_DESC_FLAGS_TRUNCATED : 0) | + (vlan_stripped ? CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED : 0)); + + desc->vlan = cpu_to_le16(vlan); + + if (fcoe) { + desc->checksum_fcoe = cpu_to_le16( + (fcoe_sof & CQ_ENET_RQ_DESC_FCOE_SOF_MASK) | + ((fcoe_eof & CQ_ENET_RQ_DESC_FCOE_EOF_MASK) << + CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT)); + } else { + desc->checksum_fcoe = cpu_to_le16(checksum); + } + + desc->flags = + (tcp_udp_csum_ok ? CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK : 0) | + (udp ? CQ_ENET_RQ_DESC_FLAGS_UDP : 0) | + (tcp ? CQ_ENET_RQ_DESC_FLAGS_TCP : 0) | + (ipv4_csum_ok ? CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK : 0) | + (ipv6 ? CQ_ENET_RQ_DESC_FLAGS_IPV6 : 0) | + (ipv4 ? CQ_ENET_RQ_DESC_FLAGS_IPV4 : 0) | + (ipv4_fragment ? CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT : 0) | + (fcs_ok ? CQ_ENET_RQ_DESC_FLAGS_FCS_OK : 0) | + (fcoe_fc_crc_ok ? CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK : 0) | + (fcoe_enc_error ? CQ_ENET_RQ_DESC_FCOE_ENC_ERROR : 0); +} + +static inline void cq_enet_rq_desc_dec(struct cq_enet_rq_desc *desc, + u8 *type, u8 *color, u16 *q_number, u16 *completed_index, + u8 *ingress_port, u8 *fcoe, u8 *eop, u8 *sop, u8 *rss_type, + u8 *csum_not_calc, u32 *rss_hash, u16 *bytes_written, u8 *packet_error, + u8 *vlan_stripped, u16 *vlan_tci, u16 *checksum, u8 *fcoe_sof, + u8 *fcoe_fc_crc_ok, u8 *fcoe_enc_error, u8 *fcoe_eof, + u8 *tcp_udp_csum_ok, u8 *udp, u8 *tcp, u8 *ipv4_csum_ok, + u8 *ipv6, u8 *ipv4, u8 *ipv4_fragment, u8 *fcs_ok) +{ + u16 completed_index_flags; + u16 q_number_rss_type_flags; + u16 bytes_written_flags; + + cq_desc_dec((struct cq_desc *)desc, type, + color, q_number, completed_index); + + completed_index_flags = le16_to_cpu(desc->completed_index_flags); + q_number_rss_type_flags = + le16_to_cpu(desc->q_number_rss_type_flags); + bytes_written_flags = le16_to_cpu(desc->bytes_written_flags); + + *ingress_port = (completed_index_flags & + CQ_ENET_RQ_DESC_FLAGS_INGRESS_PORT) ? 1 : 0; + *fcoe = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_FCOE) ? + 1 : 0; + *eop = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_EOP) ? + 1 : 0; + *sop = (completed_index_flags & CQ_ENET_RQ_DESC_FLAGS_SOP) ? + 1 : 0; + + *rss_type = (u8)((q_number_rss_type_flags >> CQ_DESC_Q_NUM_BITS) & + CQ_ENET_RQ_DESC_RSS_TYPE_MASK); + *csum_not_calc = (q_number_rss_type_flags & + CQ_ENET_RQ_DESC_FLAGS_CSUM_NOT_CALC) ? 1 : 0; + + *rss_hash = le32_to_cpu(desc->rss_hash); + + *bytes_written = bytes_written_flags & + CQ_ENET_RQ_DESC_BYTES_WRITTEN_MASK; + *packet_error = (bytes_written_flags & + CQ_ENET_RQ_DESC_FLAGS_TRUNCATED) ? 1 : 0; + *vlan_stripped = (bytes_written_flags & + CQ_ENET_RQ_DESC_FLAGS_VLAN_STRIPPED) ? 1 : 0; + + /* + * Tag Control Information(16) = user_priority(3) + cfi(1) + vlan(12) + */ + *vlan_tci = le16_to_cpu(desc->vlan); + + if (*fcoe) { + *fcoe_sof = (u8)(le16_to_cpu(desc->checksum_fcoe) & + CQ_ENET_RQ_DESC_FCOE_SOF_MASK); + *fcoe_fc_crc_ok = (desc->flags & + CQ_ENET_RQ_DESC_FCOE_FC_CRC_OK) ? 1 : 0; + *fcoe_enc_error = (desc->flags & + CQ_ENET_RQ_DESC_FCOE_ENC_ERROR) ? 1 : 0; + *fcoe_eof = (u8)((le16_to_cpu(desc->checksum_fcoe) >> + CQ_ENET_RQ_DESC_FCOE_EOF_SHIFT) & + CQ_ENET_RQ_DESC_FCOE_EOF_MASK); + *checksum = 0; + } else { + *fcoe_sof = 0; + *fcoe_fc_crc_ok = 0; + *fcoe_enc_error = 0; + *fcoe_eof = 0; + *checksum = le16_to_cpu(desc->checksum_fcoe); + } + + *tcp_udp_csum_ok = + (desc->flags & CQ_ENET_RQ_DESC_FLAGS_TCP_UDP_CSUM_OK) ? 1 : 0; + *udp = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_UDP) ? 1 : 0; + *tcp = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_TCP) ? 1 : 0; + *ipv4_csum_ok = + (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_CSUM_OK) ? 1 : 0; + *ipv6 = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV6) ? 1 : 0; + *ipv4 = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4) ? 1 : 0; + *ipv4_fragment = + (desc->flags & CQ_ENET_RQ_DESC_FLAGS_IPV4_FRAGMENT) ? 1 : 0; + *fcs_ok = (desc->flags & CQ_ENET_RQ_DESC_FLAGS_FCS_OK) ? 1 : 0; +} + +#endif /* _CQ_ENET_DESC_H_ */ diff --git a/sys/dev/enic/enic.h b/sys/dev/enic/enic.h new file mode 100644 index 000000000000..9d84ca6ecaf6 --- /dev/null +++ b/sys/dev/enic/enic.h @@ -0,0 +1,406 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD: $"); + +#ifndef _ENIC_H +#define _ENIC_H + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/sysctl.h> +#include <sys/taskqueue.h> + +#include <machine/bus.h> + +#include <net/ethernet.h> +#include <net/if.h> +#include <net/if_var.h> +#include <net/iflib.h> + +#define u8 uint8_t +#define u16 uint16_t +#define u32 uint32_t +#define u64 uint64_t + +struct enic_bar_info { + struct resource *res; + bus_space_tag_t tag; + bus_space_handle_t handle; + bus_size_t size; + int rid; + int offset; +}; + +#define ENIC_BUS_WRITE_8(res, index, value) \ + bus_space_write_8(res->bar.tag, res->bar.handle, \ + res->bar.offset + (index), value) +#define ENIC_BUS_WRITE_4(res, index, value) \ + bus_space_write_4(res->bar.tag, res->bar.handle, \ + res->bar.offset + (index), value) +#define ENIC_BUS_WRITE_REGION_4(res, index, values, count) \ + bus_space_write_region_4(res->bar.tag, res->bar.handle, \ + res->bar.offset + (index), values, count); + +#define ENIC_BUS_READ_8(res, index) \ + bus_space_read_8(res->bar.tag, res->bar.handle, \ + res->bar.offset + (index)) +#define ENIC_BUS_READ_4(res, index) \ + bus_space_read_4(res->bar.tag, res->bar.handle, \ + res->bar.offset + (index)) +#define ENIC_BUS_READ_REGION_4(res, type, index, values, count) \ + bus_space_read_region_4(res->type.tag, res->type.handle, \ + res->type.offset + (index), values, count); + +struct vnic_res { + unsigned int count; + struct enic_bar_info bar; +}; + +#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 "cq_enet_desc.h" + +#define ENIC_LOCK(_softc) mtx_lock(&(_softc)->enic_lock) +#define ENIC_UNLOCK(_softc) mtx_unlock(&(_softc)->enic_lock) + +#define DRV_NAME "enic" +#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC" +#define DRV_COPYRIGHT "Copyright 2008-2015 Cisco Systems, Inc" + +#define ENIC_MAX_MAC_ADDR 64 + +#define VLAN_ETH_HLEN 18 + +#define ENICPMD_SETTING(enic, f) ((enic->config.flags & VENETF_##f) ? 1 : 0) + +#define ENICPMD_BDF_LENGTH 13 /* 0000:00:00.0'\0' */ +#define ENIC_CALC_IP_CKSUM 1 +#define ENIC_CALC_TCP_UDP_CKSUM 2 +#define ENIC_MAX_MTU 9000 +#define ENIC_PAGE_SIZE 4096 +#define PAGE_ROUND_UP(x) \ + ((((unsigned long)(x)) + ENIC_PAGE_SIZE-1) & (~(ENIC_PAGE_SIZE-1))) + +/* must be >= VNIC_COUNTER_DMA_MIN_PERIOD */ +#define VNIC_FLOW_COUNTER_UPDATE_MSECS 500 + +/* PCI IDs */ +#define CISCO_VENDOR_ID 0x1137 + +#define PCI_DEVICE_ID_CISCO_VIC_ENET 0x0043 /* ethernet vnic */ +#define PCI_DEVICE_ID_CISCO_VIC_ENET_VF 0x0071 /* enet SRIOV VF */ + +/* Special Filter id for non-specific packet flagging. Don't change value */ +#define ENIC_MAGIC_FILTER_ID 0xffff + +#define ENICPMD_FDIR_MAX 64 + +/* HW default VXLAN port */ +#define ENIC_DEFAULT_VXLAN_PORT 4789 + +/* + * Interrupt 0: LSC and errors + * Interrupt 1: rx queue 0 + * Interrupt 2: rx queue 1 + * ... + */ +#define ENICPMD_LSC_INTR_OFFSET 0 +#define ENICPMD_RXQ_INTR_OFFSET 1 + +#include "vnic_devcmd.h" + +enum vnic_proxy_type { + PROXY_NONE, + PROXY_BY_BDF, + PROXY_BY_INDEX, +}; + +struct vnic_intr_coal_timer_info { + u32 mul; + u32 div; + u32 max_usec; +}; + +struct enic_softc; +struct vnic_dev { + void *priv; + struct rte_pci_device *pdev; + struct vnic_res res[RES_TYPE_MAX]; + enum vnic_dev_intr_mode intr_mode; + struct vnic_res __iomem *devcmd; + struct vnic_devcmd_notify *notify; + struct vnic_devcmd_notify notify_copy; + bus_addr_t notify_pa; + struct iflib_dma_info notify_res; + u32 notify_sz; + struct iflib_dma_info linkstatus_res; + struct vnic_stats *stats; + struct iflib_dma_info stats_res; + struct vnic_devcmd_fw_info *fw_info; + struct iflib_dma_info fw_info_res; + enum vnic_proxy_type proxy; + u32 proxy_index; + u64 args[VNIC_DEVCMD_NARGS]; + int in_reset; + struct vnic_intr_coal_timer_info intr_coal_timer_info; + void *(*alloc_consistent)(void *priv, size_t size, + bus_addr_t *dma_handle, struct iflib_dma_info *res, u8 *name); + void (*free_consistent)(void *priv, size_t size, void *vaddr, + bus_addr_t dma_handle, struct iflib_dma_info *res); + struct vnic_counter_counts *flow_counters; + struct iflib_dma_info flow_counters_res; + u8 flow_counters_dma_active; + struct enic_softc *softc; +}; + +struct enic_soft_stats { + uint64_t rx_nombuf; + uint64_t rx_packet_errors; + uint64_t tx_oversized; +}; + +struct intr_queue { + struct if_irq intr_irq; + struct resource *res; + int rid; + struct enic_softc *softc; +}; + +struct enic { + struct enic *next; + struct rte_pci_device *pdev; + struct vnic_enet_config config; + struct vnic_dev_bar bar0; + struct vnic_dev *vdev; + + /* + * mbuf_initializer contains 64 bits of mbuf rearm_data, used by + * the avx2 handler at this time. + */ + uint64_t mbuf_initializer; + unsigned int port_id; + bool overlay_offload; + char bdf_name[ENICPMD_BDF_LENGTH]; + int dev_fd; + int iommu_group_fd; + int iommu_groupid; + int eventfd; + uint8_t mac_addr[ETH_ALEN]; + pthread_t err_intr_thread; + u8 ig_vlan_strip_en; + int link_status; + u8 hw_ip_checksum; + u16 max_mtu; + u8 adv_filters; + u32 flow_filter_mode; + u8 filter_actions; /* HW supported actions */ + bool vxlan; + bool disable_overlay; /* devargs disable_overlay=1 */ + uint8_t enable_avx2_rx; /* devargs enable-avx2-rx=1 */ + bool nic_cfg_chk; /* NIC_CFG_CHK available */ + bool udp_rss_weak; /* Bodega style UDP RSS */ + uint8_t ig_vlan_rewrite_mode; /* devargs ig-vlan-rewrite */ + uint16_t vxlan_port; /* current vxlan port pushed to NIC */ + + unsigned int flags; + unsigned int priv_flags; + + /* work queue (len = conf_wq_count) */ + struct vnic_wq *wq; + unsigned int wq_count; /* equals eth_dev nb_tx_queues */ + + /* receive queue (len = conf_rq_count) */ + struct vnic_rq *rq; + unsigned int rq_count; /* equals eth_dev nb_rx_queues */ + + /* completion queue (len = conf_cq_count) */ + struct vnic_cq *cq; + unsigned int cq_count; /* equals rq_count + wq_count */ + + /* interrupt vectors (len = conf_intr_count) */ + struct vnic_intr *intr; + struct intr_queue *intr_queues;; + unsigned int intr_count; /* equals enabled interrupts (lsc + rxqs) */ + + + /* software counters */ + struct enic_soft_stats soft_stats; + + /* configured resources on vic */ + unsigned int conf_rq_count; + unsigned int conf_wq_count; + unsigned int conf_cq_count; + unsigned int conf_intr_count; + + /* linked list storing memory allocations */ + LIST_HEAD(enic_memzone_list, enic_memzone_entry) memzone_list; + + LIST_HEAD(enic_flows, rte_flow) flows; + int max_flow_counter; + + /* RSS */ + uint16_t reta_size; + uint8_t hash_key_size; + uint64_t flow_type_rss_offloads; /* 0 indicates RSS not supported */ + /* + * Keep a copy of current RSS config for queries, as we cannot retrieve + * it from the NIC. + */ + uint8_t rss_hash_type; /* NIC_CFG_RSS_HASH_TYPE flags */ + uint8_t rss_enable; + uint64_t rss_hf; /* ETH_RSS flags */ + union vnic_rss_key rss_key; + union vnic_rss_cpu rss_cpu; + + uint64_t rx_offload_capa; /* DEV_RX_OFFLOAD flags */ + uint64_t tx_offload_capa; /* DEV_TX_OFFLOAD flags */ + uint64_t tx_queue_offload_capa; /* DEV_TX_OFFLOAD flags */ + uint64_t tx_offload_mask; /* PKT_TX flags accepted */ + struct enic_softc *softc; + int port_mtu; +}; + +struct enic_softc { + device_t dev; + if_ctx_t ctx; + if_softc_ctx_t scctx; + if_shared_ctx_t sctx; + struct ifmedia *media; + struct ifnet *ifp; + + struct mtx enic_lock; + + struct enic_bar_info mem; + struct enic_bar_info io; + + struct vnic_dev vdev; + struct enic enic; + + int ntxqsets; + int nrxqsets; + + struct if_irq enic_event_intr_irq; + struct if_irq enic_err_intr_irq; + uint8_t lladdr[ETHER_ADDR_LEN]; + int link_active; + int stopped; + uint8_t mac_addr[ETHER_ADDR_LEN]; + + int directed; + int multicast; + int broadcast; + int promisc; + int allmulti; + + u_int mc_count; + uint8_t *mta; +}; + +/* Per-instance private data structure */ + +static inline unsigned int enic_vnic_rq_count(struct enic *enic) +{ + return enic->rq_count; +} + +static inline unsigned int enic_cq_rq(struct enic *enic, unsigned int rq) +{ + return rq; +} + +static inline unsigned int enic_cq_wq(struct enic *enic, unsigned int wq) +{ + return enic->rq_count + wq; +} + +static inline uint32_t +enic_ring_add(uint32_t n_descriptors, uint32_t i0, uint32_t i1) +{ + uint32_t d = i0 + i1; + d -= (d >= n_descriptors) ? n_descriptors : 0; + return d; +} + +static inline uint32_t +enic_ring_sub(uint32_t n_descriptors, uint32_t i0, uint32_t i1) +{ + int32_t d = i1 - i0; + return (uint32_t)((d < 0) ? ((int32_t)n_descriptors + d) : d); +} + +static inline uint32_t +enic_ring_incr(uint32_t n_descriptors, uint32_t idx) +{ + idx++; + if (unlikely(idx == n_descriptors)) + idx = 0; + return idx; +} + +void enic_free_wq(void *txq); +int enic_alloc_intr_resources(struct enic *enic); +int enic_setup_finish(struct enic *enic); +int enic_alloc_wq(struct enic *enic, uint16_t queue_idx, + unsigned int socket_id, uint16_t nb_desc); +void enic_start_wq(struct enic *enic, uint16_t queue_idx); +int enic_stop_wq(struct enic *enic, uint16_t queue_idx); +void enic_start_rq(struct enic *enic, uint16_t queue_idx); +void enic_free_rq(void *rxq); +int enic_set_vnic_res(struct enic *enic); +int enic_init_rss_nic_cfg(struct enic *enic); +int enic_set_rss_reta(struct enic *enic, union vnic_rss_cpu *rss_cpu); +int enic_set_vlan_strip(struct enic *enic); +int enic_enable(struct enic *enic); +int enic_disable(struct enic *enic); +void enic_remove(struct enic *enic); +int enic_get_link_status(struct enic *enic); +void enic_dev_stats_clear(struct enic *enic); +void enic_add_packet_filter(struct enic *enic); +int enic_set_mac_address(struct enic *enic, uint8_t *mac_addr); +int enic_del_mac_address(struct enic *enic, int mac_index); +unsigned int enic_cleanup_wq(struct enic *enic, struct vnic_wq *wq); + +void enic_post_wq_index(struct vnic_wq *wq); +int enic_probe(struct enic *enic); +int enic_clsf_init(struct enic *enic); +void enic_clsf_destroy(struct enic *enic); +int enic_set_mtu(struct enic *enic, uint16_t new_mtu); +int enic_link_update(struct enic *enic); +bool enic_use_vector_rx_handler(struct enic *enic); +void enic_fdir_info(struct enic *enic); +void enic_prep_wq_for_simple_tx(struct enic *, uint16_t); + +struct enic_ring { + uint64_t paddr; + caddr_t vaddr; + struct enic_softc *softc; + uint32_t ring_size; /* Must be a power of two */ + uint16_t id; /* Logical ID */ + uint16_t phys_id; +}; + +struct enic_cp_ring { + struct enic_ring ring; + struct if_irq irq; + uint32_t cons; + bool v_bit; /* Value of valid bit */ + struct ctx_hw_stats *stats; + uint32_t stats_ctx_id; + uint32_t last_idx; /* Used by RX rings only + * set to the last read pidx + */ +}; + +#endif /* _ENIC_H_ */ diff --git a/sys/dev/enic/enic_compat.h b/sys/dev/enic/enic_compat.h new file mode 100644 index 000000000000..d5a10f94febb --- /dev/null +++ b/sys/dev/enic/enic_compat.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright 2008-2017 Cisco Systems, Inc. All rights reserved. + * Copyright 2007 Nuova Systems, Inc. All rights reserved. + */ + +#ifndef _ENIC_COMPAT_H_ +#define _ENIC_COMPAT_H_ + +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/kernel.h> +#include <sys/bus.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/endian.h> +#include <sys/sockio.h> +#include <sys/priv.h> + +#include <machine/bus.h> +#include <machine/resource.h> + +#define ETH_ALEN ETHER_ADDR_LEN + +#define typeof __typeof__ +#define __iomem +#define unlikely(x) __builtin_expect((x),0) + +#define le16_to_cpu +#define le32_to_cpu +#define le64_to_cpu +#define cpu_to_le16 +#define cpu_to_le32 +#define cpu_to_le64 + +#define pr_err(y, args...) dev_err(0, y, ##args) +#define pr_warn(y, args...) dev_warning(0, y, ##args) +#define BUG() pr_err("BUG at %s:%d", __func__, __LINE__) + +#define VNIC_ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a)-1) +#define __ALIGN_MASK(x, mask) (((x)+(mask))&~(mask)) *** 6151 LINES SKIPPED ***