[Intel-wired-lan] [next-queue v4 13/17] fm10k: Update adaptive ITR algorithm

Alexander Duyck alexander.duyck at gmail.com
Fri Oct 16 04:01:13 UTC 2015


On 10/15/2015 03:54 PM, Jacob Keller wrote:
> The existing adaptive ITR algorithm is overly restrictive. It throttles
> incorrectly for various traffic rates, and does not produce good
> performance. The algorithm now allows for more interrupts per second,
> and does some calculation to help improve for smaller packet loads. In
> addition, take into account the new itr_scale from the hardware which
> indicates how much to scale due to PCIe link speed.
>
> Reported-by: Matthew Vick <matthew.vick at intel.com>
> Reported-by: Alex Duyck <alexander.duyck at gmail.com>
> Signed-off-by: Jacob Keller <jacob.e.keller at intel.com>
> ---
>   drivers/net/ethernet/intel/fm10k/fm10k.h      |  1 +
>   drivers/net/ethernet/intel/fm10k/fm10k_main.c | 52 ++++++++++++++++++++-------
>   drivers/net/ethernet/intel/fm10k/fm10k_pci.c  |  6 ++--
>   3 files changed, 45 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h
> index a2484cb88d86..bdbb804a594f 100644
> --- a/drivers/net/ethernet/intel/fm10k/fm10k.h
> +++ b/drivers/net/ethernet/intel/fm10k/fm10k.h
> @@ -164,6 +164,7 @@ struct fm10k_ring_container {
>   	unsigned int total_packets;	/* total packets processed this int */
>   	u16 work_limit;			/* total work allowed per interrupt */
>   	u16 itr;			/* interrupt throttle rate value */
> +	u8 itr_scale;			/* ITR adjustment scaler based on PCI speed */
>   	u8 count;			/* total number of rings in vector */
>   };
>
> diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
> index 8207ee189600..8fd9a48433a0 100644
> --- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c
> +++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
> @@ -1367,7 +1367,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))
> @@ -1379,18 +1379,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;
> +	/* 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 333K ints/sec and gradually drop to 77K ints/sec */

I was just rechecking the math on this and realized there was a rounding 
error.  This actually generates 250K interrupts per second at the peak, 
not 333K.  I basically had rounded down to 3 instead of up to 4 when I 
calculated the value for 60 byte packets.

It's just the comment that needs to be changed.  The algorithm itself 
should still be good.  I wouldn't have said anything but based on 
Bruce's comment it looks like a v5 will probably be on the way so I 
figured I would mention it.

- Alex


More information about the Intel-wired-lan mailing list