From d60c4b68b4189b047c8b3c8bf84337505e0ccfc5 Mon Sep 17 00:00:00 2001 From: Robert Mustacchi Date: Sat, 9 Sep 2017 16:34:02 +0000 Subject: OS-5858 Want support for X722 Reviewed by: Dan McDonald Reviewed by: Jerry Jelinek Reviewed by: Patrick Mooney Approved by: Jerry Jelinek --- usr/src/man/man7d/i40e.7d | 18 +-- usr/src/pkg/manifests/driver-network-i40e.mf | 14 +- usr/src/uts/common/io/i40e/i40e_main.c | 184 +++++++++++++++++++++------ usr/src/uts/common/io/i40e/i40e_sw.h | 20 ++- 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. # 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. @@ -1971,74 +1990,157 @@ i40e_config_vsi(i40e_t *i40e, i40e_hw_t *hw) return (B_TRUE); } +/* + * 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 -- cgit v1.2.3