[Intel-wired-lan] [next PATCH v2 04/11] ixgbe: Update code to better handle incrementing page count
Alexander Duyck
alexander.duyck at gmail.com
Fri Feb 10 23:15:49 UTC 2017
On Fri, Feb 10, 2017 at 3:04 PM, John Fastabend
<john.fastabend at gmail.com> wrote:
> On 17-01-17 08:36 AM, Alexander Duyck wrote:
>> From: Alexander Duyck <alexander.h.duyck at intel.com>
>>
>> Batch the page count updates instead of doing them one at a time. By doing
>> this we can improve the overall performance as the atomic increment
>> operations can be expensive due to the fact that on x86 they are locked
>> operations which can cause stalls. By doing bulk updates we can
>> consolidate the stall which should help to improve the overall receive
>> performance.
>>
>
> [...]
>
>> struct ixgbe_queue_stats {
>> diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> index 8ee8fcf0fe21..34a5271a7b35 100644
>> --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
>> @@ -1602,6 +1602,7 @@ static bool ixgbe_alloc_mapped_page(struct ixgbe_ring *rx_ring,
>> bi->dma = dma;
>> bi->page = page;
>> bi->page_offset = 0;
>> + bi->pagecnt_bias = 1;
>
> I'm curious why set pagecnt_bias to '1' here but in the ixgbe_can_reuse_rx_page
> path set it to USHRT_MAX? Any reason not to just always use the USHRT_MAX
> scheme.
Because I wanted to defer having to use page_ref_add until I know I am
going to reuse the page. The allocation can be from a memory pool
that is reserved for emergency allocations or could be from the wrong
node. In such a case we would take a penalty if we are having to
perform an atomic add and subtract from the page count. By setting it
to 1 we reflect that for now we hold the only reference to the page
and we are waiting to see if it is reusable.
>>
>> return true;
>> }
>> @@ -1960,13 +1961,15 @@ static bool ixgbe_can_reuse_rx_page(struct ixgbe_ring *rx_ring,
>> unsigned int last_offset = ixgbe_rx_pg_size(rx_ring) -
>> ixgbe_rx_bufsz(rx_ring);
>> #endif
>> + unsigned int pagecnt_bias = rx_buffer->pagecnt_bias--;
>> +
>> /* avoid re-using remote pages */
>> if (unlikely(ixgbe_page_is_reserved(page)))
>> return false;
>>
>> #if (PAGE_SIZE < 8192)
>> /* if we are only owner of page we can reuse it */
>> - if (unlikely(page_count(page) != 1))
>> + if (unlikely(page_count(page) != pagecnt_bias))
>> return false;
>>
>> /* flip page offset to other buffer */
>> @@ -1979,10 +1982,14 @@ static bool ixgbe_can_reuse_rx_page(struct ixgbe_ring *rx_ring,
>> return false;
>> #endif
>>
>> - /* Even if we own the page, we are not allowed to use atomic_set()
>> - * This would break get_page_unless_zero() users.
>> + /* If we have drained the page fragment pool we need to update
>> + * the pagecnt_bias and page count so that we fully restock the
>> + * number of references the driver holds.
>> */
>> - page_ref_inc(page);
>> + if (unlikely(pagecnt_bias == 1)) {
>> + page_ref_add(page, USHRT_MAX);
>> + rx_buffer->pagecnt_bias = USHRT_MAX;
>> + }
>>
>> return true;
>> }
>
> Otherwise patch looks good to me. Although it took me a moment to catch the
> ref_add/pagecnt_bias usage here.
Right. What we are doing here is dealing with the first real priming
of the pagecnt_bias. We had set it to one when the page count was
one, now we are forking things a bit and giving the stack one instance
of the reference count and filling the pagecnt_bias to the maximum
value supported assuming a u32 system. The value for pagecnt_bias
will always shrink from this point. It might bounce by 1 if we are
doing a copy-break but it should never exceed USHRT_MAX.
The advantage of doing it here is that this is after the
page_is_reserved check so we are are essentially just taking this hit
in place of having to do another page allocation versus adding it onto
a page allocation if we had done this earlier.
> Acked-by: John Fastabend <john.r.fastabend at intel.com>
>
More information about the Intel-wired-lan
mailing list