Skip to content

Commit 13e9beb

Browse files
committed
Merge: virtio_ring: Fix error reporting in virtqueue_resize
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10/-/merge_requests/1170 JIRA: https://issues.redhat.com/browse/RHEL-84409 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: Julio Faracco <jfaracco@redhat.com>
2 parents eaa18a1 + b82bafb commit 13e9beb

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
@@ -1065,7 +1065,7 @@ static void check_sq_full_and_disable(struct virtnet_info *vi,
10651065
* Since most packets only take 1 or 2 ring slots, stopping the queue
10661066
* early means 16 slots are typically wasted.
10671067
*/
1068-
if (sq->vq->num_free < 2+MAX_SKB_FRAGS) {
1068+
if (sq->vq->num_free < MAX_SKB_FRAGS + 2) {
10691069
struct netdev_queue *txq = netdev_get_tx_queue(dev, qnum);
10701070

10711071
netif_tx_stop_queue(txq);
@@ -1078,7 +1078,7 @@ static void check_sq_full_and_disable(struct virtnet_info *vi,
10781078
} else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
10791079
/* More just got used, free them then recheck. */
10801080
free_old_xmit(sq, txq, false);
1081-
if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
1081+
if (sq->vq->num_free >= MAX_SKB_FRAGS + 2) {
10821082
netif_start_subqueue(dev, qnum);
10831083
u64_stats_update_begin(&sq->stats.syncp);
10841084
u64_stats_inc(&sq->stats.wake);
@@ -2797,7 +2797,7 @@ static void virtnet_poll_cleantx(struct receive_queue *rq, int budget)
27972797
free_old_xmit(sq, txq, !!budget);
27982798
} while (unlikely(!virtqueue_enable_cb_delayed(sq->vq)));
27992799

2800-
if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) {
2800+
if (sq->vq->num_free >= MAX_SKB_FRAGS + 2) {
28012801
if (netif_tx_queue_stopped(txq)) {
28022802
u64_stats_update_begin(&sq->stats.syncp);
28032803
u64_stats_inc(&sq->stats.wake);
@@ -2990,7 +2990,7 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
29902990
virtqueue_disable_cb(sq->vq);
29912991
free_old_xmit(sq, txq, !!budget);
29922992

2993-
if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) {
2993+
if (sq->vq->num_free >= MAX_SKB_FRAGS + 2) {
29942994
if (netif_tx_queue_stopped(txq)) {
29952995
u64_stats_update_begin(&sq->stats.syncp);
29962996
u64_stats_inc(&sq->stats.wake);
@@ -3219,6 +3219,12 @@ static int virtnet_tx_resize(struct virtnet_info *vi, struct send_queue *sq,
32193219
{
32203220
int qindex, err;
32213221

3222+
if (ring_num <= MAX_SKB_FRAGS + 2) {
3223+
netdev_err(vi->dev, "tx size (%d) cannot be smaller than %d\n",
3224+
ring_num, MAX_SKB_FRAGS + 2);
3225+
return -EINVAL;
3226+
}
3227+
32223228
qindex = sq - vi->sq;
32233229

32243230
virtnet_tx_pause(vi, sq);

drivers/virtio/virtio_ring.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2741,7 +2741,7 @@ int virtqueue_resize(struct virtqueue *_vq, u32 num,
27412741
void (*recycle_done)(struct virtqueue *vq))
27422742
{
27432743
struct vring_virtqueue *vq = to_vvq(_vq);
2744-
int err;
2744+
int err, err_reset;
27452745

27462746
if (num > vq->vq.num_max)
27472747
return -E2BIG;
@@ -2763,7 +2763,11 @@ int virtqueue_resize(struct virtqueue *_vq, u32 num,
27632763
else
27642764
err = virtqueue_resize_split(_vq, num);
27652765

2766-
return virtqueue_enable_after_reset(_vq);
2766+
err_reset = virtqueue_enable_after_reset(_vq);
2767+
if (err_reset)
2768+
return err_reset;
2769+
2770+
return err;
27672771
}
27682772
EXPORT_SYMBOL_GPL(virtqueue_resize);
27692773

0 commit comments

Comments
 (0)