From owner-svn-src-stable-10@freebsd.org Mon Oct 31 22:03:46 2016 Return-Path: Delivered-To: svn-src-stable-10@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 33384C288DE; Mon, 31 Oct 2016 22:03:46 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id E724D151D; Mon, 31 Oct 2016 22:03:45 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u9VM3j4x004905; Mon, 31 Oct 2016 22:03:45 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u9VM3jD1004904; Mon, 31 Oct 2016 22:03:45 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201610312203.u9VM3jD1004904@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Mon, 31 Oct 2016 22:03:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r308153 - stable/10/sys/dev/cxgbe X-SVN-Group: stable-10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable-10@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for only the 10-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 31 Oct 2016 22:03:46 -0000 Author: jhb Date: Mon Oct 31 22:03:44 2016 New Revision: 308153 URL: https://svnweb.freebsd.org/changeset/base/308153 Log: MFC 289401: cxgbe(4): support for the kernel RSS option. You need PCBGROUP and RSS in the kernel config to use this. Note: Since RSS is not present in 10.x this is mostly a no-op and is stubbed out by removing the #include of opt_rss.h. This is merged primarily to reduce conflicts in future merges, however it does add a couple of diagnostic messages related to RSS buckets vs RX queue counts. Discussed with: np Sponsored by: Chelsio Communications Modified: stable/10/sys/dev/cxgbe/t4_main.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/dev/cxgbe/t4_main.c ============================================================================== --- stable/10/sys/dev/cxgbe/t4_main.c Mon Oct 31 21:57:43 2016 (r308152) +++ stable/10/sys/dev/cxgbe/t4_main.c Mon Oct 31 22:03:44 2016 (r308153) @@ -57,6 +57,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef RSS +#include +#endif #if defined(__i386__) || defined(__amd64__) #include #include @@ -3432,6 +3435,71 @@ adapter_full_uninit(struct adapter *sc) return (0); } +#ifdef RSS +#define SUPPORTED_RSS_HASHTYPES (RSS_HASHTYPE_RSS_IPV4 | \ + RSS_HASHTYPE_RSS_TCP_IPV4 | RSS_HASHTYPE_RSS_IPV6 | \ + RSS_HASHTYPE_RSS_TCP_IPV6 | RSS_HASHTYPE_RSS_UDP_IPV4 | \ + RSS_HASHTYPE_RSS_UDP_IPV6) + +/* Translates kernel hash types to hardware. */ +static int +hashconfig_to_hashen(int hashconfig) +{ + int hashen = 0; + + if (hashconfig & RSS_HASHTYPE_RSS_IPV4) + hashen |= F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN; + if (hashconfig & RSS_HASHTYPE_RSS_IPV6) + hashen |= F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN; + if (hashconfig & RSS_HASHTYPE_RSS_UDP_IPV4) { + hashen |= F_FW_RSS_VI_CONFIG_CMD_UDPEN | + F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN; + } + if (hashconfig & RSS_HASHTYPE_RSS_UDP_IPV6) { + hashen |= F_FW_RSS_VI_CONFIG_CMD_UDPEN | + F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN; + } + if (hashconfig & RSS_HASHTYPE_RSS_TCP_IPV4) + hashen |= F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN; + if (hashconfig & RSS_HASHTYPE_RSS_TCP_IPV6) + hashen |= F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN; + + return (hashen); +} + +/* Translates hardware hash types to kernel. */ +static int +hashen_to_hashconfig(int hashen) +{ + int hashconfig = 0; + + if (hashen & F_FW_RSS_VI_CONFIG_CMD_UDPEN) { + /* + * If UDP hashing was enabled it must have been enabled for + * either IPv4 or IPv6 (inclusive or). Enabling UDP without + * enabling any 4-tuple hash is nonsense configuration. + */ + MPASS(hashen & (F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN | + F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN)); + + if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) + hashconfig |= RSS_HASHTYPE_RSS_UDP_IPV4; + if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) + hashconfig |= RSS_HASHTYPE_RSS_UDP_IPV6; + } + if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) + hashconfig |= RSS_HASHTYPE_RSS_TCP_IPV4; + if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) + hashconfig |= RSS_HASHTYPE_RSS_TCP_IPV6; + if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN) + hashconfig |= RSS_HASHTYPE_RSS_IPV4; + if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN) + hashconfig |= RSS_HASHTYPE_RSS_IPV6; + + return (hashconfig); +} +#endif + int port_full_init(struct port_info *pi) { @@ -3439,7 +3507,14 @@ port_full_init(struct port_info *pi) struct ifnet *ifp = pi->ifp; uint16_t *rss; struct sge_rxq *rxq; - int rc, i, j; + int rc, i, j, hashen; +#ifdef RSS + int nbuckets = rss_getnumbuckets(); + int hashconfig = rss_gethashconfig(); + int extra; + uint32_t raw_rss_key[RSS_KEYSIZE / sizeof(uint32_t)]; + uint32_t rss_key[RSS_KEYSIZE / sizeof(uint32_t)]; +#endif ASSERT_SYNCHRONIZED_OP(sc); KASSERT((pi->flags & PORT_INIT_DONE) == 0, @@ -3458,13 +3533,42 @@ port_full_init(struct port_info *pi) /* * Setup RSS for this port. Save a copy of the RSS table for later use. */ + if (pi->nrxq > pi->rss_size) { + if_printf(ifp, "nrxq (%d) > hw RSS table size (%d); " + "some queues will never receive traffic.\n", pi->nrxq, + pi->rss_size); + } else if (pi->rss_size % pi->nrxq) { + if_printf(ifp, "nrxq (%d), hw RSS table size (%d); " + "expect uneven traffic distribution.\n", pi->nrxq, + pi->rss_size); + } +#ifdef RSS + MPASS(RSS_KEYSIZE == 40); + if (pi->nrxq != nbuckets) { + if_printf(ifp, "nrxq (%d) != kernel RSS buckets (%d);" + "performance will be impacted.\n", pi->nrxq, nbuckets); + } + + rss_getkey((void *)&raw_rss_key[0]); + for (i = 0; i < nitems(rss_key); i++) { + rss_key[i] = htobe32(raw_rss_key[nitems(rss_key) - 1 - i]); + } + t4_write_rss_key(sc, (void *)&rss_key[0], -1); +#endif rss = malloc(pi->rss_size * sizeof (*rss), M_CXGBE, M_ZERO | M_WAITOK); for (i = 0; i < pi->rss_size;) { +#ifdef RSS + j = rss_get_indirection_to_bucket(i); + j %= pi->nrxq; + rxq = &sc->sge.rxq[pi->first_rxq + j]; + rss[i++] = rxq->iq.abs_id; +#else for_each_rxq(pi, j, rxq) { rss[i++] = rxq->iq.abs_id; if (i == pi->rss_size) break; } +#endif } rc = -t4_config_rss_range(sc, sc->mbox, pi->viid, 0, pi->rss_size, rss, @@ -3474,6 +3578,54 @@ port_full_init(struct port_info *pi) goto done; } +#ifdef RSS + hashen = hashconfig_to_hashen(hashconfig); + + /* + * We may have had to enable some hashes even though the global config + * wants them disabled. This is a potential problem that must be + * reported to the user. + */ + extra = hashen_to_hashconfig(hashen) ^ hashconfig; + + /* + * If we consider only the supported hash types, then the enabled hashes + * are a superset of the requested hashes. In other words, there cannot + * be any supported hash that was requested but not enabled, but there + * can be hashes that were not requested but had to be enabled. + */ + extra &= SUPPORTED_RSS_HASHTYPES; + MPASS((extra & hashconfig) == 0); + + if (extra) { + if_printf(ifp, + "global RSS config (0x%x) cannot be accomodated.\n", + hashconfig); + } + if (extra & RSS_HASHTYPE_RSS_IPV4) + if_printf(ifp, "IPv4 2-tuple hashing forced on.\n"); + if (extra & RSS_HASHTYPE_RSS_TCP_IPV4) + if_printf(ifp, "TCP/IPv4 4-tuple hashing forced on.\n"); + if (extra & RSS_HASHTYPE_RSS_IPV6) + if_printf(ifp, "IPv6 2-tuple hashing forced on.\n"); + if (extra & RSS_HASHTYPE_RSS_TCP_IPV6) + if_printf(ifp, "TCP/IPv6 4-tuple hashing forced on.\n"); + if (extra & RSS_HASHTYPE_RSS_UDP_IPV4) + if_printf(ifp, "UDP/IPv4 4-tuple hashing forced on.\n"); + if (extra & RSS_HASHTYPE_RSS_UDP_IPV6) + if_printf(ifp, "UDP/IPv6 4-tuple hashing forced on.\n"); +#else + hashen = F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN | + F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN | + F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN | + F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN | F_FW_RSS_VI_CONFIG_CMD_UDPEN; +#endif + rc = -t4_config_vi_rss(sc, sc->mbox, pi->viid, hashen, rss[0]); + if (rc != 0) { + if_printf(ifp, "rss hash/defaultq config failed: %d\n", rc); + goto done; + } + pi->rss = rss; pi->flags |= PORT_INIT_DONE; done: @@ -8371,17 +8523,39 @@ tweak_tunables(void) { int nc = mp_ncpus; /* our snapshot of the number of CPUs */ - if (t4_ntxq10g < 1) + if (t4_ntxq10g < 1) { +#ifdef RSS + t4_ntxq10g = rss_getnumbuckets(); +#else t4_ntxq10g = min(nc, NTXQ_10G); +#endif + } - if (t4_ntxq1g < 1) + if (t4_ntxq1g < 1) { +#ifdef RSS + /* XXX: way too many for 1GbE? */ + t4_ntxq1g = rss_getnumbuckets(); +#else t4_ntxq1g = min(nc, NTXQ_1G); +#endif + } - if (t4_nrxq10g < 1) + if (t4_nrxq10g < 1) { +#ifdef RSS + t4_nrxq10g = rss_getnumbuckets(); +#else t4_nrxq10g = min(nc, NRXQ_10G); +#endif + } - if (t4_nrxq1g < 1) + if (t4_nrxq1g < 1) { +#ifdef RSS + /* XXX: way too many for 1GbE? */ + t4_nrxq1g = rss_getnumbuckets(); +#else t4_nrxq1g = min(nc, NRXQ_1G); +#endif + } #ifdef TCP_OFFLOAD if (t4_nofldtxq10g < 1)