Skip to content

Commit 3246a10

Browse files
mfijalkoborkmann
authored andcommitted
ice: Add support for XDP multi-buffer on Tx side
Similarly as for Rx side in previous patch, logic on XDP Tx in ice driver needs to be adjusted for multi-buffer support. Specifically, the way how HW Tx descriptors are produced and cleaned. Currently, XDP_TX works on strict ring boundaries, meaning it sets RS bit (on producer side) / looks up DD bit (on consumer/cleaning side) every quarter of the ring. It means that if for example multi buffer frame would span across the ring quarter boundary (say that frame consists of 4 frames and we start from 62 descriptor where ring is sized to 256 entries), RS bit would be produced in the middle of multi buffer frame, which would be a broken behavior as it needs to be set on the last descriptor of the frame. To make it work, set RS bit at the last descriptor from the batch of frames that XDP_TX action was used on and make the first entry remember the index of last descriptor with RS bit set. This way, cleaning side can take the index of descriptor with RS bit, look up DD bit's presence and clean from first entry to last. In order to clean up the code base introduce the common ice_set_rs_bit() which will return index of descriptor that got RS bit produced on so that standard driver can store this within proper ice_tx_buf and ZC driver can simply ignore return value. Co-developed-by: Martyna Szapar-Mudlaw <martyna.szapar-mudlaw@linux.intel.com> Signed-off-by: Martyna Szapar-Mudlaw <martyna.szapar-mudlaw@linux.intel.com> Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Alexander Lobakin <alexandr.lobakin@intel.com> Link: https://lore.kernel.org/bpf/20230131204506.219292-12-maciej.fijalkowski@intel.com
1 parent 2fba7dc commit 3246a10

File tree

5 files changed

+199
-96
lines changed

5 files changed

+199
-96
lines changed

drivers/net/ethernet/intel/ice/ice_txrx.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ ice_run_xdp(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
578578
case XDP_TX:
579579
if (static_branch_unlikely(&ice_xdp_locking_key))
580580
spin_lock(&xdp_ring->tx_lock);
581-
ret = ice_xmit_xdp_ring(xdp->data, xdp->data_end - xdp->data, xdp_ring);
581+
ret = __ice_xmit_xdp_ring(xdp, xdp_ring);
582582
if (static_branch_unlikely(&ice_xdp_locking_key))
583583
spin_unlock(&xdp_ring->tx_lock);
584584
if (ret == ICE_XDP_CONSUMED)
@@ -625,6 +625,7 @@ ice_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
625625
unsigned int queue_index = smp_processor_id();
626626
struct ice_vsi *vsi = np->vsi;
627627
struct ice_tx_ring *xdp_ring;
628+
struct ice_tx_buf *tx_buf;
628629
int nxmit = 0, i;
629630

630631
if (test_bit(ICE_VSI_DOWN, vsi->state))
@@ -647,16 +648,18 @@ ice_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
647648
xdp_ring = vsi->xdp_rings[queue_index];
648649
}
649650

651+
tx_buf = &xdp_ring->tx_buf[xdp_ring->next_to_use];
650652
for (i = 0; i < n; i++) {
651653
struct xdp_frame *xdpf = frames[i];
652654
int err;
653655

654-
err = ice_xmit_xdp_ring(xdpf->data, xdpf->len, xdp_ring);
656+
err = ice_xmit_xdp_ring(xdpf, xdp_ring);
655657
if (err != ICE_XDP_TX)
656658
break;
657659
nxmit++;
658660
}
659661

662+
tx_buf->rs_idx = ice_set_rs_bit(xdp_ring);
660663
if (unlikely(flags & XDP_XMIT_FLUSH))
661664
ice_xdp_ring_update_tail(xdp_ring);
662665

@@ -1136,6 +1139,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
11361139
u32 cnt = rx_ring->count;
11371140
u32 cached_ntc = ntc;
11381141
u32 xdp_xmit = 0;
1142+
u32 cached_ntu;
11391143
bool failure;
11401144
u32 first;
11411145

@@ -1145,8 +1149,10 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
11451149
#endif
11461150

11471151
xdp_prog = READ_ONCE(rx_ring->xdp_prog);
1148-
if (xdp_prog)
1152+
if (xdp_prog) {
11491153
xdp_ring = rx_ring->xdp_ring;
1154+
cached_ntu = xdp_ring->next_to_use;
1155+
}
11501156

