diff options
author | Robert Mustacchi <rm@joyent.com> | 2016-03-26 01:16:27 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2016-03-26 03:27:19 +0000 |
commit | cc232b4c9f3fcc562d4d54f56543d64cde892d27 (patch) | |
tree | 90ea5d0441e7408998e8ebce1f9c1e13ec7096d8 | |
parent | 20c6994efa1f64adce58694e09406aa80a7ad2e1 (diff) | |
download | illumos-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.7d | 19 | ||||
-rw-r--r-- | usr/src/uts/common/io/i40e/i40e_main.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/io/i40e/i40e_sw.h | 10 | ||||
-rw-r--r-- | usr/src/uts/common/io/i40e/i40e_transceiver.c | 13 |
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; |