From owner-svn-src-all@FreeBSD.ORG Mon Jan 12 18:43:36 2015 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 7FCC26DD; Mon, 12 Jan 2015 18:43:36 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::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 6AD2F892; Mon, 12 Jan 2015 18:43:36 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id t0CIhaMB067583; Mon, 12 Jan 2015 18:43:36 GMT (envelope-from jfv@FreeBSD.org) Received: (from jfv@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id t0CIhYnW067569; Mon, 12 Jan 2015 18:43:34 GMT (envelope-from jfv@FreeBSD.org) Message-Id: <201501121843.t0CIhYnW067569@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: jfv set sender to jfv@FreeBSD.org using -f From: Jack F Vogel Date: Mon, 12 Jan 2015 18:43:34 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r277084 - in head/sys: dev/ixl modules/ixl modules/ixlv X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 12 Jan 2015 18:43:36 -0000 Author: jfv Date: Mon Jan 12 18:43:34 2015 New Revision: 277084 URL: https://svnweb.freebsd.org/changeset/base/277084 Log: Intel I40E driver updates: if_ixl to version 1.3.0, if_ixlv to version 1.2.0 - Major change in both drivers is to add RSS support - In ixl fix some interface speed related issues, dual speed was not changing correctly, KR/X media was not displaying correctly (this has a workaround until a more robust media handling is in place) - Add a warning when using Dell NPAR and the speed is less than 10G - Wrap a queue hung message in IXL_DEBUG, as it is non-fatal, and without tuning can display excessively MFC after: 1 week Modified: head/sys/dev/ixl/if_ixl.c head/sys/dev/ixl/if_ixlv.c head/sys/dev/ixl/ixl.h head/sys/dev/ixl/ixl_txrx.c head/sys/modules/ixl/Makefile head/sys/modules/ixlv/Makefile Modified: head/sys/dev/ixl/if_ixl.c ============================================================================== --- head/sys/dev/ixl/if_ixl.c Mon Jan 12 18:38:09 2015 (r277083) +++ head/sys/dev/ixl/if_ixl.c Mon Jan 12 18:43:34 2015 (r277084) @@ -34,13 +34,14 @@ #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_rss.h" #include "ixl.h" #include "ixl_pf.h" /********************************************************************* * Driver version *********************************************************************/ -char ixl_driver_version[] = "1.2.8"; +char ixl_driver_version[] = "1.3.0"; /********************************************************************* * PCI Device ID Table @@ -174,7 +175,7 @@ static void ixl_stat_update48(struct i40 static void ixl_stat_update32(struct i40e_hw *, u32, bool, u64 *, u64 *); -#ifdef IXL_DEBUG +#ifdef IXL_DEBUG_SYSCTL static int ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS); static int ixl_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS); static int ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS); @@ -427,7 +428,7 @@ ixl_attach(device_t dev) OID_AUTO, "dynamic_tx_itr", CTLFLAG_RW, &ixl_dynamic_tx_itr, 0, "Dynamic TX ITR"); -#ifdef IXL_DEBUG +#ifdef IXL_DEBUG_SYSCTL SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev), SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, "link_status", CTLTYPE_STRING | CTLFLAG_RD, @@ -662,8 +663,9 @@ ixl_attach(device_t dev) /* Reset port's advertised speeds */ if (!i40e_is_40G_device(hw->device_id)) { - pf->advertised_speed = 0x7; - ixl_set_advertised_speeds(pf, 0x7); + pf->advertised_speed = + (hw->device_id == I40E_DEV_ID_10G_BASE_T) ? 0x7 : 0x6; + ixl_set_advertised_speeds(pf, pf->advertised_speed); } /* Register for VLAN events */ @@ -1407,6 +1409,12 @@ ixl_media_status(struct ifnet * ifp, str case I40E_PHY_TYPE_10GBASE_SFPP_CU: ifmr->ifm_active |= IFM_10G_TWINAX; break; + case I40E_PHY_TYPE_10GBASE_KR: + /* + ** this is not technically correct + ** but FreeBSD does not have the media + ** type defined yet, so its a compromise. + */ case I40E_PHY_TYPE_10GBASE_SR: ifmr->ifm_active |= IFM_10G_SR; break; @@ -1721,8 +1729,10 @@ ixl_local_timer(void *arg) vsi->active_queues |= ((u64)1 << que->me); } if (que->busy >= IXL_MAX_TX_BUSY) { +#ifdef IXL_DEBUG device_printf(dev,"Warning queue %d " "appears to be hung!\n", i); +#endif que->busy = IXL_QUEUE_HUNG; ++hung; } @@ -1765,6 +1775,15 @@ ixl_update_link_status(struct ixl_pf *pf "Full Duplex", ixl_fc_string[fc]); } vsi->link_active = TRUE; + /* + ** Warn user if link speed on NPAR enabled + ** partition is not at least 10GB + */ + if (hw->func_caps.npar_enable && + (hw->phy.link_info.link_speed == I40E_LINK_SPEED_1GB || + hw->phy.link_info.link_speed == I40E_LINK_SPEED_100MB)) + device_printf(dev, "The partition detected link" + "speed that is less than 10Gbps\n"); if_link_state_change(ifp, LINK_STATE_UP); } } else { /* Link down */ @@ -1901,6 +1920,7 @@ ixl_assign_vsi_msix(struct ixl_pf *pf) /* Now set up the stations */ for (int i = 0; i < vsi->num_queues; i++, vector++, que++) { + int cpu_id = i; rid = vector + 1; txr = &que->txr; que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, @@ -1921,14 +1941,23 @@ ixl_assign_vsi_msix(struct ixl_pf *pf) } bus_describe_intr(dev, que->res, que->tag, "q%d", i); /* Bind the vector to a CPU */ - bus_bind_intr(dev, que->res, i); +#ifdef RSS + cpu_id = rss_getcpu(i % rss_getnumbuckets()); +#endif + bus_bind_intr(dev, que->res, cpu_id); que->msix = vector; TASK_INIT(&que->tx_task, 0, ixl_deferred_mq_start, que); TASK_INIT(&que->task, 0, ixl_handle_que, que); que->tq = taskqueue_create_fast("ixl_que", M_NOWAIT, taskqueue_thread_enqueue, &que->tq); - taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que", - device_get_nameunit(pf->dev)); +#ifdef RSS + taskqueue_start_threads_pinned(&que->tq, 1, PI_NET, + cpu_id, "%s (bucket %d)", + device_get_nameunit(dev), cpu_id); +#else + taskqueue_start_threads(&que->tq, 1, PI_NET, + "%s que", device_get_nameunit(dev)); +#endif } return (0); @@ -1995,6 +2024,12 @@ ixl_init_msix(struct ixl_pf *pf) if ((ixl_max_queues != 0) && (ixl_max_queues <= queues)) queues = ixl_max_queues; +#ifdef RSS + /* If we're doing RSS, clamp at the number of RSS buckets */ + if (queues > rss_getnumbuckets()) + queues = rss_getnumbuckets(); +#endif + /* ** Want one vector (RX/TX pair) per queue ** plus an additional for the admin queue. @@ -2015,6 +2050,25 @@ ixl_init_msix(struct ixl_pf *pf) "Using MSIX interrupts with %d vectors\n", vectors); pf->msix = vectors; pf->vsi.num_queues = queues; +#ifdef RSS + /* + * If we're doing RSS, the number of queues needs to + * match the number of RSS buckets that are configured. + * + * + If there's more queues than RSS buckets, we'll end + * up with queues that get no traffic. + * + * + If there's more RSS buckets than queues, we'll end + * up having multiple RSS buckets map to the same queue, + * so there'll be some contention. + */ + if (queues != rss_getnumbuckets()) { + device_printf(dev, + "%s: queues (%d) != RSS buckets (%d)" + "; performance will be impacted.\n", + __func__, queues, rss_getnumbuckets()); + } +#endif return (vectors); } msi: @@ -2383,7 +2437,8 @@ ixl_setup_interface(device_t dev, struct if (aq_error == I40E_ERR_UNKNOWN_PHY) { /* Need delay to detect fiber correctly */ i40e_msec_delay(200); - aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, TRUE, &abilities_resp, NULL); + aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, + TRUE, &abilities_resp, NULL); if (aq_error == I40E_ERR_UNKNOWN_PHY) device_printf(dev, "Unknown PHY type detected!\n"); else @@ -3043,7 +3098,6 @@ ixl_add_sysctls_eth_stats(struct sysctl_ "Multicast Packets Transmitted"}, {ð_stats->tx_broadcast, "bcast_pkts_txd", "Broadcast Packets Transmitted"}, - {ð_stats->tx_discards, "tx_discards", "Discarded TX packets"}, // end {0,0,0} }; @@ -3126,19 +3180,45 @@ static void ixl_config_rss(struct ixl_vs struct ixl_pf *pf = (struct ixl_pf *)vsi->back; struct i40e_hw *hw = vsi->hw; u32 lut = 0; - u64 set_hena, hena; - int i, j; + u64 set_hena = 0, hena; + int i, j, que_id; +#ifdef RSS + u32 rss_hash_config; + u32 rss_seed[IXL_KEYSZ]; +#else + u32 rss_seed[IXL_KEYSZ] = {0x41b01687, + 0x183cfd8c, 0xce880440, 0x580cbc3c, + 0x35897377, 0x328b25e1, 0x4fa98922, + 0xb7d90c14, 0xd5bad70d, 0xcd15a2c1}; +#endif - static const u32 seed[I40E_PFQF_HKEY_MAX_INDEX + 1] = {0x41b01687, - 0x183cfd8c, 0xce880440, 0x580cbc3c, 0x35897377, - 0x328b25e1, 0x4fa98922, 0xb7d90c14, 0xd5bad70d, - 0xcd15a2c1, 0xe8580225, 0x4a1e9d11, 0xfe5731be}; +#ifdef RSS + /* Fetch the configured RSS key */ + rss_getkey((uint8_t *) &rss_seed); +#endif /* Fill out hash function seed */ - for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++) - wr32(hw, I40E_PFQF_HKEY(i), seed[i]); + for (i = 0; i < IXL_KEYSZ; i++) + wr32(hw, I40E_PFQF_HKEY(i), rss_seed[i]); /* Enable PCTYPES for RSS: */ +#ifdef RSS + rss_hash_config = rss_gethashconfig(); + if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER); + if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP); + if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP); + if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER); + if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP); + if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP); + if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX) + set_hena |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; +#else set_hena = ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | @@ -3151,7 +3231,7 @@ static void ixl_config_rss(struct ixl_vs ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6) | ((u64)1 << I40E_FILTER_PCTYPE_L2_PAYLOAD); - +#endif hena = (u64)rd32(hw, I40E_PFQF_HENA(0)) | ((u64)rd32(hw, I40E_PFQF_HENA(1)) << 32); hena |= set_hena; @@ -3162,8 +3242,19 @@ static void ixl_config_rss(struct ixl_vs for (i = j = 0; i < pf->hw.func_caps.rss_table_size; i++, j++) { if (j == vsi->num_queues) j = 0; +#ifdef RSS + /* + * Fetch the RSS bucket id for the given indirection entry. + * Cap it at the number of configured buckets (which is + * num_queues.) + */ + que_id = rss_get_indirection_to_bucket(i); + que_id = que_id % adapter->num_queues; +#else + que_id = j; +#endif /* lut = 4-byte sliding window of 4 lut entries */ - lut = (lut << 8) | (j & + lut = (lut << 8) | (que_id & ((0x1 << pf->hw.func_caps.rss_table_entry_width) - 1)); /* On i = 3, we have 4 entries in lut; write to the register */ if ((i & 3) == 3) @@ -3401,7 +3492,7 @@ ixl_add_hw_filters(struct ixl_vsi *vsi, a = malloc(sizeof(struct i40e_aqc_add_macvlan_element_data) * cnt, M_DEVBUF, M_NOWAIT | M_ZERO); if (a == NULL) { - device_printf(dev, "add hw filter failed to get memory\n"); + device_printf(dev, "add_hw_filters failed to get memory\n"); return; } @@ -3426,8 +3517,8 @@ ixl_add_hw_filters(struct ixl_vsi *vsi, if (j > 0) { err = i40e_aq_add_macvlan(hw, vsi->seid, a, j, NULL); if (err) - device_printf(dev, "aq_add_macvlan failure %d\n", - hw->aq.asq_last_status); + device_printf(dev, "aq_add_macvlan err %d, aq_error %d\n", + err, hw->aq.asq_last_status); else vsi->hw_filters_add += j; } @@ -3476,6 +3567,7 @@ ixl_del_hw_filters(struct ixl_vsi *vsi, err = i40e_aq_remove_macvlan(hw, vsi->seid, d, j, NULL); /* NOTE: returns ENOENT every time but seems to work fine, so we'll ignore that specific error. */ + // TODO: Does this still occur on current firmwares? if (err && hw->aq.asq_last_status != I40E_AQ_RC_ENOENT) { int sc = 0; for (int i = 0; i < j; i++) @@ -3828,29 +3920,6 @@ ixl_update_stats_counters(struct ixl_pf pf->stat_offsets_loaded, &osd->link_xoff_tx, &nsd->link_xoff_tx); - /* Priority flow control stats */ -#if 0 - for (int i = 0; i < 8; i++) { - ixl_stat_update32(hw, I40E_GLPRT_PXONRXC(hw->port, i), - pf->stat_offsets_loaded, - &osd->priority_xon_rx[i], - &nsd->priority_xon_rx[i]); - ixl_stat_update32(hw, I40E_GLPRT_PXONTXC(hw->port, i), - pf->stat_offsets_loaded, - &osd->priority_xon_tx[i], - &nsd->priority_xon_tx[i]); - ixl_stat_update32(hw, I40E_GLPRT_PXOFFTXC(hw->port, i), - pf->stat_offsets_loaded, - &osd->priority_xoff_tx[i], - &nsd->priority_xoff_tx[i]); - ixl_stat_update32(hw, - I40E_GLPRT_RXON2OFFCNT(hw->port, i), - pf->stat_offsets_loaded, - &osd->priority_xon_2_xoff[i], - &nsd->priority_xon_2_xoff[i]); - } -#endif - /* Packet size stats rx */ ixl_stat_update48(hw, I40E_GLPRT_PRC64H(hw->port), I40E_GLPRT_PRC64L(hw->port), @@ -4377,6 +4446,15 @@ ixl_set_advertised_speeds(struct ixl_pf return (EAGAIN); } + /* + ** This seems a bit heavy handed, but we + ** need to get a reinit on some devices + */ + IXL_PF_LOCK(pf); + ixl_stop(pf); + ixl_init_locked(pf); + IXL_PF_UNLOCK(pf); + return (0); } @@ -4521,7 +4599,7 @@ ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS) } -#ifdef IXL_DEBUG +#ifdef IXL_DEBUG_SYSCTL static int ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS) { @@ -4630,6 +4708,16 @@ ixl_sysctl_sw_filter_list(SYSCTL_HANDLER #define IXL_SW_RES_SIZE 0x14 static int +ixl_res_alloc_cmp(const void *a, const void *b) +{ + const struct i40e_aqc_switch_resource_alloc_element_resp *one, *two; + one = (struct i40e_aqc_switch_resource_alloc_element_resp *)a; + two = (struct i40e_aqc_switch_resource_alloc_element_resp *)b; + + return ((int)one->resource_type - (int)two->resource_type); +} + +static int ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS) { struct ixl_pf *pf = (struct ixl_pf *)arg1; @@ -4647,6 +4735,7 @@ ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_A return (ENOMEM); } + bzero(resp, sizeof(resp)); error = i40e_aq_get_switch_resource_alloc(hw, &num_entries, resp, IXL_SW_RES_SIZE, @@ -4657,9 +4746,14 @@ ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_A sbuf_delete(buf); return error; } - device_printf(dev, "Num_entries: %d\n", num_entries); + + /* Sort entries by type for display */ + qsort(resp, num_entries, + sizeof(struct i40e_aqc_switch_resource_alloc_element_resp), + &ixl_res_alloc_cmp); sbuf_cat(buf, "\n"); + sbuf_printf(buf, "# of entries: %d\n", num_entries); sbuf_printf(buf, "Type | Guaranteed | Total | Used | Un-allocated\n" " | (this) | (all) | (this) | (all) \n"); @@ -4864,5 +4958,5 @@ ixl_sysctl_dump_txd(SYSCTL_HANDLER_ARGS) sbuf_delete(buf); return error; } -#endif +#endif /* IXL_DEBUG_SYSCTL */ Modified: head/sys/dev/ixl/if_ixlv.c ============================================================================== --- head/sys/dev/ixl/if_ixlv.c Mon Jan 12 18:38:09 2015 (r277083) +++ head/sys/dev/ixl/if_ixlv.c Mon Jan 12 18:43:34 2015 (r277084) @@ -34,13 +34,14 @@ #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_rss.h" #include "ixl.h" #include "ixlv.h" /********************************************************************* * Driver version *********************************************************************/ -char ixlv_driver_version[] = "1.1.18"; +char ixlv_driver_version[] = "1.2.0"; /********************************************************************* * PCI Device ID Table @@ -1161,7 +1162,11 @@ ixlv_init_msix(struct ixlv_sc *sc) /* Override with hardcoded value if sane */ if ((ixlv_max_queues != 0) && (ixlv_max_queues <= queues)) queues = ixlv_max_queues; - +#ifdef RSS + /* If we're doing RSS, clamp at the number of RSS buckets */ + if (queues > rss_getnumbuckets()) + queues = rss_getnumbuckets(); +#endif /* Enforce the VF max value */ if (queues > IXLV_MAX_QUEUES) queues = IXLV_MAX_QUEUES; @@ -1181,6 +1186,26 @@ ixlv_init_msix(struct ixlv_sc *sc) goto fail; } +#ifdef RSS + /* + * If we're doing RSS, the number of queues needs to + * match the number of RSS buckets that are configured. + * + * + If there's more queues than RSS buckets, we'll end + * up with queues that get no traffic. + * + * + If there's more RSS buckets than queues, we'll end + * up having multiple RSS buckets map to the same queue, + * so there'll be some contention. + */ + if (queues != rss_getnumbuckets()) { + device_printf(dev, + "%s: queues (%d) != RSS buckets (%d)" + "; performance will be impacted.\n", + __func__, queues, rss_getnumbuckets()); + } +#endif + if (pci_alloc_msix(dev, &vectors) == 0) { device_printf(sc->dev, "Using MSIX interrupts with %d vectors\n", vectors); @@ -1352,6 +1377,7 @@ ixlv_assign_msix(struct ixlv_sc *sc) int error, rid, vector = 1; for (int i = 0; i < vsi->num_queues; i++, vector++, que++) { + int cpu_id = i; rid = vector + 1; txr = &que->txr; que->res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, @@ -1372,15 +1398,25 @@ ixlv_assign_msix(struct ixlv_sc *sc) } bus_describe_intr(dev, que->res, que->tag, "que %d", i); /* Bind the vector to a CPU */ - bus_bind_intr(dev, que->res, i); +#ifdef RSS + cpu_id = rss_getcpu(i % rss_getnumbuckets()); +#endif + bus_bind_intr(dev, que->res, cpu_id); que->msix = vector; vsi->que_mask |= (u64)(1 << que->msix); TASK_INIT(&que->tx_task, 0, ixl_deferred_mq_start, que); TASK_INIT(&que->task, 0, ixlv_handle_que, que); que->tq = taskqueue_create_fast("ixlv_que", M_NOWAIT, taskqueue_thread_enqueue, &que->tq); - taskqueue_start_threads(&que->tq, 1, PI_NET, "%s que", - device_get_nameunit(sc->dev)); +#ifdef RSS + taskqueue_start_threads_pinned(&que->tq, 1, PI_NET, + cpu_id, "%s (bucket %d)", + device_get_nameunit(dev), cpu_id); +#else + taskqueue_start_threads(&que->tq, 1, PI_NET, + "%s que", device_get_nameunit(dev)); +#endif + } return (0); @@ -2521,16 +2557,18 @@ ixlv_config_rss(struct ixlv_sc *sc) struct i40e_hw *hw = &sc->hw; struct ixl_vsi *vsi = &sc->vsi; u32 lut = 0; - u64 set_hena, hena; - int i, j; - - /* set up random bits */ - static const u32 seed[I40E_VFQF_HKEY_MAX_INDEX + 1] = { - 0x794221b4, 0xbca0c5ab, 0x6cd5ebd9, 0x1ada6127, - 0x983b3aa1, 0x1c4e71eb, 0x7f6328b2, 0xfcdc0da0, - 0xc135cafa, 0x7a6f7e2d, 0xe7102d28, 0x163cd12e, - 0x4954b126 }; - + u64 set_hena = 0, hena; + int i, j, que_id; +#ifdef RSS + u32 rss_hash_config; + u32 rss_seed[IXL_KEYSZ]; +#else + u32 rss_seed[IXL_KEYSZ] = {0x41b01687, + 0x183cfd8c, 0xce880440, 0x580cbc3c, + 0x35897377, 0x328b25e1, 0x4fa98922, + 0xb7d90c14, 0xd5bad70d, 0xcd15a2c1}; +#endif + /* Don't set up RSS if using a single queue */ if (vsi->num_queues == 1) { wr32(hw, I40E_VFQF_HENA(0), 0); @@ -2539,11 +2577,32 @@ ixlv_config_rss(struct ixlv_sc *sc) return; } +#ifdef RSS + /* Fetch the configured RSS key */ + rss_getkey((uint8_t *) &rss_seed); +#endif /* Fill out hash function seed */ - for (i = 0; i <= I40E_VFQF_HKEY_MAX_INDEX; i++) - wr32(hw, I40E_VFQF_HKEY(i), seed[i]); + for (i = 0; i <= IXL_KEYSZ; i++) + wr32(hw, I40E_VFQF_HKEY(i), rss_seed[i]); /* Enable PCTYPES for RSS: */ +#ifdef RSS + rss_hash_config = rss_gethashconfig(); + if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_OTHER); + if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP); + if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV4) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP); + if (rss_hash_config & RSS_HASHTYPE_RSS_IPV6) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER); + if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV6) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_TCP); + if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6) + set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_UDP); + if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX) + set_hena |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; +#else set_hena = ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) | ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) | @@ -2556,7 +2615,7 @@ ixlv_config_rss(struct ixlv_sc *sc) ((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) | ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6) | ((u64)1 << I40E_FILTER_PCTYPE_L2_PAYLOAD); - +#endif hena = (u64)rd32(hw, I40E_VFQF_HENA(0)) | ((u64)rd32(hw, I40E_VFQF_HENA(1)) << 32); hena |= set_hena; @@ -2564,16 +2623,26 @@ ixlv_config_rss(struct ixlv_sc *sc) wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32)); /* Populate the LUT with max no. of queues in round robin fashion */ - for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; j++) { + for (i = 0, j = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++, j++) { if (j == vsi->num_queues) j = 0; +#ifdef RSS + /* + * Fetch the RSS bucket id for the given indirection entry. + * Cap it at the number of configured buckets (which is + * num_queues.) + */ + que_id = rss_get_indirection_to_bucket(i); + que_id = que_id % adapter->num_queues; +#else + que_id = j; +#endif /* lut = 4-byte sliding window of 4 lut entries */ - lut = (lut << 8) | (j & 0xF); + lut = (lut << 8) | (que_id & 0xF); /* On i = 3, we have 4 entries in lut; write to the register */ - if ((j & 3) == 3) { + if ((i & 3) == 3) { wr32(hw, I40E_VFQF_HLUT(i), lut); DDPRINTF(sc->dev, "HLUT(%2d): %#010x", i, lut); - i++; } } ixl_flush(hw); Modified: head/sys/dev/ixl/ixl.h ============================================================================== --- head/sys/dev/ixl/ixl.h Mon Jan 12 18:38:09 2015 (r277083) +++ head/sys/dev/ixl/ixl.h Mon Jan 12 18:43:34 2015 (r277084) @@ -93,7 +93,7 @@ #include "i40e_type.h" #include "i40e_prototype.h" -#ifdef IXL_DEBUG +#if defined(IXL_DEBUG) || defined(IXL_DEBUG_SYSCTL) #include #define MAC_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x" @@ -101,7 +101,13 @@ (mac_addr)[0], (mac_addr)[1], (mac_addr)[2], (mac_addr)[3], \ (mac_addr)[4], (mac_addr)[5] #define ON_OFF_STR(is_set) ((is_set) ? "On" : "Off") +#endif /* IXL_DEBUG || IXL_DEBUG_SYSCTL */ +#ifdef IXL_DEBUG +/* Enable debug sysctls */ +#ifndef IXL_DEBUG_SYSCTL +#define IXL_DEBUG_SYSCTL 1 +#endif #define _DBG_PRINTF(S, ...) printf("%s: " S "\n", __func__, ##__VA_ARGS__) #define _DEV_DBG_PRINTF(dev, S, ...) device_printf(dev, "%s: " S "\n", __func__, ##__VA_ARGS__) @@ -128,7 +134,7 @@ #define HW_DEBUGOUT(...) if (DEBUG_HW) _DBG_PRINTF(__VA_ARGS__) -#else +#else /* no IXL_DEBUG */ #define DEBUG_INIT 0 #define DEBUG_IOCTL 0 #define DEBUG_HW 0 @@ -144,7 +150,7 @@ #define IOCTL_DBG_IF2(...) #define IOCTL_DBG_IF(...) #define HW_DEBUGOUT(...) -#endif +#endif /* IXL_DEBUG */ /* Tunables */ @@ -214,6 +220,7 @@ #define IXL_MAX_TSO_SEGS 66 #define IXL_SPARSE_CHAIN 6 #define IXL_QUEUE_HUNG 0x80000000 +#define IXL_KEYSZ 10 /* ERJ: hardware can support ~1.5k filters between all functions */ #define IXL_MAX_FILTERS 256 Modified: head/sys/dev/ixl/ixl_txrx.c ============================================================================== --- head/sys/dev/ixl/ixl_txrx.c Mon Jan 12 18:38:09 2015 (r277083) +++ head/sys/dev/ixl/ixl_txrx.c Mon Jan 12 18:43:34 2015 (r277084) @@ -66,8 +66,8 @@ ixl_mq_start(struct ifnet *ifp, struct m struct tx_ring *txr; int err, i; - /* check if flowid is set */ - if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) + /* Which queue to use */ + if ((m->m_flags & M_FLOWID) != 0) i = m->m_pkthdr.flowid % vsi->num_queues; else i = curcpu % vsi->num_queues; @@ -1089,8 +1089,8 @@ int ixl_init_rx_ring(struct ixl_queue *que) { struct rx_ring *rxr = &que->rxr; - struct ixl_vsi *vsi = que->vsi; #if defined(INET6) || defined(INET) + struct ixl_vsi *vsi = que->vsi; struct ifnet *ifp = vsi->ifp; struct lro_ctrl *lro = &rxr->lro; #endif @@ -1543,7 +1543,7 @@ ixl_rxeof(struct ixl_queue *que, int cou if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) ixl_rx_checksum(sendmp, status, error, ptype); sendmp->m_pkthdr.flowid = que->msix; - M_HASHTYPE_SET(sendmp, M_HASHTYPE_OPAQUE); + sendmp->m_flags |= M_FLOWID; } next_desc: bus_dmamap_sync(rxr->dma.tag, rxr->dma.map, Modified: head/sys/modules/ixl/Makefile ============================================================================== --- head/sys/modules/ixl/Makefile Mon Jan 12 18:38:09 2015 (r277083) +++ head/sys/modules/ixl/Makefile Mon Jan 12 18:43:34 2015 (r277084) @@ -4,7 +4,7 @@ KMOD = if_ixl SRCS = device_if.h bus_if.h pci_if.h opt_bdg.h -SRCS += opt_inet.h opt_inet6.h +SRCS += opt_inet.h opt_inet6.h opt_rss.h SRCS += if_ixl.c ixl_txrx.c i40e_osdep.c # Shared source Modified: head/sys/modules/ixlv/Makefile ============================================================================== --- head/sys/modules/ixlv/Makefile Mon Jan 12 18:38:09 2015 (r277083) +++ head/sys/modules/ixlv/Makefile Mon Jan 12 18:43:34 2015 (r277084) @@ -4,7 +4,7 @@ KMOD = if_ixlv SRCS = device_if.h bus_if.h pci_if.h opt_bdg.h -SRCS += opt_inet.h opt_inet6.h +SRCS += opt_inet.h opt_inet6.h opt_rss.h SRCS += if_ixlv.c ixlvc.c ixl_txrx.c i40e_osdep.c # Shared source