11511157
/* start the loop to process Rx packets bounded by 'budget' */
11521158
while (likely(total_rx_pkts < (unsigned int)budget)) {
@@ -1295,7 +1301,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
12951301
failure = ice_alloc_rx_bufs(rx_ring, ICE_RX_DESC_UNUSED(rx_ring));
12961302

12971303
if (xdp_xmit)
1298-
ice_finalize_xdp_rx(xdp_ring, xdp_xmit);
1304+
ice_finalize_xdp_rx(xdp_ring, xdp_xmit, cached_ntu);
12991305

13001306
if (rx_ring->ring_stats)
13011307
ice_update_rx_ring_stats(rx_ring, total_rx_pkts,

drivers/net/ethernet/intel/ice/ice_txrx.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,19 @@ static inline int ice_skb_pad(void)
150150
#define ICE_TXD_LAST_DESC_CMD (ICE_TX_DESC_CMD_EOP | ICE_TX_DESC_CMD_RS)
151151

152152
struct ice_tx_buf {
153-
struct ice_tx_desc *next_to_watch;
153+
union {
154+
struct ice_tx_desc *next_to_watch;
155+
u32 rs_idx;
156+
};
154157
union {
155158
struct sk_buff *skb;
156159
void *raw_buf; /* used for XDP */
157160
};
158161
unsigned int bytecount;
159-
unsigned short gso_segs;
162+
union {
163+
unsigned int gso_segs;
164+
unsigned int nr_frags; /* used for mbuf XDP */
165+
};
160166
u32 tx_flags;
161167
DEFINE_DMA_UNMAP_LEN(len);
162168
DEFINE_DMA_UNMAP_ADDR(dma);
@@ -343,6 +349,7 @@ struct ice_tx_ring {
343349
u16 reg_idx; /* HW register index of the ring */
344350
u16 count; /* Number of descriptors */
345351
u16 q_index; /* Queue number of ring */
352+
u16 xdp_tx_active;
346353
/* stats structs */
347354
struct ice_ring_stats *ring_stats;
348355
/* CL3 - 3rd cacheline starts here */
@@ -353,7 +360,6 @@ struct ice_tx_ring {
353360
spinlock_t tx_lock;
354361
u32 txq_teid; /* Added Tx queue TEID */
355362
/* CL4 - 4th cacheline starts here */
356-
u16 xdp_tx_active;
357363
#define ICE_TX_FLAGS_RING_XDP BIT(0)
358364
#define ICE_TX_FLAGS_RING_VLAN_L2TAG1 BIT(1)
359365
#define ICE_TX_FLAGS_RING_VLAN_L2TAG2 BIT(2)

drivers/net/ethernet/intel/ice/ice_txrx_lib.c

Lines changed: 158 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -220,112 +220,191 @@ ice_receive_skb(struct ice_rx_ring *rx_ring, struct sk_buff *skb, u16 vlan_tag)
220220
napi_gro_receive(&rx_ring->q_vector->napi, skb);
221221
}
222222

223+
/**
224+
* ice_clean_xdp_tx_buf - Free and unmap XDP Tx buffer
225+
* @xdp_ring: XDP Tx ring
226+
* @tx_buf: Tx buffer to clean
227+
*/
228+
static void
229+
ice_clean_xdp_tx_buf(struct ice_tx_ring *xdp_ring, struct ice_tx_buf *tx_buf)
230+
{
231+
dma_unmap_single(xdp_ring->dev, dma_unmap_addr(tx_buf, dma),
232+
dma_unmap_len(tx_buf, len), DMA_TO_DEVICE);
233+
dma_unmap_len_set(tx_buf, len, 0);
234+
xdp_ring->xdp_tx_active--;
235+
page_frag_free(tx_buf->raw_buf);
236+
tx_buf->raw_buf = NULL;
237+
}
238+
223239
/**
224240
* ice_clean_xdp_irq - Reclaim resources after transmit completes on XDP ring
225241
* @xdp_ring: XDP ring to clean
226242
*/
227-
static void ice_clean_xdp_irq(struct ice_tx_ring *xdp_ring)
243+
static u32 ice_clean_xdp_irq(struct ice_tx_ring *xdp_ring)
228244
{
229-
unsigned int total_bytes = 0, total_pkts = 0;
230-
u16 tx_thresh = ICE_RING_QUARTER(xdp_ring);
231-
u16 ntc = xdp_ring->next_to_clean;
232-
struct ice_tx_desc *next_dd_desc;
233-
u16 next_dd = xdp_ring->next_dd;
234-
struct ice_tx_buf *tx_buf;
235-
int i;
245+
int total_bytes = 0, total_pkts = 0;
246+
u32 ntc = xdp_ring->next_to_clean;
247+
struct ice_tx_desc *tx_desc;
248+
u32 cnt = xdp_ring->count;
249+
u32 ready_frames = 0;
250+
u32 frags;
251+
u32 idx;
252+
u32 ret;
253+
254+
idx = xdp_ring->tx_buf[ntc].rs_idx;
255+
tx_desc = ICE_TX_DESC(xdp_ring, idx);
256+
if (tx_desc->cmd_type_offset_bsz &
257+
cpu_to_le64(ICE_TX_DESC_DTYPE_DESC_DONE)) {
258+
if (idx >= ntc)
259+
ready_frames = idx - ntc + 1;
260+
else
261+
ready_frames = idx + cnt - ntc + 1;
262+
}
236263

237-
next_dd_desc = ICE_TX_DESC(xdp_ring, next_dd);
238-
if (!(next_dd_desc->cmd_type_offset_bsz &
239-
cpu_to_le64(ICE_TX_DESC_DTYPE_DESC_DONE)))
240-
return;
264+
if (!ready_frames)
265+
return 0;
266+
ret = ready_frames;
241267

242-
for (i = 0; i < tx_thresh; i++) {
243-
tx_buf = &xdp_ring->tx_buf[ntc];
268+
while (ready_frames) {
269+
struct ice_tx_buf *tx_buf = &xdp_ring->tx_buf[ntc];
244270

271+
/* bytecount holds size of head + frags */
245272
total_bytes += tx_buf->bytecount;
246-
/* normally tx_buf->gso_segs was taken but at this point
247-
* it's always 1 for us
248-
*/
273+
frags = tx_buf->nr_frags;
249274
total_pkts++;
275+
/* count head + frags */
276+
ready_frames -= frags + 1;
250277

251-
page_frag_free(tx_buf->raw_buf);
252-
dma_unmap_single(xdp_ring->dev, dma_unmap_addr(tx_buf, dma),
253-
dma_unmap_len(tx_buf, len), DMA_TO_DEVICE);
254-
dma_unmap_len_set(tx_buf, len, 0);
255-
tx_buf->raw_buf = NULL;
256-
278+
ice_clean_xdp_tx_buf(xdp_ring, tx_buf);
257279
ntc++;
258-
if (ntc >= xdp_ring->count)
280+
if (ntc == cnt)
259281
ntc = 0;
282+
283+
for (int i = 0; i < frags; i++) {
284+
tx_buf = &xdp_ring->tx_buf[ntc];
285+
286+
ice_clean_xdp_tx_buf(xdp_ring, tx_buf);
287+
ntc++;
288+
if (ntc == cnt)
289+
ntc = 0;
290+
}
260291
}
261292

262-
next_dd_desc->cmd_type_offset_bsz = 0;
263-
xdp_ring->next_dd = xdp_ring->next_dd + tx_thresh;
264-
if (xdp_ring->next_dd > xdp_ring->count)
265-
xdp_ring->next_dd = tx_thresh - 1;
293+
tx_desc->cmd_type_offset_bsz = 0;
266294
xdp_ring->next_to_clean = ntc;
267295
ice_update_tx_ring_stats(xdp_ring, total_pkts, total_bytes);
296+
297+
return ret;
268298
}
269299

270300
/**
271-
* ice_xmit_xdp_ring - submit single packet to XDP ring for transmission
272-
* @data: packet data pointer
273-
* @size: packet data size
301+
* __ice_xmit_xdp_ring - submit frame to XDP ring for transmission
302+
* @xdp: XDP buffer to be placed onto Tx descriptors
274303
* @xdp_ring: XDP ring for transmission
275304
*/
276-
int ice_xmit_xdp_ring(void *data, u16 size, struct ice_tx_ring *xdp_ring)
305+
int __ice_xmit_xdp_ring(struct xdp_buff *xdp, struct ice_tx_ring *xdp_ring)
277306
{
278-
u16 tx_thresh = ICE_RING_QUARTER(xdp_ring);
279-
u16 i = xdp_ring->next_to_use;
307+
struct skb_shared_info *sinfo = NULL;
308+
u32 size = xdp->data_end - xdp->data;
309+
struct device *dev = xdp_ring->dev;
310+
u32 ntu = xdp_ring->next_to_use;
280311
struct ice_tx_desc *tx_desc;
312+
struct ice_tx_buf *tx_head;
281313
struct ice_tx_buf *tx_buf;
282-
dma_addr_t dma;
314+
u32 cnt = xdp_ring->count;
315+
void *data = xdp->data;
316+
u32 nr_frags = 0;
317+
u32 free_space;
318+
u32 frag = 0;
319+
320+
free_space = ICE_DESC_UNUSED(xdp_ring);
321+
322+
if (ICE_DESC_UNUSED(xdp_ring) < ICE_RING_QUARTER(xdp_ring))
323+
free_space += ice_clean_xdp_irq(xdp_ring);
324+
325+
if (unlikely(xdp_buff_has_frags(xdp))) {
326+
sinfo = xdp_get_shared_info_from_buff(xdp);
327+
nr_frags = sinfo->nr_frags;
328+
if (free_space < nr_frags + 1) {
329+
xdp_ring->ring_stats->tx_stats.tx_busy++;
330+
return ICE_XDP_CONSUMED;
331+
}
332+
}
283333

284-
if (ICE_DESC_UNUSED(xdp_ring) < tx_thresh)
285-
ice_clean_xdp_irq(xdp_ring);
334+
tx_desc = ICE_TX_DESC(xdp_ring, ntu);
335+
tx_head = &xdp_ring->tx_buf[ntu];
336+
tx_buf = tx_head;
286337

287-
if (!unlikely(ICE_DESC_UNUSED(xdp_ring))) {
288-
xdp_ring->ring_stats->tx_stats.tx_busy++;
289-
return ICE_XDP_CONSUMED;
290-
}
338+
for (;;) {
339+
dma_addr_t dma;
291340

292-
dma = dma_map_single(xdp_ring->dev, data, size, DMA_TO_DEVICE);
293-
if (dma_mapping_error(xdp_ring->dev, dma))
294-
return ICE_XDP_CONSUMED;
341+
dma = dma_map_single(dev, data, size, DMA_TO_DEVICE);
342+
if (dma_mapping_error(dev, dma))
343+
goto dma_unmap;
295344

296-
tx_buf = &xdp_ring->tx_buf[i];
297-
tx_buf->bytecount = size;
298-
tx_buf->gso_segs = 1;
299-
tx_buf->raw_buf = data;
345+
/* record length, and DMA address */
346+
dma_unmap_len_set(tx_buf, len, size);
347+
dma_unmap_addr_set(tx_buf, dma, dma);
300348

301-
/* record length, and DMA address */
302-
dma_unmap_len_set(tx_buf, len, size);
303-
dma_unmap_addr_set(tx_buf, dma, dma);
349+
tx_desc->buf_addr = cpu_to_le64(dma);
350+
tx_desc->cmd_type_offset_bsz = ice_build_ctob(0, 0, size, 0);
351+
tx_buf->raw_buf = data;
304352

305-
tx_desc = ICE_TX_DESC(xdp_ring, i);
306-
tx_desc->buf_addr = cpu_to_le64(dma);
307-
tx_desc->cmd_type_offset_bsz = ice_build_ctob(ICE_TX_DESC_CMD_EOP, 0,
308-
size, 0);
353+
ntu++;
354+
if (ntu == cnt)
355+
ntu = 0;
309356

310-
xdp_ring->xdp_tx_active++;
311-
i++;
312-
if (i == xdp_ring->count) {
313-
i = 0;
314-
tx_desc = ICE_TX_DESC(xdp_ring, xdp_ring->next_rs);
315-
tx_desc->cmd_type_offset_bsz |=
316-
cpu_to_le64(ICE_TX_DESC_CMD_RS << ICE_TXD_QW1_CMD_S);
317-
xdp_ring->next_rs = tx_thresh - 1;
318-
}
319-
xdp_ring->next_to_use = i;
357+
if (frag == nr_frags)
358+
break;
359+
360+
tx_desc = ICE_TX_DESC(xdp_ring, ntu);
361+
tx_buf = &xdp_ring->tx_buf[ntu];
320362

321-
if (i > xdp_ring->next_rs) {
322-
tx_desc = ICE_TX_DESC(xdp_ring, xdp_ring->next_rs);
323-
tx_desc->cmd_type_offset_bsz |=
324-
cpu_to_le64(ICE_TX_DESC_CMD_RS << ICE_TXD_QW1_CMD_S);
325-
xdp_ring->next_rs += tx_thresh;
363+
data = skb_frag_address(&sinfo->frags[frag]);
364+
size = skb_frag_size(&sinfo->frags[frag]);
365+
frag++;
326366
}
327367

368+
/* store info about bytecount and frag count in first desc */
369+
tx_head->bytecount = xdp_get_buff_len(xdp);
370+
tx_head->nr_frags = nr_frags;
371+
372+
/* update last descriptor from a frame with EOP */
373+
tx_desc->cmd_type_offset_bsz |=
374+
cpu_to_le64(ICE_TX_DESC_CMD_EOP << ICE_TXD_QW1_CMD_S);
375+
376+
xdp_ring->xdp_tx_active++;
377+
xdp_ring->next_to_use = ntu;
378+
328379
return ICE_XDP_TX;
380+
381+
dma_unmap:
382+
for (;;) {
383+
tx_buf = &xdp_ring->tx_buf[ntu];
384+
dma_unmap_page(dev, dma_unmap_addr(tx_buf, dma),
385+
dma_unmap_len(tx_buf, len), DMA_TO_DEVICE);
386+
dma_unmap_len_set(tx_buf, len, 0);
387+
if (tx_buf == tx_head)
388+
break;
389+
390+
if (!ntu)
391+
ntu += cnt;
392+
ntu--;
393+
}
394+
return ICE_XDP_CONSUMED;
395+
}
396+
397+
/**
398+
* ice_xmit_xdp_ring - submit frame to XDP ring for transmission
399+
* @xdpf: XDP frame that will be converted to XDP buff
400+
* @xdp_ring: XDP ring for transmission
401+
*/
402+
int ice_xmit_xdp_ring(struct xdp_frame *xdpf, struct ice_tx_ring *xdp_ring)
403+
{
404+
struct xdp_buff xdp;
405+
406+
xdp_convert_frame_to_buff(xdpf, &xdp);
407+
return __ice_xmit_xdp_ring(&xdp, xdp_ring);
329408
}
330409

331410
/**
@@ -342,7 +421,7 @@ int ice_xmit_xdp_buff(struct xdp_buff *xdp, struct ice_tx_ring *xdp_ring)
342421
if (unlikely(!xdpf))
343422
return ICE_XDP_CONSUMED;
344423

345-
return ice_xmit_xdp_ring(xdpf->data, xdpf->len, xdp_ring);
424+
return ice_xmit_xdp_ring(xdpf, xdp_ring);
346425
}
347426

348427
/**
@@ -354,14 +433,21 @@ int ice_xmit_xdp_buff(struct xdp_buff *xdp, struct ice_tx_ring *xdp_ring)
354433
* should be called when a batch of packets has been processed in the
355434
* napi loop.
356435
*/
357-
void ice_finalize_xdp_rx(struct ice_tx_ring *xdp_ring, unsigned int xdp_res)
436+
void ice_finalize_xdp_rx(struct ice_tx_ring *xdp_ring, unsigned int xdp_res,
437+
u32 first_idx)
358438
{
439+
struct ice_tx_buf *tx_buf = &xdp_ring->tx_buf[first_idx];
440+
359441
if (xdp_res & ICE_XDP_REDIR)
360442
xdp_do_flush_map();
361443

362444
if (xdp_res & ICE_XDP_TX) {
363445
if (static_branch_unlikely(&ice_xdp_locking_key))
364446
spin_lock(&xdp_ring->tx_lock);
447+
/* store index of descriptor with RS bit set in the first
448+
* ice_tx_buf of given NAPI batch
449+
*/
450+
tx_buf->rs_idx = ice_set_rs_bit(xdp_ring);
365451
ice_xdp_ring_update_tail(xdp_ring);
366452
if (static_branch_unlikely(&ice_xdp_locking_key))
367453
spin_unlock(&xdp_ring->tx_lock);

0 commit comments

Comments
 (0)