@@ -527,15 +527,14 @@ int ice_setup_rx_ring(struct ice_rx_ring *rx_ring)
527527 * @xdp: xdp_buff used as input to the XDP program
528528 * @xdp_prog: XDP program to run
529529 * @xdp_ring: ring to be used for XDP_TX action
530- * @rx_buf: Rx buffer to store the XDP action
531530 * @eop_desc: Last descriptor in packet to read metadata from
532531 *
533532 * Returns any of ICE_XDP_{PASS, CONSUMED, TX, REDIR}
534533 */
535- static void
534+ static u32
536535ice_run_xdp (struct ice_rx_ring * rx_ring , struct xdp_buff * xdp ,
537536 struct bpf_prog * xdp_prog , struct ice_tx_ring * xdp_ring ,
538- struct ice_rx_buf * rx_buf , union ice_32b_rx_flex_desc * eop_desc )
537+ union ice_32b_rx_flex_desc * eop_desc )
539538{
540539 unsigned int ret = ICE_XDP_PASS ;
541540 u32 act ;
@@ -574,7 +573,7 @@ ice_run_xdp(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
574573 ret = ICE_XDP_CONSUMED ;
575574 }
576575exit :
577- ice_set_rx_bufs_act ( xdp , rx_ring , ret ) ;
576+ return ret ;
578577}
579578
580579/**
@@ -860,10 +859,8 @@ ice_add_xdp_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
860859 xdp_buff_set_frags_flag (xdp );
861860 }
862861
863- if (unlikely (sinfo -> nr_frags == MAX_SKB_FRAGS )) {
864- ice_set_rx_bufs_act (xdp , rx_ring , ICE_XDP_CONSUMED );
862+ if (unlikely (sinfo -> nr_frags == MAX_SKB_FRAGS ))
865863 return - ENOMEM ;
866- }
867864
868865 __skb_fill_page_desc_noacc (sinfo , sinfo -> nr_frags ++ , rx_buf -> page ,
869866 rx_buf -> page_offset , size );
@@ -1075,12 +1072,12 @@ ice_construct_skb(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp)
10751072 rx_buf -> page_offset + headlen , size ,
10761073 xdp -> frame_sz );
10771074 } else {
1078- /* buffer is unused, change the act that should be taken later
1079- * on; data was copied onto skb's linear part so there's no
1075+ /* buffer is unused, restore biased page count in Rx buffer;
1076+ * data was copied onto skb's linear part so there's no
10801077 * need for adjusting page offset and we can reuse this buffer
10811078 * as-is
10821079 */
1083- rx_buf -> act = ICE_SKB_CONSUMED ;
1080+ rx_buf -> pagecnt_bias ++ ;
10841081 }
10851082
10861083 if (unlikely (xdp_buff_has_frags (xdp ))) {
@@ -1133,29 +1130,34 @@ ice_put_rx_buf(struct ice_rx_ring *rx_ring, struct ice_rx_buf *rx_buf)
11331130 * @xdp: XDP buffer carrying linear + frags part
11341131 * @xdp_xmit: XDP_TX/XDP_REDIRECT verdict storage
11351132 * @ntc: a current next_to_clean value to be stored at rx_ring
1133+ * @verdict: return code from XDP program execution
11361134 *
11371135 * Walk through gathered fragments and satisfy internal page
11381136 * recycle mechanism; we take here an action related to verdict
11391137 * returned by XDP program;
11401138 */
11411139static void ice_put_rx_mbuf (struct ice_rx_ring * rx_ring , struct xdp_buff * xdp ,
1142- u32 * xdp_xmit , u32 ntc )
1140+ u32 * xdp_xmit , u32 ntc , u32 verdict )
11431141{
11441142 u32 nr_frags = rx_ring -> nr_frags + 1 ;
11451143 u32 idx = rx_ring -> first_desc ;
11461144 u32 cnt = rx_ring -> count ;
1145+ u32 post_xdp_frags = 1 ;
11471146 struct ice_rx_buf * buf ;
11481147 int i ;
11491148
1150- for (i = 0 ; i < nr_frags ; i ++ ) {
1149+ if (unlikely (xdp_buff_has_frags (xdp )))
1150+ post_xdp_frags += xdp_get_shared_info_from_buff (xdp )-> nr_frags ;
1151+
1152+ for (i = 0 ; i < post_xdp_frags ; i ++ ) {
11511153 buf = & rx_ring -> rx_buf [idx ];
11521154
1153- if (buf -> act & (ICE_XDP_TX | ICE_XDP_REDIR )) {
1155+ if (verdict & (ICE_XDP_TX | ICE_XDP_REDIR )) {
11541156 ice_rx_buf_adjust_pg_offset (buf , xdp -> frame_sz );
1155- * xdp_xmit |= buf -> act ;
1156- } else if (buf -> act & ICE_XDP_CONSUMED ) {
1157+ * xdp_xmit |= verdict ;
1158+ } else if (verdict & ICE_XDP_CONSUMED ) {
11571159 buf -> pagecnt_bias ++ ;
1158- } else if (buf -> act == ICE_XDP_PASS ) {
1160+ } else if (verdict == ICE_XDP_PASS ) {
11591161 ice_rx_buf_adjust_pg_offset (buf , xdp -> frame_sz );
11601162 }
11611163
@@ -1164,6 +1166,17 @@ static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
11641166 if (++ idx == cnt )
11651167 idx = 0 ;
11661168 }
1169+ /* handle buffers that represented frags released by XDP prog;
1170+ * for these we keep pagecnt_bias as-is; refcount from struct page
1171+ * has been decremented within XDP prog and we do not have to increase
1172+ * the biased refcnt
1173+ */
1174+ for (; i < nr_frags ; i ++ ) {
1175+ buf = & rx_ring -> rx_buf [idx ];
1176+ ice_put_rx_buf (rx_ring , buf );
1177+ if (++ idx == cnt )
1178+ idx = 0 ;
1179+ }
11671180
11681181 xdp -> data = NULL ;
11691182 rx_ring -> first_desc = ntc ;
@@ -1190,9 +1203,9 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
11901203 struct ice_tx_ring * xdp_ring = NULL ;
11911204 struct bpf_prog * xdp_prog = NULL ;
11921205 u32 ntc = rx_ring -> next_to_clean ;
1206+ u32 cached_ntu , xdp_verdict ;
11931207 u32 cnt = rx_ring -> count ;
11941208 u32 xdp_xmit = 0 ;
1195- u32 cached_ntu ;
11961209 bool failure ;
11971210
11981211 xdp_prog = READ_ONCE (rx_ring -> xdp_prog );
@@ -1255,7 +1268,7 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
12551268 xdp_prepare_buff (xdp , hard_start , offset , size , !!offset );
12561269 xdp_buff_clear_frags_flag (xdp );
12571270 } else if (ice_add_xdp_frag (rx_ring , xdp , rx_buf , size )) {
1258- ice_put_rx_mbuf (rx_ring , xdp , NULL , ntc );
1271+ ice_put_rx_mbuf (rx_ring , xdp , NULL , ntc , ICE_XDP_CONSUMED );
12591272 break ;
12601273 }
12611274 if (++ ntc == cnt )
@@ -1266,13 +1279,13 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
12661279 continue ;
12671280
12681281 ice_get_pgcnts (rx_ring );
1269- ice_run_xdp (rx_ring , xdp , xdp_prog , xdp_ring , rx_buf , rx_desc );
1270- if (rx_buf -> act == ICE_XDP_PASS )
1282+ xdp_verdict = ice_run_xdp (rx_ring , xdp , xdp_prog , xdp_ring , rx_desc );
1283+ if (xdp_verdict == ICE_XDP_PASS )
12711284 goto construct_skb ;
12721285 total_rx_bytes += xdp_get_buff_len (xdp );
12731286 total_rx_pkts ++ ;
12741287
1275- ice_put_rx_mbuf (rx_ring , xdp , & xdp_xmit , ntc );
1288+ ice_put_rx_mbuf (rx_ring , xdp , & xdp_xmit , ntc , xdp_verdict );
12761289
12771290 continue ;
12781291construct_skb :
@@ -1283,12 +1296,9 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
12831296 /* exit if we failed to retrieve a buffer */
12841297 if (!skb ) {
12851298 rx_ring -> ring_stats -> rx_stats .alloc_page_failed ++ ;
1286- rx_buf -> act = ICE_XDP_CONSUMED ;
1287- if (unlikely (xdp_buff_has_frags (xdp )))
1288- ice_set_rx_bufs_act (xdp , rx_ring ,
1289- ICE_XDP_CONSUMED );
1299+ xdp_verdict = ICE_XDP_CONSUMED ;
12901300 }
1291- ice_put_rx_mbuf (rx_ring , xdp , & xdp_xmit , ntc );
1301+ ice_put_rx_mbuf (rx_ring , xdp , & xdp_xmit , ntc , xdp_verdict );
12921302
12931303 if (!skb )
12941304 break ;
0 commit comments