summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/fm10k/fm10k_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/intel/fm10k/fm10k_main.c')
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_main.c52
1 files changed, 40 insertions, 12 deletions
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
index 21d49550935e..d422cd187101 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
@@ -1363,7 +1363,7 @@ static bool fm10k_clean_tx_irq(struct fm10k_q_vector *q_vector,
**/
static void fm10k_update_itr(struct fm10k_ring_container *ring_container)
{
- unsigned int avg_wire_size, packets;
+ unsigned int avg_wire_size, packets, itr_round;
/* Only update ITR if we are using adaptive setting */
if (!ITR_IS_ADAPTIVE(ring_container->itr))
@@ -1375,18 +1375,44 @@ static void fm10k_update_itr(struct fm10k_ring_container *ring_container)
avg_wire_size = ring_container->total_bytes / packets;
- /* Add 24 bytes to size to account for CRC, preamble, and gap */
- avg_wire_size += 24;
-
- /* Don't starve jumbo frames */
- if (avg_wire_size > 3000)
- avg_wire_size = 3000;
+ /* The following is a crude approximation of:
+ * wmem_default / (size + overhead) = desired_pkts_per_int
+ * rate / bits_per_byte / (size + ethernet overhead) = pkt_rate
+ * (desired_pkt_rate / pkt_rate) * usecs_per_sec = ITR value
+ *
+ * Assuming wmem_default is 212992 and overhead is 640 bytes per
+ * packet, (256 skb, 64 headroom, 320 shared info), we can reduce the
+ * formula down to
+ *
+ * (34 * (size + 24)) / (size + 640) = ITR
+ *
+ * We first do some math on the packet size and then finally bitshift
+ * by 8 after rounding up. We also have to account for PCIe link speed
+ * difference as ITR scales based on this.
+ */
+ if (avg_wire_size <= 360) {
+ /* Start at 250K ints/sec and gradually drop to 77K ints/sec */
+ avg_wire_size *= 8;
+ avg_wire_size += 376;
+ } else if (avg_wire_size <= 1152) {
+ /* 77K ints/sec to 45K ints/sec */
+ avg_wire_size *= 3;
+ avg_wire_size += 2176;
+ } else if (avg_wire_size <= 1920) {
+ /* 45K ints/sec to 38K ints/sec */
+ avg_wire_size += 4480;
+ } else {
+ /* plateau at a limit of 38K ints/sec */
+ avg_wire_size = 6656;
+ }
- /* Give a little boost to mid-size frames */
- if ((avg_wire_size > 300) && (avg_wire_size < 1200))
- avg_wire_size /= 3;
- else
- avg_wire_size /= 2;
+ /* Perform final bitshift for division after rounding up to ensure
+ * that the calculation will never get below a 1. The bit shift
+ * accounts for changes in the ITR due to PCIe link speed.
+ */
+ itr_round = ACCESS_ONCE(ring_container->itr_scale) + 8;
+ avg_wire_size += (1 << itr_round) - 1;
+ avg_wire_size >>= itr_round;
/* write back value and retain adaptive flag */
ring_container->itr = avg_wire_size | FM10K_ITR_ADAPTIVE;
@@ -1604,6 +1630,7 @@ static int fm10k_alloc_q_vector(struct fm10k_intfc *interface,
q_vector->tx.ring = ring;
q_vector->tx.work_limit = FM10K_DEFAULT_TX_WORK;
q_vector->tx.itr = interface->tx_itr;
+ q_vector->tx.itr_scale = interface->hw.mac.itr_scale;
q_vector->tx.count = txr_count;
while (txr_count) {
@@ -1632,6 +1659,7 @@ static int fm10k_alloc_q_vector(struct fm10k_intfc *interface,
/* save Rx ring container info */
q_vector->rx.ring = ring;
q_vector->rx.itr = interface->rx_itr;
+ q_vector->rx.itr_scale = interface->hw.mac.itr_scale;
q_vector->rx.count = rxr_count;
while (rxr_count) {