Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8df29145 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'netdev_page_frags'



Alexander Duyck says:

====================
Refactor netdev page frags and move them into mm/

This patch series addresses several things.

First I found an issue in the performance of the pfmemalloc check from
build_skb.  To work around it I have provided a cached copy of pfmemalloc
to be used in __netdev_alloc_skb and __napi_alloc_skb.

Second I moved the page fragment allocation logic into the mm tree and
added functionality for freeing page fragments.  I had to fix igb before I
could do this as it was using a reference to NETDEV_FRAG_PAGE_MAX_SIZE
incorrectly.

Finally I went through and replaced all of the duplicate code that was
calling put_page and replaced it with calls to skb_free_frag.

With these changes in place a simple receive and drop test increased from a
packet rate of 8.9Mpps to 9.8Mpps.  The gains breakdown as follows:

8.9Mpps	Before			9.8Mpps	After
------------------------	------------------------
7.8%	put_compound_page	9.1%	__free_page_frag
3.9%	skb_free_head
1.1%	put_page

4.9%	build_skb		3.8%	__napi_alloc_skb
2.5%	__alloc_rx_skb
1.9%	__napi_alloc_skb
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b396cca6 e51423d9
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -662,7 +662,7 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
static void bnx2x_frag_free(const struct bnx2x_fastpath *fp, void *data)
{
	if (fp->rx_frag_size)
		put_page(virt_to_head_page(data));
		skb_free_frag(data);
	else
		kfree(data);
}
+1 −1
Original line number Diff line number Diff line
@@ -6618,7 +6618,7 @@ static void tg3_tx(struct tg3_napi *tnapi)
static void tg3_frag_free(bool is_frag, void *data)
{
	if (is_frag)
		put_page(virt_to_head_page(data));
		skb_free_frag(data);
	else
		kfree(data);
}
+1 −1
Original line number Diff line number Diff line
@@ -798,7 +798,7 @@ static void hip04_free_ring(struct net_device *ndev, struct device *d)

	for (i = 0; i < RX_DESC_NUM; i++)
		if (priv->rx_buf[i])
			put_page(virt_to_head_page(priv->rx_buf[i]));
			skb_free_frag(priv->rx_buf[i]);

	for (i = 0; i < TX_DESC_NUM; i++)
		if (priv->tx_skb[i])
+7 −12
Original line number Diff line number Diff line
@@ -2079,11 +2079,6 @@ static void *e1000_alloc_frag(const struct e1000_adapter *a)
	return data;
}

static void e1000_free_frag(const void *data)
{
	put_page(virt_to_head_page(data));
}

/**
 * e1000_clean_rx_ring - Free Rx Buffers per Queue
 * @adapter: board private structure
@@ -2107,7 +2102,7 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter,
						 adapter->rx_buffer_len,
						 DMA_FROM_DEVICE);
			if (buffer_info->rxbuf.data) {
				e1000_free_frag(buffer_info->rxbuf.data);
				skb_free_frag(buffer_info->rxbuf.data);
				buffer_info->rxbuf.data = NULL;
			}
		} else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq) {
@@ -4594,28 +4589,28 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
			data = e1000_alloc_frag(adapter);
			/* Failed allocation, critical failure */
			if (!data) {
				e1000_free_frag(olddata);
				skb_free_frag(olddata);
				adapter->alloc_rx_buff_failed++;
				break;
			}

			if (!e1000_check_64k_bound(adapter, data, bufsz)) {
				/* give up */
				e1000_free_frag(data);
				e1000_free_frag(olddata);
				skb_free_frag(data);
				skb_free_frag(olddata);
				adapter->alloc_rx_buff_failed++;
				break;
			}

			/* Use new allocation */
			e1000_free_frag(olddata);
			skb_free_frag(olddata);
		}
		buffer_info->dma = dma_map_single(&pdev->dev,
						  data,
						  adapter->rx_buffer_len,
						  DMA_FROM_DEVICE);
		if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
			e1000_free_frag(data);
			skb_free_frag(data);
			buffer_info->dma = 0;
			adapter->alloc_rx_buff_failed++;
			break;
@@ -4637,7 +4632,7 @@ static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter,
					 adapter->rx_buffer_len,
					 DMA_FROM_DEVICE);

			e1000_free_frag(data);
			skb_free_frag(data);
			buffer_info->rxbuf.data = NULL;
			buffer_info->dma = 0;

+3 −8
Original line number Diff line number Diff line
@@ -4974,6 +4974,7 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
	struct igb_tx_buffer *first;
	int tso;
	u32 tx_flags = 0;
	unsigned short f;
	u16 count = TXD_USE_COUNT(skb_headlen(skb));
	__be16 protocol = vlan_get_protocol(skb);
	u8 hdr_len = 0;
@@ -4984,14 +4985,8 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
	 *       + 1 desc for context descriptor,
	 * otherwise try next time
	 */
	if (NETDEV_FRAG_PAGE_MAX_SIZE > IGB_MAX_DATA_PER_TXD) {
		unsigned short f;

	for (f = 0; f < skb_shinfo(skb)->nr_frags; f++)
		count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size);
	} else {
		count += skb_shinfo(skb)->nr_frags;
	}

	if (igb_maybe_stop_tx(tx_ring, count + 3)) {
		/* this is a hard error */
Loading