Skip to content

Commit 1bbc04d

Browse files
mfijalkoAlexei Starovoitov
authored andcommitted
ice: xsk: add RX multi-buffer support
This support is strongly inspired by work that introduced multi-buffer support to regular Rx data path in ice. There are some differences, though. When adding a frag, besides adding it to skb_shared_info, use also fresh xsk_buff_add_frag() helper. Reason for doing both things is that we can not rule out the fact that AF_XDP pipeline could use XDP program that needs to access frame fragments. Without them being in skb_shared_info it will not be possible. Another difference is that XDP_PASS has to allocate a new pages for each frags and copy contents from memory backed by xsk_buff_pool. chain_len that is used for programming HW Rx descriptors no longer has to be limited to 1 when xsk_pool is present - remove this restriction. Signed-off-by: Maciej Fijalkowski <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 24ea501 commit 1bbc04d

File tree

2 files changed

+102
-43
lines changed

2 files changed

+102
-43
lines changed

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,6 @@ static unsigned int ice_rx_offset(struct ice_rx_ring *rx_ring)
408408
*/
409409
static int ice_setup_rx_ctx(struct ice_rx_ring *ring)
410410
{
411-
int chain_len = ICE_MAX_CHAINED_RX_BUFS;
412411
struct ice_vsi *vsi = ring->vsi;
413412
u32 rxdid = ICE_RXDID_FLEX_NIC;
414413
struct ice_rlan_ctx rlan_ctx;
@@ -472,17 +471,11 @@ static int ice_setup_rx_ctx(struct ice_rx_ring *ring)
472471
*/
473472
rlan_ctx.showiv = 0;
474473

475-
/* For AF_XDP ZC, we disallow packets to span on
476-
* multiple buffers, thus letting us skip that
477-
* handling in the fast-path.
478-
*/
479-
if (ring->xsk_pool)
480-
chain_len = 1;
481474
/* Max packet size for this queue - must not be set to a larger value
482475
* than 5 x DBUF
483476
*/
484477
rlan_ctx.rxmax = min_t(u32, vsi->max_frame,
485-
chain_len * ring->rx_buf_len);
478+
ICE_MAX_CHAINED_RX_BUFS * ring->rx_buf_len);
486479

487480
/* Rx queue threshold in units of 64 */
488481
rlan_ctx.lrxqthresh = 1;

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

Lines changed: 101 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -545,19 +545,6 @@ bool ice_alloc_rx_bufs_zc(struct ice_rx_ring *rx_ring, u16 count)
545545
return __ice_alloc_rx_bufs_zc(rx_ring, leftover);
546546
}
547547

