summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2017-09-09 16:34:02 +0000
committerRobert Mustacchi <rm@joyent.com>2017-09-15 02:22:14 +0000
commitd60c4b68b4189b047c8b3c8bf84337505e0ccfc5 (patch)
treec2d6ce01cabba18ed28ca9cb6b6d2519ddb945a0
parent766f80363ee325875bdcd79484e9c04427d17aec (diff)
downloadillumos-joyent-d60c4b68b4189b047c8b3c8bf84337505e0ccfc5.tar.gz
OS-5858 Want support for X722
Reviewed by: Dan McDonald <danmcd@joyent.com> Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com> Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r--usr/src/man/man7d/i40e.7d18
-rw-r--r--usr/src/pkg/manifests/driver-network-i40e.mf14
-rw-r--r--usr/src/uts/common/io/i40e/i40e_main.c184
-rw-r--r--usr/src/uts/common/io/i40e/i40e_sw.h20
4 files changed, 178 insertions, 58 deletions
diff --git a/usr/src/man/man7d/i40e.7d b/usr/src/man/man7d/i40e.7d
index 992297fe7d..2d8a2da45b 100644
--- a/usr/src/man/man7d/i40e.7d
+++ b/usr/src/man/man7d/i40e.7d
@@ -9,16 +9,16 @@
.\" http://www.illumos.org/license/CDDL.
.\"
.\"
-.\" Copyright 2016 Joyent, Inc.
+.\" Copyright (c) 2017 Joyent, Inc.
.\"
-.Dd December 16, 2016
+.Dd September 8, 2017
.Dt I40E 7D
.Os
.Sh NAME
.Nm i40e
-.Nd Intel 710 Ethernet Device Driver
+.Nd Intel 710/722 Ethernet Device Driver
.Sh SYNOPSIS
-.Pa /dev/i40e*
+.Pa /dev/net/i40e*
.Sh DESCRIPTION
The
.Nm
@@ -27,9 +27,9 @@ supports the Data Link Provider Interface,
.Xr dlpi 7P .
The
.Nm
-driver supports the Intel XL710 Ethernet Controller family of networking
-interface cards which come in 1 GbE, 10 GbE, 25 GbE, and 40 GbE
-variants.
+driver supports the Intel 710 and 722 Ethernet Controller families of
+networking interface cards which come in 1 GbE, 10 GbE, 25 GbE, and 40
+GbE variants.
.Pp
In addition to basic device initialization and the sending and receiving
of frames, it supports the following features:
@@ -71,7 +71,7 @@ For example, the first instance enumerated in the system, with id 0, would be
named
.Sy i40e0 .
It exists in the file system at
-.Pa /dev/i40e0 .
+.Pa /dev/net/i40e0 .
.Sh CONFIGURATION
The
.Nm i40e
@@ -282,7 +282,7 @@ driver is only supported on
systems at this time.
.Sh FILES
.Bl -tag -width Pa
-.It Pa /dev/i40e*
+.It Pa /dev/net/i40e*
Per-instance character device.
.It Pa /kernel/drv/i40e
32-bit device driver (x86).
diff --git a/usr/src/pkg/manifests/driver-network-i40e.mf b/usr/src/pkg/manifests/driver-network-i40e.mf
index f7d8acf452..57c49438dc 100644
--- a/usr/src/pkg/manifests/driver-network-i40e.mf
+++ b/usr/src/pkg/manifests/driver-network-i40e.mf
@@ -10,13 +10,13 @@
#
#
-# Copyright 2016 Joyent, Inc.
+# Copyright (c) 2017 Joyent, Inc.
#
<include global_zone_only_component>
set name=pkg.fmri value=pkg:/driver/network/i40e@$(PKGVERS)
-set name=pkg.description value="Intel 710 Ethernet Driver"
-set name=pkg.summary value="Intel 710 Ethernet Driver"
+set name=pkg.description value="Intel 710/722 Ethernet Driver"
+set name=pkg.summary value="Intel 710/722 Ethernet Driver"
set name=info.classification \
value=org.opensolaris.category.2008:Drivers/Networking
set name=variant.arch value=i386
@@ -35,7 +35,13 @@ driver name=i40e clone_perms="i40e 0666 root sys" perms="* 0666 root sys" \
alias=pciex8086,1586 \
alias=pciex8086,1589 \
alias=pciex8086,158a \
- alias=pciex8086,158b
+ alias=pciex8086,158b \
+ alias=pciex8086,37ce \
+ alias=pciex8086,37cf \
+ alias=pciex8086,37d0 \
+ alias=pciex8086,37d1 \
+ alias=pciex8086,37d2 \
+ alias=pciex8086,37d3
file path=kernel/drv/$(ARCH64)/i40e group=sys
file path=kernel/drv/i40e group=sys
file path=kernel/drv/i40e.conf group=sys
diff --git a/usr/src/uts/common/io/i40e/i40e_main.c b/usr/src/uts/common/io/i40e/i40e_main.c
index 1a1a73aec2..768b417f3e 100644
--- a/usr/src/uts/common/io/i40e/i40e_main.c
+++ b/usr/src/uts/common/io/i40e/i40e_main.c
@@ -11,7 +11,7 @@
/*
* Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
- * Copyright 2016 Joyent, Inc.
+ * Copyright (c) 2017, Joyent, Inc.
* Copyright 2017 Tegile Systems, Inc. All rights reserved.
*/
@@ -449,6 +449,18 @@ i40e_notice(i40e_t *i40e, const char *fmt, ...)
va_end(ap);
}
+/*
+ * Various parts of the driver need to know if the controller is from the X722
+ * family, which has a few additional capabilities and different programming
+ * means. We don't consider virtual functions as part of this as they are quite
+ * different and will require substantially more work.
+ */
+static boolean_t
+i40e_is_x722(i40e_t *i40e)
+{
+ return (i40e->i40e_hw_space.mac.type == I40E_MAC_X722);
+}
+
static void
i40e_device_rele(i40e_t *i40e)
{
@@ -1700,6 +1712,13 @@ static boolean_t
i40e_alloc_intrs(i40e_t *i40e, dev_info_t *devinfo)
{
int intr_types, rc;
+ uint_t max_trqpairs;
+
+ if (i40e_is_x722(i40e)) {
+ max_trqpairs = I40E_722_MAX_TC_QUEUES;
+ } else {
+ max_trqpairs = I40E_710_MAX_TC_QUEUES;
+ }
rc = ddi_intr_get_supported_types(devinfo, &intr_types);
if (rc != DDI_SUCCESS) {
@@ -1715,8 +1734,7 @@ i40e_alloc_intrs(i40e_t *i40e, dev_info_t *devinfo)
if (i40e_alloc_intr_handles(i40e, devinfo,
DDI_INTR_TYPE_MSIX)) {
i40e->i40e_num_trqpairs =
- MIN(i40e->i40e_intr_count - 1,
- I40E_AQ_VSI_TC_QUE_SIZE_MAX);
+ MIN(i40e->i40e_intr_count - 1, max_trqpairs);
return (B_TRUE);
}
}
@@ -1934,8 +1952,9 @@ i40e_config_vsi(i40e_t *i40e, i40e_hw_t *hw)
context.info.queue_mapping[0] = I40E_ASSIGN_ALL_QUEUES;
/*
- * tc_queues determines the size of the traffic class, where the
- * size is 2^^tc_queues to a maximum of 64.
+ * tc_queues determines the size of the traffic class, where the size is
+ * 2^^tc_queues to a maximum of 64 for the X710 and 128 for the X722.
+ *
* Some examples:
* i40e_num_trqpairs == 1 => tc_queues = 0, 2^^0 = 1.
* i40e_num_trqpairs == 7 => tc_queues = 3, 2^^3 = 8.
@@ -1972,73 +1991,156 @@ i40e_config_vsi(i40e_t *i40e, i40e_hw_t *hw)
}
/*
+ * Configure the RSS key. For the X710 controller family, this is set on a
+ * per-PF basis via registers. For the X722, this is done on a per-VSI basis
+ * through the admin queue.
+ */
+static boolean_t
+i40e_config_rss_key(i40e_t *i40e, i40e_hw_t *hw)
+{
+ uint32_t seed[I40E_PFQF_HKEY_MAX_INDEX + 1];
+
+ (void) random_get_pseudo_bytes((uint8_t *)seed, sizeof (seed));
+
+ if (i40e_is_x722(i40e)) {
+ struct i40e_aqc_get_set_rss_key_data key;
+ const char *u8seed = (char *)seed;
+ enum i40e_status_code status;
+
+ ASSERT(sizeof (key) >= (sizeof (key.standard_rss_key) +
+ sizeof (key.extended_hash_key)));
+
+ bcopy(u8seed, key.standard_rss_key,
+ sizeof (key.standard_rss_key));
+ bcopy(&u8seed[sizeof (key.standard_rss_key)],
+ key.extended_hash_key, sizeof (key.extended_hash_key));
+
+ status = i40e_aq_set_rss_key(hw, i40e->i40e_vsi_num, &key);
+ if (status != I40E_SUCCESS) {
+ i40e_error(i40e, "failed to set rss key: %d", status);
+ return (B_FALSE);
+ }
+ } else {
+ uint_t i;
+ for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++)
+ i40e_write_rx_ctl(hw, I40E_PFQF_HKEY(i), seed[i]);
+ }
+
+ return (B_TRUE);
+}
+
+/*
+ * Populate the LUT. The size of each entry in the LUT depends on the controller
+ * family, with the X722 using a known 7-bit width. On the X710 controller, this
+ * is programmed through its control registers where as on the X722 this is
+ * configured through the admin queue. Also of note, the X722 allows the LUT to
+ * be set on a per-PF or VSI basis. At this time, as we only have a single VSI,
+ * we use the PF setting as it is the primary VSI.
+ *
+ * We populate the LUT in a round robin fashion with the rx queue indices from 0
+ * to i40e_num_trqpairs - 1.
+ */
+static boolean_t
+i40e_config_rss_hlut(i40e_t *i40e, i40e_hw_t *hw)
+{
+ uint32_t *hlut;
+ uint8_t lut_mask;
+ uint_t i;
+ boolean_t ret = B_FALSE;
+
+ /*
+ * We always configure the PF with a table size of 512 bytes in
+ * i40e_chip_start().
+ */
+ hlut = kmem_alloc(I40E_HLUT_TABLE_SIZE, KM_NOSLEEP);
+ if (hlut == NULL) {
+ i40e_error(i40e, "i40e_config_rss() buffer allocation failed");
+ return (B_FALSE);
+ }
+
+ /*
+ * The width of the X722 is apparently defined to be 7 bits, regardless
+ * of the capability.
+ */
+ if (i40e_is_x722(i40e)) {
+ lut_mask = (1 << 7) - 1;
+ } else {
+ lut_mask = (1 << hw->func_caps.rss_table_entry_width) - 1;
+ }
+
+ for (i = 0; i < I40E_HLUT_TABLE_SIZE; i++)
+ ((uint8_t *)hlut)[i] = (i % i40e->i40e_num_trqpairs) & lut_mask;
+
+ if (i40e_is_x722(i40e)) {
+ enum i40e_status_code status;
+ status = i40e_aq_set_rss_lut(hw, i40e->i40e_vsi_num, B_TRUE,
+ (uint8_t *)hlut, I40E_HLUT_TABLE_SIZE);
+ if (status != I40E_SUCCESS) {
+ i40e_error(i40e, "failed to set RSS LUT: %d", status);
+ goto out;
+ }
+ } else {
+ for (i = 0; i < I40E_HLUT_TABLE_SIZE >> 2; i++) {
+ I40E_WRITE_REG(hw, I40E_PFQF_HLUT(i), hlut[i]);
+ }
+ }
+ ret = B_TRUE;
+out:
+ kmem_free(hlut, I40E_HLUT_TABLE_SIZE);
+ return (ret);
+}
+
+/*
* Set up RSS.
* 1. Seed the hash key.
* 2. Enable PCTYPEs for the hash filter.
* 3. Populate the LUT.
- *
- * Note: When/if X722 support is added the hash key is seeded via a call
- * to i40e_aq_set_rss_key(), and the LUT is populated using
- * i40e_aq_set_rss_lut().
*/
static boolean_t
i40e_config_rss(i40e_t *i40e, i40e_hw_t *hw)
{
- int i;
- uint8_t lut_mask;
- uint32_t *hlut;
uint64_t hena;
- boolean_t rv = B_TRUE;
- uint32_t seed[I40E_PFQF_HKEY_MAX_INDEX + 1];
/*
* 1. Seed the hash key
*/
- (void) random_get_pseudo_bytes((uint8_t *)seed, sizeof (seed));
-
- for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++)
- i40e_write_rx_ctl(hw, I40E_PFQF_HKEY(i), seed[i]);
+ if (!i40e_config_rss_key(i40e, hw))
+ return (B_FALSE);
/*
* 2. Configure PCTYPES
*/
hena = (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) |
(1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_SCTP) |
(1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
(1ULL << I40E_FILTER_PCTYPE_FRAG_IPV4) |
(1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) |
(1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_SCTP) |
(1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
(1ULL << I40E_FILTER_PCTYPE_FRAG_IPV6) |
(1ULL << I40E_FILTER_PCTYPE_L2_PAYLOAD);
+ /*
+ * Add additional types supported by the X722 controller.
+ */
+ if (i40e_is_x722(i40e)) {
+ hena |= (1ULL << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP) |
+ (1ULL << I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);
+ }
+
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(0), (uint32_t)hena);
i40e_write_rx_ctl(hw, I40E_PFQF_HENA(1), (uint32_t)(hena >> 32));
/*
* 3. Populate LUT
- *
- * Each entry in the LUT is 8 bits and is used to index
- * the rx queue. Populate the LUT in a round robin fashion
- * with rx queue indices from 0 to i40e_num_trqpairs - 1.
*/
- hlut = kmem_alloc(hw->func_caps.rss_table_size, KM_NOSLEEP);
- if (hlut == NULL) {
- i40e_error(i40e, "i40e_config_rss() buffer allocation failed");
- return (B_FALSE);
- }
-
- lut_mask = (1 << hw->func_caps.rss_table_entry_width) - 1;
-
- for (i = 0; i < hw->func_caps.rss_table_size; i++)
- ((uint8_t *)hlut)[i] = (i % i40e->i40e_num_trqpairs) & lut_mask;
-
- for (i = 0; i < hw->func_caps.rss_table_size >> 2; i++)
- I40E_WRITE_REG(hw, I40E_PFQF_HLUT(i), hlut[i]);
-
- kmem_free(hlut, hw->func_caps.rss_table_size);
-
- return (rv);
+ return (i40e_config_rss_hlut(i40e, hw));
}
/*
@@ -2069,7 +2171,9 @@ i40e_chip_start(i40e_t *i40e)
i40e_init_macaddrs(i40e, hw);
/*
- * Set up the filter control.
+ * Set up the filter control. If the hash lut size is changed from
+ * I40E_HASH_LUT_SIZE_512 then I40E_HLUT_TABLE_SIZE and
+ * i40e_config_rss_hlut() will need to be updated.
*/
bzero(&filter, sizeof (filter));
filter.enable_ethtype = TRUE;
diff --git a/usr/src/uts/common/io/i40e/i40e_sw.h b/usr/src/uts/common/io/i40e/i40e_sw.h
index 57200c7fb6..78aced0144 100644
--- a/usr/src/uts/common/io/i40e/i40e_sw.h
+++ b/usr/src/uts/common/io/i40e/i40e_sw.h
@@ -151,7 +151,6 @@ typedef enum i40e_itr_index {
I40E_ITR_INDEX_NONE = 0x3
} i40e_itr_index_t;
-
/*
* Table 1-5 of the PRM notes that LSO supports up to 256 KB.
*/
@@ -308,11 +307,22 @@ typedef enum i40e_itr_index {
#define I40E_PBANUM_STRLEN 13
/*
- * Define the maximum size of a number of queues for a traffic class. While this
- * would ideally be a part of the common code parts, because it's not at this
- * time, we define it here.
+ * Define the maximum number of queues for a traffic class. These values come
+ * from the 'Number and offset of queue pairs per TCs' section of the 'Add VSI
+ * Command Buffer' table. For the 710 controller family this is table 7-62
+ * (r2.5) and for the 722 this is table 38-216 (r2.0).
+ */
+#define I40E_710_MAX_TC_QUEUES 64
+#define I40E_722_MAX_TC_QUEUES 128
+
+/*
+ * Define the size of the HLUT table size. The HLUT table can either be 128 or
+ * 512 bytes. We always set the table size to be 512 bytes in i40e_chip_start().
+ * Note, this should not be confused with the common code's macro
+ * I40E_HASH_LUT_SIZE_512 which is the bit pattern needed to tell the card to
+ * use a 512 byte HLUT.
*/
-#define I40E_AQ_VSI_TC_QUE_SIZE_MAX (1 << 0x6)
+#define I40E_HLUT_TABLE_SIZE 512
/*
* Bit flags for attach_progress