virtio-net: fix the vq coalescing setting for vq resize
authorHeng Qi <hengqi@linux.alibaba.com>
Sun, 8 Oct 2023 06:27:43 +0000 (14:27 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Nov 2023 10:59:01 +0000 (11:59 +0100)
[ Upstream commit f61fe5f081cf40de08d0a4c89659baf23c900f0c ]

According to the definition of virtqueue coalescing spec[1]:

  Upon disabling and re-enabling a transmit virtqueue, the device MUST set
  the coalescing parameters of the virtqueue to those configured through the
  VIRTIO_NET_CTRL_NOTF_COAL_TX_SET command, or, if the driver did not set
  any TX coalescing parameters, to 0.

  Upon disabling and re-enabling a receive virtqueue, the device MUST set
  the coalescing parameters of the virtqueue to those configured through the
  VIRTIO_NET_CTRL_NOTF_COAL_RX_SET command, or, if the driver did not set
  any RX coalescing parameters, to 0.

We need to add this setting for vq resize (ethtool -G) where vq_reset happens.

[1] https://lists.oasis-open.org/archives/virtio-dev/202303/msg00415.html

Fixes: 394bd87764b6 ("virtio_net: support per queue interrupt coalesce command")
Cc: Gavin Li <gavinl@nvidia.com>
Signed-off-by: Heng Qi <hengqi@linux.alibaba.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/virtio_net.c

index 4211f28..cd1e9e8 100644 (file)
@@ -2855,6 +2855,9 @@ static void virtnet_get_ringparam(struct net_device *dev,
        ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
 }
 
+static int virtnet_send_ctrl_coal_vq_cmd(struct virtnet_info *vi,
+                                        u16 vqn, u32 max_usecs, u32 max_packets);
+
 static int virtnet_set_ringparam(struct net_device *dev,
                                 struct ethtool_ringparam *ring,
                                 struct kernel_ethtool_ringparam *kernel_ring,
@@ -2890,12 +2893,36 @@ static int virtnet_set_ringparam(struct net_device *dev,
                        err = virtnet_tx_resize(vi, sq, ring->tx_pending);
                        if (err)
                                return err;
+
+                       /* Upon disabling and re-enabling a transmit virtqueue, the device must
+                        * set the coalescing parameters of the virtqueue to those configured
+                        * through the VIRTIO_NET_CTRL_NOTF_COAL_TX_SET command, or, if the driver
+                        * did not set any TX coalescing parameters, to 0.
+                        */
+                       err = virtnet_send_ctrl_coal_vq_cmd(vi, txq2vq(i),
+                                                           vi->intr_coal_tx.max_usecs,
+                                                           vi->intr_coal_tx.max_packets);
+                       if (err)
+                               return err;
+
+                       vi->sq[i].intr_coal.max_usecs = vi->intr_coal_tx.max_usecs;
+                       vi->sq[i].intr_coal.max_packets = vi->intr_coal_tx.max_packets;
                }
 
                if (ring->rx_pending != rx_pending) {
                        err = virtnet_rx_resize(vi, rq, ring->rx_pending);
                        if (err)
                                return err;
+
+                       /* The reason is same as the transmit virtqueue reset */
+                       err = virtnet_send_ctrl_coal_vq_cmd(vi, rxq2vq(i),
+                                                           vi->intr_coal_rx.max_usecs,
+                                                           vi->intr_coal_rx.max_packets);
+                       if (err)
+                               return err;
+
+                       vi->rq[i].intr_coal.max_usecs = vi->intr_coal_rx.max_usecs;
+                       vi->rq[i].intr_coal.max_packets = vi->intr_coal_rx.max_packets;
                }
        }