548-
/**
549-
* ice_bump_ntc - Bump the next_to_clean counter of an Rx ring
550-
* @rx_ring: Rx ring
551-
*/
552-
static void ice_bump_ntc(struct ice_rx_ring *rx_ring)
553-
{
554-
int ntc = rx_ring->next_to_clean + 1;
555-
556-
ntc = (ntc < rx_ring->count) ? ntc : 0;
557-
rx_ring->next_to_clean = ntc;
558-
prefetch(ICE_RX_DESC(rx_ring, ntc));
559-
}
560-
561548
/**
562549
* ice_construct_skb_zc - Create an sk_buff from zero-copy buffer
563550
* @rx_ring: Rx ring
@@ -572,8 +559,14 @@ ice_construct_skb_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp)
572559
{
573560
unsigned int totalsize = xdp->data_end - xdp->data_meta;
574561
unsigned int metasize = xdp->data - xdp->data_meta;
562+
struct skb_shared_info *sinfo = NULL;
575563
struct sk_buff *skb;
564+
u32 nr_frags = 0;
576565

566+
if (unlikely(xdp_buff_has_frags(xdp))) {
567+
sinfo = xdp_get_shared_info_from_buff(xdp);
568+
nr_frags = sinfo->nr_frags;
569+
}
577570
net_prefetch(xdp->data_meta);
578571

579572
skb = __napi_alloc_skb(&rx_ring->q_vector->napi, totalsize,
@@ -589,6 +582,29 @@ ice_construct_skb_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp)
589582
__skb_pull(skb, metasize);
590583
}
591584

585+
if (likely(!xdp_buff_has_frags(xdp)))
586+
goto out;
587+
588+
for (int i = 0; i < nr_frags; i++) {
589+
struct skb_shared_info *skinfo = skb_shinfo(skb);
590+
skb_frag_t *frag = &sinfo->frags[i];
591+
struct page *page;
592+
void *addr;
593+
594+
page = dev_alloc_page();
595+
if (!page) {
596+
dev_kfree_skb(skb);
597+
return NULL;
598+
}
599+
addr = page_to_virt(page);
600+
601+
memcpy(addr, skb_frag_page(frag), skb_frag_size(frag));
602+
603+
__skb_fill_page_desc_noacc(skinfo, skinfo->nr_frags++,
604+
addr, 0, skb_frag_size(frag));
605+
}
606+
607+
out:
592608
xsk_buff_free(xdp);
593609
return skb;
594610
}
@@ -752,6 +768,34 @@ ice_run_xdp_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
752768
return result;
753769
}
754770

771+
static int
772+
ice_add_xsk_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *first,
773+
struct xdp_buff *xdp, const unsigned int size)
774+
{
775+
struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(first);
776+
777+
if (!size)
778+
return 0;
779+
780+
if (!xdp_buff_has_frags(first)) {
781+
sinfo->nr_frags = 0;
782+
sinfo->xdp_frags_size = 0;
783+
xdp_buff_set_frags_flag(first);
784+
}
785+
786+
if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) {
787+
xsk_buff_free(first);
788+
return -ENOMEM;
789+
}
790+
791+
__skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++,
792+
virt_to_page(xdp->data_hard_start), 0, size);
793+
sinfo->xdp_frags_size += size;
794+
xsk_buff_add_frag(xdp);
795+
796+
return 0;
797+
}
798+
755799
/**
756800
* ice_clean_rx_irq_zc - consumes packets from the hardware ring
757801
* @rx_ring: AF_XDP Rx ring
@@ -762,9 +806,14 @@ ice_run_xdp_zc(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
762806
int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget)
763807
{
764808
unsigned int total_rx_bytes = 0, total_rx_packets = 0;
809+
struct xsk_buff_pool *xsk_pool = rx_ring->xsk_pool;
810+
u32 ntc = rx_ring->next_to_clean;
811+
u32 ntu = rx_ring->next_to_use;
812+
struct xdp_buff *first = NULL;
765813
struct ice_tx_ring *xdp_ring;
766814
unsigned int xdp_xmit = 0;
767815
struct bpf_prog *xdp_prog;
816+
u32 cnt = rx_ring->count;
768817
bool failure = false;
769818
int entries_to_alloc;
770819

@@ -774,6 +823,9 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget)
774823
xdp_prog = READ_ONCE(rx_ring->xdp_prog);
775824
xdp_ring = rx_ring->xdp_ring;
776825

826+
if (ntc != rx_ring->first_desc)
827+
first = *ice_xdp_buf(rx_ring, rx_ring->first_desc);
828+
777829
while (likely(total_rx_packets < (unsigned int)budget)) {
778830
union ice_32b_rx_flex_desc *rx_desc;
779831
unsigned int size, xdp_res = 0;
@@ -783,7 +835,7 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget)
783835
u16 vlan_tag = 0;
784836
u16 rx_ptype;
785837

786-
rx_desc = ICE_RX_DESC(rx_ring, rx_ring->next_to_clean);
838+
rx_desc = ICE_RX_DESC(rx_ring, ntc);
787839

788840
stat_err_bits = BIT(ICE_RX_FLEX_DESC_STATUS0_DD_S);
789841
if (!ice_test_staterr(rx_desc->wb.status_error0, stat_err_bits))
@@ -795,51 +847,61 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget)
795847
*/
796848
dma_rmb();
797849

798-
if (unlikely(rx_ring->next_to_clean == rx_ring->next_to_use))
850+
if (unlikely(ntc == ntu))
799851
break;
800852

801-
xdp = *ice_xdp_buf(rx_ring, rx_ring->next_to_clean);
853+
xdp = *ice_xdp_buf(rx_ring, ntc);
802854

