Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144976068
D4265.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
23 KB
Referenced Files
None
Subscribers
None
D4265.id.diff
View Options
Index: sys/dev/ixl/if_ixl.c
===================================================================
--- sys/dev/ixl/if_ixl.c
+++ sys/dev/ixl/if_ixl.c
@@ -37,10 +37,14 @@
#include "ixl.h"
#include "ixl_pf.h"
+#ifdef RSS
+#include <net/rss_config.h>
+#endif
+
/*********************************************************************
* Driver version
*********************************************************************/
-char ixl_driver_version[] = "1.2.8";
+char ixl_driver_version[] = "1.3.1";
/*********************************************************************
* PCI Device ID Table
@@ -174,7 +178,7 @@
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 +431,7 @@
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 +666,9 @@
/* 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 +1412,12 @@
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 +1732,10 @@
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 +1778,15 @@
"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 +1923,7 @@
/* 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 +1944,23 @@
}
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 +2027,12 @@
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 +2053,25 @@
"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 +2440,8 @@
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 +3101,6 @@
"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 +3183,45 @@
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_IPV6_EX)
+ set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6);
+ 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);
+#else
set_hena =
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) |
@@ -3151,7 +3234,7 @@
((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 +3245,19 @@
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 % vsi->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 +3495,7 @@
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 +3520,8 @@
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 +3570,7 @@
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 +3923,6 @@
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 +4449,15 @@
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 +4602,7 @@
}
-#ifdef IXL_DEBUG
+#ifdef IXL_DEBUG_SYSCTL
static int
ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS)
{
@@ -4630,6 +4711,16 @@
#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 +4738,7 @@
return (ENOMEM);
}
+ bzero(resp, sizeof(resp));
error = i40e_aq_get_switch_resource_alloc(hw, &num_entries,
resp,
IXL_SW_RES_SIZE,
@@ -4657,9 +4749,14 @@
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");
@@ -4847,5 +4944,5 @@
sbuf_delete(buf);
return error;
}
-#endif
+#endif /* IXL_DEBUG_SYSCTL */
Index: sys/dev/ixl/if_ixlv.c
===================================================================
--- sys/dev/ixl/if_ixlv.c
+++ sys/dev/ixl/if_ixlv.c
@@ -37,10 +37,14 @@
#include "ixl.h"
#include "ixlv.h"
+#ifdef RSS
+#include <net/rss_config.h>
+#endif
+
/*********************************************************************
* Driver version
*********************************************************************/
-char ixlv_driver_version[] = "1.1.18";
+char ixlv_driver_version[] = "1.2.1";
/*********************************************************************
* PCI Device ID Table
@@ -1161,7 +1165,11 @@
/* 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 +1189,26 @@
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 +1380,7 @@
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 +1401,25 @@
}
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 +2560,18 @@
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 +2580,32 @@
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_IPV6_EX)
+ set_hena |= ((u64)1 << I40E_FILTER_PCTYPE_FRAG_IPV6);
+ 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);
+#else
set_hena =
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
((u64)1 << I40E_FILTER_PCTYPE_NONF_IPV4_TCP) |
@@ -2556,7 +2618,7 @@
((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 +2626,26 @@
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 % vsi->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);
Index: sys/dev/ixl/ixl.h
===================================================================
--- sys/dev/ixl/ixl.h
+++ sys/dev/ixl/ixl.h
@@ -93,7 +93,7 @@
#include "i40e_type.h"
#include "i40e_prototype.h"
-#ifdef IXL_DEBUG
+#if defined(IXL_DEBUG) || defined(IXL_DEBUG_SYSCTL)
#include <sys/sbuf.h>
#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
Index: sys/dev/ixl/ixl_txrx.c
===================================================================
--- sys/dev/ixl/ixl_txrx.c
+++ sys/dev/ixl/ixl_txrx.c
@@ -42,6 +42,10 @@
#include "opt_inet6.h"
#include "ixl.h"
+#ifdef RSS
+#include <net/rss_config.h>
+#endif
+
/* Local Prototypes */
static void ixl_rx_checksum(struct mbuf *, u32, u32, u8);
static void ixl_refresh_mbufs(struct ixl_queue *, int);
@@ -65,14 +69,33 @@
struct ixl_queue *que;
struct tx_ring *txr;
int err, i;
+#ifdef RSS
+ u32 bucket_id;
+#endif
- /* check if flowid is set */
- if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE)
- i = m->m_pkthdr.flowid % vsi->num_queues;
- else
+ /*
+ ** Which queue to use:
+ **
+ ** When doing RSS, map it to the same outbound
+ ** queue as the incoming flow would be mapped to.
+ ** If everything is setup correctly, it should be
+ ** the same bucket that the current CPU we're on is.
+ */
+ if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) {
+#ifdef RSS
+ if (rss_hash2bucket(m->m_pkthdr.flowid,
+ M_HASHTYPE_GET(m), &bucket_id) == 0) {
+ i = bucket_id % vsi->num_queues;
+ } else
+#endif
+ i = m->m_pkthdr.flowid % vsi->num_queues;
+ } else
i = curcpu % vsi->num_queues;
-
- /* Check for a hung queue and pick alternative */
+ /*
+ ** This may not be perfect, but until something
+ ** better comes along it will keep from scheduling
+ ** on stalled queues.
+ */
if (((1 << i) & vsi->active_queues) == 0)
i = ffsl(vsi->active_queues);
@@ -1089,8 +1112,8 @@
ixl_init_rx_ring(struct ixl_queue *que)
{
struct rx_ring *rxr = &que->rxr;
-#if defined(INET6) || defined(INET)
struct ixl_vsi *vsi = que->vsi;
+#if defined(INET6) || defined(INET)
struct ifnet *ifp = vsi->ifp;
struct lro_ctrl *lro = &rxr->lro;
#endif
@@ -1345,6 +1368,63 @@
return;
}
+#ifdef RSS
+/*
+** ixl_ptype_to_hash: parse the packet type
+** to determine the appropriate hash.
+*/
+static inline int
+ixl_ptype_to_hash(u8 ptype)
+{
+ struct i40e_rx_ptype_decoded decoded;
+ u8 ex = 0;
+
+ decoded = decode_rx_desc_ptype(ptype);
+ ex = decoded.outer_frag;
+
+ if (!decoded.known)
+ return M_HASHTYPE_OPAQUE;
+
+ if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_L2)
+ return M_HASHTYPE_OPAQUE;
+
+ /* Note: anything that gets to this point is IP */
+ if (decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV6) {
+ switch (decoded.inner_prot) {
+ case I40E_RX_PTYPE_INNER_PROT_TCP:
+ if (ex)
+ return M_HASHTYPE_RSS_TCP_IPV6_EX;
+ else
+ return M_HASHTYPE_RSS_TCP_IPV6;
+ case I40E_RX_PTYPE_INNER_PROT_UDP:
+ if (ex)
+ return M_HASHTYPE_RSS_UDP_IPV6_EX;
+ else
+ return M_HASHTYPE_RSS_UDP_IPV6;
+ default:
+ if (ex)
+ return M_HASHTYPE_RSS_IPV6_EX;
+ else
+ return M_HASHTYPE_RSS_IPV6;
+ }
+ }
+ if (decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV4) {
+ switch (decoded.inner_prot) {
+ case I40E_RX_PTYPE_INNER_PROT_TCP:
+ return M_HASHTYPE_RSS_TCP_IPV4;
+ case I40E_RX_PTYPE_INNER_PROT_UDP:
+ if (ex)
+ return M_HASHTYPE_RSS_UDP_IPV4_EX;
+ else
+ return M_HASHTYPE_RSS_UDP_IPV4;
+ default:
+ return M_HASHTYPE_RSS_IPV4;
+ }
+ }
+ /* We should never get here!! */
+ return M_HASHTYPE_OPAQUE;
+}
+#endif /* RSS */
/*********************************************************************
*
@@ -1542,8 +1622,14 @@
rxr->bytes += sendmp->m_pkthdr.len;
if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
ixl_rx_checksum(sendmp, status, error, ptype);
+#ifdef RSS
+ sendmp->m_pkthdr.flowid =
+ le32toh(cur->wb.qword0.hi_dword.rss);
+ M_HASHTYPE_SET(sendmp, ixl_ptype_to_hash(ptype));
+#else
sendmp->m_pkthdr.flowid = que->msix;
M_HASHTYPE_SET(sendmp, M_HASHTYPE_OPAQUE);
+#endif
}
next_desc:
bus_dmamap_sync(rxr->dma.tag, rxr->dma.map,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 15, 4:15 PM (17 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28747715
Default Alt Text
D4265.id.diff (23 KB)
Attached To
Mode
D4265: MFC of RSS changes for Intel ix driver
Attached
Detach File
Event Timeline
Log In to Comment