@@ -354,6 +354,8 @@ struct receive_queue {
354354
355355 /* xdp rxq used by xsk */
356356 struct xdp_rxq_info xsk_rxq_info ;
357+
358+ struct xdp_buff * * xsk_buffs ;
357359};
358360
359361/* 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,
10541056 }
10551057}
10561058
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+
10571106static int virtnet_xsk_wakeup (struct net_device * dev , u32 qid , u32 flag )
10581107{
10591108 struct virtnet_info * vi = netdev_priv (dev );
@@ -2245,7 +2294,11 @@ static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq,
22452294 gfp_t gfp )
22462295{
22472296 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+ }
22492302
22502303 do {
22512304 if (vi -> mergeable_rx_bufs )
@@ -2255,10 +2308,11 @@ static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq,
22552308 else
22562309 err = add_recvbuf_small (vi , rq , gfp );
22572310
2258- oom = err == - ENOMEM ;
22592311 if (err )
22602312 break ;
22612313 } while (rq -> vq -> num_free );
2314+
2315+ kick :
22622316 if (virtqueue_kick_prepare (rq -> vq ) && virtqueue_notify (rq -> vq )) {
22632317 unsigned long flags ;
22642318
@@ -2267,7 +2321,7 @@ static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq,
22672321 u64_stats_update_end_irqrestore (& rq -> stats .syncp , flags );
22682322 }
22692323
2270- return ! oom ;
2324+ return err != - ENOMEM ;
22712325}
22722326
22732327static void skb_recv_done (struct virtqueue * rvq )
@@ -5104,7 +5158,7 @@ static int virtnet_xsk_pool_enable(struct net_device *dev,
51045158 struct receive_queue * rq ;
51055159 struct device * dma_dev ;
51065160 struct send_queue * sq ;
5107- int err ;
5161+ int err , size ;
51085162
51095163 if (vi -> hdr_len > xsk_pool_get_headroom (pool ))
51105164 return - EINVAL ;
@@ -5135,6 +5189,12 @@ static int virtnet_xsk_pool_enable(struct net_device *dev,
51355189 if (!dma_dev )
51365190 return - EINVAL ;
51375191
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+
51385198 err = xsk_pool_dma_map (pool , dma_dev , 0 );
51395199 if (err )
51405200 goto err_xsk_map ;
@@ -5169,6 +5229,8 @@ static int virtnet_xsk_pool_disable(struct net_device *dev, u16 qid)
51695229
51705230 xsk_pool_dma_unmap (pool , 0 );
51715231
5232+ kvfree (rq -> xsk_buffs );
5233+
51725234 return err ;
51735235}
51745236
0 commit comments