Skip to content

Commit e9f3962

Browse files
fengidrikuba-moo
authored andcommitted
virtio_net: xsk: rx: support fill with xsk buffer
Implement the logic of filling rq with XSK buffers. Signed-off-by: Xuan Zhuo <[email protected]> Acked-by: Jason Wang <[email protected]> Acked-by: Michael S. Tsirkin <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 19a5a77 commit e9f3962

File tree

1 file changed

+66
-4
lines changed

1 file changed

+66
-4
lines changed

drivers/net/virtio_net.c

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
10571106
static 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

22732327
static 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

Comments
 (0)