Skip to content

Commit 1793668

Browse files
Alexander DuyckJeff Kirsher
authored andcommitted
i40e/i40evf: Update code to better handle incrementing page count
Update the driver code so that we do bulk updates of the page reference count instead of just incrementing it by one reference at a time. The advantage to doing this is that we cut down on atomic operations and this in turn should give us a slight improvement in cycles per packet. In addition if we eventually move this over to using build_skb the gains will be more noticeable. I also found and fixed a store forwarding stall from where we were assigning "*new_buff = *old_buff". By breaking it up into individual copies we can avoid this and as a result the performance is slightly improved. Change-ID: I1d3880dece4133eca3c32423b04a5467321ccc52 Signed-off-by: Alexander Duyck <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 402a5bc commit 1793668

File tree

4 files changed

+48
-15
lines changed

4 files changed

+48
-15
lines changed

drivers/net/ethernet/intel/i40e/i40e_txrx.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ void i40e_clean_rx_ring(struct i40e_ring *rx_ring)
11541154
PAGE_SIZE,
11551155
DMA_FROM_DEVICE,
11561156
I40E_RX_DMA_ATTR);
1157-
__free_pages(rx_bi->page, 0);
1157+
__page_frag_cache_drain(rx_bi->page, rx_bi->pagecnt_bias);
11581158

11591159
rx_bi->page = NULL;
11601160
rx_bi->page_offset = 0;
@@ -1299,6 +1299,7 @@ static bool i40e_alloc_mapped_page(struct i40e_ring *rx_ring,
12991299
bi->dma = dma;
13001300
bi->page = page;
13011301
bi->page_offset = 0;
1302+
bi->pagecnt_bias = 1;
13021303

13031304
return true;
13041305
}
@@ -1604,7 +1605,10 @@ static void i40e_reuse_rx_page(struct i40e_ring *rx_ring,
16041605
rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
16051606

16061607
/* transfer page from old buffer to new buffer */
1607-
*new_buff = *old_buff;
1608+
new_buff->dma = old_buff->dma;
1609+
new_buff->page = old_buff->page;
1610+
new_buff->page_offset = old_buff->page_offset;
1611+
new_buff->pagecnt_bias = old_buff->pagecnt_bias;
16081612
}
16091613

16101614
/**
@@ -1656,14 +1660,15 @@ static bool i40e_can_reuse_rx_page(struct i40e_rx_buffer *rx_buffer,
16561660
#if (PAGE_SIZE >= 8192)
16571661
unsigned int last_offset = PAGE_SIZE - I40E_RXBUFFER_2048;
16581662
#endif
1663+
unsigned int pagecnt_bias = rx_buffer->pagecnt_bias--;
16591664

16601665
/* Is any reuse possible? */
16611666
if (unlikely(!i40e_page_is_reusable(page)))
16621667
return false;
16631668

16641669
#if (PAGE_SIZE < 8192)
16651670
/* if we are only owner of page we can reuse it */
1666-
if (unlikely(page_count(page) != 1))
1671+
if (unlikely(page_count(page) != pagecnt_bias))
16671672
return false;
16681673

16691674
/* flip page offset to other buffer */
@@ -1676,9 +1681,14 @@ static bool i40e_can_reuse_rx_page(struct i40e_rx_buffer *rx_buffer,
16761681
return false;
16771682
#endif
16781683

1679-
/* Inc ref count on page before passing it up to the stack */
1680-
get_page(page);
1681-
1684+
/* If we have drained the page fragment pool we need to update
1685+
* the pagecnt_bias and page count so that we fully restock the
1686+
* number of references the driver holds.
1687+
*/
1688+
if (unlikely(pagecnt_bias == 1)) {
1689+
page_ref_add(page, USHRT_MAX);
1690+
rx_buffer->pagecnt_bias = USHRT_MAX;
1691+
}
16821692
return true;
16831693
}
16841694

@@ -1725,7 +1735,6 @@ static bool i40e_add_rx_frag(struct i40e_ring *rx_ring,
17251735
return true;
17261736

17271737
/* this page cannot be reused so discard it */
1728-
__free_pages(page, 0);
17291738
return false;
17301739
}
17311740

@@ -1819,6 +1828,8 @@ struct sk_buff *i40e_fetch_rx_buffer(struct i40e_ring *rx_ring,
18191828
/* we are not reusing the buffer so unmap it */
18201829
dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma, PAGE_SIZE,
18211830
DMA_FROM_DEVICE, I40E_RX_DMA_ATTR);
1831+
__page_frag_cache_drain(rx_buffer->page,
1832+
rx_buffer->pagecnt_bias);
18221833
}
18231834

18241835
/* clear contents of buffer_info */

