@@ -354,6 +354,8 @@ struct receive_queue {
354
354
355
355
/* xdp rxq used by xsk */
356
356
struct xdp_rxq_info xsk_rxq_info ;
357
+
358
+ struct xdp_buff * * xsk_buffs ;
357
359
};
358
360
359
361
/* This structure can contain rss message with maximum settings for indirection table and keysize
@@ -1054,6 +1056,53 @@ static void check_sq_full_and_disable(struct virtnet_info *vi,
1054
1056
}
1055
1057
}
1056
1058
1059
+ static void sg_fill_dma (struct scatterlist * sg , dma_addr_t addr , u32 len )
1060
+ {
1061
+ sg -> dma_address = addr ;
1062
+ sg -> length = len ;
1063
+ }
1064
+
1065
+ static int virtnet_add_recvbuf_xsk (struct virtnet_info * vi , struct receive_queue * rq ,
1066
+ struct xsk_buff_pool * pool , gfp_t gfp )
1067
+ {
1068
+ struct xdp_buff * * xsk_buffs ;
1069
+ dma_addr_t addr ;
1070
+ int err = 0 ;
1071
+ u32 len , i ;
1072
+ int num ;
1073
+
1074
+ xsk_buffs = rq -> xsk_buffs ;
1075
+
1076
+ num = xsk_buff_alloc_batch (pool , xsk_buffs , rq -> vq -> num_free );
1077
+ if (!num )
1078
+ return - ENOMEM ;
1079
+
1080
+ len = xsk_pool_get_rx_frame_size (pool ) + vi -> hdr_len ;
1081
+
1082
+ for (i = 0 ; i < num ; ++ i ) {
1083
+ /* Use the part of XDP_PACKET_HEADROOM as the virtnet hdr space.
1084
+ * We assume XDP_PACKET_HEADROOM is larger than hdr->len.
1085
+ * (see function virtnet_xsk_pool_enable)
1086
+ */
1087
+ addr = xsk_buff_xdp_get_dma (xsk_buffs [i ]) - vi -> hdr_len ;
1088
+
1089
+ sg_init_table (rq -> sg , 1 );
1090
+ sg_fill_dma (rq -> sg , addr , len );
1091
+
1092
+ err = virtqueue_add_inbuf (rq -> vq , rq -> sg , 1 , xsk_buffs [i ], gfp );
1093
+ if (err )
1094
+ goto err ;
1095
+ }
1096
+
1097
+ return num ;
1098
+
1099
+ err :
1100
+ for (; i < num ; ++ i )
1101
+ xsk_buff_free (xsk_buffs [i ]);
1102
+
1103
+ return err ;
1104
+ }
1105
+
1057
1106
static int virtnet_xsk_wakeup (struct net_device * dev , u32 qid , u32 flag )
1058
1107
{
1059
1108
struct virtnet_info * vi = netdev_priv (dev );
@@ -2245,7 +2294,11 @@ static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq,
2245
2294
gfp_t gfp )
2246
2295
{
2247
2296
int err ;
2248
- bool oom ;
2297
+
2298
+ if (rq -> xsk_pool ) {
2299
+ err = virtnet_add_recvbuf_xsk (vi , rq , rq -> xsk_pool , gfp );
2300
+ goto kick ;
2301
+ }
2249
2302
2250
2303
do {
2251
2304
if (vi -> mergeable_rx_bufs )
@@ -2255,10 +2308,11 @@ static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq,
2255
2308
else
2256
2309
err = add_recvbuf_small (vi , rq , gfp );
2257
2310
2258
- oom = err == - ENOMEM ;
2259
2311
if (err )
2260
2312
break ;
2261
2313
} while (rq -> vq -> num_free );
2314
+
2315
+ kick :
2262
2316
if (virtqueue_kick_prepare (rq -> vq ) && virtqueue_notify (rq -> vq )) {
2263
2317
unsigned long flags ;
2264
2318
@@ -2267,7 +2321,7 @@ static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq,
2267
2321
u64_stats_update_end_irqrestore (& rq -> stats .syncp , flags );
2268
2322
}
2269
2323
2270
- return ! oom ;
2324
+ return err != - ENOMEM ;
2271
2325
}
2272
2326
2273
2327
static void skb_recv_done (struct virtqueue * rvq )
@@ -5104,7 +5158,7 @@ static int virtnet_xsk_pool_enable(struct net_device *dev,
5104
5158
struct receive_queue * rq ;
5105
5159
struct device * dma_dev ;
5106
5160
struct send_queue * sq ;
5107
- int err ;
5161
+ int err , size ;
5108
5162
5109
5163
if (vi -> hdr_len > xsk_pool_get_headroom (pool ))
5110
5164
return - EINVAL ;
@@ -5135,6 +5189,12 @@ static int virtnet_xsk_pool_enable(struct net_device *dev,
5135
5189
if (!dma_dev )
5136
5190
return - EINVAL ;
5137
5191
5192
+ size = virtqueue_get_vring_size (rq -> vq );
5193
+
5194
+ rq -> xsk_buffs = kvcalloc (size , sizeof (* rq -> xsk_buffs ), GFP_KERNEL );
5195
+ if (!rq -> xsk_buffs )
5196
+ return - ENOMEM ;
5197
+
5138
5198
err = xsk_pool_dma_map (pool , dma_dev , 0 );
5139
5199
if (err )
5140
5200
goto err_xsk_map ;
@@ -5169,6 +5229,8 @@ static int virtnet_xsk_pool_disable(struct net_device *dev, u16 qid)
5169
5229
5170
5230
xsk_pool_dma_unmap (pool , 0 );
5171
5231
5232
+ kvfree (rq -> xsk_buffs );
5233
+
5172
5234
return err ;
5173
5235
}
5174
5236
0 commit comments