Commit d53d4dcc authored by Maciej Fijalkowski's avatar Maciej Fijalkowski Committed by Tony Nguyen
Browse files

ice: fix truesize operations for PAGE_SIZE >= 8192



When working on multi-buffer packet on arch that has PAGE_SIZE >= 8192,
truesize is calculated and stored in xdp_buff::frame_sz per each
processed Rx buffer. This means that frame_sz will contain the truesize
based on last received buffer, but commit 1dc1a7e7 ("ice:
Centrallize Rx buffer recycling") assumed this value will be constant
for each buffer, which breaks the page recycling scheme and mess up the
way we update the page::page_offset.

To fix this, let us work on constant truesize when PAGE_SIZE >= 8192
instead of basing this on size of a packet read from Rx descriptor. This
way we can simplify the code and avoid calculating truesize per each
received frame and on top of that when using
xdp_update_skb_shared_info(), current formula for truesize update will
be valid.

This means ice_rx_frame_truesize() can be removed altogether.
Furthermore, first call to it within ice_clean_rx_irq() for 4k PAGE_SIZE
was redundant as xdp_buff::frame_sz is initialized via xdp_init_buff()
in ice_vsi_cfg_rxq(). This should have been removed at the point where
xdp_buff struct started to be a member of ice_rx_ring and it was no
longer a stack based variable.

There are two fixes tags as my understanding is that the first one
exposed us to broken truesize and page_offset handling and then second
introduced broken skb_shared_info update in ice_{construct,build}_skb().

Reported-and-tested-by: default avatarLuiz Capitulino <luizcap@redhat.com>
Closes: https://lore.kernel.org/netdev/8f9e2a5c-fd30-4206-9311-946a06d031bb@redhat.com/


Fixes: 1dc1a7e7 ("ice: Centrallize Rx buffer recycling")
Fixes: 2fba7dc5 ("ice: Add support for XDP multi-buffer on Rx side")
Signed-off-by: default avatarMaciej Fijalkowski <maciej.fijalkowski@intel.com>
Tested-by: Chandan Kumar Rout <chandanx.rout@intel.com> (A Contingent Worker at Intel)
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent b966ad83
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -512,6 +512,25 @@ static void ice_xsk_pool_fill_cb(struct ice_rx_ring *ring)
	xsk_pool_fill_cb(ring->xsk_pool, &desc);
}

/**
 * ice_get_frame_sz - calculate xdp_buff::frame_sz
 * @rx_ring: the ring being configured
 *
 * Return frame size based on underlying PAGE_SIZE
 */
static unsigned int ice_get_frame_sz(struct ice_rx_ring *rx_ring)
{
	unsigned int frame_sz;

#if (PAGE_SIZE >= 8192)
	frame_sz = rx_ring->rx_buf_len;
#else
	frame_sz = ice_rx_pg_size(rx_ring) / 2;
#endif

	return frame_sz;
}

/**
 * ice_vsi_cfg_rxq - Configure an Rx queue
 * @ring: the ring being configured
@@ -576,7 +595,7 @@ static int ice_vsi_cfg_rxq(struct ice_rx_ring *ring)
		}
	}

	xdp_init_buff(&ring->xdp, ice_rx_pg_size(ring) / 2, &ring->xdp_rxq);
	xdp_init_buff(&ring->xdp, ice_get_frame_sz(ring), &ring->xdp_rxq);
	ring->xdp.data = NULL;
	ring->xdp_ext.pkt_ctx = &ring->pkt_ctx;
	err = ice_setup_rx_ctx(ring);
+0 −33
Original line number Diff line number Diff line
@@ -521,30 +521,6 @@ int ice_setup_rx_ring(struct ice_rx_ring *rx_ring)
	return -ENOMEM;
}

/**
 * ice_rx_frame_truesize
 * @rx_ring: ptr to Rx ring
 * @size: size
 *
 * calculate the truesize with taking into the account PAGE_SIZE of
 * underlying arch
 */
static unsigned int
ice_rx_frame_truesize(struct ice_rx_ring *rx_ring, const unsigned int size)
{
	unsigned int truesize;

#if (PAGE_SIZE < 8192)
	truesize = ice_rx_pg_size(rx_ring) / 2; /* Must be power-of-2 */
#else
	truesize = rx_ring->rx_offset ?
		SKB_DATA_ALIGN(rx_ring->rx_offset + size) +
		SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
		SKB_DATA_ALIGN(size);
#endif
	return truesize;
}

/**
 * ice_run_xdp - Executes an XDP program on initialized xdp_buff
 * @rx_ring: Rx ring
@@ -1154,11 +1130,6 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
	bool failure;
	u32 first;

	/* Frame size depend on rx_ring setup when PAGE_SIZE=4K */
#if (PAGE_SIZE < 8192)
	xdp->frame_sz = ice_rx_frame_truesize(rx_ring, 0);
#endif

	xdp_prog = READ_ONCE(rx_ring->xdp_prog);
	if (xdp_prog) {
		xdp_ring = rx_ring->xdp_ring;
@@ -1217,10 +1188,6 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
			hard_start = page_address(rx_buf->page) + rx_buf->page_offset -
				     offset;
			xdp_prepare_buff(xdp, hard_start, offset, size, !!offset);
#if (PAGE_SIZE > 4096)
			/* At larger PAGE_SIZE, frame_sz depend on len size */
			xdp->frame_sz = ice_rx_frame_truesize(rx_ring, size);
#endif
			xdp_buff_clear_frags_flag(xdp);
		} else if (ice_add_xdp_frag(rx_ring, xdp, rx_buf, size)) {
			break;