mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-12 05:48:39 +08:00
net: libwx: fix memory leak on free page
ifconfig ethx up, will set page->refcount larger than 1,
and then ifconfig ethx down, calling __page_frag_cache_drain()
to free pages, it is not compatible with page pool.
So deleting codes which changing page->refcount.
Fixes: 3c47e8ae11
("net: libwx: Support to receive packets in NAPI")
Signed-off-by: duanqiangwen <duanqiangwen@net-swift.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0225191a76
commit
738b54b9b6
@ -160,60 +160,6 @@ static __le32 wx_test_staterr(union wx_rx_desc *rx_desc,
|
||||
return rx_desc->wb.upper.status_error & cpu_to_le32(stat_err_bits);
|
||||
}
|
||||
|
||||
static bool wx_can_reuse_rx_page(struct wx_rx_buffer *rx_buffer,
|
||||
int rx_buffer_pgcnt)
|
||||
{
|
||||
unsigned int pagecnt_bias = rx_buffer->pagecnt_bias;
|
||||
struct page *page = rx_buffer->page;
|
||||
|
||||
/* avoid re-using remote and pfmemalloc pages */
|
||||
if (!dev_page_is_reusable(page))
|
||||
return false;
|
||||
|
||||
#if (PAGE_SIZE < 8192)
|
||||
/* if we are only owner of page we can reuse it */
|
||||
if (unlikely((rx_buffer_pgcnt - pagecnt_bias) > 1))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
if (unlikely(pagecnt_bias == 1)) {
|
||||
page_ref_add(page, USHRT_MAX - 1);
|
||||
rx_buffer->pagecnt_bias = USHRT_MAX;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* wx_reuse_rx_page - page flip buffer and store it back on the ring
|
||||
* @rx_ring: rx descriptor ring to store buffers on
|
||||
* @old_buff: donor buffer to have page reused
|
||||
*
|
||||
* Synchronizes page for reuse by the adapter
|
||||
**/
|
||||
static void wx_reuse_rx_page(struct wx_ring *rx_ring,
|
||||
struct wx_rx_buffer *old_buff)
|
||||
{
|
||||
u16 nta = rx_ring->next_to_alloc;
|
||||
struct wx_rx_buffer *new_buff;
|
||||
|
||||
new_buff = &rx_ring->rx_buffer_info[nta];
|
||||
|
||||
/* update, and store next to alloc */
|
||||
nta++;
|
||||
rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
|
||||
|
||||
/* transfer page from old buffer to new buffer */
|
||||
new_buff->page = old_buff->page;
|
||||
new_buff->page_dma = old_buff->page_dma;
|
||||
new_buff->page_offset = old_buff->page_offset;
|
||||
new_buff->pagecnt_bias = old_buff->pagecnt_bias;
|
||||
}
|
||||
|
||||
static void wx_dma_sync_frag(struct wx_ring *rx_ring,
|
||||
struct wx_rx_buffer *rx_buffer)
|
||||
{
|
||||
@ -270,8 +216,6 @@ static struct wx_rx_buffer *wx_get_rx_buffer(struct wx_ring *rx_ring,
|
||||
size,
|
||||
DMA_FROM_DEVICE);
|
||||
skip_sync:
|
||||
rx_buffer->pagecnt_bias--;
|
||||
|
||||
return rx_buffer;
|
||||
}
|
||||
|
||||
@ -280,19 +224,9 @@ static void wx_put_rx_buffer(struct wx_ring *rx_ring,
|
||||
struct sk_buff *skb,
|
||||
int rx_buffer_pgcnt)
|
||||
{
|
||||
if (wx_can_reuse_rx_page(rx_buffer, rx_buffer_pgcnt)) {
|
||||
/* hand second half of page back to the ring */
|
||||
wx_reuse_rx_page(rx_ring, rx_buffer);
|
||||
} else {
|
||||
if (!IS_ERR(skb) && WX_CB(skb)->dma == rx_buffer->dma)
|
||||
/* the page has been released from the ring */
|
||||
WX_CB(skb)->page_released = true;
|
||||
else
|
||||
page_pool_put_full_page(rx_ring->page_pool, rx_buffer->page, false);
|
||||
|
||||
__page_frag_cache_drain(rx_buffer->page,
|
||||
rx_buffer->pagecnt_bias);
|
||||
}
|
||||
if (!IS_ERR(skb) && WX_CB(skb)->dma == rx_buffer->dma)
|
||||
/* the page has been released from the ring */
|
||||
WX_CB(skb)->page_released = true;
|
||||
|
||||
/* clear contents of rx_buffer */
|
||||
rx_buffer->page = NULL;
|
||||
@ -335,11 +269,12 @@ static struct sk_buff *wx_build_skb(struct wx_ring *rx_ring,
|
||||
if (size <= WX_RXBUFFER_256) {
|
||||
memcpy(__skb_put(skb, size), page_addr,
|
||||
ALIGN(size, sizeof(long)));
|
||||
rx_buffer->pagecnt_bias++;
|
||||
|
||||
page_pool_put_full_page(rx_ring->page_pool, rx_buffer->page, true);
|
||||
return skb;
|
||||
}
|
||||
|
||||
skb_mark_for_recycle(skb);
|
||||
|
||||
if (!wx_test_staterr(rx_desc, WX_RXD_STAT_EOP))
|
||||
WX_CB(skb)->dma = rx_buffer->dma;
|
||||
|
||||
@ -382,8 +317,6 @@ static bool wx_alloc_mapped_page(struct wx_ring *rx_ring,
|
||||
bi->page_dma = dma;
|
||||
bi->page = page;
|
||||
bi->page_offset = 0;
|
||||
page_ref_add(page, USHRT_MAX - 1);
|
||||
bi->pagecnt_bias = USHRT_MAX;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -723,7 +656,6 @@ static int wx_clean_rx_irq(struct wx_q_vector *q_vector,
|
||||
/* exit if we failed to retrieve a buffer */
|
||||
if (!skb) {
|
||||
rx_ring->rx_stats.alloc_rx_buff_failed++;
|
||||
rx_buffer->pagecnt_bias++;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2248,8 +2180,6 @@ static void wx_clean_rx_ring(struct wx_ring *rx_ring)
|
||||
|
||||
/* free resources associated with mapping */
|
||||
page_pool_put_full_page(rx_ring->page_pool, rx_buffer->page, false);
|
||||
__page_frag_cache_drain(rx_buffer->page,
|
||||
rx_buffer->pagecnt_bias);
|
||||
|
||||
i++;
|
||||
rx_buffer++;
|
||||
|
@ -787,7 +787,6 @@ struct wx_rx_buffer {
|
||||
dma_addr_t page_dma;
|
||||
struct page *page;
|
||||
unsigned int page_offset;
|
||||
u16 pagecnt_bias;
|
||||
};
|
||||
|
||||
struct wx_queue_stats {
|
||||
|
Loading…
Reference in New Issue
Block a user