summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2016-03-26 01:16:27 +0000
committerRobert Mustacchi <rm@joyent.com>2016-03-26 03:27:19 +0000
commitcc232b4c9f3fcc562d4d54f56543d64cde892d27 (patch)
tree90ea5d0441e7408998e8ebce1f9c1e13ec7096d8
parent20c6994efa1f64adce58694e09406aa80a7ad2e1 (diff)
downloadillumos-joyent-cc232b4c9f3fcc562d4d54f56543d64cde892d27.tar.gz
OS-5280 i40e tx hangs if entire ring fills before cleaning
Reviewed by: Joshua M. Clulow <jmc@joyent.com>
-rw-r--r--usr/src/man/man7d/i40e.7d19
-rw-r--r--usr/src/uts/common/io/i40e/i40e_main.c5
-rw-r--r--usr/src/uts/common/io/i40e/i40e_sw.h10
-rw-r--r--usr/src/uts/common/io/i40e/i40e_transceiver.c13
4 files changed, 42 insertions, 5 deletions
diff --git a/usr/src/man/man7d/i40e.7d b/usr/src/man/man7d/i40e.7d
index c9002143a6..0a8019ac9a 100644
--- a/usr/src/man/man7d/i40e.7d
+++ b/usr/src/man/man7d/i40e.7d
@@ -11,7 +11,7 @@
.\"
.\" Copyright 2016 Joyent, Inc.
.\"
-.Dd February 02, 2016
+.Dd March 25, 2016
.Dt I40E 7D
.Os
.Sh NAME
@@ -168,6 +168,23 @@ tune this value. Hardware requires that the ring size be a multiple of
32. The system will round up the set value to the nearest multiple of
32.
.Ed
+.It Sy tx_resched_threshold
+.Bd -filled -compact
+Minimum:
+.Sy 8 |
+Maximum:
+.Sy Variable
+.Ed
+.Bd -filled
+The
+.Sy tx_resched_threshold
+property determines the number of descriptors that must be available for
+a frame to be transmitted. The maximum is variable. It is dependent on
+the value of the
+.Sy tx_ring_size
+property. At least eight descriptors must be available for the device to
+function correctly.
+.Ed
.It Sy rx_limit_per_intr
.Bd -filled -compact
Minimum:
diff --git a/usr/src/uts/common/io/i40e/i40e_main.c b/usr/src/uts/common/io/i40e/i40e_main.c
index e8bac07eef..1d7c7c8676 100644
--- a/usr/src/uts/common/io/i40e/i40e_main.c
+++ b/usr/src/uts/common/io/i40e/i40e_main.c
@@ -1502,6 +1502,11 @@ i40e_init_properties(i40e_t *i40e)
I40E_DESC_ALIGN);
}
+ i40e->i40e_tx_block_thresh = i40e_get_prop(i40e, "tx_resched_threshold",
+ I40E_MIN_TX_BLOCK_THRESH,
+ i40e->i40e_tx_ring_size - I40E_TX_MAX_COOKIE,
+ I40E_DEF_TX_BLOCK_THRESH);
+
i40e->i40e_rx_ring_size = i40e_get_prop(i40e, "rx_ring_size",
I40E_MIN_RX_RING_SIZE, I40E_MAX_RX_RING_SIZE,
I40E_DEF_RX_RING_SIZE);
diff --git a/usr/src/uts/common/io/i40e/i40e_sw.h b/usr/src/uts/common/io/i40e/i40e_sw.h
index 3b045d6438..26e851176b 100644
--- a/usr/src/uts/common/io/i40e/i40e_sw.h
+++ b/usr/src/uts/common/io/i40e/i40e_sw.h
@@ -156,6 +156,15 @@ extern "C" {
#define I40E_TX_MAX_COOKIE 8
/*
+ * Sizing to determine the amount of available descriptors at which we'll
+ * consider ourselves blocked. Also, when we have these available, we'll then
+ * consider ourselves available to transmit to MAC again. Strictly speaking, the
+ * MAX is based on the ring size. The default sizing is based on ixgbe.
+ */
+#define I40E_MIN_TX_BLOCK_THRESH I40E_TX_MAX_COOKIE
+#define I40E_DEF_TX_BLOCK_THRESH I40E_MIN_TX_BLOCK_THRESH
+
+/*
* Resource sizing counts. There are various aspects of hardware where we may
* have some variable number of elements that we need to handle. Such as the
* hardware capabilities and switch capacities. We cannot know a priori how many
@@ -749,6 +758,7 @@ typedef struct i40e {
uint32_t i40e_rx_limit_per_intr;
uint32_t i40e_tx_ring_size;
uint32_t i40e_tx_buf_size;
+ uint32_t i40e_tx_block_thresh;
boolean_t i40e_tx_hcksum_enable;
/*
diff --git a/usr/src/uts/common/io/i40e/i40e_transceiver.c b/usr/src/uts/common/io/i40e/i40e_transceiver.c
index 9aa02286da..3c05a7cec3 100644
--- a/usr/src/uts/common/io/i40e/i40e_transceiver.c
+++ b/usr/src/uts/common/io/i40e/i40e_transceiver.c
@@ -1847,9 +1847,6 @@ i40e_tx_cleanup_ring(i40e_trqpair_t *itrq)
/*
* Because we should have shut down the chip at this point, it should be
* safe to just clean up all the entries between our head and tail.
- *
- * XXX This should probably just check I40E_QTX_ENA_QENA_REQ_MASK due to
- * stalls.
*/
#ifdef DEBUG
index = I40E_READ_REG(&itrq->itrq_i40e->i40e_hw_space,
@@ -1945,6 +1942,14 @@ i40e_tx_recycle_ring(i40e_trqpair_t *itrq)
itrq->itrq_desc_free += count;
ASSERT(itrq->itrq_desc_free <= itrq->itrq_tx_ring_size);
+ if (itrq->itrq_tx_blocked == B_TRUE &&
+ itrq->itrq_desc_free > i40e->i40e_tx_block_thresh) {
+ itrq->itrq_tx_blocked = B_FALSE;
+
+ mac_tx_ring_update(i40e->i40e_mac_hdl, itrq->itrq_mactxring);
+ itrq->itrq_txstat.itxs_num_unblocked.value.ui64++;
+ }
+
mutex_exit(&itrq->itrq_tx_lock);
}
@@ -2053,7 +2058,7 @@ i40e_ring_tx(void *arg, mblk_t *mp)
I40E_DMA_SYNC(&tcb->tcb_dma, DDI_DMA_SYNC_FORDEV);
mutex_enter(&itrq->itrq_tx_lock);
- if (itrq->itrq_desc_free < 1) {
+ if (itrq->itrq_desc_free < i40e->i40e_tx_block_thresh) {
txs->itxs_err_nodescs.value.ui64++;
mutex_exit(&itrq->itrq_tx_lock);
goto txfail;