803855
size = le16_to_cpu(rx_desc->wb.pkt_len) &
804856
ICE_RX_FLX_DESC_PKT_LEN_M;
805-
if (!size) {
806-
xdp->data = NULL;
807-
xdp->data_end = NULL;
808-
xdp->data_hard_start = NULL;
809-
xdp->data_meta = NULL;
810-
goto construct_skb;
811-
}
812857

813858
xsk_buff_set_size(xdp, size);
814-
xsk_buff_dma_sync_for_cpu(xdp, rx_ring->xsk_pool);
859+
xsk_buff_dma_sync_for_cpu(xdp, xsk_pool);
860+
861+
if (!first) {
862+
first = xdp;
863+
xdp_buff_clear_frags_flag(first);
864+
} else if (ice_add_xsk_frag(rx_ring, first, xdp, size)) {
865+
break;
866+
}
867+
868+
if (++ntc == cnt)
869+
ntc = 0;
870+
871+
if (ice_is_non_eop(rx_ring, rx_desc))
872+
continue;
815873

816-
xdp_res = ice_run_xdp_zc(rx_ring, xdp, xdp_prog, xdp_ring);
874+
xdp_res = ice_run_xdp_zc(rx_ring, first, xdp_prog, xdp_ring);
817875
if (likely(xdp_res & (ICE_XDP_TX | ICE_XDP_REDIR))) {
818876
xdp_xmit |= xdp_res;
819877
} else if (xdp_res == ICE_XDP_EXIT) {
820878
failure = true;
879+
first = NULL;
880+
rx_ring->first_desc = ntc;
821881
break;
822882
} else if (xdp_res == ICE_XDP_CONSUMED) {
823-
xsk_buff_free(xdp);
883+
xsk_buff_free(first);
824884
} else if (xdp_res == ICE_XDP_PASS) {
825885
goto construct_skb;
826886
}
827887

828-
total_rx_bytes += size;
888+
total_rx_bytes += xdp_get_buff_len(first);
829889
total_rx_packets++;
830890

831-
ice_bump_ntc(rx_ring);
891+
first = NULL;
892+
rx_ring->first_desc = ntc;
832893
continue;
833894

834895
construct_skb:
835896
/* XDP_PASS path */
836-
skb = ice_construct_skb_zc(rx_ring, xdp);
897+
skb = ice_construct_skb_zc(rx_ring, first);
837898
if (!skb) {
838899
rx_ring->ring_stats->rx_stats.alloc_buf_failed++;
839900
break;
840901
}
841902

842-
ice_bump_ntc(rx_ring);
903+
first = NULL;
904+
rx_ring->first_desc = ntc;
843905

844906
if (eth_skb_pad(skb)) {
845907
skb = NULL;
@@ -858,18 +920,22 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget)
858920
ice_receive_skb(rx_ring, skb, vlan_tag);
859921
}
860922

861-
entries_to_alloc = ICE_DESC_UNUSED(rx_ring);
923+
rx_ring->next_to_clean = ntc;
924+
entries_to_alloc = ICE_RX_DESC_UNUSED(rx_ring);
862925
if (entries_to_alloc > ICE_RING_QUARTER(rx_ring))
863926
failure |= !ice_alloc_rx_bufs_zc(rx_ring, entries_to_alloc);
864927

865928
ice_finalize_xdp_rx(xdp_ring, xdp_xmit, 0);
866929
ice_update_rx_ring_stats(rx_ring, total_rx_packets, total_rx_bytes);
867930

868-
if (xsk_uses_need_wakeup(rx_ring->xsk_pool)) {
869-
if (failure || rx_ring->next_to_clean == rx_ring->next_to_use)
870-
xsk_set_rx_need_wakeup(rx_ring->xsk_pool);
931+
if (xsk_uses_need_wakeup(xsk_pool)) {
932+
/* ntu could have changed when allocating entries above, so
933+
* use rx_ring value instead of stack based one
934+
*/
935+
if (failure || ntc == rx_ring->next_to_use)
936+
xsk_set_rx_need_wakeup(xsk_pool);
871937
else
872-
xsk_clear_rx_need_wakeup(rx_ring->xsk_pool);
938+
xsk_clear_rx_need_wakeup(xsk_pool);
873939

874940
return (int)total_rx_packets;
875941
}

0 commit comments

Comments
 (0)