Skip to content

Commit b0727b0

Browse files
author
Paolo Abeni
committed
Merge branch 'virtio-fixes-for-tx-ring-sizing-and-resize-error-reporting'
Laurent Vivier says: ==================== virtio: Fixes for TX ring sizing and resize error reporting This patch series contains two fixes and a cleanup for the virtio subsystem. The first patch fixes an error reporting bug in virtio_ring's virtqueue_resize() function. Previously, errors from internal resize helpers could be masked if the subsequent re-enabling of the virtqueue succeeded. This patch restores the correct error propagation, ensuring that callers of virtqueue_resize() are properly informed of underlying resize failures. The second patch does a cleanup of the use of '2+MAX_SKB_FRAGS' The third patch addresses a reliability issue in virtio_net where the TX ring size could be configured too small, potentially leading to persistently stopped queues and degraded performance. It enforces a minimum TX ring size to ensure there's always enough space for at least one maximally-fragmented packet plus an additional slot. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 5177373 + 24b2f5d commit b0727b0

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
@@ -1104,7 +1104,7 @@ static bool tx_may_stop(struct virtnet_info *vi,
11041104
* Since most packets only take 1 or 2 ring slots, stopping the queue
11051105
* early means 16 slots are typically wasted.
11061106
*/
1107-
if (sq->vq->num_free < 2+MAX_SKB_FRAGS) {
1107+
if (sq->vq->num_free < MAX_SKB_FRAGS + 2) {
11081108
struct netdev_queue *txq = netdev_get_tx_queue(dev, qnum);
11091109

11101110
netif_tx_stop_queue(txq);
@@ -1136,7 +1136,7 @@ static void check_sq_full_and_disable(struct virtnet_info *vi,
11361136
} else if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
11371137
/* More just got used, free them then recheck. */
11381138
free_old_xmit(sq, txq, false);
1139-
if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
1139+
if (sq->vq->num_free >= MAX_SKB_FRAGS + 2) {
11401140
netif_start_subqueue(dev, qnum);
11411141
u64_stats_update_begin(&sq->stats.syncp);
11421142
u64_stats_inc(&sq->stats.wake);
@@ -3021,7 +3021,7 @@ static void virtnet_poll_cleantx(struct receive_queue *rq, int budget)
30213021
free_old_xmit(sq, txq, !!budget);
30223022
} while (unlikely(!virtqueue_enable_cb_delayed(sq->vq)));
30233023

3024-
if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) {
3024+
if (sq->vq->num_free >= MAX_SKB_FRAGS + 2) {
30253025
if (netif_tx_queue_stopped(txq)) {
30263026
u64_stats_update_begin(&sq->stats.syncp);
30273027
u64_stats_inc(&sq->stats.wake);
@@ -3218,7 +3218,7 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
32183218
else
32193219
free_old_xmit(sq, txq, !!budget);
32203220

3221-
if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) {
3221+
if (sq->vq->num_free >= MAX_SKB_FRAGS + 2) {
32223222
if (netif_tx_queue_stopped(txq)) {
32233223
u64_stats_update_begin(&sq->stats.syncp);
32243224
u64_stats_inc(&sq->stats.wake);
@@ -3504,6 +3504,12 @@ static int virtnet_tx_resize(struct virtnet_info *vi, struct send_queue *sq,
35043504
{
35053505
int qindex, err;
35063506

3507+
if (ring_num <= MAX_SKB_FRAGS + 2) {
3508+
netdev_err(vi->dev, "tx size (%d) cannot be smaller than %d\n",
3509+
ring_num, MAX_SKB_FRAGS + 2);
3510+
return -EINVAL;
3511+
}
3512+
35073513
qindex = sq - vi->sq;
35083514

35093515
virtnet_tx_pause(vi, sq);

drivers/virtio/virtio_ring.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2797,7 +2797,7 @@ int virtqueue_resize(struct virtqueue *_vq, u32 num,
27972797
void (*recycle_done)(struct virtqueue *vq))
27982798
{
27992799
struct vring_virtqueue *vq = to_vvq(_vq);
2800-
int err;
2800+
int err, err_reset;
28012801

28022802
if (num > vq->vq.num_max)
28032803
return -E2BIG;
@@ -2819,7 +2819,11 @@ int virtqueue_resize(struct virtqueue *_vq, u32 num,
28192819
else
28202820
err = virtqueue_resize_split(_vq, num);
28212821

2822-
return virtqueue_enable_after_reset(_vq);
2822+
err_reset = virtqueue_enable_after_reset(_vq);
2823+
if (err_reset)
2824+
return err_reset;
2825+
2826+
return err;
28232827
}
28242828
EXPORT_SYMBOL_GPL(virtqueue_resize);
28252829

0 commit comments

Comments
 (0)