In cases when synchronizing DMA operations is necessary, xsk_buff_alloc_batch() returns a single buffer instead of the requested count. Detect such situation when filling HW Rx ring in ZC driver and use xsk_buff_alloc() in a loop manner so that ring gets the buffers to be used.
Reported-and-tested-by: Dries De Winter <[email protected]> Fixes: db804cfc21e9 ("ice: Use the xsk batched rx allocation interface") Signed-off-by: Maciej Fijalkowski <[email protected]> --- drivers/net/ethernet/intel/ice/ice_xsk.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c index 240a7bec242b..889d0a5070d7 100644 --- a/drivers/net/ethernet/intel/ice/ice_xsk.c +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c @@ -449,7 +449,24 @@ static u16 ice_fill_rx_descs(struct xsk_buff_pool *pool, struct xdp_buff **xdp, u16 buffs; int i; + if (unlikely(!xsk_buff_can_alloc(pool, count))) + return 0; + buffs = xsk_buff_alloc_batch(pool, xdp, count); + /* fill the remainder part that batch API did not provide for us, + * this is usually the case for non-coherent systems that require DMA + * syncs + */ + for (; buffs < count; buffs++) { + struct xdp_buff *tmp; + + tmp = xsk_buff_alloc(pool); + if (unlikely(!tmp)) + goto free; + + xdp[buffs] = tmp; + } + for (i = 0; i < buffs; i++) { dma = xsk_buff_xdp_get_dma(*xdp); rx_desc->read.pkt_addr = cpu_to_le64(dma); @@ -465,6 +482,13 @@ static u16 ice_fill_rx_descs(struct xsk_buff_pool *pool, struct xdp_buff **xdp, } return buffs; + +free: + for (i = 0; i < buffs; i++) { + xsk_buff_free(*xdp); + xdp++; + } + return 0; } /** -- 2.34.1
