Skip to content

Commit 09bff23

Browse files
committed
Merge: virtio_ring: Fix error reporting in virtqueue_resize
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/7101 JIRA: https://issues.redhat.com/browse/RHEL-84199 Enforce minimum TX ring size for reliability The `tx_may_stop()` logic stops TX queues if free descriptors (`sq->vq->num_free`) fall below the threshold of (`MAX_SKB_FRAGS` + 2). If the total ring size (`ring_num`) is not strictly greater than this value, queues can become persistently stopped or stop after minimal use, severely degrading performance. A single sk_buff transmission typically requires descriptors for: - The virtio_net_hdr (1 descriptor) - The sk_buff's linear data (head) (1 descriptor) - Paged fragments (up to MAX_SKB_FRAGS descriptors) Signed-off-by: Laurent Vivier <lvivier@redhat.com> Approved-by: Eugenio Pérez <eperezma@redhat.com> Approved-by: Cindy Lu <lulu@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Augusto Caringi <acaringi@redhat.com>
2 parents da0d31c + 1324ca8 commit 09bff23

File tree

2 files changed

+16
-6
lines changed

2 files changed

+16
-6
lines changed

drivers/net/virtio_net.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -802,15 +802,15 @@ static void check_sq_full_and_disable(struct virtnet_info *vi,
802802
* Since most packets only take 1 or 2 ring slots, stopping the queue
803803
* early means 16 slots are typically wasted.
804804
*/
805-
if (sq->vq->num_free < 2+MAX_SKB_FRAGS) {
805+
if (sq->vq->num_free < MAX_SKB_FRAGS + 2) {
806806
netif_stop_subqueue(dev, qnum);
807807
if (use_napi) {
808808
if (unlikely(!virtqueue_enable_cb_delayed(sq->vq)))
809809
virtqueue_napi_schedule(&sq->napi, sq->vq);
810810
} else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
811811
/* More just got used, free them then recheck. */
812812
free_old_xmit_skbs(sq, false);
813-
if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
813+
if (sq->vq->num_free >= MAX_SKB_FRAGS + 2) {
814814
netif_start_subqueue(dev, qnum);
815815
virtqueue_disable_cb(sq->vq);
816816
}
@@ -2129,7 +2129,7 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
21292129
free_old_xmit_skbs(sq, true);
21302130
} while (unlikely(!virtqueue_enable_cb_delayed(sq->vq)));
21312131

2132-
if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS)
2132+
if (sq->vq->num_free >= MAX_SKB_FRAGS + 2)
21332133
netif_tx_wake_queue(txq);
21342134

21352135
__netif_tx_unlock(txq);
@@ -2250,7 +2250,7 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
22502250
virtqueue_disable_cb(sq->vq);
22512251
free_old_xmit_skbs(sq, true);
22522252

2253-
if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS)
2253+
if (sq->vq->num_free >= MAX_SKB_FRAGS + 2)
22542254
netif_tx_wake_queue(txq);
22552255

22562256
opaque = virtqueue_enable_cb_prepare(sq->vq);
@@ -2410,6 +2410,12 @@ static int virtnet_tx_resize(struct virtnet_info *vi,
24102410
struct netdev_queue *txq;
24112411
int err, qindex;
24122412

2413+
if (ring_num <= MAX_SKB_FRAGS + 2) {
2414+
netdev_err(vi->dev, "tx size (%d) cannot be smaller than %d\n",
2415+
ring_num, (int)MAX_SKB_FRAGS + 2);
2416+
return -EINVAL;
2417+
}
2418+
24132419
qindex = sq - vi->sq;
24142420

24152421
if (running)

drivers/virtio/virtio_ring.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2724,7 +2724,7 @@ int virtqueue_resize(struct virtqueue *_vq, u32 num,
27242724
void (*recycle)(struct virtqueue *vq, void *buf))
27252725
{
27262726
struct vring_virtqueue *vq = to_vvq(_vq);
2727-
int err;
2727+
int err, err_reset;
27282728

27292729
if (num > vq->vq.num_max)
27302730
return -E2BIG;
@@ -2744,7 +2744,11 @@ int virtqueue_resize(struct virtqueue *_vq, u32 num,
27442744
else
27452745
err = virtqueue_resize_split(_vq, num);
27462746

2747-
return virtqueue_enable_after_reset(_vq);
2747+
err_reset = virtqueue_enable_after_reset(_vq);
2748+
if (err_reset)
2749+
return err_reset;
2750+
2751+
return err;
27482752
}
27492753
EXPORT_SYMBOL_GPL(virtqueue_resize);
27502754

0 commit comments

Comments
 (0)