drivers/net/ethernet/intel/i40e/i40e_txrx.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,12 @@ struct i40e_tx_buffer {
258258
struct i40e_rx_buffer {
259259
dma_addr_t dma;
260260
struct page *page;
261-
unsigned int page_offset;
261+
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
262+
__u32 page_offset;
263+
#else
264+
__u16 page_offset;
265+
#endif
266+
__u16 pagecnt_bias;
262267
};
263268

264269
struct i40e_queue_stats {

drivers/net/ethernet/intel/i40evf/i40e_txrx.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ void i40evf_clean_rx_ring(struct i40e_ring *rx_ring)
526526
PAGE_SIZE,
527527
DMA_FROM_DEVICE,
528528
I40E_RX_DMA_ATTR);
529-
__free_pages(rx_bi->page, 0);
529+
__page_frag_cache_drain(rx_bi->page, rx_bi->pagecnt_bias);
530530

531531
rx_bi->page = NULL;
532532
rx_bi->page_offset = 0;
@@ -671,6 +671,7 @@ static bool i40e_alloc_mapped_page(struct i40e_ring *rx_ring,
671671
bi->dma = dma;
672672
bi->page = page;
673673
bi->page_offset = 0;
674+
bi->pagecnt_bias = 1;
674675

675676
return true;
676677
}
@@ -966,7 +967,10 @@ static void i40e_reuse_rx_page(struct i40e_ring *rx_ring,
966967
rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
967968

968969
/* transfer page from old buffer to new buffer */
969-
*new_buff = *old_buff;
970+
new_buff->dma = old_buff->dma;
971+
new_buff->page = old_buff->page;
972+
new_buff->page_offset = old_buff->page_offset;
973+
new_buff->pagecnt_bias = old_buff->pagecnt_bias;
970974
}
971975

972976
/**
@@ -1018,14 +1022,15 @@ static bool i40e_can_reuse_rx_page(struct i40e_rx_buffer *rx_buffer,
10181022
#if (PAGE_SIZE >= 8192)
10191023
unsigned int last_offset = PAGE_SIZE - I40E_RXBUFFER_2048;
10201024
#endif
1025+
unsigned int pagecnt_bias = rx_buffer->pagecnt_bias--;
10211026

10221027
/* Is any reuse possible? */
10231028
if (unlikely(!i40e_page_is_reusable(page)))
10241029
return false;
10251030

10261031
#if (PAGE_SIZE < 8192)
10271032
/* if we are only owner of page we can reuse it */
1028-
if (unlikely(page_count(page) != 1))
1033+
if (unlikely(page_count(page) != pagecnt_bias))
10291034
return false;
10301035

10311036
/* flip page offset to other buffer */
@@ -1038,8 +1043,14 @@ static bool i40e_can_reuse_rx_page(struct i40e_rx_buffer *rx_buffer,
10381043
return false;
10391044
#endif
10401045

1041-
/* Inc ref count on page before passing it up to the stack */
1042-
get_page(page);
1046+
/* If we have drained the page fragment pool we need to update
1047+
* the pagecnt_bias and page count so that we fully restock the
1048+
* number of references the driver holds.
1049+
*/
1050+
if (unlikely(pagecnt_bias == 1)) {
1051+
page_ref_add(page, USHRT_MAX);
1052+
rx_buffer->pagecnt_bias = USHRT_MAX;
1053+
}
10431054

10441055
return true;
10451056
}
@@ -1087,7 +1098,6 @@ static bool i40e_add_rx_frag(struct i40e_ring *rx_ring,
10871098
return true;
10881099

10891100
/* this page cannot be reused so discard it */
1090-
__free_pages(page, 0);
10911101
return false;
10921102
}
10931103

@@ -1181,6 +1191,8 @@ struct sk_buff *i40evf_fetch_rx_buffer(struct i40e_ring *rx_ring,
11811191
/* we are not reusing the buffer so unmap it */
11821192
dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma, PAGE_SIZE,
11831193
DMA_FROM_DEVICE, I40E_RX_DMA_ATTR);
1194+
__page_frag_cache_drain(rx_buffer->page,
1195+
rx_buffer->pagecnt_bias);
11841196
}
11851197

11861198
/* clear contents of buffer_info */

drivers/net/ethernet/intel/i40evf/i40e_txrx.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,12 @@ struct i40e_tx_buffer {
244244
struct i40e_rx_buffer {
245245
dma_addr_t dma;
246246
struct page *page;
247-
unsigned int page_offset;
247+
#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536)
248+
__u32 page_offset;
249+
#else
250+
__u16 page_offset;
251+
#endif
252+
__u16 pagecnt_bias;
248253
};
249254

250255
struct i40e_queue_stats {

0 commit comments

Comments
 (0)