@@ -527,15 +527,14 @@ int ice_setup_rx_ring(struct ice_rx_ring *rx_ring)
527
527
* @xdp: xdp_buff used as input to the XDP program
528
528
* @xdp_prog: XDP program to run
529
529
* @xdp_ring: ring to be used for XDP_TX action
530
- * @rx_buf: Rx buffer to store the XDP action
531
530
* @eop_desc: Last descriptor in packet to read metadata from
532
531
*
533
532
* Returns any of ICE_XDP_{PASS, CONSUMED, TX, REDIR}
534
533
*/
535
- static void
534
+ static u32
536
535
ice_run_xdp (struct ice_rx_ring * rx_ring , struct xdp_buff * xdp ,
537
536
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 )
539
538
{
540
539
unsigned int ret = ICE_XDP_PASS ;
541
540
u32 act ;
@@ -574,7 +573,7 @@ ice_run_xdp(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
574
573
ret = ICE_XDP_CONSUMED ;
575
574
}
576
575
exit :
577
- ice_set_rx_bufs_act ( xdp , rx_ring , ret ) ;
576
+ return ret ;
578
577
}
579
578
580
579
/**
@@ -860,10 +859,8 @@ ice_add_xdp_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
860
859
xdp_buff_set_frags_flag (xdp );
861
860
}
862
861
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 ))
865
863
return - ENOMEM ;
866
- }
867
864
868
865
__skb_fill_page_desc_noacc (sinfo , sinfo -> nr_frags ++ , rx_buf -> page ,
869
866
rx_buf -> page_offset , size );
@@ -1075,12 +1072,12 @@ ice_construct_skb(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp)
1075
1072
rx_buf -> page_offset + headlen , size ,
1076
1073
xdp -> frame_sz );
1077
1074
} 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
1080
1077
* need for adjusting page offset and we can reuse this buffer
1081
1078
* as-is
1082
1079
*/
1083
- rx_buf -> act = ICE_SKB_CONSUMED ;
1080
+ rx_buf -> pagecnt_bias ++ ;
1084
1081
}
1085
1082
1086
1083
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)
1133
1130
* @xdp: XDP buffer carrying linear + frags part
1134
1131
* @xdp_xmit: XDP_TX/XDP_REDIRECT verdict storage
1135
1132
* @ntc: a current next_to_clean value to be stored at rx_ring
1133
+ * @verdict: return code from XDP program execution
1136
1134
*
1137
1135
* Walk through gathered fragments and satisfy internal page
1138
1136
* recycle mechanism; we take here an action related to verdict
1139
1137
* returned by XDP program;
1140
1138
*/
1141
1139
static 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 )
1143
1141
{
1144
1142
u32 nr_frags = rx_ring -> nr_frags + 1 ;
1145
1143
u32 idx = rx_ring -> first_desc ;
1146
1144
u32 cnt = rx_ring -> count ;
1145
+ u32 post_xdp_frags = 1 ;
1147
1146
struct ice_rx_buf * buf ;
1148
1147
int i ;
1149
1148
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 ++ ) {
1151
1153
buf = & rx_ring -> rx_buf [idx ];
1152
1154
1153
- if (buf -> act & (ICE_XDP_TX | ICE_XDP_REDIR )) {
1155
+ if (verdict & (ICE_XDP_TX | ICE_XDP_REDIR )) {
1154
1156
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 ) {
1157
1159
buf -> pagecnt_bias ++ ;
1158
- } else if (buf -> act == ICE_XDP_PASS ) {
1160
+ } else if (verdict == ICE_XDP_PASS ) {
1159
1161
ice_rx_buf_adjust_pg_offset (buf , xdp -> frame_sz );
1160
1162
}
1161
1163
@@ -1164,6 +1166,17 @@ static void ice_put_rx_mbuf(struct ice_rx_ring *rx_ring, struct xdp_buff *xdp,
1164
1166
if (++ idx == cnt )
1165
1167
idx = 0 ;
1166
1168
}
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
+ }
1167
1180
1168
1181
xdp -> data = NULL ;
1169
1182
rx_ring -> first_desc = ntc ;
@@ -1190,9 +1203,9 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
1190
1203
struct ice_tx_ring * xdp_ring = NULL ;
1191
1204
struct bpf_prog * xdp_prog = NULL ;
1192
1205
u32 ntc = rx_ring -> next_to_clean ;
1206
+ u32 cached_ntu , xdp_verdict ;
1193
1207
u32 cnt = rx_ring -> count ;
1194
1208
u32 xdp_xmit = 0 ;
1195
- u32 cached_ntu ;
1196
1209
bool failure ;
1197
1210
1198
1211
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)
1255
1268
xdp_prepare_buff (xdp , hard_start , offset , size , !!offset );
1256
1269
xdp_buff_clear_frags_flag (xdp );
1257
1270
} 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 );
1259
1272
break ;
1260
1273
}
1261
1274
if (++ ntc == cnt )
@@ -1266,13 +1279,13 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
1266
1279
continue ;
1267
1280
1268
1281
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 )
1271
1284
goto construct_skb ;
1272
1285
total_rx_bytes += xdp_get_buff_len (xdp );
1273
1286
total_rx_pkts ++ ;
1274
1287
1275
- ice_put_rx_mbuf (rx_ring , xdp , & xdp_xmit , ntc );
1288
+ ice_put_rx_mbuf (rx_ring , xdp , & xdp_xmit , ntc , xdp_verdict );
1276
1289
1277
1290
continue ;
1278
1291
construct_skb :
@@ -1283,12 +1296,9 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
1283
1296
/* exit if we failed to retrieve a buffer */
1284
1297
if (!skb ) {
1285
1298
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 ;
1290
1300
}
1291
- ice_put_rx_mbuf (rx_ring , xdp , & xdp_xmit , ntc );
1301
+ ice_put_rx_mbuf (rx_ring , xdp , & xdp_xmit , ntc , xdp_verdict );
1292
1302
1293
1303
if (!skb )
1294
1304
break ;
0 commit comments