All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 00/26] virtio pci support VIRTIO_F_RING_RESET
@ 2022-03-08 12:34 ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

The virtio spec already supports the virtio queue reset function. This patch set
is to add this function to the kernel. The relevant virtio spec information is
here:

    https://github.com/oasis-tcs/virtio-spec/issues/124

Also regarding MMIO support for queue reset, I plan to support it after this
patch is passed.

Performing reset on a queue is divided into four steps:
     1. virtio_reset_vq()              - notify the device to reset the queue
     2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
     3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
     4. virtio_enable_resetq()         - mmap vring to device, and enable the queue

The first part 1-17 of this patch set implements virtio pci's support and API
for queue reset. The latter part is to make virtio-net support set_ringparam. Do
these things for this feature:

      1. virtio-net support rx,tx reset
      2. find_vqs() support to special the max size of each vq
      3. virtio-net support set_ringparam

#1 -#3 :       prepare
#4 -#12:       virtio ring support reset vring of the vq
#13-#14:       add helper
#15-#17:       virtio pci support reset queue and re-enable
#18-#21:       find_vqs() support sizes to special the max size of each vq
#23-#24:       virtio-net support rx, tx reset
#22, #25, #26: virtio-net support set ringparam

Test environment:
    Host: 4.19.91
    Qemu: QEMU emulator version 6.2.50 (with vq reset support)
    Test Cmd:  ethtool -G eth1 rx $1 tx $2; ethtool -g eth1

    The default is split mode, modify Qemu virtio-net to add PACKED feature to test
    packed mode.


Please review. Thanks.

v7:
  1. fix #6 subject typo
  2. fix #6 ring_size_in_bytes is uninitialized
  3. check by: make W=12

v6:
  1. virtio_pci: use synchronize_irq(irq) to sync the irq callbacks
  2. Introduce virtqueue_reset_vring() to implement the reset of vring during
     the reset process. May use the old vring if num of the vq not change.
  3. find_vqs() support sizes to special the max size of each vq

v5:
  1. add virtio-net support set_ringparam

v4:
  1. just the code of virtio, without virtio-net
  2. Performing reset on a queue is divided into these steps:
    1. reset_vq: reset one vq
    2. recycle the buffer from vq by virtqueue_detach_unused_buf()
    3. release the ring of the vq by vring_release_virtqueue()
    4. enable_reset_vq: re-enable the reset queue
  3. Simplify the parameters of enable_reset_vq()
  4. add container structures for virtio_pci_common_cfg

v3:
  1. keep vq, irq unreleased

*** BLURB HERE ***

Xuan Zhuo (26):
  virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
  virtio: queue_reset: add VIRTIO_F_RING_RESET
  virtio: add helper virtqueue_get_vring_max_size()
  virtio_ring: split: extract the logic of creating vring
  virtio_ring: split: extract the logic of init vq and attach vring
  virtio_ring: packed: extract the logic of creating vring
  virtio_ring: packed: extract the logic of init vq and attach vring
  virtio_ring: extract the logic of freeing vring
  virtio_ring: split: implement virtqueue_reset_vring_split()
  virtio_ring: packed: implement virtqueue_reset_vring_packed()
  virtio_ring: introduce virtqueue_reset_vring()
  virtio_ring: update the document of the virtqueue_detach_unused_buf
    for queue reset
  virtio: queue_reset: struct virtio_config_ops add callbacks for
    queue_reset
  virtio: add helper for queue reset
  virtio_pci: queue_reset: update struct virtio_pci_common_cfg and
    option functions
  virtio_pci: queue_reset: extract the logic of active vq for modern pci
  virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
  virtio: find_vqs() add arg sizes
  virtio_pci: support the arg sizes of find_vqs()
  virtio_mmio: support the arg sizes of find_vqs()
  virtio: add helper virtio_find_vqs_ctx_size()
  virtio_net: get ringparam by virtqueue_get_vring_max_size()
  virtio_net: split free_unused_bufs()
  virtio_net: support rx/tx queue reset
  virtio_net: set the default max ring size by find_vqs()
  virtio_net: support set_ringparam

 arch/um/drivers/virtio_uml.c             |   2 +-
 drivers/net/virtio_net.c                 | 257 ++++++++--
 drivers/platform/mellanox/mlxbf-tmfifo.c |   3 +-
 drivers/remoteproc/remoteproc_virtio.c   |   2 +-
 drivers/s390/virtio/virtio_ccw.c         |   2 +-
 drivers/virtio/virtio_mmio.c             |  12 +-
 drivers/virtio/virtio_pci_common.c       |  28 +-
 drivers/virtio/virtio_pci_common.h       |   3 +-
 drivers/virtio/virtio_pci_legacy.c       |   8 +-
 drivers/virtio/virtio_pci_modern.c       | 146 +++++-
 drivers/virtio/virtio_pci_modern_dev.c   |  36 ++
 drivers/virtio/virtio_ring.c             | 584 +++++++++++++++++------
 drivers/virtio/virtio_vdpa.c             |   2 +-
 include/linux/virtio.h                   |  12 +
 include/linux/virtio_config.h            |  74 ++-
 include/linux/virtio_pci_modern.h        |   2 +
 include/uapi/linux/virtio_config.h       |   7 +-
 include/uapi/linux/virtio_pci.h          |  14 +
 18 files changed, 979 insertions(+), 215 deletions(-)

--
2.31.0


^ permalink raw reply	[flat|nested] 218+ messages in thread

* [PATCH v7 00/26] virtio pci support VIRTIO_F_RING_RESET
@ 2022-03-08 12:34 ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

The virtio spec already supports the virtio queue reset function. This patch set
is to add this function to the kernel. The relevant virtio spec information is
here:

    https://github.com/oasis-tcs/virtio-spec/issues/124

Also regarding MMIO support for queue reset, I plan to support it after this
patch is passed.

Performing reset on a queue is divided into four steps:
     1. virtio_reset_vq()              - notify the device to reset the queue
     2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
     3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
     4. virtio_enable_resetq()         - mmap vring to device, and enable the queue

The first part 1-17 of this patch set implements virtio pci's support and API
for queue reset. The latter part is to make virtio-net support set_ringparam. Do
these things for this feature:

      1. virtio-net support rx,tx reset
      2. find_vqs() support to special the max size of each vq
      3. virtio-net support set_ringparam

#1 -#3 :       prepare
#4 -#12:       virtio ring support reset vring of the vq
#13-#14:       add helper
#15-#17:       virtio pci support reset queue and re-enable
#18-#21:       find_vqs() support sizes to special the max size of each vq
#23-#24:       virtio-net support rx, tx reset
#22, #25, #26: virtio-net support set ringparam

Test environment:
    Host: 4.19.91
    Qemu: QEMU emulator version 6.2.50 (with vq reset support)
    Test Cmd:  ethtool -G eth1 rx $1 tx $2; ethtool -g eth1

    The default is split mode, modify Qemu virtio-net to add PACKED feature to test
    packed mode.


Please review. Thanks.

v7:
  1. fix #6 subject typo
  2. fix #6 ring_size_in_bytes is uninitialized
  3. check by: make W=12

v6:
  1. virtio_pci: use synchronize_irq(irq) to sync the irq callbacks
  2. Introduce virtqueue_reset_vring() to implement the reset of vring during
     the reset process. May use the old vring if num of the vq not change.
  3. find_vqs() support sizes to special the max size of each vq

v5:
  1. add virtio-net support set_ringparam

v4:
  1. just the code of virtio, without virtio-net
  2. Performing reset on a queue is divided into these steps:
    1. reset_vq: reset one vq
    2. recycle the buffer from vq by virtqueue_detach_unused_buf()
    3. release the ring of the vq by vring_release_virtqueue()
    4. enable_reset_vq: re-enable the reset queue
  3. Simplify the parameters of enable_reset_vq()
  4. add container structures for virtio_pci_common_cfg

v3:
  1. keep vq, irq unreleased

*** BLURB HERE ***

Xuan Zhuo (26):
  virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
  virtio: queue_reset: add VIRTIO_F_RING_RESET
  virtio: add helper virtqueue_get_vring_max_size()
  virtio_ring: split: extract the logic of creating vring
  virtio_ring: split: extract the logic of init vq and attach vring
  virtio_ring: packed: extract the logic of creating vring
  virtio_ring: packed: extract the logic of init vq and attach vring
  virtio_ring: extract the logic of freeing vring
  virtio_ring: split: implement virtqueue_reset_vring_split()
  virtio_ring: packed: implement virtqueue_reset_vring_packed()
  virtio_ring: introduce virtqueue_reset_vring()
  virtio_ring: update the document of the virtqueue_detach_unused_buf
    for queue reset
  virtio: queue_reset: struct virtio_config_ops add callbacks for
    queue_reset
  virtio: add helper for queue reset
  virtio_pci: queue_reset: update struct virtio_pci_common_cfg and
    option functions
  virtio_pci: queue_reset: extract the logic of active vq for modern pci
  virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
  virtio: find_vqs() add arg sizes
  virtio_pci: support the arg sizes of find_vqs()
  virtio_mmio: support the arg sizes of find_vqs()
  virtio: add helper virtio_find_vqs_ctx_size()
  virtio_net: get ringparam by virtqueue_get_vring_max_size()
  virtio_net: split free_unused_bufs()
  virtio_net: support rx/tx queue reset
  virtio_net: set the default max ring size by find_vqs()
  virtio_net: support set_ringparam

 arch/um/drivers/virtio_uml.c             |   2 +-
 drivers/net/virtio_net.c                 | 257 ++++++++--
 drivers/platform/mellanox/mlxbf-tmfifo.c |   3 +-
 drivers/remoteproc/remoteproc_virtio.c   |   2 +-
 drivers/s390/virtio/virtio_ccw.c         |   2 +-
 drivers/virtio/virtio_mmio.c             |  12 +-
 drivers/virtio/virtio_pci_common.c       |  28 +-
 drivers/virtio/virtio_pci_common.h       |   3 +-
 drivers/virtio/virtio_pci_legacy.c       |   8 +-
 drivers/virtio/virtio_pci_modern.c       | 146 +++++-
 drivers/virtio/virtio_pci_modern_dev.c   |  36 ++
 drivers/virtio/virtio_ring.c             | 584 +++++++++++++++++------
 drivers/virtio/virtio_vdpa.c             |   2 +-
 include/linux/virtio.h                   |  12 +
 include/linux/virtio_config.h            |  74 ++-
 include/linux/virtio_pci_modern.h        |   2 +
 include/uapi/linux/virtio_config.h       |   7 +-
 include/uapi/linux/virtio_pci.h          |  14 +
 18 files changed, 979 insertions(+), 215 deletions(-)

--
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* [PATCH v7 00/26] virtio pci support VIRTIO_F_RING_RESET
@ 2022-03-08 12:34 ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

The virtio spec already supports the virtio queue reset function. This patch set
is to add this function to the kernel. The relevant virtio spec information is
here:

    https://github.com/oasis-tcs/virtio-spec/issues/124

Also regarding MMIO support for queue reset, I plan to support it after this
patch is passed.

Performing reset on a queue is divided into four steps:
     1. virtio_reset_vq()              - notify the device to reset the queue
     2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
     3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
     4. virtio_enable_resetq()         - mmap vring to device, and enable the queue

The first part 1-17 of this patch set implements virtio pci's support and API
for queue reset. The latter part is to make virtio-net support set_ringparam. Do
these things for this feature:

      1. virtio-net support rx,tx reset
      2. find_vqs() support to special the max size of each vq
      3. virtio-net support set_ringparam

#1 -#3 :       prepare
#4 -#12:       virtio ring support reset vring of the vq
#13-#14:       add helper
#15-#17:       virtio pci support reset queue and re-enable
#18-#21:       find_vqs() support sizes to special the max size of each vq
#23-#24:       virtio-net support rx, tx reset
#22, #25, #26: virtio-net support set ringparam

Test environment:
    Host: 4.19.91
    Qemu: QEMU emulator version 6.2.50 (with vq reset support)
    Test Cmd:  ethtool -G eth1 rx $1 tx $2; ethtool -g eth1

    The default is split mode, modify Qemu virtio-net to add PACKED feature to test
    packed mode.


Please review. Thanks.

v7:
  1. fix #6 subject typo
  2. fix #6 ring_size_in_bytes is uninitialized
  3. check by: make W=12

v6:
  1. virtio_pci: use synchronize_irq(irq) to sync the irq callbacks
  2. Introduce virtqueue_reset_vring() to implement the reset of vring during
     the reset process. May use the old vring if num of the vq not change.
  3. find_vqs() support sizes to special the max size of each vq

v5:
  1. add virtio-net support set_ringparam

v4:
  1. just the code of virtio, without virtio-net
  2. Performing reset on a queue is divided into these steps:
    1. reset_vq: reset one vq
    2. recycle the buffer from vq by virtqueue_detach_unused_buf()
    3. release the ring of the vq by vring_release_virtqueue()
    4. enable_reset_vq: re-enable the reset queue
  3. Simplify the parameters of enable_reset_vq()
  4. add container structures for virtio_pci_common_cfg

v3:
  1. keep vq, irq unreleased

*** BLURB HERE ***

Xuan Zhuo (26):
  virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
  virtio: queue_reset: add VIRTIO_F_RING_RESET
  virtio: add helper virtqueue_get_vring_max_size()
  virtio_ring: split: extract the logic of creating vring
  virtio_ring: split: extract the logic of init vq and attach vring
  virtio_ring: packed: extract the logic of creating vring
  virtio_ring: packed: extract the logic of init vq and attach vring
  virtio_ring: extract the logic of freeing vring
  virtio_ring: split: implement virtqueue_reset_vring_split()
  virtio_ring: packed: implement virtqueue_reset_vring_packed()
  virtio_ring: introduce virtqueue_reset_vring()
  virtio_ring: update the document of the virtqueue_detach_unused_buf
    for queue reset
  virtio: queue_reset: struct virtio_config_ops add callbacks for
    queue_reset
  virtio: add helper for queue reset
  virtio_pci: queue_reset: update struct virtio_pci_common_cfg and
    option functions
  virtio_pci: queue_reset: extract the logic of active vq for modern pci
  virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
  virtio: find_vqs() add arg sizes
  virtio_pci: support the arg sizes of find_vqs()
  virtio_mmio: support the arg sizes of find_vqs()
  virtio: add helper virtio_find_vqs_ctx_size()
  virtio_net: get ringparam by virtqueue_get_vring_max_size()
  virtio_net: split free_unused_bufs()
  virtio_net: support rx/tx queue reset
  virtio_net: set the default max ring size by find_vqs()
  virtio_net: support set_ringparam

 arch/um/drivers/virtio_uml.c             |   2 +-
 drivers/net/virtio_net.c                 | 257 ++++++++--
 drivers/platform/mellanox/mlxbf-tmfifo.c |   3 +-
 drivers/remoteproc/remoteproc_virtio.c   |   2 +-
 drivers/s390/virtio/virtio_ccw.c         |   2 +-
 drivers/virtio/virtio_mmio.c             |  12 +-
 drivers/virtio/virtio_pci_common.c       |  28 +-
 drivers/virtio/virtio_pci_common.h       |   3 +-
 drivers/virtio/virtio_pci_legacy.c       |   8 +-
 drivers/virtio/virtio_pci_modern.c       | 146 +++++-
 drivers/virtio/virtio_pci_modern_dev.c   |  36 ++
 drivers/virtio/virtio_ring.c             | 584 +++++++++++++++++------
 drivers/virtio/virtio_vdpa.c             |   2 +-
 include/linux/virtio.h                   |  12 +
 include/linux/virtio_config.h            |  74 ++-
 include/linux/virtio_pci_modern.h        |   2 +
 include/uapi/linux/virtio_config.h       |   7 +-
 include/uapi/linux/virtio_pci.h          |  14 +
 18 files changed, 979 insertions(+), 215 deletions(-)

--
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 218+ messages in thread

* [PATCH v7 01/26] virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:34   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Add queue_notify_data in struct virtio_pci_common_cfg, which comes from
here https://github.com/oasis-tcs/virtio-spec/issues/89

For not breaks uABI, add a new struct virtio_pci_common_cfg_notify.

Since I want to add queue_reset after queue_notify_data, I submitted
this patch first.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/uapi/linux/virtio_pci.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
index 3a86f36d7e3d..22bec9bd0dfc 100644
--- a/include/uapi/linux/virtio_pci.h
+++ b/include/uapi/linux/virtio_pci.h
@@ -166,6 +166,13 @@ struct virtio_pci_common_cfg {
 	__le32 queue_used_hi;		/* read-write */
 };
 
+struct virtio_pci_common_cfg_notify {
+	struct virtio_pci_common_cfg cfg;
+
+	__le16 queue_notify_data;	/* read-write */
+	__le16 padding;
+};
+
 /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
 struct virtio_pci_cfg_cap {
 	struct virtio_pci_cap cap;
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 01/26] virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Add queue_notify_data in struct virtio_pci_common_cfg, which comes from
here https://github.com/oasis-tcs/virtio-spec/issues/89

For not breaks uABI, add a new struct virtio_pci_common_cfg_notify.

Since I want to add queue_reset after queue_notify_data, I submitted
this patch first.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/uapi/linux/virtio_pci.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
index 3a86f36d7e3d..22bec9bd0dfc 100644
--- a/include/uapi/linux/virtio_pci.h
+++ b/include/uapi/linux/virtio_pci.h
@@ -166,6 +166,13 @@ struct virtio_pci_common_cfg {
 	__le32 queue_used_hi;		/* read-write */
 };
 
+struct virtio_pci_common_cfg_notify {
+	struct virtio_pci_common_cfg cfg;
+
+	__le16 queue_notify_data;	/* read-write */
+	__le16 padding;
+};
+
 /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
 struct virtio_pci_cfg_cap {
 	struct virtio_pci_cap cap;
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 01/26] virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Add queue_notify_data in struct virtio_pci_common_cfg, which comes from
here https://github.com/oasis-tcs/virtio-spec/issues/89

For not breaks uABI, add a new struct virtio_pci_common_cfg_notify.

Since I want to add queue_reset after queue_notify_data, I submitted
this patch first.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/uapi/linux/virtio_pci.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
index 3a86f36d7e3d..22bec9bd0dfc 100644
--- a/include/uapi/linux/virtio_pci.h
+++ b/include/uapi/linux/virtio_pci.h
@@ -166,6 +166,13 @@ struct virtio_pci_common_cfg {
 	__le32 queue_used_hi;		/* read-write */
 };
 
+struct virtio_pci_common_cfg_notify {
+	struct virtio_pci_common_cfg cfg;
+
+	__le16 queue_notify_data;	/* read-write */
+	__le16 padding;
+};
+
 /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
 struct virtio_pci_cfg_cap {
 	struct virtio_pci_cap cap;
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 02/26] virtio: queue_reset: add VIRTIO_F_RING_RESET
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:34   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Added VIRTIO_F_RING_RESET, it came from here
https://github.com/oasis-tcs/virtio-spec/issues/124

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/uapi/linux/virtio_config.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/virtio_config.h b/include/uapi/linux/virtio_config.h
index b5eda06f0d57..0862be802ff8 100644
--- a/include/uapi/linux/virtio_config.h
+++ b/include/uapi/linux/virtio_config.h
@@ -52,7 +52,7 @@
  * rest are per-device feature bits.
  */
 #define VIRTIO_TRANSPORT_F_START	28
-#define VIRTIO_TRANSPORT_F_END		38
+#define VIRTIO_TRANSPORT_F_END		41
 
 #ifndef VIRTIO_CONFIG_NO_LEGACY
 /* Do we get callbacks when the ring is completely used, even if we've
@@ -92,4 +92,9 @@
  * Does the device support Single Root I/O Virtualization?
  */
 #define VIRTIO_F_SR_IOV			37
+
+/*
+ * This feature indicates that the driver can reset a queue individually.
+ */
+#define VIRTIO_F_RING_RESET		40
 #endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 02/26] virtio: queue_reset: add VIRTIO_F_RING_RESET
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Added VIRTIO_F_RING_RESET, it came from here
https://github.com/oasis-tcs/virtio-spec/issues/124

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/uapi/linux/virtio_config.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/virtio_config.h b/include/uapi/linux/virtio_config.h
index b5eda06f0d57..0862be802ff8 100644
--- a/include/uapi/linux/virtio_config.h
+++ b/include/uapi/linux/virtio_config.h
@@ -52,7 +52,7 @@
  * rest are per-device feature bits.
  */
 #define VIRTIO_TRANSPORT_F_START	28
-#define VIRTIO_TRANSPORT_F_END		38
+#define VIRTIO_TRANSPORT_F_END		41
 
 #ifndef VIRTIO_CONFIG_NO_LEGACY
 /* Do we get callbacks when the ring is completely used, even if we've
@@ -92,4 +92,9 @@
  * Does the device support Single Root I/O Virtualization?
  */
 #define VIRTIO_F_SR_IOV			37
+
+/*
+ * This feature indicates that the driver can reset a queue individually.
+ */
+#define VIRTIO_F_RING_RESET		40
 #endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 02/26] virtio: queue_reset: add VIRTIO_F_RING_RESET
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Added VIRTIO_F_RING_RESET, it came from here
https://github.com/oasis-tcs/virtio-spec/issues/124

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/uapi/linux/virtio_config.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/include/uapi/linux/virtio_config.h b/include/uapi/linux/virtio_config.h
index b5eda06f0d57..0862be802ff8 100644
--- a/include/uapi/linux/virtio_config.h
+++ b/include/uapi/linux/virtio_config.h
@@ -52,7 +52,7 @@
  * rest are per-device feature bits.
  */
 #define VIRTIO_TRANSPORT_F_START	28
-#define VIRTIO_TRANSPORT_F_END		38
+#define VIRTIO_TRANSPORT_F_END		41
 
 #ifndef VIRTIO_CONFIG_NO_LEGACY
 /* Do we get callbacks when the ring is completely used, even if we've
@@ -92,4 +92,9 @@
  * Does the device support Single Root I/O Virtualization?
  */
 #define VIRTIO_F_SR_IOV			37
+
+/*
+ * This feature indicates that the driver can reset a queue individually.
+ */
+#define VIRTIO_F_RING_RESET		40
 #endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 03/26] virtio: add helper virtqueue_get_vring_max_size()
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:34   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Record the maximum queue num supported by the device.

virtio-net can display the maximum (supported by hardware) ring size in
ethtool -g eth0.

When the subsequent patch implements vring reset, it can judge whether
the ring size passed by the driver is legal based on this.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_mmio.c       |  2 ++
 drivers/virtio/virtio_pci_legacy.c |  2 ++
 drivers/virtio/virtio_pci_modern.c |  2 ++
 drivers/virtio/virtio_ring.c       | 14 ++++++++++++++
 include/linux/virtio.h             |  2 ++
 5 files changed, 22 insertions(+)

diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 56128b9c46eb..a41abc8051b9 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -390,6 +390,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
 		goto error_new_virtqueue;
 	}
 
+	vq->num_max = num;
+
 	/* Activate the queue */
 	writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
 	if (vm_dev->version == 1) {
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
index 34141b9abe27..b68934fe6b5d 100644
--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -135,6 +135,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!vq)
 		return ERR_PTR(-ENOMEM);
 
+	vq->num_max = num;
+
 	q_pfn = virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
 	if (q_pfn >> 32) {
 		dev_err(&vp_dev->pci_dev->dev,
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 5455bc041fb6..86d301f272b8 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -218,6 +218,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!vq)
 		return ERR_PTR(-ENOMEM);
 
+	vq->num_max = num;
+
 	/* activate the queue */
 	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
 	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 962f1477b1fa..b87130c8f312 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2371,6 +2371,20 @@ void vring_transport_features(struct virtio_device *vdev)
 }
 EXPORT_SYMBOL_GPL(vring_transport_features);
 
+/**
+ * virtqueue_get_vring_max_size - return the max size of the virtqueue's vring
+ * @_vq: the struct virtqueue containing the vring of interest.
+ *
+ * Returns the max size of the vring.
+ *
+ * Unlike other operations, this need not be serialized.
+ */
+unsigned int virtqueue_get_vring_max_size(struct virtqueue *_vq)
+{
+	return _vq->num_max;
+}
+EXPORT_SYMBOL_GPL(virtqueue_get_vring_max_size);
+
 /**
  * virtqueue_get_vring_size - return the size of the virtqueue's vring
  * @_vq: the struct virtqueue containing the vring of interest.
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 72292a62cd90..d59adc4be068 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -31,6 +31,7 @@ struct virtqueue {
 	struct virtio_device *vdev;
 	unsigned int index;
 	unsigned int num_free;
+	unsigned int num_max;
 	void *priv;
 };
 
@@ -80,6 +81,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
 
 void *virtqueue_detach_unused_buf(struct virtqueue *vq);
 
+unsigned int virtqueue_get_vring_max_size(struct virtqueue *vq);
 unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
 
 bool virtqueue_is_broken(struct virtqueue *vq);
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 03/26] virtio: add helper virtqueue_get_vring_max_size()
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Record the maximum queue num supported by the device.

virtio-net can display the maximum (supported by hardware) ring size in
ethtool -g eth0.

When the subsequent patch implements vring reset, it can judge whether
the ring size passed by the driver is legal based on this.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_mmio.c       |  2 ++
 drivers/virtio/virtio_pci_legacy.c |  2 ++
 drivers/virtio/virtio_pci_modern.c |  2 ++
 drivers/virtio/virtio_ring.c       | 14 ++++++++++++++
 include/linux/virtio.h             |  2 ++
 5 files changed, 22 insertions(+)

diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 56128b9c46eb..a41abc8051b9 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -390,6 +390,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
 		goto error_new_virtqueue;
 	}
 
+	vq->num_max = num;
+
 	/* Activate the queue */
 	writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
 	if (vm_dev->version == 1) {
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
index 34141b9abe27..b68934fe6b5d 100644
--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -135,6 +135,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!vq)
 		return ERR_PTR(-ENOMEM);
 
+	vq->num_max = num;
+
 	q_pfn = virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
 	if (q_pfn >> 32) {
 		dev_err(&vp_dev->pci_dev->dev,
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 5455bc041fb6..86d301f272b8 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -218,6 +218,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!vq)
 		return ERR_PTR(-ENOMEM);
 
+	vq->num_max = num;
+
 	/* activate the queue */
 	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
 	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 962f1477b1fa..b87130c8f312 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2371,6 +2371,20 @@ void vring_transport_features(struct virtio_device *vdev)
 }
 EXPORT_SYMBOL_GPL(vring_transport_features);
 
+/**
+ * virtqueue_get_vring_max_size - return the max size of the virtqueue's vring
+ * @_vq: the struct virtqueue containing the vring of interest.
+ *
+ * Returns the max size of the vring.
+ *
+ * Unlike other operations, this need not be serialized.
+ */
+unsigned int virtqueue_get_vring_max_size(struct virtqueue *_vq)
+{
+	return _vq->num_max;
+}
+EXPORT_SYMBOL_GPL(virtqueue_get_vring_max_size);
+
 /**
  * virtqueue_get_vring_size - return the size of the virtqueue's vring
  * @_vq: the struct virtqueue containing the vring of interest.
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 72292a62cd90..d59adc4be068 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -31,6 +31,7 @@ struct virtqueue {
 	struct virtio_device *vdev;
 	unsigned int index;
 	unsigned int num_free;
+	unsigned int num_max;
 	void *priv;
 };
 
@@ -80,6 +81,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
 
 void *virtqueue_detach_unused_buf(struct virtqueue *vq);
 
+unsigned int virtqueue_get_vring_max_size(struct virtqueue *vq);
 unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
 
 bool virtqueue_is_broken(struct virtqueue *vq);
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 03/26] virtio: add helper virtqueue_get_vring_max_size()
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Record the maximum queue num supported by the device.

virtio-net can display the maximum (supported by hardware) ring size in
ethtool -g eth0.

When the subsequent patch implements vring reset, it can judge whether
the ring size passed by the driver is legal based on this.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_mmio.c       |  2 ++
 drivers/virtio/virtio_pci_legacy.c |  2 ++
 drivers/virtio/virtio_pci_modern.c |  2 ++
 drivers/virtio/virtio_ring.c       | 14 ++++++++++++++
 include/linux/virtio.h             |  2 ++
 5 files changed, 22 insertions(+)

diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 56128b9c46eb..a41abc8051b9 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -390,6 +390,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
 		goto error_new_virtqueue;
 	}
 
+	vq->num_max = num;
+
 	/* Activate the queue */
 	writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
 	if (vm_dev->version == 1) {
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
index 34141b9abe27..b68934fe6b5d 100644
--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -135,6 +135,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!vq)
 		return ERR_PTR(-ENOMEM);
 
+	vq->num_max = num;
+
 	q_pfn = virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
 	if (q_pfn >> 32) {
 		dev_err(&vp_dev->pci_dev->dev,
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 5455bc041fb6..86d301f272b8 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -218,6 +218,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!vq)
 		return ERR_PTR(-ENOMEM);
 
+	vq->num_max = num;
+
 	/* activate the queue */
 	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
 	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 962f1477b1fa..b87130c8f312 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2371,6 +2371,20 @@ void vring_transport_features(struct virtio_device *vdev)
 }
 EXPORT_SYMBOL_GPL(vring_transport_features);
 
+/**
+ * virtqueue_get_vring_max_size - return the max size of the virtqueue's vring
+ * @_vq: the struct virtqueue containing the vring of interest.
+ *
+ * Returns the max size of the vring.
+ *
+ * Unlike other operations, this need not be serialized.
+ */
+unsigned int virtqueue_get_vring_max_size(struct virtqueue *_vq)
+{
+	return _vq->num_max;
+}
+EXPORT_SYMBOL_GPL(virtqueue_get_vring_max_size);
+
 /**
  * virtqueue_get_vring_size - return the size of the virtqueue's vring
  * @_vq: the struct virtqueue containing the vring of interest.
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 72292a62cd90..d59adc4be068 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -31,6 +31,7 @@ struct virtqueue {
 	struct virtio_device *vdev;
 	unsigned int index;
 	unsigned int num_free;
+	unsigned int num_max;
 	void *priv;
 };
 
@@ -80,6 +81,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
 
 void *virtqueue_detach_unused_buf(struct virtqueue *vq);
 
+unsigned int virtqueue_get_vring_max_size(struct virtqueue *vq);
 unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
 
 bool virtqueue_is_broken(struct virtqueue *vq);
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 04/26] virtio_ring: split: extract the logic of creating vring
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:34   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Separate the logic of split to create vring queue.

For the convenience of passing parameters, add a structure
vring_split.

This feature is required for subsequent virtuqueue reset vring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 74 +++++++++++++++++++++++++-----------
 1 file changed, 51 insertions(+), 23 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index b87130c8f312..d32793615451 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -85,6 +85,13 @@ struct vring_desc_extra {
 	u16 next;			/* The next desc state in a list. */
 };
 
+struct vring_split {
+	void *queue;
+	dma_addr_t dma_addr;
+	size_t queue_size_in_bytes;
+	struct vring vring;
+};
+
 struct vring_virtqueue {
 	struct virtqueue vq;
 
@@ -915,28 +922,21 @@ static void *virtqueue_detach_unused_buf_split(struct virtqueue *_vq)
 	return NULL;
 }
 
-static struct virtqueue *vring_create_virtqueue_split(
-	unsigned int index,
-	unsigned int num,
-	unsigned int vring_align,
-	struct virtio_device *vdev,
-	bool weak_barriers,
-	bool may_reduce_num,
-	bool context,
-	bool (*notify)(struct virtqueue *),
-	void (*callback)(struct virtqueue *),
-	const char *name)
+static int vring_create_vring_split(struct vring_split *vring,
+				    struct virtio_device *vdev,
+				    unsigned int vring_align,
+				    bool weak_barriers,
+				    bool may_reduce_num,
+				    u32 num)
 {
-	struct virtqueue *vq;
 	void *queue = NULL;
 	dma_addr_t dma_addr;
 	size_t queue_size_in_bytes;
-	struct vring vring;
 
 	/* We assume num is a power of 2. */
 	if (num & (num - 1)) {
 		dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
-		return NULL;
+		return -EINVAL;
 	}
 
 	/* TODO: allocate each queue chunk individually */
@@ -947,11 +947,11 @@ static struct virtqueue *vring_create_virtqueue_split(
 		if (queue)
 			break;
 		if (!may_reduce_num)
-			return NULL;
+			return -ENOMEM;
 	}
 
 	if (!num)
-		return NULL;
+		return -ENOMEM;
 
 	if (!queue) {
 		/* Try to get a single page. You are my only hope! */
@@ -959,21 +959,49 @@ static struct virtqueue *vring_create_virtqueue_split(
 					  &dma_addr, GFP_KERNEL|__GFP_ZERO);
 	}
 	if (!queue)
-		return NULL;
+		return -ENOMEM;
 
 	queue_size_in_bytes = vring_size(num, vring_align);
-	vring_init(&vring, num, queue, vring_align);
+	vring_init(&vring->vring, num, queue, vring_align);
+
+	vring->dma_addr = dma_addr;
+	vring->queue = queue;
+	vring->queue_size_in_bytes = queue_size_in_bytes;
+
+	return 0;
+}
+
+static struct virtqueue *vring_create_virtqueue_split(
+	unsigned int index,
+	unsigned int num,
+	unsigned int vring_align,
+	struct virtio_device *vdev,
+	bool weak_barriers,
+	bool may_reduce_num,
+	bool context,
+	bool (*notify)(struct virtqueue *),
+	void (*callback)(struct virtqueue *),
+	const char *name)
+{
+	struct vring_split vring;
+	struct virtqueue *vq;
+	int err;
+
+	err = vring_create_vring_split(&vring, vdev, vring_align, weak_barriers,
+				       may_reduce_num, num);
+	if (err)
+		return NULL;
 
-	vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
+	vq = __vring_new_virtqueue(index, vring.vring, vdev, weak_barriers, context,
 				   notify, callback, name);
 	if (!vq) {
-		vring_free_queue(vdev, queue_size_in_bytes, queue,
-				 dma_addr);
+		vring_free_queue(vdev, vring.queue_size_in_bytes, vring.queue,
+				 vring.dma_addr);
 		return NULL;
 	}
 
-	to_vvq(vq)->split.queue_dma_addr = dma_addr;
-	to_vvq(vq)->split.queue_size_in_bytes = queue_size_in_bytes;
+	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
+	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
 	to_vvq(vq)->we_own_ring = true;
 
 	return vq;
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 04/26] virtio_ring: split: extract the logic of creating vring
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Separate the logic of split to create vring queue.

For the convenience of passing parameters, add a structure
vring_split.

This feature is required for subsequent virtuqueue reset vring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 74 +++++++++++++++++++++++++-----------
 1 file changed, 51 insertions(+), 23 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index b87130c8f312..d32793615451 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -85,6 +85,13 @@ struct vring_desc_extra {
 	u16 next;			/* The next desc state in a list. */
 };
 
+struct vring_split {
+	void *queue;
+	dma_addr_t dma_addr;
+	size_t queue_size_in_bytes;
+	struct vring vring;
+};
+
 struct vring_virtqueue {
 	struct virtqueue vq;
 
@@ -915,28 +922,21 @@ static void *virtqueue_detach_unused_buf_split(struct virtqueue *_vq)
 	return NULL;
 }
 
-static struct virtqueue *vring_create_virtqueue_split(
-	unsigned int index,
-	unsigned int num,
-	unsigned int vring_align,
-	struct virtio_device *vdev,
-	bool weak_barriers,
-	bool may_reduce_num,
-	bool context,
-	bool (*notify)(struct virtqueue *),
-	void (*callback)(struct virtqueue *),
-	const char *name)
+static int vring_create_vring_split(struct vring_split *vring,
+				    struct virtio_device *vdev,
+				    unsigned int vring_align,
+				    bool weak_barriers,
+				    bool may_reduce_num,
+				    u32 num)
 {
-	struct virtqueue *vq;
 	void *queue = NULL;
 	dma_addr_t dma_addr;
 	size_t queue_size_in_bytes;
-	struct vring vring;
 
 	/* We assume num is a power of 2. */
 	if (num & (num - 1)) {
 		dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
-		return NULL;
+		return -EINVAL;
 	}
 
 	/* TODO: allocate each queue chunk individually */
@@ -947,11 +947,11 @@ static struct virtqueue *vring_create_virtqueue_split(
 		if (queue)
 			break;
 		if (!may_reduce_num)
-			return NULL;
+			return -ENOMEM;
 	}
 
 	if (!num)
-		return NULL;
+		return -ENOMEM;
 
 	if (!queue) {
 		/* Try to get a single page. You are my only hope! */
@@ -959,21 +959,49 @@ static struct virtqueue *vring_create_virtqueue_split(
 					  &dma_addr, GFP_KERNEL|__GFP_ZERO);
 	}
 	if (!queue)
-		return NULL;
+		return -ENOMEM;
 
 	queue_size_in_bytes = vring_size(num, vring_align);
-	vring_init(&vring, num, queue, vring_align);
+	vring_init(&vring->vring, num, queue, vring_align);
+
+	vring->dma_addr = dma_addr;
+	vring->queue = queue;
+	vring->queue_size_in_bytes = queue_size_in_bytes;
+
+	return 0;
+}
+
+static struct virtqueue *vring_create_virtqueue_split(
+	unsigned int index,
+	unsigned int num,
+	unsigned int vring_align,
+	struct virtio_device *vdev,
+	bool weak_barriers,
+	bool may_reduce_num,
+	bool context,
+	bool (*notify)(struct virtqueue *),
+	void (*callback)(struct virtqueue *),
+	const char *name)
+{
+	struct vring_split vring;
+	struct virtqueue *vq;
+	int err;
+
+	err = vring_create_vring_split(&vring, vdev, vring_align, weak_barriers,
+				       may_reduce_num, num);
+	if (err)
+		return NULL;
 
-	vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
+	vq = __vring_new_virtqueue(index, vring.vring, vdev, weak_barriers, context,
 				   notify, callback, name);
 	if (!vq) {
-		vring_free_queue(vdev, queue_size_in_bytes, queue,
-				 dma_addr);
+		vring_free_queue(vdev, vring.queue_size_in_bytes, vring.queue,
+				 vring.dma_addr);
 		return NULL;
 	}
 
-	to_vvq(vq)->split.queue_dma_addr = dma_addr;
-	to_vvq(vq)->split.queue_size_in_bytes = queue_size_in_bytes;
+	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
+	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
 	to_vvq(vq)->we_own_ring = true;
 
 	return vq;
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 04/26] virtio_ring: split: extract the logic of creating vring
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Separate the logic of split to create vring queue.

For the convenience of passing parameters, add a structure
vring_split.

This feature is required for subsequent virtuqueue reset vring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 74 +++++++++++++++++++++++++-----------
 1 file changed, 51 insertions(+), 23 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index b87130c8f312..d32793615451 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -85,6 +85,13 @@ struct vring_desc_extra {
 	u16 next;			/* The next desc state in a list. */
 };
 
+struct vring_split {
+	void *queue;
+	dma_addr_t dma_addr;
+	size_t queue_size_in_bytes;
+	struct vring vring;
+};
+
 struct vring_virtqueue {
 	struct virtqueue vq;
 
@@ -915,28 +922,21 @@ static void *virtqueue_detach_unused_buf_split(struct virtqueue *_vq)
 	return NULL;
 }
 
-static struct virtqueue *vring_create_virtqueue_split(
-	unsigned int index,
-	unsigned int num,
-	unsigned int vring_align,
-	struct virtio_device *vdev,
-	bool weak_barriers,
-	bool may_reduce_num,
-	bool context,
-	bool (*notify)(struct virtqueue *),
-	void (*callback)(struct virtqueue *),
-	const char *name)
+static int vring_create_vring_split(struct vring_split *vring,
+				    struct virtio_device *vdev,
+				    unsigned int vring_align,
+				    bool weak_barriers,
+				    bool may_reduce_num,
+				    u32 num)
 {
-	struct virtqueue *vq;
 	void *queue = NULL;
 	dma_addr_t dma_addr;
 	size_t queue_size_in_bytes;
-	struct vring vring;
 
 	/* We assume num is a power of 2. */
 	if (num & (num - 1)) {
 		dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
-		return NULL;
+		return -EINVAL;
 	}
 
 	/* TODO: allocate each queue chunk individually */
@@ -947,11 +947,11 @@ static struct virtqueue *vring_create_virtqueue_split(
 		if (queue)
 			break;
 		if (!may_reduce_num)
-			return NULL;
+			return -ENOMEM;
 	}
 
 	if (!num)
-		return NULL;
+		return -ENOMEM;
 
 	if (!queue) {
 		/* Try to get a single page. You are my only hope! */
@@ -959,21 +959,49 @@ static struct virtqueue *vring_create_virtqueue_split(
 					  &dma_addr, GFP_KERNEL|__GFP_ZERO);
 	}
 	if (!queue)
-		return NULL;
+		return -ENOMEM;
 
 	queue_size_in_bytes = vring_size(num, vring_align);
-	vring_init(&vring, num, queue, vring_align);
+	vring_init(&vring->vring, num, queue, vring_align);
+
+	vring->dma_addr = dma_addr;
+	vring->queue = queue;
+	vring->queue_size_in_bytes = queue_size_in_bytes;
+
+	return 0;
+}
+
+static struct virtqueue *vring_create_virtqueue_split(
+	unsigned int index,
+	unsigned int num,
+	unsigned int vring_align,
+	struct virtio_device *vdev,
+	bool weak_barriers,
+	bool may_reduce_num,
+	bool context,
+	bool (*notify)(struct virtqueue *),
+	void (*callback)(struct virtqueue *),
+	const char *name)
+{
+	struct vring_split vring;
+	struct virtqueue *vq;
+	int err;
+
+	err = vring_create_vring_split(&vring, vdev, vring_align, weak_barriers,
+				       may_reduce_num, num);
+	if (err)
+		return NULL;
 
-	vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
+	vq = __vring_new_virtqueue(index, vring.vring, vdev, weak_barriers, context,
 				   notify, callback, name);
 	if (!vq) {
-		vring_free_queue(vdev, queue_size_in_bytes, queue,
-				 dma_addr);
+		vring_free_queue(vdev, vring.queue_size_in_bytes, vring.queue,
+				 vring.dma_addr);
 		return NULL;
 	}
 
-	to_vvq(vq)->split.queue_dma_addr = dma_addr;
-	to_vvq(vq)->split.queue_size_in_bytes = queue_size_in_bytes;
+	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
+	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
 	to_vvq(vq)->we_own_ring = true;
 
 	return vq;
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 05/26] virtio_ring: split: extract the logic of init vq and attach vring
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:34   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Split the logic of split assignment vq into three parts.

1. The assignment passed from the function parameter
2. The part that attaches vring to vq. -- __vring_virtqueue_attach_split()
3. The part that initializes vq to a fixed value --
   __vring_virtqueue_init_split()

This feature is required for subsequent virtuqueue reset vring

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 111 +++++++++++++++++++++--------------
 1 file changed, 67 insertions(+), 44 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index d32793615451..dc6313b79305 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2196,34 +2196,40 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
 }
 EXPORT_SYMBOL_GPL(vring_interrupt);
 
-/* Only available for split ring */
-struct virtqueue *__vring_new_virtqueue(unsigned int index,
-					struct vring vring,
-					struct virtio_device *vdev,
-					bool weak_barriers,
-					bool context,
-					bool (*notify)(struct virtqueue *),
-					void (*callback)(struct virtqueue *),
-					const char *name)
+static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
+					  struct virtio_device *vdev,
+					  struct vring vring)
 {
-	struct vring_virtqueue *vq;
+	vq->vq.num_free = vring.num;
 
-	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
-		return NULL;
+	vq->split.vring = vring;
+	vq->split.queue_dma_addr = 0;
+	vq->split.queue_size_in_bytes = 0;
 
-	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
-	if (!vq)
-		return NULL;
+	vq->split.desc_state = kmalloc_array(vring.num,
+					     sizeof(struct vring_desc_state_split), GFP_KERNEL);
+	if (!vq->split.desc_state)
+		goto err_state;
 
+	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
+	if (!vq->split.desc_extra)
+		goto err_extra;
+
+	memset(vq->split.desc_state, 0, vring.num *
+	       sizeof(struct vring_desc_state_split));
+	return 0;
+
+err_extra:
+	kfree(vq->split.desc_state);
+err_state:
+	return -ENOMEM;
+}
+
+static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
+					 struct virtio_device *vdev)
+{
 	vq->packed_ring = false;
-	vq->vq.callback = callback;
-	vq->vq.vdev = vdev;
-	vq->vq.name = name;
-	vq->vq.num_free = vring.num;
-	vq->vq.index = index;
 	vq->we_own_ring = false;
-	vq->notify = notify;
-	vq->weak_barriers = weak_barriers;
 	vq->broken = false;
 	vq->last_used_idx = 0;
 	vq->event_triggered = false;
@@ -2234,50 +2240,67 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
 	vq->last_add_time_valid = false;
 #endif
 
-	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
-		!context;
 	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
 	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
 		vq->weak_barriers = false;
 
-	vq->split.queue_dma_addr = 0;
-	vq->split.queue_size_in_bytes = 0;
-
-	vq->split.vring = vring;
 	vq->split.avail_flags_shadow = 0;
 	vq->split.avail_idx_shadow = 0;
 
 	/* No callback?  Tell other side not to bother us. */
-	if (!callback) {
+	if (!vq->vq.callback) {
 		vq->split.avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
 		if (!vq->event)
 			vq->split.vring.avail->flags = cpu_to_virtio16(vdev,
 					vq->split.avail_flags_shadow);
 	}
 
-	vq->split.desc_state = kmalloc_array(vring.num,
-			sizeof(struct vring_desc_state_split), GFP_KERNEL);
-	if (!vq->split.desc_state)
-		goto err_state;
-
-	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
-	if (!vq->split.desc_extra)
-		goto err_extra;
-
 	/* Put everything in free lists. */
 	vq->free_head = 0;
-	memset(vq->split.desc_state, 0, vring.num *
-			sizeof(struct vring_desc_state_split));
+}
+
+/* Only available for split ring */
+struct virtqueue *__vring_new_virtqueue(unsigned int index,
+					struct vring vring,
+					struct virtio_device *vdev,
+					bool weak_barriers,
+					bool context,
+					bool (*notify)(struct virtqueue *),
+					void (*callback)(struct virtqueue *),
+					const char *name)
+{
+	struct vring_virtqueue *vq;
+	int err;
+
+	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
+		return NULL;
+
+	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
+	if (!vq)
+		return NULL;
+
+	vq->vq.callback = callback;
+	vq->vq.vdev = vdev;
+	vq->vq.name = name;
+	vq->vq.index = index;
+	vq->notify = notify;
+	vq->weak_barriers = weak_barriers;
+	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
+		!context;
+
+	err = __vring_virtqueue_attach_split(vq, vdev, vring);
+	if (err)
+		goto err;
+
+	__vring_virtqueue_init_split(vq, vdev);
 
 	spin_lock(&vdev->vqs_list_lock);
 	list_add_tail(&vq->vq.list, &vdev->vqs);
 	spin_unlock(&vdev->vqs_list_lock);
-	return &vq->vq;
 
-err_extra:
-	kfree(vq->split.desc_state);
-err_state:
+	return &vq->vq;
+err:
 	kfree(vq);
 	return NULL;
 }
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 05/26] virtio_ring: split: extract the logic of init vq and attach vring
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Split the logic of split assignment vq into three parts.

1. The assignment passed from the function parameter
2. The part that attaches vring to vq. -- __vring_virtqueue_attach_split()
3. The part that initializes vq to a fixed value --
   __vring_virtqueue_init_split()

This feature is required for subsequent virtuqueue reset vring

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 111 +++++++++++++++++++++--------------
 1 file changed, 67 insertions(+), 44 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index d32793615451..dc6313b79305 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2196,34 +2196,40 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
 }
 EXPORT_SYMBOL_GPL(vring_interrupt);
 
-/* Only available for split ring */
-struct virtqueue *__vring_new_virtqueue(unsigned int index,
-					struct vring vring,
-					struct virtio_device *vdev,
-					bool weak_barriers,
-					bool context,
-					bool (*notify)(struct virtqueue *),
-					void (*callback)(struct virtqueue *),
-					const char *name)
+static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
+					  struct virtio_device *vdev,
+					  struct vring vring)
 {
-	struct vring_virtqueue *vq;
+	vq->vq.num_free = vring.num;
 
-	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
-		return NULL;
+	vq->split.vring = vring;
+	vq->split.queue_dma_addr = 0;
+	vq->split.queue_size_in_bytes = 0;
 
-	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
-	if (!vq)
-		return NULL;
+	vq->split.desc_state = kmalloc_array(vring.num,
+					     sizeof(struct vring_desc_state_split), GFP_KERNEL);
+	if (!vq->split.desc_state)
+		goto err_state;
 
+	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
+	if (!vq->split.desc_extra)
+		goto err_extra;
+
+	memset(vq->split.desc_state, 0, vring.num *
+	       sizeof(struct vring_desc_state_split));
+	return 0;
+
+err_extra:
+	kfree(vq->split.desc_state);
+err_state:
+	return -ENOMEM;
+}
+
+static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
+					 struct virtio_device *vdev)
+{
 	vq->packed_ring = false;
-	vq->vq.callback = callback;
-	vq->vq.vdev = vdev;
-	vq->vq.name = name;
-	vq->vq.num_free = vring.num;
-	vq->vq.index = index;
 	vq->we_own_ring = false;
-	vq->notify = notify;
-	vq->weak_barriers = weak_barriers;
 	vq->broken = false;
 	vq->last_used_idx = 0;
 	vq->event_triggered = false;
@@ -2234,50 +2240,67 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
 	vq->last_add_time_valid = false;
 #endif
 
-	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
-		!context;
 	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
 	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
 		vq->weak_barriers = false;
 
-	vq->split.queue_dma_addr = 0;
-	vq->split.queue_size_in_bytes = 0;
-
-	vq->split.vring = vring;
 	vq->split.avail_flags_shadow = 0;
 	vq->split.avail_idx_shadow = 0;
 
 	/* No callback?  Tell other side not to bother us. */
-	if (!callback) {
+	if (!vq->vq.callback) {
 		vq->split.avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
 		if (!vq->event)
 			vq->split.vring.avail->flags = cpu_to_virtio16(vdev,
 					vq->split.avail_flags_shadow);
 	}
 
-	vq->split.desc_state = kmalloc_array(vring.num,
-			sizeof(struct vring_desc_state_split), GFP_KERNEL);
-	if (!vq->split.desc_state)
-		goto err_state;
-
-	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
-	if (!vq->split.desc_extra)
-		goto err_extra;
-
 	/* Put everything in free lists. */
 	vq->free_head = 0;
-	memset(vq->split.desc_state, 0, vring.num *
-			sizeof(struct vring_desc_state_split));
+}
+
+/* Only available for split ring */
+struct virtqueue *__vring_new_virtqueue(unsigned int index,
+					struct vring vring,
+					struct virtio_device *vdev,
+					bool weak_barriers,
+					bool context,
+					bool (*notify)(struct virtqueue *),
+					void (*callback)(struct virtqueue *),
+					const char *name)
+{
+	struct vring_virtqueue *vq;
+	int err;
+
+	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
+		return NULL;
+
+	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
+	if (!vq)
+		return NULL;
+
+	vq->vq.callback = callback;
+	vq->vq.vdev = vdev;
+	vq->vq.name = name;
+	vq->vq.index = index;
+	vq->notify = notify;
+	vq->weak_barriers = weak_barriers;
+	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
+		!context;
+
+	err = __vring_virtqueue_attach_split(vq, vdev, vring);
+	if (err)
+		goto err;
+
+	__vring_virtqueue_init_split(vq, vdev);
 
 	spin_lock(&vdev->vqs_list_lock);
 	list_add_tail(&vq->vq.list, &vdev->vqs);
 	spin_unlock(&vdev->vqs_list_lock);
-	return &vq->vq;
 
-err_extra:
-	kfree(vq->split.desc_state);
-err_state:
+	return &vq->vq;
+err:
 	kfree(vq);
 	return NULL;
 }
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 05/26] virtio_ring: split: extract the logic of init vq and attach vring
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Split the logic of split assignment vq into three parts.

1. The assignment passed from the function parameter
2. The part that attaches vring to vq. -- __vring_virtqueue_attach_split()
3. The part that initializes vq to a fixed value --
   __vring_virtqueue_init_split()

This feature is required for subsequent virtuqueue reset vring

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 111 +++++++++++++++++++++--------------
 1 file changed, 67 insertions(+), 44 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index d32793615451..dc6313b79305 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2196,34 +2196,40 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
 }
 EXPORT_SYMBOL_GPL(vring_interrupt);
 
-/* Only available for split ring */
-struct virtqueue *__vring_new_virtqueue(unsigned int index,
-					struct vring vring,
-					struct virtio_device *vdev,
-					bool weak_barriers,
-					bool context,
-					bool (*notify)(struct virtqueue *),
-					void (*callback)(struct virtqueue *),
-					const char *name)
+static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
+					  struct virtio_device *vdev,
+					  struct vring vring)
 {
-	struct vring_virtqueue *vq;
+	vq->vq.num_free = vring.num;
 
-	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
-		return NULL;
+	vq->split.vring = vring;
+	vq->split.queue_dma_addr = 0;
+	vq->split.queue_size_in_bytes = 0;
 
-	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
-	if (!vq)
-		return NULL;
+	vq->split.desc_state = kmalloc_array(vring.num,
+					     sizeof(struct vring_desc_state_split), GFP_KERNEL);
+	if (!vq->split.desc_state)
+		goto err_state;
 
+	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
+	if (!vq->split.desc_extra)
+		goto err_extra;
+
+	memset(vq->split.desc_state, 0, vring.num *
+	       sizeof(struct vring_desc_state_split));
+	return 0;
+
+err_extra:
+	kfree(vq->split.desc_state);
+err_state:
+	return -ENOMEM;
+}
+
+static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
+					 struct virtio_device *vdev)
+{
 	vq->packed_ring = false;
-	vq->vq.callback = callback;
-	vq->vq.vdev = vdev;
-	vq->vq.name = name;
-	vq->vq.num_free = vring.num;
-	vq->vq.index = index;
 	vq->we_own_ring = false;
-	vq->notify = notify;
-	vq->weak_barriers = weak_barriers;
 	vq->broken = false;
 	vq->last_used_idx = 0;
 	vq->event_triggered = false;
@@ -2234,50 +2240,67 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
 	vq->last_add_time_valid = false;
 #endif
 
-	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
-		!context;
 	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
 	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
 		vq->weak_barriers = false;
 
-	vq->split.queue_dma_addr = 0;
-	vq->split.queue_size_in_bytes = 0;
-
-	vq->split.vring = vring;
 	vq->split.avail_flags_shadow = 0;
 	vq->split.avail_idx_shadow = 0;
 
 	/* No callback?  Tell other side not to bother us. */
-	if (!callback) {
+	if (!vq->vq.callback) {
 		vq->split.avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
 		if (!vq->event)
 			vq->split.vring.avail->flags = cpu_to_virtio16(vdev,
 					vq->split.avail_flags_shadow);
 	}
 
-	vq->split.desc_state = kmalloc_array(vring.num,
-			sizeof(struct vring_desc_state_split), GFP_KERNEL);
-	if (!vq->split.desc_state)
-		goto err_state;
-
-	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
-	if (!vq->split.desc_extra)
-		goto err_extra;
-
 	/* Put everything in free lists. */
 	vq->free_head = 0;
-	memset(vq->split.desc_state, 0, vring.num *
-			sizeof(struct vring_desc_state_split));
+}
+
+/* Only available for split ring */
+struct virtqueue *__vring_new_virtqueue(unsigned int index,
+					struct vring vring,
+					struct virtio_device *vdev,
+					bool weak_barriers,
+					bool context,
+					bool (*notify)(struct virtqueue *),
+					void (*callback)(struct virtqueue *),
+					const char *name)
+{
+	struct vring_virtqueue *vq;
+	int err;
+
+	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
+		return NULL;
+
+	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
+	if (!vq)
+		return NULL;
+
+	vq->vq.callback = callback;
+	vq->vq.vdev = vdev;
+	vq->vq.name = name;
+	vq->vq.index = index;
+	vq->notify = notify;
+	vq->weak_barriers = weak_barriers;
+	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
+		!context;
+
+	err = __vring_virtqueue_attach_split(vq, vdev, vring);
+	if (err)
+		goto err;
+
+	__vring_virtqueue_init_split(vq, vdev);
 
 	spin_lock(&vdev->vqs_list_lock);
 	list_add_tail(&vq->vq.list, &vdev->vqs);
 	spin_unlock(&vdev->vqs_list_lock);
-	return &vq->vq;
 
-err_extra:
-	kfree(vq->split.desc_state);
-err_state:
+	return &vq->vq;
+err:
 	kfree(vq);
 	return NULL;
 }
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 06/26] virtio_ring: packed: extract the logic of creating vring
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:34   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Separate the logic of packed to create vring queue.

For the convenience of passing parameters, add a structure
vring_packed.

This feature is required for subsequent virtuqueue reset vring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 121 ++++++++++++++++++++++++++---------
 1 file changed, 92 insertions(+), 29 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index dc6313b79305..1af98b112996 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -92,6 +92,18 @@ struct vring_split {
 	struct vring vring;
 };
 
+struct vring_packed {
+	u32 num;
+	struct vring_packed_desc *ring;
+	struct vring_packed_desc_event *driver;
+	struct vring_packed_desc_event *device;
+	dma_addr_t ring_dma_addr;
+	dma_addr_t driver_event_dma_addr;
+	dma_addr_t device_event_dma_addr;
+	size_t ring_size_in_bytes;
+	size_t event_size_in_bytes;
+};
+
 struct vring_virtqueue {
 	struct virtqueue vq;
 
@@ -1683,45 +1695,101 @@ static struct vring_desc_extra *vring_alloc_desc_extra(struct vring_virtqueue *v
 	return desc_extra;
 }
 
-static struct virtqueue *vring_create_virtqueue_packed(
-	unsigned int index,
-	unsigned int num,
-	unsigned int vring_align,
-	struct virtio_device *vdev,
-	bool weak_barriers,
-	bool may_reduce_num,
-	bool context,
-	bool (*notify)(struct virtqueue *),
-	void (*callback)(struct virtqueue *),
-	const char *name)
+static void vring_free_vring_packed(struct vring_packed *vring,
+				    struct virtio_device *vdev)
+{
+	dma_addr_t ring_dma_addr, driver_event_dma_addr, device_event_dma_addr;
+	struct vring_packed_desc_event *driver, *device;
+	size_t ring_size_in_bytes, event_size_in_bytes;
+	struct vring_packed_desc *ring;
+
+	ring                  = vring->ring;
+	driver                = vring->driver;
+	device                = vring->device;
+	ring_size_in_bytes    = vring->ring_size_in_bytes;
+	event_size_in_bytes   = vring->event_size_in_bytes;
+	ring_dma_addr         = vring->ring_dma_addr;
+	driver_event_dma_addr = vring->driver_event_dma_addr;
+	device_event_dma_addr = vring->device_event_dma_addr;
+
+	if (device)
+		vring_free_queue(vdev, event_size_in_bytes, device, device_event_dma_addr);
+
+	if (driver)
+		vring_free_queue(vdev, event_size_in_bytes, driver, driver_event_dma_addr);
+
+	if (ring)
+		vring_free_queue(vdev, ring_size_in_bytes, ring, ring_dma_addr);
+}
+
+static int vring_create_vring_packed(struct vring_packed *vring,
+				    struct virtio_device *vdev,
+				    u32 num)
 {
-	struct vring_virtqueue *vq;
 	struct vring_packed_desc *ring;
 	struct vring_packed_desc_event *driver, *device;
 	dma_addr_t ring_dma_addr, driver_event_dma_addr, device_event_dma_addr;
 	size_t ring_size_in_bytes, event_size_in_bytes;
 
+	memset(vring, 0, sizeof(*vring));
+
 	ring_size_in_bytes = num * sizeof(struct vring_packed_desc);
 
 	ring = vring_alloc_queue(vdev, ring_size_in_bytes,
 				 &ring_dma_addr,
 				 GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
 	if (!ring)
-		goto err_ring;
+		goto err;
+
+	vring->num = num;
+	vring->ring = ring;
+	vring->ring_size_in_bytes = ring_size_in_bytes;
+	vring->ring_dma_addr = ring_dma_addr;
 
 	event_size_in_bytes = sizeof(struct vring_packed_desc_event);
+	vring->event_size_in_bytes = event_size_in_bytes;
 
 	driver = vring_alloc_queue(vdev, event_size_in_bytes,
 				   &driver_event_dma_addr,
 				   GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
 	if (!driver)
-		goto err_driver;
+		goto err;
+
+	vring->driver = driver;
+	vring->driver_event_dma_addr = driver_event_dma_addr;
 
 	device = vring_alloc_queue(vdev, event_size_in_bytes,
 				   &device_event_dma_addr,
 				   GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
 	if (!device)
-		goto err_device;
+		goto err;
+
+	vring->device = device;
+	vring->device_event_dma_addr = device_event_dma_addr;
+	return 0;
+
+err:
+	vring_free_vring_packed(vring, vdev);
+	return -ENOMEM;
+}
+
+static struct virtqueue *vring_create_virtqueue_packed(
+	unsigned int index,
+	unsigned int num,
+	unsigned int vring_align,
+	struct virtio_device *vdev,
+	bool weak_barriers,
+	bool may_reduce_num,
+	bool context,
+	bool (*notify)(struct virtqueue *),
+	void (*callback)(struct virtqueue *),
+	const char *name)
+{
+	struct vring_virtqueue *vq;
+	struct vring_packed vring;
+
+	if (vring_create_vring_packed(&vring, vdev, num))
+		goto err_vq;
 
 	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
 	if (!vq)
@@ -1753,17 +1821,17 @@ static struct virtqueue *vring_create_virtqueue_packed(
 	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
 		vq->weak_barriers = false;
 
-	vq->packed.ring_dma_addr = ring_dma_addr;
-	vq->packed.driver_event_dma_addr = driver_event_dma_addr;
-	vq->packed.device_event_dma_addr = device_event_dma_addr;
+	vq->packed.ring_dma_addr = vring.ring_dma_addr;
+	vq->packed.driver_event_dma_addr = vring.driver_event_dma_addr;
+	vq->packed.device_event_dma_addr = vring.device_event_dma_addr;
 
-	vq->packed.ring_size_in_bytes = ring_size_in_bytes;
-	vq->packed.event_size_in_bytes = event_size_in_bytes;
+	vq->packed.ring_size_in_bytes = vring.ring_size_in_bytes;
+	vq->packed.event_size_in_bytes = vring.event_size_in_bytes;
 
 	vq->packed.vring.num = num;
-	vq->packed.vring.desc = ring;
-	vq->packed.vring.driver = driver;
-	vq->packed.vring.device = device;
+	vq->packed.vring.desc = vring.ring;
+	vq->packed.vring.driver = vring.driver;
+	vq->packed.vring.device = vring.device;
 
 	vq->packed.next_avail_idx = 0;
 	vq->packed.avail_wrap_counter = 1;
@@ -1804,12 +1872,7 @@ static struct virtqueue *vring_create_virtqueue_packed(
 err_desc_state:
 	kfree(vq);
 err_vq:
-	vring_free_queue(vdev, event_size_in_bytes, device, device_event_dma_addr);
-err_device:
-	vring_free_queue(vdev, event_size_in_bytes, driver, driver_event_dma_addr);
-err_driver:
-	vring_free_queue(vdev, ring_size_in_bytes, ring, ring_dma_addr);
-err_ring:
+	vring_free_vring_packed(&vring, vdev);
 	return NULL;
 }
 
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 06/26] virtio_ring: packed: extract the logic of creating vring
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Separate the logic of packed to create vring queue.

For the convenience of passing parameters, add a structure
vring_packed.

This feature is required for subsequent virtuqueue reset vring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 121 ++++++++++++++++++++++++++---------
 1 file changed, 92 insertions(+), 29 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index dc6313b79305..1af98b112996 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -92,6 +92,18 @@ struct vring_split {
 	struct vring vring;
 };
 
+struct vring_packed {
+	u32 num;
+	struct vring_packed_desc *ring;
+	struct vring_packed_desc_event *driver;
+	struct vring_packed_desc_event *device;
+	dma_addr_t ring_dma_addr;
+	dma_addr_t driver_event_dma_addr;
+	dma_addr_t device_event_dma_addr;
+	size_t ring_size_in_bytes;
+	size_t event_size_in_bytes;
+};
+
 struct vring_virtqueue {
 	struct virtqueue vq;
 
@@ -1683,45 +1695,101 @@ static struct vring_desc_extra *vring_alloc_desc_extra(struct vring_virtqueue *v
 	return desc_extra;
 }
 
-static struct virtqueue *vring_create_virtqueue_packed(
-	unsigned int index,
-	unsigned int num,
-	unsigned int vring_align,
-	struct virtio_device *vdev,
-	bool weak_barriers,
-	bool may_reduce_num,
-	bool context,
-	bool (*notify)(struct virtqueue *),
-	void (*callback)(struct virtqueue *),
-	const char *name)
+static void vring_free_vring_packed(struct vring_packed *vring,
+				    struct virtio_device *vdev)
+{
+	dma_addr_t ring_dma_addr, driver_event_dma_addr, device_event_dma_addr;
+	struct vring_packed_desc_event *driver, *device;
+	size_t ring_size_in_bytes, event_size_in_bytes;
+	struct vring_packed_desc *ring;
+
+	ring                  = vring->ring;
+	driver                = vring->driver;
+	device                = vring->device;
+	ring_size_in_bytes    = vring->ring_size_in_bytes;
+	event_size_in_bytes   = vring->event_size_in_bytes;
+	ring_dma_addr         = vring->ring_dma_addr;
+	driver_event_dma_addr = vring->driver_event_dma_addr;
+	device_event_dma_addr = vring->device_event_dma_addr;
+
+	if (device)
+		vring_free_queue(vdev, event_size_in_bytes, device, device_event_dma_addr);
+
+	if (driver)
+		vring_free_queue(vdev, event_size_in_bytes, driver, driver_event_dma_addr);
+
+	if (ring)
+		vring_free_queue(vdev, ring_size_in_bytes, ring, ring_dma_addr);
+}
+
+static int vring_create_vring_packed(struct vring_packed *vring,
+				    struct virtio_device *vdev,
+				    u32 num)
 {
-	struct vring_virtqueue *vq;
 	struct vring_packed_desc *ring;
 	struct vring_packed_desc_event *driver, *device;
 	dma_addr_t ring_dma_addr, driver_event_dma_addr, device_event_dma_addr;
 	size_t ring_size_in_bytes, event_size_in_bytes;
 
+	memset(vring, 0, sizeof(*vring));
+
 	ring_size_in_bytes = num * sizeof(struct vring_packed_desc);
 
 	ring = vring_alloc_queue(vdev, ring_size_in_bytes,
 				 &ring_dma_addr,
 				 GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
 	if (!ring)
-		goto err_ring;
+		goto err;
+
+	vring->num = num;
+	vring->ring = ring;
+	vring->ring_size_in_bytes = ring_size_in_bytes;
+	vring->ring_dma_addr = ring_dma_addr;
 
 	event_size_in_bytes = sizeof(struct vring_packed_desc_event);
+	vring->event_size_in_bytes = event_size_in_bytes;
 
 	driver = vring_alloc_queue(vdev, event_size_in_bytes,
 				   &driver_event_dma_addr,
 				   GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
 	if (!driver)
-		goto err_driver;
+		goto err;
+
+	vring->driver = driver;
+	vring->driver_event_dma_addr = driver_event_dma_addr;
 
 	device = vring_alloc_queue(vdev, event_size_in_bytes,
 				   &device_event_dma_addr,
 				   GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
 	if (!device)
-		goto err_device;
+		goto err;
+
+	vring->device = device;
+	vring->device_event_dma_addr = device_event_dma_addr;
+	return 0;
+
+err:
+	vring_free_vring_packed(vring, vdev);
+	return -ENOMEM;
+}
+
+static struct virtqueue *vring_create_virtqueue_packed(
+	unsigned int index,
+	unsigned int num,
+	unsigned int vring_align,
+	struct virtio_device *vdev,
+	bool weak_barriers,
+	bool may_reduce_num,
+	bool context,
+	bool (*notify)(struct virtqueue *),
+	void (*callback)(struct virtqueue *),
+	const char *name)
+{
+	struct vring_virtqueue *vq;
+	struct vring_packed vring;
+
+	if (vring_create_vring_packed(&vring, vdev, num))
+		goto err_vq;
 
 	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
 	if (!vq)
@@ -1753,17 +1821,17 @@ static struct virtqueue *vring_create_virtqueue_packed(
 	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
 		vq->weak_barriers = false;
 
-	vq->packed.ring_dma_addr = ring_dma_addr;
-	vq->packed.driver_event_dma_addr = driver_event_dma_addr;
-	vq->packed.device_event_dma_addr = device_event_dma_addr;
+	vq->packed.ring_dma_addr = vring.ring_dma_addr;
+	vq->packed.driver_event_dma_addr = vring.driver_event_dma_addr;
+	vq->packed.device_event_dma_addr = vring.device_event_dma_addr;
 
-	vq->packed.ring_size_in_bytes = ring_size_in_bytes;
-	vq->packed.event_size_in_bytes = event_size_in_bytes;
+	vq->packed.ring_size_in_bytes = vring.ring_size_in_bytes;
+	vq->packed.event_size_in_bytes = vring.event_size_in_bytes;
 
 	vq->packed.vring.num = num;
-	vq->packed.vring.desc = ring;
-	vq->packed.vring.driver = driver;
-	vq->packed.vring.device = device;
+	vq->packed.vring.desc = vring.ring;
+	vq->packed.vring.driver = vring.driver;
+	vq->packed.vring.device = vring.device;
 
 	vq->packed.next_avail_idx = 0;
 	vq->packed.avail_wrap_counter = 1;
@@ -1804,12 +1872,7 @@ static struct virtqueue *vring_create_virtqueue_packed(
 err_desc_state:
 	kfree(vq);
 err_vq:
-	vring_free_queue(vdev, event_size_in_bytes, device, device_event_dma_addr);
-err_device:
-	vring_free_queue(vdev, event_size_in_bytes, driver, driver_event_dma_addr);
-err_driver:
-	vring_free_queue(vdev, ring_size_in_bytes, ring, ring_dma_addr);
-err_ring:
+	vring_free_vring_packed(&vring, vdev);
 	return NULL;
 }
 
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 06/26] virtio_ring: packed: extract the logic of creating vring
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Separate the logic of packed to create vring queue.

For the convenience of passing parameters, add a structure
vring_packed.

This feature is required for subsequent virtuqueue reset vring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 121 ++++++++++++++++++++++++++---------
 1 file changed, 92 insertions(+), 29 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index dc6313b79305..1af98b112996 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -92,6 +92,18 @@ struct vring_split {
 	struct vring vring;
 };
 
+struct vring_packed {
+	u32 num;
+	struct vring_packed_desc *ring;
+	struct vring_packed_desc_event *driver;
+	struct vring_packed_desc_event *device;
+	dma_addr_t ring_dma_addr;
+	dma_addr_t driver_event_dma_addr;
+	dma_addr_t device_event_dma_addr;
+	size_t ring_size_in_bytes;
+	size_t event_size_in_bytes;
+};
+
 struct vring_virtqueue {
 	struct virtqueue vq;
 
@@ -1683,45 +1695,101 @@ static struct vring_desc_extra *vring_alloc_desc_extra(struct vring_virtqueue *v
 	return desc_extra;
 }
 
-static struct virtqueue *vring_create_virtqueue_packed(
-	unsigned int index,
-	unsigned int num,
-	unsigned int vring_align,
-	struct virtio_device *vdev,
-	bool weak_barriers,
-	bool may_reduce_num,
-	bool context,
-	bool (*notify)(struct virtqueue *),
-	void (*callback)(struct virtqueue *),
-	const char *name)
+static void vring_free_vring_packed(struct vring_packed *vring,
+				    struct virtio_device *vdev)
+{
+	dma_addr_t ring_dma_addr, driver_event_dma_addr, device_event_dma_addr;
+	struct vring_packed_desc_event *driver, *device;
+	size_t ring_size_in_bytes, event_size_in_bytes;
+	struct vring_packed_desc *ring;
+
+	ring                  = vring->ring;
+	driver                = vring->driver;
+	device                = vring->device;
+	ring_size_in_bytes    = vring->ring_size_in_bytes;
+	event_size_in_bytes   = vring->event_size_in_bytes;
+	ring_dma_addr         = vring->ring_dma_addr;
+	driver_event_dma_addr = vring->driver_event_dma_addr;
+	device_event_dma_addr = vring->device_event_dma_addr;
+
+	if (device)
+		vring_free_queue(vdev, event_size_in_bytes, device, device_event_dma_addr);
+
+	if (driver)
+		vring_free_queue(vdev, event_size_in_bytes, driver, driver_event_dma_addr);
+
+	if (ring)
+		vring_free_queue(vdev, ring_size_in_bytes, ring, ring_dma_addr);
+}
+
+static int vring_create_vring_packed(struct vring_packed *vring,
+				    struct virtio_device *vdev,
+				    u32 num)
 {
-	struct vring_virtqueue *vq;
 	struct vring_packed_desc *ring;
 	struct vring_packed_desc_event *driver, *device;
 	dma_addr_t ring_dma_addr, driver_event_dma_addr, device_event_dma_addr;
 	size_t ring_size_in_bytes, event_size_in_bytes;
 
+	memset(vring, 0, sizeof(*vring));
+
 	ring_size_in_bytes = num * sizeof(struct vring_packed_desc);
 
 	ring = vring_alloc_queue(vdev, ring_size_in_bytes,
 				 &ring_dma_addr,
 				 GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
 	if (!ring)
-		goto err_ring;
+		goto err;
+
+	vring->num = num;
+	vring->ring = ring;
+	vring->ring_size_in_bytes = ring_size_in_bytes;
+	vring->ring_dma_addr = ring_dma_addr;
 
 	event_size_in_bytes = sizeof(struct vring_packed_desc_event);
+	vring->event_size_in_bytes = event_size_in_bytes;
 
 	driver = vring_alloc_queue(vdev, event_size_in_bytes,
 				   &driver_event_dma_addr,
 				   GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
 	if (!driver)
-		goto err_driver;
+		goto err;
+
+	vring->driver = driver;
+	vring->driver_event_dma_addr = driver_event_dma_addr;
 
 	device = vring_alloc_queue(vdev, event_size_in_bytes,
 				   &device_event_dma_addr,
 				   GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
 	if (!device)
-		goto err_device;
+		goto err;
+
+	vring->device = device;
+	vring->device_event_dma_addr = device_event_dma_addr;
+	return 0;
+
+err:
+	vring_free_vring_packed(vring, vdev);
+	return -ENOMEM;
+}
+
+static struct virtqueue *vring_create_virtqueue_packed(
+	unsigned int index,
+	unsigned int num,
+	unsigned int vring_align,
+	struct virtio_device *vdev,
+	bool weak_barriers,
+	bool may_reduce_num,
+	bool context,
+	bool (*notify)(struct virtqueue *),
+	void (*callback)(struct virtqueue *),
+	const char *name)
+{
+	struct vring_virtqueue *vq;
+	struct vring_packed vring;
+
+	if (vring_create_vring_packed(&vring, vdev, num))
+		goto err_vq;
 
 	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
 	if (!vq)
@@ -1753,17 +1821,17 @@ static struct virtqueue *vring_create_virtqueue_packed(
 	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
 		vq->weak_barriers = false;
 
-	vq->packed.ring_dma_addr = ring_dma_addr;
-	vq->packed.driver_event_dma_addr = driver_event_dma_addr;
-	vq->packed.device_event_dma_addr = device_event_dma_addr;
+	vq->packed.ring_dma_addr = vring.ring_dma_addr;
+	vq->packed.driver_event_dma_addr = vring.driver_event_dma_addr;
+	vq->packed.device_event_dma_addr = vring.device_event_dma_addr;
 
-	vq->packed.ring_size_in_bytes = ring_size_in_bytes;
-	vq->packed.event_size_in_bytes = event_size_in_bytes;
+	vq->packed.ring_size_in_bytes = vring.ring_size_in_bytes;
+	vq->packed.event_size_in_bytes = vring.event_size_in_bytes;
 
 	vq->packed.vring.num = num;
-	vq->packed.vring.desc = ring;
-	vq->packed.vring.driver = driver;
-	vq->packed.vring.device = device;
+	vq->packed.vring.desc = vring.ring;
+	vq->packed.vring.driver = vring.driver;
+	vq->packed.vring.device = vring.device;
 
 	vq->packed.next_avail_idx = 0;
 	vq->packed.avail_wrap_counter = 1;
@@ -1804,12 +1872,7 @@ static struct virtqueue *vring_create_virtqueue_packed(
 err_desc_state:
 	kfree(vq);
 err_vq:
-	vring_free_queue(vdev, event_size_in_bytes, device, device_event_dma_addr);
-err_device:
-	vring_free_queue(vdev, event_size_in_bytes, driver, driver_event_dma_addr);
-err_driver:
-	vring_free_queue(vdev, ring_size_in_bytes, ring, ring_dma_addr);
-err_ring:
+	vring_free_vring_packed(&vring, vdev);
 	return NULL;
 }
 
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 07/26] virtio_ring: packed: extract the logic of init vq and attach vring
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:34   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Split the logic of packed assignment vq into three parts.

1. The assignment passed from the function parameter
2. The part that attaches vring to vq. -- vring_virtqueue_attach_packed()
3. The part that initializes vq to a fixed value --
vring_virtqueue_init_packed()

This feature is required for subsequent virtuqueue reset vring

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 138 +++++++++++++++++++++--------------
 1 file changed, 82 insertions(+), 56 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 1af98b112996..b5a9bf4f45b3 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1773,36 +1773,53 @@ static int vring_create_vring_packed(struct vring_packed *vring,
 	return -ENOMEM;
 }
 
-static struct virtqueue *vring_create_virtqueue_packed(
-	unsigned int index,
-	unsigned int num,
-	unsigned int vring_align,
-	struct virtio_device *vdev,
-	bool weak_barriers,
-	bool may_reduce_num,
-	bool context,
-	bool (*notify)(struct virtqueue *),
-	void (*callback)(struct virtqueue *),
-	const char *name)
+static int vring_virtqueue_attach_packed(struct vring_virtqueue *vq,
+					 struct vring_packed *vring,
+					 struct virtio_device *vdev)
 {
-	struct vring_virtqueue *vq;
-	struct vring_packed vring;
-
-	if (vring_create_vring_packed(&vring, vdev, num))
-		goto err_vq;
+	u32 num;
 
-	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
-	if (!vq)
-		goto err_vq;
+	num = vring->num;
 
-	vq->vq.callback = callback;
-	vq->vq.vdev = vdev;
-	vq->vq.name = name;
 	vq->vq.num_free = num;
-	vq->vq.index = index;
+
+	vq->packed.ring_dma_addr = vring->ring_dma_addr;
+	vq->packed.driver_event_dma_addr = vring->driver_event_dma_addr;
+	vq->packed.device_event_dma_addr = vring->device_event_dma_addr;
+
+	vq->packed.ring_size_in_bytes = vring->ring_size_in_bytes;
+	vq->packed.event_size_in_bytes = vring->event_size_in_bytes;
+
+	vq->packed.vring.num = num;
+	vq->packed.vring.desc = vring->ring;
+	vq->packed.vring.driver = vring->driver;
+	vq->packed.vring.device = vring->device;
+
+	vq->packed.desc_state = kmalloc_array(num,
+			sizeof(struct vring_desc_state_packed),
+			GFP_KERNEL);
+	if (!vq->packed.desc_state)
+		goto err_desc_state;
+
+	memset(vq->packed.desc_state, 0,
+		num * sizeof(struct vring_desc_state_packed));
+
+	vq->packed.desc_extra = vring_alloc_desc_extra(vq, num);
+	if (!vq->packed.desc_extra)
+		goto err_desc_extra;
+
+	return 0;
+
+err_desc_extra:
+	kfree(vq->packed.desc_state);
+err_desc_state:
+	return -ENOMEM;
+}
+
+static void vring_virtqueue_init_packed(struct vring_virtqueue *vq,
+					struct virtio_device *vdev)
+{
 	vq->we_own_ring = true;
-	vq->notify = notify;
-	vq->weak_barriers = weak_barriers;
 	vq->broken = false;
 	vq->last_used_idx = 0;
 	vq->event_triggered = false;
@@ -1814,62 +1831,71 @@ static struct virtqueue *vring_create_virtqueue_packed(
 	vq->last_add_time_valid = false;
 #endif
 
-	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
-		!context;
 	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
 	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
 		vq->weak_barriers = false;
 
-	vq->packed.ring_dma_addr = vring.ring_dma_addr;
-	vq->packed.driver_event_dma_addr = vring.driver_event_dma_addr;
-	vq->packed.device_event_dma_addr = vring.device_event_dma_addr;
-
-	vq->packed.ring_size_in_bytes = vring.ring_size_in_bytes;
-	vq->packed.event_size_in_bytes = vring.event_size_in_bytes;
-
-	vq->packed.vring.num = num;
-	vq->packed.vring.desc = vring.ring;
-	vq->packed.vring.driver = vring.driver;
-	vq->packed.vring.device = vring.device;
-
 	vq->packed.next_avail_idx = 0;
 	vq->packed.avail_wrap_counter = 1;
 	vq->packed.used_wrap_counter = 1;
 	vq->packed.event_flags_shadow = 0;
 	vq->packed.avail_used_flags = 1 << VRING_PACKED_DESC_F_AVAIL;
 
-	vq->packed.desc_state = kmalloc_array(num,
-			sizeof(struct vring_desc_state_packed),
-			GFP_KERNEL);
-	if (!vq->packed.desc_state)
-		goto err_desc_state;
-
-	memset(vq->packed.desc_state, 0,
-		num * sizeof(struct vring_desc_state_packed));
-
 	/* Put everything in free lists. */
 	vq->free_head = 0;
 
-	vq->packed.desc_extra = vring_alloc_desc_extra(vq, num);
-	if (!vq->packed.desc_extra)
-		goto err_desc_extra;
-
 	/* No callback?  Tell other side not to bother us. */
-	if (!callback) {
+	if (!vq->vq.callback) {
 		vq->packed.event_flags_shadow = VRING_PACKED_EVENT_FLAG_DISABLE;
 		vq->packed.vring.driver->flags =
 			cpu_to_le16(vq->packed.event_flags_shadow);
 	}
+}
+
+static struct virtqueue *vring_create_virtqueue_packed(
+	unsigned int index,
+	unsigned int num,
+	unsigned int vring_align,
+	struct virtio_device *vdev,
+	bool weak_barriers,
+	bool may_reduce_num,
+	bool context,
+	bool (*notify)(struct virtqueue *),
+	void (*callback)(struct virtqueue *),
+	const char *name)
+{
+	struct vring_virtqueue *vq;
+	struct vring_packed vring;
+
+	if (vring_create_vring_packed(&vring, vdev, num))
+		goto err_vq;
+
+	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
+	if (!vq)
+		goto err_vq;
+
+	vq->vq.callback = callback;
+	vq->vq.vdev = vdev;
+	vq->vq.name = name;
+	vq->vq.index = index;
+	vq->notify = notify;
+	vq->weak_barriers = weak_barriers;
+	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
+		!context;
+
+	if (vring_virtqueue_attach_packed(vq, &vring, vdev))
+		goto err;
+
+	vring_virtqueue_init_packed(vq, vdev);
 
 	spin_lock(&vdev->vqs_list_lock);
 	list_add_tail(&vq->vq.list, &vdev->vqs);
 	spin_unlock(&vdev->vqs_list_lock);
+
 	return &vq->vq;
 
-err_desc_extra:
-	kfree(vq->packed.desc_state);
-err_desc_state:
+err:
 	kfree(vq);
 err_vq:
 	vring_free_vring_packed(&vring, vdev);
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 07/26] virtio_ring: packed: extract the logic of init vq and attach vring
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Split the logic of packed assignment vq into three parts.

1. The assignment passed from the function parameter
2. The part that attaches vring to vq. -- vring_virtqueue_attach_packed()
3. The part that initializes vq to a fixed value --
vring_virtqueue_init_packed()

This feature is required for subsequent virtuqueue reset vring

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 138 +++++++++++++++++++++--------------
 1 file changed, 82 insertions(+), 56 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 1af98b112996..b5a9bf4f45b3 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1773,36 +1773,53 @@ static int vring_create_vring_packed(struct vring_packed *vring,
 	return -ENOMEM;
 }
 
-static struct virtqueue *vring_create_virtqueue_packed(
-	unsigned int index,
-	unsigned int num,
-	unsigned int vring_align,
-	struct virtio_device *vdev,
-	bool weak_barriers,
-	bool may_reduce_num,
-	bool context,
-	bool (*notify)(struct virtqueue *),
-	void (*callback)(struct virtqueue *),
-	const char *name)
+static int vring_virtqueue_attach_packed(struct vring_virtqueue *vq,
+					 struct vring_packed *vring,
+					 struct virtio_device *vdev)
 {
-	struct vring_virtqueue *vq;
-	struct vring_packed vring;
-
-	if (vring_create_vring_packed(&vring, vdev, num))
-		goto err_vq;
+	u32 num;
 
-	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
-	if (!vq)
-		goto err_vq;
+	num = vring->num;
 
-	vq->vq.callback = callback;
-	vq->vq.vdev = vdev;
-	vq->vq.name = name;
 	vq->vq.num_free = num;
-	vq->vq.index = index;
+
+	vq->packed.ring_dma_addr = vring->ring_dma_addr;
+	vq->packed.driver_event_dma_addr = vring->driver_event_dma_addr;
+	vq->packed.device_event_dma_addr = vring->device_event_dma_addr;
+
+	vq->packed.ring_size_in_bytes = vring->ring_size_in_bytes;
+	vq->packed.event_size_in_bytes = vring->event_size_in_bytes;
+
+	vq->packed.vring.num = num;
+	vq->packed.vring.desc = vring->ring;
+	vq->packed.vring.driver = vring->driver;
+	vq->packed.vring.device = vring->device;
+
+	vq->packed.desc_state = kmalloc_array(num,
+			sizeof(struct vring_desc_state_packed),
+			GFP_KERNEL);
+	if (!vq->packed.desc_state)
+		goto err_desc_state;
+
+	memset(vq->packed.desc_state, 0,
+		num * sizeof(struct vring_desc_state_packed));
+
+	vq->packed.desc_extra = vring_alloc_desc_extra(vq, num);
+	if (!vq->packed.desc_extra)
+		goto err_desc_extra;
+
+	return 0;
+
+err_desc_extra:
+	kfree(vq->packed.desc_state);
+err_desc_state:
+	return -ENOMEM;
+}
+
+static void vring_virtqueue_init_packed(struct vring_virtqueue *vq,
+					struct virtio_device *vdev)
+{
 	vq->we_own_ring = true;
-	vq->notify = notify;
-	vq->weak_barriers = weak_barriers;
 	vq->broken = false;
 	vq->last_used_idx = 0;
 	vq->event_triggered = false;
@@ -1814,62 +1831,71 @@ static struct virtqueue *vring_create_virtqueue_packed(
 	vq->last_add_time_valid = false;
 #endif
 
-	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
-		!context;
 	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
 	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
 		vq->weak_barriers = false;
 
-	vq->packed.ring_dma_addr = vring.ring_dma_addr;
-	vq->packed.driver_event_dma_addr = vring.driver_event_dma_addr;
-	vq->packed.device_event_dma_addr = vring.device_event_dma_addr;
-
-	vq->packed.ring_size_in_bytes = vring.ring_size_in_bytes;
-	vq->packed.event_size_in_bytes = vring.event_size_in_bytes;
-
-	vq->packed.vring.num = num;
-	vq->packed.vring.desc = vring.ring;
-	vq->packed.vring.driver = vring.driver;
-	vq->packed.vring.device = vring.device;
-
 	vq->packed.next_avail_idx = 0;
 	vq->packed.avail_wrap_counter = 1;
 	vq->packed.used_wrap_counter = 1;
 	vq->packed.event_flags_shadow = 0;
 	vq->packed.avail_used_flags = 1 << VRING_PACKED_DESC_F_AVAIL;
 
-	vq->packed.desc_state = kmalloc_array(num,
-			sizeof(struct vring_desc_state_packed),
-			GFP_KERNEL);
-	if (!vq->packed.desc_state)
-		goto err_desc_state;
-
-	memset(vq->packed.desc_state, 0,
-		num * sizeof(struct vring_desc_state_packed));
-
 	/* Put everything in free lists. */
 	vq->free_head = 0;
 
-	vq->packed.desc_extra = vring_alloc_desc_extra(vq, num);
-	if (!vq->packed.desc_extra)
-		goto err_desc_extra;
-
 	/* No callback?  Tell other side not to bother us. */
-	if (!callback) {
+	if (!vq->vq.callback) {
 		vq->packed.event_flags_shadow = VRING_PACKED_EVENT_FLAG_DISABLE;
 		vq->packed.vring.driver->flags =
 			cpu_to_le16(vq->packed.event_flags_shadow);
 	}
+}
+
+static struct virtqueue *vring_create_virtqueue_packed(
+	unsigned int index,
+	unsigned int num,
+	unsigned int vring_align,
+	struct virtio_device *vdev,
+	bool weak_barriers,
+	bool may_reduce_num,
+	bool context,
+	bool (*notify)(struct virtqueue *),
+	void (*callback)(struct virtqueue *),
+	const char *name)
+{
+	struct vring_virtqueue *vq;
+	struct vring_packed vring;
+
+	if (vring_create_vring_packed(&vring, vdev, num))
+		goto err_vq;
+
+	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
+	if (!vq)
+		goto err_vq;
+
+	vq->vq.callback = callback;
+	vq->vq.vdev = vdev;
+	vq->vq.name = name;
+	vq->vq.index = index;
+	vq->notify = notify;
+	vq->weak_barriers = weak_barriers;
+	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
+		!context;
+
+	if (vring_virtqueue_attach_packed(vq, &vring, vdev))
+		goto err;
+
+	vring_virtqueue_init_packed(vq, vdev);
 
 	spin_lock(&vdev->vqs_list_lock);
 	list_add_tail(&vq->vq.list, &vdev->vqs);
 	spin_unlock(&vdev->vqs_list_lock);
+
 	return &vq->vq;
 
-err_desc_extra:
-	kfree(vq->packed.desc_state);
-err_desc_state:
+err:
 	kfree(vq);
 err_vq:
 	vring_free_vring_packed(&vring, vdev);
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 07/26] virtio_ring: packed: extract the logic of init vq and attach vring
@ 2022-03-08 12:34   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:34 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Split the logic of packed assignment vq into three parts.

1. The assignment passed from the function parameter
2. The part that attaches vring to vq. -- vring_virtqueue_attach_packed()
3. The part that initializes vq to a fixed value --
vring_virtqueue_init_packed()

This feature is required for subsequent virtuqueue reset vring

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 138 +++++++++++++++++++++--------------
 1 file changed, 82 insertions(+), 56 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 1af98b112996..b5a9bf4f45b3 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1773,36 +1773,53 @@ static int vring_create_vring_packed(struct vring_packed *vring,
 	return -ENOMEM;
 }
 
-static struct virtqueue *vring_create_virtqueue_packed(
-	unsigned int index,
-	unsigned int num,
-	unsigned int vring_align,
-	struct virtio_device *vdev,
-	bool weak_barriers,
-	bool may_reduce_num,
-	bool context,
-	bool (*notify)(struct virtqueue *),
-	void (*callback)(struct virtqueue *),
-	const char *name)
+static int vring_virtqueue_attach_packed(struct vring_virtqueue *vq,
+					 struct vring_packed *vring,
+					 struct virtio_device *vdev)
 {
-	struct vring_virtqueue *vq;
-	struct vring_packed vring;
-
-	if (vring_create_vring_packed(&vring, vdev, num))
-		goto err_vq;
+	u32 num;
 
-	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
-	if (!vq)
-		goto err_vq;
+	num = vring->num;
 
-	vq->vq.callback = callback;
-	vq->vq.vdev = vdev;
-	vq->vq.name = name;
 	vq->vq.num_free = num;
-	vq->vq.index = index;
+
+	vq->packed.ring_dma_addr = vring->ring_dma_addr;
+	vq->packed.driver_event_dma_addr = vring->driver_event_dma_addr;
+	vq->packed.device_event_dma_addr = vring->device_event_dma_addr;
+
+	vq->packed.ring_size_in_bytes = vring->ring_size_in_bytes;
+	vq->packed.event_size_in_bytes = vring->event_size_in_bytes;
+
+	vq->packed.vring.num = num;
+	vq->packed.vring.desc = vring->ring;
+	vq->packed.vring.driver = vring->driver;
+	vq->packed.vring.device = vring->device;
+
+	vq->packed.desc_state = kmalloc_array(num,
+			sizeof(struct vring_desc_state_packed),
+			GFP_KERNEL);
+	if (!vq->packed.desc_state)
+		goto err_desc_state;
+
+	memset(vq->packed.desc_state, 0,
+		num * sizeof(struct vring_desc_state_packed));
+
+	vq->packed.desc_extra = vring_alloc_desc_extra(vq, num);
+	if (!vq->packed.desc_extra)
+		goto err_desc_extra;
+
+	return 0;
+
+err_desc_extra:
+	kfree(vq->packed.desc_state);
+err_desc_state:
+	return -ENOMEM;
+}
+
+static void vring_virtqueue_init_packed(struct vring_virtqueue *vq,
+					struct virtio_device *vdev)
+{
 	vq->we_own_ring = true;
-	vq->notify = notify;
-	vq->weak_barriers = weak_barriers;
 	vq->broken = false;
 	vq->last_used_idx = 0;
 	vq->event_triggered = false;
@@ -1814,62 +1831,71 @@ static struct virtqueue *vring_create_virtqueue_packed(
 	vq->last_add_time_valid = false;
 #endif
 
-	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
-		!context;
 	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
 	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
 		vq->weak_barriers = false;
 
-	vq->packed.ring_dma_addr = vring.ring_dma_addr;
-	vq->packed.driver_event_dma_addr = vring.driver_event_dma_addr;
-	vq->packed.device_event_dma_addr = vring.device_event_dma_addr;
-
-	vq->packed.ring_size_in_bytes = vring.ring_size_in_bytes;
-	vq->packed.event_size_in_bytes = vring.event_size_in_bytes;
-
-	vq->packed.vring.num = num;
-	vq->packed.vring.desc = vring.ring;
-	vq->packed.vring.driver = vring.driver;
-	vq->packed.vring.device = vring.device;
-
 	vq->packed.next_avail_idx = 0;
 	vq->packed.avail_wrap_counter = 1;
 	vq->packed.used_wrap_counter = 1;
 	vq->packed.event_flags_shadow = 0;
 	vq->packed.avail_used_flags = 1 << VRING_PACKED_DESC_F_AVAIL;
 
-	vq->packed.desc_state = kmalloc_array(num,
-			sizeof(struct vring_desc_state_packed),
-			GFP_KERNEL);
-	if (!vq->packed.desc_state)
-		goto err_desc_state;
-
-	memset(vq->packed.desc_state, 0,
-		num * sizeof(struct vring_desc_state_packed));
-
 	/* Put everything in free lists. */
 	vq->free_head = 0;
 
-	vq->packed.desc_extra = vring_alloc_desc_extra(vq, num);
-	if (!vq->packed.desc_extra)
-		goto err_desc_extra;
-
 	/* No callback?  Tell other side not to bother us. */
-	if (!callback) {
+	if (!vq->vq.callback) {
 		vq->packed.event_flags_shadow = VRING_PACKED_EVENT_FLAG_DISABLE;
 		vq->packed.vring.driver->flags =
 			cpu_to_le16(vq->packed.event_flags_shadow);
 	}
+}
+
+static struct virtqueue *vring_create_virtqueue_packed(
+	unsigned int index,
+	unsigned int num,
+	unsigned int vring_align,
+	struct virtio_device *vdev,
+	bool weak_barriers,
+	bool may_reduce_num,
+	bool context,
+	bool (*notify)(struct virtqueue *),
+	void (*callback)(struct virtqueue *),
+	const char *name)
+{
+	struct vring_virtqueue *vq;
+	struct vring_packed vring;
+
+	if (vring_create_vring_packed(&vring, vdev, num))
+		goto err_vq;
+
+	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
+	if (!vq)
+		goto err_vq;
+
+	vq->vq.callback = callback;
+	vq->vq.vdev = vdev;
+	vq->vq.name = name;
+	vq->vq.index = index;
+	vq->notify = notify;
+	vq->weak_barriers = weak_barriers;
+	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
+		!context;
+
+	if (vring_virtqueue_attach_packed(vq, &vring, vdev))
+		goto err;
+
+	vring_virtqueue_init_packed(vq, vdev);
 
 	spin_lock(&vdev->vqs_list_lock);
 	list_add_tail(&vq->vq.list, &vdev->vqs);
 	spin_unlock(&vdev->vqs_list_lock);
+
 	return &vq->vq;
 
-err_desc_extra:
-	kfree(vq->packed.desc_state);
-err_desc_state:
+err:
 	kfree(vq);
 err_vq:
 	vring_free_vring_packed(&vring, vdev);
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 08/26] virtio_ring: extract the logic of freeing vring
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Introduce vring_free() to free the vring of vq.

Prevent double free by setting vq->reset.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 25 ++++++++++++++++++++-----
 include/linux/virtio.h       |  8 ++++++++
 2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index b5a9bf4f45b3..e0422c04c903 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2442,14 +2442,10 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
 }
 EXPORT_SYMBOL_GPL(vring_new_virtqueue);
 
-void vring_del_virtqueue(struct virtqueue *_vq)
+static void __vring_free(struct virtqueue *_vq)
 {
 	struct vring_virtqueue *vq = to_vvq(_vq);
 
-	spin_lock(&vq->vq.vdev->vqs_list_lock);
-	list_del(&_vq->list);
-	spin_unlock(&vq->vq.vdev->vqs_list_lock);
-
 	if (vq->we_own_ring) {
 		if (vq->packed_ring) {
 			vring_free_queue(vq->vq.vdev,
@@ -2480,6 +2476,25 @@ void vring_del_virtqueue(struct virtqueue *_vq)
 		kfree(vq->split.desc_state);
 		kfree(vq->split.desc_extra);
 	}
+}
+
+static void vring_free(struct virtqueue *vq)
+{
+	__vring_free(vq);
+	vq->reset = VIRTIO_VQ_RESET_STEP_VRING_RELEASE;
+}
+
+void vring_del_virtqueue(struct virtqueue *_vq)
+{
+	struct vring_virtqueue *vq = to_vvq(_vq);
+
+	spin_lock(&vq->vq.vdev->vqs_list_lock);
+	list_del(&_vq->list);
+	spin_unlock(&vq->vq.vdev->vqs_list_lock);
+
+	if (_vq->reset != VIRTIO_VQ_RESET_STEP_VRING_RELEASE)
+		__vring_free(_vq);
+
 	kfree(vq);
 }
 EXPORT_SYMBOL_GPL(vring_del_virtqueue);
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index d59adc4be068..e3714e6db330 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -10,6 +10,13 @@
 #include <linux/mod_devicetable.h>
 #include <linux/gfp.h>
 
+enum virtio_vq_reset_step {
+	VIRTIO_VQ_RESET_STEP_NONE,
+	VIRTIO_VQ_RESET_STEP_DEVICE,
+	VIRTIO_VQ_RESET_STEP_VRING_RELEASE,
+	VIRTIO_VQ_RESET_STEP_VRING_ATTACH,
+};
+
 /**
  * virtqueue - a queue to register buffers for sending or receiving.
  * @list: the chain of virtqueues for this device
@@ -33,6 +40,7 @@ struct virtqueue {
 	unsigned int num_free;
 	unsigned int num_max;
 	void *priv;
+	enum virtio_vq_reset_step reset;
 };
 
 int virtqueue_add_outbuf(struct virtqueue *vq,
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 08/26] virtio_ring: extract the logic of freeing vring
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Introduce vring_free() to free the vring of vq.

Prevent double free by setting vq->reset.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 25 ++++++++++++++++++++-----
 include/linux/virtio.h       |  8 ++++++++
 2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index b5a9bf4f45b3..e0422c04c903 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2442,14 +2442,10 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
 }
 EXPORT_SYMBOL_GPL(vring_new_virtqueue);
 
-void vring_del_virtqueue(struct virtqueue *_vq)
+static void __vring_free(struct virtqueue *_vq)
 {
 	struct vring_virtqueue *vq = to_vvq(_vq);
 
-	spin_lock(&vq->vq.vdev->vqs_list_lock);
-	list_del(&_vq->list);
-	spin_unlock(&vq->vq.vdev->vqs_list_lock);
-
 	if (vq->we_own_ring) {
 		if (vq->packed_ring) {
 			vring_free_queue(vq->vq.vdev,
@@ -2480,6 +2476,25 @@ void vring_del_virtqueue(struct virtqueue *_vq)
 		kfree(vq->split.desc_state);
 		kfree(vq->split.desc_extra);
 	}
+}
+
+static void vring_free(struct virtqueue *vq)
+{
+	__vring_free(vq);
+	vq->reset = VIRTIO_VQ_RESET_STEP_VRING_RELEASE;
+}
+
+void vring_del_virtqueue(struct virtqueue *_vq)
+{
+	struct vring_virtqueue *vq = to_vvq(_vq);
+
+	spin_lock(&vq->vq.vdev->vqs_list_lock);
+	list_del(&_vq->list);
+	spin_unlock(&vq->vq.vdev->vqs_list_lock);
+
+	if (_vq->reset != VIRTIO_VQ_RESET_STEP_VRING_RELEASE)
+		__vring_free(_vq);
+
 	kfree(vq);
 }
 EXPORT_SYMBOL_GPL(vring_del_virtqueue);
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index d59adc4be068..e3714e6db330 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -10,6 +10,13 @@
 #include <linux/mod_devicetable.h>
 #include <linux/gfp.h>
 
+enum virtio_vq_reset_step {
+	VIRTIO_VQ_RESET_STEP_NONE,
+	VIRTIO_VQ_RESET_STEP_DEVICE,
+	VIRTIO_VQ_RESET_STEP_VRING_RELEASE,
+	VIRTIO_VQ_RESET_STEP_VRING_ATTACH,
+};
+
 /**
  * virtqueue - a queue to register buffers for sending or receiving.
  * @list: the chain of virtqueues for this device
@@ -33,6 +40,7 @@ struct virtqueue {
 	unsigned int num_free;
 	unsigned int num_max;
 	void *priv;
+	enum virtio_vq_reset_step reset;
 };
 
 int virtqueue_add_outbuf(struct virtqueue *vq,
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 08/26] virtio_ring: extract the logic of freeing vring
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Introduce vring_free() to free the vring of vq.

Prevent double free by setting vq->reset.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 25 ++++++++++++++++++++-----
 include/linux/virtio.h       |  8 ++++++++
 2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index b5a9bf4f45b3..e0422c04c903 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2442,14 +2442,10 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
 }
 EXPORT_SYMBOL_GPL(vring_new_virtqueue);
 
-void vring_del_virtqueue(struct virtqueue *_vq)
+static void __vring_free(struct virtqueue *_vq)
 {
 	struct vring_virtqueue *vq = to_vvq(_vq);
 
-	spin_lock(&vq->vq.vdev->vqs_list_lock);
-	list_del(&_vq->list);
-	spin_unlock(&vq->vq.vdev->vqs_list_lock);
-
 	if (vq->we_own_ring) {
 		if (vq->packed_ring) {
 			vring_free_queue(vq->vq.vdev,
@@ -2480,6 +2476,25 @@ void vring_del_virtqueue(struct virtqueue *_vq)
 		kfree(vq->split.desc_state);
 		kfree(vq->split.desc_extra);
 	}
+}
+
+static void vring_free(struct virtqueue *vq)
+{
+	__vring_free(vq);
+	vq->reset = VIRTIO_VQ_RESET_STEP_VRING_RELEASE;
+}
+
+void vring_del_virtqueue(struct virtqueue *_vq)
+{
+	struct vring_virtqueue *vq = to_vvq(_vq);
+
+	spin_lock(&vq->vq.vdev->vqs_list_lock);
+	list_del(&_vq->list);
+	spin_unlock(&vq->vq.vdev->vqs_list_lock);
+
+	if (_vq->reset != VIRTIO_VQ_RESET_STEP_VRING_RELEASE)
+		__vring_free(_vq);
+
 	kfree(vq);
 }
 EXPORT_SYMBOL_GPL(vring_del_virtqueue);
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index d59adc4be068..e3714e6db330 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -10,6 +10,13 @@
 #include <linux/mod_devicetable.h>
 #include <linux/gfp.h>
 
+enum virtio_vq_reset_step {
+	VIRTIO_VQ_RESET_STEP_NONE,
+	VIRTIO_VQ_RESET_STEP_DEVICE,
+	VIRTIO_VQ_RESET_STEP_VRING_RELEASE,
+	VIRTIO_VQ_RESET_STEP_VRING_ATTACH,
+};
+
 /**
  * virtqueue - a queue to register buffers for sending or receiving.
  * @list: the chain of virtqueues for this device
@@ -33,6 +40,7 @@ struct virtqueue {
 	unsigned int num_free;
 	unsigned int num_max;
 	void *priv;
+	enum virtio_vq_reset_step reset;
 };
 
 int virtqueue_add_outbuf(struct virtqueue *vq,
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

virtio ring supports reset.

Queue reset is divided into several stages.

1. notify device queue reset
2. vring release
3. attach new vring
4. notify device queue re-enable

After the first step is completed, the vring reset operation can be
performed. If the newly set vring num does not change, then just reset
the vq related value.

Otherwise, the vring will be released and the vring will be reallocated.
And the vring will be attached to the vq. If this process fails, the
function will exit, and the state of the vq will be the vring release
state. You can call this function again to reallocate the vring.

In addition, vring_align, may_reduce_num are necessary for reallocating
vring, so they are retained when creating vq.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index e0422c04c903..148fb1fd3d5a 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -158,6 +158,12 @@ struct vring_virtqueue {
 			/* DMA address and size information */
 			dma_addr_t queue_dma_addr;
 			size_t queue_size_in_bytes;
+
+			/* The parameters for creating vrings are reserved for
+			 * creating new vrings when enabling reset queue.
+			 */
+			u32 vring_align;
+			bool may_reduce_num;
 		} split;
 
 		/* Available for packed ring */
@@ -217,6 +223,12 @@ struct vring_virtqueue {
 #endif
 };
 
+static void vring_free(struct virtqueue *vq);
+static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
+					 struct virtio_device *vdev);
+static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
+					  struct virtio_device *vdev,
+					  struct vring vring);
 
 /*
  * Helpers.
@@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
 		return NULL;
 	}
 
+	to_vvq(vq)->split.vring_align = vring_align;
+	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
 	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
 	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
 	to_vvq(vq)->we_own_ring = true;
@@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
 	return vq;
 }
 
+static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
+{
+	struct vring_virtqueue *vq = to_vvq(_vq);
+	struct virtio_device *vdev = _vq->vdev;
+	struct vring_split vring;
+	int err;
+
+	if (num > _vq->num_max)
+		return -E2BIG;
+
+	switch (vq->vq.reset) {
+	case VIRTIO_VQ_RESET_STEP_NONE:
+		return -ENOENT;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
+	case VIRTIO_VQ_RESET_STEP_DEVICE:
+		if (vq->split.vring.num == num || !num)
+			break;
+
+		vring_free(_vq);
+
+		fallthrough;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
+		if (!num)
+			num = vq->split.vring.num;
+
+		err = vring_create_vring_split(&vring, vdev,
+					       vq->split.vring_align,
+					       vq->weak_barriers,
+					       vq->split.may_reduce_num, num);
+		if (err)
+			return -ENOMEM;
+
+		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
+		if (err) {
+			vring_free_queue(vdev, vring.queue_size_in_bytes,
+					 vring.queue,
+					 vring.dma_addr);
+			return -ENOMEM;
+		}
+
+		vq->split.queue_dma_addr = vring.dma_addr;
+		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
+	}
+
+	__vring_virtqueue_init_split(vq, vdev);
+	vq->we_own_ring = true;
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
+
+	return 0;
+}
+
 
 /*
  * Packed ring specific functions - *_packed().
@@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
 static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
 					 struct virtio_device *vdev)
 {
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
+
 	vq->packed_ring = false;
 	vq->we_own_ring = false;
 	vq->broken = false;
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

virtio ring supports reset.

Queue reset is divided into several stages.

1. notify device queue reset
2. vring release
3. attach new vring
4. notify device queue re-enable

After the first step is completed, the vring reset operation can be
performed. If the newly set vring num does not change, then just reset
the vq related value.

Otherwise, the vring will be released and the vring will be reallocated.
And the vring will be attached to the vq. If this process fails, the
function will exit, and the state of the vq will be the vring release
state. You can call this function again to reallocate the vring.

In addition, vring_align, may_reduce_num are necessary for reallocating
vring, so they are retained when creating vq.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index e0422c04c903..148fb1fd3d5a 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -158,6 +158,12 @@ struct vring_virtqueue {
 			/* DMA address and size information */
 			dma_addr_t queue_dma_addr;
 			size_t queue_size_in_bytes;
+
+			/* The parameters for creating vrings are reserved for
+			 * creating new vrings when enabling reset queue.
+			 */
+			u32 vring_align;
+			bool may_reduce_num;
 		} split;
 
 		/* Available for packed ring */
@@ -217,6 +223,12 @@ struct vring_virtqueue {
 #endif
 };
 
+static void vring_free(struct virtqueue *vq);
+static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
+					 struct virtio_device *vdev);
+static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
+					  struct virtio_device *vdev,
+					  struct vring vring);
 
 /*
  * Helpers.
@@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
 		return NULL;
 	}
 
+	to_vvq(vq)->split.vring_align = vring_align;
+	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
 	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
 	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
 	to_vvq(vq)->we_own_ring = true;
@@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
 	return vq;
 }
 
+static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
+{
+	struct vring_virtqueue *vq = to_vvq(_vq);
+	struct virtio_device *vdev = _vq->vdev;
+	struct vring_split vring;
+	int err;
+
+	if (num > _vq->num_max)
+		return -E2BIG;
+
+	switch (vq->vq.reset) {
+	case VIRTIO_VQ_RESET_STEP_NONE:
+		return -ENOENT;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
+	case VIRTIO_VQ_RESET_STEP_DEVICE:
+		if (vq->split.vring.num == num || !num)
+			break;
+
+		vring_free(_vq);
+
+		fallthrough;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
+		if (!num)
+			num = vq->split.vring.num;
+
+		err = vring_create_vring_split(&vring, vdev,
+					       vq->split.vring_align,
+					       vq->weak_barriers,
+					       vq->split.may_reduce_num, num);
+		if (err)
+			return -ENOMEM;
+
+		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
+		if (err) {
+			vring_free_queue(vdev, vring.queue_size_in_bytes,
+					 vring.queue,
+					 vring.dma_addr);
+			return -ENOMEM;
+		}
+
+		vq->split.queue_dma_addr = vring.dma_addr;
+		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
+	}
+
+	__vring_virtqueue_init_split(vq, vdev);
+	vq->we_own_ring = true;
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
+
+	return 0;
+}
+
 
 /*
  * Packed ring specific functions - *_packed().
@@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
 static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
 					 struct virtio_device *vdev)
 {
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
+
 	vq->packed_ring = false;
 	vq->we_own_ring = false;
 	vq->broken = false;
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

virtio ring supports reset.

Queue reset is divided into several stages.

1. notify device queue reset
2. vring release
3. attach new vring
4. notify device queue re-enable

After the first step is completed, the vring reset operation can be
performed. If the newly set vring num does not change, then just reset
the vq related value.

Otherwise, the vring will be released and the vring will be reallocated.
And the vring will be attached to the vq. If this process fails, the
function will exit, and the state of the vq will be the vring release
state. You can call this function again to reallocate the vring.

In addition, vring_align, may_reduce_num are necessary for reallocating
vring, so they are retained when creating vq.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index e0422c04c903..148fb1fd3d5a 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -158,6 +158,12 @@ struct vring_virtqueue {
 			/* DMA address and size information */
 			dma_addr_t queue_dma_addr;
 			size_t queue_size_in_bytes;
+
+			/* The parameters for creating vrings are reserved for
+			 * creating new vrings when enabling reset queue.
+			 */
+			u32 vring_align;
+			bool may_reduce_num;
 		} split;
 
 		/* Available for packed ring */
@@ -217,6 +223,12 @@ struct vring_virtqueue {
 #endif
 };
 
+static void vring_free(struct virtqueue *vq);
+static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
+					 struct virtio_device *vdev);
+static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
+					  struct virtio_device *vdev,
+					  struct vring vring);
 
 /*
  * Helpers.
@@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
 		return NULL;
 	}
 
+	to_vvq(vq)->split.vring_align = vring_align;
+	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
 	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
 	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
 	to_vvq(vq)->we_own_ring = true;
@@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
 	return vq;
 }
 
+static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
+{
+	struct vring_virtqueue *vq = to_vvq(_vq);
+	struct virtio_device *vdev = _vq->vdev;
+	struct vring_split vring;
+	int err;
+
+	if (num > _vq->num_max)
+		return -E2BIG;
+
+	switch (vq->vq.reset) {
+	case VIRTIO_VQ_RESET_STEP_NONE:
+		return -ENOENT;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
+	case VIRTIO_VQ_RESET_STEP_DEVICE:
+		if (vq->split.vring.num == num || !num)
+			break;
+
+		vring_free(_vq);
+
+		fallthrough;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
+		if (!num)
+			num = vq->split.vring.num;
+
+		err = vring_create_vring_split(&vring, vdev,
+					       vq->split.vring_align,
+					       vq->weak_barriers,
+					       vq->split.may_reduce_num, num);
+		if (err)
+			return -ENOMEM;
+
+		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
+		if (err) {
+			vring_free_queue(vdev, vring.queue_size_in_bytes,
+					 vring.queue,
+					 vring.dma_addr);
+			return -ENOMEM;
+		}
+
+		vq->split.queue_dma_addr = vring.dma_addr;
+		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
+	}
+
+	__vring_virtqueue_init_split(vq, vdev);
+	vq->we_own_ring = true;
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
+
+	return 0;
+}
+
 
 /*
  * Packed ring specific functions - *_packed().
@@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
 static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
 					 struct virtio_device *vdev)
 {
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
+
 	vq->packed_ring = false;
 	vq->we_own_ring = false;
 	vq->broken = false;
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 10/26] virtio_ring: packed: implement virtqueue_reset_vring_packed()
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

virtio ring supports reset.

Queue reset is divided into several stages.

1. notify device queue reset
2. vring release
3. attach new vring
4. notify device queue re-enable

After the first step is completed, the vring reset operation can be
performed. If the newly set vring num does not change, then just reset
the vq related value.

Otherwise, the vring will be released and the vring will be reallocated.
And the vring will be attached to the vq. If this process fails, the
function will exit, and the state of the vq will be the vring release
state. You can call this function again to reallocate the vring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 46 ++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 148fb1fd3d5a..5afcbabcfb1e 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1886,6 +1886,8 @@ static int vring_virtqueue_attach_packed(struct vring_virtqueue *vq,
 static void vring_virtqueue_init_packed(struct vring_virtqueue *vq,
 					struct virtio_device *vdev)
 {
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
+
 	vq->we_own_ring = true;
 	vq->broken = false;
 	vq->last_used_idx = 0;
@@ -1969,6 +1971,50 @@ static struct virtqueue *vring_create_virtqueue_packed(
 	return NULL;
 }
 
+static int virtqueue_reset_vring_packed(struct virtqueue *_vq, u32 num)
+{
+	struct vring_virtqueue *vq = to_vvq(_vq);
+	struct virtio_device *vdev = _vq->vdev;
+	struct vring_packed vring;
+	int err;
+
+	if (num > _vq->num_max)
+		return -E2BIG;
+
+	switch (vq->vq.reset) {
+	case VIRTIO_VQ_RESET_STEP_NONE:
+		return -ENOENT;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
+	case VIRTIO_VQ_RESET_STEP_DEVICE:
+		if (vq->packed.vring.num == num || !num)
+			break;
+
+		vring_free(_vq);
+
+		fallthrough;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
+		if (!num)
+			num = vq->packed.vring.num;
+
+		err = vring_create_vring_packed(&vring, vdev, num);
+		if (err)
+			return -ENOMEM;
+
+		err = vring_virtqueue_attach_packed(vq, &vring, vdev);
+		if (err) {
+			vring_free_vring_packed(&vring, vdev);
+			return -ENOMEM;
+		}
+	}
+
+	vring_virtqueue_init_packed(vq, vdev);
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
+
+	return 0;
+}
+
 
 /*
  * Generic functions and exported symbols.
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 10/26] virtio_ring: packed: implement virtqueue_reset_vring_packed()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

virtio ring supports reset.

Queue reset is divided into several stages.

1. notify device queue reset
2. vring release
3. attach new vring
4. notify device queue re-enable

After the first step is completed, the vring reset operation can be
performed. If the newly set vring num does not change, then just reset
the vq related value.

Otherwise, the vring will be released and the vring will be reallocated.
And the vring will be attached to the vq. If this process fails, the
function will exit, and the state of the vq will be the vring release
state. You can call this function again to reallocate the vring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 46 ++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 148fb1fd3d5a..5afcbabcfb1e 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1886,6 +1886,8 @@ static int vring_virtqueue_attach_packed(struct vring_virtqueue *vq,
 static void vring_virtqueue_init_packed(struct vring_virtqueue *vq,
 					struct virtio_device *vdev)
 {
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
+
 	vq->we_own_ring = true;
 	vq->broken = false;
 	vq->last_used_idx = 0;
@@ -1969,6 +1971,50 @@ static struct virtqueue *vring_create_virtqueue_packed(
 	return NULL;
 }
 
+static int virtqueue_reset_vring_packed(struct virtqueue *_vq, u32 num)
+{
+	struct vring_virtqueue *vq = to_vvq(_vq);
+	struct virtio_device *vdev = _vq->vdev;
+	struct vring_packed vring;
+	int err;
+
+	if (num > _vq->num_max)
+		return -E2BIG;
+
+	switch (vq->vq.reset) {
+	case VIRTIO_VQ_RESET_STEP_NONE:
+		return -ENOENT;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
+	case VIRTIO_VQ_RESET_STEP_DEVICE:
+		if (vq->packed.vring.num == num || !num)
+			break;
+
+		vring_free(_vq);
+
+		fallthrough;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
+		if (!num)
+			num = vq->packed.vring.num;
+
+		err = vring_create_vring_packed(&vring, vdev, num);
+		if (err)
+			return -ENOMEM;
+
+		err = vring_virtqueue_attach_packed(vq, &vring, vdev);
+		if (err) {
+			vring_free_vring_packed(&vring, vdev);
+			return -ENOMEM;
+		}
+	}
+
+	vring_virtqueue_init_packed(vq, vdev);
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
+
+	return 0;
+}
+
 
 /*
  * Generic functions and exported symbols.
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 10/26] virtio_ring: packed: implement virtqueue_reset_vring_packed()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

virtio ring supports reset.

Queue reset is divided into several stages.

1. notify device queue reset
2. vring release
3. attach new vring
4. notify device queue re-enable

After the first step is completed, the vring reset operation can be
performed. If the newly set vring num does not change, then just reset
the vq related value.

Otherwise, the vring will be released and the vring will be reallocated.
And the vring will be attached to the vq. If this process fails, the
function will exit, and the state of the vq will be the vring release
state. You can call this function again to reallocate the vring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 46 ++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 148fb1fd3d5a..5afcbabcfb1e 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1886,6 +1886,8 @@ static int vring_virtqueue_attach_packed(struct vring_virtqueue *vq,
 static void vring_virtqueue_init_packed(struct vring_virtqueue *vq,
 					struct virtio_device *vdev)
 {
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
+
 	vq->we_own_ring = true;
 	vq->broken = false;
 	vq->last_used_idx = 0;
@@ -1969,6 +1971,50 @@ static struct virtqueue *vring_create_virtqueue_packed(
 	return NULL;
 }
 
+static int virtqueue_reset_vring_packed(struct virtqueue *_vq, u32 num)
+{
+	struct vring_virtqueue *vq = to_vvq(_vq);
+	struct virtio_device *vdev = _vq->vdev;
+	struct vring_packed vring;
+	int err;
+
+	if (num > _vq->num_max)
+		return -E2BIG;
+
+	switch (vq->vq.reset) {
+	case VIRTIO_VQ_RESET_STEP_NONE:
+		return -ENOENT;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
+	case VIRTIO_VQ_RESET_STEP_DEVICE:
+		if (vq->packed.vring.num == num || !num)
+			break;
+
+		vring_free(_vq);
+
+		fallthrough;
+
+	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
+		if (!num)
+			num = vq->packed.vring.num;
+
+		err = vring_create_vring_packed(&vring, vdev, num);
+		if (err)
+			return -ENOMEM;
+
+		err = vring_virtqueue_attach_packed(vq, &vring, vdev);
+		if (err) {
+			vring_free_vring_packed(&vring, vdev);
+			return -ENOMEM;
+		}
+	}
+
+	vring_virtqueue_init_packed(vq, vdev);
+	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
+
+	return 0;
+}
+
 
 /*
  * Generic functions and exported symbols.
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 11/26] virtio_ring: introduce virtqueue_reset_vring()
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Introduce virtqueue_reset_vring() to implement the reset of vring during
the reset process.

If num is equal to 0 or equal to the original ring num, the original vring
will be used directly. The vring will not be reallocated. Otherwise, the
original vring will be released, and the vring will be re-allocated
based on num.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 30 ++++++++++++++++++++++++++++++
 include/linux/virtio.h       |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 5afcbabcfb1e..bbff9ba53f80 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2534,6 +2534,36 @@ struct virtqueue *vring_create_virtqueue(
 }
 EXPORT_SYMBOL_GPL(vring_create_virtqueue);
 
+/**
+ * virtqueue_reset_vring - reset the vring of vq
+ * @vq: the struct virtqueue we're talking about.
+ * @num: new ring num
+ *
+ * If num is equal to 0 or equal to the original ring num, the original vring
+ * will be used directly. The vring will not be reallocated. Otherwise, the
+ * original vring will be released, and the vring will be re-allocated based on
+ * num.
+ *
+ * This function must be called after virtio_reset_vq(). For more information on
+ * vq reset see the description of virtio_reset_vq().
+ *
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error.
+ */
+int virtqueue_reset_vring(struct virtqueue *vq, u32 num)
+{
+	struct virtio_device *vdev = vq->vdev;
+
+	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
+		return virtqueue_reset_vring_packed(vq, num);
+
+	return virtqueue_reset_vring_split(vq, num);
+}
+EXPORT_SYMBOL_GPL(virtqueue_reset_vring);
+
 /* Only available for split ring */
 struct virtqueue *vring_new_virtqueue(unsigned int index,
 				      unsigned int num,
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index e3714e6db330..7bf29f9e7491 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -99,6 +99,8 @@ dma_addr_t virtqueue_get_desc_addr(struct virtqueue *vq);
 dma_addr_t virtqueue_get_avail_addr(struct virtqueue *vq);
 dma_addr_t virtqueue_get_used_addr(struct virtqueue *vq);
 
+int virtqueue_reset_vring(struct virtqueue *vq, u32 num);
+
 /**
  * virtio_device - representation of a device using virtio
  * @index: unique position on the virtio bus
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 11/26] virtio_ring: introduce virtqueue_reset_vring()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Introduce virtqueue_reset_vring() to implement the reset of vring during
the reset process.

If num is equal to 0 or equal to the original ring num, the original vring
will be used directly. The vring will not be reallocated. Otherwise, the
original vring will be released, and the vring will be re-allocated
based on num.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 30 ++++++++++++++++++++++++++++++
 include/linux/virtio.h       |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 5afcbabcfb1e..bbff9ba53f80 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2534,6 +2534,36 @@ struct virtqueue *vring_create_virtqueue(
 }
 EXPORT_SYMBOL_GPL(vring_create_virtqueue);
 
+/**
+ * virtqueue_reset_vring - reset the vring of vq
+ * @vq: the struct virtqueue we're talking about.
+ * @num: new ring num
+ *
+ * If num is equal to 0 or equal to the original ring num, the original vring
+ * will be used directly. The vring will not be reallocated. Otherwise, the
+ * original vring will be released, and the vring will be re-allocated based on
+ * num.
+ *
+ * This function must be called after virtio_reset_vq(). For more information on
+ * vq reset see the description of virtio_reset_vq().
+ *
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error.
+ */
+int virtqueue_reset_vring(struct virtqueue *vq, u32 num)
+{
+	struct virtio_device *vdev = vq->vdev;
+
+	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
+		return virtqueue_reset_vring_packed(vq, num);
+
+	return virtqueue_reset_vring_split(vq, num);
+}
+EXPORT_SYMBOL_GPL(virtqueue_reset_vring);
+
 /* Only available for split ring */
 struct virtqueue *vring_new_virtqueue(unsigned int index,
 				      unsigned int num,
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index e3714e6db330..7bf29f9e7491 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -99,6 +99,8 @@ dma_addr_t virtqueue_get_desc_addr(struct virtqueue *vq);
 dma_addr_t virtqueue_get_avail_addr(struct virtqueue *vq);
 dma_addr_t virtqueue_get_used_addr(struct virtqueue *vq);
 
+int virtqueue_reset_vring(struct virtqueue *vq, u32 num);
+
 /**
  * virtio_device - representation of a device using virtio
  * @index: unique position on the virtio bus
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 11/26] virtio_ring: introduce virtqueue_reset_vring()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Introduce virtqueue_reset_vring() to implement the reset of vring during
the reset process.

If num is equal to 0 or equal to the original ring num, the original vring
will be used directly. The vring will not be reallocated. Otherwise, the
original vring will be released, and the vring will be re-allocated
based on num.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 30 ++++++++++++++++++++++++++++++
 include/linux/virtio.h       |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 5afcbabcfb1e..bbff9ba53f80 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2534,6 +2534,36 @@ struct virtqueue *vring_create_virtqueue(
 }
 EXPORT_SYMBOL_GPL(vring_create_virtqueue);
 
+/**
+ * virtqueue_reset_vring - reset the vring of vq
+ * @vq: the struct virtqueue we're talking about.
+ * @num: new ring num
+ *
+ * If num is equal to 0 or equal to the original ring num, the original vring
+ * will be used directly. The vring will not be reallocated. Otherwise, the
+ * original vring will be released, and the vring will be re-allocated based on
+ * num.
+ *
+ * This function must be called after virtio_reset_vq(). For more information on
+ * vq reset see the description of virtio_reset_vq().
+ *
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error.
+ */
+int virtqueue_reset_vring(struct virtqueue *vq, u32 num)
+{
+	struct virtio_device *vdev = vq->vdev;
+
+	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
+		return virtqueue_reset_vring_packed(vq, num);
+
+	return virtqueue_reset_vring_split(vq, num);
+}
+EXPORT_SYMBOL_GPL(virtqueue_reset_vring);
+
 /* Only available for split ring */
 struct virtqueue *vring_new_virtqueue(unsigned int index,
 				      unsigned int num,
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index e3714e6db330..7bf29f9e7491 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -99,6 +99,8 @@ dma_addr_t virtqueue_get_desc_addr(struct virtqueue *vq);
 dma_addr_t virtqueue_get_avail_addr(struct virtqueue *vq);
 dma_addr_t virtqueue_get_used_addr(struct virtqueue *vq);
 
+int virtqueue_reset_vring(struct virtqueue *vq, u32 num);
+
 /**
  * virtio_device - representation of a device using virtio
  * @index: unique position on the virtio bus
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 12/26] virtio_ring: update the document of the virtqueue_detach_unused_buf for queue reset
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Added documentation for virtqueue_detach_unused_buf, allowing it to be
called on queue reset.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index bbff9ba53f80..f388be7562cd 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2357,8 +2357,8 @@ EXPORT_SYMBOL_GPL(virtqueue_enable_cb_delayed);
  * @_vq: the struct virtqueue we're talking about.
  *
  * Returns NULL or the "data" token handed to virtqueue_add_*().
- * This is not valid on an active queue; it is useful only for device
- * shutdown.
+ * This is not valid on an active queue; it is useful for device
+ * shutdown or the reset queue.
  */
 void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
 {
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 12/26] virtio_ring: update the document of the virtqueue_detach_unused_buf for queue reset
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Added documentation for virtqueue_detach_unused_buf, allowing it to be
called on queue reset.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index bbff9ba53f80..f388be7562cd 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2357,8 +2357,8 @@ EXPORT_SYMBOL_GPL(virtqueue_enable_cb_delayed);
  * @_vq: the struct virtqueue we're talking about.
  *
  * Returns NULL or the "data" token handed to virtqueue_add_*().
- * This is not valid on an active queue; it is useful only for device
- * shutdown.
+ * This is not valid on an active queue; it is useful for device
+ * shutdown or the reset queue.
  */
 void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
 {
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 12/26] virtio_ring: update the document of the virtqueue_detach_unused_buf for queue reset
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Added documentation for virtqueue_detach_unused_buf, allowing it to be
called on queue reset.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_ring.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index bbff9ba53f80..f388be7562cd 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2357,8 +2357,8 @@ EXPORT_SYMBOL_GPL(virtqueue_enable_cb_delayed);
  * @_vq: the struct virtqueue we're talking about.
  *
  * Returns NULL or the "data" token handed to virtqueue_add_*().
- * This is not valid on an active queue; it is useful only for device
- * shutdown.
+ * This is not valid on an active queue; it is useful for device
+ * shutdown or the reset queue.
  */
 void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
 {
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 13/26] virtio: queue_reset: struct virtio_config_ops add callbacks for queue_reset
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Performing reset on a queue is divided into four steps:

 1. reset_vq()                     - notify the device to reset the queue
 2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
 3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
 4. enable_reset_vq()              - mmap vring to device, and enable the queue

So add two callbacks reset_vq, enable_reset_vq to struct
virtio_config_ops.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/linux/virtio_config.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 4d107ad31149..d51906b1389f 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -74,6 +74,15 @@ struct virtio_shm_region {
  * @set_vq_affinity: set the affinity for a virtqueue (optional).
  * @get_vq_affinity: get the affinity for a virtqueue (optional).
  * @get_shm_region: get a shared memory region based on the index.
+ * @reset_vq: reset a queue individually (optional).
+ *	vq: the virtqueue
+ *	Returns 0 on success or error status
+ *	Caller should guarantee that the vring is not accessed by any functions
+ *	of virtqueue.
+ * @enable_reset_vq: enable a reset queue
+ *	vq: the virtqueue
+ *	Returns 0 on success or error status
+ *	If reset_vq is set, then enable_reset_vq must also be set.
  */
 typedef void vq_callback_t(struct virtqueue *);
 struct virtio_config_ops {
@@ -100,6 +109,8 @@ struct virtio_config_ops {
 			int index);
 	bool (*get_shm_region)(struct virtio_device *vdev,
 			       struct virtio_shm_region *region, u8 id);
+	int (*reset_vq)(struct virtqueue *vq);
+	int (*enable_reset_vq)(struct virtqueue *vq);
 };
 
 /* If driver didn't advertise the feature, it will never appear. */
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 13/26] virtio: queue_reset: struct virtio_config_ops add callbacks for queue_reset
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Performing reset on a queue is divided into four steps:

 1. reset_vq()                     - notify the device to reset the queue
 2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
 3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
 4. enable_reset_vq()              - mmap vring to device, and enable the queue

So add two callbacks reset_vq, enable_reset_vq to struct
virtio_config_ops.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/linux/virtio_config.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 4d107ad31149..d51906b1389f 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -74,6 +74,15 @@ struct virtio_shm_region {
  * @set_vq_affinity: set the affinity for a virtqueue (optional).
  * @get_vq_affinity: get the affinity for a virtqueue (optional).
  * @get_shm_region: get a shared memory region based on the index.
+ * @reset_vq: reset a queue individually (optional).
+ *	vq: the virtqueue
+ *	Returns 0 on success or error status
+ *	Caller should guarantee that the vring is not accessed by any functions
+ *	of virtqueue.
+ * @enable_reset_vq: enable a reset queue
+ *	vq: the virtqueue
+ *	Returns 0 on success or error status
+ *	If reset_vq is set, then enable_reset_vq must also be set.
  */
 typedef void vq_callback_t(struct virtqueue *);
 struct virtio_config_ops {
@@ -100,6 +109,8 @@ struct virtio_config_ops {
 			int index);
 	bool (*get_shm_region)(struct virtio_device *vdev,
 			       struct virtio_shm_region *region, u8 id);
+	int (*reset_vq)(struct virtqueue *vq);
+	int (*enable_reset_vq)(struct virtqueue *vq);
 };
 
 /* If driver didn't advertise the feature, it will never appear. */
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 13/26] virtio: queue_reset: struct virtio_config_ops add callbacks for queue_reset
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Performing reset on a queue is divided into four steps:

 1. reset_vq()                     - notify the device to reset the queue
 2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
 3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
 4. enable_reset_vq()              - mmap vring to device, and enable the queue

So add two callbacks reset_vq, enable_reset_vq to struct
virtio_config_ops.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/linux/virtio_config.h | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 4d107ad31149..d51906b1389f 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -74,6 +74,15 @@ struct virtio_shm_region {
  * @set_vq_affinity: set the affinity for a virtqueue (optional).
  * @get_vq_affinity: get the affinity for a virtqueue (optional).
  * @get_shm_region: get a shared memory region based on the index.
+ * @reset_vq: reset a queue individually (optional).
+ *	vq: the virtqueue
+ *	Returns 0 on success or error status
+ *	Caller should guarantee that the vring is not accessed by any functions
+ *	of virtqueue.
+ * @enable_reset_vq: enable a reset queue
+ *	vq: the virtqueue
+ *	Returns 0 on success or error status
+ *	If reset_vq is set, then enable_reset_vq must also be set.
  */
 typedef void vq_callback_t(struct virtqueue *);
 struct virtio_config_ops {
@@ -100,6 +109,8 @@ struct virtio_config_ops {
 			int index);
 	bool (*get_shm_region)(struct virtio_device *vdev,
 			       struct virtio_shm_region *region, u8 id);
+	int (*reset_vq)(struct virtqueue *vq);
+	int (*enable_reset_vq)(struct virtqueue *vq);
 };
 
 /* If driver didn't advertise the feature, it will never appear. */
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 14/26] virtio: add helper for queue reset
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Add helper for virtio queue reset.

* virtio_reset_vq(): reset a queue individually
* virtio_enable_resetq(): enable a reset queue

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/linux/virtio_config.h | 40 +++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index d51906b1389f..0b81fbe17c85 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -230,6 +230,46 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
 				      desc);
 }
 
+/**
+ * virtio_reset_vq - reset a queue individually
+ * @vq: the virtqueue
+ *
+ * returns 0 on success or error status
+ *
+ * The api process of reset under normal circumstances:
+ *	1. virtio_reset_vq()              - notify the device to reset the queue
+ *	2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
+ *	3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
+ *	4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
+ *
+ * Caller should guarantee that the vring is not accessed by any functions
+ * of virtqueue.
+ */
+static inline
+int virtio_reset_vq(struct virtqueue *vq)
+{
+	if (!vq->vdev->config->reset_vq)
+		return -ENOENT;
+
+	return vq->vdev->config->reset_vq(vq);
+}
+
+/**
+ * virtio_enable_resetq - enable a reset queue
+ * @vq: the virtqueue
+ *
+ * returns 0 on success or error status
+ *
+ */
+static inline
+int virtio_enable_resetq(struct virtqueue *vq)
+{
+	if (!vq->vdev->config->enable_reset_vq)
+		return -ENOENT;
+
+	return vq->vdev->config->enable_reset_vq(vq);
+}
+
 /**
  * virtio_device_ready - enable vq use in probe function
  * @vdev: the device
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 14/26] virtio: add helper for queue reset
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Add helper for virtio queue reset.

* virtio_reset_vq(): reset a queue individually
* virtio_enable_resetq(): enable a reset queue

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/linux/virtio_config.h | 40 +++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index d51906b1389f..0b81fbe17c85 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -230,6 +230,46 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
 				      desc);
 }
 
+/**
+ * virtio_reset_vq - reset a queue individually
+ * @vq: the virtqueue
+ *
+ * returns 0 on success or error status
+ *
+ * The api process of reset under normal circumstances:
+ *	1. virtio_reset_vq()              - notify the device to reset the queue
+ *	2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
+ *	3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
+ *	4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
+ *
+ * Caller should guarantee that the vring is not accessed by any functions
+ * of virtqueue.
+ */
+static inline
+int virtio_reset_vq(struct virtqueue *vq)
+{
+	if (!vq->vdev->config->reset_vq)
+		return -ENOENT;
+
+	return vq->vdev->config->reset_vq(vq);
+}
+
+/**
+ * virtio_enable_resetq - enable a reset queue
+ * @vq: the virtqueue
+ *
+ * returns 0 on success or error status
+ *
+ */
+static inline
+int virtio_enable_resetq(struct virtqueue *vq)
+{
+	if (!vq->vdev->config->enable_reset_vq)
+		return -ENOENT;
+
+	return vq->vdev->config->enable_reset_vq(vq);
+}
+
 /**
  * virtio_device_ready - enable vq use in probe function
  * @vdev: the device
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 14/26] virtio: add helper for queue reset
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Add helper for virtio queue reset.

* virtio_reset_vq(): reset a queue individually
* virtio_enable_resetq(): enable a reset queue

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/linux/virtio_config.h | 40 +++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index d51906b1389f..0b81fbe17c85 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -230,6 +230,46 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
 				      desc);
 }
 
+/**
+ * virtio_reset_vq - reset a queue individually
+ * @vq: the virtqueue
+ *
+ * returns 0 on success or error status
+ *
+ * The api process of reset under normal circumstances:
+ *	1. virtio_reset_vq()              - notify the device to reset the queue
+ *	2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
+ *	3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
+ *	4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
+ *
+ * Caller should guarantee that the vring is not accessed by any functions
+ * of virtqueue.
+ */
+static inline
+int virtio_reset_vq(struct virtqueue *vq)
+{
+	if (!vq->vdev->config->reset_vq)
+		return -ENOENT;
+
+	return vq->vdev->config->reset_vq(vq);
+}
+
+/**
+ * virtio_enable_resetq - enable a reset queue
+ * @vq: the virtqueue
+ *
+ * returns 0 on success or error status
+ *
+ */
+static inline
+int virtio_enable_resetq(struct virtqueue *vq)
+{
+	if (!vq->vdev->config->enable_reset_vq)
+		return -ENOENT;
+
+	return vq->vdev->config->enable_reset_vq(vq);
+}
+
 /**
  * virtio_device_ready - enable vq use in probe function
  * @vdev: the device
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 15/26] virtio_pci: queue_reset: update struct virtio_pci_common_cfg and option functions
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Add queue_reset in virtio_pci_common_cfg, and add related operation
functions.

For not breaks uABI, add a new struct virtio_pci_common_cfg_reset.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_modern_dev.c | 36 ++++++++++++++++++++++++++
 include/linux/virtio_pci_modern.h      |  2 ++
 include/uapi/linux/virtio_pci.h        |  7 +++++
 3 files changed, 45 insertions(+)

diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c
index e8b3ff2b9fbc..8c74b00bc511 100644
--- a/drivers/virtio/virtio_pci_modern_dev.c
+++ b/drivers/virtio/virtio_pci_modern_dev.c
@@ -3,6 +3,7 @@
 #include <linux/virtio_pci_modern.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 
 /*
  * vp_modern_map_capability - map a part of virtio pci capability
@@ -463,6 +464,41 @@ void vp_modern_set_status(struct virtio_pci_modern_device *mdev,
 }
 EXPORT_SYMBOL_GPL(vp_modern_set_status);
 
+/*
+ * vp_modern_get_queue_reset - get the queue reset status
+ * @mdev: the modern virtio-pci device
+ * @index: queue index
+ */
+int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index)
+{
+	struct virtio_pci_common_cfg_reset __iomem *cfg;
+
+	cfg = (struct virtio_pci_common_cfg_reset __iomem *)mdev->common;
+
+	vp_iowrite16(index, &cfg->cfg.queue_select);
+	return vp_ioread16(&cfg->queue_reset);
+}
+EXPORT_SYMBOL_GPL(vp_modern_get_queue_reset);
+
+/*
+ * vp_modern_set_queue_reset - reset the queue
+ * @mdev: the modern virtio-pci device
+ * @index: queue index
+ */
+void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index)
+{
+	struct virtio_pci_common_cfg_reset __iomem *cfg;
+
+	cfg = (struct virtio_pci_common_cfg_reset __iomem *)mdev->common;
+
+	vp_iowrite16(index, &cfg->cfg.queue_select);
+	vp_iowrite16(1, &cfg->queue_reset);
+
+	while (vp_ioread16(&cfg->queue_reset) != 1)
+		msleep(1);
+}
+EXPORT_SYMBOL_GPL(vp_modern_set_queue_reset);
+
 /*
  * vp_modern_queue_vector - set the MSIX vector for a specific virtqueue
  * @mdev: the modern virtio-pci device
diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h
index eb2bd9b4077d..cc4154dd7b28 100644
--- a/include/linux/virtio_pci_modern.h
+++ b/include/linux/virtio_pci_modern.h
@@ -106,4 +106,6 @@ void __iomem * vp_modern_map_vq_notify(struct virtio_pci_modern_device *mdev,
 				       u16 index, resource_size_t *pa);
 int vp_modern_probe(struct virtio_pci_modern_device *mdev);
 void vp_modern_remove(struct virtio_pci_modern_device *mdev);
+int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index);
+void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index);
 #endif
diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
index 22bec9bd0dfc..d9462efd6ce8 100644
--- a/include/uapi/linux/virtio_pci.h
+++ b/include/uapi/linux/virtio_pci.h
@@ -173,6 +173,13 @@ struct virtio_pci_common_cfg_notify {
 	__le16 padding;
 };
 
+struct virtio_pci_common_cfg_reset {
+	struct virtio_pci_common_cfg cfg;
+
+	__le16 queue_notify_data;	/* read-write */
+	__le16 queue_reset;		/* read-write */
+};
+
 /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
 struct virtio_pci_cfg_cap {
 	struct virtio_pci_cap cap;
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 15/26] virtio_pci: queue_reset: update struct virtio_pci_common_cfg and option functions
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Add queue_reset in virtio_pci_common_cfg, and add related operation
functions.

For not breaks uABI, add a new struct virtio_pci_common_cfg_reset.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_modern_dev.c | 36 ++++++++++++++++++++++++++
 include/linux/virtio_pci_modern.h      |  2 ++
 include/uapi/linux/virtio_pci.h        |  7 +++++
 3 files changed, 45 insertions(+)

diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c
index e8b3ff2b9fbc..8c74b00bc511 100644
--- a/drivers/virtio/virtio_pci_modern_dev.c
+++ b/drivers/virtio/virtio_pci_modern_dev.c
@@ -3,6 +3,7 @@
 #include <linux/virtio_pci_modern.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 
 /*
  * vp_modern_map_capability - map a part of virtio pci capability
@@ -463,6 +464,41 @@ void vp_modern_set_status(struct virtio_pci_modern_device *mdev,
 }
 EXPORT_SYMBOL_GPL(vp_modern_set_status);
 
+/*
+ * vp_modern_get_queue_reset - get the queue reset status
+ * @mdev: the modern virtio-pci device
+ * @index: queue index
+ */
+int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index)
+{
+	struct virtio_pci_common_cfg_reset __iomem *cfg;
+
+	cfg = (struct virtio_pci_common_cfg_reset __iomem *)mdev->common;
+
+	vp_iowrite16(index, &cfg->cfg.queue_select);
+	return vp_ioread16(&cfg->queue_reset);
+}
+EXPORT_SYMBOL_GPL(vp_modern_get_queue_reset);
+
+/*
+ * vp_modern_set_queue_reset - reset the queue
+ * @mdev: the modern virtio-pci device
+ * @index: queue index
+ */
+void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index)
+{
+	struct virtio_pci_common_cfg_reset __iomem *cfg;
+
+	cfg = (struct virtio_pci_common_cfg_reset __iomem *)mdev->common;
+
+	vp_iowrite16(index, &cfg->cfg.queue_select);
+	vp_iowrite16(1, &cfg->queue_reset);
+
+	while (vp_ioread16(&cfg->queue_reset) != 1)
+		msleep(1);
+}
+EXPORT_SYMBOL_GPL(vp_modern_set_queue_reset);
+
 /*
  * vp_modern_queue_vector - set the MSIX vector for a specific virtqueue
  * @mdev: the modern virtio-pci device
diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h
index eb2bd9b4077d..cc4154dd7b28 100644
--- a/include/linux/virtio_pci_modern.h
+++ b/include/linux/virtio_pci_modern.h
@@ -106,4 +106,6 @@ void __iomem * vp_modern_map_vq_notify(struct virtio_pci_modern_device *mdev,
 				       u16 index, resource_size_t *pa);
 int vp_modern_probe(struct virtio_pci_modern_device *mdev);
 void vp_modern_remove(struct virtio_pci_modern_device *mdev);
+int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index);
+void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index);
 #endif
diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
index 22bec9bd0dfc..d9462efd6ce8 100644
--- a/include/uapi/linux/virtio_pci.h
+++ b/include/uapi/linux/virtio_pci.h
@@ -173,6 +173,13 @@ struct virtio_pci_common_cfg_notify {
 	__le16 padding;
 };
 
+struct virtio_pci_common_cfg_reset {
+	struct virtio_pci_common_cfg cfg;
+
+	__le16 queue_notify_data;	/* read-write */
+	__le16 queue_reset;		/* read-write */
+};
+
 /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
 struct virtio_pci_cfg_cap {
 	struct virtio_pci_cap cap;
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 15/26] virtio_pci: queue_reset: update struct virtio_pci_common_cfg and option functions
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Add queue_reset in virtio_pci_common_cfg, and add related operation
functions.

For not breaks uABI, add a new struct virtio_pci_common_cfg_reset.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_modern_dev.c | 36 ++++++++++++++++++++++++++
 include/linux/virtio_pci_modern.h      |  2 ++
 include/uapi/linux/virtio_pci.h        |  7 +++++
 3 files changed, 45 insertions(+)

diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c
index e8b3ff2b9fbc..8c74b00bc511 100644
--- a/drivers/virtio/virtio_pci_modern_dev.c
+++ b/drivers/virtio/virtio_pci_modern_dev.c
@@ -3,6 +3,7 @@
 #include <linux/virtio_pci_modern.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/delay.h>
 
 /*
  * vp_modern_map_capability - map a part of virtio pci capability
@@ -463,6 +464,41 @@ void vp_modern_set_status(struct virtio_pci_modern_device *mdev,
 }
 EXPORT_SYMBOL_GPL(vp_modern_set_status);
 
+/*
+ * vp_modern_get_queue_reset - get the queue reset status
+ * @mdev: the modern virtio-pci device
+ * @index: queue index
+ */
+int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index)
+{
+	struct virtio_pci_common_cfg_reset __iomem *cfg;
+
+	cfg = (struct virtio_pci_common_cfg_reset __iomem *)mdev->common;
+
+	vp_iowrite16(index, &cfg->cfg.queue_select);
+	return vp_ioread16(&cfg->queue_reset);
+}
+EXPORT_SYMBOL_GPL(vp_modern_get_queue_reset);
+
+/*
+ * vp_modern_set_queue_reset - reset the queue
+ * @mdev: the modern virtio-pci device
+ * @index: queue index
+ */
+void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index)
+{
+	struct virtio_pci_common_cfg_reset __iomem *cfg;
+
+	cfg = (struct virtio_pci_common_cfg_reset __iomem *)mdev->common;
+
+	vp_iowrite16(index, &cfg->cfg.queue_select);
+	vp_iowrite16(1, &cfg->queue_reset);
+
+	while (vp_ioread16(&cfg->queue_reset) != 1)
+		msleep(1);
+}
+EXPORT_SYMBOL_GPL(vp_modern_set_queue_reset);
+
 /*
  * vp_modern_queue_vector - set the MSIX vector for a specific virtqueue
  * @mdev: the modern virtio-pci device
diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h
index eb2bd9b4077d..cc4154dd7b28 100644
--- a/include/linux/virtio_pci_modern.h
+++ b/include/linux/virtio_pci_modern.h
@@ -106,4 +106,6 @@ void __iomem * vp_modern_map_vq_notify(struct virtio_pci_modern_device *mdev,
 				       u16 index, resource_size_t *pa);
 int vp_modern_probe(struct virtio_pci_modern_device *mdev);
 void vp_modern_remove(struct virtio_pci_modern_device *mdev);
+int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index);
+void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index);
 #endif
diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
index 22bec9bd0dfc..d9462efd6ce8 100644
--- a/include/uapi/linux/virtio_pci.h
+++ b/include/uapi/linux/virtio_pci.h
@@ -173,6 +173,13 @@ struct virtio_pci_common_cfg_notify {
 	__le16 padding;
 };
 
+struct virtio_pci_common_cfg_reset {
+	struct virtio_pci_common_cfg cfg;
+
+	__le16 queue_notify_data;	/* read-write */
+	__le16 queue_reset;		/* read-write */
+};
+
 /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
 struct virtio_pci_cfg_cap {
 	struct virtio_pci_cap cap;
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 16/26] virtio_pci: queue_reset: extract the logic of active vq for modern pci
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Introduce vp_active_vq() to configure vring to backend after vq attach
vring. And configure vq vector if necessary.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_modern.c | 46 ++++++++++++++++++------------
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 86d301f272b8..49a4493732cf 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -176,6 +176,29 @@ static void vp_reset(struct virtio_device *vdev)
 	vp_disable_cbs(vdev);
 }
 
+static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
+{
+	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+	unsigned long index;
+
+	index = vq->index;
+
+	/* activate the queue */
+	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
+	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
+				virtqueue_get_avail_addr(vq),
+				virtqueue_get_used_addr(vq));
+
+	if (msix_vec != VIRTIO_MSI_NO_VECTOR) {
+		msix_vec = vp_modern_queue_vector(mdev, index, msix_vec);
+		if (msix_vec == VIRTIO_MSI_NO_VECTOR)
+			return -EBUSY;
+	}
+
+	return 0;
+}
+
 static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
 {
 	return vp_modern_config_vector(&vp_dev->mdev, vector);
@@ -220,32 +243,19 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 
 	vq->num_max = num;
 
-	/* activate the queue */
-	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
-	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
-				virtqueue_get_avail_addr(vq),
-				virtqueue_get_used_addr(vq));
+	err = vp_active_vq(vq, msix_vec);
+	if (err)
+		goto err;
 
 	vq->priv = (void __force *)vp_modern_map_vq_notify(mdev, index, NULL);
 	if (!vq->priv) {
 		err = -ENOMEM;
-		goto err_map_notify;
-	}
-
-	if (msix_vec != VIRTIO_MSI_NO_VECTOR) {
-		msix_vec = vp_modern_queue_vector(mdev, index, msix_vec);
-		if (msix_vec == VIRTIO_MSI_NO_VECTOR) {
-			err = -EBUSY;
-			goto err_assign_vector;
-		}
+		goto err;
 	}
 
 	return vq;
 
-err_assign_vector:
-	if (!mdev->notify_base)
-		pci_iounmap(mdev->pci_dev, (void __iomem __force *)vq->priv);
-err_map_notify:
+err:
 	vring_del_virtqueue(vq);
 	return ERR_PTR(err);
 }
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 16/26] virtio_pci: queue_reset: extract the logic of active vq for modern pci
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Introduce vp_active_vq() to configure vring to backend after vq attach
vring. And configure vq vector if necessary.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_modern.c | 46 ++++++++++++++++++------------
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 86d301f272b8..49a4493732cf 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -176,6 +176,29 @@ static void vp_reset(struct virtio_device *vdev)
 	vp_disable_cbs(vdev);
 }
 
+static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
+{
+	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+	unsigned long index;
+
+	index = vq->index;
+
+	/* activate the queue */
+	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
+	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
+				virtqueue_get_avail_addr(vq),
+				virtqueue_get_used_addr(vq));
+
+	if (msix_vec != VIRTIO_MSI_NO_VECTOR) {
+		msix_vec = vp_modern_queue_vector(mdev, index, msix_vec);
+		if (msix_vec == VIRTIO_MSI_NO_VECTOR)
+			return -EBUSY;
+	}
+
+	return 0;
+}
+
 static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
 {
 	return vp_modern_config_vector(&vp_dev->mdev, vector);
@@ -220,32 +243,19 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 
 	vq->num_max = num;
 
-	/* activate the queue */
-	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
-	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
-				virtqueue_get_avail_addr(vq),
-				virtqueue_get_used_addr(vq));
+	err = vp_active_vq(vq, msix_vec);
+	if (err)
+		goto err;
 
 	vq->priv = (void __force *)vp_modern_map_vq_notify(mdev, index, NULL);
 	if (!vq->priv) {
 		err = -ENOMEM;
-		goto err_map_notify;
-	}
-
-	if (msix_vec != VIRTIO_MSI_NO_VECTOR) {
-		msix_vec = vp_modern_queue_vector(mdev, index, msix_vec);
-		if (msix_vec == VIRTIO_MSI_NO_VECTOR) {
-			err = -EBUSY;
-			goto err_assign_vector;
-		}
+		goto err;
 	}
 
 	return vq;
 
-err_assign_vector:
-	if (!mdev->notify_base)
-		pci_iounmap(mdev->pci_dev, (void __iomem __force *)vq->priv);
-err_map_notify:
+err:
 	vring_del_virtqueue(vq);
 	return ERR_PTR(err);
 }
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 16/26] virtio_pci: queue_reset: extract the logic of active vq for modern pci
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Introduce vp_active_vq() to configure vring to backend after vq attach
vring. And configure vq vector if necessary.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_modern.c | 46 ++++++++++++++++++------------
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 86d301f272b8..49a4493732cf 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -176,6 +176,29 @@ static void vp_reset(struct virtio_device *vdev)
 	vp_disable_cbs(vdev);
 }
 
+static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
+{
+	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+	unsigned long index;
+
+	index = vq->index;
+
+	/* activate the queue */
+	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
+	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
+				virtqueue_get_avail_addr(vq),
+				virtqueue_get_used_addr(vq));
+
+	if (msix_vec != VIRTIO_MSI_NO_VECTOR) {
+		msix_vec = vp_modern_queue_vector(mdev, index, msix_vec);
+		if (msix_vec == VIRTIO_MSI_NO_VECTOR)
+			return -EBUSY;
+	}
+
+	return 0;
+}
+
 static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
 {
 	return vp_modern_config_vector(&vp_dev->mdev, vector);
@@ -220,32 +243,19 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 
 	vq->num_max = num;
 
-	/* activate the queue */
-	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
-	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
-				virtqueue_get_avail_addr(vq),
-				virtqueue_get_used_addr(vq));
+	err = vp_active_vq(vq, msix_vec);
+	if (err)
+		goto err;
 
 	vq->priv = (void __force *)vp_modern_map_vq_notify(mdev, index, NULL);
 	if (!vq->priv) {
 		err = -ENOMEM;
-		goto err_map_notify;
-	}
-
-	if (msix_vec != VIRTIO_MSI_NO_VECTOR) {
-		msix_vec = vp_modern_queue_vector(mdev, index, msix_vec);
-		if (msix_vec == VIRTIO_MSI_NO_VECTOR) {
-			err = -EBUSY;
-			goto err_assign_vector;
-		}
+		goto err;
 	}
 
 	return vq;
 
-err_assign_vector:
-	if (!mdev->notify_base)
-		pci_iounmap(mdev->pci_dev, (void __iomem __force *)vq->priv);
-err_map_notify:
+err:
 	vring_del_virtqueue(vq);
 	return ERR_PTR(err);
 }
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

This patch implements virtio pci support for QUEUE RESET.

Performing reset on a queue is divided into these steps:

 1. virtio_reset_vq()              - notify the device to reset the queue
 2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
 3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
 4. virtio_enable_resetq()         - mmap vring to device, and enable the queue

This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
pci scenario.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_common.c |  8 +--
 drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index fdbde1db5ec5..863d3a8a0956 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
 	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
 	unsigned long flags;
 
-	spin_lock_irqsave(&vp_dev->lock, flags);
-	list_del(&info->node);
-	spin_unlock_irqrestore(&vp_dev->lock, flags);
+	if (!vq->reset) {
+		spin_lock_irqsave(&vp_dev->lock, flags);
+		list_del(&info->node);
+		spin_unlock_irqrestore(&vp_dev->lock, flags);
+	}
 
 	vp_dev->del_vq(info);
 	kfree(info);
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 49a4493732cf..3c67d3607802 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
 	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
 			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
 		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
+
+	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
+		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
 }
 
 /* virtio config->finalize_features() implementation */
@@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
 	return 0;
 }
 
+static int vp_modern_reset_vq(struct virtqueue *vq)
+{
+	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+	struct virtio_pci_vq_info *info;
+	unsigned long flags;
+	unsigned int irq;
+
+	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
+		return -ENOENT;
+
+	vp_modern_set_queue_reset(mdev, vq->index);
+
+	info = vp_dev->vqs[vq->index];
+
+	/* delete vq from irq handler */
+	spin_lock_irqsave(&vp_dev->lock, flags);
+	list_del(&info->node);
+	spin_unlock_irqrestore(&vp_dev->lock, flags);
+
+	INIT_LIST_HEAD(&info->node);
+
+	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
+
+	/* sync irq callback. */
+	if (vp_dev->intx_enabled) {
+		irq = vp_dev->pci_dev->irq;
+
+	} else {
+		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
+			return 0;
+
+		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
+	}
+
+	synchronize_irq(irq);
+
+	return 0;
+}
+
+static int vp_modern_enable_reset_vq(struct virtqueue *vq)
+{
+	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+	struct virtio_pci_vq_info *info;
+	unsigned long flags, index;
+	int err;
+
+	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
+		return -EBUSY;
+
+	index = vq->index;
+	info = vp_dev->vqs[index];
+
+	/* check queue reset status */
+	if (vp_modern_get_queue_reset(mdev, index) != 1)
+		return -EBUSY;
+
+	err = vp_active_vq(vq, info->msix_vector);
+	if (err)
+		return err;
+
+	if (vq->callback) {
+		spin_lock_irqsave(&vp_dev->lock, flags);
+		list_add(&info->node, &vp_dev->virtqueues);
+		spin_unlock_irqrestore(&vp_dev->lock, flags);
+	} else {
+		INIT_LIST_HEAD(&info->node);
+	}
+
+	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
+	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
+
+	return 0;
+}
+
 static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
 {
 	return vp_modern_config_vector(&vp_dev->mdev, vector);
@@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
 	.set_vq_affinity = vp_set_vq_affinity,
 	.get_vq_affinity = vp_get_vq_affinity,
 	.get_shm_region  = vp_get_shm_region,
+	.reset_vq	 = vp_modern_reset_vq,
+	.enable_reset_vq = vp_modern_enable_reset_vq,
 };
 
 static const struct virtio_config_ops virtio_pci_config_ops = {
@@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
 	.set_vq_affinity = vp_set_vq_affinity,
 	.get_vq_affinity = vp_get_vq_affinity,
 	.get_shm_region  = vp_get_shm_region,
+	.reset_vq	 = vp_modern_reset_vq,
+	.enable_reset_vq = vp_modern_enable_reset_vq,
 };
 
 /* the PCI probing function */
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

This patch implements virtio pci support for QUEUE RESET.

Performing reset on a queue is divided into these steps:

 1. virtio_reset_vq()              - notify the device to reset the queue
 2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
 3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
 4. virtio_enable_resetq()         - mmap vring to device, and enable the queue

This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
pci scenario.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_common.c |  8 +--
 drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index fdbde1db5ec5..863d3a8a0956 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
 	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
 	unsigned long flags;
 
-	spin_lock_irqsave(&vp_dev->lock, flags);
-	list_del(&info->node);
-	spin_unlock_irqrestore(&vp_dev->lock, flags);
+	if (!vq->reset) {
+		spin_lock_irqsave(&vp_dev->lock, flags);
+		list_del(&info->node);
+		spin_unlock_irqrestore(&vp_dev->lock, flags);
+	}
 
 	vp_dev->del_vq(info);
 	kfree(info);
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 49a4493732cf..3c67d3607802 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
 	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
 			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
 		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
+
+	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
+		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
 }
 
 /* virtio config->finalize_features() implementation */
@@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
 	return 0;
 }
 
+static int vp_modern_reset_vq(struct virtqueue *vq)
+{
+	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+	struct virtio_pci_vq_info *info;
+	unsigned long flags;
+	unsigned int irq;
+
+	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
+		return -ENOENT;
+
+	vp_modern_set_queue_reset(mdev, vq->index);
+
+	info = vp_dev->vqs[vq->index];
+
+	/* delete vq from irq handler */
+	spin_lock_irqsave(&vp_dev->lock, flags);
+	list_del(&info->node);
+	spin_unlock_irqrestore(&vp_dev->lock, flags);
+
+	INIT_LIST_HEAD(&info->node);
+
+	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
+
+	/* sync irq callback. */
+	if (vp_dev->intx_enabled) {
+		irq = vp_dev->pci_dev->irq;
+
+	} else {
+		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
+			return 0;
+
+		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
+	}
+
+	synchronize_irq(irq);
+
+	return 0;
+}
+
+static int vp_modern_enable_reset_vq(struct virtqueue *vq)
+{
+	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+	struct virtio_pci_vq_info *info;
+	unsigned long flags, index;
+	int err;
+
+	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
+		return -EBUSY;
+
+	index = vq->index;
+	info = vp_dev->vqs[index];
+
+	/* check queue reset status */
+	if (vp_modern_get_queue_reset(mdev, index) != 1)
+		return -EBUSY;
+
+	err = vp_active_vq(vq, info->msix_vector);
+	if (err)
+		return err;
+
+	if (vq->callback) {
+		spin_lock_irqsave(&vp_dev->lock, flags);
+		list_add(&info->node, &vp_dev->virtqueues);
+		spin_unlock_irqrestore(&vp_dev->lock, flags);
+	} else {
+		INIT_LIST_HEAD(&info->node);
+	}
+
+	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
+	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
+
+	return 0;
+}
+
 static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
 {
 	return vp_modern_config_vector(&vp_dev->mdev, vector);
@@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
 	.set_vq_affinity = vp_set_vq_affinity,
 	.get_vq_affinity = vp_get_vq_affinity,
 	.get_shm_region  = vp_get_shm_region,
+	.reset_vq	 = vp_modern_reset_vq,
+	.enable_reset_vq = vp_modern_enable_reset_vq,
 };
 
 static const struct virtio_config_ops virtio_pci_config_ops = {
@@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
 	.set_vq_affinity = vp_set_vq_affinity,
 	.get_vq_affinity = vp_get_vq_affinity,
 	.get_shm_region  = vp_get_shm_region,
+	.reset_vq	 = vp_modern_reset_vq,
+	.enable_reset_vq = vp_modern_enable_reset_vq,
 };
 
 /* the PCI probing function */
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

This patch implements virtio pci support for QUEUE RESET.

Performing reset on a queue is divided into these steps:

 1. virtio_reset_vq()              - notify the device to reset the queue
 2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
 3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
 4. virtio_enable_resetq()         - mmap vring to device, and enable the queue

This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
pci scenario.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_common.c |  8 +--
 drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index fdbde1db5ec5..863d3a8a0956 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
 	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
 	unsigned long flags;
 
-	spin_lock_irqsave(&vp_dev->lock, flags);
-	list_del(&info->node);
-	spin_unlock_irqrestore(&vp_dev->lock, flags);
+	if (!vq->reset) {
+		spin_lock_irqsave(&vp_dev->lock, flags);
+		list_del(&info->node);
+		spin_unlock_irqrestore(&vp_dev->lock, flags);
+	}
 
 	vp_dev->del_vq(info);
 	kfree(info);
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 49a4493732cf..3c67d3607802 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
 	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
 			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
 		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
+
+	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
+		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
 }
 
 /* virtio config->finalize_features() implementation */
@@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
 	return 0;
 }
 
+static int vp_modern_reset_vq(struct virtqueue *vq)
+{
+	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+	struct virtio_pci_vq_info *info;
+	unsigned long flags;
+	unsigned int irq;
+
+	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
+		return -ENOENT;
+
+	vp_modern_set_queue_reset(mdev, vq->index);
+
+	info = vp_dev->vqs[vq->index];
+
+	/* delete vq from irq handler */
+	spin_lock_irqsave(&vp_dev->lock, flags);
+	list_del(&info->node);
+	spin_unlock_irqrestore(&vp_dev->lock, flags);
+
+	INIT_LIST_HEAD(&info->node);
+
+	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
+
+	/* sync irq callback. */
+	if (vp_dev->intx_enabled) {
+		irq = vp_dev->pci_dev->irq;
+
+	} else {
+		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
+			return 0;
+
+		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
+	}
+
+	synchronize_irq(irq);
+
+	return 0;
+}
+
+static int vp_modern_enable_reset_vq(struct virtqueue *vq)
+{
+	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+	struct virtio_pci_vq_info *info;
+	unsigned long flags, index;
+	int err;
+
+	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
+		return -EBUSY;
+
+	index = vq->index;
+	info = vp_dev->vqs[index];
+
+	/* check queue reset status */
+	if (vp_modern_get_queue_reset(mdev, index) != 1)
+		return -EBUSY;
+
+	err = vp_active_vq(vq, info->msix_vector);
+	if (err)
+		return err;
+
+	if (vq->callback) {
+		spin_lock_irqsave(&vp_dev->lock, flags);
+		list_add(&info->node, &vp_dev->virtqueues);
+		spin_unlock_irqrestore(&vp_dev->lock, flags);
+	} else {
+		INIT_LIST_HEAD(&info->node);
+	}
+
+	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
+	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
+
+	return 0;
+}
+
 static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
 {
 	return vp_modern_config_vector(&vp_dev->mdev, vector);
@@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
 	.set_vq_affinity = vp_set_vq_affinity,
 	.get_vq_affinity = vp_get_vq_affinity,
 	.get_shm_region  = vp_get_shm_region,
+	.reset_vq	 = vp_modern_reset_vq,
+	.enable_reset_vq = vp_modern_enable_reset_vq,
 };
 
 static const struct virtio_config_ops virtio_pci_config_ops = {
@@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
 	.set_vq_affinity = vp_set_vq_affinity,
 	.get_vq_affinity = vp_get_vq_affinity,
 	.get_shm_region  = vp_get_shm_region,
+	.reset_vq	 = vp_modern_reset_vq,
+	.enable_reset_vq = vp_modern_enable_reset_vq,
 };
 
 /* the PCI probing function */
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 18/26] virtio: find_vqs() add arg sizes
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

find_vqs() adds a new parameter sizes to specify the size of each vq
vring.

0 means use the maximum size supported by the backend.

In the split scenario, the meaning of size is the largest size, because
it may be limited by memory, the virtio core will try a smaller size.
And the size is power of 2.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 arch/um/drivers/virtio_uml.c             |  2 +-
 drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
 drivers/remoteproc/remoteproc_virtio.c   |  2 +-
 drivers/s390/virtio/virtio_ccw.c         |  2 +-
 drivers/virtio/virtio_mmio.c             |  2 +-
 drivers/virtio/virtio_pci_common.c       |  2 +-
 drivers/virtio/virtio_pci_common.h       |  2 +-
 drivers/virtio/virtio_pci_modern.c       |  5 +++--
 drivers/virtio/virtio_vdpa.c             |  2 +-
 include/linux/virtio_config.h            | 11 +++++++----
 10 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
index ba562d68dc04..055b91ccbe8a 100644
--- a/arch/um/drivers/virtio_uml.c
+++ b/arch/um/drivers/virtio_uml.c
@@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
 static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
 		       const char * const names[], const bool *ctx,
-		       struct irq_affinity *desc)
+		       struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
 	int i, queue_idx = 0, rc;
diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
index 38800e86ed8a..aea7aa218b22 100644
--- a/drivers/platform/mellanox/mlxbf-tmfifo.c
+++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
@@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
 					vq_callback_t *callbacks[],
 					const char * const names[],
 					const bool *ctx,
-					struct irq_affinity *desc)
+					struct irq_affinity *desc,
+					u32 sizes[])
 {
 	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
 	struct mlxbf_tmfifo_vring *vring;
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index 70ab496d0431..3a167bec5b09 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
 				 vq_callback_t *callbacks[],
 				 const char * const names[],
 				 const bool * ctx,
-				 struct irq_affinity *desc)
+				 struct irq_affinity *desc, u32 sizes[])
 {
 	int i, ret, queue_idx = 0;
 
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index d35e7a3f7067..b74e08c71534 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 			       vq_callback_t *callbacks[],
 			       const char * const names[],
 			       const bool *ctx,
-			       struct irq_affinity *desc)
+			       struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
 	unsigned long *indicatorp = NULL;
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index a41abc8051b9..55d575f6ef2d 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		       vq_callback_t *callbacks[],
 		       const char * const names[],
 		       const bool *ctx,
-		       struct irq_affinity *desc)
+		       struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
 	int irq = platform_get_irq(vm_dev->pdev, 0);
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 863d3a8a0956..8e8fa7e5ad80 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
 		const char * const names[], const bool *ctx,
-		struct irq_affinity *desc)
+		struct irq_affinity *desc, u32 sizes[])
 {
 	int err;
 
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
index 23f6c5c678d5..9dbf1d555dff 100644
--- a/drivers/virtio/virtio_pci_common.h
+++ b/drivers/virtio/virtio_pci_common.h
@@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
 		const char * const names[], const bool *ctx,
-		struct irq_affinity *desc);
+		struct irq_affinity *desc, u32 sizes[]);
 const char *vp_bus_name(struct virtio_device *vdev);
 
 /* Setup the affinity for a virtqueue:
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 3c67d3607802..342795175c29 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 			      struct virtqueue *vqs[],
 			      vq_callback_t *callbacks[],
 			      const char * const names[], const bool *ctx,
-			      struct irq_affinity *desc)
+			      struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	struct virtqueue *vq;
-	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
+	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
+			     sizes);
 
 	if (rc)
 		return rc;
diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
index 7767a7f0119b..ee08d01ee8b1 100644
--- a/drivers/virtio/virtio_vdpa.c
+++ b/drivers/virtio/virtio_vdpa.c
@@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 				vq_callback_t *callbacks[],
 				const char * const names[],
 				const bool *ctx,
-				struct irq_affinity *desc)
+				struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
 	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 0b81fbe17c85..5157524d8036 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -57,6 +57,7 @@ struct virtio_shm_region {
  *		include a NULL entry for vqs that do not need a callback
  *	names: array of virtqueue names (mainly for debugging)
  *		include a NULL entry for vqs unused by driver
+ *	sizes: array of virtqueue sizes
  *	Returns 0 on success or error status
  * @del_vqs: free virtqueues found by find_vqs().
  * @get_features: get the array of feature bits for this device.
@@ -98,7 +99,8 @@ struct virtio_config_ops {
 	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
 			struct virtqueue *vqs[], vq_callback_t *callbacks[],
 			const char * const names[], const bool *ctx,
-			struct irq_affinity *desc);
+			struct irq_affinity *desc,
+			u32 sizes[]);
 	void (*del_vqs)(struct virtio_device *);
 	u64 (*get_features)(struct virtio_device *vdev);
 	int (*finalize_features)(struct virtio_device *vdev);
@@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
 	const char *names[] = { n };
 	struct virtqueue *vq;
 	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
-					 NULL);
+					 NULL, NULL);
 	if (err < 0)
 		return ERR_PTR(err);
 	return vq;
@@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 			const char * const names[],
 			struct irq_affinity *desc)
 {
-	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
+	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
+				      desc, NULL);
 }
 
 static inline
@@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
 			struct irq_affinity *desc)
 {
 	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
-				      desc);
+				      desc, NULL);
 }
 
 /**
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 18/26] virtio: find_vqs() add arg sizes
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

find_vqs() adds a new parameter sizes to specify the size of each vq
vring.

0 means use the maximum size supported by the backend.

In the split scenario, the meaning of size is the largest size, because
it may be limited by memory, the virtio core will try a smaller size.
And the size is power of 2.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 arch/um/drivers/virtio_uml.c             |  2 +-
 drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
 drivers/remoteproc/remoteproc_virtio.c   |  2 +-
 drivers/s390/virtio/virtio_ccw.c         |  2 +-
 drivers/virtio/virtio_mmio.c             |  2 +-
 drivers/virtio/virtio_pci_common.c       |  2 +-
 drivers/virtio/virtio_pci_common.h       |  2 +-
 drivers/virtio/virtio_pci_modern.c       |  5 +++--
 drivers/virtio/virtio_vdpa.c             |  2 +-
 include/linux/virtio_config.h            | 11 +++++++----
 10 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
index ba562d68dc04..055b91ccbe8a 100644
--- a/arch/um/drivers/virtio_uml.c
+++ b/arch/um/drivers/virtio_uml.c
@@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
 static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
 		       const char * const names[], const bool *ctx,
-		       struct irq_affinity *desc)
+		       struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
 	int i, queue_idx = 0, rc;
diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
index 38800e86ed8a..aea7aa218b22 100644
--- a/drivers/platform/mellanox/mlxbf-tmfifo.c
+++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
@@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
 					vq_callback_t *callbacks[],
 					const char * const names[],
 					const bool *ctx,
-					struct irq_affinity *desc)
+					struct irq_affinity *desc,
+					u32 sizes[])
 {
 	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
 	struct mlxbf_tmfifo_vring *vring;
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index 70ab496d0431..3a167bec5b09 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
 				 vq_callback_t *callbacks[],
 				 const char * const names[],
 				 const bool * ctx,
-				 struct irq_affinity *desc)
+				 struct irq_affinity *desc, u32 sizes[])
 {
 	int i, ret, queue_idx = 0;
 
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index d35e7a3f7067..b74e08c71534 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 			       vq_callback_t *callbacks[],
 			       const char * const names[],
 			       const bool *ctx,
-			       struct irq_affinity *desc)
+			       struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
 	unsigned long *indicatorp = NULL;
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index a41abc8051b9..55d575f6ef2d 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		       vq_callback_t *callbacks[],
 		       const char * const names[],
 		       const bool *ctx,
-		       struct irq_affinity *desc)
+		       struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
 	int irq = platform_get_irq(vm_dev->pdev, 0);
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 863d3a8a0956..8e8fa7e5ad80 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
 		const char * const names[], const bool *ctx,
-		struct irq_affinity *desc)
+		struct irq_affinity *desc, u32 sizes[])
 {
 	int err;
 
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
index 23f6c5c678d5..9dbf1d555dff 100644
--- a/drivers/virtio/virtio_pci_common.h
+++ b/drivers/virtio/virtio_pci_common.h
@@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
 		const char * const names[], const bool *ctx,
-		struct irq_affinity *desc);
+		struct irq_affinity *desc, u32 sizes[]);
 const char *vp_bus_name(struct virtio_device *vdev);
 
 /* Setup the affinity for a virtqueue:
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 3c67d3607802..342795175c29 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 			      struct virtqueue *vqs[],
 			      vq_callback_t *callbacks[],
 			      const char * const names[], const bool *ctx,
-			      struct irq_affinity *desc)
+			      struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	struct virtqueue *vq;
-	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
+	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
+			     sizes);
 
 	if (rc)
 		return rc;
diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
index 7767a7f0119b..ee08d01ee8b1 100644
--- a/drivers/virtio/virtio_vdpa.c
+++ b/drivers/virtio/virtio_vdpa.c
@@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 				vq_callback_t *callbacks[],
 				const char * const names[],
 				const bool *ctx,
-				struct irq_affinity *desc)
+				struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
 	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 0b81fbe17c85..5157524d8036 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -57,6 +57,7 @@ struct virtio_shm_region {
  *		include a NULL entry for vqs that do not need a callback
  *	names: array of virtqueue names (mainly for debugging)
  *		include a NULL entry for vqs unused by driver
+ *	sizes: array of virtqueue sizes
  *	Returns 0 on success or error status
  * @del_vqs: free virtqueues found by find_vqs().
  * @get_features: get the array of feature bits for this device.
@@ -98,7 +99,8 @@ struct virtio_config_ops {
 	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
 			struct virtqueue *vqs[], vq_callback_t *callbacks[],
 			const char * const names[], const bool *ctx,
-			struct irq_affinity *desc);
+			struct irq_affinity *desc,
+			u32 sizes[]);
 	void (*del_vqs)(struct virtio_device *);
 	u64 (*get_features)(struct virtio_device *vdev);
 	int (*finalize_features)(struct virtio_device *vdev);
@@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
 	const char *names[] = { n };
 	struct virtqueue *vq;
 	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
-					 NULL);
+					 NULL, NULL);
 	if (err < 0)
 		return ERR_PTR(err);
 	return vq;
@@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 			const char * const names[],
 			struct irq_affinity *desc)
 {
-	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
+	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
+				      desc, NULL);
 }
 
 static inline
@@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
 			struct irq_affinity *desc)
 {
 	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
-				      desc);
+				      desc, NULL);
 }
 
 /**
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 18/26] virtio: find_vqs() add arg sizes
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

find_vqs() adds a new parameter sizes to specify the size of each vq
vring.

0 means use the maximum size supported by the backend.

In the split scenario, the meaning of size is the largest size, because
it may be limited by memory, the virtio core will try a smaller size.
And the size is power of 2.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 arch/um/drivers/virtio_uml.c             |  2 +-
 drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
 drivers/remoteproc/remoteproc_virtio.c   |  2 +-
 drivers/s390/virtio/virtio_ccw.c         |  2 +-
 drivers/virtio/virtio_mmio.c             |  2 +-
 drivers/virtio/virtio_pci_common.c       |  2 +-
 drivers/virtio/virtio_pci_common.h       |  2 +-
 drivers/virtio/virtio_pci_modern.c       |  5 +++--
 drivers/virtio/virtio_vdpa.c             |  2 +-
 include/linux/virtio_config.h            | 11 +++++++----
 10 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
index ba562d68dc04..055b91ccbe8a 100644
--- a/arch/um/drivers/virtio_uml.c
+++ b/arch/um/drivers/virtio_uml.c
@@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
 static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
 		       const char * const names[], const bool *ctx,
-		       struct irq_affinity *desc)
+		       struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
 	int i, queue_idx = 0, rc;
diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
index 38800e86ed8a..aea7aa218b22 100644
--- a/drivers/platform/mellanox/mlxbf-tmfifo.c
+++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
@@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
 					vq_callback_t *callbacks[],
 					const char * const names[],
 					const bool *ctx,
-					struct irq_affinity *desc)
+					struct irq_affinity *desc,
+					u32 sizes[])
 {
 	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
 	struct mlxbf_tmfifo_vring *vring;
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
index 70ab496d0431..3a167bec5b09 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
 				 vq_callback_t *callbacks[],
 				 const char * const names[],
 				 const bool * ctx,
-				 struct irq_affinity *desc)
+				 struct irq_affinity *desc, u32 sizes[])
 {
 	int i, ret, queue_idx = 0;
 
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index d35e7a3f7067..b74e08c71534 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 			       vq_callback_t *callbacks[],
 			       const char * const names[],
 			       const bool *ctx,
-			       struct irq_affinity *desc)
+			       struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
 	unsigned long *indicatorp = NULL;
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index a41abc8051b9..55d575f6ef2d 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		       vq_callback_t *callbacks[],
 		       const char * const names[],
 		       const bool *ctx,
-		       struct irq_affinity *desc)
+		       struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
 	int irq = platform_get_irq(vm_dev->pdev, 0);
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 863d3a8a0956..8e8fa7e5ad80 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
 		const char * const names[], const bool *ctx,
-		struct irq_affinity *desc)
+		struct irq_affinity *desc, u32 sizes[])
 {
 	int err;
 
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
index 23f6c5c678d5..9dbf1d555dff 100644
--- a/drivers/virtio/virtio_pci_common.h
+++ b/drivers/virtio/virtio_pci_common.h
@@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
 		const char * const names[], const bool *ctx,
-		struct irq_affinity *desc);
+		struct irq_affinity *desc, u32 sizes[]);
 const char *vp_bus_name(struct virtio_device *vdev);
 
 /* Setup the affinity for a virtqueue:
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 3c67d3607802..342795175c29 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 			      struct virtqueue *vqs[],
 			      vq_callback_t *callbacks[],
 			      const char * const names[], const bool *ctx,
-			      struct irq_affinity *desc)
+			      struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	struct virtqueue *vq;
-	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
+	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
+			     sizes);
 
 	if (rc)
 		return rc;
diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
index 7767a7f0119b..ee08d01ee8b1 100644
--- a/drivers/virtio/virtio_vdpa.c
+++ b/drivers/virtio/virtio_vdpa.c
@@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 				vq_callback_t *callbacks[],
 				const char * const names[],
 				const bool *ctx,
-				struct irq_affinity *desc)
+				struct irq_affinity *desc, u32 sizes[])
 {
 	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
 	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 0b81fbe17c85..5157524d8036 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -57,6 +57,7 @@ struct virtio_shm_region {
  *		include a NULL entry for vqs that do not need a callback
  *	names: array of virtqueue names (mainly for debugging)
  *		include a NULL entry for vqs unused by driver
+ *	sizes: array of virtqueue sizes
  *	Returns 0 on success or error status
  * @del_vqs: free virtqueues found by find_vqs().
  * @get_features: get the array of feature bits for this device.
@@ -98,7 +99,8 @@ struct virtio_config_ops {
 	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
 			struct virtqueue *vqs[], vq_callback_t *callbacks[],
 			const char * const names[], const bool *ctx,
-			struct irq_affinity *desc);
+			struct irq_affinity *desc,
+			u32 sizes[]);
 	void (*del_vqs)(struct virtio_device *);
 	u64 (*get_features)(struct virtio_device *vdev);
 	int (*finalize_features)(struct virtio_device *vdev);
@@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
 	const char *names[] = { n };
 	struct virtqueue *vq;
 	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
-					 NULL);
+					 NULL, NULL);
 	if (err < 0)
 		return ERR_PTR(err);
 	return vq;
@@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 			const char * const names[],
 			struct irq_affinity *desc)
 {
-	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
+	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
+				      desc, NULL);
 }
 
 static inline
@@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
 			struct irq_affinity *desc)
 {
 	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
-				      desc);
+				      desc, NULL);
 }
 
 /**
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 19/26] virtio_pci: support the arg sizes of find_vqs()
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Virtio PCI supports new parameter sizes of find_vqs().

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_common.c | 18 ++++++++++--------
 drivers/virtio/virtio_pci_common.h |  1 +
 drivers/virtio/virtio_pci_legacy.c |  6 +++++-
 drivers/virtio/virtio_pci_modern.c | 10 +++++++---
 4 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 8e8fa7e5ad80..1faf65325060 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -208,6 +208,7 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
 static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index,
 				     void (*callback)(struct virtqueue *vq),
 				     const char *name,
+				     u32 size,
 				     bool ctx,
 				     u16 msix_vec)
 {
@@ -221,7 +222,7 @@ static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index,
 		return ERR_PTR(-ENOMEM);
 
 	vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx,
-			      msix_vec);
+			      size, msix_vec);
 	if (IS_ERR(vq))
 		goto out_info;
 
@@ -314,7 +315,7 @@ void vp_del_vqs(struct virtio_device *vdev)
 
 static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
-		const char * const names[], bool per_vq_vectors,
+		const char * const names[], u32 sizes[], bool per_vq_vectors,
 		const bool *ctx,
 		struct irq_affinity *desc)
 {
@@ -357,8 +358,8 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 		else
 			msix_vec = VP_MSIX_VQ_VECTOR;
 		vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
-				     ctx ? ctx[i] : false,
-				     msix_vec);
+				     sizes ? sizes[i] : 0,
+				     ctx ? ctx[i] : false, msix_vec);
 		if (IS_ERR(vqs[i])) {
 			err = PTR_ERR(vqs[i]);
 			goto error_find;
@@ -388,7 +389,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 
 static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
-		const char * const names[], const bool *ctx)
+		const char * const names[], u32 sizes[], const bool *ctx)
 {
 	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	int i, err, queue_idx = 0;
@@ -410,6 +411,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
 			continue;
 		}
 		vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
+				     sizes ? sizes[i] : 0,
 				     ctx ? ctx[i] : false,
 				     VIRTIO_MSI_NO_VECTOR);
 		if (IS_ERR(vqs[i])) {
@@ -433,15 +435,15 @@ int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 	int err;
 
 	/* Try MSI-X with one vector per queue. */
-	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, ctx, desc);
+	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, sizes, true, ctx, desc);
 	if (!err)
 		return 0;
 	/* Fallback: MSI-X with one vector for config, one shared for queues. */
-	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, ctx, desc);
+	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, sizes, false, ctx, desc);
 	if (!err)
 		return 0;
 	/* Finally fall back to regular interrupts. */
-	return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, ctx);
+	return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, sizes, ctx);
 }
 
 const char *vp_bus_name(struct virtio_device *vdev)
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
index 9dbf1d555dff..a15ac5570ddd 100644
--- a/drivers/virtio/virtio_pci_common.h
+++ b/drivers/virtio/virtio_pci_common.h
@@ -82,6 +82,7 @@ struct virtio_pci_device {
 				      void (*callback)(struct virtqueue *vq),
 				      const char *name,
 				      bool ctx,
+				      u32 size,
 				      u16 msix_vec);
 	void (*del_vq)(struct virtio_pci_vq_info *info);
 
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
index b68934fe6b5d..efa98d2debe0 100644
--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -113,6 +113,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 				  void (*callback)(struct virtqueue *vq),
 				  const char *name,
 				  bool ctx,
+				  u32 size,
 				  u16 msix_vec)
 {
 	struct virtqueue *vq;
@@ -125,10 +126,13 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!num || vp_legacy_get_queue_enable(&vp_dev->ldev, index))
 		return ERR_PTR(-ENOENT);
 
+	if (!size || size > num)
+		size = num;
+
 	info->msix_vector = msix_vec;
 
 	/* create the vring */
-	vq = vring_create_virtqueue(index, num,
+	vq = vring_create_virtqueue(index, size,
 				    VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev,
 				    true, false, ctx,
 				    vp_notify, callback, name);
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 342795175c29..0e17e0df6a8a 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -289,6 +289,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 				  void (*callback)(struct virtqueue *vq),
 				  const char *name,
 				  bool ctx,
+				  u32 size,
 				  u16 msix_vec)
 {
 
@@ -305,15 +306,18 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!num || vp_modern_get_queue_enable(mdev, index))
 		return ERR_PTR(-ENOENT);
 
-	if (num & (num - 1)) {
-		dev_warn(&vp_dev->pci_dev->dev, "bad queue size %u", num);
+	if (!size || size > num)
+		size = num;
+
+	if (size & (size - 1)) {
+		dev_warn(&vp_dev->pci_dev->dev, "bad queue size %u", size);
 		return ERR_PTR(-EINVAL);
 	}
 
 	info->msix_vector = msix_vec;
 
 	/* create the vring */
-	vq = vring_create_virtqueue(index, num,
+	vq = vring_create_virtqueue(index, size,
 				    SMP_CACHE_BYTES, &vp_dev->vdev,
 				    true, true, ctx,
 				    vp_notify, callback, name);
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 19/26] virtio_pci: support the arg sizes of find_vqs()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Virtio PCI supports new parameter sizes of find_vqs().

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_common.c | 18 ++++++++++--------
 drivers/virtio/virtio_pci_common.h |  1 +
 drivers/virtio/virtio_pci_legacy.c |  6 +++++-
 drivers/virtio/virtio_pci_modern.c | 10 +++++++---
 4 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 8e8fa7e5ad80..1faf65325060 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -208,6 +208,7 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
 static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index,
 				     void (*callback)(struct virtqueue *vq),
 				     const char *name,
+				     u32 size,
 				     bool ctx,
 				     u16 msix_vec)
 {
@@ -221,7 +222,7 @@ static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index,
 		return ERR_PTR(-ENOMEM);
 
 	vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx,
-			      msix_vec);
+			      size, msix_vec);
 	if (IS_ERR(vq))
 		goto out_info;
 
@@ -314,7 +315,7 @@ void vp_del_vqs(struct virtio_device *vdev)
 
 static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
-		const char * const names[], bool per_vq_vectors,
+		const char * const names[], u32 sizes[], bool per_vq_vectors,
 		const bool *ctx,
 		struct irq_affinity *desc)
 {
@@ -357,8 +358,8 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 		else
 			msix_vec = VP_MSIX_VQ_VECTOR;
 		vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
-				     ctx ? ctx[i] : false,
-				     msix_vec);
+				     sizes ? sizes[i] : 0,
+				     ctx ? ctx[i] : false, msix_vec);
 		if (IS_ERR(vqs[i])) {
 			err = PTR_ERR(vqs[i]);
 			goto error_find;
@@ -388,7 +389,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 
 static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
-		const char * const names[], const bool *ctx)
+		const char * const names[], u32 sizes[], const bool *ctx)
 {
 	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	int i, err, queue_idx = 0;
@@ -410,6 +411,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
 			continue;
 		}
 		vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
+				     sizes ? sizes[i] : 0,
 				     ctx ? ctx[i] : false,
 				     VIRTIO_MSI_NO_VECTOR);
 		if (IS_ERR(vqs[i])) {
@@ -433,15 +435,15 @@ int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 	int err;
 
 	/* Try MSI-X with one vector per queue. */
-	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, ctx, desc);
+	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, sizes, true, ctx, desc);
 	if (!err)
 		return 0;
 	/* Fallback: MSI-X with one vector for config, one shared for queues. */
-	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, ctx, desc);
+	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, sizes, false, ctx, desc);
 	if (!err)
 		return 0;
 	/* Finally fall back to regular interrupts. */
-	return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, ctx);
+	return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, sizes, ctx);
 }
 
 const char *vp_bus_name(struct virtio_device *vdev)
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
index 9dbf1d555dff..a15ac5570ddd 100644
--- a/drivers/virtio/virtio_pci_common.h
+++ b/drivers/virtio/virtio_pci_common.h
@@ -82,6 +82,7 @@ struct virtio_pci_device {
 				      void (*callback)(struct virtqueue *vq),
 				      const char *name,
 				      bool ctx,
+				      u32 size,
 				      u16 msix_vec);
 	void (*del_vq)(struct virtio_pci_vq_info *info);
 
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
index b68934fe6b5d..efa98d2debe0 100644
--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -113,6 +113,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 				  void (*callback)(struct virtqueue *vq),
 				  const char *name,
 				  bool ctx,
+				  u32 size,
 				  u16 msix_vec)
 {
 	struct virtqueue *vq;
@@ -125,10 +126,13 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!num || vp_legacy_get_queue_enable(&vp_dev->ldev, index))
 		return ERR_PTR(-ENOENT);
 
+	if (!size || size > num)
+		size = num;
+
 	info->msix_vector = msix_vec;
 
 	/* create the vring */
-	vq = vring_create_virtqueue(index, num,
+	vq = vring_create_virtqueue(index, size,
 				    VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev,
 				    true, false, ctx,
 				    vp_notify, callback, name);
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 342795175c29..0e17e0df6a8a 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -289,6 +289,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 				  void (*callback)(struct virtqueue *vq),
 				  const char *name,
 				  bool ctx,
+				  u32 size,
 				  u16 msix_vec)
 {
 
@@ -305,15 +306,18 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!num || vp_modern_get_queue_enable(mdev, index))
 		return ERR_PTR(-ENOENT);
 
-	if (num & (num - 1)) {
-		dev_warn(&vp_dev->pci_dev->dev, "bad queue size %u", num);
+	if (!size || size > num)
+		size = num;
+
+	if (size & (size - 1)) {
+		dev_warn(&vp_dev->pci_dev->dev, "bad queue size %u", size);
 		return ERR_PTR(-EINVAL);
 	}
 
 	info->msix_vector = msix_vec;
 
 	/* create the vring */
-	vq = vring_create_virtqueue(index, num,
+	vq = vring_create_virtqueue(index, size,
 				    SMP_CACHE_BYTES, &vp_dev->vdev,
 				    true, true, ctx,
 				    vp_notify, callback, name);
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 19/26] virtio_pci: support the arg sizes of find_vqs()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Virtio PCI supports new parameter sizes of find_vqs().

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_pci_common.c | 18 ++++++++++--------
 drivers/virtio/virtio_pci_common.h |  1 +
 drivers/virtio/virtio_pci_legacy.c |  6 +++++-
 drivers/virtio/virtio_pci_modern.c | 10 +++++++---
 4 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 8e8fa7e5ad80..1faf65325060 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -208,6 +208,7 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
 static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index,
 				     void (*callback)(struct virtqueue *vq),
 				     const char *name,
+				     u32 size,
 				     bool ctx,
 				     u16 msix_vec)
 {
@@ -221,7 +222,7 @@ static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index,
 		return ERR_PTR(-ENOMEM);
 
 	vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx,
-			      msix_vec);
+			      size, msix_vec);
 	if (IS_ERR(vq))
 		goto out_info;
 
@@ -314,7 +315,7 @@ void vp_del_vqs(struct virtio_device *vdev)
 
 static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
-		const char * const names[], bool per_vq_vectors,
+		const char * const names[], u32 sizes[], bool per_vq_vectors,
 		const bool *ctx,
 		struct irq_affinity *desc)
 {
@@ -357,8 +358,8 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 		else
 			msix_vec = VP_MSIX_VQ_VECTOR;
 		vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
-				     ctx ? ctx[i] : false,
-				     msix_vec);
+				     sizes ? sizes[i] : 0,
+				     ctx ? ctx[i] : false, msix_vec);
 		if (IS_ERR(vqs[i])) {
 			err = PTR_ERR(vqs[i]);
 			goto error_find;
@@ -388,7 +389,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 
 static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
 		struct virtqueue *vqs[], vq_callback_t *callbacks[],
-		const char * const names[], const bool *ctx)
+		const char * const names[], u32 sizes[], const bool *ctx)
 {
 	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
 	int i, err, queue_idx = 0;
@@ -410,6 +411,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
 			continue;
 		}
 		vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
+				     sizes ? sizes[i] : 0,
 				     ctx ? ctx[i] : false,
 				     VIRTIO_MSI_NO_VECTOR);
 		if (IS_ERR(vqs[i])) {
@@ -433,15 +435,15 @@ int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 	int err;
 
 	/* Try MSI-X with one vector per queue. */
-	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, ctx, desc);
+	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, sizes, true, ctx, desc);
 	if (!err)
 		return 0;
 	/* Fallback: MSI-X with one vector for config, one shared for queues. */
-	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, ctx, desc);
+	err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, sizes, false, ctx, desc);
 	if (!err)
 		return 0;
 	/* Finally fall back to regular interrupts. */
-	return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, ctx);
+	return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, sizes, ctx);
 }
 
 const char *vp_bus_name(struct virtio_device *vdev)
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
index 9dbf1d555dff..a15ac5570ddd 100644
--- a/drivers/virtio/virtio_pci_common.h
+++ b/drivers/virtio/virtio_pci_common.h
@@ -82,6 +82,7 @@ struct virtio_pci_device {
 				      void (*callback)(struct virtqueue *vq),
 				      const char *name,
 				      bool ctx,
+				      u32 size,
 				      u16 msix_vec);
 	void (*del_vq)(struct virtio_pci_vq_info *info);
 
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
index b68934fe6b5d..efa98d2debe0 100644
--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -113,6 +113,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 				  void (*callback)(struct virtqueue *vq),
 				  const char *name,
 				  bool ctx,
+				  u32 size,
 				  u16 msix_vec)
 {
 	struct virtqueue *vq;
@@ -125,10 +126,13 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!num || vp_legacy_get_queue_enable(&vp_dev->ldev, index))
 		return ERR_PTR(-ENOENT);
 
+	if (!size || size > num)
+		size = num;
+
 	info->msix_vector = msix_vec;
 
 	/* create the vring */
-	vq = vring_create_virtqueue(index, num,
+	vq = vring_create_virtqueue(index, size,
 				    VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev,
 				    true, false, ctx,
 				    vp_notify, callback, name);
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 342795175c29..0e17e0df6a8a 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -289,6 +289,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 				  void (*callback)(struct virtqueue *vq),
 				  const char *name,
 				  bool ctx,
+				  u32 size,
 				  u16 msix_vec)
 {
 
@@ -305,15 +306,18 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
 	if (!num || vp_modern_get_queue_enable(mdev, index))
 		return ERR_PTR(-ENOENT);
 
-	if (num & (num - 1)) {
-		dev_warn(&vp_dev->pci_dev->dev, "bad queue size %u", num);
+	if (!size || size > num)
+		size = num;
+
+	if (size & (size - 1)) {
+		dev_warn(&vp_dev->pci_dev->dev, "bad queue size %u", size);
 		return ERR_PTR(-EINVAL);
 	}
 
 	info->msix_vector = msix_vec;
 
 	/* create the vring */
-	vq = vring_create_virtqueue(index, num,
+	vq = vring_create_virtqueue(index, size,
 				    SMP_CACHE_BYTES, &vp_dev->vdev,
 				    true, true, ctx,
 				    vp_notify, callback, name);
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 20/26] virtio_mmio: support the arg sizes of find_vqs()
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Virtio MMIO support the new parameter sizes of find_vqs().

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_mmio.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 55d575f6ef2d..4d7cd8881282 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -347,7 +347,7 @@ static void vm_del_vqs(struct virtio_device *vdev)
 
 static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
 				  void (*callback)(struct virtqueue *vq),
-				  const char *name, bool ctx)
+				  const char *name, u32 size, bool ctx)
 {
 	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
 	struct virtio_mmio_vq_info *info;
@@ -382,8 +382,11 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
 		goto error_new_virtqueue;
 	}
 
+	if (!size || size > num)
+		size = num;
+
 	/* Create the vring */
-	vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, vdev,
+	vq = vring_create_virtqueue(index, size, VIRTIO_MMIO_VRING_ALIGN, vdev,
 				 true, true, ctx, vm_notify, callback, name);
 	if (!vq) {
 		err = -ENOMEM;
@@ -483,6 +486,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		}
 
 		vqs[i] = vm_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
+				     sizes ? sizes[i] : 0,
 				     ctx ? ctx[i] : false);
 		if (IS_ERR(vqs[i])) {
 			vm_del_vqs(vdev);
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 20/26] virtio_mmio: support the arg sizes of find_vqs()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Virtio MMIO support the new parameter sizes of find_vqs().

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_mmio.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 55d575f6ef2d..4d7cd8881282 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -347,7 +347,7 @@ static void vm_del_vqs(struct virtio_device *vdev)
 
 static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
 				  void (*callback)(struct virtqueue *vq),
-				  const char *name, bool ctx)
+				  const char *name, u32 size, bool ctx)
 {
 	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
 	struct virtio_mmio_vq_info *info;
@@ -382,8 +382,11 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
 		goto error_new_virtqueue;
 	}
 
+	if (!size || size > num)
+		size = num;
+
 	/* Create the vring */
-	vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, vdev,
+	vq = vring_create_virtqueue(index, size, VIRTIO_MMIO_VRING_ALIGN, vdev,
 				 true, true, ctx, vm_notify, callback, name);
 	if (!vq) {
 		err = -ENOMEM;
@@ -483,6 +486,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		}
 
 		vqs[i] = vm_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
+				     sizes ? sizes[i] : 0,
 				     ctx ? ctx[i] : false);
 		if (IS_ERR(vqs[i])) {
 			vm_del_vqs(vdev);
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 20/26] virtio_mmio: support the arg sizes of find_vqs()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Virtio MMIO support the new parameter sizes of find_vqs().

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/virtio/virtio_mmio.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 55d575f6ef2d..4d7cd8881282 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -347,7 +347,7 @@ static void vm_del_vqs(struct virtio_device *vdev)
 
 static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
 				  void (*callback)(struct virtqueue *vq),
-				  const char *name, bool ctx)
+				  const char *name, u32 size, bool ctx)
 {
 	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
 	struct virtio_mmio_vq_info *info;
@@ -382,8 +382,11 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
 		goto error_new_virtqueue;
 	}
 
+	if (!size || size > num)
+		size = num;
+
 	/* Create the vring */
-	vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, vdev,
+	vq = vring_create_virtqueue(index, size, VIRTIO_MMIO_VRING_ALIGN, vdev,
 				 true, true, ctx, vm_notify, callback, name);
 	if (!vq) {
 		err = -ENOMEM;
@@ -483,6 +486,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 		}
 
 		vqs[i] = vm_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
+				     sizes ? sizes[i] : 0,
 				     ctx ? ctx[i] : false);
 		if (IS_ERR(vqs[i])) {
 			vm_del_vqs(vdev);
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 21/26] virtio: add helper virtio_find_vqs_ctx_size()
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Introduce helper virtio_find_vqs_ctx_size() to call find_vqs and specify
the maximum size of each vq ring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/linux/virtio_config.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 5157524d8036..921d8610db0c 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -233,6 +233,18 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
 				      desc, NULL);
 }
 
+static inline
+int virtio_find_vqs_ctx_size(struct virtio_device *vdev, u32 nvqs,
+				 struct virtqueue *vqs[],
+				 vq_callback_t *callbacks[],
+				 const char * const names[],
+				 const bool *ctx, struct irq_affinity *desc,
+				 u32 sizes[])
+{
+	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
+				      desc, sizes);
+}
+
 /**
  * virtio_reset_vq - reset a queue individually
  * @vq: the virtqueue
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 21/26] virtio: add helper virtio_find_vqs_ctx_size()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Introduce helper virtio_find_vqs_ctx_size() to call find_vqs and specify
the maximum size of each vq ring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/linux/virtio_config.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 5157524d8036..921d8610db0c 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -233,6 +233,18 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
 				      desc, NULL);
 }
 
+static inline
+int virtio_find_vqs_ctx_size(struct virtio_device *vdev, u32 nvqs,
+				 struct virtqueue *vqs[],
+				 vq_callback_t *callbacks[],
+				 const char * const names[],
+				 const bool *ctx, struct irq_affinity *desc,
+				 u32 sizes[])
+{
+	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
+				      desc, sizes);
+}
+
 /**
  * virtio_reset_vq - reset a queue individually
  * @vq: the virtqueue
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 21/26] virtio: add helper virtio_find_vqs_ctx_size()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Introduce helper virtio_find_vqs_ctx_size() to call find_vqs and specify
the maximum size of each vq ring.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 include/linux/virtio_config.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index 5157524d8036..921d8610db0c 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -233,6 +233,18 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
 				      desc, NULL);
 }
 
+static inline
+int virtio_find_vqs_ctx_size(struct virtio_device *vdev, u32 nvqs,
+				 struct virtqueue *vqs[],
+				 vq_callback_t *callbacks[],
+				 const char * const names[],
+				 const bool *ctx, struct irq_affinity *desc,
+				 u32 sizes[])
+{
+	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
+				      desc, sizes);
+}
+
 /**
  * virtio_reset_vq - reset a queue individually
  * @vq: the virtqueue
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 22/26] virtio_net: get ringparam by virtqueue_get_vring_max_size()
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Use virtqueue_get_vring_max_size() in virtnet_get_ringparam() to set
tx,rx_max_pending.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index a801ea40908f..59b1ea82f5f0 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2177,10 +2177,10 @@ static void virtnet_get_ringparam(struct net_device *dev,
 {
 	struct virtnet_info *vi = netdev_priv(dev);
 
-	ring->rx_max_pending = virtqueue_get_vring_size(vi->rq[0].vq);
-	ring->tx_max_pending = virtqueue_get_vring_size(vi->sq[0].vq);
-	ring->rx_pending = ring->rx_max_pending;
-	ring->tx_pending = ring->tx_max_pending;
+	ring->rx_max_pending = virtqueue_get_vring_max_size(vi->rq[0].vq);
+	ring->tx_max_pending = virtqueue_get_vring_max_size(vi->sq[0].vq);
+	ring->rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
+	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
 }
 
 
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 22/26] virtio_net: get ringparam by virtqueue_get_vring_max_size()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Use virtqueue_get_vring_max_size() in virtnet_get_ringparam() to set
tx,rx_max_pending.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index a801ea40908f..59b1ea82f5f0 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2177,10 +2177,10 @@ static void virtnet_get_ringparam(struct net_device *dev,
 {
 	struct virtnet_info *vi = netdev_priv(dev);
 
-	ring->rx_max_pending = virtqueue_get_vring_size(vi->rq[0].vq);
-	ring->tx_max_pending = virtqueue_get_vring_size(vi->sq[0].vq);
-	ring->rx_pending = ring->rx_max_pending;
-	ring->tx_pending = ring->tx_max_pending;
+	ring->rx_max_pending = virtqueue_get_vring_max_size(vi->rq[0].vq);
+	ring->tx_max_pending = virtqueue_get_vring_max_size(vi->sq[0].vq);
+	ring->rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
+	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
 }
 
 
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 22/26] virtio_net: get ringparam by virtqueue_get_vring_max_size()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Use virtqueue_get_vring_max_size() in virtnet_get_ringparam() to set
tx,rx_max_pending.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index a801ea40908f..59b1ea82f5f0 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2177,10 +2177,10 @@ static void virtnet_get_ringparam(struct net_device *dev,
 {
 	struct virtnet_info *vi = netdev_priv(dev);
 
-	ring->rx_max_pending = virtqueue_get_vring_size(vi->rq[0].vq);
-	ring->tx_max_pending = virtqueue_get_vring_size(vi->sq[0].vq);
-	ring->rx_pending = ring->rx_max_pending;
-	ring->tx_pending = ring->tx_max_pending;
+	ring->rx_max_pending = virtqueue_get_vring_max_size(vi->rq[0].vq);
+	ring->tx_max_pending = virtqueue_get_vring_max_size(vi->sq[0].vq);
+	ring->rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
+	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
 }
 
 
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 23/26] virtio_net: split free_unused_bufs()
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

This patch separates two functions for freeing sq buf and rq buf from
free_unused_bufs().

When supporting the enable/disable tx/rq queue in the future, it is
necessary to support separate recovery of a sq buf or a rq buf.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 53 +++++++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 22 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 59b1ea82f5f0..409a8e180918 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2804,36 +2804,45 @@ static void free_receive_page_frags(struct virtnet_info *vi)
 			put_page(vi->rq[i].alloc_frag.page);
 }
 
-static void free_unused_bufs(struct virtnet_info *vi)
+static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
+					struct send_queue *sq)
 {
 	void *buf;
-	int i;
 
-	for (i = 0; i < vi->max_queue_pairs; i++) {
-		struct virtqueue *vq = vi->sq[i].vq;
-		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-			if (!is_xdp_frame(buf))
-				dev_kfree_skb(buf);
-			else
-				xdp_return_frame(ptr_to_xdp(buf));
-		}
+	while ((buf = virtqueue_detach_unused_buf(sq->vq)) != NULL) {
+		if (!is_xdp_frame(buf))
+			dev_kfree_skb(buf);
+		else
+			xdp_return_frame(ptr_to_xdp(buf));
 	}
+}
 
-	for (i = 0; i < vi->max_queue_pairs; i++) {
-		struct virtqueue *vq = vi->rq[i].vq;
-
-		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-			if (vi->mergeable_rx_bufs) {
-				put_page(virt_to_head_page(buf));
-			} else if (vi->big_packets) {
-				give_pages(&vi->rq[i], buf);
-			} else {
-				put_page(virt_to_head_page(buf));
-			}
-		}
+static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
+					struct receive_queue *rq)
+{
+	void *buf;
+
+	while ((buf = virtqueue_detach_unused_buf(rq->vq)) != NULL) {
+		if (vi->mergeable_rx_bufs)
+			put_page(virt_to_head_page(buf));
+		else if (vi->big_packets)
+			give_pages(rq, buf);
+		else
+			put_page(virt_to_head_page(buf));
 	}
 }
 
+static void free_unused_bufs(struct virtnet_info *vi)
+{
+	int i;
+
+	for (i = 0; i < vi->max_queue_pairs; i++)
+		virtnet_sq_free_unused_bufs(vi, vi->sq + i);
+
+	for (i = 0; i < vi->max_queue_pairs; i++)
+		virtnet_rq_free_unused_bufs(vi, vi->rq + i);
+}
+
 static void virtnet_del_vqs(struct virtnet_info *vi)
 {
 	struct virtio_device *vdev = vi->vdev;
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 23/26] virtio_net: split free_unused_bufs()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

This patch separates two functions for freeing sq buf and rq buf from
free_unused_bufs().

When supporting the enable/disable tx/rq queue in the future, it is
necessary to support separate recovery of a sq buf or a rq buf.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 53 +++++++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 22 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 59b1ea82f5f0..409a8e180918 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2804,36 +2804,45 @@ static void free_receive_page_frags(struct virtnet_info *vi)
 			put_page(vi->rq[i].alloc_frag.page);
 }
 
-static void free_unused_bufs(struct virtnet_info *vi)
+static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
+					struct send_queue *sq)
 {
 	void *buf;
-	int i;
 
-	for (i = 0; i < vi->max_queue_pairs; i++) {
-		struct virtqueue *vq = vi->sq[i].vq;
-		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-			if (!is_xdp_frame(buf))
-				dev_kfree_skb(buf);
-			else
-				xdp_return_frame(ptr_to_xdp(buf));
-		}
+	while ((buf = virtqueue_detach_unused_buf(sq->vq)) != NULL) {
+		if (!is_xdp_frame(buf))
+			dev_kfree_skb(buf);
+		else
+			xdp_return_frame(ptr_to_xdp(buf));
 	}
+}
 
-	for (i = 0; i < vi->max_queue_pairs; i++) {
-		struct virtqueue *vq = vi->rq[i].vq;
-
-		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-			if (vi->mergeable_rx_bufs) {
-				put_page(virt_to_head_page(buf));
-			} else if (vi->big_packets) {
-				give_pages(&vi->rq[i], buf);
-			} else {
-				put_page(virt_to_head_page(buf));
-			}
-		}
+static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
+					struct receive_queue *rq)
+{
+	void *buf;
+
+	while ((buf = virtqueue_detach_unused_buf(rq->vq)) != NULL) {
+		if (vi->mergeable_rx_bufs)
+			put_page(virt_to_head_page(buf));
+		else if (vi->big_packets)
+			give_pages(rq, buf);
+		else
+			put_page(virt_to_head_page(buf));
 	}
 }
 
+static void free_unused_bufs(struct virtnet_info *vi)
+{
+	int i;
+
+	for (i = 0; i < vi->max_queue_pairs; i++)
+		virtnet_sq_free_unused_bufs(vi, vi->sq + i);
+
+	for (i = 0; i < vi->max_queue_pairs; i++)
+		virtnet_rq_free_unused_bufs(vi, vi->rq + i);
+}
+
 static void virtnet_del_vqs(struct virtnet_info *vi)
 {
 	struct virtio_device *vdev = vi->vdev;
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 23/26] virtio_net: split free_unused_bufs()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

This patch separates two functions for freeing sq buf and rq buf from
free_unused_bufs().

When supporting the enable/disable tx/rq queue in the future, it is
necessary to support separate recovery of a sq buf or a rq buf.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 53 +++++++++++++++++++++++-----------------
 1 file changed, 31 insertions(+), 22 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 59b1ea82f5f0..409a8e180918 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2804,36 +2804,45 @@ static void free_receive_page_frags(struct virtnet_info *vi)
 			put_page(vi->rq[i].alloc_frag.page);
 }
 
-static void free_unused_bufs(struct virtnet_info *vi)
+static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
+					struct send_queue *sq)
 {
 	void *buf;
-	int i;
 
-	for (i = 0; i < vi->max_queue_pairs; i++) {
-		struct virtqueue *vq = vi->sq[i].vq;
-		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-			if (!is_xdp_frame(buf))
-				dev_kfree_skb(buf);
-			else
-				xdp_return_frame(ptr_to_xdp(buf));
-		}
+	while ((buf = virtqueue_detach_unused_buf(sq->vq)) != NULL) {
+		if (!is_xdp_frame(buf))
+			dev_kfree_skb(buf);
+		else
+			xdp_return_frame(ptr_to_xdp(buf));
 	}
+}
 
-	for (i = 0; i < vi->max_queue_pairs; i++) {
-		struct virtqueue *vq = vi->rq[i].vq;
-
-		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-			if (vi->mergeable_rx_bufs) {
-				put_page(virt_to_head_page(buf));
-			} else if (vi->big_packets) {
-				give_pages(&vi->rq[i], buf);
-			} else {
-				put_page(virt_to_head_page(buf));
-			}
-		}
+static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
+					struct receive_queue *rq)
+{
+	void *buf;
+
+	while ((buf = virtqueue_detach_unused_buf(rq->vq)) != NULL) {
+		if (vi->mergeable_rx_bufs)
+			put_page(virt_to_head_page(buf));
+		else if (vi->big_packets)
+			give_pages(rq, buf);
+		else
+			put_page(virt_to_head_page(buf));
 	}
 }
 
+static void free_unused_bufs(struct virtnet_info *vi)
+{
+	int i;
+
+	for (i = 0; i < vi->max_queue_pairs; i++)
+		virtnet_sq_free_unused_bufs(vi, vi->sq + i);
+
+	for (i = 0; i < vi->max_queue_pairs; i++)
+		virtnet_rq_free_unused_bufs(vi, vi->rq + i);
+}
+
 static void virtnet_del_vqs(struct virtnet_info *vi)
 {
 	struct virtio_device *vdev = vi->vdev;
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 24/26] virtio_net: support rx/tx queue reset
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

This patch implements the reset function of the rx, tx queues.

Based on this function, it is possible to modify the ring num of the
queue. And quickly recycle the buffer in the queue.

In the process of the queue disable, in theory, as long as virtio
supports queue reset, there will be no exceptions.

However, in the process of the queue enable, there may be exceptions due to
memory allocation.  In this case, vq is not available, but we still have
to execute napi_enable(). Because napi_disable is similar to a lock,
napi_enable must be called after calling napi_disable.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 409a8e180918..ffff323dcef0 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -251,6 +251,11 @@ struct padded_vnet_hdr {
 	char padding[4];
 };
 
+static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
+					struct send_queue *sq);
+static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
+					struct receive_queue *rq);
+
 static bool is_xdp_frame(void *ptr)
 {
 	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
@@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
 {
 	napi_enable(napi);
 
+	if (vq->reset)
+		return;
+
 	/* If all buffers were filled by other side before we napi_enabled, we
 	 * won't get another interrupt, so process any outstanding packets now.
 	 * Call local_bh_enable after to trigger softIRQ processing.
@@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
 		struct receive_queue *rq = &vi->rq[i];
 
 		napi_disable(&rq->napi);
+		if (rq->vq->reset) {
+			virtnet_napi_enable(rq->vq, &rq->napi);
+			continue;
+		}
 		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
 		virtnet_napi_enable(rq->vq, &rq->napi);
 
@@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
 	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
 		return;
 
+	if (sq->vq->reset)
+		return;
+
 	if (__netif_tx_trylock(txq)) {
 		do {
 			virtqueue_disable_cb(sq->vq);
@@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return NETDEV_TX_OK;
 }
 
+static int virtnet_rx_vq_reset(struct virtnet_info *vi,
+			       struct receive_queue *rq, u32 ring_num)
+{
+	int err;
+
+	/* stop napi */
+	napi_disable(&rq->napi);
+
+	/* reset the queue */
+	err = virtio_reset_vq(rq->vq);
+	if (err)
+		goto err;
+
+	/* free bufs */
+	virtnet_rq_free_unused_bufs(vi, rq);
+
+	/* reset vring. */
+	err = virtqueue_reset_vring(rq->vq, ring_num);
+	if (err)
+		goto err;
+
+	/* enable reset queue */
+	err = virtio_enable_resetq(rq->vq);
+	if (err)
+		goto err;
+
+	/* fill recv */
+	if (!try_fill_recv(vi, rq, GFP_KERNEL))
+		schedule_delayed_work(&vi->refill, 0);
+
+	/* enable napi */
+	virtnet_napi_enable(rq->vq, &rq->napi);
+	return 0;
+
+err:
+	netdev_err(vi->dev,
+		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
+		   rq - vi->rq, err);
+	virtnet_napi_enable(rq->vq, &rq->napi);
+	return err;
+}
+
+static int virtnet_tx_vq_reset(struct virtnet_info *vi,
+			       struct send_queue *sq, u32 ring_num)
+{
+	struct netdev_queue *txq;
+	int err, qindex;
+
+	qindex = sq - vi->sq;
+
+	txq = netdev_get_tx_queue(vi->dev, qindex);
+	__netif_tx_lock_bh(txq);
+
+	/* stop tx queue and napi */
+	netif_stop_subqueue(vi->dev, qindex);
+	virtnet_napi_tx_disable(&sq->napi);
+
+	__netif_tx_unlock_bh(txq);
+
+	/* reset the queue */
+	err = virtio_reset_vq(sq->vq);
+	if (err) {
+		netif_start_subqueue(vi->dev, qindex);
+		goto err;
+	}
+
+	/* free bufs */
+	virtnet_sq_free_unused_bufs(vi, sq);
+
+	/* reset vring. */
+	err = virtqueue_reset_vring(sq->vq, ring_num);
+	if (err)
+		goto err;
+
+	/* enable reset queue */
+	err = virtio_enable_resetq(sq->vq);
+	if (err)
+		goto err;
+
+	/* start tx queue and napi */
+	netif_start_subqueue(vi->dev, qindex);
+	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
+	return 0;
+
+err:
+	netdev_err(vi->dev,
+		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
+		   sq - vi->sq, err);
+	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
+	return err;
+}
+
 /*
  * Send command via the control virtqueue and check status.  Commands
  * supported by the hypervisor, as indicated by feature bits, should
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 24/26] virtio_net: support rx/tx queue reset
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

This patch implements the reset function of the rx, tx queues.

Based on this function, it is possible to modify the ring num of the
queue. And quickly recycle the buffer in the queue.

In the process of the queue disable, in theory, as long as virtio
supports queue reset, there will be no exceptions.

However, in the process of the queue enable, there may be exceptions due to
memory allocation.  In this case, vq is not available, but we still have
to execute napi_enable(). Because napi_disable is similar to a lock,
napi_enable must be called after calling napi_disable.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 409a8e180918..ffff323dcef0 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -251,6 +251,11 @@ struct padded_vnet_hdr {
 	char padding[4];
 };
 
+static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
+					struct send_queue *sq);
+static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
+					struct receive_queue *rq);
+
 static bool is_xdp_frame(void *ptr)
 {
 	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
@@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
 {
 	napi_enable(napi);
 
+	if (vq->reset)
+		return;
+
 	/* If all buffers were filled by other side before we napi_enabled, we
 	 * won't get another interrupt, so process any outstanding packets now.
 	 * Call local_bh_enable after to trigger softIRQ processing.
@@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
 		struct receive_queue *rq = &vi->rq[i];
 
 		napi_disable(&rq->napi);
+		if (rq->vq->reset) {
+			virtnet_napi_enable(rq->vq, &rq->napi);
+			continue;
+		}
 		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
 		virtnet_napi_enable(rq->vq, &rq->napi);
 
@@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
 	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
 		return;
 
+	if (sq->vq->reset)
+		return;
+
 	if (__netif_tx_trylock(txq)) {
 		do {
 			virtqueue_disable_cb(sq->vq);
@@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return NETDEV_TX_OK;
 }
 
+static int virtnet_rx_vq_reset(struct virtnet_info *vi,
+			       struct receive_queue *rq, u32 ring_num)
+{
+	int err;
+
+	/* stop napi */
+	napi_disable(&rq->napi);
+
+	/* reset the queue */
+	err = virtio_reset_vq(rq->vq);
+	if (err)
+		goto err;
+
+	/* free bufs */
+	virtnet_rq_free_unused_bufs(vi, rq);
+
+	/* reset vring. */
+	err = virtqueue_reset_vring(rq->vq, ring_num);
+	if (err)
+		goto err;
+
+	/* enable reset queue */
+	err = virtio_enable_resetq(rq->vq);
+	if (err)
+		goto err;
+
+	/* fill recv */
+	if (!try_fill_recv(vi, rq, GFP_KERNEL))
+		schedule_delayed_work(&vi->refill, 0);
+
+	/* enable napi */
+	virtnet_napi_enable(rq->vq, &rq->napi);
+	return 0;
+
+err:
+	netdev_err(vi->dev,
+		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
+		   rq - vi->rq, err);
+	virtnet_napi_enable(rq->vq, &rq->napi);
+	return err;
+}
+
+static int virtnet_tx_vq_reset(struct virtnet_info *vi,
+			       struct send_queue *sq, u32 ring_num)
+{
+	struct netdev_queue *txq;
+	int err, qindex;
+
+	qindex = sq - vi->sq;
+
+	txq = netdev_get_tx_queue(vi->dev, qindex);
+	__netif_tx_lock_bh(txq);
+
+	/* stop tx queue and napi */
+	netif_stop_subqueue(vi->dev, qindex);
+	virtnet_napi_tx_disable(&sq->napi);
+
+	__netif_tx_unlock_bh(txq);
+
+	/* reset the queue */
+	err = virtio_reset_vq(sq->vq);
+	if (err) {
+		netif_start_subqueue(vi->dev, qindex);
+		goto err;
+	}
+
+	/* free bufs */
+	virtnet_sq_free_unused_bufs(vi, sq);
+
+	/* reset vring. */
+	err = virtqueue_reset_vring(sq->vq, ring_num);
+	if (err)
+		goto err;
+
+	/* enable reset queue */
+	err = virtio_enable_resetq(sq->vq);
+	if (err)
+		goto err;
+
+	/* start tx queue and napi */
+	netif_start_subqueue(vi->dev, qindex);
+	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
+	return 0;
+
+err:
+	netdev_err(vi->dev,
+		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
+		   sq - vi->sq, err);
+	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
+	return err;
+}
+
 /*
  * Send command via the control virtqueue and check status.  Commands
  * supported by the hypervisor, as indicated by feature bits, should
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 24/26] virtio_net: support rx/tx queue reset
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

This patch implements the reset function of the rx, tx queues.

Based on this function, it is possible to modify the ring num of the
queue. And quickly recycle the buffer in the queue.

In the process of the queue disable, in theory, as long as virtio
supports queue reset, there will be no exceptions.

However, in the process of the queue enable, there may be exceptions due to
memory allocation.  In this case, vq is not available, but we still have
to execute napi_enable(). Because napi_disable is similar to a lock,
napi_enable must be called after calling napi_disable.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 409a8e180918..ffff323dcef0 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -251,6 +251,11 @@ struct padded_vnet_hdr {
 	char padding[4];
 };
 
+static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
+					struct send_queue *sq);
+static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
+					struct receive_queue *rq);
+
 static bool is_xdp_frame(void *ptr)
 {
 	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
@@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
 {
 	napi_enable(napi);
 
+	if (vq->reset)
+		return;
+
 	/* If all buffers were filled by other side before we napi_enabled, we
 	 * won't get another interrupt, so process any outstanding packets now.
 	 * Call local_bh_enable after to trigger softIRQ processing.
@@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
 		struct receive_queue *rq = &vi->rq[i];
 
 		napi_disable(&rq->napi);
+		if (rq->vq->reset) {
+			virtnet_napi_enable(rq->vq, &rq->napi);
+			continue;
+		}
 		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
 		virtnet_napi_enable(rq->vq, &rq->napi);
 
@@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
 	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
 		return;
 
+	if (sq->vq->reset)
+		return;
+
 	if (__netif_tx_trylock(txq)) {
 		do {
 			virtqueue_disable_cb(sq->vq);
@@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 	return NETDEV_TX_OK;
 }
 
+static int virtnet_rx_vq_reset(struct virtnet_info *vi,
+			       struct receive_queue *rq, u32 ring_num)
+{
+	int err;
+
+	/* stop napi */
+	napi_disable(&rq->napi);
+
+	/* reset the queue */
+	err = virtio_reset_vq(rq->vq);
+	if (err)
+		goto err;
+
+	/* free bufs */
+	virtnet_rq_free_unused_bufs(vi, rq);
+
+	/* reset vring. */
+	err = virtqueue_reset_vring(rq->vq, ring_num);
+	if (err)
+		goto err;
+
+	/* enable reset queue */
+	err = virtio_enable_resetq(rq->vq);
+	if (err)
+		goto err;
+
+	/* fill recv */
+	if (!try_fill_recv(vi, rq, GFP_KERNEL))
+		schedule_delayed_work(&vi->refill, 0);
+
+	/* enable napi */
+	virtnet_napi_enable(rq->vq, &rq->napi);
+	return 0;
+
+err:
+	netdev_err(vi->dev,
+		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
+		   rq - vi->rq, err);
+	virtnet_napi_enable(rq->vq, &rq->napi);
+	return err;
+}
+
+static int virtnet_tx_vq_reset(struct virtnet_info *vi,
+			       struct send_queue *sq, u32 ring_num)
+{
+	struct netdev_queue *txq;
+	int err, qindex;
+
+	qindex = sq - vi->sq;
+
+	txq = netdev_get_tx_queue(vi->dev, qindex);
+	__netif_tx_lock_bh(txq);
+
+	/* stop tx queue and napi */
+	netif_stop_subqueue(vi->dev, qindex);
+	virtnet_napi_tx_disable(&sq->napi);
+
+	__netif_tx_unlock_bh(txq);
+
+	/* reset the queue */
+	err = virtio_reset_vq(sq->vq);
+	if (err) {
+		netif_start_subqueue(vi->dev, qindex);
+		goto err;
+	}
+
+	/* free bufs */
+	virtnet_sq_free_unused_bufs(vi, sq);
+
+	/* reset vring. */
+	err = virtqueue_reset_vring(sq->vq, ring_num);
+	if (err)
+		goto err;
+
+	/* enable reset queue */
+	err = virtio_enable_resetq(sq->vq);
+	if (err)
+		goto err;
+
+	/* start tx queue and napi */
+	netif_start_subqueue(vi->dev, qindex);
+	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
+	return 0;
+
+err:
+	netdev_err(vi->dev,
+		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
+		   sq - vi->sq, err);
+	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
+	return err;
+}
+
 /*
  * Send command via the control virtqueue and check status.  Commands
  * supported by the hypervisor, as indicated by feature bits, should
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 25/26] virtio_net: set the default max ring size by find_vqs()
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Use virtio_find_vqs_ctx_size() to specify the maximum ring size of tx,
rx at the same time.

                         | rx/tx ring size
-------------------------------------------
speed == UNKNOWN or < 10G| 1024
speed < 40G              | 4096
speed >= 40G             | 8192

Call virtnet_update_settings() once before calling init_vqs() to update
speed.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 42 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index ffff323dcef0..f1bdc6ce21c3 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2977,6 +2977,29 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
 		   (unsigned int)GOOD_PACKET_LEN);
 }
 
+static void virtnet_config_sizes(struct virtnet_info *vi, u32 *sizes)
+{
+	u32 i, rx_size, tx_size;
+
+	if (vi->speed == SPEED_UNKNOWN || vi->speed < SPEED_10000) {
+		rx_size = 1024;
+		tx_size = 1024;
+
+	} else if (vi->speed < SPEED_40000) {
+		rx_size = 1024 * 4;
+		tx_size = 1024 * 4;
+
+	} else {
+		rx_size = 1024 * 8;
+		tx_size = 1024 * 8;
+	}
+
+	for (i = 0; i < vi->max_queue_pairs; i++) {
+		sizes[rxq2vq(i)] = rx_size;
+		sizes[txq2vq(i)] = tx_size;
+	}
+}
+
 static int virtnet_find_vqs(struct virtnet_info *vi)
 {
 	vq_callback_t **callbacks;
@@ -2984,6 +3007,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 	int ret = -ENOMEM;
 	int i, total_vqs;
 	const char **names;
+	u32 *sizes;
 	bool *ctx;
 
 	/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
@@ -3011,10 +3035,15 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 		ctx = NULL;
 	}
 
+	sizes = kmalloc_array(total_vqs, sizeof(*sizes), GFP_KERNEL);
+	if (!sizes)
+		goto err_sizes;
+
 	/* Parameters for control virtqueue, if any */
 	if (vi->has_cvq) {
 		callbacks[total_vqs - 1] = NULL;
 		names[total_vqs - 1] = "control";
+		sizes[total_vqs - 1] = 0;
 	}
 
 	/* Allocate/initialize parameters for send/receive virtqueues */
@@ -3029,8 +3058,10 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 			ctx[rxq2vq(i)] = true;
 	}
 
-	ret = virtio_find_vqs_ctx(vi->vdev, total_vqs, vqs, callbacks,
-				  names, ctx, NULL);
+	virtnet_config_sizes(vi, sizes);
+
+	ret = virtio_find_vqs_ctx_size(vi->vdev, total_vqs, vqs, callbacks,
+				       names, ctx, NULL, sizes);
 	if (ret)
 		goto err_find;
 
@@ -3050,6 +3081,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 
 
 err_find:
+	kfree(sizes);
+err_sizes:
 	kfree(ctx);
 err_ctx:
 	kfree(names);
@@ -3368,6 +3401,9 @@ static int virtnet_probe(struct virtio_device *vdev)
 		vi->curr_queue_pairs = num_online_cpus();
 	vi->max_queue_pairs = max_queue_pairs;
 
+	virtnet_init_settings(dev);
+	virtnet_update_settings(vi);
+
 	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
 	err = init_vqs(vi);
 	if (err)
@@ -3380,8 +3416,6 @@ static int virtnet_probe(struct virtio_device *vdev)
 	netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs);
 	netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs);
 
-	virtnet_init_settings(dev);
-
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
 		vi->failover = net_failover_create(vi->dev);
 		if (IS_ERR(vi->failover)) {
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 25/26] virtio_net: set the default max ring size by find_vqs()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Use virtio_find_vqs_ctx_size() to specify the maximum ring size of tx,
rx at the same time.

                         | rx/tx ring size
-------------------------------------------
speed == UNKNOWN or < 10G| 1024
speed < 40G              | 4096
speed >= 40G             | 8192

Call virtnet_update_settings() once before calling init_vqs() to update
speed.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 42 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index ffff323dcef0..f1bdc6ce21c3 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2977,6 +2977,29 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
 		   (unsigned int)GOOD_PACKET_LEN);
 }
 
+static void virtnet_config_sizes(struct virtnet_info *vi, u32 *sizes)
+{
+	u32 i, rx_size, tx_size;
+
+	if (vi->speed == SPEED_UNKNOWN || vi->speed < SPEED_10000) {
+		rx_size = 1024;
+		tx_size = 1024;
+
+	} else if (vi->speed < SPEED_40000) {
+		rx_size = 1024 * 4;
+		tx_size = 1024 * 4;
+
+	} else {
+		rx_size = 1024 * 8;
+		tx_size = 1024 * 8;
+	}
+
+	for (i = 0; i < vi->max_queue_pairs; i++) {
+		sizes[rxq2vq(i)] = rx_size;
+		sizes[txq2vq(i)] = tx_size;
+	}
+}
+
 static int virtnet_find_vqs(struct virtnet_info *vi)
 {
 	vq_callback_t **callbacks;
@@ -2984,6 +3007,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 	int ret = -ENOMEM;
 	int i, total_vqs;
 	const char **names;
+	u32 *sizes;
 	bool *ctx;
 
 	/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
@@ -3011,10 +3035,15 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 		ctx = NULL;
 	}
 
+	sizes = kmalloc_array(total_vqs, sizeof(*sizes), GFP_KERNEL);
+	if (!sizes)
+		goto err_sizes;
+
 	/* Parameters for control virtqueue, if any */
 	if (vi->has_cvq) {
 		callbacks[total_vqs - 1] = NULL;
 		names[total_vqs - 1] = "control";
+		sizes[total_vqs - 1] = 0;
 	}
 
 	/* Allocate/initialize parameters for send/receive virtqueues */
@@ -3029,8 +3058,10 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 			ctx[rxq2vq(i)] = true;
 	}
 
-	ret = virtio_find_vqs_ctx(vi->vdev, total_vqs, vqs, callbacks,
-				  names, ctx, NULL);
+	virtnet_config_sizes(vi, sizes);
+
+	ret = virtio_find_vqs_ctx_size(vi->vdev, total_vqs, vqs, callbacks,
+				       names, ctx, NULL, sizes);
 	if (ret)
 		goto err_find;
 
@@ -3050,6 +3081,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 
 
 err_find:
+	kfree(sizes);
+err_sizes:
 	kfree(ctx);
 err_ctx:
 	kfree(names);
@@ -3368,6 +3401,9 @@ static int virtnet_probe(struct virtio_device *vdev)
 		vi->curr_queue_pairs = num_online_cpus();
 	vi->max_queue_pairs = max_queue_pairs;
 
+	virtnet_init_settings(dev);
+	virtnet_update_settings(vi);
+
 	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
 	err = init_vqs(vi);
 	if (err)
@@ -3380,8 +3416,6 @@ static int virtnet_probe(struct virtio_device *vdev)
 	netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs);
 	netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs);
 
-	virtnet_init_settings(dev);
-
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
 		vi->failover = net_failover_create(vi->dev);
 		if (IS_ERR(vi->failover)) {
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 25/26] virtio_net: set the default max ring size by find_vqs()
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Use virtio_find_vqs_ctx_size() to specify the maximum ring size of tx,
rx at the same time.

                         | rx/tx ring size
-------------------------------------------
speed == UNKNOWN or < 10G| 1024
speed < 40G              | 4096
speed >= 40G             | 8192

Call virtnet_update_settings() once before calling init_vqs() to update
speed.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 42 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index ffff323dcef0..f1bdc6ce21c3 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2977,6 +2977,29 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
 		   (unsigned int)GOOD_PACKET_LEN);
 }
 
+static void virtnet_config_sizes(struct virtnet_info *vi, u32 *sizes)
+{
+	u32 i, rx_size, tx_size;
+
+	if (vi->speed == SPEED_UNKNOWN || vi->speed < SPEED_10000) {
+		rx_size = 1024;
+		tx_size = 1024;
+
+	} else if (vi->speed < SPEED_40000) {
+		rx_size = 1024 * 4;
+		tx_size = 1024 * 4;
+
+	} else {
+		rx_size = 1024 * 8;
+		tx_size = 1024 * 8;
+	}
+
+	for (i = 0; i < vi->max_queue_pairs; i++) {
+		sizes[rxq2vq(i)] = rx_size;
+		sizes[txq2vq(i)] = tx_size;
+	}
+}
+
 static int virtnet_find_vqs(struct virtnet_info *vi)
 {
 	vq_callback_t **callbacks;
@@ -2984,6 +3007,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 	int ret = -ENOMEM;
 	int i, total_vqs;
 	const char **names;
+	u32 *sizes;
 	bool *ctx;
 
 	/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
@@ -3011,10 +3035,15 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 		ctx = NULL;
 	}
 
+	sizes = kmalloc_array(total_vqs, sizeof(*sizes), GFP_KERNEL);
+	if (!sizes)
+		goto err_sizes;
+
 	/* Parameters for control virtqueue, if any */
 	if (vi->has_cvq) {
 		callbacks[total_vqs - 1] = NULL;
 		names[total_vqs - 1] = "control";
+		sizes[total_vqs - 1] = 0;
 	}
 
 	/* Allocate/initialize parameters for send/receive virtqueues */
@@ -3029,8 +3058,10 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 			ctx[rxq2vq(i)] = true;
 	}
 
-	ret = virtio_find_vqs_ctx(vi->vdev, total_vqs, vqs, callbacks,
-				  names, ctx, NULL);
+	virtnet_config_sizes(vi, sizes);
+
+	ret = virtio_find_vqs_ctx_size(vi->vdev, total_vqs, vqs, callbacks,
+				       names, ctx, NULL, sizes);
 	if (ret)
 		goto err_find;
 
@@ -3050,6 +3081,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 
 
 err_find:
+	kfree(sizes);
+err_sizes:
 	kfree(ctx);
 err_ctx:
 	kfree(names);
@@ -3368,6 +3401,9 @@ static int virtnet_probe(struct virtio_device *vdev)
 		vi->curr_queue_pairs = num_online_cpus();
 	vi->max_queue_pairs = max_queue_pairs;
 
+	virtnet_init_settings(dev);
+	virtnet_update_settings(vi);
+
 	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
 	err = init_vqs(vi);
 	if (err)
@@ -3380,8 +3416,6 @@ static int virtnet_probe(struct virtio_device *vdev)
 	netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs);
 	netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs);
 
-	virtnet_init_settings(dev);
-
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
 		vi->failover = net_failover_create(vi->dev);
 		if (IS_ERR(vi->failover)) {
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 26/26] virtio_net: support set_ringparam
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-08 12:35   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	platform-driver-x86, Mathieu Poirier, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

Support set_ringparam based on virtio queue reset.

The rx,tx_pending required to be passed must be power of 2.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 47 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f1bdc6ce21c3..1fa2d632a994 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2290,6 +2290,52 @@ static void virtnet_get_ringparam(struct net_device *dev,
 	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
 }
 
+static int virtnet_set_ringparam(struct net_device *dev,
+				 struct ethtool_ringparam *ring,
+				 struct kernel_ethtool_ringparam *kernel_ring,
+				 struct netlink_ext_ack *extack)
+{
+	struct virtnet_info *vi = netdev_priv(dev);
+	u32 rx_pending, tx_pending;
+	struct receive_queue *rq;
+	struct send_queue *sq;
+	int i, err;
+
+	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
+		return -EINVAL;
+
+	rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
+	tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
+
+	if (ring->rx_pending == rx_pending &&
+	    ring->tx_pending == tx_pending)
+		return 0;
+
+	if (ring->rx_pending > virtqueue_get_vring_max_size(vi->rq[0].vq))
+		return -EINVAL;
+
+	if (ring->tx_pending > virtqueue_get_vring_max_size(vi->sq[0].vq))
+		return -EINVAL;
+
+	for (i = 0; i < vi->max_queue_pairs; i++) {
+		rq = vi->rq + i;
+		sq = vi->sq + i;
+
+		if (ring->tx_pending != tx_pending) {
+			err = virtnet_tx_vq_reset(vi, sq, ring->tx_pending);
+			if (err)
+				return err;
+		}
+
+		if (ring->rx_pending != rx_pending) {
+			err = virtnet_rx_vq_reset(vi, rq, ring->rx_pending);
+			if (err)
+				return err;
+		}
+	}
+
+	return 0;
+}
 
 static void virtnet_get_drvinfo(struct net_device *dev,
 				struct ethtool_drvinfo *info)
@@ -2523,6 +2569,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
 	.get_drvinfo = virtnet_get_drvinfo,
 	.get_link = ethtool_op_get_link,
 	.get_ringparam = virtnet_get_ringparam,
+	.set_ringparam = virtnet_set_ringparam,
 	.get_strings = virtnet_get_strings,
 	.get_sset_count = virtnet_get_sset_count,
 	.get_ethtool_stats = virtnet_get_ethtool_stats,
-- 
2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 26/26] virtio_net: support set_ringparam
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Support set_ringparam based on virtio queue reset.

The rx,tx_pending required to be passed must be power of 2.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 47 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f1bdc6ce21c3..1fa2d632a994 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2290,6 +2290,52 @@ static void virtnet_get_ringparam(struct net_device *dev,
 	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
 }
 
+static int virtnet_set_ringparam(struct net_device *dev,
+				 struct ethtool_ringparam *ring,
+				 struct kernel_ethtool_ringparam *kernel_ring,
+				 struct netlink_ext_ack *extack)
+{
+	struct virtnet_info *vi = netdev_priv(dev);
+	u32 rx_pending, tx_pending;
+	struct receive_queue *rq;
+	struct send_queue *sq;
+	int i, err;
+
+	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
+		return -EINVAL;
+
+	rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
+	tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
+
+	if (ring->rx_pending == rx_pending &&
+	    ring->tx_pending == tx_pending)
+		return 0;
+
+	if (ring->rx_pending > virtqueue_get_vring_max_size(vi->rq[0].vq))
+		return -EINVAL;
+
+	if (ring->tx_pending > virtqueue_get_vring_max_size(vi->sq[0].vq))
+		return -EINVAL;
+
+	for (i = 0; i < vi->max_queue_pairs; i++) {
+		rq = vi->rq + i;
+		sq = vi->sq + i;
+
+		if (ring->tx_pending != tx_pending) {
+			err = virtnet_tx_vq_reset(vi, sq, ring->tx_pending);
+			if (err)
+				return err;
+		}
+
+		if (ring->rx_pending != rx_pending) {
+			err = virtnet_rx_vq_reset(vi, rq, ring->rx_pending);
+			if (err)
+				return err;
+		}
+	}
+
+	return 0;
+}
 
 static void virtnet_get_drvinfo(struct net_device *dev,
 				struct ethtool_drvinfo *info)
@@ -2523,6 +2569,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
 	.get_drvinfo = virtnet_get_drvinfo,
 	.get_link = ethtool_op_get_link,
 	.get_ringparam = virtnet_get_ringparam,
+	.set_ringparam = virtnet_set_ringparam,
 	.get_strings = virtnet_get_strings,
 	.get_sset_count = virtnet_get_sset_count,
 	.get_ethtool_stats = virtnet_get_ethtool_stats,
-- 
2.31.0


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* [PATCH v7 26/26] virtio_net: support set_ringparam
@ 2022-03-08 12:35   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-08 12:35 UTC (permalink / raw)
  To: virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, Xuan Zhuo,
	linux-um, platform-driver-x86, linux-remoteproc, linux-s390, kvm,
	bpf

Support set_ringparam based on virtio queue reset.

The rx,tx_pending required to be passed must be power of 2.

Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
---
 drivers/net/virtio_net.c | 47 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f1bdc6ce21c3..1fa2d632a994 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2290,6 +2290,52 @@ static void virtnet_get_ringparam(struct net_device *dev,
 	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
 }
 
+static int virtnet_set_ringparam(struct net_device *dev,
+				 struct ethtool_ringparam *ring,
+				 struct kernel_ethtool_ringparam *kernel_ring,
+				 struct netlink_ext_ack *extack)
+{
+	struct virtnet_info *vi = netdev_priv(dev);
+	u32 rx_pending, tx_pending;
+	struct receive_queue *rq;
+	struct send_queue *sq;
+	int i, err;
+
+	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
+		return -EINVAL;
+
+	rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
+	tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
+
+	if (ring->rx_pending == rx_pending &&
+	    ring->tx_pending == tx_pending)
+		return 0;
+
+	if (ring->rx_pending > virtqueue_get_vring_max_size(vi->rq[0].vq))
+		return -EINVAL;
+
+	if (ring->tx_pending > virtqueue_get_vring_max_size(vi->sq[0].vq))
+		return -EINVAL;
+
+	for (i = 0; i < vi->max_queue_pairs; i++) {
+		rq = vi->rq + i;
+		sq = vi->sq + i;
+
+		if (ring->tx_pending != tx_pending) {
+			err = virtnet_tx_vq_reset(vi, sq, ring->tx_pending);
+			if (err)
+				return err;
+		}
+
+		if (ring->rx_pending != rx_pending) {
+			err = virtnet_rx_vq_reset(vi, rq, ring->rx_pending);
+			if (err)
+				return err;
+		}
+	}
+
+	return 0;
+}
 
 static void virtnet_get_drvinfo(struct net_device *dev,
 				struct ethtool_drvinfo *info)
@@ -2523,6 +2569,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
 	.get_drvinfo = virtnet_get_drvinfo,
 	.get_link = ethtool_op_get_link,
 	.get_ringparam = virtnet_get_ringparam,
+	.set_ringparam = virtnet_set_ringparam,
 	.get_strings = virtnet_get_strings,
 	.get_sset_count = virtnet_get_sset_count,
 	.get_ethtool_stats = virtnet_get_ethtool_stats,
-- 
2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply related	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 18/26] virtio: find_vqs() add arg sizes
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-08 13:13     ` Hans de Goede
  -1 siblings, 0 replies; 218+ messages in thread
From: Hans de Goede @ 2022-03-08 13:13 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf

Hi,

On 3/8/22 13:35, Xuan Zhuo wrote:
> find_vqs() adds a new parameter sizes to specify the size of each vq
> vring.
> 
> 0 means use the maximum size supported by the backend.
> 
> In the split scenario, the meaning of size is the largest size, because
> it may be limited by memory, the virtio core will try a smaller size.
> And the size is power of 2.
> 
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>  arch/um/drivers/virtio_uml.c             |  2 +-
>  drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
>  drivers/remoteproc/remoteproc_virtio.c   |  2 +-
>  drivers/s390/virtio/virtio_ccw.c         |  2 +-
>  drivers/virtio/virtio_mmio.c             |  2 +-
>  drivers/virtio/virtio_pci_common.c       |  2 +-
>  drivers/virtio/virtio_pci_common.h       |  2 +-
>  drivers/virtio/virtio_pci_modern.c       |  5 +++--
>  drivers/virtio/virtio_vdpa.c             |  2 +-
>  include/linux/virtio_config.h            | 11 +++++++----
>  10 files changed, 19 insertions(+), 14 deletions(-)

I assume this will be merged through the virtio tree, here
is my ack for merging the drivers/platform/mellanox/ part
through the virtio tree:

Acked-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans


> 
> diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> index ba562d68dc04..055b91ccbe8a 100644
> --- a/arch/um/drivers/virtio_uml.c
> +++ b/arch/um/drivers/virtio_uml.c
> @@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
>  static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		       const char * const names[], const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
>  	int i, queue_idx = 0, rc;
> diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
> index 38800e86ed8a..aea7aa218b22 100644
> --- a/drivers/platform/mellanox/mlxbf-tmfifo.c
> +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
> @@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
>  					vq_callback_t *callbacks[],
>  					const char * const names[],
>  					const bool *ctx,
> -					struct irq_affinity *desc)
> +					struct irq_affinity *desc,
> +					u32 sizes[])
>  {
>  	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
>  	struct mlxbf_tmfifo_vring *vring;
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index 70ab496d0431..3a167bec5b09 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
>  				 vq_callback_t *callbacks[],
>  				 const char * const names[],
>  				 const bool * ctx,
> -				 struct irq_affinity *desc)
> +				 struct irq_affinity *desc, u32 sizes[])
>  {
>  	int i, ret, queue_idx = 0;
>  
> diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
> index d35e7a3f7067..b74e08c71534 100644
> --- a/drivers/s390/virtio/virtio_ccw.c
> +++ b/drivers/s390/virtio/virtio_ccw.c
> @@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			       vq_callback_t *callbacks[],
>  			       const char * const names[],
>  			       const bool *ctx,
> -			       struct irq_affinity *desc)
> +			       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
>  	unsigned long *indicatorp = NULL;
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index a41abc8051b9..55d575f6ef2d 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		       vq_callback_t *callbacks[],
>  		       const char * const names[],
>  		       const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
>  	int irq = platform_get_irq(vm_dev->pdev, 0);
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 863d3a8a0956..8e8fa7e5ad80 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
>  int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc)
> +		struct irq_affinity *desc, u32 sizes[])
>  {
>  	int err;
>  
> diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> index 23f6c5c678d5..9dbf1d555dff 100644
> --- a/drivers/virtio/virtio_pci_common.h
> +++ b/drivers/virtio/virtio_pci_common.h
> @@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
>  int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc);
> +		struct irq_affinity *desc, u32 sizes[]);
>  const char *vp_bus_name(struct virtio_device *vdev);
>  
>  /* Setup the affinity for a virtqueue:
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 3c67d3607802..342795175c29 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			      struct virtqueue *vqs[],
>  			      vq_callback_t *callbacks[],
>  			      const char * const names[], const bool *ctx,
> -			      struct irq_affinity *desc)
> +			      struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
>  	struct virtqueue *vq;
> -	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
> +	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
> +			     sizes);
>  
>  	if (rc)
>  		return rc;
> diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
> index 7767a7f0119b..ee08d01ee8b1 100644
> --- a/drivers/virtio/virtio_vdpa.c
> +++ b/drivers/virtio/virtio_vdpa.c
> @@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  				vq_callback_t *callbacks[],
>  				const char * const names[],
>  				const bool *ctx,
> -				struct irq_affinity *desc)
> +				struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
>  	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 0b81fbe17c85..5157524d8036 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -57,6 +57,7 @@ struct virtio_shm_region {
>   *		include a NULL entry for vqs that do not need a callback
>   *	names: array of virtqueue names (mainly for debugging)
>   *		include a NULL entry for vqs unused by driver
> + *	sizes: array of virtqueue sizes
>   *	Returns 0 on success or error status
>   * @del_vqs: free virtqueues found by find_vqs().
>   * @get_features: get the array of feature bits for this device.
> @@ -98,7 +99,8 @@ struct virtio_config_ops {
>  	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
>  			struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  			const char * const names[], const bool *ctx,
> -			struct irq_affinity *desc);
> +			struct irq_affinity *desc,
> +			u32 sizes[]);
>  	void (*del_vqs)(struct virtio_device *);
>  	u64 (*get_features)(struct virtio_device *vdev);
>  	int (*finalize_features)(struct virtio_device *vdev);
> @@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
>  	const char *names[] = { n };
>  	struct virtqueue *vq;
>  	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
> -					 NULL);
> +					 NULL, NULL);
>  	if (err < 0)
>  		return ERR_PTR(err);
>  	return vq;
> @@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			const char * const names[],
>  			struct irq_affinity *desc)
>  {
> -	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
> +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
> +				      desc, NULL);
>  }
>  
>  static inline
> @@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>  			struct irq_affinity *desc)
>  {
>  	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> -				      desc);
> +				      desc, NULL);
>  }
>  
>  /**


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 18/26] virtio: find_vqs() add arg sizes
@ 2022-03-08 13:13     ` Hans de Goede
  0 siblings, 0 replies; 218+ messages in thread
From: Hans de Goede @ 2022-03-08 13:13 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, kvm, platform-driver-x86, Mathieu Poirier,
	Cornelia Huck, Sven Schnelle, bpf, David S. Miller

Hi,

On 3/8/22 13:35, Xuan Zhuo wrote:
> find_vqs() adds a new parameter sizes to specify the size of each vq
> vring.
> 
> 0 means use the maximum size supported by the backend.
> 
> In the split scenario, the meaning of size is the largest size, because
> it may be limited by memory, the virtio core will try a smaller size.
> And the size is power of 2.
> 
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>  arch/um/drivers/virtio_uml.c             |  2 +-
>  drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
>  drivers/remoteproc/remoteproc_virtio.c   |  2 +-
>  drivers/s390/virtio/virtio_ccw.c         |  2 +-
>  drivers/virtio/virtio_mmio.c             |  2 +-
>  drivers/virtio/virtio_pci_common.c       |  2 +-
>  drivers/virtio/virtio_pci_common.h       |  2 +-
>  drivers/virtio/virtio_pci_modern.c       |  5 +++--
>  drivers/virtio/virtio_vdpa.c             |  2 +-
>  include/linux/virtio_config.h            | 11 +++++++----
>  10 files changed, 19 insertions(+), 14 deletions(-)

I assume this will be merged through the virtio tree, here
is my ack for merging the drivers/platform/mellanox/ part
through the virtio tree:

Acked-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans


> 
> diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> index ba562d68dc04..055b91ccbe8a 100644
> --- a/arch/um/drivers/virtio_uml.c
> +++ b/arch/um/drivers/virtio_uml.c
> @@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
>  static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		       const char * const names[], const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
>  	int i, queue_idx = 0, rc;
> diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
> index 38800e86ed8a..aea7aa218b22 100644
> --- a/drivers/platform/mellanox/mlxbf-tmfifo.c
> +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
> @@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
>  					vq_callback_t *callbacks[],
>  					const char * const names[],
>  					const bool *ctx,
> -					struct irq_affinity *desc)
> +					struct irq_affinity *desc,
> +					u32 sizes[])
>  {
>  	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
>  	struct mlxbf_tmfifo_vring *vring;
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index 70ab496d0431..3a167bec5b09 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
>  				 vq_callback_t *callbacks[],
>  				 const char * const names[],
>  				 const bool * ctx,
> -				 struct irq_affinity *desc)
> +				 struct irq_affinity *desc, u32 sizes[])
>  {
>  	int i, ret, queue_idx = 0;
>  
> diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
> index d35e7a3f7067..b74e08c71534 100644
> --- a/drivers/s390/virtio/virtio_ccw.c
> +++ b/drivers/s390/virtio/virtio_ccw.c
> @@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			       vq_callback_t *callbacks[],
>  			       const char * const names[],
>  			       const bool *ctx,
> -			       struct irq_affinity *desc)
> +			       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
>  	unsigned long *indicatorp = NULL;
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index a41abc8051b9..55d575f6ef2d 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		       vq_callback_t *callbacks[],
>  		       const char * const names[],
>  		       const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
>  	int irq = platform_get_irq(vm_dev->pdev, 0);
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 863d3a8a0956..8e8fa7e5ad80 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
>  int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc)
> +		struct irq_affinity *desc, u32 sizes[])
>  {
>  	int err;
>  
> diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> index 23f6c5c678d5..9dbf1d555dff 100644
> --- a/drivers/virtio/virtio_pci_common.h
> +++ b/drivers/virtio/virtio_pci_common.h
> @@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
>  int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc);
> +		struct irq_affinity *desc, u32 sizes[]);
>  const char *vp_bus_name(struct virtio_device *vdev);
>  
>  /* Setup the affinity for a virtqueue:
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 3c67d3607802..342795175c29 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			      struct virtqueue *vqs[],
>  			      vq_callback_t *callbacks[],
>  			      const char * const names[], const bool *ctx,
> -			      struct irq_affinity *desc)
> +			      struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
>  	struct virtqueue *vq;
> -	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
> +	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
> +			     sizes);
>  
>  	if (rc)
>  		return rc;
> diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
> index 7767a7f0119b..ee08d01ee8b1 100644
> --- a/drivers/virtio/virtio_vdpa.c
> +++ b/drivers/virtio/virtio_vdpa.c
> @@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  				vq_callback_t *callbacks[],
>  				const char * const names[],
>  				const bool *ctx,
> -				struct irq_affinity *desc)
> +				struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
>  	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 0b81fbe17c85..5157524d8036 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -57,6 +57,7 @@ struct virtio_shm_region {
>   *		include a NULL entry for vqs that do not need a callback
>   *	names: array of virtqueue names (mainly for debugging)
>   *		include a NULL entry for vqs unused by driver
> + *	sizes: array of virtqueue sizes
>   *	Returns 0 on success or error status
>   * @del_vqs: free virtqueues found by find_vqs().
>   * @get_features: get the array of feature bits for this device.
> @@ -98,7 +99,8 @@ struct virtio_config_ops {
>  	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
>  			struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  			const char * const names[], const bool *ctx,
> -			struct irq_affinity *desc);
> +			struct irq_affinity *desc,
> +			u32 sizes[]);
>  	void (*del_vqs)(struct virtio_device *);
>  	u64 (*get_features)(struct virtio_device *vdev);
>  	int (*finalize_features)(struct virtio_device *vdev);
> @@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
>  	const char *names[] = { n };
>  	struct virtqueue *vq;
>  	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
> -					 NULL);
> +					 NULL, NULL);
>  	if (err < 0)
>  		return ERR_PTR(err);
>  	return vq;
> @@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			const char * const names[],
>  			struct irq_affinity *desc)
>  {
> -	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
> +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
> +				      desc, NULL);
>  }
>  
>  static inline
> @@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>  			struct irq_affinity *desc)
>  {
>  	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> -				      desc);
> +				      desc, NULL);
>  }
>  
>  /**

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 18/26] virtio: find_vqs() add arg sizes
@ 2022-03-08 13:13     ` Hans de Goede
  0 siblings, 0 replies; 218+ messages in thread
From: Hans de Goede @ 2022-03-08 13:13 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	Jason Wang, David S. Miller, Jakub Kicinski, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf

Hi,

On 3/8/22 13:35, Xuan Zhuo wrote:
> find_vqs() adds a new parameter sizes to specify the size of each vq
> vring.
> 
> 0 means use the maximum size supported by the backend.
> 
> In the split scenario, the meaning of size is the largest size, because
> it may be limited by memory, the virtio core will try a smaller size.
> And the size is power of 2.
> 
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>  arch/um/drivers/virtio_uml.c             |  2 +-
>  drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
>  drivers/remoteproc/remoteproc_virtio.c   |  2 +-
>  drivers/s390/virtio/virtio_ccw.c         |  2 +-
>  drivers/virtio/virtio_mmio.c             |  2 +-
>  drivers/virtio/virtio_pci_common.c       |  2 +-
>  drivers/virtio/virtio_pci_common.h       |  2 +-
>  drivers/virtio/virtio_pci_modern.c       |  5 +++--
>  drivers/virtio/virtio_vdpa.c             |  2 +-
>  include/linux/virtio_config.h            | 11 +++++++----
>  10 files changed, 19 insertions(+), 14 deletions(-)

I assume this will be merged through the virtio tree, here
is my ack for merging the drivers/platform/mellanox/ part
through the virtio tree:

Acked-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans


> 
> diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> index ba562d68dc04..055b91ccbe8a 100644
> --- a/arch/um/drivers/virtio_uml.c
> +++ b/arch/um/drivers/virtio_uml.c
> @@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
>  static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		       const char * const names[], const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
>  	int i, queue_idx = 0, rc;
> diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
> index 38800e86ed8a..aea7aa218b22 100644
> --- a/drivers/platform/mellanox/mlxbf-tmfifo.c
> +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
> @@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
>  					vq_callback_t *callbacks[],
>  					const char * const names[],
>  					const bool *ctx,
> -					struct irq_affinity *desc)
> +					struct irq_affinity *desc,
> +					u32 sizes[])
>  {
>  	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
>  	struct mlxbf_tmfifo_vring *vring;
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index 70ab496d0431..3a167bec5b09 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
>  				 vq_callback_t *callbacks[],
>  				 const char * const names[],
>  				 const bool * ctx,
> -				 struct irq_affinity *desc)
> +				 struct irq_affinity *desc, u32 sizes[])
>  {
>  	int i, ret, queue_idx = 0;
>  
> diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
> index d35e7a3f7067..b74e08c71534 100644
> --- a/drivers/s390/virtio/virtio_ccw.c
> +++ b/drivers/s390/virtio/virtio_ccw.c
> @@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			       vq_callback_t *callbacks[],
>  			       const char * const names[],
>  			       const bool *ctx,
> -			       struct irq_affinity *desc)
> +			       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
>  	unsigned long *indicatorp = NULL;
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index a41abc8051b9..55d575f6ef2d 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		       vq_callback_t *callbacks[],
>  		       const char * const names[],
>  		       const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
>  	int irq = platform_get_irq(vm_dev->pdev, 0);
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 863d3a8a0956..8e8fa7e5ad80 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
>  int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc)
> +		struct irq_affinity *desc, u32 sizes[])
>  {
>  	int err;
>  
> diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> index 23f6c5c678d5..9dbf1d555dff 100644
> --- a/drivers/virtio/virtio_pci_common.h
> +++ b/drivers/virtio/virtio_pci_common.h
> @@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
>  int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc);
> +		struct irq_affinity *desc, u32 sizes[]);
>  const char *vp_bus_name(struct virtio_device *vdev);
>  
>  /* Setup the affinity for a virtqueue:
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 3c67d3607802..342795175c29 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			      struct virtqueue *vqs[],
>  			      vq_callback_t *callbacks[],
>  			      const char * const names[], const bool *ctx,
> -			      struct irq_affinity *desc)
> +			      struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
>  	struct virtqueue *vq;
> -	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
> +	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
> +			     sizes);
>  
>  	if (rc)
>  		return rc;
> diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
> index 7767a7f0119b..ee08d01ee8b1 100644
> --- a/drivers/virtio/virtio_vdpa.c
> +++ b/drivers/virtio/virtio_vdpa.c
> @@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  				vq_callback_t *callbacks[],
>  				const char * const names[],
>  				const bool *ctx,
> -				struct irq_affinity *desc)
> +				struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
>  	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 0b81fbe17c85..5157524d8036 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -57,6 +57,7 @@ struct virtio_shm_region {
>   *		include a NULL entry for vqs that do not need a callback
>   *	names: array of virtqueue names (mainly for debugging)
>   *		include a NULL entry for vqs unused by driver
> + *	sizes: array of virtqueue sizes
>   *	Returns 0 on success or error status
>   * @del_vqs: free virtqueues found by find_vqs().
>   * @get_features: get the array of feature bits for this device.
> @@ -98,7 +99,8 @@ struct virtio_config_ops {
>  	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
>  			struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  			const char * const names[], const bool *ctx,
> -			struct irq_affinity *desc);
> +			struct irq_affinity *desc,
> +			u32 sizes[]);
>  	void (*del_vqs)(struct virtio_device *);
>  	u64 (*get_features)(struct virtio_device *vdev);
>  	int (*finalize_features)(struct virtio_device *vdev);
> @@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
>  	const char *names[] = { n };
>  	struct virtqueue *vq;
>  	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
> -					 NULL);
> +					 NULL, NULL);
>  	if (err < 0)
>  		return ERR_PTR(err);
>  	return vq;
> @@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			const char * const names[],
>  			struct irq_affinity *desc)
>  {
> -	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
> +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
> +				      desc, NULL);
>  }
>  
>  static inline
> @@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>  			struct irq_affinity *desc)
>  {
>  	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> -				      desc);
> +				      desc, NULL);
>  }
>  
>  /**


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 00/26] virtio pci support VIRTIO_F_RING_RESET
  2022-03-08 12:34 ` Xuan Zhuo
  (?)
@ 2022-03-09  4:45   ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  4:45 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> The virtio spec already supports the virtio queue reset function. This patch set
> is to add this function to the kernel. The relevant virtio spec information is
> here:
>
>      https://github.com/oasis-tcs/virtio-spec/issues/124
>
> Also regarding MMIO support for queue reset, I plan to support it after this
> patch is passed.
>
> Performing reset on a queue is divided into four steps:
>       1. virtio_reset_vq()              - notify the device to reset the queue
>       2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>       3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>       4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>
> The first part 1-17 of this patch set implements virtio pci's support and API
> for queue reset. The latter part is to make virtio-net support set_ringparam. Do
> these things for this feature:
>
>        1. virtio-net support rx,tx reset
>        2. find_vqs() support to special the max size of each vq
>        3. virtio-net support set_ringparam
>
> #1 -#3 :       prepare
> #4 -#12:       virtio ring support reset vring of the vq
> #13-#14:       add helper
> #15-#17:       virtio pci support reset queue and re-enable
> #18-#21:       find_vqs() support sizes to special the max size of each vq
> #23-#24:       virtio-net support rx, tx reset
> #22, #25, #26: virtio-net support set ringparam
>
> Test environment:
>      Host: 4.19.91
>      Qemu: QEMU emulator version 6.2.50 (with vq reset support)
>      Test Cmd:  ethtool -G eth1 rx $1 tx $2; ethtool -g eth1
>
>      The default is split mode, modify Qemu virtio-net to add PACKED feature to test
>      packed mode.
>
>
> Please review. Thanks.
>
> v7:
>    1. fix #6 subject typo
>    2. fix #6 ring_size_in_bytes is uninitialized
>    3. check by: make W=12
>
> v6:
>    1. virtio_pci: use synchronize_irq(irq) to sync the irq callbacks
>    2. Introduce virtqueue_reset_vring() to implement the reset of vring during
>       the reset process. May use the old vring if num of the vq not change.
>    3. find_vqs() support sizes to special the max size of each vq
>
> v5:
>    1. add virtio-net support set_ringparam
>
> v4:
>    1. just the code of virtio, without virtio-net
>    2. Performing reset on a queue is divided into these steps:
>      1. reset_vq: reset one vq
>      2. recycle the buffer from vq by virtqueue_detach_unused_buf()
>      3. release the ring of the vq by vring_release_virtqueue()
>      4. enable_reset_vq: re-enable the reset queue
>    3. Simplify the parameters of enable_reset_vq()
>    4. add container structures for virtio_pci_common_cfg
>
> v3:
>    1. keep vq, irq unreleased


The series became kind of huge.

I'd suggest to split it into two series.

1) refactoring of the virtio_ring to prepare for the resize
2) the reset support + virtio-net support

Thanks


>
> *** BLURB HERE ***
>
> Xuan Zhuo (26):
>    virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
>    virtio: queue_reset: add VIRTIO_F_RING_RESET
>    virtio: add helper virtqueue_get_vring_max_size()
>    virtio_ring: split: extract the logic of creating vring
>    virtio_ring: split: extract the logic of init vq and attach vring
>    virtio_ring: packed: extract the logic of creating vring
>    virtio_ring: packed: extract the logic of init vq and attach vring
>    virtio_ring: extract the logic of freeing vring
>    virtio_ring: split: implement virtqueue_reset_vring_split()
>    virtio_ring: packed: implement virtqueue_reset_vring_packed()
>    virtio_ring: introduce virtqueue_reset_vring()
>    virtio_ring: update the document of the virtqueue_detach_unused_buf
>      for queue reset
>    virtio: queue_reset: struct virtio_config_ops add callbacks for
>      queue_reset
>    virtio: add helper for queue reset
>    virtio_pci: queue_reset: update struct virtio_pci_common_cfg and
>      option functions
>    virtio_pci: queue_reset: extract the logic of active vq for modern pci
>    virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
>    virtio: find_vqs() add arg sizes
>    virtio_pci: support the arg sizes of find_vqs()
>    virtio_mmio: support the arg sizes of find_vqs()
>    virtio: add helper virtio_find_vqs_ctx_size()
>    virtio_net: get ringparam by virtqueue_get_vring_max_size()
>    virtio_net: split free_unused_bufs()
>    virtio_net: support rx/tx queue reset
>    virtio_net: set the default max ring size by find_vqs()
>    virtio_net: support set_ringparam
>
>   arch/um/drivers/virtio_uml.c             |   2 +-
>   drivers/net/virtio_net.c                 | 257 ++++++++--
>   drivers/platform/mellanox/mlxbf-tmfifo.c |   3 +-
>   drivers/remoteproc/remoteproc_virtio.c   |   2 +-
>   drivers/s390/virtio/virtio_ccw.c         |   2 +-
>   drivers/virtio/virtio_mmio.c             |  12 +-
>   drivers/virtio/virtio_pci_common.c       |  28 +-
>   drivers/virtio/virtio_pci_common.h       |   3 +-
>   drivers/virtio/virtio_pci_legacy.c       |   8 +-
>   drivers/virtio/virtio_pci_modern.c       | 146 +++++-
>   drivers/virtio/virtio_pci_modern_dev.c   |  36 ++
>   drivers/virtio/virtio_ring.c             | 584 +++++++++++++++++------
>   drivers/virtio/virtio_vdpa.c             |   2 +-
>   include/linux/virtio.h                   |  12 +
>   include/linux/virtio_config.h            |  74 ++-
>   include/linux/virtio_pci_modern.h        |   2 +
>   include/uapi/linux/virtio_config.h       |   7 +-
>   include/uapi/linux/virtio_pci.h          |  14 +
>   18 files changed, 979 insertions(+), 215 deletions(-)
>
> --
> 2.31.0
>


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 00/26] virtio pci support VIRTIO_F_RING_RESET
@ 2022-03-09  4:45   ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  4:45 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> The virtio spec already supports the virtio queue reset function. This patch set
> is to add this function to the kernel. The relevant virtio spec information is
> here:
>
>      https://github.com/oasis-tcs/virtio-spec/issues/124
>
> Also regarding MMIO support for queue reset, I plan to support it after this
> patch is passed.
>
> Performing reset on a queue is divided into four steps:
>       1. virtio_reset_vq()              - notify the device to reset the queue
>       2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>       3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>       4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>
> The first part 1-17 of this patch set implements virtio pci's support and API
> for queue reset. The latter part is to make virtio-net support set_ringparam. Do
> these things for this feature:
>
>        1. virtio-net support rx,tx reset
>        2. find_vqs() support to special the max size of each vq
>        3. virtio-net support set_ringparam
>
> #1 -#3 :       prepare
> #4 -#12:       virtio ring support reset vring of the vq
> #13-#14:       add helper
> #15-#17:       virtio pci support reset queue and re-enable
> #18-#21:       find_vqs() support sizes to special the max size of each vq
> #23-#24:       virtio-net support rx, tx reset
> #22, #25, #26: virtio-net support set ringparam
>
> Test environment:
>      Host: 4.19.91
>      Qemu: QEMU emulator version 6.2.50 (with vq reset support)
>      Test Cmd:  ethtool -G eth1 rx $1 tx $2; ethtool -g eth1
>
>      The default is split mode, modify Qemu virtio-net to add PACKED feature to test
>      packed mode.
>
>
> Please review. Thanks.
>
> v7:
>    1. fix #6 subject typo
>    2. fix #6 ring_size_in_bytes is uninitialized
>    3. check by: make W=12
>
> v6:
>    1. virtio_pci: use synchronize_irq(irq) to sync the irq callbacks
>    2. Introduce virtqueue_reset_vring() to implement the reset of vring during
>       the reset process. May use the old vring if num of the vq not change.
>    3. find_vqs() support sizes to special the max size of each vq
>
> v5:
>    1. add virtio-net support set_ringparam
>
> v4:
>    1. just the code of virtio, without virtio-net
>    2. Performing reset on a queue is divided into these steps:
>      1. reset_vq: reset one vq
>      2. recycle the buffer from vq by virtqueue_detach_unused_buf()
>      3. release the ring of the vq by vring_release_virtqueue()
>      4. enable_reset_vq: re-enable the reset queue
>    3. Simplify the parameters of enable_reset_vq()
>    4. add container structures for virtio_pci_common_cfg
>
> v3:
>    1. keep vq, irq unreleased


The series became kind of huge.

I'd suggest to split it into two series.

1) refactoring of the virtio_ring to prepare for the resize
2) the reset support + virtio-net support

Thanks


>
> *** BLURB HERE ***
>
> Xuan Zhuo (26):
>    virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
>    virtio: queue_reset: add VIRTIO_F_RING_RESET
>    virtio: add helper virtqueue_get_vring_max_size()
>    virtio_ring: split: extract the logic of creating vring
>    virtio_ring: split: extract the logic of init vq and attach vring
>    virtio_ring: packed: extract the logic of creating vring
>    virtio_ring: packed: extract the logic of init vq and attach vring
>    virtio_ring: extract the logic of freeing vring
>    virtio_ring: split: implement virtqueue_reset_vring_split()
>    virtio_ring: packed: implement virtqueue_reset_vring_packed()
>    virtio_ring: introduce virtqueue_reset_vring()
>    virtio_ring: update the document of the virtqueue_detach_unused_buf
>      for queue reset
>    virtio: queue_reset: struct virtio_config_ops add callbacks for
>      queue_reset
>    virtio: add helper for queue reset
>    virtio_pci: queue_reset: update struct virtio_pci_common_cfg and
>      option functions
>    virtio_pci: queue_reset: extract the logic of active vq for modern pci
>    virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
>    virtio: find_vqs() add arg sizes
>    virtio_pci: support the arg sizes of find_vqs()
>    virtio_mmio: support the arg sizes of find_vqs()
>    virtio: add helper virtio_find_vqs_ctx_size()
>    virtio_net: get ringparam by virtqueue_get_vring_max_size()
>    virtio_net: split free_unused_bufs()
>    virtio_net: support rx/tx queue reset
>    virtio_net: set the default max ring size by find_vqs()
>    virtio_net: support set_ringparam
>
>   arch/um/drivers/virtio_uml.c             |   2 +-
>   drivers/net/virtio_net.c                 | 257 ++++++++--
>   drivers/platform/mellanox/mlxbf-tmfifo.c |   3 +-
>   drivers/remoteproc/remoteproc_virtio.c   |   2 +-
>   drivers/s390/virtio/virtio_ccw.c         |   2 +-
>   drivers/virtio/virtio_mmio.c             |  12 +-
>   drivers/virtio/virtio_pci_common.c       |  28 +-
>   drivers/virtio/virtio_pci_common.h       |   3 +-
>   drivers/virtio/virtio_pci_legacy.c       |   8 +-
>   drivers/virtio/virtio_pci_modern.c       | 146 +++++-
>   drivers/virtio/virtio_pci_modern_dev.c   |  36 ++
>   drivers/virtio/virtio_ring.c             | 584 +++++++++++++++++------
>   drivers/virtio/virtio_vdpa.c             |   2 +-
>   include/linux/virtio.h                   |  12 +
>   include/linux/virtio_config.h            |  74 ++-
>   include/linux/virtio_pci_modern.h        |   2 +
>   include/uapi/linux/virtio_config.h       |   7 +-
>   include/uapi/linux/virtio_pci.h          |  14 +
>   18 files changed, 979 insertions(+), 215 deletions(-)
>
> --
> 2.31.0
>

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 00/26] virtio pci support VIRTIO_F_RING_RESET
@ 2022-03-09  4:45   ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  4:45 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> The virtio spec already supports the virtio queue reset function. This patch set
> is to add this function to the kernel. The relevant virtio spec information is
> here:
>
>      https://github.com/oasis-tcs/virtio-spec/issues/124
>
> Also regarding MMIO support for queue reset, I plan to support it after this
> patch is passed.
>
> Performing reset on a queue is divided into four steps:
>       1. virtio_reset_vq()              - notify the device to reset the queue
>       2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>       3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>       4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>
> The first part 1-17 of this patch set implements virtio pci's support and API
> for queue reset. The latter part is to make virtio-net support set_ringparam. Do
> these things for this feature:
>
>        1. virtio-net support rx,tx reset
>        2. find_vqs() support to special the max size of each vq
>        3. virtio-net support set_ringparam
>
> #1 -#3 :       prepare
> #4 -#12:       virtio ring support reset vring of the vq
> #13-#14:       add helper
> #15-#17:       virtio pci support reset queue and re-enable
> #18-#21:       find_vqs() support sizes to special the max size of each vq
> #23-#24:       virtio-net support rx, tx reset
> #22, #25, #26: virtio-net support set ringparam
>
> Test environment:
>      Host: 4.19.91
>      Qemu: QEMU emulator version 6.2.50 (with vq reset support)
>      Test Cmd:  ethtool -G eth1 rx $1 tx $2; ethtool -g eth1
>
>      The default is split mode, modify Qemu virtio-net to add PACKED feature to test
>      packed mode.
>
>
> Please review. Thanks.
>
> v7:
>    1. fix #6 subject typo
>    2. fix #6 ring_size_in_bytes is uninitialized
>    3. check by: make W=12
>
> v6:
>    1. virtio_pci: use synchronize_irq(irq) to sync the irq callbacks
>    2. Introduce virtqueue_reset_vring() to implement the reset of vring during
>       the reset process. May use the old vring if num of the vq not change.
>    3. find_vqs() support sizes to special the max size of each vq
>
> v5:
>    1. add virtio-net support set_ringparam
>
> v4:
>    1. just the code of virtio, without virtio-net
>    2. Performing reset on a queue is divided into these steps:
>      1. reset_vq: reset one vq
>      2. recycle the buffer from vq by virtqueue_detach_unused_buf()
>      3. release the ring of the vq by vring_release_virtqueue()
>      4. enable_reset_vq: re-enable the reset queue
>    3. Simplify the parameters of enable_reset_vq()
>    4. add container structures for virtio_pci_common_cfg
>
> v3:
>    1. keep vq, irq unreleased


The series became kind of huge.

I'd suggest to split it into two series.

1) refactoring of the virtio_ring to prepare for the resize
2) the reset support + virtio-net support

Thanks


>
> *** BLURB HERE ***
>
> Xuan Zhuo (26):
>    virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
>    virtio: queue_reset: add VIRTIO_F_RING_RESET
>    virtio: add helper virtqueue_get_vring_max_size()
>    virtio_ring: split: extract the logic of creating vring
>    virtio_ring: split: extract the logic of init vq and attach vring
>    virtio_ring: packed: extract the logic of creating vring
>    virtio_ring: packed: extract the logic of init vq and attach vring
>    virtio_ring: extract the logic of freeing vring
>    virtio_ring: split: implement virtqueue_reset_vring_split()
>    virtio_ring: packed: implement virtqueue_reset_vring_packed()
>    virtio_ring: introduce virtqueue_reset_vring()
>    virtio_ring: update the document of the virtqueue_detach_unused_buf
>      for queue reset
>    virtio: queue_reset: struct virtio_config_ops add callbacks for
>      queue_reset
>    virtio: add helper for queue reset
>    virtio_pci: queue_reset: update struct virtio_pci_common_cfg and
>      option functions
>    virtio_pci: queue_reset: extract the logic of active vq for modern pci
>    virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
>    virtio: find_vqs() add arg sizes
>    virtio_pci: support the arg sizes of find_vqs()
>    virtio_mmio: support the arg sizes of find_vqs()
>    virtio: add helper virtio_find_vqs_ctx_size()
>    virtio_net: get ringparam by virtqueue_get_vring_max_size()
>    virtio_net: split free_unused_bufs()
>    virtio_net: support rx/tx queue reset
>    virtio_net: set the default max ring size by find_vqs()
>    virtio_net: support set_ringparam
>
>   arch/um/drivers/virtio_uml.c             |   2 +-
>   drivers/net/virtio_net.c                 | 257 ++++++++--
>   drivers/platform/mellanox/mlxbf-tmfifo.c |   3 +-
>   drivers/remoteproc/remoteproc_virtio.c   |   2 +-
>   drivers/s390/virtio/virtio_ccw.c         |   2 +-
>   drivers/virtio/virtio_mmio.c             |  12 +-
>   drivers/virtio/virtio_pci_common.c       |  28 +-
>   drivers/virtio/virtio_pci_common.h       |   3 +-
>   drivers/virtio/virtio_pci_legacy.c       |   8 +-
>   drivers/virtio/virtio_pci_modern.c       | 146 +++++-
>   drivers/virtio/virtio_pci_modern_dev.c   |  36 ++
>   drivers/virtio/virtio_ring.c             | 584 +++++++++++++++++------
>   drivers/virtio/virtio_vdpa.c             |   2 +-
>   include/linux/virtio.h                   |  12 +
>   include/linux/virtio_config.h            |  74 ++-
>   include/linux/virtio_pci_modern.h        |   2 +
>   include/uapi/linux/virtio_config.h       |   7 +-
>   include/uapi/linux/virtio_pci.h          |  14 +
>   18 files changed, 979 insertions(+), 215 deletions(-)
>
> --
> 2.31.0
>


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 01/26] virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
  2022-03-08 12:34   ` Xuan Zhuo
  (?)
@ 2022-03-09  4:48     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  4:48 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Add queue_notify_data in struct virtio_pci_common_cfg, which comes from
> here https://github.com/oasis-tcs/virtio-spec/issues/89
>
> For not breaks uABI, add a new struct virtio_pci_common_cfg_notify.
>
> Since I want to add queue_reset after queue_notify_data, I submitted
> this patch first.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>


Acked-by: Jason Wang <jasowang@redhat.com>


> ---
>   include/uapi/linux/virtio_pci.h | 7 +++++++
>   1 file changed, 7 insertions(+)
>
> diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
> index 3a86f36d7e3d..22bec9bd0dfc 100644
> --- a/include/uapi/linux/virtio_pci.h
> +++ b/include/uapi/linux/virtio_pci.h
> @@ -166,6 +166,13 @@ struct virtio_pci_common_cfg {
>   	__le32 queue_used_hi;		/* read-write */
>   };
>   
> +struct virtio_pci_common_cfg_notify {
> +	struct virtio_pci_common_cfg cfg;
> +
> +	__le16 queue_notify_data;	/* read-write */
> +	__le16 padding;
> +};
> +
>   /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
>   struct virtio_pci_cfg_cap {
>   	struct virtio_pci_cap cap;


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 01/26] virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
@ 2022-03-09  4:48     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  4:48 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Add queue_notify_data in struct virtio_pci_common_cfg, which comes from
> here https://github.com/oasis-tcs/virtio-spec/issues/89
>
> For not breaks uABI, add a new struct virtio_pci_common_cfg_notify.
>
> Since I want to add queue_reset after queue_notify_data, I submitted
> this patch first.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>


Acked-by: Jason Wang <jasowang@redhat.com>


> ---
>   include/uapi/linux/virtio_pci.h | 7 +++++++
>   1 file changed, 7 insertions(+)
>
> diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
> index 3a86f36d7e3d..22bec9bd0dfc 100644
> --- a/include/uapi/linux/virtio_pci.h
> +++ b/include/uapi/linux/virtio_pci.h
> @@ -166,6 +166,13 @@ struct virtio_pci_common_cfg {
>   	__le32 queue_used_hi;		/* read-write */
>   };
>   
> +struct virtio_pci_common_cfg_notify {
> +	struct virtio_pci_common_cfg cfg;
> +
> +	__le16 queue_notify_data;	/* read-write */
> +	__le16 padding;
> +};
> +
>   /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
>   struct virtio_pci_cfg_cap {
>   	struct virtio_pci_cap cap;

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 01/26] virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
@ 2022-03-09  4:48     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  4:48 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Add queue_notify_data in struct virtio_pci_common_cfg, which comes from
> here https://github.com/oasis-tcs/virtio-spec/issues/89
>
> For not breaks uABI, add a new struct virtio_pci_common_cfg_notify.
>
> Since I want to add queue_reset after queue_notify_data, I submitted
> this patch first.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>


Acked-by: Jason Wang <jasowang@redhat.com>


> ---
>   include/uapi/linux/virtio_pci.h | 7 +++++++
>   1 file changed, 7 insertions(+)
>
> diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
> index 3a86f36d7e3d..22bec9bd0dfc 100644
> --- a/include/uapi/linux/virtio_pci.h
> +++ b/include/uapi/linux/virtio_pci.h
> @@ -166,6 +166,13 @@ struct virtio_pci_common_cfg {
>   	__le32 queue_used_hi;		/* read-write */
>   };
>   
> +struct virtio_pci_common_cfg_notify {
> +	struct virtio_pci_common_cfg cfg;
> +
> +	__le16 queue_notify_data;	/* read-write */
> +	__le16 padding;
> +};
> +
>   /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
>   struct virtio_pci_cfg_cap {
>   	struct virtio_pci_cap cap;


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 02/26] virtio: queue_reset: add VIRTIO_F_RING_RESET
  2022-03-08 12:34   ` Xuan Zhuo
  (?)
@ 2022-03-09  6:14     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  6:14 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Added VIRTIO_F_RING_RESET, it came from here
> https://github.com/oasis-tcs/virtio-spec/issues/124


Nit: it's better to explain VIRTIO_F_RING_RESET a little bit here.

Other than this.

Acked-by: Jason Wang <jasowang@redhat.com>


>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/uapi/linux/virtio_config.h | 7 ++++++-
>   1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/include/uapi/linux/virtio_config.h b/include/uapi/linux/virtio_config.h
> index b5eda06f0d57..0862be802ff8 100644
> --- a/include/uapi/linux/virtio_config.h
> +++ b/include/uapi/linux/virtio_config.h
> @@ -52,7 +52,7 @@
>    * rest are per-device feature bits.
>    */
>   #define VIRTIO_TRANSPORT_F_START	28
> -#define VIRTIO_TRANSPORT_F_END		38
> +#define VIRTIO_TRANSPORT_F_END		41
>   
>   #ifndef VIRTIO_CONFIG_NO_LEGACY
>   /* Do we get callbacks when the ring is completely used, even if we've
> @@ -92,4 +92,9 @@
>    * Does the device support Single Root I/O Virtualization?
>    */
>   #define VIRTIO_F_SR_IOV			37
> +
> +/*
> + * This feature indicates that the driver can reset a queue individually.
> + */
> +#define VIRTIO_F_RING_RESET		40
>   #endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 02/26] virtio: queue_reset: add VIRTIO_F_RING_RESET
@ 2022-03-09  6:14     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  6:14 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Added VIRTIO_F_RING_RESET, it came from here
> https://github.com/oasis-tcs/virtio-spec/issues/124


Nit: it's better to explain VIRTIO_F_RING_RESET a little bit here.

Other than this.

Acked-by: Jason Wang <jasowang@redhat.com>


>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/uapi/linux/virtio_config.h | 7 ++++++-
>   1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/include/uapi/linux/virtio_config.h b/include/uapi/linux/virtio_config.h
> index b5eda06f0d57..0862be802ff8 100644
> --- a/include/uapi/linux/virtio_config.h
> +++ b/include/uapi/linux/virtio_config.h
> @@ -52,7 +52,7 @@
>    * rest are per-device feature bits.
>    */
>   #define VIRTIO_TRANSPORT_F_START	28
> -#define VIRTIO_TRANSPORT_F_END		38
> +#define VIRTIO_TRANSPORT_F_END		41
>   
>   #ifndef VIRTIO_CONFIG_NO_LEGACY
>   /* Do we get callbacks when the ring is completely used, even if we've
> @@ -92,4 +92,9 @@
>    * Does the device support Single Root I/O Virtualization?
>    */
>   #define VIRTIO_F_SR_IOV			37
> +
> +/*
> + * This feature indicates that the driver can reset a queue individually.
> + */
> +#define VIRTIO_F_RING_RESET		40
>   #endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 02/26] virtio: queue_reset: add VIRTIO_F_RING_RESET
@ 2022-03-09  6:14     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  6:14 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Added VIRTIO_F_RING_RESET, it came from here
> https://github.com/oasis-tcs/virtio-spec/issues/124


Nit: it's better to explain VIRTIO_F_RING_RESET a little bit here.

Other than this.

Acked-by: Jason Wang <jasowang@redhat.com>


>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/uapi/linux/virtio_config.h | 7 ++++++-
>   1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/include/uapi/linux/virtio_config.h b/include/uapi/linux/virtio_config.h
> index b5eda06f0d57..0862be802ff8 100644
> --- a/include/uapi/linux/virtio_config.h
> +++ b/include/uapi/linux/virtio_config.h
> @@ -52,7 +52,7 @@
>    * rest are per-device feature bits.
>    */
>   #define VIRTIO_TRANSPORT_F_START	28
> -#define VIRTIO_TRANSPORT_F_END		38
> +#define VIRTIO_TRANSPORT_F_END		41
>   
>   #ifndef VIRTIO_CONFIG_NO_LEGACY
>   /* Do we get callbacks when the ring is completely used, even if we've
> @@ -92,4 +92,9 @@
>    * Does the device support Single Root I/O Virtualization?
>    */
>   #define VIRTIO_F_SR_IOV			37
> +
> +/*
> + * This feature indicates that the driver can reset a queue individually.
> + */
> +#define VIRTIO_F_RING_RESET		40
>   #endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 03/26] virtio: add helper virtqueue_get_vring_max_size()
  2022-03-08 12:34   ` Xuan Zhuo
  (?)
@ 2022-03-09  6:16     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  6:16 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Record the maximum queue num supported by the device.
>
> virtio-net can display the maximum (supported by hardware) ring size in
> ethtool -g eth0.
>
> When the subsequent patch implements vring reset, it can judge whether
> the ring size passed by the driver is legal based on this.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>


Acked-by: Jason Wang <jasowang@redhat.com>


> ---
>   drivers/virtio/virtio_mmio.c       |  2 ++
>   drivers/virtio/virtio_pci_legacy.c |  2 ++
>   drivers/virtio/virtio_pci_modern.c |  2 ++
>   drivers/virtio/virtio_ring.c       | 14 ++++++++++++++
>   include/linux/virtio.h             |  2 ++
>   5 files changed, 22 insertions(+)
>
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index 56128b9c46eb..a41abc8051b9 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -390,6 +390,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
>   		goto error_new_virtqueue;
>   	}
>   
> +	vq->num_max = num;
> +
>   	/* Activate the queue */
>   	writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
>   	if (vm_dev->version == 1) {
> diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
> index 34141b9abe27..b68934fe6b5d 100644
> --- a/drivers/virtio/virtio_pci_legacy.c
> +++ b/drivers/virtio/virtio_pci_legacy.c
> @@ -135,6 +135,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
>   	if (!vq)
>   		return ERR_PTR(-ENOMEM);
>   
> +	vq->num_max = num;
> +
>   	q_pfn = virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
>   	if (q_pfn >> 32) {
>   		dev_err(&vp_dev->pci_dev->dev,
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 5455bc041fb6..86d301f272b8 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -218,6 +218,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
>   	if (!vq)
>   		return ERR_PTR(-ENOMEM);
>   
> +	vq->num_max = num;
> +
>   	/* activate the queue */
>   	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
>   	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index 962f1477b1fa..b87130c8f312 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -2371,6 +2371,20 @@ void vring_transport_features(struct virtio_device *vdev)
>   }
>   EXPORT_SYMBOL_GPL(vring_transport_features);
>   
> +/**
> + * virtqueue_get_vring_max_size - return the max size of the virtqueue's vring
> + * @_vq: the struct virtqueue containing the vring of interest.
> + *
> + * Returns the max size of the vring.
> + *
> + * Unlike other operations, this need not be serialized.
> + */
> +unsigned int virtqueue_get_vring_max_size(struct virtqueue *_vq)
> +{
> +	return _vq->num_max;
> +}
> +EXPORT_SYMBOL_GPL(virtqueue_get_vring_max_size);
> +
>   /**
>    * virtqueue_get_vring_size - return the size of the virtqueue's vring
>    * @_vq: the struct virtqueue containing the vring of interest.
> diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> index 72292a62cd90..d59adc4be068 100644
> --- a/include/linux/virtio.h
> +++ b/include/linux/virtio.h
> @@ -31,6 +31,7 @@ struct virtqueue {
>   	struct virtio_device *vdev;
>   	unsigned int index;
>   	unsigned int num_free;
> +	unsigned int num_max;
>   	void *priv;
>   };
>   
> @@ -80,6 +81,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
>   
>   void *virtqueue_detach_unused_buf(struct virtqueue *vq);
>   
> +unsigned int virtqueue_get_vring_max_size(struct virtqueue *vq);
>   unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
>   
>   bool virtqueue_is_broken(struct virtqueue *vq);


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 03/26] virtio: add helper virtqueue_get_vring_max_size()
@ 2022-03-09  6:16     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  6:16 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Record the maximum queue num supported by the device.
>
> virtio-net can display the maximum (supported by hardware) ring size in
> ethtool -g eth0.
>
> When the subsequent patch implements vring reset, it can judge whether
> the ring size passed by the driver is legal based on this.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>


Acked-by: Jason Wang <jasowang@redhat.com>


> ---
>   drivers/virtio/virtio_mmio.c       |  2 ++
>   drivers/virtio/virtio_pci_legacy.c |  2 ++
>   drivers/virtio/virtio_pci_modern.c |  2 ++
>   drivers/virtio/virtio_ring.c       | 14 ++++++++++++++
>   include/linux/virtio.h             |  2 ++
>   5 files changed, 22 insertions(+)
>
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index 56128b9c46eb..a41abc8051b9 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -390,6 +390,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
>   		goto error_new_virtqueue;
>   	}
>   
> +	vq->num_max = num;
> +
>   	/* Activate the queue */
>   	writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
>   	if (vm_dev->version == 1) {
> diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
> index 34141b9abe27..b68934fe6b5d 100644
> --- a/drivers/virtio/virtio_pci_legacy.c
> +++ b/drivers/virtio/virtio_pci_legacy.c
> @@ -135,6 +135,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
>   	if (!vq)
>   		return ERR_PTR(-ENOMEM);
>   
> +	vq->num_max = num;
> +
>   	q_pfn = virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
>   	if (q_pfn >> 32) {
>   		dev_err(&vp_dev->pci_dev->dev,
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 5455bc041fb6..86d301f272b8 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -218,6 +218,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
>   	if (!vq)
>   		return ERR_PTR(-ENOMEM);
>   
> +	vq->num_max = num;
> +
>   	/* activate the queue */
>   	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
>   	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index 962f1477b1fa..b87130c8f312 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -2371,6 +2371,20 @@ void vring_transport_features(struct virtio_device *vdev)
>   }
>   EXPORT_SYMBOL_GPL(vring_transport_features);
>   
> +/**
> + * virtqueue_get_vring_max_size - return the max size of the virtqueue's vring
> + * @_vq: the struct virtqueue containing the vring of interest.
> + *
> + * Returns the max size of the vring.
> + *
> + * Unlike other operations, this need not be serialized.
> + */
> +unsigned int virtqueue_get_vring_max_size(struct virtqueue *_vq)
> +{
> +	return _vq->num_max;
> +}
> +EXPORT_SYMBOL_GPL(virtqueue_get_vring_max_size);
> +
>   /**
>    * virtqueue_get_vring_size - return the size of the virtqueue's vring
>    * @_vq: the struct virtqueue containing the vring of interest.
> diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> index 72292a62cd90..d59adc4be068 100644
> --- a/include/linux/virtio.h
> +++ b/include/linux/virtio.h
> @@ -31,6 +31,7 @@ struct virtqueue {
>   	struct virtio_device *vdev;
>   	unsigned int index;
>   	unsigned int num_free;
> +	unsigned int num_max;
>   	void *priv;
>   };
>   
> @@ -80,6 +81,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
>   
>   void *virtqueue_detach_unused_buf(struct virtqueue *vq);
>   
> +unsigned int virtqueue_get_vring_max_size(struct virtqueue *vq);
>   unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
>   
>   bool virtqueue_is_broken(struct virtqueue *vq);

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 03/26] virtio: add helper virtqueue_get_vring_max_size()
@ 2022-03-09  6:16     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  6:16 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Record the maximum queue num supported by the device.
>
> virtio-net can display the maximum (supported by hardware) ring size in
> ethtool -g eth0.
>
> When the subsequent patch implements vring reset, it can judge whether
> the ring size passed by the driver is legal based on this.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>


Acked-by: Jason Wang <jasowang@redhat.com>


> ---
>   drivers/virtio/virtio_mmio.c       |  2 ++
>   drivers/virtio/virtio_pci_legacy.c |  2 ++
>   drivers/virtio/virtio_pci_modern.c |  2 ++
>   drivers/virtio/virtio_ring.c       | 14 ++++++++++++++
>   include/linux/virtio.h             |  2 ++
>   5 files changed, 22 insertions(+)
>
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index 56128b9c46eb..a41abc8051b9 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -390,6 +390,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
>   		goto error_new_virtqueue;
>   	}
>   
> +	vq->num_max = num;
> +
>   	/* Activate the queue */
>   	writel(virtqueue_get_vring_size(vq), vm_dev->base + VIRTIO_MMIO_QUEUE_NUM);
>   	if (vm_dev->version == 1) {
> diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
> index 34141b9abe27..b68934fe6b5d 100644
> --- a/drivers/virtio/virtio_pci_legacy.c
> +++ b/drivers/virtio/virtio_pci_legacy.c
> @@ -135,6 +135,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
>   	if (!vq)
>   		return ERR_PTR(-ENOMEM);
>   
> +	vq->num_max = num;
> +
>   	q_pfn = virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
>   	if (q_pfn >> 32) {
>   		dev_err(&vp_dev->pci_dev->dev,
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 5455bc041fb6..86d301f272b8 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -218,6 +218,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
>   	if (!vq)
>   		return ERR_PTR(-ENOMEM);
>   
> +	vq->num_max = num;
> +
>   	/* activate the queue */
>   	vp_modern_set_queue_size(mdev, index, virtqueue_get_vring_size(vq));
>   	vp_modern_queue_address(mdev, index, virtqueue_get_desc_addr(vq),
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index 962f1477b1fa..b87130c8f312 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -2371,6 +2371,20 @@ void vring_transport_features(struct virtio_device *vdev)
>   }
>   EXPORT_SYMBOL_GPL(vring_transport_features);
>   
> +/**
> + * virtqueue_get_vring_max_size - return the max size of the virtqueue's vring
> + * @_vq: the struct virtqueue containing the vring of interest.
> + *
> + * Returns the max size of the vring.
> + *
> + * Unlike other operations, this need not be serialized.
> + */
> +unsigned int virtqueue_get_vring_max_size(struct virtqueue *_vq)
> +{
> +	return _vq->num_max;
> +}
> +EXPORT_SYMBOL_GPL(virtqueue_get_vring_max_size);
> +
>   /**
>    * virtqueue_get_vring_size - return the size of the virtqueue's vring
>    * @_vq: the struct virtqueue containing the vring of interest.
> diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> index 72292a62cd90..d59adc4be068 100644
> --- a/include/linux/virtio.h
> +++ b/include/linux/virtio.h
> @@ -31,6 +31,7 @@ struct virtqueue {
>   	struct virtio_device *vdev;
>   	unsigned int index;
>   	unsigned int num_free;
> +	unsigned int num_max;
>   	void *priv;
>   };
>   
> @@ -80,6 +81,7 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
>   
>   void *virtqueue_detach_unused_buf(struct virtqueue *vq);
>   
> +unsigned int virtqueue_get_vring_max_size(struct virtqueue *vq);
>   unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
>   
>   bool virtqueue_is_broken(struct virtqueue *vq);


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 04/26] virtio_ring: split: extract the logic of creating vring
  2022-03-08 12:34   ` Xuan Zhuo
  (?)
@ 2022-03-09  6:46     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  6:46 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Separate the logic of split to create vring queue.
>
> For the convenience of passing parameters, add a structure
> vring_split.
>
> This feature is required for subsequent virtuqueue reset vring.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 74 +++++++++++++++++++++++++-----------
>   1 file changed, 51 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index b87130c8f312..d32793615451 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -85,6 +85,13 @@ struct vring_desc_extra {
>   	u16 next;			/* The next desc state in a list. */
>   };
>   
> +struct vring_split {
> +	void *queue;
> +	dma_addr_t dma_addr;
> +	size_t queue_size_in_bytes;
> +	struct vring vring;
> +};


So this structure will be only used in vring_create_vring_split() which 
seems not that useful.

More see below.


> +
>   struct vring_virtqueue {
>   	struct virtqueue vq;
>   
> @@ -915,28 +922,21 @@ static void *virtqueue_detach_unused_buf_split(struct virtqueue *_vq)
>   	return NULL;
>   }
>   
> -static struct virtqueue *vring_create_virtqueue_split(
> -	unsigned int index,
> -	unsigned int num,
> -	unsigned int vring_align,
> -	struct virtio_device *vdev,
> -	bool weak_barriers,
> -	bool may_reduce_num,
> -	bool context,
> -	bool (*notify)(struct virtqueue *),
> -	void (*callback)(struct virtqueue *),
> -	const char *name)
> +static int vring_create_vring_split(struct vring_split *vring,
> +				    struct virtio_device *vdev,
> +				    unsigned int vring_align,
> +				    bool weak_barriers,
> +				    bool may_reduce_num,
> +				    u32 num)


I'd rename this as vring_alloc_queue_split() and let it simply return 
the address of queue like vring_alloc_queue().

And let it simple accept dma_addr_t *dma_adder instead of vring_split.


>   {
> -	struct virtqueue *vq;
>   	void *queue = NULL;
>   	dma_addr_t dma_addr;
>   	size_t queue_size_in_bytes;
> -	struct vring vring;
>   
>   	/* We assume num is a power of 2. */
>   	if (num & (num - 1)) {
>   		dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
> -		return NULL;
> +		return -EINVAL;
>   	}
>   
>   	/* TODO: allocate each queue chunk individually */
> @@ -947,11 +947,11 @@ static struct virtqueue *vring_create_virtqueue_split(
>   		if (queue)
>   			break;
>   		if (!may_reduce_num)
> -			return NULL;
> +			return -ENOMEM;
>   	}
>   
>   	if (!num)
> -		return NULL;
> +		return -ENOMEM;
>   
>   	if (!queue) {
>   		/* Try to get a single page. You are my only hope! */
> @@ -959,21 +959,49 @@ static struct virtqueue *vring_create_virtqueue_split(
>   					  &dma_addr, GFP_KERNEL|__GFP_ZERO);
>   	}
>   	if (!queue)
> -		return NULL;
> +		return -ENOMEM;
>   
>   	queue_size_in_bytes = vring_size(num, vring_align);
> -	vring_init(&vring, num, queue, vring_align);
> +	vring_init(&vring->vring, num, queue, vring_align);


It's better to move this to its caller (vring_create_virtqueue_split), 
so we have rather simple logic below:



> +
> +	vring->dma_addr = dma_addr;
> +	vring->queue = queue;
> +	vring->queue_size_in_bytes = queue_size_in_bytes;
> +
> +	return 0;
> +}
> +
> +static struct virtqueue *vring_create_virtqueue_split(
> +	unsigned int index,
> +	unsigned int num,
> +	unsigned int vring_align,
> +	struct virtio_device *vdev,
> +	bool weak_barriers,
> +	bool may_reduce_num,
> +	bool context,
> +	bool (*notify)(struct virtqueue *),
> +	void (*callback)(struct virtqueue *),
> +	const char *name)
> +{
> +	struct vring_split vring;
> +	struct virtqueue *vq;
> +	int err;
> +
> +	err = vring_create_vring_split(&vring, vdev, vring_align, weak_barriers,
> +				       may_reduce_num, num);
> +	if (err)
> +		return NULL;


queue = vring_alloc_queue_split(vdev, &dma_addr, ...);

if (!queue)

     return -ENOMEM;

vring_init();

...

Thanks


>   
> -	vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
> +	vq = __vring_new_virtqueue(index, vring.vring, vdev, weak_barriers, context,
>   				   notify, callback, name);
>   	if (!vq) {
> -		vring_free_queue(vdev, queue_size_in_bytes, queue,
> -				 dma_addr);
> +		vring_free_queue(vdev, vring.queue_size_in_bytes, vring.queue,
> +				 vring.dma_addr);
>   		return NULL;
>   	}
>   
> -	to_vvq(vq)->split.queue_dma_addr = dma_addr;
> -	to_vvq(vq)->split.queue_size_in_bytes = queue_size_in_bytes;
> +	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> +	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>   	to_vvq(vq)->we_own_ring = true;
>   
>   	return vq;


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 04/26] virtio_ring: split: extract the logic of creating vring
@ 2022-03-09  6:46     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  6:46 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Separate the logic of split to create vring queue.
>
> For the convenience of passing parameters, add a structure
> vring_split.
>
> This feature is required for subsequent virtuqueue reset vring.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 74 +++++++++++++++++++++++++-----------
>   1 file changed, 51 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index b87130c8f312..d32793615451 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -85,6 +85,13 @@ struct vring_desc_extra {
>   	u16 next;			/* The next desc state in a list. */
>   };
>   
> +struct vring_split {
> +	void *queue;
> +	dma_addr_t dma_addr;
> +	size_t queue_size_in_bytes;
> +	struct vring vring;
> +};


So this structure will be only used in vring_create_vring_split() which 
seems not that useful.

More see below.


> +
>   struct vring_virtqueue {
>   	struct virtqueue vq;
>   
> @@ -915,28 +922,21 @@ static void *virtqueue_detach_unused_buf_split(struct virtqueue *_vq)
>   	return NULL;
>   }
>   
> -static struct virtqueue *vring_create_virtqueue_split(
> -	unsigned int index,
> -	unsigned int num,
> -	unsigned int vring_align,
> -	struct virtio_device *vdev,
> -	bool weak_barriers,
> -	bool may_reduce_num,
> -	bool context,
> -	bool (*notify)(struct virtqueue *),
> -	void (*callback)(struct virtqueue *),
> -	const char *name)
> +static int vring_create_vring_split(struct vring_split *vring,
> +				    struct virtio_device *vdev,
> +				    unsigned int vring_align,
> +				    bool weak_barriers,
> +				    bool may_reduce_num,
> +				    u32 num)


I'd rename this as vring_alloc_queue_split() and let it simply return 
the address of queue like vring_alloc_queue().

And let it simple accept dma_addr_t *dma_adder instead of vring_split.


>   {
> -	struct virtqueue *vq;
>   	void *queue = NULL;
>   	dma_addr_t dma_addr;
>   	size_t queue_size_in_bytes;
> -	struct vring vring;
>   
>   	/* We assume num is a power of 2. */
>   	if (num & (num - 1)) {
>   		dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
> -		return NULL;
> +		return -EINVAL;
>   	}
>   
>   	/* TODO: allocate each queue chunk individually */
> @@ -947,11 +947,11 @@ static struct virtqueue *vring_create_virtqueue_split(
>   		if (queue)
>   			break;
>   		if (!may_reduce_num)
> -			return NULL;
> +			return -ENOMEM;
>   	}
>   
>   	if (!num)
> -		return NULL;
> +		return -ENOMEM;
>   
>   	if (!queue) {
>   		/* Try to get a single page. You are my only hope! */
> @@ -959,21 +959,49 @@ static struct virtqueue *vring_create_virtqueue_split(
>   					  &dma_addr, GFP_KERNEL|__GFP_ZERO);
>   	}
>   	if (!queue)
> -		return NULL;
> +		return -ENOMEM;
>   
>   	queue_size_in_bytes = vring_size(num, vring_align);
> -	vring_init(&vring, num, queue, vring_align);
> +	vring_init(&vring->vring, num, queue, vring_align);


It's better to move this to its caller (vring_create_virtqueue_split), 
so we have rather simple logic below:



> +
> +	vring->dma_addr = dma_addr;
> +	vring->queue = queue;
> +	vring->queue_size_in_bytes = queue_size_in_bytes;
> +
> +	return 0;
> +}
> +
> +static struct virtqueue *vring_create_virtqueue_split(
> +	unsigned int index,
> +	unsigned int num,
> +	unsigned int vring_align,
> +	struct virtio_device *vdev,
> +	bool weak_barriers,
> +	bool may_reduce_num,
> +	bool context,
> +	bool (*notify)(struct virtqueue *),
> +	void (*callback)(struct virtqueue *),
> +	const char *name)
> +{
> +	struct vring_split vring;
> +	struct virtqueue *vq;
> +	int err;
> +
> +	err = vring_create_vring_split(&vring, vdev, vring_align, weak_barriers,
> +				       may_reduce_num, num);
> +	if (err)
> +		return NULL;


queue = vring_alloc_queue_split(vdev, &dma_addr, ...);

if (!queue)

     return -ENOMEM;

vring_init();

...

Thanks


>   
> -	vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
> +	vq = __vring_new_virtqueue(index, vring.vring, vdev, weak_barriers, context,
>   				   notify, callback, name);
>   	if (!vq) {
> -		vring_free_queue(vdev, queue_size_in_bytes, queue,
> -				 dma_addr);
> +		vring_free_queue(vdev, vring.queue_size_in_bytes, vring.queue,
> +				 vring.dma_addr);
>   		return NULL;
>   	}
>   
> -	to_vvq(vq)->split.queue_dma_addr = dma_addr;
> -	to_vvq(vq)->split.queue_size_in_bytes = queue_size_in_bytes;
> +	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> +	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>   	to_vvq(vq)->we_own_ring = true;
>   
>   	return vq;

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 04/26] virtio_ring: split: extract the logic of creating vring
@ 2022-03-09  6:46     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  6:46 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Separate the logic of split to create vring queue.
>
> For the convenience of passing parameters, add a structure
> vring_split.
>
> This feature is required for subsequent virtuqueue reset vring.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 74 +++++++++++++++++++++++++-----------
>   1 file changed, 51 insertions(+), 23 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index b87130c8f312..d32793615451 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -85,6 +85,13 @@ struct vring_desc_extra {
>   	u16 next;			/* The next desc state in a list. */
>   };
>   
> +struct vring_split {
> +	void *queue;
> +	dma_addr_t dma_addr;
> +	size_t queue_size_in_bytes;
> +	struct vring vring;
> +};


So this structure will be only used in vring_create_vring_split() which 
seems not that useful.

More see below.


> +
>   struct vring_virtqueue {
>   	struct virtqueue vq;
>   
> @@ -915,28 +922,21 @@ static void *virtqueue_detach_unused_buf_split(struct virtqueue *_vq)
>   	return NULL;
>   }
>   
> -static struct virtqueue *vring_create_virtqueue_split(
> -	unsigned int index,
> -	unsigned int num,
> -	unsigned int vring_align,
> -	struct virtio_device *vdev,
> -	bool weak_barriers,
> -	bool may_reduce_num,
> -	bool context,
> -	bool (*notify)(struct virtqueue *),
> -	void (*callback)(struct virtqueue *),
> -	const char *name)
> +static int vring_create_vring_split(struct vring_split *vring,
> +				    struct virtio_device *vdev,
> +				    unsigned int vring_align,
> +				    bool weak_barriers,
> +				    bool may_reduce_num,
> +				    u32 num)


I'd rename this as vring_alloc_queue_split() and let it simply return 
the address of queue like vring_alloc_queue().

And let it simple accept dma_addr_t *dma_adder instead of vring_split.


>   {
> -	struct virtqueue *vq;
>   	void *queue = NULL;
>   	dma_addr_t dma_addr;
>   	size_t queue_size_in_bytes;
> -	struct vring vring;
>   
>   	/* We assume num is a power of 2. */
>   	if (num & (num - 1)) {
>   		dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
> -		return NULL;
> +		return -EINVAL;
>   	}
>   
>   	/* TODO: allocate each queue chunk individually */
> @@ -947,11 +947,11 @@ static struct virtqueue *vring_create_virtqueue_split(
>   		if (queue)
>   			break;
>   		if (!may_reduce_num)
> -			return NULL;
> +			return -ENOMEM;
>   	}
>   
>   	if (!num)
> -		return NULL;
> +		return -ENOMEM;
>   
>   	if (!queue) {
>   		/* Try to get a single page. You are my only hope! */
> @@ -959,21 +959,49 @@ static struct virtqueue *vring_create_virtqueue_split(
>   					  &dma_addr, GFP_KERNEL|__GFP_ZERO);
>   	}
>   	if (!queue)
> -		return NULL;
> +		return -ENOMEM;
>   
>   	queue_size_in_bytes = vring_size(num, vring_align);
> -	vring_init(&vring, num, queue, vring_align);
> +	vring_init(&vring->vring, num, queue, vring_align);


It's better to move this to its caller (vring_create_virtqueue_split), 
so we have rather simple logic below:



> +
> +	vring->dma_addr = dma_addr;
> +	vring->queue = queue;
> +	vring->queue_size_in_bytes = queue_size_in_bytes;
> +
> +	return 0;
> +}
> +
> +static struct virtqueue *vring_create_virtqueue_split(
> +	unsigned int index,
> +	unsigned int num,
> +	unsigned int vring_align,
> +	struct virtio_device *vdev,
> +	bool weak_barriers,
> +	bool may_reduce_num,
> +	bool context,
> +	bool (*notify)(struct virtqueue *),
> +	void (*callback)(struct virtqueue *),
> +	const char *name)
> +{
> +	struct vring_split vring;
> +	struct virtqueue *vq;
> +	int err;
> +
> +	err = vring_create_vring_split(&vring, vdev, vring_align, weak_barriers,
> +				       may_reduce_num, num);
> +	if (err)
> +		return NULL;


queue = vring_alloc_queue_split(vdev, &dma_addr, ...);

if (!queue)

     return -ENOMEM;

vring_init();

...

Thanks


>   
> -	vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
> +	vq = __vring_new_virtqueue(index, vring.vring, vdev, weak_barriers, context,
>   				   notify, callback, name);
>   	if (!vq) {
> -		vring_free_queue(vdev, queue_size_in_bytes, queue,
> -				 dma_addr);
> +		vring_free_queue(vdev, vring.queue_size_in_bytes, vring.queue,
> +				 vring.dma_addr);
>   		return NULL;
>   	}
>   
> -	to_vvq(vq)->split.queue_dma_addr = dma_addr;
> -	to_vvq(vq)->split.queue_size_in_bytes = queue_size_in_bytes;
> +	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> +	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>   	to_vvq(vq)->we_own_ring = true;
>   
>   	return vq;


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 05/26] virtio_ring: split: extract the logic of init vq and attach vring
  2022-03-08 12:34   ` Xuan Zhuo
  (?)
@ 2022-03-09  7:36     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  7:36 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Split the logic of split assignment vq into three parts.
>
> 1. The assignment passed from the function parameter
> 2. The part that attaches vring to vq. -- __vring_virtqueue_attach_split()
> 3. The part that initializes vq to a fixed value --
>     __vring_virtqueue_init_split()
>
> This feature is required for subsequent virtuqueue reset vring
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 111 +++++++++++++++++++++--------------
>   1 file changed, 67 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index d32793615451..dc6313b79305 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -2196,34 +2196,40 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
>   }
>   EXPORT_SYMBOL_GPL(vring_interrupt);
>   
> -/* Only available for split ring */
> -struct virtqueue *__vring_new_virtqueue(unsigned int index,
> -					struct vring vring,
> -					struct virtio_device *vdev,
> -					bool weak_barriers,
> -					bool context,
> -					bool (*notify)(struct virtqueue *),
> -					void (*callback)(struct virtqueue *),
> -					const char *name)
> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> +					  struct virtio_device *vdev,
> +					  struct vring vring)
>   {
> -	struct vring_virtqueue *vq;
> +	vq->vq.num_free = vring.num;
>   
> -	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> -		return NULL;
> +	vq->split.vring = vring;
> +	vq->split.queue_dma_addr = 0;
> +	vq->split.queue_size_in_bytes = 0;
>   
> -	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> -	if (!vq)
> -		return NULL;
> +	vq->split.desc_state = kmalloc_array(vring.num,
> +					     sizeof(struct vring_desc_state_split), GFP_KERNEL);
> +	if (!vq->split.desc_state)
> +		goto err_state;
>   
> +	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> +	if (!vq->split.desc_extra)
> +		goto err_extra;


So this contains stuffs more than just attach. I wonder if it's better 
to split the allocation out to an dedicated helper (we have dedicated 
helper to allocate vring).

Thanks


> +
> +	memset(vq->split.desc_state, 0, vring.num *
> +	       sizeof(struct vring_desc_state_split));
> +	return 0;
> +
> +err_extra:
> +	kfree(vq->split.desc_state);
> +err_state:
> +	return -ENOMEM;
> +}
> +
> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> +					 struct virtio_device *vdev)
> +{
>   	vq->packed_ring = false;
> -	vq->vq.callback = callback;
> -	vq->vq.vdev = vdev;
> -	vq->vq.name = name;
> -	vq->vq.num_free = vring.num;
> -	vq->vq.index = index;
>   	vq->we_own_ring = false;
> -	vq->notify = notify;
> -	vq->weak_barriers = weak_barriers;
>   	vq->broken = false;
>   	vq->last_used_idx = 0;
>   	vq->event_triggered = false;
> @@ -2234,50 +2240,67 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
>   	vq->last_add_time_valid = false;
>   #endif
>   
> -	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> -		!context;
>   	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
>   
>   	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
>   		vq->weak_barriers = false;
>   
> -	vq->split.queue_dma_addr = 0;
> -	vq->split.queue_size_in_bytes = 0;
> -
> -	vq->split.vring = vring;
>   	vq->split.avail_flags_shadow = 0;
>   	vq->split.avail_idx_shadow = 0;
>   
>   	/* No callback?  Tell other side not to bother us. */
> -	if (!callback) {
> +	if (!vq->vq.callback) {
>   		vq->split.avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
>   		if (!vq->event)
>   			vq->split.vring.avail->flags = cpu_to_virtio16(vdev,
>   					vq->split.avail_flags_shadow);
>   	}
>   
> -	vq->split.desc_state = kmalloc_array(vring.num,
> -			sizeof(struct vring_desc_state_split), GFP_KERNEL);
> -	if (!vq->split.desc_state)
> -		goto err_state;
> -
> -	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> -	if (!vq->split.desc_extra)
> -		goto err_extra;
> -
>   	/* Put everything in free lists. */
>   	vq->free_head = 0;
> -	memset(vq->split.desc_state, 0, vring.num *
> -			sizeof(struct vring_desc_state_split));
> +}
> +
> +/* Only available for split ring */
> +struct virtqueue *__vring_new_virtqueue(unsigned int index,
> +					struct vring vring,
> +					struct virtio_device *vdev,
> +					bool weak_barriers,
> +					bool context,
> +					bool (*notify)(struct virtqueue *),
> +					void (*callback)(struct virtqueue *),
> +					const char *name)
> +{
> +	struct vring_virtqueue *vq;
> +	int err;
> +
> +	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> +		return NULL;
> +
> +	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> +	if (!vq)
> +		return NULL;
> +
> +	vq->vq.callback = callback;
> +	vq->vq.vdev = vdev;
> +	vq->vq.name = name;
> +	vq->vq.index = index;
> +	vq->notify = notify;
> +	vq->weak_barriers = weak_barriers;
> +	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> +		!context;
> +
> +	err = __vring_virtqueue_attach_split(vq, vdev, vring);
> +	if (err)
> +		goto err;
> +
> +	__vring_virtqueue_init_split(vq, vdev);
>   
>   	spin_lock(&vdev->vqs_list_lock);
>   	list_add_tail(&vq->vq.list, &vdev->vqs);
>   	spin_unlock(&vdev->vqs_list_lock);
> -	return &vq->vq;
>   
> -err_extra:
> -	kfree(vq->split.desc_state);
> -err_state:
> +	return &vq->vq;
> +err:
>   	kfree(vq);
>   	return NULL;
>   }


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 05/26] virtio_ring: split: extract the logic of init vq and attach vring
@ 2022-03-09  7:36     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  7:36 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Split the logic of split assignment vq into three parts.
>
> 1. The assignment passed from the function parameter
> 2. The part that attaches vring to vq. -- __vring_virtqueue_attach_split()
> 3. The part that initializes vq to a fixed value --
>     __vring_virtqueue_init_split()
>
> This feature is required for subsequent virtuqueue reset vring
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 111 +++++++++++++++++++++--------------
>   1 file changed, 67 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index d32793615451..dc6313b79305 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -2196,34 +2196,40 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
>   }
>   EXPORT_SYMBOL_GPL(vring_interrupt);
>   
> -/* Only available for split ring */
> -struct virtqueue *__vring_new_virtqueue(unsigned int index,
> -					struct vring vring,
> -					struct virtio_device *vdev,
> -					bool weak_barriers,
> -					bool context,
> -					bool (*notify)(struct virtqueue *),
> -					void (*callback)(struct virtqueue *),
> -					const char *name)
> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> +					  struct virtio_device *vdev,
> +					  struct vring vring)
>   {
> -	struct vring_virtqueue *vq;
> +	vq->vq.num_free = vring.num;
>   
> -	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> -		return NULL;
> +	vq->split.vring = vring;
> +	vq->split.queue_dma_addr = 0;
> +	vq->split.queue_size_in_bytes = 0;
>   
> -	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> -	if (!vq)
> -		return NULL;
> +	vq->split.desc_state = kmalloc_array(vring.num,
> +					     sizeof(struct vring_desc_state_split), GFP_KERNEL);
> +	if (!vq->split.desc_state)
> +		goto err_state;
>   
> +	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> +	if (!vq->split.desc_extra)
> +		goto err_extra;


So this contains stuffs more than just attach. I wonder if it's better 
to split the allocation out to an dedicated helper (we have dedicated 
helper to allocate vring).

Thanks


> +
> +	memset(vq->split.desc_state, 0, vring.num *
> +	       sizeof(struct vring_desc_state_split));
> +	return 0;
> +
> +err_extra:
> +	kfree(vq->split.desc_state);
> +err_state:
> +	return -ENOMEM;
> +}
> +
> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> +					 struct virtio_device *vdev)
> +{
>   	vq->packed_ring = false;
> -	vq->vq.callback = callback;
> -	vq->vq.vdev = vdev;
> -	vq->vq.name = name;
> -	vq->vq.num_free = vring.num;
> -	vq->vq.index = index;
>   	vq->we_own_ring = false;
> -	vq->notify = notify;
> -	vq->weak_barriers = weak_barriers;
>   	vq->broken = false;
>   	vq->last_used_idx = 0;
>   	vq->event_triggered = false;
> @@ -2234,50 +2240,67 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
>   	vq->last_add_time_valid = false;
>   #endif
>   
> -	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> -		!context;
>   	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
>   
>   	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
>   		vq->weak_barriers = false;
>   
> -	vq->split.queue_dma_addr = 0;
> -	vq->split.queue_size_in_bytes = 0;
> -
> -	vq->split.vring = vring;
>   	vq->split.avail_flags_shadow = 0;
>   	vq->split.avail_idx_shadow = 0;
>   
>   	/* No callback?  Tell other side not to bother us. */
> -	if (!callback) {
> +	if (!vq->vq.callback) {
>   		vq->split.avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
>   		if (!vq->event)
>   			vq->split.vring.avail->flags = cpu_to_virtio16(vdev,
>   					vq->split.avail_flags_shadow);
>   	}
>   
> -	vq->split.desc_state = kmalloc_array(vring.num,
> -			sizeof(struct vring_desc_state_split), GFP_KERNEL);
> -	if (!vq->split.desc_state)
> -		goto err_state;
> -
> -	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> -	if (!vq->split.desc_extra)
> -		goto err_extra;
> -
>   	/* Put everything in free lists. */
>   	vq->free_head = 0;
> -	memset(vq->split.desc_state, 0, vring.num *
> -			sizeof(struct vring_desc_state_split));
> +}
> +
> +/* Only available for split ring */
> +struct virtqueue *__vring_new_virtqueue(unsigned int index,
> +					struct vring vring,
> +					struct virtio_device *vdev,
> +					bool weak_barriers,
> +					bool context,
> +					bool (*notify)(struct virtqueue *),
> +					void (*callback)(struct virtqueue *),
> +					const char *name)
> +{
> +	struct vring_virtqueue *vq;
> +	int err;
> +
> +	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> +		return NULL;
> +
> +	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> +	if (!vq)
> +		return NULL;
> +
> +	vq->vq.callback = callback;
> +	vq->vq.vdev = vdev;
> +	vq->vq.name = name;
> +	vq->vq.index = index;
> +	vq->notify = notify;
> +	vq->weak_barriers = weak_barriers;
> +	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> +		!context;
> +
> +	err = __vring_virtqueue_attach_split(vq, vdev, vring);
> +	if (err)
> +		goto err;
> +
> +	__vring_virtqueue_init_split(vq, vdev);
>   
>   	spin_lock(&vdev->vqs_list_lock);
>   	list_add_tail(&vq->vq.list, &vdev->vqs);
>   	spin_unlock(&vdev->vqs_list_lock);
> -	return &vq->vq;
>   
> -err_extra:
> -	kfree(vq->split.desc_state);
> -err_state:
> +	return &vq->vq;
> +err:
>   	kfree(vq);
>   	return NULL;
>   }

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 05/26] virtio_ring: split: extract the logic of init vq and attach vring
@ 2022-03-09  7:36     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  7:36 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> Split the logic of split assignment vq into three parts.
>
> 1. The assignment passed from the function parameter
> 2. The part that attaches vring to vq. -- __vring_virtqueue_attach_split()
> 3. The part that initializes vq to a fixed value --
>     __vring_virtqueue_init_split()
>
> This feature is required for subsequent virtuqueue reset vring
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 111 +++++++++++++++++++++--------------
>   1 file changed, 67 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index d32793615451..dc6313b79305 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -2196,34 +2196,40 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
>   }
>   EXPORT_SYMBOL_GPL(vring_interrupt);
>   
> -/* Only available for split ring */
> -struct virtqueue *__vring_new_virtqueue(unsigned int index,
> -					struct vring vring,
> -					struct virtio_device *vdev,
> -					bool weak_barriers,
> -					bool context,
> -					bool (*notify)(struct virtqueue *),
> -					void (*callback)(struct virtqueue *),
> -					const char *name)
> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> +					  struct virtio_device *vdev,
> +					  struct vring vring)
>   {
> -	struct vring_virtqueue *vq;
> +	vq->vq.num_free = vring.num;
>   
> -	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> -		return NULL;
> +	vq->split.vring = vring;
> +	vq->split.queue_dma_addr = 0;
> +	vq->split.queue_size_in_bytes = 0;
>   
> -	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> -	if (!vq)
> -		return NULL;
> +	vq->split.desc_state = kmalloc_array(vring.num,
> +					     sizeof(struct vring_desc_state_split), GFP_KERNEL);
> +	if (!vq->split.desc_state)
> +		goto err_state;
>   
> +	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> +	if (!vq->split.desc_extra)
> +		goto err_extra;


So this contains stuffs more than just attach. I wonder if it's better 
to split the allocation out to an dedicated helper (we have dedicated 
helper to allocate vring).

Thanks


> +
> +	memset(vq->split.desc_state, 0, vring.num *
> +	       sizeof(struct vring_desc_state_split));
> +	return 0;
> +
> +err_extra:
> +	kfree(vq->split.desc_state);
> +err_state:
> +	return -ENOMEM;
> +}
> +
> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> +					 struct virtio_device *vdev)
> +{
>   	vq->packed_ring = false;
> -	vq->vq.callback = callback;
> -	vq->vq.vdev = vdev;
> -	vq->vq.name = name;
> -	vq->vq.num_free = vring.num;
> -	vq->vq.index = index;
>   	vq->we_own_ring = false;
> -	vq->notify = notify;
> -	vq->weak_barriers = weak_barriers;
>   	vq->broken = false;
>   	vq->last_used_idx = 0;
>   	vq->event_triggered = false;
> @@ -2234,50 +2240,67 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
>   	vq->last_add_time_valid = false;
>   #endif
>   
> -	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> -		!context;
>   	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
>   
>   	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
>   		vq->weak_barriers = false;
>   
> -	vq->split.queue_dma_addr = 0;
> -	vq->split.queue_size_in_bytes = 0;
> -
> -	vq->split.vring = vring;
>   	vq->split.avail_flags_shadow = 0;
>   	vq->split.avail_idx_shadow = 0;
>   
>   	/* No callback?  Tell other side not to bother us. */
> -	if (!callback) {
> +	if (!vq->vq.callback) {
>   		vq->split.avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
>   		if (!vq->event)
>   			vq->split.vring.avail->flags = cpu_to_virtio16(vdev,
>   					vq->split.avail_flags_shadow);
>   	}
>   
> -	vq->split.desc_state = kmalloc_array(vring.num,
> -			sizeof(struct vring_desc_state_split), GFP_KERNEL);
> -	if (!vq->split.desc_state)
> -		goto err_state;
> -
> -	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> -	if (!vq->split.desc_extra)
> -		goto err_extra;
> -
>   	/* Put everything in free lists. */
>   	vq->free_head = 0;
> -	memset(vq->split.desc_state, 0, vring.num *
> -			sizeof(struct vring_desc_state_split));
> +}
> +
> +/* Only available for split ring */
> +struct virtqueue *__vring_new_virtqueue(unsigned int index,
> +					struct vring vring,
> +					struct virtio_device *vdev,
> +					bool weak_barriers,
> +					bool context,
> +					bool (*notify)(struct virtqueue *),
> +					void (*callback)(struct virtqueue *),
> +					const char *name)
> +{
> +	struct vring_virtqueue *vq;
> +	int err;
> +
> +	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> +		return NULL;
> +
> +	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> +	if (!vq)
> +		return NULL;
> +
> +	vq->vq.callback = callback;
> +	vq->vq.vdev = vdev;
> +	vq->vq.name = name;
> +	vq->vq.index = index;
> +	vq->notify = notify;
> +	vq->weak_barriers = weak_barriers;
> +	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> +		!context;
> +
> +	err = __vring_virtqueue_attach_split(vq, vdev, vring);
> +	if (err)
> +		goto err;
> +
> +	__vring_virtqueue_init_split(vq, vdev);
>   
>   	spin_lock(&vdev->vqs_list_lock);
>   	list_add_tail(&vq->vq.list, &vdev->vqs);
>   	spin_unlock(&vdev->vqs_list_lock);
> -	return &vq->vq;
>   
> -err_extra:
> -	kfree(vq->split.desc_state);
> -err_state:
> +	return &vq->vq;
> +err:
>   	kfree(vq);
>   	return NULL;
>   }


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 08/26] virtio_ring: extract the logic of freeing vring
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-09  7:51     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  7:51 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Introduce vring_free() to free the vring of vq.
>
> Prevent double free by setting vq->reset.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 25 ++++++++++++++++++++-----
>   include/linux/virtio.h       |  8 ++++++++
>   2 files changed, 28 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index b5a9bf4f45b3..e0422c04c903 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -2442,14 +2442,10 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
>   }
>   EXPORT_SYMBOL_GPL(vring_new_virtqueue);
>   
> -void vring_del_virtqueue(struct virtqueue *_vq)
> +static void __vring_free(struct virtqueue *_vq)
>   {
>   	struct vring_virtqueue *vq = to_vvq(_vq);
>   
> -	spin_lock(&vq->vq.vdev->vqs_list_lock);
> -	list_del(&_vq->list);
> -	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> -
>   	if (vq->we_own_ring) {
>   		if (vq->packed_ring) {
>   			vring_free_queue(vq->vq.vdev,
> @@ -2480,6 +2476,25 @@ void vring_del_virtqueue(struct virtqueue *_vq)
>   		kfree(vq->split.desc_state);
>   		kfree(vq->split.desc_extra);
>   	}
> +}
> +
> +static void vring_free(struct virtqueue *vq)
> +{
> +	__vring_free(vq);
> +	vq->reset = VIRTIO_VQ_RESET_STEP_VRING_RELEASE;
> +}
> +
> +void vring_del_virtqueue(struct virtqueue *_vq)
> +{
> +	struct vring_virtqueue *vq = to_vvq(_vq);
> +
> +	spin_lock(&vq->vq.vdev->vqs_list_lock);
> +	list_del(&_vq->list);
> +	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> +
> +	if (_vq->reset != VIRTIO_VQ_RESET_STEP_VRING_RELEASE)
> +		__vring_free(_vq);
> +
>   	kfree(vq);
>   }
>   EXPORT_SYMBOL_GPL(vring_del_virtqueue);
> diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> index d59adc4be068..e3714e6db330 100644
> --- a/include/linux/virtio.h
> +++ b/include/linux/virtio.h
> @@ -10,6 +10,13 @@
>   #include <linux/mod_devicetable.h>
>   #include <linux/gfp.h>
>   
> +enum virtio_vq_reset_step {
> +	VIRTIO_VQ_RESET_STEP_NONE,
> +	VIRTIO_VQ_RESET_STEP_DEVICE,
> +	VIRTIO_VQ_RESET_STEP_VRING_RELEASE,
> +	VIRTIO_VQ_RESET_STEP_VRING_ATTACH,
> +};


This part looks not related to the subject.

And it needs detail documentation on this.

But I wonder how useful it is, anyway we can check the reset status via 
transport specific way and in the future we may want to do more than 
just resizing (e.g PASID).

Thanks


> +
>   /**
>    * virtqueue - a queue to register buffers for sending or receiving.
>    * @list: the chain of virtqueues for this device
> @@ -33,6 +40,7 @@ struct virtqueue {
>   	unsigned int num_free;
>   	unsigned int num_max;
>   	void *priv;
> +	enum virtio_vq_reset_step reset;
>   };
>   
>   int virtqueue_add_outbuf(struct virtqueue *vq,


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 08/26] virtio_ring: extract the logic of freeing vring
@ 2022-03-09  7:51     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  7:51 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Introduce vring_free() to free the vring of vq.
>
> Prevent double free by setting vq->reset.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 25 ++++++++++++++++++++-----
>   include/linux/virtio.h       |  8 ++++++++
>   2 files changed, 28 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index b5a9bf4f45b3..e0422c04c903 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -2442,14 +2442,10 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
>   }
>   EXPORT_SYMBOL_GPL(vring_new_virtqueue);
>   
> -void vring_del_virtqueue(struct virtqueue *_vq)
> +static void __vring_free(struct virtqueue *_vq)
>   {
>   	struct vring_virtqueue *vq = to_vvq(_vq);
>   
> -	spin_lock(&vq->vq.vdev->vqs_list_lock);
> -	list_del(&_vq->list);
> -	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> -
>   	if (vq->we_own_ring) {
>   		if (vq->packed_ring) {
>   			vring_free_queue(vq->vq.vdev,
> @@ -2480,6 +2476,25 @@ void vring_del_virtqueue(struct virtqueue *_vq)
>   		kfree(vq->split.desc_state);
>   		kfree(vq->split.desc_extra);
>   	}
> +}
> +
> +static void vring_free(struct virtqueue *vq)
> +{
> +	__vring_free(vq);
> +	vq->reset = VIRTIO_VQ_RESET_STEP_VRING_RELEASE;
> +}
> +
> +void vring_del_virtqueue(struct virtqueue *_vq)
> +{
> +	struct vring_virtqueue *vq = to_vvq(_vq);
> +
> +	spin_lock(&vq->vq.vdev->vqs_list_lock);
> +	list_del(&_vq->list);
> +	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> +
> +	if (_vq->reset != VIRTIO_VQ_RESET_STEP_VRING_RELEASE)
> +		__vring_free(_vq);
> +
>   	kfree(vq);
>   }
>   EXPORT_SYMBOL_GPL(vring_del_virtqueue);
> diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> index d59adc4be068..e3714e6db330 100644
> --- a/include/linux/virtio.h
> +++ b/include/linux/virtio.h
> @@ -10,6 +10,13 @@
>   #include <linux/mod_devicetable.h>
>   #include <linux/gfp.h>
>   
> +enum virtio_vq_reset_step {
> +	VIRTIO_VQ_RESET_STEP_NONE,
> +	VIRTIO_VQ_RESET_STEP_DEVICE,
> +	VIRTIO_VQ_RESET_STEP_VRING_RELEASE,
> +	VIRTIO_VQ_RESET_STEP_VRING_ATTACH,
> +};


This part looks not related to the subject.

And it needs detail documentation on this.

But I wonder how useful it is, anyway we can check the reset status via 
transport specific way and in the future we may want to do more than 
just resizing (e.g PASID).

Thanks


> +
>   /**
>    * virtqueue - a queue to register buffers for sending or receiving.
>    * @list: the chain of virtqueues for this device
> @@ -33,6 +40,7 @@ struct virtqueue {
>   	unsigned int num_free;
>   	unsigned int num_max;
>   	void *priv;
> +	enum virtio_vq_reset_step reset;
>   };
>   
>   int virtqueue_add_outbuf(struct virtqueue *vq,

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 08/26] virtio_ring: extract the logic of freeing vring
@ 2022-03-09  7:51     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  7:51 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Introduce vring_free() to free the vring of vq.
>
> Prevent double free by setting vq->reset.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 25 ++++++++++++++++++++-----
>   include/linux/virtio.h       |  8 ++++++++
>   2 files changed, 28 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index b5a9bf4f45b3..e0422c04c903 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -2442,14 +2442,10 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
>   }
>   EXPORT_SYMBOL_GPL(vring_new_virtqueue);
>   
> -void vring_del_virtqueue(struct virtqueue *_vq)
> +static void __vring_free(struct virtqueue *_vq)
>   {
>   	struct vring_virtqueue *vq = to_vvq(_vq);
>   
> -	spin_lock(&vq->vq.vdev->vqs_list_lock);
> -	list_del(&_vq->list);
> -	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> -
>   	if (vq->we_own_ring) {
>   		if (vq->packed_ring) {
>   			vring_free_queue(vq->vq.vdev,
> @@ -2480,6 +2476,25 @@ void vring_del_virtqueue(struct virtqueue *_vq)
>   		kfree(vq->split.desc_state);
>   		kfree(vq->split.desc_extra);
>   	}
> +}
> +
> +static void vring_free(struct virtqueue *vq)
> +{
> +	__vring_free(vq);
> +	vq->reset = VIRTIO_VQ_RESET_STEP_VRING_RELEASE;
> +}
> +
> +void vring_del_virtqueue(struct virtqueue *_vq)
> +{
> +	struct vring_virtqueue *vq = to_vvq(_vq);
> +
> +	spin_lock(&vq->vq.vdev->vqs_list_lock);
> +	list_del(&_vq->list);
> +	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> +
> +	if (_vq->reset != VIRTIO_VQ_RESET_STEP_VRING_RELEASE)
> +		__vring_free(_vq);
> +
>   	kfree(vq);
>   }
>   EXPORT_SYMBOL_GPL(vring_del_virtqueue);
> diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> index d59adc4be068..e3714e6db330 100644
> --- a/include/linux/virtio.h
> +++ b/include/linux/virtio.h
> @@ -10,6 +10,13 @@
>   #include <linux/mod_devicetable.h>
>   #include <linux/gfp.h>
>   
> +enum virtio_vq_reset_step {
> +	VIRTIO_VQ_RESET_STEP_NONE,
> +	VIRTIO_VQ_RESET_STEP_DEVICE,
> +	VIRTIO_VQ_RESET_STEP_VRING_RELEASE,
> +	VIRTIO_VQ_RESET_STEP_VRING_ATTACH,
> +};


This part looks not related to the subject.

And it needs detail documentation on this.

But I wonder how useful it is, anyway we can check the reset status via 
transport specific way and in the future we may want to do more than 
just resizing (e.g PASID).

Thanks


> +
>   /**
>    * virtqueue - a queue to register buffers for sending or receiving.
>    * @list: the chain of virtqueues for this device
> @@ -33,6 +40,7 @@ struct virtqueue {
>   	unsigned int num_free;
>   	unsigned int num_max;
>   	void *priv;
> +	enum virtio_vq_reset_step reset;
>   };
>   
>   int virtqueue_add_outbuf(struct virtqueue *vq,


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-09  7:55     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  7:55 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> virtio ring supports reset.
>
> Queue reset is divided into several stages.
>
> 1. notify device queue reset
> 2. vring release
> 3. attach new vring
> 4. notify device queue re-enable
>
> After the first step is completed, the vring reset operation can be
> performed. If the newly set vring num does not change, then just reset
> the vq related value.
>
> Otherwise, the vring will be released and the vring will be reallocated.
> And the vring will be attached to the vq. If this process fails, the
> function will exit, and the state of the vq will be the vring release
> state. You can call this function again to reallocate the vring.
>
> In addition, vring_align, may_reduce_num are necessary for reallocating
> vring, so they are retained when creating vq.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
>   1 file changed, 69 insertions(+)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index e0422c04c903..148fb1fd3d5a 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -158,6 +158,12 @@ struct vring_virtqueue {
>   			/* DMA address and size information */
>   			dma_addr_t queue_dma_addr;
>   			size_t queue_size_in_bytes;
> +
> +			/* The parameters for creating vrings are reserved for
> +			 * creating new vrings when enabling reset queue.
> +			 */
> +			u32 vring_align;
> +			bool may_reduce_num;
>   		} split;
>   
>   		/* Available for packed ring */
> @@ -217,6 +223,12 @@ struct vring_virtqueue {
>   #endif
>   };
>   
> +static void vring_free(struct virtqueue *vq);
> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> +					 struct virtio_device *vdev);
> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> +					  struct virtio_device *vdev,
> +					  struct vring vring);
>   
>   /*
>    * Helpers.
> @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
>   		return NULL;
>   	}
>   
> +	to_vvq(vq)->split.vring_align = vring_align;
> +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
>   	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
>   	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>   	to_vvq(vq)->we_own_ring = true;
> @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
>   	return vq;
>   }
>   
> +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> +{


So what this function does is to resize the virtqueue actually, I 
suggest to rename it as virtqueue_resize_split().


> +	struct vring_virtqueue *vq = to_vvq(_vq);
> +	struct virtio_device *vdev = _vq->vdev;
> +	struct vring_split vring;
> +	int err;
> +
> +	if (num > _vq->num_max)
> +		return -E2BIG;
> +
> +	switch (vq->vq.reset) {
> +	case VIRTIO_VQ_RESET_STEP_NONE:
> +		return -ENOENT;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> +		if (vq->split.vring.num == num || !num)
> +			break;
> +
> +		vring_free(_vq);
> +
> +		fallthrough;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> +		if (!num)
> +			num = vq->split.vring.num;
> +
> +		err = vring_create_vring_split(&vring, vdev,
> +					       vq->split.vring_align,
> +					       vq->weak_barriers,
> +					       vq->split.may_reduce_num, num);
> +		if (err)
> +			return -ENOMEM;


We'd better need a safe fallback here like:

If we can't allocate new memory, we can keep using the current one. 
Otherwise an ethtool -G fail may make the device not usable.

This could be done by not freeing the old vring and virtqueue states 
until new is allocated.


> +
> +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> +		if (err) {
> +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> +					 vring.queue,
> +					 vring.dma_addr);
> +			return -ENOMEM;
> +		}
> +
> +		vq->split.queue_dma_addr = vring.dma_addr;
> +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> +	}
> +
> +	__vring_virtqueue_init_split(vq, vdev);
> +	vq->we_own_ring = true;


This seems wrong, we have the transport (rproc/mlxtbf) that allocate the 
vring by themselves. I think we need to fail the resize for we_own_ring 
== false.

Thanks



> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> +
> +	return 0;
> +}
> +
>   
>   /*
>    * Packed ring specific functions - *_packed().
> @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>   static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>   					 struct virtio_device *vdev)
>   {
> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> +
>   	vq->packed_ring = false;
>   	vq->we_own_ring = false;
>   	vq->broken = false;

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-09  7:55     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  7:55 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> virtio ring supports reset.
>
> Queue reset is divided into several stages.
>
> 1. notify device queue reset
> 2. vring release
> 3. attach new vring
> 4. notify device queue re-enable
>
> After the first step is completed, the vring reset operation can be
> performed. If the newly set vring num does not change, then just reset
> the vq related value.
>
> Otherwise, the vring will be released and the vring will be reallocated.
> And the vring will be attached to the vq. If this process fails, the
> function will exit, and the state of the vq will be the vring release
> state. You can call this function again to reallocate the vring.
>
> In addition, vring_align, may_reduce_num are necessary for reallocating
> vring, so they are retained when creating vq.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
>   1 file changed, 69 insertions(+)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index e0422c04c903..148fb1fd3d5a 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -158,6 +158,12 @@ struct vring_virtqueue {
>   			/* DMA address and size information */
>   			dma_addr_t queue_dma_addr;
>   			size_t queue_size_in_bytes;
> +
> +			/* The parameters for creating vrings are reserved for
> +			 * creating new vrings when enabling reset queue.
> +			 */
> +			u32 vring_align;
> +			bool may_reduce_num;
>   		} split;
>   
>   		/* Available for packed ring */
> @@ -217,6 +223,12 @@ struct vring_virtqueue {
>   #endif
>   };
>   
> +static void vring_free(struct virtqueue *vq);
> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> +					 struct virtio_device *vdev);
> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> +					  struct virtio_device *vdev,
> +					  struct vring vring);
>   
>   /*
>    * Helpers.
> @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
>   		return NULL;
>   	}
>   
> +	to_vvq(vq)->split.vring_align = vring_align;
> +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
>   	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
>   	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>   	to_vvq(vq)->we_own_ring = true;
> @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
>   	return vq;
>   }
>   
> +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> +{


So what this function does is to resize the virtqueue actually, I 
suggest to rename it as virtqueue_resize_split().


> +	struct vring_virtqueue *vq = to_vvq(_vq);
> +	struct virtio_device *vdev = _vq->vdev;
> +	struct vring_split vring;
> +	int err;
> +
> +	if (num > _vq->num_max)
> +		return -E2BIG;
> +
> +	switch (vq->vq.reset) {
> +	case VIRTIO_VQ_RESET_STEP_NONE:
> +		return -ENOENT;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> +		if (vq->split.vring.num == num || !num)
> +			break;
> +
> +		vring_free(_vq);
> +
> +		fallthrough;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> +		if (!num)
> +			num = vq->split.vring.num;
> +
> +		err = vring_create_vring_split(&vring, vdev,
> +					       vq->split.vring_align,
> +					       vq->weak_barriers,
> +					       vq->split.may_reduce_num, num);
> +		if (err)
> +			return -ENOMEM;


We'd better need a safe fallback here like:

If we can't allocate new memory, we can keep using the current one. 
Otherwise an ethtool -G fail may make the device not usable.

This could be done by not freeing the old vring and virtqueue states 
until new is allocated.


> +
> +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> +		if (err) {
> +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> +					 vring.queue,
> +					 vring.dma_addr);
> +			return -ENOMEM;
> +		}
> +
> +		vq->split.queue_dma_addr = vring.dma_addr;
> +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> +	}
> +
> +	__vring_virtqueue_init_split(vq, vdev);
> +	vq->we_own_ring = true;


This seems wrong, we have the transport (rproc/mlxtbf) that allocate the 
vring by themselves. I think we need to fail the resize for we_own_ring 
== false.

Thanks



> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> +
> +	return 0;
> +}
> +
>   
>   /*
>    * Packed ring specific functions - *_packed().
> @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>   static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>   					 struct virtio_device *vdev)
>   {
> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> +
>   	vq->packed_ring = false;
>   	vq->we_own_ring = false;
>   	vq->broken = false;


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-09  7:55     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  7:55 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> virtio ring supports reset.
>
> Queue reset is divided into several stages.
>
> 1. notify device queue reset
> 2. vring release
> 3. attach new vring
> 4. notify device queue re-enable
>
> After the first step is completed, the vring reset operation can be
> performed. If the newly set vring num does not change, then just reset
> the vq related value.
>
> Otherwise, the vring will be released and the vring will be reallocated.
> And the vring will be attached to the vq. If this process fails, the
> function will exit, and the state of the vq will be the vring release
> state. You can call this function again to reallocate the vring.
>
> In addition, vring_align, may_reduce_num are necessary for reallocating
> vring, so they are retained when creating vq.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
>   1 file changed, 69 insertions(+)
>
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index e0422c04c903..148fb1fd3d5a 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -158,6 +158,12 @@ struct vring_virtqueue {
>   			/* DMA address and size information */
>   			dma_addr_t queue_dma_addr;
>   			size_t queue_size_in_bytes;
> +
> +			/* The parameters for creating vrings are reserved for
> +			 * creating new vrings when enabling reset queue.
> +			 */
> +			u32 vring_align;
> +			bool may_reduce_num;
>   		} split;
>   
>   		/* Available for packed ring */
> @@ -217,6 +223,12 @@ struct vring_virtqueue {
>   #endif
>   };
>   
> +static void vring_free(struct virtqueue *vq);
> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> +					 struct virtio_device *vdev);
> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> +					  struct virtio_device *vdev,
> +					  struct vring vring);
>   
>   /*
>    * Helpers.
> @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
>   		return NULL;
>   	}
>   
> +	to_vvq(vq)->split.vring_align = vring_align;
> +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
>   	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
>   	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>   	to_vvq(vq)->we_own_ring = true;
> @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
>   	return vq;
>   }
>   
> +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> +{


So what this function does is to resize the virtqueue actually, I 
suggest to rename it as virtqueue_resize_split().


> +	struct vring_virtqueue *vq = to_vvq(_vq);
> +	struct virtio_device *vdev = _vq->vdev;
> +	struct vring_split vring;
> +	int err;
> +
> +	if (num > _vq->num_max)
> +		return -E2BIG;
> +
> +	switch (vq->vq.reset) {
> +	case VIRTIO_VQ_RESET_STEP_NONE:
> +		return -ENOENT;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> +		if (vq->split.vring.num == num || !num)
> +			break;
> +
> +		vring_free(_vq);
> +
> +		fallthrough;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> +		if (!num)
> +			num = vq->split.vring.num;
> +
> +		err = vring_create_vring_split(&vring, vdev,
> +					       vq->split.vring_align,
> +					       vq->weak_barriers,
> +					       vq->split.may_reduce_num, num);
> +		if (err)
> +			return -ENOMEM;


We'd better need a safe fallback here like:

If we can't allocate new memory, we can keep using the current one. 
Otherwise an ethtool -G fail may make the device not usable.

This could be done by not freeing the old vring and virtqueue states 
until new is allocated.


> +
> +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> +		if (err) {
> +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> +					 vring.queue,
> +					 vring.dma_addr);
> +			return -ENOMEM;
> +		}
> +
> +		vq->split.queue_dma_addr = vring.dma_addr;
> +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> +	}
> +
> +	__vring_virtqueue_init_split(vq, vdev);
> +	vq->we_own_ring = true;


This seems wrong, we have the transport (rproc/mlxtbf) that allocate the 
vring by themselves. I think we need to fail the resize for we_own_ring 
== false.

Thanks



> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> +
> +	return 0;
> +}
> +
>   
>   /*
>    * Packed ring specific functions - *_packed().
> @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>   static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>   					 struct virtio_device *vdev)
>   {
> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> +
>   	vq->packed_ring = false;
>   	vq->we_own_ring = false;
>   	vq->broken = false;


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 13/26] virtio: queue_reset: struct virtio_config_ops add callbacks for queue_reset
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-09  8:47     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:47 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Performing reset on a queue is divided into four steps:
>
>   1. reset_vq()                     - notify the device to reset the queue
>   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>   4. enable_reset_vq()              - mmap vring to device, and enable the queue
>
> So add two callbacks reset_vq, enable_reset_vq to struct
> virtio_config_ops.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/linux/virtio_config.h | 11 +++++++++++
>   1 file changed, 11 insertions(+)
>
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 4d107ad31149..d51906b1389f 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -74,6 +74,15 @@ struct virtio_shm_region {
>    * @set_vq_affinity: set the affinity for a virtqueue (optional).
>    * @get_vq_affinity: get the affinity for a virtqueue (optional).
>    * @get_shm_region: get a shared memory region based on the index.
> + * @reset_vq: reset a queue individually (optional).
> + *	vq: the virtqueue
> + *	Returns 0 on success or error status
> + *	Caller should guarantee that the vring is not accessed by any functions
> + *	of virtqueue.


We probably need to be more accurate here:

1) reset_vq will guarantee that the callbacks are disabled or synchronized
2) except for the callback, the caller should guarantee ...

Thanks


> + * @enable_reset_vq: enable a reset queue
> + *	vq: the virtqueue
> + *	Returns 0 on success or error status
> + *	If reset_vq is set, then enable_reset_vq must also be set.
>    */
>   typedef void vq_callback_t(struct virtqueue *);
>   struct virtio_config_ops {
> @@ -100,6 +109,8 @@ struct virtio_config_ops {
>   			int index);
>   	bool (*get_shm_region)(struct virtio_device *vdev,
>   			       struct virtio_shm_region *region, u8 id);
> +	int (*reset_vq)(struct virtqueue *vq);
> +	int (*enable_reset_vq)(struct virtqueue *vq);
>   };
>   
>   /* If driver didn't advertise the feature, it will never appear. */


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 13/26] virtio: queue_reset: struct virtio_config_ops add callbacks for queue_reset
@ 2022-03-09  8:47     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:47 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Performing reset on a queue is divided into four steps:
>
>   1. reset_vq()                     - notify the device to reset the queue
>   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>   4. enable_reset_vq()              - mmap vring to device, and enable the queue
>
> So add two callbacks reset_vq, enable_reset_vq to struct
> virtio_config_ops.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/linux/virtio_config.h | 11 +++++++++++
>   1 file changed, 11 insertions(+)
>
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 4d107ad31149..d51906b1389f 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -74,6 +74,15 @@ struct virtio_shm_region {
>    * @set_vq_affinity: set the affinity for a virtqueue (optional).
>    * @get_vq_affinity: get the affinity for a virtqueue (optional).
>    * @get_shm_region: get a shared memory region based on the index.
> + * @reset_vq: reset a queue individually (optional).
> + *	vq: the virtqueue
> + *	Returns 0 on success or error status
> + *	Caller should guarantee that the vring is not accessed by any functions
> + *	of virtqueue.


We probably need to be more accurate here:

1) reset_vq will guarantee that the callbacks are disabled or synchronized
2) except for the callback, the caller should guarantee ...

Thanks


> + * @enable_reset_vq: enable a reset queue
> + *	vq: the virtqueue
> + *	Returns 0 on success or error status
> + *	If reset_vq is set, then enable_reset_vq must also be set.
>    */
>   typedef void vq_callback_t(struct virtqueue *);
>   struct virtio_config_ops {
> @@ -100,6 +109,8 @@ struct virtio_config_ops {
>   			int index);
>   	bool (*get_shm_region)(struct virtio_device *vdev,
>   			       struct virtio_shm_region *region, u8 id);
> +	int (*reset_vq)(struct virtqueue *vq);
> +	int (*enable_reset_vq)(struct virtqueue *vq);
>   };
>   
>   /* If driver didn't advertise the feature, it will never appear. */

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 13/26] virtio: queue_reset: struct virtio_config_ops add callbacks for queue_reset
@ 2022-03-09  8:47     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:47 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Performing reset on a queue is divided into four steps:
>
>   1. reset_vq()                     - notify the device to reset the queue
>   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>   4. enable_reset_vq()              - mmap vring to device, and enable the queue
>
> So add two callbacks reset_vq, enable_reset_vq to struct
> virtio_config_ops.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/linux/virtio_config.h | 11 +++++++++++
>   1 file changed, 11 insertions(+)
>
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 4d107ad31149..d51906b1389f 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -74,6 +74,15 @@ struct virtio_shm_region {
>    * @set_vq_affinity: set the affinity for a virtqueue (optional).
>    * @get_vq_affinity: get the affinity for a virtqueue (optional).
>    * @get_shm_region: get a shared memory region based on the index.
> + * @reset_vq: reset a queue individually (optional).
> + *	vq: the virtqueue
> + *	Returns 0 on success or error status
> + *	Caller should guarantee that the vring is not accessed by any functions
> + *	of virtqueue.


We probably need to be more accurate here:

1) reset_vq will guarantee that the callbacks are disabled or synchronized
2) except for the callback, the caller should guarantee ...

Thanks


> + * @enable_reset_vq: enable a reset queue
> + *	vq: the virtqueue
> + *	Returns 0 on success or error status
> + *	If reset_vq is set, then enable_reset_vq must also be set.
>    */
>   typedef void vq_callback_t(struct virtqueue *);
>   struct virtio_config_ops {
> @@ -100,6 +109,8 @@ struct virtio_config_ops {
>   			int index);
>   	bool (*get_shm_region)(struct virtio_device *vdev,
>   			       struct virtio_shm_region *region, u8 id);
> +	int (*reset_vq)(struct virtqueue *vq);
> +	int (*enable_reset_vq)(struct virtqueue *vq);
>   };
>   
>   /* If driver didn't advertise the feature, it will never appear. */


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 14/26] virtio: add helper for queue reset
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-09  8:48     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:48 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Add helper for virtio queue reset.
>
> * virtio_reset_vq(): reset a queue individually
> * virtio_enable_resetq(): enable a reset queue
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/linux/virtio_config.h | 40 +++++++++++++++++++++++++++++++++++
>   1 file changed, 40 insertions(+)
>
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index d51906b1389f..0b81fbe17c85 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -230,6 +230,46 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>   				      desc);
>   }
>   
> +/**
> + * virtio_reset_vq - reset a queue individually
> + * @vq: the virtqueue
> + *
> + * returns 0 on success or error status
> + *
> + * The api process of reset under normal circumstances:
> + *	1. virtio_reset_vq()              - notify the device to reset the queue
> + *	2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> + *	3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> + *	4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> + *
> + * Caller should guarantee that the vring is not accessed by any functions
> + * of virtqueue.
> + */
> +static inline
> +int virtio_reset_vq(struct virtqueue *vq)
> +{


It looks to me the prefix "virtio" is used for the device specific 
operations.

I wonder if it's better to rename this as virtqueue_reste() and move it 
to virtio_ring.c?

Thanks


> +	if (!vq->vdev->config->reset_vq)
> +		return -ENOENT;
> +
> +	return vq->vdev->config->reset_vq(vq);
> +}
> +
> +/**
> + * virtio_enable_resetq - enable a reset queue
> + * @vq: the virtqueue
> + *
> + * returns 0 on success or error status
> + *
> + */
> +static inline
> +int virtio_enable_resetq(struct virtqueue *vq)
> +{
> +	if (!vq->vdev->config->enable_reset_vq)
> +		return -ENOENT;
> +
> +	return vq->vdev->config->enable_reset_vq(vq);
> +}
> +
>   /**
>    * virtio_device_ready - enable vq use in probe function
>    * @vdev: the device


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 14/26] virtio: add helper for queue reset
@ 2022-03-09  8:48     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:48 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Add helper for virtio queue reset.
>
> * virtio_reset_vq(): reset a queue individually
> * virtio_enable_resetq(): enable a reset queue
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/linux/virtio_config.h | 40 +++++++++++++++++++++++++++++++++++
>   1 file changed, 40 insertions(+)
>
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index d51906b1389f..0b81fbe17c85 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -230,6 +230,46 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>   				      desc);
>   }
>   
> +/**
> + * virtio_reset_vq - reset a queue individually
> + * @vq: the virtqueue
> + *
> + * returns 0 on success or error status
> + *
> + * The api process of reset under normal circumstances:
> + *	1. virtio_reset_vq()              - notify the device to reset the queue
> + *	2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> + *	3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> + *	4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> + *
> + * Caller should guarantee that the vring is not accessed by any functions
> + * of virtqueue.
> + */
> +static inline
> +int virtio_reset_vq(struct virtqueue *vq)
> +{


It looks to me the prefix "virtio" is used for the device specific 
operations.

I wonder if it's better to rename this as virtqueue_reste() and move it 
to virtio_ring.c?

Thanks


> +	if (!vq->vdev->config->reset_vq)
> +		return -ENOENT;
> +
> +	return vq->vdev->config->reset_vq(vq);
> +}
> +
> +/**
> + * virtio_enable_resetq - enable a reset queue
> + * @vq: the virtqueue
> + *
> + * returns 0 on success or error status
> + *
> + */
> +static inline
> +int virtio_enable_resetq(struct virtqueue *vq)
> +{
> +	if (!vq->vdev->config->enable_reset_vq)
> +		return -ENOENT;
> +
> +	return vq->vdev->config->enable_reset_vq(vq);
> +}
> +
>   /**
>    * virtio_device_ready - enable vq use in probe function
>    * @vdev: the device

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 14/26] virtio: add helper for queue reset
@ 2022-03-09  8:48     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:48 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Add helper for virtio queue reset.
>
> * virtio_reset_vq(): reset a queue individually
> * virtio_enable_resetq(): enable a reset queue
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/linux/virtio_config.h | 40 +++++++++++++++++++++++++++++++++++
>   1 file changed, 40 insertions(+)
>
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index d51906b1389f..0b81fbe17c85 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -230,6 +230,46 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>   				      desc);
>   }
>   
> +/**
> + * virtio_reset_vq - reset a queue individually
> + * @vq: the virtqueue
> + *
> + * returns 0 on success or error status
> + *
> + * The api process of reset under normal circumstances:
> + *	1. virtio_reset_vq()              - notify the device to reset the queue
> + *	2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> + *	3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> + *	4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> + *
> + * Caller should guarantee that the vring is not accessed by any functions
> + * of virtqueue.
> + */
> +static inline
> +int virtio_reset_vq(struct virtqueue *vq)
> +{


It looks to me the prefix "virtio" is used for the device specific 
operations.

I wonder if it's better to rename this as virtqueue_reste() and move it 
to virtio_ring.c?

Thanks


> +	if (!vq->vdev->config->reset_vq)
> +		return -ENOENT;
> +
> +	return vq->vdev->config->reset_vq(vq);
> +}
> +
> +/**
> + * virtio_enable_resetq - enable a reset queue
> + * @vq: the virtqueue
> + *
> + * returns 0 on success or error status
> + *
> + */
> +static inline
> +int virtio_enable_resetq(struct virtqueue *vq)
> +{
> +	if (!vq->vdev->config->enable_reset_vq)
> +		return -ENOENT;
> +
> +	return vq->vdev->config->enable_reset_vq(vq);
> +}
> +
>   /**
>    * virtio_device_ready - enable vq use in probe function
>    * @vdev: the device


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-09  8:54     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:54 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> This patch implements virtio pci support for QUEUE RESET.
>
> Performing reset on a queue is divided into these steps:
>
>   1. virtio_reset_vq()              - notify the device to reset the queue
>   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>   4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>
> This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
> pci scenario.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_pci_common.c |  8 +--
>   drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
>   2 files changed, 88 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index fdbde1db5ec5..863d3a8a0956 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
>   	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
>   	unsigned long flags;
>   
> -	spin_lock_irqsave(&vp_dev->lock, flags);
> -	list_del(&info->node);
> -	spin_unlock_irqrestore(&vp_dev->lock, flags);
> +	if (!vq->reset) {
> +		spin_lock_irqsave(&vp_dev->lock, flags);
> +		list_del(&info->node);
> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> +	}
>   
>   	vp_dev->del_vq(info);
>   	kfree(info);
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 49a4493732cf..3c67d3607802 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
>   	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
>   			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
>   		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
> +
> +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
> +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
>   }
>   
>   /* virtio config->finalize_features() implementation */
> @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
>   	return 0;
>   }
>   
> +static int vp_modern_reset_vq(struct virtqueue *vq)
> +{
> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +	struct virtio_pci_vq_info *info;
> +	unsigned long flags;
> +	unsigned int irq;
> +
> +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> +		return -ENOENT;
> +
> +	vp_modern_set_queue_reset(mdev, vq->index);
> +
> +	info = vp_dev->vqs[vq->index];
> +
> +	/* delete vq from irq handler */
> +	spin_lock_irqsave(&vp_dev->lock, flags);
> +	list_del(&info->node);
> +	spin_unlock_irqrestore(&vp_dev->lock, flags);
> +
> +	INIT_LIST_HEAD(&info->node);
> +
> +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
> +
> +	/* sync irq callback. */
> +	if (vp_dev->intx_enabled) {
> +		irq = vp_dev->pci_dev->irq;
> +
> +	} else {
> +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
> +			return 0;
> +
> +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
> +	}
> +
> +	synchronize_irq(irq);


Synchronize_irq() is not sufficient here since it breaks the effort of 
the interrupt hardening which is done by commits:

080cd7c3ac87 virtio-pci: harden INTX interrupts
9e35276a5344 virtio_pci: harden MSI-X interrupts

Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were 
used for the affinity managed irq but we're discussing a fix.


> +
> +	return 0;
> +}
> +
> +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
> +{
> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +	struct virtio_pci_vq_info *info;
> +	unsigned long flags, index;
> +	int err;
> +
> +	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
> +		return -EBUSY;
> +
> +	index = vq->index;
> +	info = vp_dev->vqs[index];
> +
> +	/* check queue reset status */
> +	if (vp_modern_get_queue_reset(mdev, index) != 1)
> +		return -EBUSY;
> +
> +	err = vp_active_vq(vq, info->msix_vector);
> +	if (err)
> +		return err;
> +
> +	if (vq->callback) {
> +		spin_lock_irqsave(&vp_dev->lock, flags);
> +		list_add(&info->node, &vp_dev->virtqueues);
> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> +	} else {
> +		INIT_LIST_HEAD(&info->node);
> +	}
> +
> +	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);


Any reason we need to check queue_enable() here?

Thanks


> +	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
> +
> +	return 0;
> +}
> +
>   static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
>   {
>   	return vp_modern_config_vector(&vp_dev->mdev, vector);
> @@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
>   	.set_vq_affinity = vp_set_vq_affinity,
>   	.get_vq_affinity = vp_get_vq_affinity,
>   	.get_shm_region  = vp_get_shm_region,
> +	.reset_vq	 = vp_modern_reset_vq,
> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>   };
>   
>   static const struct virtio_config_ops virtio_pci_config_ops = {
> @@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
>   	.set_vq_affinity = vp_set_vq_affinity,
>   	.get_vq_affinity = vp_get_vq_affinity,
>   	.get_shm_region  = vp_get_shm_region,
> +	.reset_vq	 = vp_modern_reset_vq,
> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>   };
>   
>   /* the PCI probing function */


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-09  8:54     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:54 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> This patch implements virtio pci support for QUEUE RESET.
>
> Performing reset on a queue is divided into these steps:
>
>   1. virtio_reset_vq()              - notify the device to reset the queue
>   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>   4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>
> This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
> pci scenario.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_pci_common.c |  8 +--
>   drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
>   2 files changed, 88 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index fdbde1db5ec5..863d3a8a0956 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
>   	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
>   	unsigned long flags;
>   
> -	spin_lock_irqsave(&vp_dev->lock, flags);
> -	list_del(&info->node);
> -	spin_unlock_irqrestore(&vp_dev->lock, flags);
> +	if (!vq->reset) {
> +		spin_lock_irqsave(&vp_dev->lock, flags);
> +		list_del(&info->node);
> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> +	}
>   
>   	vp_dev->del_vq(info);
>   	kfree(info);
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 49a4493732cf..3c67d3607802 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
>   	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
>   			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
>   		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
> +
> +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
> +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
>   }
>   
>   /* virtio config->finalize_features() implementation */
> @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
>   	return 0;
>   }
>   
> +static int vp_modern_reset_vq(struct virtqueue *vq)
> +{
> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +	struct virtio_pci_vq_info *info;
> +	unsigned long flags;
> +	unsigned int irq;
> +
> +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> +		return -ENOENT;
> +
> +	vp_modern_set_queue_reset(mdev, vq->index);
> +
> +	info = vp_dev->vqs[vq->index];
> +
> +	/* delete vq from irq handler */
> +	spin_lock_irqsave(&vp_dev->lock, flags);
> +	list_del(&info->node);
> +	spin_unlock_irqrestore(&vp_dev->lock, flags);
> +
> +	INIT_LIST_HEAD(&info->node);
> +
> +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
> +
> +	/* sync irq callback. */
> +	if (vp_dev->intx_enabled) {
> +		irq = vp_dev->pci_dev->irq;
> +
> +	} else {
> +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
> +			return 0;
> +
> +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
> +	}
> +
> +	synchronize_irq(irq);


Synchronize_irq() is not sufficient here since it breaks the effort of 
the interrupt hardening which is done by commits:

080cd7c3ac87 virtio-pci: harden INTX interrupts
9e35276a5344 virtio_pci: harden MSI-X interrupts

Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were 
used for the affinity managed irq but we're discussing a fix.


> +
> +	return 0;
> +}
> +
> +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
> +{
> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +	struct virtio_pci_vq_info *info;
> +	unsigned long flags, index;
> +	int err;
> +
> +	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
> +		return -EBUSY;
> +
> +	index = vq->index;
> +	info = vp_dev->vqs[index];
> +
> +	/* check queue reset status */
> +	if (vp_modern_get_queue_reset(mdev, index) != 1)
> +		return -EBUSY;
> +
> +	err = vp_active_vq(vq, info->msix_vector);
> +	if (err)
> +		return err;
> +
> +	if (vq->callback) {
> +		spin_lock_irqsave(&vp_dev->lock, flags);
> +		list_add(&info->node, &vp_dev->virtqueues);
> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> +	} else {
> +		INIT_LIST_HEAD(&info->node);
> +	}
> +
> +	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);


Any reason we need to check queue_enable() here?

Thanks


> +	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
> +
> +	return 0;
> +}
> +
>   static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
>   {
>   	return vp_modern_config_vector(&vp_dev->mdev, vector);
> @@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
>   	.set_vq_affinity = vp_set_vq_affinity,
>   	.get_vq_affinity = vp_get_vq_affinity,
>   	.get_shm_region  = vp_get_shm_region,
> +	.reset_vq	 = vp_modern_reset_vq,
> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>   };
>   
>   static const struct virtio_config_ops virtio_pci_config_ops = {
> @@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
>   	.set_vq_affinity = vp_set_vq_affinity,
>   	.get_vq_affinity = vp_get_vq_affinity,
>   	.get_shm_region  = vp_get_shm_region,
> +	.reset_vq	 = vp_modern_reset_vq,
> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>   };
>   
>   /* the PCI probing function */

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-09  8:54     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:54 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> This patch implements virtio pci support for QUEUE RESET.
>
> Performing reset on a queue is divided into these steps:
>
>   1. virtio_reset_vq()              - notify the device to reset the queue
>   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>   4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>
> This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
> pci scenario.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/virtio/virtio_pci_common.c |  8 +--
>   drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
>   2 files changed, 88 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index fdbde1db5ec5..863d3a8a0956 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
>   	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
>   	unsigned long flags;
>   
> -	spin_lock_irqsave(&vp_dev->lock, flags);
> -	list_del(&info->node);
> -	spin_unlock_irqrestore(&vp_dev->lock, flags);
> +	if (!vq->reset) {
> +		spin_lock_irqsave(&vp_dev->lock, flags);
> +		list_del(&info->node);
> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> +	}
>   
>   	vp_dev->del_vq(info);
>   	kfree(info);
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 49a4493732cf..3c67d3607802 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
>   	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
>   			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
>   		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
> +
> +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
> +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
>   }
>   
>   /* virtio config->finalize_features() implementation */
> @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
>   	return 0;
>   }
>   
> +static int vp_modern_reset_vq(struct virtqueue *vq)
> +{
> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +	struct virtio_pci_vq_info *info;
> +	unsigned long flags;
> +	unsigned int irq;
> +
> +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> +		return -ENOENT;
> +
> +	vp_modern_set_queue_reset(mdev, vq->index);
> +
> +	info = vp_dev->vqs[vq->index];
> +
> +	/* delete vq from irq handler */
> +	spin_lock_irqsave(&vp_dev->lock, flags);
> +	list_del(&info->node);
> +	spin_unlock_irqrestore(&vp_dev->lock, flags);
> +
> +	INIT_LIST_HEAD(&info->node);
> +
> +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
> +
> +	/* sync irq callback. */
> +	if (vp_dev->intx_enabled) {
> +		irq = vp_dev->pci_dev->irq;
> +
> +	} else {
> +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
> +			return 0;
> +
> +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
> +	}
> +
> +	synchronize_irq(irq);


Synchronize_irq() is not sufficient here since it breaks the effort of 
the interrupt hardening which is done by commits:

080cd7c3ac87 virtio-pci: harden INTX interrupts
9e35276a5344 virtio_pci: harden MSI-X interrupts

Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were 
used for the affinity managed irq but we're discussing a fix.


> +
> +	return 0;
> +}
> +
> +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
> +{
> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +	struct virtio_pci_vq_info *info;
> +	unsigned long flags, index;
> +	int err;
> +
> +	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
> +		return -EBUSY;
> +
> +	index = vq->index;
> +	info = vp_dev->vqs[index];
> +
> +	/* check queue reset status */
> +	if (vp_modern_get_queue_reset(mdev, index) != 1)
> +		return -EBUSY;
> +
> +	err = vp_active_vq(vq, info->msix_vector);
> +	if (err)
> +		return err;
> +
> +	if (vq->callback) {
> +		spin_lock_irqsave(&vp_dev->lock, flags);
> +		list_add(&info->node, &vp_dev->virtqueues);
> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> +	} else {
> +		INIT_LIST_HEAD(&info->node);
> +	}
> +
> +	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);


Any reason we need to check queue_enable() here?

Thanks


> +	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
> +
> +	return 0;
> +}
> +
>   static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
>   {
>   	return vp_modern_config_vector(&vp_dev->mdev, vector);
> @@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
>   	.set_vq_affinity = vp_set_vq_affinity,
>   	.get_vq_affinity = vp_get_vq_affinity,
>   	.get_shm_region  = vp_get_shm_region,
> +	.reset_vq	 = vp_modern_reset_vq,
> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>   };
>   
>   static const struct virtio_config_ops virtio_pci_config_ops = {
> @@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
>   	.set_vq_affinity = vp_set_vq_affinity,
>   	.get_vq_affinity = vp_get_vq_affinity,
>   	.get_shm_region  = vp_get_shm_region,
> +	.reset_vq	 = vp_modern_reset_vq,
> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>   };
>   
>   /* the PCI probing function */


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 18/26] virtio: find_vqs() add arg sizes
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-09  8:59     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:59 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> find_vqs() adds a new parameter sizes to specify the size of each vq
> vring.
>
> 0 means use the maximum size supported by the backend.
>
> In the split scenario, the meaning of size is the largest size, because
> it may be limited by memory, the virtio core will try a smaller size.
> And the size is power of 2.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   arch/um/drivers/virtio_uml.c             |  2 +-
>   drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
>   drivers/remoteproc/remoteproc_virtio.c   |  2 +-
>   drivers/s390/virtio/virtio_ccw.c         |  2 +-
>   drivers/virtio/virtio_mmio.c             |  2 +-
>   drivers/virtio/virtio_pci_common.c       |  2 +-
>   drivers/virtio/virtio_pci_common.h       |  2 +-
>   drivers/virtio/virtio_pci_modern.c       |  5 +++--
>   drivers/virtio/virtio_vdpa.c             |  2 +-
>   include/linux/virtio_config.h            | 11 +++++++----
>   10 files changed, 19 insertions(+), 14 deletions(-)
>
> diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> index ba562d68dc04..055b91ccbe8a 100644
> --- a/arch/um/drivers/virtio_uml.c
> +++ b/arch/um/drivers/virtio_uml.c
> @@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
>   static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   		       const char * const names[], const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
>   	int i, queue_idx = 0, rc;
> diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
> index 38800e86ed8a..aea7aa218b22 100644
> --- a/drivers/platform/mellanox/mlxbf-tmfifo.c
> +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
> @@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
>   					vq_callback_t *callbacks[],
>   					const char * const names[],


Nit: Let's be consistent here, e.g move sizes before ctx (this is what 
next patch did and seems cleaner).

Thanks


>   					const bool *ctx,
> -					struct irq_affinity *desc)
> +					struct irq_affinity *desc,
> +					u32 sizes[])
>   {
>   	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
>   	struct mlxbf_tmfifo_vring *vring;
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index 70ab496d0431..3a167bec5b09 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
>   				 vq_callback_t *callbacks[],
>   				 const char * const names[],
>   				 const bool * ctx,
> -				 struct irq_affinity *desc)
> +				 struct irq_affinity *desc, u32 sizes[])
>   {
>   	int i, ret, queue_idx = 0;
>   
> diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
> index d35e7a3f7067..b74e08c71534 100644
> --- a/drivers/s390/virtio/virtio_ccw.c
> +++ b/drivers/s390/virtio/virtio_ccw.c
> @@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   			       vq_callback_t *callbacks[],
>   			       const char * const names[],
>   			       const bool *ctx,
> -			       struct irq_affinity *desc)
> +			       struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
>   	unsigned long *indicatorp = NULL;
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index a41abc8051b9..55d575f6ef2d 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		       vq_callback_t *callbacks[],
>   		       const char * const names[],
>   		       const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
>   	int irq = platform_get_irq(vm_dev->pdev, 0);
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 863d3a8a0956..8e8fa7e5ad80 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
>   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc)
> +		struct irq_affinity *desc, u32 sizes[])
>   {
>   	int err;
>   
> diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> index 23f6c5c678d5..9dbf1d555dff 100644
> --- a/drivers/virtio/virtio_pci_common.h
> +++ b/drivers/virtio/virtio_pci_common.h
> @@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
>   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc);
> +		struct irq_affinity *desc, u32 sizes[]);
>   const char *vp_bus_name(struct virtio_device *vdev);
>   
>   /* Setup the affinity for a virtqueue:
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 3c67d3607802..342795175c29 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   			      struct virtqueue *vqs[],
>   			      vq_callback_t *callbacks[],
>   			      const char * const names[], const bool *ctx,
> -			      struct irq_affinity *desc)
> +			      struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
>   	struct virtqueue *vq;
> -	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
> +	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
> +			     sizes);
>   
>   	if (rc)
>   		return rc;
> diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
> index 7767a7f0119b..ee08d01ee8b1 100644
> --- a/drivers/virtio/virtio_vdpa.c
> +++ b/drivers/virtio/virtio_vdpa.c
> @@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   				vq_callback_t *callbacks[],
>   				const char * const names[],
>   				const bool *ctx,
> -				struct irq_affinity *desc)
> +				struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
>   	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 0b81fbe17c85..5157524d8036 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -57,6 +57,7 @@ struct virtio_shm_region {
>    *		include a NULL entry for vqs that do not need a callback
>    *	names: array of virtqueue names (mainly for debugging)
>    *		include a NULL entry for vqs unused by driver
> + *	sizes: array of virtqueue sizes
>    *	Returns 0 on success or error status
>    * @del_vqs: free virtqueues found by find_vqs().
>    * @get_features: get the array of feature bits for this device.
> @@ -98,7 +99,8 @@ struct virtio_config_ops {
>   	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
>   			struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   			const char * const names[], const bool *ctx,
> -			struct irq_affinity *desc);
> +			struct irq_affinity *desc,
> +			u32 sizes[]);
>   	void (*del_vqs)(struct virtio_device *);
>   	u64 (*get_features)(struct virtio_device *vdev);
>   	int (*finalize_features)(struct virtio_device *vdev);
> @@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
>   	const char *names[] = { n };
>   	struct virtqueue *vq;
>   	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
> -					 NULL);
> +					 NULL, NULL);
>   	if (err < 0)
>   		return ERR_PTR(err);
>   	return vq;
> @@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   			const char * const names[],
>   			struct irq_affinity *desc)
>   {
> -	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
> +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
> +				      desc, NULL);
>   }
>   
>   static inline
> @@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>   			struct irq_affinity *desc)
>   {
>   	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> -				      desc);
> +				      desc, NULL);
>   }
>   
>   /**


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 18/26] virtio: find_vqs() add arg sizes
@ 2022-03-09  8:59     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:59 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> find_vqs() adds a new parameter sizes to specify the size of each vq
> vring.
>
> 0 means use the maximum size supported by the backend.
>
> In the split scenario, the meaning of size is the largest size, because
> it may be limited by memory, the virtio core will try a smaller size.
> And the size is power of 2.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   arch/um/drivers/virtio_uml.c             |  2 +-
>   drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
>   drivers/remoteproc/remoteproc_virtio.c   |  2 +-
>   drivers/s390/virtio/virtio_ccw.c         |  2 +-
>   drivers/virtio/virtio_mmio.c             |  2 +-
>   drivers/virtio/virtio_pci_common.c       |  2 +-
>   drivers/virtio/virtio_pci_common.h       |  2 +-
>   drivers/virtio/virtio_pci_modern.c       |  5 +++--
>   drivers/virtio/virtio_vdpa.c             |  2 +-
>   include/linux/virtio_config.h            | 11 +++++++----
>   10 files changed, 19 insertions(+), 14 deletions(-)
>
> diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> index ba562d68dc04..055b91ccbe8a 100644
> --- a/arch/um/drivers/virtio_uml.c
> +++ b/arch/um/drivers/virtio_uml.c
> @@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
>   static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   		       const char * const names[], const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
>   	int i, queue_idx = 0, rc;
> diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
> index 38800e86ed8a..aea7aa218b22 100644
> --- a/drivers/platform/mellanox/mlxbf-tmfifo.c
> +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
> @@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
>   					vq_callback_t *callbacks[],
>   					const char * const names[],


Nit: Let's be consistent here, e.g move sizes before ctx (this is what 
next patch did and seems cleaner).

Thanks


>   					const bool *ctx,
> -					struct irq_affinity *desc)
> +					struct irq_affinity *desc,
> +					u32 sizes[])
>   {
>   	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
>   	struct mlxbf_tmfifo_vring *vring;
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index 70ab496d0431..3a167bec5b09 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
>   				 vq_callback_t *callbacks[],
>   				 const char * const names[],
>   				 const bool * ctx,
> -				 struct irq_affinity *desc)
> +				 struct irq_affinity *desc, u32 sizes[])
>   {
>   	int i, ret, queue_idx = 0;
>   
> diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
> index d35e7a3f7067..b74e08c71534 100644
> --- a/drivers/s390/virtio/virtio_ccw.c
> +++ b/drivers/s390/virtio/virtio_ccw.c
> @@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   			       vq_callback_t *callbacks[],
>   			       const char * const names[],
>   			       const bool *ctx,
> -			       struct irq_affinity *desc)
> +			       struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
>   	unsigned long *indicatorp = NULL;
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index a41abc8051b9..55d575f6ef2d 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		       vq_callback_t *callbacks[],
>   		       const char * const names[],
>   		       const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
>   	int irq = platform_get_irq(vm_dev->pdev, 0);
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 863d3a8a0956..8e8fa7e5ad80 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
>   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc)
> +		struct irq_affinity *desc, u32 sizes[])
>   {
>   	int err;
>   
> diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> index 23f6c5c678d5..9dbf1d555dff 100644
> --- a/drivers/virtio/virtio_pci_common.h
> +++ b/drivers/virtio/virtio_pci_common.h
> @@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
>   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc);
> +		struct irq_affinity *desc, u32 sizes[]);
>   const char *vp_bus_name(struct virtio_device *vdev);
>   
>   /* Setup the affinity for a virtqueue:
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 3c67d3607802..342795175c29 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   			      struct virtqueue *vqs[],
>   			      vq_callback_t *callbacks[],
>   			      const char * const names[], const bool *ctx,
> -			      struct irq_affinity *desc)
> +			      struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
>   	struct virtqueue *vq;
> -	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
> +	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
> +			     sizes);
>   
>   	if (rc)
>   		return rc;
> diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
> index 7767a7f0119b..ee08d01ee8b1 100644
> --- a/drivers/virtio/virtio_vdpa.c
> +++ b/drivers/virtio/virtio_vdpa.c
> @@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   				vq_callback_t *callbacks[],
>   				const char * const names[],
>   				const bool *ctx,
> -				struct irq_affinity *desc)
> +				struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
>   	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 0b81fbe17c85..5157524d8036 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -57,6 +57,7 @@ struct virtio_shm_region {
>    *		include a NULL entry for vqs that do not need a callback
>    *	names: array of virtqueue names (mainly for debugging)
>    *		include a NULL entry for vqs unused by driver
> + *	sizes: array of virtqueue sizes
>    *	Returns 0 on success or error status
>    * @del_vqs: free virtqueues found by find_vqs().
>    * @get_features: get the array of feature bits for this device.
> @@ -98,7 +99,8 @@ struct virtio_config_ops {
>   	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
>   			struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   			const char * const names[], const bool *ctx,
> -			struct irq_affinity *desc);
> +			struct irq_affinity *desc,
> +			u32 sizes[]);
>   	void (*del_vqs)(struct virtio_device *);
>   	u64 (*get_features)(struct virtio_device *vdev);
>   	int (*finalize_features)(struct virtio_device *vdev);
> @@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
>   	const char *names[] = { n };
>   	struct virtqueue *vq;
>   	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
> -					 NULL);
> +					 NULL, NULL);
>   	if (err < 0)
>   		return ERR_PTR(err);
>   	return vq;
> @@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   			const char * const names[],
>   			struct irq_affinity *desc)
>   {
> -	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
> +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
> +				      desc, NULL);
>   }
>   
>   static inline
> @@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>   			struct irq_affinity *desc)
>   {
>   	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> -				      desc);
> +				      desc, NULL);
>   }
>   
>   /**

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 18/26] virtio: find_vqs() add arg sizes
@ 2022-03-09  8:59     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  8:59 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> find_vqs() adds a new parameter sizes to specify the size of each vq
> vring.
>
> 0 means use the maximum size supported by the backend.
>
> In the split scenario, the meaning of size is the largest size, because
> it may be limited by memory, the virtio core will try a smaller size.
> And the size is power of 2.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   arch/um/drivers/virtio_uml.c             |  2 +-
>   drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
>   drivers/remoteproc/remoteproc_virtio.c   |  2 +-
>   drivers/s390/virtio/virtio_ccw.c         |  2 +-
>   drivers/virtio/virtio_mmio.c             |  2 +-
>   drivers/virtio/virtio_pci_common.c       |  2 +-
>   drivers/virtio/virtio_pci_common.h       |  2 +-
>   drivers/virtio/virtio_pci_modern.c       |  5 +++--
>   drivers/virtio/virtio_vdpa.c             |  2 +-
>   include/linux/virtio_config.h            | 11 +++++++----
>   10 files changed, 19 insertions(+), 14 deletions(-)
>
> diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> index ba562d68dc04..055b91ccbe8a 100644
> --- a/arch/um/drivers/virtio_uml.c
> +++ b/arch/um/drivers/virtio_uml.c
> @@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
>   static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   		       const char * const names[], const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
>   	int i, queue_idx = 0, rc;
> diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
> index 38800e86ed8a..aea7aa218b22 100644
> --- a/drivers/platform/mellanox/mlxbf-tmfifo.c
> +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
> @@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
>   					vq_callback_t *callbacks[],
>   					const char * const names[],


Nit: Let's be consistent here, e.g move sizes before ctx (this is what 
next patch did and seems cleaner).

Thanks


>   					const bool *ctx,
> -					struct irq_affinity *desc)
> +					struct irq_affinity *desc,
> +					u32 sizes[])
>   {
>   	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
>   	struct mlxbf_tmfifo_vring *vring;
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index 70ab496d0431..3a167bec5b09 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
>   				 vq_callback_t *callbacks[],
>   				 const char * const names[],
>   				 const bool * ctx,
> -				 struct irq_affinity *desc)
> +				 struct irq_affinity *desc, u32 sizes[])
>   {
>   	int i, ret, queue_idx = 0;
>   
> diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
> index d35e7a3f7067..b74e08c71534 100644
> --- a/drivers/s390/virtio/virtio_ccw.c
> +++ b/drivers/s390/virtio/virtio_ccw.c
> @@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   			       vq_callback_t *callbacks[],
>   			       const char * const names[],
>   			       const bool *ctx,
> -			       struct irq_affinity *desc)
> +			       struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
>   	unsigned long *indicatorp = NULL;
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index a41abc8051b9..55d575f6ef2d 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		       vq_callback_t *callbacks[],
>   		       const char * const names[],
>   		       const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
>   	int irq = platform_get_irq(vm_dev->pdev, 0);
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 863d3a8a0956..8e8fa7e5ad80 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
>   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc)
> +		struct irq_affinity *desc, u32 sizes[])
>   {
>   	int err;
>   
> diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> index 23f6c5c678d5..9dbf1d555dff 100644
> --- a/drivers/virtio/virtio_pci_common.h
> +++ b/drivers/virtio/virtio_pci_common.h
> @@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
>   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc);
> +		struct irq_affinity *desc, u32 sizes[]);
>   const char *vp_bus_name(struct virtio_device *vdev);
>   
>   /* Setup the affinity for a virtqueue:
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 3c67d3607802..342795175c29 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   			      struct virtqueue *vqs[],
>   			      vq_callback_t *callbacks[],
>   			      const char * const names[], const bool *ctx,
> -			      struct irq_affinity *desc)
> +			      struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
>   	struct virtqueue *vq;
> -	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
> +	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
> +			     sizes);
>   
>   	if (rc)
>   		return rc;
> diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
> index 7767a7f0119b..ee08d01ee8b1 100644
> --- a/drivers/virtio/virtio_vdpa.c
> +++ b/drivers/virtio/virtio_vdpa.c
> @@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   				vq_callback_t *callbacks[],
>   				const char * const names[],
>   				const bool *ctx,
> -				struct irq_affinity *desc)
> +				struct irq_affinity *desc, u32 sizes[])
>   {
>   	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
>   	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 0b81fbe17c85..5157524d8036 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -57,6 +57,7 @@ struct virtio_shm_region {
>    *		include a NULL entry for vqs that do not need a callback
>    *	names: array of virtqueue names (mainly for debugging)
>    *		include a NULL entry for vqs unused by driver
> + *	sizes: array of virtqueue sizes
>    *	Returns 0 on success or error status
>    * @del_vqs: free virtqueues found by find_vqs().
>    * @get_features: get the array of feature bits for this device.
> @@ -98,7 +99,8 @@ struct virtio_config_ops {
>   	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
>   			struct virtqueue *vqs[], vq_callback_t *callbacks[],
>   			const char * const names[], const bool *ctx,
> -			struct irq_affinity *desc);
> +			struct irq_affinity *desc,
> +			u32 sizes[]);
>   	void (*del_vqs)(struct virtio_device *);
>   	u64 (*get_features)(struct virtio_device *vdev);
>   	int (*finalize_features)(struct virtio_device *vdev);
> @@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
>   	const char *names[] = { n };
>   	struct virtqueue *vq;
>   	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
> -					 NULL);
> +					 NULL, NULL);
>   	if (err < 0)
>   		return ERR_PTR(err);
>   	return vq;
> @@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>   			const char * const names[],
>   			struct irq_affinity *desc)
>   {
> -	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
> +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
> +				      desc, NULL);
>   }
>   
>   static inline
> @@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>   			struct irq_affinity *desc)
>   {
>   	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> -				      desc);
> +				      desc, NULL);
>   }
>   
>   /**


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 00/26] virtio pci support VIRTIO_F_RING_RESET
  2022-03-09  4:45   ` Jason Wang
  (?)
@ 2022-03-09  9:02     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-09  9:02 UTC (permalink / raw)
  To: Jason Wang
  Cc: Xuan Zhuo, virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf

On Wed, Mar 09, 2022 at 12:45:57PM +0800, Jason Wang wrote:
> 
> 在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> > The virtio spec already supports the virtio queue reset function. This patch set
> > is to add this function to the kernel. The relevant virtio spec information is
> > here:
> > 
> >      https://github.com/oasis-tcs/virtio-spec/issues/124
> > 
> > Also regarding MMIO support for queue reset, I plan to support it after this
> > patch is passed.
> > 
> > Performing reset on a queue is divided into four steps:
> >       1. virtio_reset_vq()              - notify the device to reset the queue
> >       2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >       3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >       4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> > 
> > The first part 1-17 of this patch set implements virtio pci's support and API
> > for queue reset. The latter part is to make virtio-net support set_ringparam. Do
> > these things for this feature:
> > 
> >        1. virtio-net support rx,tx reset
> >        2. find_vqs() support to special the max size of each vq
> >        3. virtio-net support set_ringparam
> > 
> > #1 -#3 :       prepare
> > #4 -#12:       virtio ring support reset vring of the vq
> > #13-#14:       add helper
> > #15-#17:       virtio pci support reset queue and re-enable
> > #18-#21:       find_vqs() support sizes to special the max size of each vq
> > #23-#24:       virtio-net support rx, tx reset
> > #22, #25, #26: virtio-net support set ringparam
> > 
> > Test environment:
> >      Host: 4.19.91
> >      Qemu: QEMU emulator version 6.2.50 (with vq reset support)
> >      Test Cmd:  ethtool -G eth1 rx $1 tx $2; ethtool -g eth1
> > 
> >      The default is split mode, modify Qemu virtio-net to add PACKED feature to test
> >      packed mode.
> > 
> > 
> > Please review. Thanks.
> > 
> > v7:
> >    1. fix #6 subject typo
> >    2. fix #6 ring_size_in_bytes is uninitialized
> >    3. check by: make W=12
> > 
> > v6:
> >    1. virtio_pci: use synchronize_irq(irq) to sync the irq callbacks
> >    2. Introduce virtqueue_reset_vring() to implement the reset of vring during
> >       the reset process. May use the old vring if num of the vq not change.
> >    3. find_vqs() support sizes to special the max size of each vq
> > 
> > v5:
> >    1. add virtio-net support set_ringparam
> > 
> > v4:
> >    1. just the code of virtio, without virtio-net
> >    2. Performing reset on a queue is divided into these steps:
> >      1. reset_vq: reset one vq
> >      2. recycle the buffer from vq by virtqueue_detach_unused_buf()
> >      3. release the ring of the vq by vring_release_virtqueue()
> >      4. enable_reset_vq: re-enable the reset queue
> >    3. Simplify the parameters of enable_reset_vq()
> >    4. add container structures for virtio_pci_common_cfg
> > 
> > v3:
> >    1. keep vq, irq unreleased
> 
> 
> The series became kind of huge.
> 
> I'd suggest to split it into two series.
> 
> 1) refactoring of the virtio_ring to prepare for the resize
> 2) the reset support + virtio-net support
> 
> Thanks


And just to clarify, I think you mean all the "extract logic"
things need to also go into the refactoring part, right?
Just making 3 first patches a series by themselves won't help ...
I'm kind of ambivalent on the splitup - both parts
need work for now, so I wonder how does it help.
But if you care about it, I don't mind.

> > 
> > *** BLURB HERE ***


You don't want this in your cover letters btw.

> > Xuan Zhuo (26):
> >    virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
> >    virtio: queue_reset: add VIRTIO_F_RING_RESET
> >    virtio: add helper virtqueue_get_vring_max_size()
> >    virtio_ring: split: extract the logic of creating vring
> >    virtio_ring: split: extract the logic of init vq and attach vring
> >    virtio_ring: packed: extract the logic of creating vring
> >    virtio_ring: packed: extract the logic of init vq and attach vring
> >    virtio_ring: extract the logic of freeing vring
> >    virtio_ring: split: implement virtqueue_reset_vring_split()
> >    virtio_ring: packed: implement virtqueue_reset_vring_packed()
> >    virtio_ring: introduce virtqueue_reset_vring()
> >    virtio_ring: update the document of the virtqueue_detach_unused_buf
> >      for queue reset
> >    virtio: queue_reset: struct virtio_config_ops add callbacks for
> >      queue_reset
> >    virtio: add helper for queue reset
> >    virtio_pci: queue_reset: update struct virtio_pci_common_cfg and
> >      option functions
> >    virtio_pci: queue_reset: extract the logic of active vq for modern pci
> >    virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
> >    virtio: find_vqs() add arg sizes
> >    virtio_pci: support the arg sizes of find_vqs()
> >    virtio_mmio: support the arg sizes of find_vqs()
> >    virtio: add helper virtio_find_vqs_ctx_size()
> >    virtio_net: get ringparam by virtqueue_get_vring_max_size()
> >    virtio_net: split free_unused_bufs()
> >    virtio_net: support rx/tx queue reset
> >    virtio_net: set the default max ring size by find_vqs()
> >    virtio_net: support set_ringparam
> > 
> >   arch/um/drivers/virtio_uml.c             |   2 +-
> >   drivers/net/virtio_net.c                 | 257 ++++++++--
> >   drivers/platform/mellanox/mlxbf-tmfifo.c |   3 +-
> >   drivers/remoteproc/remoteproc_virtio.c   |   2 +-
> >   drivers/s390/virtio/virtio_ccw.c         |   2 +-
> >   drivers/virtio/virtio_mmio.c             |  12 +-
> >   drivers/virtio/virtio_pci_common.c       |  28 +-
> >   drivers/virtio/virtio_pci_common.h       |   3 +-
> >   drivers/virtio/virtio_pci_legacy.c       |   8 +-
> >   drivers/virtio/virtio_pci_modern.c       | 146 +++++-
> >   drivers/virtio/virtio_pci_modern_dev.c   |  36 ++
> >   drivers/virtio/virtio_ring.c             | 584 +++++++++++++++++------
> >   drivers/virtio/virtio_vdpa.c             |   2 +-
> >   include/linux/virtio.h                   |  12 +
> >   include/linux/virtio_config.h            |  74 ++-
> >   include/linux/virtio_pci_modern.h        |   2 +
> >   include/uapi/linux/virtio_config.h       |   7 +-
> >   include/uapi/linux/virtio_pci.h          |  14 +
> >   18 files changed, 979 insertions(+), 215 deletions(-)
> > 
> > --
> > 2.31.0
> > 


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 00/26] virtio pci support VIRTIO_F_RING_RESET
@ 2022-03-09  9:02     ` Michael S. Tsirkin
  0 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-09  9:02 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, linux-remoteproc, Alexei Starovoitov,
	virtualization, Alexander Gordeev, Anton Ivanov, Johannes Berg,
	Daniel Borkmann, Richard Weinberger, Vincent Whitchurch,
	John Fastabend, Halil Pasic, Jakub Kicinski, Heiko Carstens,
	platform-driver-x86, Jesper Dangaard Brouer, Vasily Gorbik,
	linux-s390, Jeff Dike, linux-um, Mark Gross, Hans de Goede, kvm,
	Bjorn Andersson, Mathieu Poirier, netdev, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

On Wed, Mar 09, 2022 at 12:45:57PM +0800, Jason Wang wrote:
> 
> 在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> > The virtio spec already supports the virtio queue reset function. This patch set
> > is to add this function to the kernel. The relevant virtio spec information is
> > here:
> > 
> >      https://github.com/oasis-tcs/virtio-spec/issues/124
> > 
> > Also regarding MMIO support for queue reset, I plan to support it after this
> > patch is passed.
> > 
> > Performing reset on a queue is divided into four steps:
> >       1. virtio_reset_vq()              - notify the device to reset the queue
> >       2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >       3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >       4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> > 
> > The first part 1-17 of this patch set implements virtio pci's support and API
> > for queue reset. The latter part is to make virtio-net support set_ringparam. Do
> > these things for this feature:
> > 
> >        1. virtio-net support rx,tx reset
> >        2. find_vqs() support to special the max size of each vq
> >        3. virtio-net support set_ringparam
> > 
> > #1 -#3 :       prepare
> > #4 -#12:       virtio ring support reset vring of the vq
> > #13-#14:       add helper
> > #15-#17:       virtio pci support reset queue and re-enable
> > #18-#21:       find_vqs() support sizes to special the max size of each vq
> > #23-#24:       virtio-net support rx, tx reset
> > #22, #25, #26: virtio-net support set ringparam
> > 
> > Test environment:
> >      Host: 4.19.91
> >      Qemu: QEMU emulator version 6.2.50 (with vq reset support)
> >      Test Cmd:  ethtool -G eth1 rx $1 tx $2; ethtool -g eth1
> > 
> >      The default is split mode, modify Qemu virtio-net to add PACKED feature to test
> >      packed mode.
> > 
> > 
> > Please review. Thanks.
> > 
> > v7:
> >    1. fix #6 subject typo
> >    2. fix #6 ring_size_in_bytes is uninitialized
> >    3. check by: make W=12
> > 
> > v6:
> >    1. virtio_pci: use synchronize_irq(irq) to sync the irq callbacks
> >    2. Introduce virtqueue_reset_vring() to implement the reset of vring during
> >       the reset process. May use the old vring if num of the vq not change.
> >    3. find_vqs() support sizes to special the max size of each vq
> > 
> > v5:
> >    1. add virtio-net support set_ringparam
> > 
> > v4:
> >    1. just the code of virtio, without virtio-net
> >    2. Performing reset on a queue is divided into these steps:
> >      1. reset_vq: reset one vq
> >      2. recycle the buffer from vq by virtqueue_detach_unused_buf()
> >      3. release the ring of the vq by vring_release_virtqueue()
> >      4. enable_reset_vq: re-enable the reset queue
> >    3. Simplify the parameters of enable_reset_vq()
> >    4. add container structures for virtio_pci_common_cfg
> > 
> > v3:
> >    1. keep vq, irq unreleased
> 
> 
> The series became kind of huge.
> 
> I'd suggest to split it into two series.
> 
> 1) refactoring of the virtio_ring to prepare for the resize
> 2) the reset support + virtio-net support
> 
> Thanks


And just to clarify, I think you mean all the "extract logic"
things need to also go into the refactoring part, right?
Just making 3 first patches a series by themselves won't help ...
I'm kind of ambivalent on the splitup - both parts
need work for now, so I wonder how does it help.
But if you care about it, I don't mind.

> > 
> > *** BLURB HERE ***


You don't want this in your cover letters btw.

> > Xuan Zhuo (26):
> >    virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
> >    virtio: queue_reset: add VIRTIO_F_RING_RESET
> >    virtio: add helper virtqueue_get_vring_max_size()
> >    virtio_ring: split: extract the logic of creating vring
> >    virtio_ring: split: extract the logic of init vq and attach vring
> >    virtio_ring: packed: extract the logic of creating vring
> >    virtio_ring: packed: extract the logic of init vq and attach vring
> >    virtio_ring: extract the logic of freeing vring
> >    virtio_ring: split: implement virtqueue_reset_vring_split()
> >    virtio_ring: packed: implement virtqueue_reset_vring_packed()
> >    virtio_ring: introduce virtqueue_reset_vring()
> >    virtio_ring: update the document of the virtqueue_detach_unused_buf
> >      for queue reset
> >    virtio: queue_reset: struct virtio_config_ops add callbacks for
> >      queue_reset
> >    virtio: add helper for queue reset
> >    virtio_pci: queue_reset: update struct virtio_pci_common_cfg and
> >      option functions
> >    virtio_pci: queue_reset: extract the logic of active vq for modern pci
> >    virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
> >    virtio: find_vqs() add arg sizes
> >    virtio_pci: support the arg sizes of find_vqs()
> >    virtio_mmio: support the arg sizes of find_vqs()
> >    virtio: add helper virtio_find_vqs_ctx_size()
> >    virtio_net: get ringparam by virtqueue_get_vring_max_size()
> >    virtio_net: split free_unused_bufs()
> >    virtio_net: support rx/tx queue reset
> >    virtio_net: set the default max ring size by find_vqs()
> >    virtio_net: support set_ringparam
> > 
> >   arch/um/drivers/virtio_uml.c             |   2 +-
> >   drivers/net/virtio_net.c                 | 257 ++++++++--
> >   drivers/platform/mellanox/mlxbf-tmfifo.c |   3 +-
> >   drivers/remoteproc/remoteproc_virtio.c   |   2 +-
> >   drivers/s390/virtio/virtio_ccw.c         |   2 +-
> >   drivers/virtio/virtio_mmio.c             |  12 +-
> >   drivers/virtio/virtio_pci_common.c       |  28 +-
> >   drivers/virtio/virtio_pci_common.h       |   3 +-
> >   drivers/virtio/virtio_pci_legacy.c       |   8 +-
> >   drivers/virtio/virtio_pci_modern.c       | 146 +++++-
> >   drivers/virtio/virtio_pci_modern_dev.c   |  36 ++
> >   drivers/virtio/virtio_ring.c             | 584 +++++++++++++++++------
> >   drivers/virtio/virtio_vdpa.c             |   2 +-
> >   include/linux/virtio.h                   |  12 +
> >   include/linux/virtio_config.h            |  74 ++-
> >   include/linux/virtio_pci_modern.h        |   2 +
> >   include/uapi/linux/virtio_config.h       |   7 +-
> >   include/uapi/linux/virtio_pci.h          |  14 +
> >   18 files changed, 979 insertions(+), 215 deletions(-)
> > 
> > --
> > 2.31.0
> > 

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 00/26] virtio pci support VIRTIO_F_RING_RESET
@ 2022-03-09  9:02     ` Michael S. Tsirkin
  0 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-09  9:02 UTC (permalink / raw)
  To: Jason Wang
  Cc: Xuan Zhuo, virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, David S. Miller, Jakub Kicinski, Hans de Goede,
	Mark Gross, Vadim Pasternak, Bjorn Andersson, Mathieu Poirier,
	Cornelia Huck, Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf

On Wed, Mar 09, 2022 at 12:45:57PM +0800, Jason Wang wrote:
> 
> 在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> > The virtio spec already supports the virtio queue reset function. This patch set
> > is to add this function to the kernel. The relevant virtio spec information is
> > here:
> > 
> >      https://github.com/oasis-tcs/virtio-spec/issues/124
> > 
> > Also regarding MMIO support for queue reset, I plan to support it after this
> > patch is passed.
> > 
> > Performing reset on a queue is divided into four steps:
> >       1. virtio_reset_vq()              - notify the device to reset the queue
> >       2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >       3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >       4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> > 
> > The first part 1-17 of this patch set implements virtio pci's support and API
> > for queue reset. The latter part is to make virtio-net support set_ringparam. Do
> > these things for this feature:
> > 
> >        1. virtio-net support rx,tx reset
> >        2. find_vqs() support to special the max size of each vq
> >        3. virtio-net support set_ringparam
> > 
> > #1 -#3 :       prepare
> > #4 -#12:       virtio ring support reset vring of the vq
> > #13-#14:       add helper
> > #15-#17:       virtio pci support reset queue and re-enable
> > #18-#21:       find_vqs() support sizes to special the max size of each vq
> > #23-#24:       virtio-net support rx, tx reset
> > #22, #25, #26: virtio-net support set ringparam
> > 
> > Test environment:
> >      Host: 4.19.91
> >      Qemu: QEMU emulator version 6.2.50 (with vq reset support)
> >      Test Cmd:  ethtool -G eth1 rx $1 tx $2; ethtool -g eth1
> > 
> >      The default is split mode, modify Qemu virtio-net to add PACKED feature to test
> >      packed mode.
> > 
> > 
> > Please review. Thanks.
> > 
> > v7:
> >    1. fix #6 subject typo
> >    2. fix #6 ring_size_in_bytes is uninitialized
> >    3. check by: make W=12
> > 
> > v6:
> >    1. virtio_pci: use synchronize_irq(irq) to sync the irq callbacks
> >    2. Introduce virtqueue_reset_vring() to implement the reset of vring during
> >       the reset process. May use the old vring if num of the vq not change.
> >    3. find_vqs() support sizes to special the max size of each vq
> > 
> > v5:
> >    1. add virtio-net support set_ringparam
> > 
> > v4:
> >    1. just the code of virtio, without virtio-net
> >    2. Performing reset on a queue is divided into these steps:
> >      1. reset_vq: reset one vq
> >      2. recycle the buffer from vq by virtqueue_detach_unused_buf()
> >      3. release the ring of the vq by vring_release_virtqueue()
> >      4. enable_reset_vq: re-enable the reset queue
> >    3. Simplify the parameters of enable_reset_vq()
> >    4. add container structures for virtio_pci_common_cfg
> > 
> > v3:
> >    1. keep vq, irq unreleased
> 
> 
> The series became kind of huge.
> 
> I'd suggest to split it into two series.
> 
> 1) refactoring of the virtio_ring to prepare for the resize
> 2) the reset support + virtio-net support
> 
> Thanks


And just to clarify, I think you mean all the "extract logic"
things need to also go into the refactoring part, right?
Just making 3 first patches a series by themselves won't help ...
I'm kind of ambivalent on the splitup - both parts
need work for now, so I wonder how does it help.
But if you care about it, I don't mind.

> > 
> > *** BLURB HERE ***


You don't want this in your cover letters btw.

> > Xuan Zhuo (26):
> >    virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
> >    virtio: queue_reset: add VIRTIO_F_RING_RESET
> >    virtio: add helper virtqueue_get_vring_max_size()
> >    virtio_ring: split: extract the logic of creating vring
> >    virtio_ring: split: extract the logic of init vq and attach vring
> >    virtio_ring: packed: extract the logic of creating vring
> >    virtio_ring: packed: extract the logic of init vq and attach vring
> >    virtio_ring: extract the logic of freeing vring
> >    virtio_ring: split: implement virtqueue_reset_vring_split()
> >    virtio_ring: packed: implement virtqueue_reset_vring_packed()
> >    virtio_ring: introduce virtqueue_reset_vring()
> >    virtio_ring: update the document of the virtqueue_detach_unused_buf
> >      for queue reset
> >    virtio: queue_reset: struct virtio_config_ops add callbacks for
> >      queue_reset
> >    virtio: add helper for queue reset
> >    virtio_pci: queue_reset: update struct virtio_pci_common_cfg and
> >      option functions
> >    virtio_pci: queue_reset: extract the logic of active vq for modern pci
> >    virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
> >    virtio: find_vqs() add arg sizes
> >    virtio_pci: support the arg sizes of find_vqs()
> >    virtio_mmio: support the arg sizes of find_vqs()
> >    virtio: add helper virtio_find_vqs_ctx_size()
> >    virtio_net: get ringparam by virtqueue_get_vring_max_size()
> >    virtio_net: split free_unused_bufs()
> >    virtio_net: support rx/tx queue reset
> >    virtio_net: set the default max ring size by find_vqs()
> >    virtio_net: support set_ringparam
> > 
> >   arch/um/drivers/virtio_uml.c             |   2 +-
> >   drivers/net/virtio_net.c                 | 257 ++++++++--
> >   drivers/platform/mellanox/mlxbf-tmfifo.c |   3 +-
> >   drivers/remoteproc/remoteproc_virtio.c   |   2 +-
> >   drivers/s390/virtio/virtio_ccw.c         |   2 +-
> >   drivers/virtio/virtio_mmio.c             |  12 +-
> >   drivers/virtio/virtio_pci_common.c       |  28 +-
> >   drivers/virtio/virtio_pci_common.h       |   3 +-
> >   drivers/virtio/virtio_pci_legacy.c       |   8 +-
> >   drivers/virtio/virtio_pci_modern.c       | 146 +++++-
> >   drivers/virtio/virtio_pci_modern_dev.c   |  36 ++
> >   drivers/virtio/virtio_ring.c             | 584 +++++++++++++++++------
> >   drivers/virtio/virtio_vdpa.c             |   2 +-
> >   include/linux/virtio.h                   |  12 +
> >   include/linux/virtio_config.h            |  74 ++-
> >   include/linux/virtio_pci_modern.h        |   2 +
> >   include/uapi/linux/virtio_config.h       |   7 +-
> >   include/uapi/linux/virtio_pci.h          |  14 +
> >   18 files changed, 979 insertions(+), 215 deletions(-)
> > 
> > --
> > 2.31.0
> > 


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 21/26] virtio: add helper virtio_find_vqs_ctx_size()
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-09  9:04     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:04 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Introduce helper virtio_find_vqs_ctx_size() to call find_vqs and specify
> the maximum size of each vq ring.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/linux/virtio_config.h | 12 ++++++++++++
>   1 file changed, 12 insertions(+)
>
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 5157524d8036..921d8610db0c 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -233,6 +233,18 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>   				      desc, NULL);
>   }
>   
> +static inline
> +int virtio_find_vqs_ctx_size(struct virtio_device *vdev, u32 nvqs,
> +				 struct virtqueue *vqs[],
> +				 vq_callback_t *callbacks[],
> +				 const char * const names[],
> +				 const bool *ctx, struct irq_affinity *desc,
> +				 u32 sizes[])
> +{
> +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> +				      desc, sizes);
> +}


Do we need to convert all the open coded direct call to find_vqs() other 
than net?

Thanks


> +
>   /**
>    * virtio_reset_vq - reset a queue individually
>    * @vq: the virtqueue


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 21/26] virtio: add helper virtio_find_vqs_ctx_size()
@ 2022-03-09  9:04     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:04 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Introduce helper virtio_find_vqs_ctx_size() to call find_vqs and specify
> the maximum size of each vq ring.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/linux/virtio_config.h | 12 ++++++++++++
>   1 file changed, 12 insertions(+)
>
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 5157524d8036..921d8610db0c 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -233,6 +233,18 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>   				      desc, NULL);
>   }
>   
> +static inline
> +int virtio_find_vqs_ctx_size(struct virtio_device *vdev, u32 nvqs,
> +				 struct virtqueue *vqs[],
> +				 vq_callback_t *callbacks[],
> +				 const char * const names[],
> +				 const bool *ctx, struct irq_affinity *desc,
> +				 u32 sizes[])
> +{
> +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> +				      desc, sizes);
> +}


Do we need to convert all the open coded direct call to find_vqs() other 
than net?

Thanks


> +
>   /**
>    * virtio_reset_vq - reset a queue individually
>    * @vq: the virtqueue

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 21/26] virtio: add helper virtio_find_vqs_ctx_size()
@ 2022-03-09  9:04     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:04 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Introduce helper virtio_find_vqs_ctx_size() to call find_vqs and specify
> the maximum size of each vq ring.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   include/linux/virtio_config.h | 12 ++++++++++++
>   1 file changed, 12 insertions(+)
>
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 5157524d8036..921d8610db0c 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -233,6 +233,18 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>   				      desc, NULL);
>   }
>   
> +static inline
> +int virtio_find_vqs_ctx_size(struct virtio_device *vdev, u32 nvqs,
> +				 struct virtqueue *vqs[],
> +				 vq_callback_t *callbacks[],
> +				 const char * const names[],
> +				 const bool *ctx, struct irq_affinity *desc,
> +				 u32 sizes[])
> +{
> +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> +				      desc, sizes);
> +}


Do we need to convert all the open coded direct call to find_vqs() other 
than net?

Thanks


> +
>   /**
>    * virtio_reset_vq - reset a queue individually
>    * @vq: the virtqueue


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 23/26] virtio_net: split free_unused_bufs()
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-09  9:06     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:06 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> This patch separates two functions for freeing sq buf and rq buf from
> free_unused_bufs().
>
> When supporting the enable/disable tx/rq queue in the future, it is
> necessary to support separate recovery of a sq buf or a rq buf.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>


Acked-by: Jason Wang <jasowang@redhat.com>


> ---
>   drivers/net/virtio_net.c | 53 +++++++++++++++++++++++-----------------
>   1 file changed, 31 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 59b1ea82f5f0..409a8e180918 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -2804,36 +2804,45 @@ static void free_receive_page_frags(struct virtnet_info *vi)
>   			put_page(vi->rq[i].alloc_frag.page);
>   }
>   
> -static void free_unused_bufs(struct virtnet_info *vi)
> +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> +					struct send_queue *sq)
>   {
>   	void *buf;
> -	int i;
>   
> -	for (i = 0; i < vi->max_queue_pairs; i++) {
> -		struct virtqueue *vq = vi->sq[i].vq;
> -		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
> -			if (!is_xdp_frame(buf))
> -				dev_kfree_skb(buf);
> -			else
> -				xdp_return_frame(ptr_to_xdp(buf));
> -		}
> +	while ((buf = virtqueue_detach_unused_buf(sq->vq)) != NULL) {
> +		if (!is_xdp_frame(buf))
> +			dev_kfree_skb(buf);
> +		else
> +			xdp_return_frame(ptr_to_xdp(buf));
>   	}
> +}
>   
> -	for (i = 0; i < vi->max_queue_pairs; i++) {
> -		struct virtqueue *vq = vi->rq[i].vq;
> -
> -		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
> -			if (vi->mergeable_rx_bufs) {
> -				put_page(virt_to_head_page(buf));
> -			} else if (vi->big_packets) {
> -				give_pages(&vi->rq[i], buf);
> -			} else {
> -				put_page(virt_to_head_page(buf));
> -			}
> -		}
> +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> +					struct receive_queue *rq)
> +{
> +	void *buf;
> +
> +	while ((buf = virtqueue_detach_unused_buf(rq->vq)) != NULL) {
> +		if (vi->mergeable_rx_bufs)
> +			put_page(virt_to_head_page(buf));
> +		else if (vi->big_packets)
> +			give_pages(rq, buf);
> +		else
> +			put_page(virt_to_head_page(buf));
>   	}
>   }
>   
> +static void free_unused_bufs(struct virtnet_info *vi)
> +{
> +	int i;
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++)
> +		virtnet_sq_free_unused_bufs(vi, vi->sq + i);
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++)
> +		virtnet_rq_free_unused_bufs(vi, vi->rq + i);
> +}
> +
>   static void virtnet_del_vqs(struct virtnet_info *vi)
>   {
>   	struct virtio_device *vdev = vi->vdev;


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 23/26] virtio_net: split free_unused_bufs()
@ 2022-03-09  9:06     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:06 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> This patch separates two functions for freeing sq buf and rq buf from
> free_unused_bufs().
>
> When supporting the enable/disable tx/rq queue in the future, it is
> necessary to support separate recovery of a sq buf or a rq buf.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>


Acked-by: Jason Wang <jasowang@redhat.com>


> ---
>   drivers/net/virtio_net.c | 53 +++++++++++++++++++++++-----------------
>   1 file changed, 31 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 59b1ea82f5f0..409a8e180918 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -2804,36 +2804,45 @@ static void free_receive_page_frags(struct virtnet_info *vi)
>   			put_page(vi->rq[i].alloc_frag.page);
>   }
>   
> -static void free_unused_bufs(struct virtnet_info *vi)
> +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> +					struct send_queue *sq)
>   {
>   	void *buf;
> -	int i;
>   
> -	for (i = 0; i < vi->max_queue_pairs; i++) {
> -		struct virtqueue *vq = vi->sq[i].vq;
> -		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
> -			if (!is_xdp_frame(buf))
> -				dev_kfree_skb(buf);
> -			else
> -				xdp_return_frame(ptr_to_xdp(buf));
> -		}
> +	while ((buf = virtqueue_detach_unused_buf(sq->vq)) != NULL) {
> +		if (!is_xdp_frame(buf))
> +			dev_kfree_skb(buf);
> +		else
> +			xdp_return_frame(ptr_to_xdp(buf));
>   	}
> +}
>   
> -	for (i = 0; i < vi->max_queue_pairs; i++) {
> -		struct virtqueue *vq = vi->rq[i].vq;
> -
> -		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
> -			if (vi->mergeable_rx_bufs) {
> -				put_page(virt_to_head_page(buf));
> -			} else if (vi->big_packets) {
> -				give_pages(&vi->rq[i], buf);
> -			} else {
> -				put_page(virt_to_head_page(buf));
> -			}
> -		}
> +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> +					struct receive_queue *rq)
> +{
> +	void *buf;
> +
> +	while ((buf = virtqueue_detach_unused_buf(rq->vq)) != NULL) {
> +		if (vi->mergeable_rx_bufs)
> +			put_page(virt_to_head_page(buf));
> +		else if (vi->big_packets)
> +			give_pages(rq, buf);
> +		else
> +			put_page(virt_to_head_page(buf));
>   	}
>   }
>   
> +static void free_unused_bufs(struct virtnet_info *vi)
> +{
> +	int i;
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++)
> +		virtnet_sq_free_unused_bufs(vi, vi->sq + i);
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++)
> +		virtnet_rq_free_unused_bufs(vi, vi->rq + i);
> +}
> +
>   static void virtnet_del_vqs(struct virtnet_info *vi)
>   {
>   	struct virtio_device *vdev = vi->vdev;

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 23/26] virtio_net: split free_unused_bufs()
@ 2022-03-09  9:06     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:06 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> This patch separates two functions for freeing sq buf and rq buf from
> free_unused_bufs().
>
> When supporting the enable/disable tx/rq queue in the future, it is
> necessary to support separate recovery of a sq buf or a rq buf.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>


Acked-by: Jason Wang <jasowang@redhat.com>


> ---
>   drivers/net/virtio_net.c | 53 +++++++++++++++++++++++-----------------
>   1 file changed, 31 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 59b1ea82f5f0..409a8e180918 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -2804,36 +2804,45 @@ static void free_receive_page_frags(struct virtnet_info *vi)
>   			put_page(vi->rq[i].alloc_frag.page);
>   }
>   
> -static void free_unused_bufs(struct virtnet_info *vi)
> +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> +					struct send_queue *sq)
>   {
>   	void *buf;
> -	int i;
>   
> -	for (i = 0; i < vi->max_queue_pairs; i++) {
> -		struct virtqueue *vq = vi->sq[i].vq;
> -		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
> -			if (!is_xdp_frame(buf))
> -				dev_kfree_skb(buf);
> -			else
> -				xdp_return_frame(ptr_to_xdp(buf));
> -		}
> +	while ((buf = virtqueue_detach_unused_buf(sq->vq)) != NULL) {
> +		if (!is_xdp_frame(buf))
> +			dev_kfree_skb(buf);
> +		else
> +			xdp_return_frame(ptr_to_xdp(buf));
>   	}
> +}
>   
> -	for (i = 0; i < vi->max_queue_pairs; i++) {
> -		struct virtqueue *vq = vi->rq[i].vq;
> -
> -		while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
> -			if (vi->mergeable_rx_bufs) {
> -				put_page(virt_to_head_page(buf));
> -			} else if (vi->big_packets) {
> -				give_pages(&vi->rq[i], buf);
> -			} else {
> -				put_page(virt_to_head_page(buf));
> -			}
> -		}
> +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> +					struct receive_queue *rq)
> +{
> +	void *buf;
> +
> +	while ((buf = virtqueue_detach_unused_buf(rq->vq)) != NULL) {
> +		if (vi->mergeable_rx_bufs)
> +			put_page(virt_to_head_page(buf));
> +		else if (vi->big_packets)
> +			give_pages(rq, buf);
> +		else
> +			put_page(virt_to_head_page(buf));
>   	}
>   }
>   
> +static void free_unused_bufs(struct virtnet_info *vi)
> +{
> +	int i;
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++)
> +		virtnet_sq_free_unused_bufs(vi, vi->sq + i);
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++)
> +		virtnet_rq_free_unused_bufs(vi, vi->rq + i);
> +}
> +
>   static void virtnet_del_vqs(struct virtnet_info *vi)
>   {
>   	struct virtio_device *vdev = vi->vdev;


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 24/26] virtio_net: support rx/tx queue reset
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-09  9:14     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:14 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> This patch implements the reset function of the rx, tx queues.
>
> Based on this function, it is possible to modify the ring num of the
> queue. And quickly recycle the buffer in the queue.
>
> In the process of the queue disable, in theory, as long as virtio
> supports queue reset, there will be no exceptions.
>
> However, in the process of the queue enable, there may be exceptions due to
> memory allocation.  In this case, vq is not available, but we still have
> to execute napi_enable(). Because napi_disable is similar to a lock,
> napi_enable must be called after calling napi_disable.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
>   1 file changed, 107 insertions(+)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 409a8e180918..ffff323dcef0 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -251,6 +251,11 @@ struct padded_vnet_hdr {
>   	char padding[4];
>   };
>   
> +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> +					struct send_queue *sq);
> +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> +					struct receive_queue *rq);
> +
>   static bool is_xdp_frame(void *ptr)
>   {
>   	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
> @@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
>   {
>   	napi_enable(napi);
>   
> +	if (vq->reset)
> +		return;
> +


Let's WARN_ONCE() here?


>   	/* If all buffers were filled by other side before we napi_enabled, we
>   	 * won't get another interrupt, so process any outstanding packets now.
>   	 * Call local_bh_enable after to trigger softIRQ processing.
> @@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
>   		struct receive_queue *rq = &vi->rq[i];
>   
>   		napi_disable(&rq->napi);
> +		if (rq->vq->reset) {
> +			virtnet_napi_enable(rq->vq, &rq->napi);
> +			continue;
> +		}


This seems racy and it's a hint that we need sync with the refill work 
during reset like what we did in virtnet_close():

         /* Make sure refill_work doesn't re-enable napi! */
         cancel_delayed_work_sync(&vi->refill);


>   		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
>   		virtnet_napi_enable(rq->vq, &rq->napi);
>   
> @@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
>   	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
>   		return;
>   
> +	if (sq->vq->reset)
> +		return;


It looks to me we'd better either WARN or just remove this. Since it 
looks like a workaround for the un-synchronized NAPI somehow.


> +
>   	if (__netif_tx_trylock(txq)) {
>   		do {
>   			virtqueue_disable_cb(sq->vq);
> @@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
>   	return NETDEV_TX_OK;
>   }
>   
> +static int virtnet_rx_vq_reset(struct virtnet_info *vi,
> +			       struct receive_queue *rq, u32 ring_num)


It's better to rename this as virtnet_rx_resize().


> +{
> +	int err;
> +
> +	/* stop napi */
> +	napi_disable(&rq->napi);
> +


Here, as discussed above, we need synchronize with the refill work.


> +	/* reset the queue */
> +	err = virtio_reset_vq(rq->vq);
> +	if (err)
> +		goto err;


Btw, most comment of this function seems useless since code already 
explain themselves.


> +
> +	/* free bufs */
> +	virtnet_rq_free_unused_bufs(vi, rq);
> +
> +	/* reset vring. */
> +	err = virtqueue_reset_vring(rq->vq, ring_num);
> +	if (err)
> +		goto err;
> +
> +	/* enable reset queue */
> +	err = virtio_enable_resetq(rq->vq);
> +	if (err)
> +		goto err;
> +
> +	/* fill recv */
> +	if (!try_fill_recv(vi, rq, GFP_KERNEL))
> +		schedule_delayed_work(&vi->refill, 0);
> +
> +	/* enable napi */
> +	virtnet_napi_enable(rq->vq, &rq->napi);
> +	return 0;
> +
> +err:
> +	netdev_err(vi->dev,
> +		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
> +		   rq - vi->rq, err);
> +	virtnet_napi_enable(rq->vq, &rq->napi);
> +	return err;
> +}
> +
> +static int virtnet_tx_vq_reset(struct virtnet_info *vi,
> +			       struct send_queue *sq, u32 ring_num)
> +{


It looks to me it's better to rename this as "virtnet_rx_resize()"


> +	struct netdev_queue *txq;
> +	int err, qindex;
> +
> +	qindex = sq - vi->sq;
> +
> +	txq = netdev_get_tx_queue(vi->dev, qindex);
> +	__netif_tx_lock_bh(txq);
> +
> +	/* stop tx queue and napi */
> +	netif_stop_subqueue(vi->dev, qindex);
> +	virtnet_napi_tx_disable(&sq->napi);


There's no need to hold tx lock for napi disable.

Thanks


> +
> +	__netif_tx_unlock_bh(txq);
> +
> +	/* reset the queue */
> +	err = virtio_reset_vq(sq->vq);
> +	if (err) {
> +		netif_start_subqueue(vi->dev, qindex);
> +		goto err;
> +	}
> +
> +	/* free bufs */
> +	virtnet_sq_free_unused_bufs(vi, sq);
> +
> +	/* reset vring. */
> +	err = virtqueue_reset_vring(sq->vq, ring_num);
> +	if (err)
> +		goto err;
> +
> +	/* enable reset queue */
> +	err = virtio_enable_resetq(sq->vq);
> +	if (err)
> +		goto err;
> +
> +	/* start tx queue and napi */
> +	netif_start_subqueue(vi->dev, qindex);
> +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> +	return 0;
> +
> +err:
> +	netdev_err(vi->dev,
> +		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
> +		   sq - vi->sq, err);
> +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> +	return err;
> +}
> +
>   /*
>    * Send command via the control virtqueue and check status.  Commands
>    * supported by the hypervisor, as indicated by feature bits, should


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 24/26] virtio_net: support rx/tx queue reset
@ 2022-03-09  9:14     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:14 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> This patch implements the reset function of the rx, tx queues.
>
> Based on this function, it is possible to modify the ring num of the
> queue. And quickly recycle the buffer in the queue.
>
> In the process of the queue disable, in theory, as long as virtio
> supports queue reset, there will be no exceptions.
>
> However, in the process of the queue enable, there may be exceptions due to
> memory allocation.  In this case, vq is not available, but we still have
> to execute napi_enable(). Because napi_disable is similar to a lock,
> napi_enable must be called after calling napi_disable.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
>   1 file changed, 107 insertions(+)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 409a8e180918..ffff323dcef0 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -251,6 +251,11 @@ struct padded_vnet_hdr {
>   	char padding[4];
>   };
>   
> +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> +					struct send_queue *sq);
> +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> +					struct receive_queue *rq);
> +
>   static bool is_xdp_frame(void *ptr)
>   {
>   	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
> @@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
>   {
>   	napi_enable(napi);
>   
> +	if (vq->reset)
> +		return;
> +


Let's WARN_ONCE() here?


>   	/* If all buffers were filled by other side before we napi_enabled, we
>   	 * won't get another interrupt, so process any outstanding packets now.
>   	 * Call local_bh_enable after to trigger softIRQ processing.
> @@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
>   		struct receive_queue *rq = &vi->rq[i];
>   
>   		napi_disable(&rq->napi);
> +		if (rq->vq->reset) {
> +			virtnet_napi_enable(rq->vq, &rq->napi);
> +			continue;
> +		}


This seems racy and it's a hint that we need sync with the refill work 
during reset like what we did in virtnet_close():

         /* Make sure refill_work doesn't re-enable napi! */
         cancel_delayed_work_sync(&vi->refill);


>   		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
>   		virtnet_napi_enable(rq->vq, &rq->napi);
>   
> @@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
>   	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
>   		return;
>   
> +	if (sq->vq->reset)
> +		return;


It looks to me we'd better either WARN or just remove this. Since it 
looks like a workaround for the un-synchronized NAPI somehow.


> +
>   	if (__netif_tx_trylock(txq)) {
>   		do {
>   			virtqueue_disable_cb(sq->vq);
> @@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
>   	return NETDEV_TX_OK;
>   }
>   
> +static int virtnet_rx_vq_reset(struct virtnet_info *vi,
> +			       struct receive_queue *rq, u32 ring_num)


It's better to rename this as virtnet_rx_resize().


> +{
> +	int err;
> +
> +	/* stop napi */
> +	napi_disable(&rq->napi);
> +


Here, as discussed above, we need synchronize with the refill work.


> +	/* reset the queue */
> +	err = virtio_reset_vq(rq->vq);
> +	if (err)
> +		goto err;


Btw, most comment of this function seems useless since code already 
explain themselves.


> +
> +	/* free bufs */
> +	virtnet_rq_free_unused_bufs(vi, rq);
> +
> +	/* reset vring. */
> +	err = virtqueue_reset_vring(rq->vq, ring_num);
> +	if (err)
> +		goto err;
> +
> +	/* enable reset queue */
> +	err = virtio_enable_resetq(rq->vq);
> +	if (err)
> +		goto err;
> +
> +	/* fill recv */
> +	if (!try_fill_recv(vi, rq, GFP_KERNEL))
> +		schedule_delayed_work(&vi->refill, 0);
> +
> +	/* enable napi */
> +	virtnet_napi_enable(rq->vq, &rq->napi);
> +	return 0;
> +
> +err:
> +	netdev_err(vi->dev,
> +		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
> +		   rq - vi->rq, err);
> +	virtnet_napi_enable(rq->vq, &rq->napi);
> +	return err;
> +}
> +
> +static int virtnet_tx_vq_reset(struct virtnet_info *vi,
> +			       struct send_queue *sq, u32 ring_num)
> +{


It looks to me it's better to rename this as "virtnet_rx_resize()"


> +	struct netdev_queue *txq;
> +	int err, qindex;
> +
> +	qindex = sq - vi->sq;
> +
> +	txq = netdev_get_tx_queue(vi->dev, qindex);
> +	__netif_tx_lock_bh(txq);
> +
> +	/* stop tx queue and napi */
> +	netif_stop_subqueue(vi->dev, qindex);
> +	virtnet_napi_tx_disable(&sq->napi);


There's no need to hold tx lock for napi disable.

Thanks


> +
> +	__netif_tx_unlock_bh(txq);
> +
> +	/* reset the queue */
> +	err = virtio_reset_vq(sq->vq);
> +	if (err) {
> +		netif_start_subqueue(vi->dev, qindex);
> +		goto err;
> +	}
> +
> +	/* free bufs */
> +	virtnet_sq_free_unused_bufs(vi, sq);
> +
> +	/* reset vring. */
> +	err = virtqueue_reset_vring(sq->vq, ring_num);
> +	if (err)
> +		goto err;
> +
> +	/* enable reset queue */
> +	err = virtio_enable_resetq(sq->vq);
> +	if (err)
> +		goto err;
> +
> +	/* start tx queue and napi */
> +	netif_start_subqueue(vi->dev, qindex);
> +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> +	return 0;
> +
> +err:
> +	netdev_err(vi->dev,
> +		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
> +		   sq - vi->sq, err);
> +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> +	return err;
> +}
> +
>   /*
>    * Send command via the control virtqueue and check status.  Commands
>    * supported by the hypervisor, as indicated by feature bits, should

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 24/26] virtio_net: support rx/tx queue reset
@ 2022-03-09  9:14     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:14 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> This patch implements the reset function of the rx, tx queues.
>
> Based on this function, it is possible to modify the ring num of the
> queue. And quickly recycle the buffer in the queue.
>
> In the process of the queue disable, in theory, as long as virtio
> supports queue reset, there will be no exceptions.
>
> However, in the process of the queue enable, there may be exceptions due to
> memory allocation.  In this case, vq is not available, but we still have
> to execute napi_enable(). Because napi_disable is similar to a lock,
> napi_enable must be called after calling napi_disable.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
>   1 file changed, 107 insertions(+)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index 409a8e180918..ffff323dcef0 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -251,6 +251,11 @@ struct padded_vnet_hdr {
>   	char padding[4];
>   };
>   
> +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> +					struct send_queue *sq);
> +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> +					struct receive_queue *rq);
> +
>   static bool is_xdp_frame(void *ptr)
>   {
>   	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
> @@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
>   {
>   	napi_enable(napi);
>   
> +	if (vq->reset)
> +		return;
> +


Let's WARN_ONCE() here?


>   	/* If all buffers were filled by other side before we napi_enabled, we
>   	 * won't get another interrupt, so process any outstanding packets now.
>   	 * Call local_bh_enable after to trigger softIRQ processing.
> @@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
>   		struct receive_queue *rq = &vi->rq[i];
>   
>   		napi_disable(&rq->napi);
> +		if (rq->vq->reset) {
> +			virtnet_napi_enable(rq->vq, &rq->napi);
> +			continue;
> +		}


This seems racy and it's a hint that we need sync with the refill work 
during reset like what we did in virtnet_close():

         /* Make sure refill_work doesn't re-enable napi! */
         cancel_delayed_work_sync(&vi->refill);


>   		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
>   		virtnet_napi_enable(rq->vq, &rq->napi);
>   
> @@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
>   	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
>   		return;
>   
> +	if (sq->vq->reset)
> +		return;


It looks to me we'd better either WARN or just remove this. Since it 
looks like a workaround for the un-synchronized NAPI somehow.


> +
>   	if (__netif_tx_trylock(txq)) {
>   		do {
>   			virtqueue_disable_cb(sq->vq);
> @@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
>   	return NETDEV_TX_OK;
>   }
>   
> +static int virtnet_rx_vq_reset(struct virtnet_info *vi,
> +			       struct receive_queue *rq, u32 ring_num)


It's better to rename this as virtnet_rx_resize().


> +{
> +	int err;
> +
> +	/* stop napi */
> +	napi_disable(&rq->napi);
> +


Here, as discussed above, we need synchronize with the refill work.


> +	/* reset the queue */
> +	err = virtio_reset_vq(rq->vq);
> +	if (err)
> +		goto err;


Btw, most comment of this function seems useless since code already 
explain themselves.


> +
> +	/* free bufs */
> +	virtnet_rq_free_unused_bufs(vi, rq);
> +
> +	/* reset vring. */
> +	err = virtqueue_reset_vring(rq->vq, ring_num);
> +	if (err)
> +		goto err;
> +
> +	/* enable reset queue */
> +	err = virtio_enable_resetq(rq->vq);
> +	if (err)
> +		goto err;
> +
> +	/* fill recv */
> +	if (!try_fill_recv(vi, rq, GFP_KERNEL))
> +		schedule_delayed_work(&vi->refill, 0);
> +
> +	/* enable napi */
> +	virtnet_napi_enable(rq->vq, &rq->napi);
> +	return 0;
> +
> +err:
> +	netdev_err(vi->dev,
> +		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
> +		   rq - vi->rq, err);
> +	virtnet_napi_enable(rq->vq, &rq->napi);
> +	return err;
> +}
> +
> +static int virtnet_tx_vq_reset(struct virtnet_info *vi,
> +			       struct send_queue *sq, u32 ring_num)
> +{


It looks to me it's better to rename this as "virtnet_rx_resize()"


> +	struct netdev_queue *txq;
> +	int err, qindex;
> +
> +	qindex = sq - vi->sq;
> +
> +	txq = netdev_get_tx_queue(vi->dev, qindex);
> +	__netif_tx_lock_bh(txq);
> +
> +	/* stop tx queue and napi */
> +	netif_stop_subqueue(vi->dev, qindex);
> +	virtnet_napi_tx_disable(&sq->napi);


There's no need to hold tx lock for napi disable.

Thanks


> +
> +	__netif_tx_unlock_bh(txq);
> +
> +	/* reset the queue */
> +	err = virtio_reset_vq(sq->vq);
> +	if (err) {
> +		netif_start_subqueue(vi->dev, qindex);
> +		goto err;
> +	}
> +
> +	/* free bufs */
> +	virtnet_sq_free_unused_bufs(vi, sq);
> +
> +	/* reset vring. */
> +	err = virtqueue_reset_vring(sq->vq, ring_num);
> +	if (err)
> +		goto err;
> +
> +	/* enable reset queue */
> +	err = virtio_enable_resetq(sq->vq);
> +	if (err)
> +		goto err;
> +
> +	/* start tx queue and napi */
> +	netif_start_subqueue(vi->dev, qindex);
> +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> +	return 0;
> +
> +err:
> +	netdev_err(vi->dev,
> +		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
> +		   sq - vi->sq, err);
> +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> +	return err;
> +}
> +
>   /*
>    * Send command via the control virtqueue and check status.  Commands
>    * supported by the hypervisor, as indicated by feature bits, should


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 04/26] virtio_ring: split: extract the logic of creating vring
  2022-03-09  6:46     ` Jason Wang
  (?)
@ 2022-03-09  9:20       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:20 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

Agree for all.

Thanks.

On Wed, 9 Mar 2022 14:46:01 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> > Separate the logic of split to create vring queue.
> >
> > For the convenience of passing parameters, add a structure
> > vring_split.
> >
> > This feature is required for subsequent virtuqueue reset vring.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 74 +++++++++++++++++++++++++-----------
> >   1 file changed, 51 insertions(+), 23 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index b87130c8f312..d32793615451 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -85,6 +85,13 @@ struct vring_desc_extra {
> >   	u16 next;			/* The next desc state in a list. */
> >   };
> >
> > +struct vring_split {
> > +	void *queue;
> > +	dma_addr_t dma_addr;
> > +	size_t queue_size_in_bytes;
> > +	struct vring vring;
> > +};
>
>
> So this structure will be only used in vring_create_vring_split() which
> seems not that useful.
>
> More see below.
>
>
> > +
> >   struct vring_virtqueue {
> >   	struct virtqueue vq;
> >
> > @@ -915,28 +922,21 @@ static void *virtqueue_detach_unused_buf_split(struct virtqueue *_vq)
> >   	return NULL;
> >   }
> >
> > -static struct virtqueue *vring_create_virtqueue_split(
> > -	unsigned int index,
> > -	unsigned int num,
> > -	unsigned int vring_align,
> > -	struct virtio_device *vdev,
> > -	bool weak_barriers,
> > -	bool may_reduce_num,
> > -	bool context,
> > -	bool (*notify)(struct virtqueue *),
> > -	void (*callback)(struct virtqueue *),
> > -	const char *name)
> > +static int vring_create_vring_split(struct vring_split *vring,
> > +				    struct virtio_device *vdev,
> > +				    unsigned int vring_align,
> > +				    bool weak_barriers,
> > +				    bool may_reduce_num,
> > +				    u32 num)
>
>
> I'd rename this as vring_alloc_queue_split() and let it simply return
> the address of queue like vring_alloc_queue().
>
> And let it simple accept dma_addr_t *dma_adder instead of vring_split.
>
>
> >   {
> > -	struct virtqueue *vq;
> >   	void *queue = NULL;
> >   	dma_addr_t dma_addr;
> >   	size_t queue_size_in_bytes;
> > -	struct vring vring;
> >
> >   	/* We assume num is a power of 2. */
> >   	if (num & (num - 1)) {
> >   		dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
> > -		return NULL;
> > +		return -EINVAL;
> >   	}
> >
> >   	/* TODO: allocate each queue chunk individually */
> > @@ -947,11 +947,11 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   		if (queue)
> >   			break;
> >   		if (!may_reduce_num)
> > -			return NULL;
> > +			return -ENOMEM;
> >   	}
> >
> >   	if (!num)
> > -		return NULL;
> > +		return -ENOMEM;
> >
> >   	if (!queue) {
> >   		/* Try to get a single page. You are my only hope! */
> > @@ -959,21 +959,49 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   					  &dma_addr, GFP_KERNEL|__GFP_ZERO);
> >   	}
> >   	if (!queue)
> > -		return NULL;
> > +		return -ENOMEM;
> >
> >   	queue_size_in_bytes = vring_size(num, vring_align);
> > -	vring_init(&vring, num, queue, vring_align);
> > +	vring_init(&vring->vring, num, queue, vring_align);
>
>
> It's better to move this to its caller (vring_create_virtqueue_split),
> so we have rather simple logic below:
>
>
>
> > +
> > +	vring->dma_addr = dma_addr;
> > +	vring->queue = queue;
> > +	vring->queue_size_in_bytes = queue_size_in_bytes;
> > +
> > +	return 0;
> > +}
> > +
> > +static struct virtqueue *vring_create_virtqueue_split(
> > +	unsigned int index,
> > +	unsigned int num,
> > +	unsigned int vring_align,
> > +	struct virtio_device *vdev,
> > +	bool weak_barriers,
> > +	bool may_reduce_num,
> > +	bool context,
> > +	bool (*notify)(struct virtqueue *),
> > +	void (*callback)(struct virtqueue *),
> > +	const char *name)
> > +{
> > +	struct vring_split vring;
> > +	struct virtqueue *vq;
> > +	int err;
> > +
> > +	err = vring_create_vring_split(&vring, vdev, vring_align, weak_barriers,
> > +				       may_reduce_num, num);
> > +	if (err)
> > +		return NULL;
>
>
> queue = vring_alloc_queue_split(vdev, &dma_addr, ...);
>
> if (!queue)
>
>      return -ENOMEM;
>
> vring_init();
>
> ...
>
> Thanks
>
>
> >
> > -	vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
> > +	vq = __vring_new_virtqueue(index, vring.vring, vdev, weak_barriers, context,
> >   				   notify, callback, name);
> >   	if (!vq) {
> > -		vring_free_queue(vdev, queue_size_in_bytes, queue,
> > -				 dma_addr);
> > +		vring_free_queue(vdev, vring.queue_size_in_bytes, vring.queue,
> > +				 vring.dma_addr);
> >   		return NULL;
> >   	}
> >
> > -	to_vvq(vq)->split.queue_dma_addr = dma_addr;
> > -	to_vvq(vq)->split.queue_size_in_bytes = queue_size_in_bytes;
> > +	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > +	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >   	to_vvq(vq)->we_own_ring = true;
> >
> >   	return vq;
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 04/26] virtio_ring: split: extract the logic of creating vring
@ 2022-03-09  9:20       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:20 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

Agree for all.

Thanks.

On Wed, 9 Mar 2022 14:46:01 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> > Separate the logic of split to create vring queue.
> >
> > For the convenience of passing parameters, add a structure
> > vring_split.
> >
> > This feature is required for subsequent virtuqueue reset vring.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 74 +++++++++++++++++++++++++-----------
> >   1 file changed, 51 insertions(+), 23 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index b87130c8f312..d32793615451 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -85,6 +85,13 @@ struct vring_desc_extra {
> >   	u16 next;			/* The next desc state in a list. */
> >   };
> >
> > +struct vring_split {
> > +	void *queue;
> > +	dma_addr_t dma_addr;
> > +	size_t queue_size_in_bytes;
> > +	struct vring vring;
> > +};
>
>
> So this structure will be only used in vring_create_vring_split() which
> seems not that useful.
>
> More see below.
>
>
> > +
> >   struct vring_virtqueue {
> >   	struct virtqueue vq;
> >
> > @@ -915,28 +922,21 @@ static void *virtqueue_detach_unused_buf_split(struct virtqueue *_vq)
> >   	return NULL;
> >   }
> >
> > -static struct virtqueue *vring_create_virtqueue_split(
> > -	unsigned int index,
> > -	unsigned int num,
> > -	unsigned int vring_align,
> > -	struct virtio_device *vdev,
> > -	bool weak_barriers,
> > -	bool may_reduce_num,
> > -	bool context,
> > -	bool (*notify)(struct virtqueue *),
> > -	void (*callback)(struct virtqueue *),
> > -	const char *name)
> > +static int vring_create_vring_split(struct vring_split *vring,
> > +				    struct virtio_device *vdev,
> > +				    unsigned int vring_align,
> > +				    bool weak_barriers,
> > +				    bool may_reduce_num,
> > +				    u32 num)
>
>
> I'd rename this as vring_alloc_queue_split() and let it simply return
> the address of queue like vring_alloc_queue().
>
> And let it simple accept dma_addr_t *dma_adder instead of vring_split.
>
>
> >   {
> > -	struct virtqueue *vq;
> >   	void *queue = NULL;
> >   	dma_addr_t dma_addr;
> >   	size_t queue_size_in_bytes;
> > -	struct vring vring;
> >
> >   	/* We assume num is a power of 2. */
> >   	if (num & (num - 1)) {
> >   		dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
> > -		return NULL;
> > +		return -EINVAL;
> >   	}
> >
> >   	/* TODO: allocate each queue chunk individually */
> > @@ -947,11 +947,11 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   		if (queue)
> >   			break;
> >   		if (!may_reduce_num)
> > -			return NULL;
> > +			return -ENOMEM;
> >   	}
> >
> >   	if (!num)
> > -		return NULL;
> > +		return -ENOMEM;
> >
> >   	if (!queue) {
> >   		/* Try to get a single page. You are my only hope! */
> > @@ -959,21 +959,49 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   					  &dma_addr, GFP_KERNEL|__GFP_ZERO);
> >   	}
> >   	if (!queue)
> > -		return NULL;
> > +		return -ENOMEM;
> >
> >   	queue_size_in_bytes = vring_size(num, vring_align);
> > -	vring_init(&vring, num, queue, vring_align);
> > +	vring_init(&vring->vring, num, queue, vring_align);
>
>
> It's better to move this to its caller (vring_create_virtqueue_split),
> so we have rather simple logic below:
>
>
>
> > +
> > +	vring->dma_addr = dma_addr;
> > +	vring->queue = queue;
> > +	vring->queue_size_in_bytes = queue_size_in_bytes;
> > +
> > +	return 0;
> > +}
> > +
> > +static struct virtqueue *vring_create_virtqueue_split(
> > +	unsigned int index,
> > +	unsigned int num,
> > +	unsigned int vring_align,
> > +	struct virtio_device *vdev,
> > +	bool weak_barriers,
> > +	bool may_reduce_num,
> > +	bool context,
> > +	bool (*notify)(struct virtqueue *),
> > +	void (*callback)(struct virtqueue *),
> > +	const char *name)
> > +{
> > +	struct vring_split vring;
> > +	struct virtqueue *vq;
> > +	int err;
> > +
> > +	err = vring_create_vring_split(&vring, vdev, vring_align, weak_barriers,
> > +				       may_reduce_num, num);
> > +	if (err)
> > +		return NULL;
>
>
> queue = vring_alloc_queue_split(vdev, &dma_addr, ...);
>
> if (!queue)
>
>      return -ENOMEM;
>
> vring_init();
>
> ...
>
> Thanks
>
>
> >
> > -	vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
> > +	vq = __vring_new_virtqueue(index, vring.vring, vdev, weak_barriers, context,
> >   				   notify, callback, name);
> >   	if (!vq) {
> > -		vring_free_queue(vdev, queue_size_in_bytes, queue,
> > -				 dma_addr);
> > +		vring_free_queue(vdev, vring.queue_size_in_bytes, vring.queue,
> > +				 vring.dma_addr);
> >   		return NULL;
> >   	}
> >
> > -	to_vvq(vq)->split.queue_dma_addr = dma_addr;
> > -	to_vvq(vq)->split.queue_size_in_bytes = queue_size_in_bytes;
> > +	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > +	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >   	to_vvq(vq)->we_own_ring = true;
> >
> >   	return vq;
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 04/26] virtio_ring: split: extract the logic of creating vring
@ 2022-03-09  9:20       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:20 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

Agree for all.

Thanks.

On Wed, 9 Mar 2022 14:46:01 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> > Separate the logic of split to create vring queue.
> >
> > For the convenience of passing parameters, add a structure
> > vring_split.
> >
> > This feature is required for subsequent virtuqueue reset vring.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 74 +++++++++++++++++++++++++-----------
> >   1 file changed, 51 insertions(+), 23 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index b87130c8f312..d32793615451 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -85,6 +85,13 @@ struct vring_desc_extra {
> >   	u16 next;			/* The next desc state in a list. */
> >   };
> >
> > +struct vring_split {
> > +	void *queue;
> > +	dma_addr_t dma_addr;
> > +	size_t queue_size_in_bytes;
> > +	struct vring vring;
> > +};
>
>
> So this structure will be only used in vring_create_vring_split() which
> seems not that useful.
>
> More see below.
>
>
> > +
> >   struct vring_virtqueue {
> >   	struct virtqueue vq;
> >
> > @@ -915,28 +922,21 @@ static void *virtqueue_detach_unused_buf_split(struct virtqueue *_vq)
> >   	return NULL;
> >   }
> >
> > -static struct virtqueue *vring_create_virtqueue_split(
> > -	unsigned int index,
> > -	unsigned int num,
> > -	unsigned int vring_align,
> > -	struct virtio_device *vdev,
> > -	bool weak_barriers,
> > -	bool may_reduce_num,
> > -	bool context,
> > -	bool (*notify)(struct virtqueue *),
> > -	void (*callback)(struct virtqueue *),
> > -	const char *name)
> > +static int vring_create_vring_split(struct vring_split *vring,
> > +				    struct virtio_device *vdev,
> > +				    unsigned int vring_align,
> > +				    bool weak_barriers,
> > +				    bool may_reduce_num,
> > +				    u32 num)
>
>
> I'd rename this as vring_alloc_queue_split() and let it simply return
> the address of queue like vring_alloc_queue().
>
> And let it simple accept dma_addr_t *dma_adder instead of vring_split.
>
>
> >   {
> > -	struct virtqueue *vq;
> >   	void *queue = NULL;
> >   	dma_addr_t dma_addr;
> >   	size_t queue_size_in_bytes;
> > -	struct vring vring;
> >
> >   	/* We assume num is a power of 2. */
> >   	if (num & (num - 1)) {
> >   		dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num);
> > -		return NULL;
> > +		return -EINVAL;
> >   	}
> >
> >   	/* TODO: allocate each queue chunk individually */
> > @@ -947,11 +947,11 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   		if (queue)
> >   			break;
> >   		if (!may_reduce_num)
> > -			return NULL;
> > +			return -ENOMEM;
> >   	}
> >
> >   	if (!num)
> > -		return NULL;
> > +		return -ENOMEM;
> >
> >   	if (!queue) {
> >   		/* Try to get a single page. You are my only hope! */
> > @@ -959,21 +959,49 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   					  &dma_addr, GFP_KERNEL|__GFP_ZERO);
> >   	}
> >   	if (!queue)
> > -		return NULL;
> > +		return -ENOMEM;
> >
> >   	queue_size_in_bytes = vring_size(num, vring_align);
> > -	vring_init(&vring, num, queue, vring_align);
> > +	vring_init(&vring->vring, num, queue, vring_align);
>
>
> It's better to move this to its caller (vring_create_virtqueue_split),
> so we have rather simple logic below:
>
>
>
> > +
> > +	vring->dma_addr = dma_addr;
> > +	vring->queue = queue;
> > +	vring->queue_size_in_bytes = queue_size_in_bytes;
> > +
> > +	return 0;
> > +}
> > +
> > +static struct virtqueue *vring_create_virtqueue_split(
> > +	unsigned int index,
> > +	unsigned int num,
> > +	unsigned int vring_align,
> > +	struct virtio_device *vdev,
> > +	bool weak_barriers,
> > +	bool may_reduce_num,
> > +	bool context,
> > +	bool (*notify)(struct virtqueue *),
> > +	void (*callback)(struct virtqueue *),
> > +	const char *name)
> > +{
> > +	struct vring_split vring;
> > +	struct virtqueue *vq;
> > +	int err;
> > +
> > +	err = vring_create_vring_split(&vring, vdev, vring_align, weak_barriers,
> > +				       may_reduce_num, num);
> > +	if (err)
> > +		return NULL;
>
>
> queue = vring_alloc_queue_split(vdev, &dma_addr, ...);
>
> if (!queue)
>
>      return -ENOMEM;
>
> vring_init();
>
> ...
>
> Thanks
>
>
> >
> > -	vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
> > +	vq = __vring_new_virtqueue(index, vring.vring, vdev, weak_barriers, context,
> >   				   notify, callback, name);
> >   	if (!vq) {
> > -		vring_free_queue(vdev, queue_size_in_bytes, queue,
> > -				 dma_addr);
> > +		vring_free_queue(vdev, vring.queue_size_in_bytes, vring.queue,
> > +				 vring.dma_addr);
> >   		return NULL;
> >   	}
> >
> > -	to_vvq(vq)->split.queue_dma_addr = dma_addr;
> > -	to_vvq(vq)->split.queue_size_in_bytes = queue_size_in_bytes;
> > +	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > +	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >   	to_vvq(vq)->we_own_ring = true;
> >
> >   	return vq;
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 05/26] virtio_ring: split: extract the logic of init vq and attach vring
  2022-03-09  7:36     ` Jason Wang
  (?)
@ 2022-03-09  9:21       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:21 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 15:36:59 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> > Split the logic of split assignment vq into three parts.
> >
> > 1. The assignment passed from the function parameter
> > 2. The part that attaches vring to vq. -- __vring_virtqueue_attach_split()
> > 3. The part that initializes vq to a fixed value --
> >     __vring_virtqueue_init_split()
> >
> > This feature is required for subsequent virtuqueue reset vring
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 111 +++++++++++++++++++++--------------
> >   1 file changed, 67 insertions(+), 44 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index d32793615451..dc6313b79305 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -2196,34 +2196,40 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
> >   }
> >   EXPORT_SYMBOL_GPL(vring_interrupt);
> >
> > -/* Only available for split ring */
> > -struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > -					struct vring vring,
> > -					struct virtio_device *vdev,
> > -					bool weak_barriers,
> > -					bool context,
> > -					bool (*notify)(struct virtqueue *),
> > -					void (*callback)(struct virtqueue *),
> > -					const char *name)
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring)
> >   {
> > -	struct vring_virtqueue *vq;
> > +	vq->vq.num_free = vring.num;
> >
> > -	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> > -		return NULL;
> > +	vq->split.vring = vring;
> > +	vq->split.queue_dma_addr = 0;
> > +	vq->split.queue_size_in_bytes = 0;
> >
> > -	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> > -	if (!vq)
> > -		return NULL;
> > +	vq->split.desc_state = kmalloc_array(vring.num,
> > +					     sizeof(struct vring_desc_state_split), GFP_KERNEL);
> > +	if (!vq->split.desc_state)
> > +		goto err_state;
> >
> > +	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> > +	if (!vq->split.desc_extra)
> > +		goto err_extra;
>
>
> So this contains stuffs more than just attach. I wonder if it's better
> to split the allocation out to an dedicated helper (we have dedicated
> helper to allocate vring).

I will try in next version.

Thanks.

>
> Thanks
>
>
> > +
> > +	memset(vq->split.desc_state, 0, vring.num *
> > +	       sizeof(struct vring_desc_state_split));
> > +	return 0;
> > +
> > +err_extra:
> > +	kfree(vq->split.desc_state);
> > +err_state:
> > +	return -ENOMEM;
> > +}
> > +
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev)
> > +{
> >   	vq->packed_ring = false;
> > -	vq->vq.callback = callback;
> > -	vq->vq.vdev = vdev;
> > -	vq->vq.name = name;
> > -	vq->vq.num_free = vring.num;
> > -	vq->vq.index = index;
> >   	vq->we_own_ring = false;
> > -	vq->notify = notify;
> > -	vq->weak_barriers = weak_barriers;
> >   	vq->broken = false;
> >   	vq->last_used_idx = 0;
> >   	vq->event_triggered = false;
> > @@ -2234,50 +2240,67 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
> >   	vq->last_add_time_valid = false;
> >   #endif
> >
> > -	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> > -		!context;
> >   	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
> >
> >   	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
> >   		vq->weak_barriers = false;
> >
> > -	vq->split.queue_dma_addr = 0;
> > -	vq->split.queue_size_in_bytes = 0;
> > -
> > -	vq->split.vring = vring;
> >   	vq->split.avail_flags_shadow = 0;
> >   	vq->split.avail_idx_shadow = 0;
> >
> >   	/* No callback?  Tell other side not to bother us. */
> > -	if (!callback) {
> > +	if (!vq->vq.callback) {
> >   		vq->split.avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
> >   		if (!vq->event)
> >   			vq->split.vring.avail->flags = cpu_to_virtio16(vdev,
> >   					vq->split.avail_flags_shadow);
> >   	}
> >
> > -	vq->split.desc_state = kmalloc_array(vring.num,
> > -			sizeof(struct vring_desc_state_split), GFP_KERNEL);
> > -	if (!vq->split.desc_state)
> > -		goto err_state;
> > -
> > -	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> > -	if (!vq->split.desc_extra)
> > -		goto err_extra;
> > -
> >   	/* Put everything in free lists. */
> >   	vq->free_head = 0;
> > -	memset(vq->split.desc_state, 0, vring.num *
> > -			sizeof(struct vring_desc_state_split));
> > +}
> > +
> > +/* Only available for split ring */
> > +struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > +					struct vring vring,
> > +					struct virtio_device *vdev,
> > +					bool weak_barriers,
> > +					bool context,
> > +					bool (*notify)(struct virtqueue *),
> > +					void (*callback)(struct virtqueue *),
> > +					const char *name)
> > +{
> > +	struct vring_virtqueue *vq;
> > +	int err;
> > +
> > +	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> > +		return NULL;
> > +
> > +	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> > +	if (!vq)
> > +		return NULL;
> > +
> > +	vq->vq.callback = callback;
> > +	vq->vq.vdev = vdev;
> > +	vq->vq.name = name;
> > +	vq->vq.index = index;
> > +	vq->notify = notify;
> > +	vq->weak_barriers = weak_barriers;
> > +	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> > +		!context;
> > +
> > +	err = __vring_virtqueue_attach_split(vq, vdev, vring);
> > +	if (err)
> > +		goto err;
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> >
> >   	spin_lock(&vdev->vqs_list_lock);
> >   	list_add_tail(&vq->vq.list, &vdev->vqs);
> >   	spin_unlock(&vdev->vqs_list_lock);
> > -	return &vq->vq;
> >
> > -err_extra:
> > -	kfree(vq->split.desc_state);
> > -err_state:
> > +	return &vq->vq;
> > +err:
> >   	kfree(vq);
> >   	return NULL;
> >   }
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 05/26] virtio_ring: split: extract the logic of init vq and attach vring
@ 2022-03-09  9:21       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:21 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 15:36:59 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> > Split the logic of split assignment vq into three parts.
> >
> > 1. The assignment passed from the function parameter
> > 2. The part that attaches vring to vq. -- __vring_virtqueue_attach_split()
> > 3. The part that initializes vq to a fixed value --
> >     __vring_virtqueue_init_split()
> >
> > This feature is required for subsequent virtuqueue reset vring
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 111 +++++++++++++++++++++--------------
> >   1 file changed, 67 insertions(+), 44 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index d32793615451..dc6313b79305 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -2196,34 +2196,40 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
> >   }
> >   EXPORT_SYMBOL_GPL(vring_interrupt);
> >
> > -/* Only available for split ring */
> > -struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > -					struct vring vring,
> > -					struct virtio_device *vdev,
> > -					bool weak_barriers,
> > -					bool context,
> > -					bool (*notify)(struct virtqueue *),
> > -					void (*callback)(struct virtqueue *),
> > -					const char *name)
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring)
> >   {
> > -	struct vring_virtqueue *vq;
> > +	vq->vq.num_free = vring.num;
> >
> > -	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> > -		return NULL;
> > +	vq->split.vring = vring;
> > +	vq->split.queue_dma_addr = 0;
> > +	vq->split.queue_size_in_bytes = 0;
> >
> > -	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> > -	if (!vq)
> > -		return NULL;
> > +	vq->split.desc_state = kmalloc_array(vring.num,
> > +					     sizeof(struct vring_desc_state_split), GFP_KERNEL);
> > +	if (!vq->split.desc_state)
> > +		goto err_state;
> >
> > +	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> > +	if (!vq->split.desc_extra)
> > +		goto err_extra;
>
>
> So this contains stuffs more than just attach. I wonder if it's better
> to split the allocation out to an dedicated helper (we have dedicated
> helper to allocate vring).

I will try in next version.

Thanks.

>
> Thanks
>
>
> > +
> > +	memset(vq->split.desc_state, 0, vring.num *
> > +	       sizeof(struct vring_desc_state_split));
> > +	return 0;
> > +
> > +err_extra:
> > +	kfree(vq->split.desc_state);
> > +err_state:
> > +	return -ENOMEM;
> > +}
> > +
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev)
> > +{
> >   	vq->packed_ring = false;
> > -	vq->vq.callback = callback;
> > -	vq->vq.vdev = vdev;
> > -	vq->vq.name = name;
> > -	vq->vq.num_free = vring.num;
> > -	vq->vq.index = index;
> >   	vq->we_own_ring = false;
> > -	vq->notify = notify;
> > -	vq->weak_barriers = weak_barriers;
> >   	vq->broken = false;
> >   	vq->last_used_idx = 0;
> >   	vq->event_triggered = false;
> > @@ -2234,50 +2240,67 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
> >   	vq->last_add_time_valid = false;
> >   #endif
> >
> > -	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> > -		!context;
> >   	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
> >
> >   	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
> >   		vq->weak_barriers = false;
> >
> > -	vq->split.queue_dma_addr = 0;
> > -	vq->split.queue_size_in_bytes = 0;
> > -
> > -	vq->split.vring = vring;
> >   	vq->split.avail_flags_shadow = 0;
> >   	vq->split.avail_idx_shadow = 0;
> >
> >   	/* No callback?  Tell other side not to bother us. */
> > -	if (!callback) {
> > +	if (!vq->vq.callback) {
> >   		vq->split.avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
> >   		if (!vq->event)
> >   			vq->split.vring.avail->flags = cpu_to_virtio16(vdev,
> >   					vq->split.avail_flags_shadow);
> >   	}
> >
> > -	vq->split.desc_state = kmalloc_array(vring.num,
> > -			sizeof(struct vring_desc_state_split), GFP_KERNEL);
> > -	if (!vq->split.desc_state)
> > -		goto err_state;
> > -
> > -	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> > -	if (!vq->split.desc_extra)
> > -		goto err_extra;
> > -
> >   	/* Put everything in free lists. */
> >   	vq->free_head = 0;
> > -	memset(vq->split.desc_state, 0, vring.num *
> > -			sizeof(struct vring_desc_state_split));
> > +}
> > +
> > +/* Only available for split ring */
> > +struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > +					struct vring vring,
> > +					struct virtio_device *vdev,
> > +					bool weak_barriers,
> > +					bool context,
> > +					bool (*notify)(struct virtqueue *),
> > +					void (*callback)(struct virtqueue *),
> > +					const char *name)
> > +{
> > +	struct vring_virtqueue *vq;
> > +	int err;
> > +
> > +	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> > +		return NULL;
> > +
> > +	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> > +	if (!vq)
> > +		return NULL;
> > +
> > +	vq->vq.callback = callback;
> > +	vq->vq.vdev = vdev;
> > +	vq->vq.name = name;
> > +	vq->vq.index = index;
> > +	vq->notify = notify;
> > +	vq->weak_barriers = weak_barriers;
> > +	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> > +		!context;
> > +
> > +	err = __vring_virtqueue_attach_split(vq, vdev, vring);
> > +	if (err)
> > +		goto err;
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> >
> >   	spin_lock(&vdev->vqs_list_lock);
> >   	list_add_tail(&vq->vq.list, &vdev->vqs);
> >   	spin_unlock(&vdev->vqs_list_lock);
> > -	return &vq->vq;
> >
> > -err_extra:
> > -	kfree(vq->split.desc_state);
> > -err_state:
> > +	return &vq->vq;
> > +err:
> >   	kfree(vq);
> >   	return NULL;
> >   }
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 05/26] virtio_ring: split: extract the logic of init vq and attach vring
@ 2022-03-09  9:21       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:21 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 15:36:59 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:34, Xuan Zhuo 写道:
> > Split the logic of split assignment vq into three parts.
> >
> > 1. The assignment passed from the function parameter
> > 2. The part that attaches vring to vq. -- __vring_virtqueue_attach_split()
> > 3. The part that initializes vq to a fixed value --
> >     __vring_virtqueue_init_split()
> >
> > This feature is required for subsequent virtuqueue reset vring
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 111 +++++++++++++++++++++--------------
> >   1 file changed, 67 insertions(+), 44 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index d32793615451..dc6313b79305 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -2196,34 +2196,40 @@ irqreturn_t vring_interrupt(int irq, void *_vq)
> >   }
> >   EXPORT_SYMBOL_GPL(vring_interrupt);
> >
> > -/* Only available for split ring */
> > -struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > -					struct vring vring,
> > -					struct virtio_device *vdev,
> > -					bool weak_barriers,
> > -					bool context,
> > -					bool (*notify)(struct virtqueue *),
> > -					void (*callback)(struct virtqueue *),
> > -					const char *name)
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring)
> >   {
> > -	struct vring_virtqueue *vq;
> > +	vq->vq.num_free = vring.num;
> >
> > -	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> > -		return NULL;
> > +	vq->split.vring = vring;
> > +	vq->split.queue_dma_addr = 0;
> > +	vq->split.queue_size_in_bytes = 0;
> >
> > -	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> > -	if (!vq)
> > -		return NULL;
> > +	vq->split.desc_state = kmalloc_array(vring.num,
> > +					     sizeof(struct vring_desc_state_split), GFP_KERNEL);
> > +	if (!vq->split.desc_state)
> > +		goto err_state;
> >
> > +	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> > +	if (!vq->split.desc_extra)
> > +		goto err_extra;
>
>
> So this contains stuffs more than just attach. I wonder if it's better
> to split the allocation out to an dedicated helper (we have dedicated
> helper to allocate vring).

I will try in next version.

Thanks.

>
> Thanks
>
>
> > +
> > +	memset(vq->split.desc_state, 0, vring.num *
> > +	       sizeof(struct vring_desc_state_split));
> > +	return 0;
> > +
> > +err_extra:
> > +	kfree(vq->split.desc_state);
> > +err_state:
> > +	return -ENOMEM;
> > +}
> > +
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev)
> > +{
> >   	vq->packed_ring = false;
> > -	vq->vq.callback = callback;
> > -	vq->vq.vdev = vdev;
> > -	vq->vq.name = name;
> > -	vq->vq.num_free = vring.num;
> > -	vq->vq.index = index;
> >   	vq->we_own_ring = false;
> > -	vq->notify = notify;
> > -	vq->weak_barriers = weak_barriers;
> >   	vq->broken = false;
> >   	vq->last_used_idx = 0;
> >   	vq->event_triggered = false;
> > @@ -2234,50 +2240,67 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
> >   	vq->last_add_time_valid = false;
> >   #endif
> >
> > -	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> > -		!context;
> >   	vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
> >
> >   	if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
> >   		vq->weak_barriers = false;
> >
> > -	vq->split.queue_dma_addr = 0;
> > -	vq->split.queue_size_in_bytes = 0;
> > -
> > -	vq->split.vring = vring;
> >   	vq->split.avail_flags_shadow = 0;
> >   	vq->split.avail_idx_shadow = 0;
> >
> >   	/* No callback?  Tell other side not to bother us. */
> > -	if (!callback) {
> > +	if (!vq->vq.callback) {
> >   		vq->split.avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
> >   		if (!vq->event)
> >   			vq->split.vring.avail->flags = cpu_to_virtio16(vdev,
> >   					vq->split.avail_flags_shadow);
> >   	}
> >
> > -	vq->split.desc_state = kmalloc_array(vring.num,
> > -			sizeof(struct vring_desc_state_split), GFP_KERNEL);
> > -	if (!vq->split.desc_state)
> > -		goto err_state;
> > -
> > -	vq->split.desc_extra = vring_alloc_desc_extra(vq, vring.num);
> > -	if (!vq->split.desc_extra)
> > -		goto err_extra;
> > -
> >   	/* Put everything in free lists. */
> >   	vq->free_head = 0;
> > -	memset(vq->split.desc_state, 0, vring.num *
> > -			sizeof(struct vring_desc_state_split));
> > +}
> > +
> > +/* Only available for split ring */
> > +struct virtqueue *__vring_new_virtqueue(unsigned int index,
> > +					struct vring vring,
> > +					struct virtio_device *vdev,
> > +					bool weak_barriers,
> > +					bool context,
> > +					bool (*notify)(struct virtqueue *),
> > +					void (*callback)(struct virtqueue *),
> > +					const char *name)
> > +{
> > +	struct vring_virtqueue *vq;
> > +	int err;
> > +
> > +	if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
> > +		return NULL;
> > +
> > +	vq = kmalloc(sizeof(*vq), GFP_KERNEL);
> > +	if (!vq)
> > +		return NULL;
> > +
> > +	vq->vq.callback = callback;
> > +	vq->vq.vdev = vdev;
> > +	vq->vq.name = name;
> > +	vq->vq.index = index;
> > +	vq->notify = notify;
> > +	vq->weak_barriers = weak_barriers;
> > +	vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
> > +		!context;
> > +
> > +	err = __vring_virtqueue_attach_split(vq, vdev, vring);
> > +	if (err)
> > +		goto err;
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> >
> >   	spin_lock(&vdev->vqs_list_lock);
> >   	list_add_tail(&vq->vq.list, &vdev->vqs);
> >   	spin_unlock(&vdev->vqs_list_lock);
> > -	return &vq->vq;
> >
> > -err_extra:
> > -	kfree(vq->split.desc_state);
> > -err_state:
> > +	return &vq->vq;
> > +err:
> >   	kfree(vq);
> >   	return NULL;
> >   }
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 08/26] virtio_ring: extract the logic of freeing vring
  2022-03-09  7:51     ` Jason Wang
  (?)
@ 2022-03-09  9:22       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:22 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 15:51:13 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Introduce vring_free() to free the vring of vq.
> >
> > Prevent double free by setting vq->reset.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 25 ++++++++++++++++++++-----
> >   include/linux/virtio.h       |  8 ++++++++
> >   2 files changed, 28 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index b5a9bf4f45b3..e0422c04c903 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -2442,14 +2442,10 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
> >   }
> >   EXPORT_SYMBOL_GPL(vring_new_virtqueue);
> >
> > -void vring_del_virtqueue(struct virtqueue *_vq)
> > +static void __vring_free(struct virtqueue *_vq)
> >   {
> >   	struct vring_virtqueue *vq = to_vvq(_vq);
> >
> > -	spin_lock(&vq->vq.vdev->vqs_list_lock);
> > -	list_del(&_vq->list);
> > -	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> > -
> >   	if (vq->we_own_ring) {
> >   		if (vq->packed_ring) {
> >   			vring_free_queue(vq->vq.vdev,
> > @@ -2480,6 +2476,25 @@ void vring_del_virtqueue(struct virtqueue *_vq)
> >   		kfree(vq->split.desc_state);
> >   		kfree(vq->split.desc_extra);
> >   	}
> > +}
> > +
> > +static void vring_free(struct virtqueue *vq)
> > +{
> > +	__vring_free(vq);
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_VRING_RELEASE;
> > +}
> > +
> > +void vring_del_virtqueue(struct virtqueue *_vq)
> > +{
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +
> > +	spin_lock(&vq->vq.vdev->vqs_list_lock);
> > +	list_del(&_vq->list);
> > +	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> > +
> > +	if (_vq->reset != VIRTIO_VQ_RESET_STEP_VRING_RELEASE)
> > +		__vring_free(_vq);
> > +
> >   	kfree(vq);
> >   }
> >   EXPORT_SYMBOL_GPL(vring_del_virtqueue);
> > diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> > index d59adc4be068..e3714e6db330 100644
> > --- a/include/linux/virtio.h
> > +++ b/include/linux/virtio.h
> > @@ -10,6 +10,13 @@
> >   #include <linux/mod_devicetable.h>
> >   #include <linux/gfp.h>
> >
> > +enum virtio_vq_reset_step {
> > +	VIRTIO_VQ_RESET_STEP_NONE,
> > +	VIRTIO_VQ_RESET_STEP_DEVICE,
> > +	VIRTIO_VQ_RESET_STEP_VRING_RELEASE,
> > +	VIRTIO_VQ_RESET_STEP_VRING_ATTACH,
> > +};
>
>
> This part looks not related to the subject.
>
> And it needs detail documentation on this.
>
> But I wonder how useful it is, anyway we can check the reset status via
> transport specific way and in the future we may want to do more than
> just resizing (e.g PASID).


I will try and remove it from here.

Thanks.

>
> Thanks
>
>
> > +
> >   /**
> >    * virtqueue - a queue to register buffers for sending or receiving.
> >    * @list: the chain of virtqueues for this device
> > @@ -33,6 +40,7 @@ struct virtqueue {
> >   	unsigned int num_free;
> >   	unsigned int num_max;
> >   	void *priv;
> > +	enum virtio_vq_reset_step reset;
> >   };
> >
> >   int virtqueue_add_outbuf(struct virtqueue *vq,
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 08/26] virtio_ring: extract the logic of freeing vring
@ 2022-03-09  9:22       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:22 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 15:51:13 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Introduce vring_free() to free the vring of vq.
> >
> > Prevent double free by setting vq->reset.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 25 ++++++++++++++++++++-----
> >   include/linux/virtio.h       |  8 ++++++++
> >   2 files changed, 28 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index b5a9bf4f45b3..e0422c04c903 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -2442,14 +2442,10 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
> >   }
> >   EXPORT_SYMBOL_GPL(vring_new_virtqueue);
> >
> > -void vring_del_virtqueue(struct virtqueue *_vq)
> > +static void __vring_free(struct virtqueue *_vq)
> >   {
> >   	struct vring_virtqueue *vq = to_vvq(_vq);
> >
> > -	spin_lock(&vq->vq.vdev->vqs_list_lock);
> > -	list_del(&_vq->list);
> > -	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> > -
> >   	if (vq->we_own_ring) {
> >   		if (vq->packed_ring) {
> >   			vring_free_queue(vq->vq.vdev,
> > @@ -2480,6 +2476,25 @@ void vring_del_virtqueue(struct virtqueue *_vq)
> >   		kfree(vq->split.desc_state);
> >   		kfree(vq->split.desc_extra);
> >   	}
> > +}
> > +
> > +static void vring_free(struct virtqueue *vq)
> > +{
> > +	__vring_free(vq);
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_VRING_RELEASE;
> > +}
> > +
> > +void vring_del_virtqueue(struct virtqueue *_vq)
> > +{
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +
> > +	spin_lock(&vq->vq.vdev->vqs_list_lock);
> > +	list_del(&_vq->list);
> > +	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> > +
> > +	if (_vq->reset != VIRTIO_VQ_RESET_STEP_VRING_RELEASE)
> > +		__vring_free(_vq);
> > +
> >   	kfree(vq);
> >   }
> >   EXPORT_SYMBOL_GPL(vring_del_virtqueue);
> > diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> > index d59adc4be068..e3714e6db330 100644
> > --- a/include/linux/virtio.h
> > +++ b/include/linux/virtio.h
> > @@ -10,6 +10,13 @@
> >   #include <linux/mod_devicetable.h>
> >   #include <linux/gfp.h>
> >
> > +enum virtio_vq_reset_step {
> > +	VIRTIO_VQ_RESET_STEP_NONE,
> > +	VIRTIO_VQ_RESET_STEP_DEVICE,
> > +	VIRTIO_VQ_RESET_STEP_VRING_RELEASE,
> > +	VIRTIO_VQ_RESET_STEP_VRING_ATTACH,
> > +};
>
>
> This part looks not related to the subject.
>
> And it needs detail documentation on this.
>
> But I wonder how useful it is, anyway we can check the reset status via
> transport specific way and in the future we may want to do more than
> just resizing (e.g PASID).


I will try and remove it from here.

Thanks.

>
> Thanks
>
>
> > +
> >   /**
> >    * virtqueue - a queue to register buffers for sending or receiving.
> >    * @list: the chain of virtqueues for this device
> > @@ -33,6 +40,7 @@ struct virtqueue {
> >   	unsigned int num_free;
> >   	unsigned int num_max;
> >   	void *priv;
> > +	enum virtio_vq_reset_step reset;
> >   };
> >
> >   int virtqueue_add_outbuf(struct virtqueue *vq,
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 08/26] virtio_ring: extract the logic of freeing vring
@ 2022-03-09  9:22       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:22 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 15:51:13 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Introduce vring_free() to free the vring of vq.
> >
> > Prevent double free by setting vq->reset.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 25 ++++++++++++++++++++-----
> >   include/linux/virtio.h       |  8 ++++++++
> >   2 files changed, 28 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index b5a9bf4f45b3..e0422c04c903 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -2442,14 +2442,10 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
> >   }
> >   EXPORT_SYMBOL_GPL(vring_new_virtqueue);
> >
> > -void vring_del_virtqueue(struct virtqueue *_vq)
> > +static void __vring_free(struct virtqueue *_vq)
> >   {
> >   	struct vring_virtqueue *vq = to_vvq(_vq);
> >
> > -	spin_lock(&vq->vq.vdev->vqs_list_lock);
> > -	list_del(&_vq->list);
> > -	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> > -
> >   	if (vq->we_own_ring) {
> >   		if (vq->packed_ring) {
> >   			vring_free_queue(vq->vq.vdev,
> > @@ -2480,6 +2476,25 @@ void vring_del_virtqueue(struct virtqueue *_vq)
> >   		kfree(vq->split.desc_state);
> >   		kfree(vq->split.desc_extra);
> >   	}
> > +}
> > +
> > +static void vring_free(struct virtqueue *vq)
> > +{
> > +	__vring_free(vq);
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_VRING_RELEASE;
> > +}
> > +
> > +void vring_del_virtqueue(struct virtqueue *_vq)
> > +{
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +
> > +	spin_lock(&vq->vq.vdev->vqs_list_lock);
> > +	list_del(&_vq->list);
> > +	spin_unlock(&vq->vq.vdev->vqs_list_lock);
> > +
> > +	if (_vq->reset != VIRTIO_VQ_RESET_STEP_VRING_RELEASE)
> > +		__vring_free(_vq);
> > +
> >   	kfree(vq);
> >   }
> >   EXPORT_SYMBOL_GPL(vring_del_virtqueue);
> > diff --git a/include/linux/virtio.h b/include/linux/virtio.h
> > index d59adc4be068..e3714e6db330 100644
> > --- a/include/linux/virtio.h
> > +++ b/include/linux/virtio.h
> > @@ -10,6 +10,13 @@
> >   #include <linux/mod_devicetable.h>
> >   #include <linux/gfp.h>
> >
> > +enum virtio_vq_reset_step {
> > +	VIRTIO_VQ_RESET_STEP_NONE,
> > +	VIRTIO_VQ_RESET_STEP_DEVICE,
> > +	VIRTIO_VQ_RESET_STEP_VRING_RELEASE,
> > +	VIRTIO_VQ_RESET_STEP_VRING_ATTACH,
> > +};
>
>
> This part looks not related to the subject.
>
> And it needs detail documentation on this.
>
> But I wonder how useful it is, anyway we can check the reset status via
> transport specific way and in the future we may want to do more than
> just resizing (e.g PASID).


I will try and remove it from here.

Thanks.

>
> Thanks
>
>
> > +
> >   /**
> >    * virtqueue - a queue to register buffers for sending or receiving.
> >    * @list: the chain of virtqueues for this device
> > @@ -33,6 +40,7 @@ struct virtqueue {
> >   	unsigned int num_free;
> >   	unsigned int num_max;
> >   	void *priv;
> > +	enum virtio_vq_reset_step reset;
> >   };
> >
> >   int virtqueue_add_outbuf(struct virtqueue *vq,
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-09  7:55     ` Jason Wang
  (?)
@ 2022-03-09  9:24       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:24 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 15:55:44 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > virtio ring supports reset.
> >
> > Queue reset is divided into several stages.
> >
> > 1. notify device queue reset
> > 2. vring release
> > 3. attach new vring
> > 4. notify device queue re-enable
> >
> > After the first step is completed, the vring reset operation can be
> > performed. If the newly set vring num does not change, then just reset
> > the vq related value.
> >
> > Otherwise, the vring will be released and the vring will be reallocated.
> > And the vring will be attached to the vq. If this process fails, the
> > function will exit, and the state of the vq will be the vring release
> > state. You can call this function again to reallocate the vring.
> >
> > In addition, vring_align, may_reduce_num are necessary for reallocating
> > vring, so they are retained when creating vq.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> >   1 file changed, 69 insertions(+)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index e0422c04c903..148fb1fd3d5a 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> >   			/* DMA address and size information */
> >   			dma_addr_t queue_dma_addr;
> >   			size_t queue_size_in_bytes;
> > +
> > +			/* The parameters for creating vrings are reserved for
> > +			 * creating new vrings when enabling reset queue.
> > +			 */
> > +			u32 vring_align;
> > +			bool may_reduce_num;
> >   		} split;
> >
> >   		/* Available for packed ring */
> > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> >   #endif
> >   };
> >
> > +static void vring_free(struct virtqueue *vq);
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev);
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring);
> >
> >   /*
> >    * Helpers.
> > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   		return NULL;
> >   	}
> >
> > +	to_vvq(vq)->split.vring_align = vring_align;
> > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> >   	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> >   	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >   	to_vvq(vq)->we_own_ring = true;
> > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   	return vq;
> >   }
> >
> > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > +{
>
>
> So what this function does is to resize the virtqueue actually, I
> suggest to rename it as virtqueue_resize_split().

OK.

>
>
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +	struct virtio_device *vdev = _vq->vdev;
> > +	struct vring_split vring;
> > +	int err;
> > +
> > +	if (num > _vq->num_max)
> > +		return -E2BIG;
> > +
> > +	switch (vq->vq.reset) {
> > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > +		return -ENOENT;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > +		if (vq->split.vring.num == num || !num)
> > +			break;
> > +
> > +		vring_free(_vq);
> > +
> > +		fallthrough;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > +		if (!num)
> > +			num = vq->split.vring.num;
> > +
> > +		err = vring_create_vring_split(&vring, vdev,
> > +					       vq->split.vring_align,
> > +					       vq->weak_barriers,
> > +					       vq->split.may_reduce_num, num);
> > +		if (err)
> > +			return -ENOMEM;
>
>
> We'd better need a safe fallback here like:
>
> If we can't allocate new memory, we can keep using the current one.
> Otherwise an ethtool -G fail may make the device not usable.
>
> This could be done by not freeing the old vring and virtqueue states
> until new is allocated.

I've been thinking the same thing for the past two days.

>
>
> > +
> > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > +		if (err) {
> > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > +					 vring.queue,
> > +					 vring.dma_addr);
> > +			return -ENOMEM;
> > +		}
> > +
> > +		vq->split.queue_dma_addr = vring.dma_addr;
> > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > +	}
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> > +	vq->we_own_ring = true;
>
>
> This seems wrong, we have the transport (rproc/mlxtbf) that allocate the
> vring by themselves. I think we need to fail the resize for we_own_ring
> == false.

Oh, it turns out that we_own_ring is for this purpose.

Thanks.

>
> Thanks
>
>
>
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > +
> > +	return 0;
> > +}
> > +
> >
> >   /*
> >    * Packed ring specific functions - *_packed().
> > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> >   static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> >   					 struct virtio_device *vdev)
> >   {
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> >   	vq->packed_ring = false;
> >   	vq->we_own_ring = false;
> >   	vq->broken = false;
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-09  9:24       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:24 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 15:55:44 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > virtio ring supports reset.
> >
> > Queue reset is divided into several stages.
> >
> > 1. notify device queue reset
> > 2. vring release
> > 3. attach new vring
> > 4. notify device queue re-enable
> >
> > After the first step is completed, the vring reset operation can be
> > performed. If the newly set vring num does not change, then just reset
> > the vq related value.
> >
> > Otherwise, the vring will be released and the vring will be reallocated.
> > And the vring will be attached to the vq. If this process fails, the
> > function will exit, and the state of the vq will be the vring release
> > state. You can call this function again to reallocate the vring.
> >
> > In addition, vring_align, may_reduce_num are necessary for reallocating
> > vring, so they are retained when creating vq.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> >   1 file changed, 69 insertions(+)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index e0422c04c903..148fb1fd3d5a 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> >   			/* DMA address and size information */
> >   			dma_addr_t queue_dma_addr;
> >   			size_t queue_size_in_bytes;
> > +
> > +			/* The parameters for creating vrings are reserved for
> > +			 * creating new vrings when enabling reset queue.
> > +			 */
> > +			u32 vring_align;
> > +			bool may_reduce_num;
> >   		} split;
> >
> >   		/* Available for packed ring */
> > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> >   #endif
> >   };
> >
> > +static void vring_free(struct virtqueue *vq);
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev);
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring);
> >
> >   /*
> >    * Helpers.
> > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   		return NULL;
> >   	}
> >
> > +	to_vvq(vq)->split.vring_align = vring_align;
> > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> >   	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> >   	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >   	to_vvq(vq)->we_own_ring = true;
> > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   	return vq;
> >   }
> >
> > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > +{
>
>
> So what this function does is to resize the virtqueue actually, I
> suggest to rename it as virtqueue_resize_split().

OK.

>
>
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +	struct virtio_device *vdev = _vq->vdev;
> > +	struct vring_split vring;
> > +	int err;
> > +
> > +	if (num > _vq->num_max)
> > +		return -E2BIG;
> > +
> > +	switch (vq->vq.reset) {
> > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > +		return -ENOENT;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > +		if (vq->split.vring.num == num || !num)
> > +			break;
> > +
> > +		vring_free(_vq);
> > +
> > +		fallthrough;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > +		if (!num)
> > +			num = vq->split.vring.num;
> > +
> > +		err = vring_create_vring_split(&vring, vdev,
> > +					       vq->split.vring_align,
> > +					       vq->weak_barriers,
> > +					       vq->split.may_reduce_num, num);
> > +		if (err)
> > +			return -ENOMEM;
>
>
> We'd better need a safe fallback here like:
>
> If we can't allocate new memory, we can keep using the current one.
> Otherwise an ethtool -G fail may make the device not usable.
>
> This could be done by not freeing the old vring and virtqueue states
> until new is allocated.

I've been thinking the same thing for the past two days.

>
>
> > +
> > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > +		if (err) {
> > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > +					 vring.queue,
> > +					 vring.dma_addr);
> > +			return -ENOMEM;
> > +		}
> > +
> > +		vq->split.queue_dma_addr = vring.dma_addr;
> > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > +	}
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> > +	vq->we_own_ring = true;
>
>
> This seems wrong, we have the transport (rproc/mlxtbf) that allocate the
> vring by themselves. I think we need to fail the resize for we_own_ring
> == false.

Oh, it turns out that we_own_ring is for this purpose.

Thanks.

>
> Thanks
>
>
>
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > +
> > +	return 0;
> > +}
> > +
> >
> >   /*
> >    * Packed ring specific functions - *_packed().
> > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> >   static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> >   					 struct virtio_device *vdev)
> >   {
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> >   	vq->packed_ring = false;
> >   	vq->we_own_ring = false;
> >   	vq->broken = false;
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-09  9:24       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:24 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 15:55:44 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > virtio ring supports reset.
> >
> > Queue reset is divided into several stages.
> >
> > 1. notify device queue reset
> > 2. vring release
> > 3. attach new vring
> > 4. notify device queue re-enable
> >
> > After the first step is completed, the vring reset operation can be
> > performed. If the newly set vring num does not change, then just reset
> > the vq related value.
> >
> > Otherwise, the vring will be released and the vring will be reallocated.
> > And the vring will be attached to the vq. If this process fails, the
> > function will exit, and the state of the vq will be the vring release
> > state. You can call this function again to reallocate the vring.
> >
> > In addition, vring_align, may_reduce_num are necessary for reallocating
> > vring, so they are retained when creating vq.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> >   1 file changed, 69 insertions(+)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index e0422c04c903..148fb1fd3d5a 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> >   			/* DMA address and size information */
> >   			dma_addr_t queue_dma_addr;
> >   			size_t queue_size_in_bytes;
> > +
> > +			/* The parameters for creating vrings are reserved for
> > +			 * creating new vrings when enabling reset queue.
> > +			 */
> > +			u32 vring_align;
> > +			bool may_reduce_num;
> >   		} split;
> >
> >   		/* Available for packed ring */
> > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> >   #endif
> >   };
> >
> > +static void vring_free(struct virtqueue *vq);
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev);
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring);
> >
> >   /*
> >    * Helpers.
> > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   		return NULL;
> >   	}
> >
> > +	to_vvq(vq)->split.vring_align = vring_align;
> > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> >   	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> >   	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >   	to_vvq(vq)->we_own_ring = true;
> > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   	return vq;
> >   }
> >
> > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > +{
>
>
> So what this function does is to resize the virtqueue actually, I
> suggest to rename it as virtqueue_resize_split().

OK.

>
>
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +	struct virtio_device *vdev = _vq->vdev;
> > +	struct vring_split vring;
> > +	int err;
> > +
> > +	if (num > _vq->num_max)
> > +		return -E2BIG;
> > +
> > +	switch (vq->vq.reset) {
> > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > +		return -ENOENT;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > +		if (vq->split.vring.num == num || !num)
> > +			break;
> > +
> > +		vring_free(_vq);
> > +
> > +		fallthrough;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > +		if (!num)
> > +			num = vq->split.vring.num;
> > +
> > +		err = vring_create_vring_split(&vring, vdev,
> > +					       vq->split.vring_align,
> > +					       vq->weak_barriers,
> > +					       vq->split.may_reduce_num, num);
> > +		if (err)
> > +			return -ENOMEM;
>
>
> We'd better need a safe fallback here like:
>
> If we can't allocate new memory, we can keep using the current one.
> Otherwise an ethtool -G fail may make the device not usable.
>
> This could be done by not freeing the old vring and virtqueue states
> until new is allocated.

I've been thinking the same thing for the past two days.

>
>
> > +
> > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > +		if (err) {
> > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > +					 vring.queue,
> > +					 vring.dma_addr);
> > +			return -ENOMEM;
> > +		}
> > +
> > +		vq->split.queue_dma_addr = vring.dma_addr;
> > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > +	}
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> > +	vq->we_own_ring = true;
>
>
> This seems wrong, we have the transport (rproc/mlxtbf) that allocate the
> vring by themselves. I think we need to fail the resize for we_own_ring
> == false.

Oh, it turns out that we_own_ring is for this purpose.

Thanks.

>
> Thanks
>
>
>
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > +
> > +	return 0;
> > +}
> > +
> >
> >   /*
> >    * Packed ring specific functions - *_packed().
> > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> >   static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> >   					 struct virtio_device *vdev)
> >   {
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> >   	vq->packed_ring = false;
> >   	vq->we_own_ring = false;
> >   	vq->broken = false;
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 13/26] virtio: queue_reset: struct virtio_config_ops add callbacks for queue_reset
  2022-03-09  8:47     ` Jason Wang
  (?)
@ 2022-03-09  9:25       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:25 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 16:47:11 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Performing reset on a queue is divided into four steps:
> >
> >   1. reset_vq()                     - notify the device to reset the queue
> >   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >   4. enable_reset_vq()              - mmap vring to device, and enable the queue
> >
> > So add two callbacks reset_vq, enable_reset_vq to struct
> > virtio_config_ops.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   include/linux/virtio_config.h | 11 +++++++++++
> >   1 file changed, 11 insertions(+)
> >
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index 4d107ad31149..d51906b1389f 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -74,6 +74,15 @@ struct virtio_shm_region {
> >    * @set_vq_affinity: set the affinity for a virtqueue (optional).
> >    * @get_vq_affinity: get the affinity for a virtqueue (optional).
> >    * @get_shm_region: get a shared memory region based on the index.
> > + * @reset_vq: reset a queue individually (optional).
> > + *	vq: the virtqueue
> > + *	Returns 0 on success or error status
> > + *	Caller should guarantee that the vring is not accessed by any functions
> > + *	of virtqueue.
>
>
> We probably need to be more accurate here:
>
> 1) reset_vq will guarantee that the callbacks are disabled or synchronized
> 2) except for the callback, the caller should guarantee ...

OK.

Thanks.

>
> Thanks
>
>
> > + * @enable_reset_vq: enable a reset queue
> > + *	vq: the virtqueue
> > + *	Returns 0 on success or error status
> > + *	If reset_vq is set, then enable_reset_vq must also be set.
> >    */
> >   typedef void vq_callback_t(struct virtqueue *);
> >   struct virtio_config_ops {
> > @@ -100,6 +109,8 @@ struct virtio_config_ops {
> >   			int index);
> >   	bool (*get_shm_region)(struct virtio_device *vdev,
> >   			       struct virtio_shm_region *region, u8 id);
> > +	int (*reset_vq)(struct virtqueue *vq);
> > +	int (*enable_reset_vq)(struct virtqueue *vq);
> >   };
> >
> >   /* If driver didn't advertise the feature, it will never appear. */
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 13/26] virtio: queue_reset: struct virtio_config_ops add callbacks for queue_reset
@ 2022-03-09  9:25       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:25 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 16:47:11 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Performing reset on a queue is divided into four steps:
> >
> >   1. reset_vq()                     - notify the device to reset the queue
> >   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >   4. enable_reset_vq()              - mmap vring to device, and enable the queue
> >
> > So add two callbacks reset_vq, enable_reset_vq to struct
> > virtio_config_ops.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   include/linux/virtio_config.h | 11 +++++++++++
> >   1 file changed, 11 insertions(+)
> >
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index 4d107ad31149..d51906b1389f 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -74,6 +74,15 @@ struct virtio_shm_region {
> >    * @set_vq_affinity: set the affinity for a virtqueue (optional).
> >    * @get_vq_affinity: get the affinity for a virtqueue (optional).
> >    * @get_shm_region: get a shared memory region based on the index.
> > + * @reset_vq: reset a queue individually (optional).
> > + *	vq: the virtqueue
> > + *	Returns 0 on success or error status
> > + *	Caller should guarantee that the vring is not accessed by any functions
> > + *	of virtqueue.
>
>
> We probably need to be more accurate here:
>
> 1) reset_vq will guarantee that the callbacks are disabled or synchronized
> 2) except for the callback, the caller should guarantee ...

OK.

Thanks.

>
> Thanks
>
>
> > + * @enable_reset_vq: enable a reset queue
> > + *	vq: the virtqueue
> > + *	Returns 0 on success or error status
> > + *	If reset_vq is set, then enable_reset_vq must also be set.
> >    */
> >   typedef void vq_callback_t(struct virtqueue *);
> >   struct virtio_config_ops {
> > @@ -100,6 +109,8 @@ struct virtio_config_ops {
> >   			int index);
> >   	bool (*get_shm_region)(struct virtio_device *vdev,
> >   			       struct virtio_shm_region *region, u8 id);
> > +	int (*reset_vq)(struct virtqueue *vq);
> > +	int (*enable_reset_vq)(struct virtqueue *vq);
> >   };
> >
> >   /* If driver didn't advertise the feature, it will never appear. */
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 13/26] virtio: queue_reset: struct virtio_config_ops add callbacks for queue_reset
@ 2022-03-09  9:25       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:25 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 16:47:11 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Performing reset on a queue is divided into four steps:
> >
> >   1. reset_vq()                     - notify the device to reset the queue
> >   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >   4. enable_reset_vq()              - mmap vring to device, and enable the queue
> >
> > So add two callbacks reset_vq, enable_reset_vq to struct
> > virtio_config_ops.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   include/linux/virtio_config.h | 11 +++++++++++
> >   1 file changed, 11 insertions(+)
> >
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index 4d107ad31149..d51906b1389f 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -74,6 +74,15 @@ struct virtio_shm_region {
> >    * @set_vq_affinity: set the affinity for a virtqueue (optional).
> >    * @get_vq_affinity: get the affinity for a virtqueue (optional).
> >    * @get_shm_region: get a shared memory region based on the index.
> > + * @reset_vq: reset a queue individually (optional).
> > + *	vq: the virtqueue
> > + *	Returns 0 on success or error status
> > + *	Caller should guarantee that the vring is not accessed by any functions
> > + *	of virtqueue.
>
>
> We probably need to be more accurate here:
>
> 1) reset_vq will guarantee that the callbacks are disabled or synchronized
> 2) except for the callback, the caller should guarantee ...

OK.

Thanks.

>
> Thanks
>
>
> > + * @enable_reset_vq: enable a reset queue
> > + *	vq: the virtqueue
> > + *	Returns 0 on success or error status
> > + *	If reset_vq is set, then enable_reset_vq must also be set.
> >    */
> >   typedef void vq_callback_t(struct virtqueue *);
> >   struct virtio_config_ops {
> > @@ -100,6 +109,8 @@ struct virtio_config_ops {
> >   			int index);
> >   	bool (*get_shm_region)(struct virtio_device *vdev,
> >   			       struct virtio_shm_region *region, u8 id);
> > +	int (*reset_vq)(struct virtqueue *vq);
> > +	int (*enable_reset_vq)(struct virtqueue *vq);
> >   };
> >
> >   /* If driver didn't advertise the feature, it will never appear. */
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 14/26] virtio: add helper for queue reset
  2022-03-09  8:48     ` Jason Wang
  (?)
@ 2022-03-09  9:27       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:27 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 16:48:28 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Add helper for virtio queue reset.
> >
> > * virtio_reset_vq(): reset a queue individually
> > * virtio_enable_resetq(): enable a reset queue
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   include/linux/virtio_config.h | 40 +++++++++++++++++++++++++++++++++++
> >   1 file changed, 40 insertions(+)
> >
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index d51906b1389f..0b81fbe17c85 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -230,6 +230,46 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
> >   				      desc);
> >   }
> >
> > +/**
> > + * virtio_reset_vq - reset a queue individually
> > + * @vq: the virtqueue
> > + *
> > + * returns 0 on success or error status
> > + *
> > + * The api process of reset under normal circumstances:
> > + *	1. virtio_reset_vq()              - notify the device to reset the queue
> > + *	2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> > + *	3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> > + *	4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> > + *
> > + * Caller should guarantee that the vring is not accessed by any functions
> > + * of virtqueue.
> > + */
> > +static inline
> > +int virtio_reset_vq(struct virtqueue *vq)
> > +{
>
>
> It looks to me the prefix "virtio" is used for the device specific
> operations.
>
> I wonder if it's better to rename this as virtqueue_reste() and move it
> to virtio_ring.c?

Call vq->vdev->config->reset_vq in virtio_ring.c?

If it fits, I think it's fine.

Thanks.

>
> Thanks
>
>
> > +	if (!vq->vdev->config->reset_vq)
> > +		return -ENOENT;
> > +
> > +	return vq->vdev->config->reset_vq(vq);
> > +}
> > +
> > +/**
> > + * virtio_enable_resetq - enable a reset queue
> > + * @vq: the virtqueue
> > + *
> > + * returns 0 on success or error status
> > + *
> > + */
> > +static inline
> > +int virtio_enable_resetq(struct virtqueue *vq)
> > +{
> > +	if (!vq->vdev->config->enable_reset_vq)
> > +		return -ENOENT;
> > +
> > +	return vq->vdev->config->enable_reset_vq(vq);
> > +}
> > +
> >   /**
> >    * virtio_device_ready - enable vq use in probe function
> >    * @vdev: the device
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 14/26] virtio: add helper for queue reset
@ 2022-03-09  9:27       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:27 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 16:48:28 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Add helper for virtio queue reset.
> >
> > * virtio_reset_vq(): reset a queue individually
> > * virtio_enable_resetq(): enable a reset queue
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   include/linux/virtio_config.h | 40 +++++++++++++++++++++++++++++++++++
> >   1 file changed, 40 insertions(+)
> >
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index d51906b1389f..0b81fbe17c85 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -230,6 +230,46 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
> >   				      desc);
> >   }
> >
> > +/**
> > + * virtio_reset_vq - reset a queue individually
> > + * @vq: the virtqueue
> > + *
> > + * returns 0 on success or error status
> > + *
> > + * The api process of reset under normal circumstances:
> > + *	1. virtio_reset_vq()              - notify the device to reset the queue
> > + *	2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> > + *	3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> > + *	4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> > + *
> > + * Caller should guarantee that the vring is not accessed by any functions
> > + * of virtqueue.
> > + */
> > +static inline
> > +int virtio_reset_vq(struct virtqueue *vq)
> > +{
>
>
> It looks to me the prefix "virtio" is used for the device specific
> operations.
>
> I wonder if it's better to rename this as virtqueue_reste() and move it
> to virtio_ring.c?

Call vq->vdev->config->reset_vq in virtio_ring.c?

If it fits, I think it's fine.

Thanks.

>
> Thanks
>
>
> > +	if (!vq->vdev->config->reset_vq)
> > +		return -ENOENT;
> > +
> > +	return vq->vdev->config->reset_vq(vq);
> > +}
> > +
> > +/**
> > + * virtio_enable_resetq - enable a reset queue
> > + * @vq: the virtqueue
> > + *
> > + * returns 0 on success or error status
> > + *
> > + */
> > +static inline
> > +int virtio_enable_resetq(struct virtqueue *vq)
> > +{
> > +	if (!vq->vdev->config->enable_reset_vq)
> > +		return -ENOENT;
> > +
> > +	return vq->vdev->config->enable_reset_vq(vq);
> > +}
> > +
> >   /**
> >    * virtio_device_ready - enable vq use in probe function
> >    * @vdev: the device
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 14/26] virtio: add helper for queue reset
@ 2022-03-09  9:27       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:27 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 16:48:28 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Add helper for virtio queue reset.
> >
> > * virtio_reset_vq(): reset a queue individually
> > * virtio_enable_resetq(): enable a reset queue
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   include/linux/virtio_config.h | 40 +++++++++++++++++++++++++++++++++++
> >   1 file changed, 40 insertions(+)
> >
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index d51906b1389f..0b81fbe17c85 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -230,6 +230,46 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
> >   				      desc);
> >   }
> >
> > +/**
> > + * virtio_reset_vq - reset a queue individually
> > + * @vq: the virtqueue
> > + *
> > + * returns 0 on success or error status
> > + *
> > + * The api process of reset under normal circumstances:
> > + *	1. virtio_reset_vq()              - notify the device to reset the queue
> > + *	2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> > + *	3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> > + *	4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> > + *
> > + * Caller should guarantee that the vring is not accessed by any functions
> > + * of virtqueue.
> > + */
> > +static inline
> > +int virtio_reset_vq(struct virtqueue *vq)
> > +{
>
>
> It looks to me the prefix "virtio" is used for the device specific
> operations.
>
> I wonder if it's better to rename this as virtqueue_reste() and move it
> to virtio_ring.c?

Call vq->vdev->config->reset_vq in virtio_ring.c?

If it fits, I think it's fine.

Thanks.

>
> Thanks
>
>
> > +	if (!vq->vdev->config->reset_vq)
> > +		return -ENOENT;
> > +
> > +	return vq->vdev->config->reset_vq(vq);
> > +}
> > +
> > +/**
> > + * virtio_enable_resetq - enable a reset queue
> > + * @vq: the virtqueue
> > + *
> > + * returns 0 on success or error status
> > + *
> > + */
> > +static inline
> > +int virtio_enable_resetq(struct virtqueue *vq)
> > +{
> > +	if (!vq->vdev->config->enable_reset_vq)
> > +		return -ENOENT;
> > +
> > +	return vq->vdev->config->enable_reset_vq(vq);
> > +}
> > +
> >   /**
> >    * virtio_device_ready - enable vq use in probe function
> >    * @vdev: the device
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 25/26] virtio_net: set the default max ring size by find_vqs()
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-09  9:28     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:28 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Use virtio_find_vqs_ctx_size() to specify the maximum ring size of tx,
> rx at the same time.
>
>                           | rx/tx ring size
> -------------------------------------------
> speed == UNKNOWN or < 10G| 1024
> speed < 40G              | 4096
> speed >= 40G             | 8192
>
> Call virtnet_update_settings() once before calling init_vqs() to update
> speed.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/net/virtio_net.c | 42 ++++++++++++++++++++++++++++++++++++----
>   1 file changed, 38 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index ffff323dcef0..f1bdc6ce21c3 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -2977,6 +2977,29 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
>   		   (unsigned int)GOOD_PACKET_LEN);
>   }
>   
> +static void virtnet_config_sizes(struct virtnet_info *vi, u32 *sizes)
> +{
> +	u32 i, rx_size, tx_size;
> +
> +	if (vi->speed == SPEED_UNKNOWN || vi->speed < SPEED_10000) {
> +		rx_size = 1024;
> +		tx_size = 1024;
> +
> +	} else if (vi->speed < SPEED_40000) {
> +		rx_size = 1024 * 4;
> +		tx_size = 1024 * 4;
> +
> +	} else {
> +		rx_size = 1024 * 8;
> +		tx_size = 1024 * 8;
> +	}
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++) {
> +		sizes[rxq2vq(i)] = rx_size;
> +		sizes[txq2vq(i)] = tx_size;
> +	}
> +}
> +
>   static int virtnet_find_vqs(struct virtnet_info *vi)
>   {
>   	vq_callback_t **callbacks;
> @@ -2984,6 +3007,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   	int ret = -ENOMEM;
>   	int i, total_vqs;
>   	const char **names;
> +	u32 *sizes;
>   	bool *ctx;
>   
>   	/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
> @@ -3011,10 +3035,15 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   		ctx = NULL;
>   	}
>   
> +	sizes = kmalloc_array(total_vqs, sizeof(*sizes), GFP_KERNEL);
> +	if (!sizes)
> +		goto err_sizes;
> +
>   	/* Parameters for control virtqueue, if any */
>   	if (vi->has_cvq) {
>   		callbacks[total_vqs - 1] = NULL;
>   		names[total_vqs - 1] = "control";
> +		sizes[total_vqs - 1] = 0;


Nit: Do we need a sane value for the control vq? (e.g 64)

Thanks


>   	}
>   
>   	/* Allocate/initialize parameters for send/receive virtqueues */
> @@ -3029,8 +3058,10 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   			ctx[rxq2vq(i)] = true;
>   	}
>   
> -	ret = virtio_find_vqs_ctx(vi->vdev, total_vqs, vqs, callbacks,
> -				  names, ctx, NULL);
> +	virtnet_config_sizes(vi, sizes);
> +
> +	ret = virtio_find_vqs_ctx_size(vi->vdev, total_vqs, vqs, callbacks,
> +				       names, ctx, NULL, sizes);
>   	if (ret)
>   		goto err_find;
>   
> @@ -3050,6 +3081,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   
>   
>   err_find:
> +	kfree(sizes);
> +err_sizes:
>   	kfree(ctx);
>   err_ctx:
>   	kfree(names);
> @@ -3368,6 +3401,9 @@ static int virtnet_probe(struct virtio_device *vdev)
>   		vi->curr_queue_pairs = num_online_cpus();
>   	vi->max_queue_pairs = max_queue_pairs;
>   
> +	virtnet_init_settings(dev);
> +	virtnet_update_settings(vi);
> +
>   	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
>   	err = init_vqs(vi);
>   	if (err)
> @@ -3380,8 +3416,6 @@ static int virtnet_probe(struct virtio_device *vdev)
>   	netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs);
>   	netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs);
>   
> -	virtnet_init_settings(dev);
> -
>   	if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
>   		vi->failover = net_failover_create(vi->dev);
>   		if (IS_ERR(vi->failover)) {


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 25/26] virtio_net: set the default max ring size by find_vqs()
@ 2022-03-09  9:28     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:28 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Use virtio_find_vqs_ctx_size() to specify the maximum ring size of tx,
> rx at the same time.
>
>                           | rx/tx ring size
> -------------------------------------------
> speed == UNKNOWN or < 10G| 1024
> speed < 40G              | 4096
> speed >= 40G             | 8192
>
> Call virtnet_update_settings() once before calling init_vqs() to update
> speed.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/net/virtio_net.c | 42 ++++++++++++++++++++++++++++++++++++----
>   1 file changed, 38 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index ffff323dcef0..f1bdc6ce21c3 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -2977,6 +2977,29 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
>   		   (unsigned int)GOOD_PACKET_LEN);
>   }
>   
> +static void virtnet_config_sizes(struct virtnet_info *vi, u32 *sizes)
> +{
> +	u32 i, rx_size, tx_size;
> +
> +	if (vi->speed == SPEED_UNKNOWN || vi->speed < SPEED_10000) {
> +		rx_size = 1024;
> +		tx_size = 1024;
> +
> +	} else if (vi->speed < SPEED_40000) {
> +		rx_size = 1024 * 4;
> +		tx_size = 1024 * 4;
> +
> +	} else {
> +		rx_size = 1024 * 8;
> +		tx_size = 1024 * 8;
> +	}
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++) {
> +		sizes[rxq2vq(i)] = rx_size;
> +		sizes[txq2vq(i)] = tx_size;
> +	}
> +}
> +
>   static int virtnet_find_vqs(struct virtnet_info *vi)
>   {
>   	vq_callback_t **callbacks;
> @@ -2984,6 +3007,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   	int ret = -ENOMEM;
>   	int i, total_vqs;
>   	const char **names;
> +	u32 *sizes;
>   	bool *ctx;
>   
>   	/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
> @@ -3011,10 +3035,15 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   		ctx = NULL;
>   	}
>   
> +	sizes = kmalloc_array(total_vqs, sizeof(*sizes), GFP_KERNEL);
> +	if (!sizes)
> +		goto err_sizes;
> +
>   	/* Parameters for control virtqueue, if any */
>   	if (vi->has_cvq) {
>   		callbacks[total_vqs - 1] = NULL;
>   		names[total_vqs - 1] = "control";
> +		sizes[total_vqs - 1] = 0;


Nit: Do we need a sane value for the control vq? (e.g 64)

Thanks


>   	}
>   
>   	/* Allocate/initialize parameters for send/receive virtqueues */
> @@ -3029,8 +3058,10 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   			ctx[rxq2vq(i)] = true;
>   	}
>   
> -	ret = virtio_find_vqs_ctx(vi->vdev, total_vqs, vqs, callbacks,
> -				  names, ctx, NULL);
> +	virtnet_config_sizes(vi, sizes);
> +
> +	ret = virtio_find_vqs_ctx_size(vi->vdev, total_vqs, vqs, callbacks,
> +				       names, ctx, NULL, sizes);
>   	if (ret)
>   		goto err_find;
>   
> @@ -3050,6 +3081,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   
>   
>   err_find:
> +	kfree(sizes);
> +err_sizes:
>   	kfree(ctx);
>   err_ctx:
>   	kfree(names);
> @@ -3368,6 +3401,9 @@ static int virtnet_probe(struct virtio_device *vdev)
>   		vi->curr_queue_pairs = num_online_cpus();
>   	vi->max_queue_pairs = max_queue_pairs;
>   
> +	virtnet_init_settings(dev);
> +	virtnet_update_settings(vi);
> +
>   	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
>   	err = init_vqs(vi);
>   	if (err)
> @@ -3380,8 +3416,6 @@ static int virtnet_probe(struct virtio_device *vdev)
>   	netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs);
>   	netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs);
>   
> -	virtnet_init_settings(dev);
> -
>   	if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
>   		vi->failover = net_failover_create(vi->dev);
>   		if (IS_ERR(vi->failover)) {

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 25/26] virtio_net: set the default max ring size by find_vqs()
@ 2022-03-09  9:28     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:28 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Use virtio_find_vqs_ctx_size() to specify the maximum ring size of tx,
> rx at the same time.
>
>                           | rx/tx ring size
> -------------------------------------------
> speed == UNKNOWN or < 10G| 1024
> speed < 40G              | 4096
> speed >= 40G             | 8192
>
> Call virtnet_update_settings() once before calling init_vqs() to update
> speed.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/net/virtio_net.c | 42 ++++++++++++++++++++++++++++++++++++----
>   1 file changed, 38 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index ffff323dcef0..f1bdc6ce21c3 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -2977,6 +2977,29 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
>   		   (unsigned int)GOOD_PACKET_LEN);
>   }
>   
> +static void virtnet_config_sizes(struct virtnet_info *vi, u32 *sizes)
> +{
> +	u32 i, rx_size, tx_size;
> +
> +	if (vi->speed == SPEED_UNKNOWN || vi->speed < SPEED_10000) {
> +		rx_size = 1024;
> +		tx_size = 1024;
> +
> +	} else if (vi->speed < SPEED_40000) {
> +		rx_size = 1024 * 4;
> +		tx_size = 1024 * 4;
> +
> +	} else {
> +		rx_size = 1024 * 8;
> +		tx_size = 1024 * 8;
> +	}
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++) {
> +		sizes[rxq2vq(i)] = rx_size;
> +		sizes[txq2vq(i)] = tx_size;
> +	}
> +}
> +
>   static int virtnet_find_vqs(struct virtnet_info *vi)
>   {
>   	vq_callback_t **callbacks;
> @@ -2984,6 +3007,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   	int ret = -ENOMEM;
>   	int i, total_vqs;
>   	const char **names;
> +	u32 *sizes;
>   	bool *ctx;
>   
>   	/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
> @@ -3011,10 +3035,15 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   		ctx = NULL;
>   	}
>   
> +	sizes = kmalloc_array(total_vqs, sizeof(*sizes), GFP_KERNEL);
> +	if (!sizes)
> +		goto err_sizes;
> +
>   	/* Parameters for control virtqueue, if any */
>   	if (vi->has_cvq) {
>   		callbacks[total_vqs - 1] = NULL;
>   		names[total_vqs - 1] = "control";
> +		sizes[total_vqs - 1] = 0;


Nit: Do we need a sane value for the control vq? (e.g 64)

Thanks


>   	}
>   
>   	/* Allocate/initialize parameters for send/receive virtqueues */
> @@ -3029,8 +3058,10 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   			ctx[rxq2vq(i)] = true;
>   	}
>   
> -	ret = virtio_find_vqs_ctx(vi->vdev, total_vqs, vqs, callbacks,
> -				  names, ctx, NULL);
> +	virtnet_config_sizes(vi, sizes);
> +
> +	ret = virtio_find_vqs_ctx_size(vi->vdev, total_vqs, vqs, callbacks,
> +				       names, ctx, NULL, sizes);
>   	if (ret)
>   		goto err_find;
>   
> @@ -3050,6 +3081,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
>   
>   
>   err_find:
> +	kfree(sizes);
> +err_sizes:
>   	kfree(ctx);
>   err_ctx:
>   	kfree(names);
> @@ -3368,6 +3401,9 @@ static int virtnet_probe(struct virtio_device *vdev)
>   		vi->curr_queue_pairs = num_online_cpus();
>   	vi->max_queue_pairs = max_queue_pairs;
>   
> +	virtnet_init_settings(dev);
> +	virtnet_update_settings(vi);
> +
>   	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
>   	err = init_vqs(vi);
>   	if (err)
> @@ -3380,8 +3416,6 @@ static int virtnet_probe(struct virtio_device *vdev)
>   	netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs);
>   	netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs);
>   
> -	virtnet_init_settings(dev);
> -
>   	if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
>   		vi->failover = net_failover_create(vi->dev);
>   		if (IS_ERR(vi->failover)) {


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 26/26] virtio_net: support set_ringparam
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-09  9:29     ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:29 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Support set_ringparam based on virtio queue reset.
>
> The rx,tx_pending required to be passed must be power of 2.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/net/virtio_net.c | 47 ++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 47 insertions(+)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index f1bdc6ce21c3..1fa2d632a994 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -2290,6 +2290,52 @@ static void virtnet_get_ringparam(struct net_device *dev,
>   	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
>   }
>   
> +static int virtnet_set_ringparam(struct net_device *dev,
> +				 struct ethtool_ringparam *ring,
> +				 struct kernel_ethtool_ringparam *kernel_ring,
> +				 struct netlink_ext_ack *extack)
> +{
> +	struct virtnet_info *vi = netdev_priv(dev);
> +	u32 rx_pending, tx_pending;
> +	struct receive_queue *rq;
> +	struct send_queue *sq;
> +	int i, err;
> +
> +	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
> +		return -EINVAL;


Any chance that we may hit this EINVAL?

Thanks


> +
> +	rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
> +	tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
> +
> +	if (ring->rx_pending == rx_pending &&
> +	    ring->tx_pending == tx_pending)
> +		return 0;
> +
> +	if (ring->rx_pending > virtqueue_get_vring_max_size(vi->rq[0].vq))
> +		return -EINVAL;
> +
> +	if (ring->tx_pending > virtqueue_get_vring_max_size(vi->sq[0].vq))
> +		return -EINVAL;
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++) {
> +		rq = vi->rq + i;
> +		sq = vi->sq + i;
> +
> +		if (ring->tx_pending != tx_pending) {
> +			err = virtnet_tx_vq_reset(vi, sq, ring->tx_pending);
> +			if (err)
> +				return err;
> +		}
> +
> +		if (ring->rx_pending != rx_pending) {
> +			err = virtnet_rx_vq_reset(vi, rq, ring->rx_pending);
> +			if (err)
> +				return err;
> +		}
> +	}
> +
> +	return 0;
> +}
>   
>   static void virtnet_get_drvinfo(struct net_device *dev,
>   				struct ethtool_drvinfo *info)
> @@ -2523,6 +2569,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
>   	.get_drvinfo = virtnet_get_drvinfo,
>   	.get_link = ethtool_op_get_link,
>   	.get_ringparam = virtnet_get_ringparam,
> +	.set_ringparam = virtnet_set_ringparam,
>   	.get_strings = virtnet_get_strings,
>   	.get_sset_count = virtnet_get_sset_count,
>   	.get_ethtool_stats = virtnet_get_ethtool_stats,


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 26/26] virtio_net: support set_ringparam
@ 2022-03-09  9:29     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:29 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Support set_ringparam based on virtio queue reset.
>
> The rx,tx_pending required to be passed must be power of 2.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/net/virtio_net.c | 47 ++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 47 insertions(+)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index f1bdc6ce21c3..1fa2d632a994 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -2290,6 +2290,52 @@ static void virtnet_get_ringparam(struct net_device *dev,
>   	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
>   }
>   
> +static int virtnet_set_ringparam(struct net_device *dev,
> +				 struct ethtool_ringparam *ring,
> +				 struct kernel_ethtool_ringparam *kernel_ring,
> +				 struct netlink_ext_ack *extack)
> +{
> +	struct virtnet_info *vi = netdev_priv(dev);
> +	u32 rx_pending, tx_pending;
> +	struct receive_queue *rq;
> +	struct send_queue *sq;
> +	int i, err;
> +
> +	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
> +		return -EINVAL;


Any chance that we may hit this EINVAL?

Thanks


> +
> +	rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
> +	tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
> +
> +	if (ring->rx_pending == rx_pending &&
> +	    ring->tx_pending == tx_pending)
> +		return 0;
> +
> +	if (ring->rx_pending > virtqueue_get_vring_max_size(vi->rq[0].vq))
> +		return -EINVAL;
> +
> +	if (ring->tx_pending > virtqueue_get_vring_max_size(vi->sq[0].vq))
> +		return -EINVAL;
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++) {
> +		rq = vi->rq + i;
> +		sq = vi->sq + i;
> +
> +		if (ring->tx_pending != tx_pending) {
> +			err = virtnet_tx_vq_reset(vi, sq, ring->tx_pending);
> +			if (err)
> +				return err;
> +		}
> +
> +		if (ring->rx_pending != rx_pending) {
> +			err = virtnet_rx_vq_reset(vi, rq, ring->rx_pending);
> +			if (err)
> +				return err;
> +		}
> +	}
> +
> +	return 0;
> +}
>   
>   static void virtnet_get_drvinfo(struct net_device *dev,
>   				struct ethtool_drvinfo *info)
> @@ -2523,6 +2569,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
>   	.get_drvinfo = virtnet_get_drvinfo,
>   	.get_link = ethtool_op_get_link,
>   	.get_ringparam = virtnet_get_ringparam,
> +	.set_ringparam = virtnet_set_ringparam,
>   	.get_strings = virtnet_get_strings,
>   	.get_sset_count = virtnet_get_sset_count,
>   	.get_ethtool_stats = virtnet_get_ethtool_stats,

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 26/26] virtio_net: support set_ringparam
@ 2022-03-09  9:29     ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-09  9:29 UTC (permalink / raw)
  To: Xuan Zhuo, virtualization, netdev
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf


在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> Support set_ringparam based on virtio queue reset.
>
> The rx,tx_pending required to be passed must be power of 2.
>
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>   drivers/net/virtio_net.c | 47 ++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 47 insertions(+)
>
> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> index f1bdc6ce21c3..1fa2d632a994 100644
> --- a/drivers/net/virtio_net.c
> +++ b/drivers/net/virtio_net.c
> @@ -2290,6 +2290,52 @@ static void virtnet_get_ringparam(struct net_device *dev,
>   	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
>   }
>   
> +static int virtnet_set_ringparam(struct net_device *dev,
> +				 struct ethtool_ringparam *ring,
> +				 struct kernel_ethtool_ringparam *kernel_ring,
> +				 struct netlink_ext_ack *extack)
> +{
> +	struct virtnet_info *vi = netdev_priv(dev);
> +	u32 rx_pending, tx_pending;
> +	struct receive_queue *rq;
> +	struct send_queue *sq;
> +	int i, err;
> +
> +	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
> +		return -EINVAL;


Any chance that we may hit this EINVAL?

Thanks


> +
> +	rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
> +	tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
> +
> +	if (ring->rx_pending == rx_pending &&
> +	    ring->tx_pending == tx_pending)
> +		return 0;
> +
> +	if (ring->rx_pending > virtqueue_get_vring_max_size(vi->rq[0].vq))
> +		return -EINVAL;
> +
> +	if (ring->tx_pending > virtqueue_get_vring_max_size(vi->sq[0].vq))
> +		return -EINVAL;
> +
> +	for (i = 0; i < vi->max_queue_pairs; i++) {
> +		rq = vi->rq + i;
> +		sq = vi->sq + i;
> +
> +		if (ring->tx_pending != tx_pending) {
> +			err = virtnet_tx_vq_reset(vi, sq, ring->tx_pending);
> +			if (err)
> +				return err;
> +		}
> +
> +		if (ring->rx_pending != rx_pending) {
> +			err = virtnet_rx_vq_reset(vi, rq, ring->rx_pending);
> +			if (err)
> +				return err;
> +		}
> +	}
> +
> +	return 0;
> +}
>   
>   static void virtnet_get_drvinfo(struct net_device *dev,
>   				struct ethtool_drvinfo *info)
> @@ -2523,6 +2569,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
>   	.get_drvinfo = virtnet_get_drvinfo,
>   	.get_link = ethtool_op_get_link,
>   	.get_ringparam = virtnet_get_ringparam,
> +	.set_ringparam = virtnet_set_ringparam,
>   	.get_strings = virtnet_get_strings,
>   	.get_sset_count = virtnet_get_sset_count,
>   	.get_ethtool_stats = virtnet_get_ethtool_stats,


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
  2022-03-09  8:54     ` Jason Wang
  (?)
@ 2022-03-09  9:32       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:32 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements virtio pci support for QUEUE RESET.
> >
> > Performing reset on a queue is divided into these steps:
> >
> >   1. virtio_reset_vq()              - notify the device to reset the queue
> >   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >   4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> >
> > This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
> > pci scenario.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_pci_common.c |  8 +--
> >   drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
> >   2 files changed, 88 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> > index fdbde1db5ec5..863d3a8a0956 100644
> > --- a/drivers/virtio/virtio_pci_common.c
> > +++ b/drivers/virtio/virtio_pci_common.c
> > @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
> >   	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
> >   	unsigned long flags;
> >
> > -	spin_lock_irqsave(&vp_dev->lock, flags);
> > -	list_del(&info->node);
> > -	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	if (!vq->reset) {
> > +		spin_lock_irqsave(&vp_dev->lock, flags);
> > +		list_del(&info->node);
> > +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	}
> >
> >   	vp_dev->del_vq(info);
> >   	kfree(info);
> > diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> > index 49a4493732cf..3c67d3607802 100644
> > --- a/drivers/virtio/virtio_pci_modern.c
> > +++ b/drivers/virtio/virtio_pci_modern.c
> > @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
> >   	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
> >   			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
> >   		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
> > +
> > +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
> > +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
> >   }
> >
> >   /* virtio config->finalize_features() implementation */
> > @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
> >   	return 0;
> >   }
> >
> > +static int vp_modern_reset_vq(struct virtqueue *vq)
> > +{
> > +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> > +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> > +	struct virtio_pci_vq_info *info;
> > +	unsigned long flags;
> > +	unsigned int irq;
> > +
> > +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> > +		return -ENOENT;
> > +
> > +	vp_modern_set_queue_reset(mdev, vq->index);
> > +
> > +	info = vp_dev->vqs[vq->index];
> > +
> > +	/* delete vq from irq handler */
> > +	spin_lock_irqsave(&vp_dev->lock, flags);
> > +	list_del(&info->node);
> > +	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +
> > +	INIT_LIST_HEAD(&info->node);
> > +
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
> > +
> > +	/* sync irq callback. */
> > +	if (vp_dev->intx_enabled) {
> > +		irq = vp_dev->pci_dev->irq;
> > +
> > +	} else {
> > +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
> > +			return 0;
> > +
> > +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
> > +	}
> > +
> > +	synchronize_irq(irq);
>
>
> Synchronize_irq() is not sufficient here since it breaks the effort of
> the interrupt hardening which is done by commits:
>
> 080cd7c3ac87 virtio-pci: harden INTX interrupts
> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>
> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
> used for the affinity managed irq but we're discussing a fix.

I need to understand it first.

>
>
> > +
> > +	return 0;
> > +}
> > +
> > +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
> > +{
> > +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> > +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> > +	struct virtio_pci_vq_info *info;
> > +	unsigned long flags, index;
> > +	int err;
> > +
> > +	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
> > +		return -EBUSY;
> > +
> > +	index = vq->index;
> > +	info = vp_dev->vqs[index];
> > +
> > +	/* check queue reset status */
> > +	if (vp_modern_get_queue_reset(mdev, index) != 1)
> > +		return -EBUSY;
> > +
> > +	err = vp_active_vq(vq, info->msix_vector);
> > +	if (err)
> > +		return err;
> > +
> > +	if (vq->callback) {
> > +		spin_lock_irqsave(&vp_dev->lock, flags);
> > +		list_add(&info->node, &vp_dev->virtqueues);
> > +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	} else {
> > +		INIT_LIST_HEAD(&info->node);
> > +	}
> > +
> > +	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
>
>
> Any reason we need to check queue_enable() here?

The purpose of this function is to enable a reset vq, so call queue_enable() to
activate it.

Thanks.

>
> Thanks
>
>
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> > +	return 0;
> > +}
> > +
> >   static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
> >   {
> >   	return vp_modern_config_vector(&vp_dev->mdev, vector);
> > @@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
> >   	.set_vq_affinity = vp_set_vq_affinity,
> >   	.get_vq_affinity = vp_get_vq_affinity,
> >   	.get_shm_region  = vp_get_shm_region,
> > +	.reset_vq	 = vp_modern_reset_vq,
> > +	.enable_reset_vq = vp_modern_enable_reset_vq,
> >   };
> >
> >   static const struct virtio_config_ops virtio_pci_config_ops = {
> > @@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
> >   	.set_vq_affinity = vp_set_vq_affinity,
> >   	.get_vq_affinity = vp_get_vq_affinity,
> >   	.get_shm_region  = vp_get_shm_region,
> > +	.reset_vq	 = vp_modern_reset_vq,
> > +	.enable_reset_vq = vp_modern_enable_reset_vq,
> >   };
> >
> >   /* the PCI probing function */
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-09  9:32       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:32 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements virtio pci support for QUEUE RESET.
> >
> > Performing reset on a queue is divided into these steps:
> >
> >   1. virtio_reset_vq()              - notify the device to reset the queue
> >   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >   4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> >
> > This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
> > pci scenario.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_pci_common.c |  8 +--
> >   drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
> >   2 files changed, 88 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> > index fdbde1db5ec5..863d3a8a0956 100644
> > --- a/drivers/virtio/virtio_pci_common.c
> > +++ b/drivers/virtio/virtio_pci_common.c
> > @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
> >   	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
> >   	unsigned long flags;
> >
> > -	spin_lock_irqsave(&vp_dev->lock, flags);
> > -	list_del(&info->node);
> > -	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	if (!vq->reset) {
> > +		spin_lock_irqsave(&vp_dev->lock, flags);
> > +		list_del(&info->node);
> > +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	}
> >
> >   	vp_dev->del_vq(info);
> >   	kfree(info);
> > diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> > index 49a4493732cf..3c67d3607802 100644
> > --- a/drivers/virtio/virtio_pci_modern.c
> > +++ b/drivers/virtio/virtio_pci_modern.c
> > @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
> >   	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
> >   			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
> >   		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
> > +
> > +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
> > +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
> >   }
> >
> >   /* virtio config->finalize_features() implementation */
> > @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
> >   	return 0;
> >   }
> >
> > +static int vp_modern_reset_vq(struct virtqueue *vq)
> > +{
> > +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> > +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> > +	struct virtio_pci_vq_info *info;
> > +	unsigned long flags;
> > +	unsigned int irq;
> > +
> > +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> > +		return -ENOENT;
> > +
> > +	vp_modern_set_queue_reset(mdev, vq->index);
> > +
> > +	info = vp_dev->vqs[vq->index];
> > +
> > +	/* delete vq from irq handler */
> > +	spin_lock_irqsave(&vp_dev->lock, flags);
> > +	list_del(&info->node);
> > +	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +
> > +	INIT_LIST_HEAD(&info->node);
> > +
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
> > +
> > +	/* sync irq callback. */
> > +	if (vp_dev->intx_enabled) {
> > +		irq = vp_dev->pci_dev->irq;
> > +
> > +	} else {
> > +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
> > +			return 0;
> > +
> > +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
> > +	}
> > +
> > +	synchronize_irq(irq);
>
>
> Synchronize_irq() is not sufficient here since it breaks the effort of
> the interrupt hardening which is done by commits:
>
> 080cd7c3ac87 virtio-pci: harden INTX interrupts
> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>
> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
> used for the affinity managed irq but we're discussing a fix.

I need to understand it first.

>
>
> > +
> > +	return 0;
> > +}
> > +
> > +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
> > +{
> > +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> > +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> > +	struct virtio_pci_vq_info *info;
> > +	unsigned long flags, index;
> > +	int err;
> > +
> > +	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
> > +		return -EBUSY;
> > +
> > +	index = vq->index;
> > +	info = vp_dev->vqs[index];
> > +
> > +	/* check queue reset status */
> > +	if (vp_modern_get_queue_reset(mdev, index) != 1)
> > +		return -EBUSY;
> > +
> > +	err = vp_active_vq(vq, info->msix_vector);
> > +	if (err)
> > +		return err;
> > +
> > +	if (vq->callback) {
> > +		spin_lock_irqsave(&vp_dev->lock, flags);
> > +		list_add(&info->node, &vp_dev->virtqueues);
> > +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	} else {
> > +		INIT_LIST_HEAD(&info->node);
> > +	}
> > +
> > +	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
>
>
> Any reason we need to check queue_enable() here?

The purpose of this function is to enable a reset vq, so call queue_enable() to
activate it.

Thanks.

>
> Thanks
>
>
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> > +	return 0;
> > +}
> > +
> >   static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
> >   {
> >   	return vp_modern_config_vector(&vp_dev->mdev, vector);
> > @@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
> >   	.set_vq_affinity = vp_set_vq_affinity,
> >   	.get_vq_affinity = vp_get_vq_affinity,
> >   	.get_shm_region  = vp_get_shm_region,
> > +	.reset_vq	 = vp_modern_reset_vq,
> > +	.enable_reset_vq = vp_modern_enable_reset_vq,
> >   };
> >
> >   static const struct virtio_config_ops virtio_pci_config_ops = {
> > @@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
> >   	.set_vq_affinity = vp_set_vq_affinity,
> >   	.get_vq_affinity = vp_get_vq_affinity,
> >   	.get_shm_region  = vp_get_shm_region,
> > +	.reset_vq	 = vp_modern_reset_vq,
> > +	.enable_reset_vq = vp_modern_enable_reset_vq,
> >   };
> >
> >   /* the PCI probing function */
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-09  9:32       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:32 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements virtio pci support for QUEUE RESET.
> >
> > Performing reset on a queue is divided into these steps:
> >
> >   1. virtio_reset_vq()              - notify the device to reset the queue
> >   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >   4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> >
> > This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
> > pci scenario.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_pci_common.c |  8 +--
> >   drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
> >   2 files changed, 88 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> > index fdbde1db5ec5..863d3a8a0956 100644
> > --- a/drivers/virtio/virtio_pci_common.c
> > +++ b/drivers/virtio/virtio_pci_common.c
> > @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
> >   	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
> >   	unsigned long flags;
> >
> > -	spin_lock_irqsave(&vp_dev->lock, flags);
> > -	list_del(&info->node);
> > -	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	if (!vq->reset) {
> > +		spin_lock_irqsave(&vp_dev->lock, flags);
> > +		list_del(&info->node);
> > +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	}
> >
> >   	vp_dev->del_vq(info);
> >   	kfree(info);
> > diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> > index 49a4493732cf..3c67d3607802 100644
> > --- a/drivers/virtio/virtio_pci_modern.c
> > +++ b/drivers/virtio/virtio_pci_modern.c
> > @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
> >   	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
> >   			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
> >   		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
> > +
> > +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
> > +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
> >   }
> >
> >   /* virtio config->finalize_features() implementation */
> > @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
> >   	return 0;
> >   }
> >
> > +static int vp_modern_reset_vq(struct virtqueue *vq)
> > +{
> > +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> > +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> > +	struct virtio_pci_vq_info *info;
> > +	unsigned long flags;
> > +	unsigned int irq;
> > +
> > +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> > +		return -ENOENT;
> > +
> > +	vp_modern_set_queue_reset(mdev, vq->index);
> > +
> > +	info = vp_dev->vqs[vq->index];
> > +
> > +	/* delete vq from irq handler */
> > +	spin_lock_irqsave(&vp_dev->lock, flags);
> > +	list_del(&info->node);
> > +	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +
> > +	INIT_LIST_HEAD(&info->node);
> > +
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
> > +
> > +	/* sync irq callback. */
> > +	if (vp_dev->intx_enabled) {
> > +		irq = vp_dev->pci_dev->irq;
> > +
> > +	} else {
> > +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
> > +			return 0;
> > +
> > +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
> > +	}
> > +
> > +	synchronize_irq(irq);
>
>
> Synchronize_irq() is not sufficient here since it breaks the effort of
> the interrupt hardening which is done by commits:
>
> 080cd7c3ac87 virtio-pci: harden INTX interrupts
> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>
> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
> used for the affinity managed irq but we're discussing a fix.

I need to understand it first.

>
>
> > +
> > +	return 0;
> > +}
> > +
> > +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
> > +{
> > +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> > +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> > +	struct virtio_pci_vq_info *info;
> > +	unsigned long flags, index;
> > +	int err;
> > +
> > +	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
> > +		return -EBUSY;
> > +
> > +	index = vq->index;
> > +	info = vp_dev->vqs[index];
> > +
> > +	/* check queue reset status */
> > +	if (vp_modern_get_queue_reset(mdev, index) != 1)
> > +		return -EBUSY;
> > +
> > +	err = vp_active_vq(vq, info->msix_vector);
> > +	if (err)
> > +		return err;
> > +
> > +	if (vq->callback) {
> > +		spin_lock_irqsave(&vp_dev->lock, flags);
> > +		list_add(&info->node, &vp_dev->virtqueues);
> > +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	} else {
> > +		INIT_LIST_HEAD(&info->node);
> > +	}
> > +
> > +	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
>
>
> Any reason we need to check queue_enable() here?

The purpose of this function is to enable a reset vq, so call queue_enable() to
activate it.

Thanks.

>
> Thanks
>
>
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> > +	return 0;
> > +}
> > +
> >   static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
> >   {
> >   	return vp_modern_config_vector(&vp_dev->mdev, vector);
> > @@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
> >   	.set_vq_affinity = vp_set_vq_affinity,
> >   	.get_vq_affinity = vp_get_vq_affinity,
> >   	.get_shm_region  = vp_get_shm_region,
> > +	.reset_vq	 = vp_modern_reset_vq,
> > +	.enable_reset_vq = vp_modern_enable_reset_vq,
> >   };
> >
> >   static const struct virtio_config_ops virtio_pci_config_ops = {
> > @@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
> >   	.set_vq_affinity = vp_set_vq_affinity,
> >   	.get_vq_affinity = vp_get_vq_affinity,
> >   	.get_shm_region  = vp_get_shm_region,
> > +	.reset_vq	 = vp_modern_reset_vq,
> > +	.enable_reset_vq = vp_modern_enable_reset_vq,
> >   };
> >
> >   /* the PCI probing function */
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 18/26] virtio: find_vqs() add arg sizes
  2022-03-09  8:59     ` Jason Wang
  (?)
@ 2022-03-09  9:34       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:34 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 16:59:32 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > find_vqs() adds a new parameter sizes to specify the size of each vq
> > vring.
> >
> > 0 means use the maximum size supported by the backend.
> >
> > In the split scenario, the meaning of size is the largest size, because
> > it may be limited by memory, the virtio core will try a smaller size.
> > And the size is power of 2.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   arch/um/drivers/virtio_uml.c             |  2 +-
> >   drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
> >   drivers/remoteproc/remoteproc_virtio.c   |  2 +-
> >   drivers/s390/virtio/virtio_ccw.c         |  2 +-
> >   drivers/virtio/virtio_mmio.c             |  2 +-
> >   drivers/virtio/virtio_pci_common.c       |  2 +-
> >   drivers/virtio/virtio_pci_common.h       |  2 +-
> >   drivers/virtio/virtio_pci_modern.c       |  5 +++--
> >   drivers/virtio/virtio_vdpa.c             |  2 +-
> >   include/linux/virtio_config.h            | 11 +++++++----
> >   10 files changed, 19 insertions(+), 14 deletions(-)
> >
> > diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> > index ba562d68dc04..055b91ccbe8a 100644
> > --- a/arch/um/drivers/virtio_uml.c
> > +++ b/arch/um/drivers/virtio_uml.c
> > @@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
> >   static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   		       const char * const names[], const bool *ctx,
> > -		       struct irq_affinity *desc)
> > +		       struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
> >   	int i, queue_idx = 0, rc;
> > diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
> > index 38800e86ed8a..aea7aa218b22 100644
> > --- a/drivers/platform/mellanox/mlxbf-tmfifo.c
> > +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
> > @@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
> >   					vq_callback_t *callbacks[],
> >   					const char * const names[],
>
>
> Nit: Let's be consistent here, e.g move sizes before ctx (this is what
> next patch did and seems cleaner).

OK.

Thanks.

>
> Thanks
>
>
> >   					const bool *ctx,
> > -					struct irq_affinity *desc)
> > +					struct irq_affinity *desc,
> > +					u32 sizes[])
> >   {
> >   	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
> >   	struct mlxbf_tmfifo_vring *vring;
> > diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> > index 70ab496d0431..3a167bec5b09 100644
> > --- a/drivers/remoteproc/remoteproc_virtio.c
> > +++ b/drivers/remoteproc/remoteproc_virtio.c
> > @@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
> >   				 vq_callback_t *callbacks[],
> >   				 const char * const names[],
> >   				 const bool * ctx,
> > -				 struct irq_affinity *desc)
> > +				 struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	int i, ret, queue_idx = 0;
> >
> > diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
> > index d35e7a3f7067..b74e08c71534 100644
> > --- a/drivers/s390/virtio/virtio_ccw.c
> > +++ b/drivers/s390/virtio/virtio_ccw.c
> > @@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   			       vq_callback_t *callbacks[],
> >   			       const char * const names[],
> >   			       const bool *ctx,
> > -			       struct irq_affinity *desc)
> > +			       struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
> >   	unsigned long *indicatorp = NULL;
> > diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> > index a41abc8051b9..55d575f6ef2d 100644
> > --- a/drivers/virtio/virtio_mmio.c
> > +++ b/drivers/virtio/virtio_mmio.c
> > @@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		       vq_callback_t *callbacks[],
> >   		       const char * const names[],
> >   		       const bool *ctx,
> > -		       struct irq_affinity *desc)
> > +		       struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
> >   	int irq = platform_get_irq(vm_dev->pdev, 0);
> > diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> > index 863d3a8a0956..8e8fa7e5ad80 100644
> > --- a/drivers/virtio/virtio_pci_common.c
> > +++ b/drivers/virtio/virtio_pci_common.c
> > @@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
> >   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   		const char * const names[], const bool *ctx,
> > -		struct irq_affinity *desc)
> > +		struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	int err;
> >
> > diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> > index 23f6c5c678d5..9dbf1d555dff 100644
> > --- a/drivers/virtio/virtio_pci_common.h
> > +++ b/drivers/virtio/virtio_pci_common.h
> > @@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
> >   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   		const char * const names[], const bool *ctx,
> > -		struct irq_affinity *desc);
> > +		struct irq_affinity *desc, u32 sizes[]);
> >   const char *vp_bus_name(struct virtio_device *vdev);
> >
> >   /* Setup the affinity for a virtqueue:
> > diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> > index 3c67d3607802..342795175c29 100644
> > --- a/drivers/virtio/virtio_pci_modern.c
> > +++ b/drivers/virtio/virtio_pci_modern.c
> > @@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   			      struct virtqueue *vqs[],
> >   			      vq_callback_t *callbacks[],
> >   			      const char * const names[], const bool *ctx,
> > -			      struct irq_affinity *desc)
> > +			      struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
> >   	struct virtqueue *vq;
> > -	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
> > +	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
> > +			     sizes);
> >
> >   	if (rc)
> >   		return rc;
> > diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
> > index 7767a7f0119b..ee08d01ee8b1 100644
> > --- a/drivers/virtio/virtio_vdpa.c
> > +++ b/drivers/virtio/virtio_vdpa.c
> > @@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   				vq_callback_t *callbacks[],
> >   				const char * const names[],
> >   				const bool *ctx,
> > -				struct irq_affinity *desc)
> > +				struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
> >   	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index 0b81fbe17c85..5157524d8036 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -57,6 +57,7 @@ struct virtio_shm_region {
> >    *		include a NULL entry for vqs that do not need a callback
> >    *	names: array of virtqueue names (mainly for debugging)
> >    *		include a NULL entry for vqs unused by driver
> > + *	sizes: array of virtqueue sizes
> >    *	Returns 0 on success or error status
> >    * @del_vqs: free virtqueues found by find_vqs().
> >    * @get_features: get the array of feature bits for this device.
> > @@ -98,7 +99,8 @@ struct virtio_config_ops {
> >   	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
> >   			struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   			const char * const names[], const bool *ctx,
> > -			struct irq_affinity *desc);
> > +			struct irq_affinity *desc,
> > +			u32 sizes[]);
> >   	void (*del_vqs)(struct virtio_device *);
> >   	u64 (*get_features)(struct virtio_device *vdev);
> >   	int (*finalize_features)(struct virtio_device *vdev);
> > @@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
> >   	const char *names[] = { n };
> >   	struct virtqueue *vq;
> >   	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
> > -					 NULL);
> > +					 NULL, NULL);
> >   	if (err < 0)
> >   		return ERR_PTR(err);
> >   	return vq;
> > @@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   			const char * const names[],
> >   			struct irq_affinity *desc)
> >   {
> > -	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
> > +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
> > +				      desc, NULL);
> >   }
> >
> >   static inline
> > @@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
> >   			struct irq_affinity *desc)
> >   {
> >   	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> > -				      desc);
> > +				      desc, NULL);
> >   }
> >
> >   /**
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 18/26] virtio: find_vqs() add arg sizes
@ 2022-03-09  9:34       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:34 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 16:59:32 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > find_vqs() adds a new parameter sizes to specify the size of each vq
> > vring.
> >
> > 0 means use the maximum size supported by the backend.
> >
> > In the split scenario, the meaning of size is the largest size, because
> > it may be limited by memory, the virtio core will try a smaller size.
> > And the size is power of 2.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   arch/um/drivers/virtio_uml.c             |  2 +-
> >   drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
> >   drivers/remoteproc/remoteproc_virtio.c   |  2 +-
> >   drivers/s390/virtio/virtio_ccw.c         |  2 +-
> >   drivers/virtio/virtio_mmio.c             |  2 +-
> >   drivers/virtio/virtio_pci_common.c       |  2 +-
> >   drivers/virtio/virtio_pci_common.h       |  2 +-
> >   drivers/virtio/virtio_pci_modern.c       |  5 +++--
> >   drivers/virtio/virtio_vdpa.c             |  2 +-
> >   include/linux/virtio_config.h            | 11 +++++++----
> >   10 files changed, 19 insertions(+), 14 deletions(-)
> >
> > diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> > index ba562d68dc04..055b91ccbe8a 100644
> > --- a/arch/um/drivers/virtio_uml.c
> > +++ b/arch/um/drivers/virtio_uml.c
> > @@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
> >   static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   		       const char * const names[], const bool *ctx,
> > -		       struct irq_affinity *desc)
> > +		       struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
> >   	int i, queue_idx = 0, rc;
> > diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
> > index 38800e86ed8a..aea7aa218b22 100644
> > --- a/drivers/platform/mellanox/mlxbf-tmfifo.c
> > +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
> > @@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
> >   					vq_callback_t *callbacks[],
> >   					const char * const names[],
>
>
> Nit: Let's be consistent here, e.g move sizes before ctx (this is what
> next patch did and seems cleaner).

OK.

Thanks.

>
> Thanks
>
>
> >   					const bool *ctx,
> > -					struct irq_affinity *desc)
> > +					struct irq_affinity *desc,
> > +					u32 sizes[])
> >   {
> >   	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
> >   	struct mlxbf_tmfifo_vring *vring;
> > diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> > index 70ab496d0431..3a167bec5b09 100644
> > --- a/drivers/remoteproc/remoteproc_virtio.c
> > +++ b/drivers/remoteproc/remoteproc_virtio.c
> > @@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
> >   				 vq_callback_t *callbacks[],
> >   				 const char * const names[],
> >   				 const bool * ctx,
> > -				 struct irq_affinity *desc)
> > +				 struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	int i, ret, queue_idx = 0;
> >
> > diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
> > index d35e7a3f7067..b74e08c71534 100644
> > --- a/drivers/s390/virtio/virtio_ccw.c
> > +++ b/drivers/s390/virtio/virtio_ccw.c
> > @@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   			       vq_callback_t *callbacks[],
> >   			       const char * const names[],
> >   			       const bool *ctx,
> > -			       struct irq_affinity *desc)
> > +			       struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
> >   	unsigned long *indicatorp = NULL;
> > diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> > index a41abc8051b9..55d575f6ef2d 100644
> > --- a/drivers/virtio/virtio_mmio.c
> > +++ b/drivers/virtio/virtio_mmio.c
> > @@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		       vq_callback_t *callbacks[],
> >   		       const char * const names[],
> >   		       const bool *ctx,
> > -		       struct irq_affinity *desc)
> > +		       struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
> >   	int irq = platform_get_irq(vm_dev->pdev, 0);
> > diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> > index 863d3a8a0956..8e8fa7e5ad80 100644
> > --- a/drivers/virtio/virtio_pci_common.c
> > +++ b/drivers/virtio/virtio_pci_common.c
> > @@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
> >   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   		const char * const names[], const bool *ctx,
> > -		struct irq_affinity *desc)
> > +		struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	int err;
> >
> > diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> > index 23f6c5c678d5..9dbf1d555dff 100644
> > --- a/drivers/virtio/virtio_pci_common.h
> > +++ b/drivers/virtio/virtio_pci_common.h
> > @@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
> >   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   		const char * const names[], const bool *ctx,
> > -		struct irq_affinity *desc);
> > +		struct irq_affinity *desc, u32 sizes[]);
> >   const char *vp_bus_name(struct virtio_device *vdev);
> >
> >   /* Setup the affinity for a virtqueue:
> > diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> > index 3c67d3607802..342795175c29 100644
> > --- a/drivers/virtio/virtio_pci_modern.c
> > +++ b/drivers/virtio/virtio_pci_modern.c
> > @@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   			      struct virtqueue *vqs[],
> >   			      vq_callback_t *callbacks[],
> >   			      const char * const names[], const bool *ctx,
> > -			      struct irq_affinity *desc)
> > +			      struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
> >   	struct virtqueue *vq;
> > -	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
> > +	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
> > +			     sizes);
> >
> >   	if (rc)
> >   		return rc;
> > diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
> > index 7767a7f0119b..ee08d01ee8b1 100644
> > --- a/drivers/virtio/virtio_vdpa.c
> > +++ b/drivers/virtio/virtio_vdpa.c
> > @@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   				vq_callback_t *callbacks[],
> >   				const char * const names[],
> >   				const bool *ctx,
> > -				struct irq_affinity *desc)
> > +				struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
> >   	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index 0b81fbe17c85..5157524d8036 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -57,6 +57,7 @@ struct virtio_shm_region {
> >    *		include a NULL entry for vqs that do not need a callback
> >    *	names: array of virtqueue names (mainly for debugging)
> >    *		include a NULL entry for vqs unused by driver
> > + *	sizes: array of virtqueue sizes
> >    *	Returns 0 on success or error status
> >    * @del_vqs: free virtqueues found by find_vqs().
> >    * @get_features: get the array of feature bits for this device.
> > @@ -98,7 +99,8 @@ struct virtio_config_ops {
> >   	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
> >   			struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   			const char * const names[], const bool *ctx,
> > -			struct irq_affinity *desc);
> > +			struct irq_affinity *desc,
> > +			u32 sizes[]);
> >   	void (*del_vqs)(struct virtio_device *);
> >   	u64 (*get_features)(struct virtio_device *vdev);
> >   	int (*finalize_features)(struct virtio_device *vdev);
> > @@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
> >   	const char *names[] = { n };
> >   	struct virtqueue *vq;
> >   	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
> > -					 NULL);
> > +					 NULL, NULL);
> >   	if (err < 0)
> >   		return ERR_PTR(err);
> >   	return vq;
> > @@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   			const char * const names[],
> >   			struct irq_affinity *desc)
> >   {
> > -	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
> > +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
> > +				      desc, NULL);
> >   }
> >
> >   static inline
> > @@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
> >   			struct irq_affinity *desc)
> >   {
> >   	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> > -				      desc);
> > +				      desc, NULL);
> >   }
> >
> >   /**
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 18/26] virtio: find_vqs() add arg sizes
@ 2022-03-09  9:34       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:34 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 16:59:32 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > find_vqs() adds a new parameter sizes to specify the size of each vq
> > vring.
> >
> > 0 means use the maximum size supported by the backend.
> >
> > In the split scenario, the meaning of size is the largest size, because
> > it may be limited by memory, the virtio core will try a smaller size.
> > And the size is power of 2.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   arch/um/drivers/virtio_uml.c             |  2 +-
> >   drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
> >   drivers/remoteproc/remoteproc_virtio.c   |  2 +-
> >   drivers/s390/virtio/virtio_ccw.c         |  2 +-
> >   drivers/virtio/virtio_mmio.c             |  2 +-
> >   drivers/virtio/virtio_pci_common.c       |  2 +-
> >   drivers/virtio/virtio_pci_common.h       |  2 +-
> >   drivers/virtio/virtio_pci_modern.c       |  5 +++--
> >   drivers/virtio/virtio_vdpa.c             |  2 +-
> >   include/linux/virtio_config.h            | 11 +++++++----
> >   10 files changed, 19 insertions(+), 14 deletions(-)
> >
> > diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> > index ba562d68dc04..055b91ccbe8a 100644
> > --- a/arch/um/drivers/virtio_uml.c
> > +++ b/arch/um/drivers/virtio_uml.c
> > @@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
> >   static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   		       const char * const names[], const bool *ctx,
> > -		       struct irq_affinity *desc)
> > +		       struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
> >   	int i, queue_idx = 0, rc;
> > diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
> > index 38800e86ed8a..aea7aa218b22 100644
> > --- a/drivers/platform/mellanox/mlxbf-tmfifo.c
> > +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
> > @@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
> >   					vq_callback_t *callbacks[],
> >   					const char * const names[],
>
>
> Nit: Let's be consistent here, e.g move sizes before ctx (this is what
> next patch did and seems cleaner).

OK.

Thanks.

>
> Thanks
>
>
> >   					const bool *ctx,
> > -					struct irq_affinity *desc)
> > +					struct irq_affinity *desc,
> > +					u32 sizes[])
> >   {
> >   	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
> >   	struct mlxbf_tmfifo_vring *vring;
> > diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> > index 70ab496d0431..3a167bec5b09 100644
> > --- a/drivers/remoteproc/remoteproc_virtio.c
> > +++ b/drivers/remoteproc/remoteproc_virtio.c
> > @@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
> >   				 vq_callback_t *callbacks[],
> >   				 const char * const names[],
> >   				 const bool * ctx,
> > -				 struct irq_affinity *desc)
> > +				 struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	int i, ret, queue_idx = 0;
> >
> > diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
> > index d35e7a3f7067..b74e08c71534 100644
> > --- a/drivers/s390/virtio/virtio_ccw.c
> > +++ b/drivers/s390/virtio/virtio_ccw.c
> > @@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   			       vq_callback_t *callbacks[],
> >   			       const char * const names[],
> >   			       const bool *ctx,
> > -			       struct irq_affinity *desc)
> > +			       struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
> >   	unsigned long *indicatorp = NULL;
> > diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> > index a41abc8051b9..55d575f6ef2d 100644
> > --- a/drivers/virtio/virtio_mmio.c
> > +++ b/drivers/virtio/virtio_mmio.c
> > @@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		       vq_callback_t *callbacks[],
> >   		       const char * const names[],
> >   		       const bool *ctx,
> > -		       struct irq_affinity *desc)
> > +		       struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
> >   	int irq = platform_get_irq(vm_dev->pdev, 0);
> > diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> > index 863d3a8a0956..8e8fa7e5ad80 100644
> > --- a/drivers/virtio/virtio_pci_common.c
> > +++ b/drivers/virtio/virtio_pci_common.c
> > @@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
> >   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   		const char * const names[], const bool *ctx,
> > -		struct irq_affinity *desc)
> > +		struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	int err;
> >
> > diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> > index 23f6c5c678d5..9dbf1d555dff 100644
> > --- a/drivers/virtio/virtio_pci_common.h
> > +++ b/drivers/virtio/virtio_pci_common.h
> > @@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
> >   int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   		struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   		const char * const names[], const bool *ctx,
> > -		struct irq_affinity *desc);
> > +		struct irq_affinity *desc, u32 sizes[]);
> >   const char *vp_bus_name(struct virtio_device *vdev);
> >
> >   /* Setup the affinity for a virtqueue:
> > diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> > index 3c67d3607802..342795175c29 100644
> > --- a/drivers/virtio/virtio_pci_modern.c
> > +++ b/drivers/virtio/virtio_pci_modern.c
> > @@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   			      struct virtqueue *vqs[],
> >   			      vq_callback_t *callbacks[],
> >   			      const char * const names[], const bool *ctx,
> > -			      struct irq_affinity *desc)
> > +			      struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
> >   	struct virtqueue *vq;
> > -	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
> > +	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
> > +			     sizes);
> >
> >   	if (rc)
> >   		return rc;
> > diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
> > index 7767a7f0119b..ee08d01ee8b1 100644
> > --- a/drivers/virtio/virtio_vdpa.c
> > +++ b/drivers/virtio/virtio_vdpa.c
> > @@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   				vq_callback_t *callbacks[],
> >   				const char * const names[],
> >   				const bool *ctx,
> > -				struct irq_affinity *desc)
> > +				struct irq_affinity *desc, u32 sizes[])
> >   {
> >   	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
> >   	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index 0b81fbe17c85..5157524d8036 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -57,6 +57,7 @@ struct virtio_shm_region {
> >    *		include a NULL entry for vqs that do not need a callback
> >    *	names: array of virtqueue names (mainly for debugging)
> >    *		include a NULL entry for vqs unused by driver
> > + *	sizes: array of virtqueue sizes
> >    *	Returns 0 on success or error status
> >    * @del_vqs: free virtqueues found by find_vqs().
> >    * @get_features: get the array of feature bits for this device.
> > @@ -98,7 +99,8 @@ struct virtio_config_ops {
> >   	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
> >   			struct virtqueue *vqs[], vq_callback_t *callbacks[],
> >   			const char * const names[], const bool *ctx,
> > -			struct irq_affinity *desc);
> > +			struct irq_affinity *desc,
> > +			u32 sizes[]);
> >   	void (*del_vqs)(struct virtio_device *);
> >   	u64 (*get_features)(struct virtio_device *vdev);
> >   	int (*finalize_features)(struct virtio_device *vdev);
> > @@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
> >   	const char *names[] = { n };
> >   	struct virtqueue *vq;
> >   	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
> > -					 NULL);
> > +					 NULL, NULL);
> >   	if (err < 0)
> >   		return ERR_PTR(err);
> >   	return vq;
> > @@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
> >   			const char * const names[],
> >   			struct irq_affinity *desc)
> >   {
> > -	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
> > +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
> > +				      desc, NULL);
> >   }
> >
> >   static inline
> > @@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
> >   			struct irq_affinity *desc)
> >   {
> >   	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> > -				      desc);
> > +				      desc, NULL);
> >   }
> >
> >   /**
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 25/26] virtio_net: set the default max ring size by find_vqs()
  2022-03-09  9:28     ` Jason Wang
  (?)
@ 2022-03-09  9:35       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:35 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 17:28:21 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Use virtio_find_vqs_ctx_size() to specify the maximum ring size of tx,
> > rx at the same time.
> >
> >                           | rx/tx ring size
> > -------------------------------------------
> > speed == UNKNOWN or < 10G| 1024
> > speed < 40G              | 4096
> > speed >= 40G             | 8192
> >
> > Call virtnet_update_settings() once before calling init_vqs() to update
> > speed.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 42 ++++++++++++++++++++++++++++++++++++----
> >   1 file changed, 38 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index ffff323dcef0..f1bdc6ce21c3 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -2977,6 +2977,29 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
> >   		   (unsigned int)GOOD_PACKET_LEN);
> >   }
> >
> > +static void virtnet_config_sizes(struct virtnet_info *vi, u32 *sizes)
> > +{
> > +	u32 i, rx_size, tx_size;
> > +
> > +	if (vi->speed == SPEED_UNKNOWN || vi->speed < SPEED_10000) {
> > +		rx_size = 1024;
> > +		tx_size = 1024;
> > +
> > +	} else if (vi->speed < SPEED_40000) {
> > +		rx_size = 1024 * 4;
> > +		tx_size = 1024 * 4;
> > +
> > +	} else {
> > +		rx_size = 1024 * 8;
> > +		tx_size = 1024 * 8;
> > +	}
> > +
> > +	for (i = 0; i < vi->max_queue_pairs; i++) {
> > +		sizes[rxq2vq(i)] = rx_size;
> > +		sizes[txq2vq(i)] = tx_size;
> > +	}
> > +}
> > +
> >   static int virtnet_find_vqs(struct virtnet_info *vi)
> >   {
> >   	vq_callback_t **callbacks;
> > @@ -2984,6 +3007,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >   	int ret = -ENOMEM;
> >   	int i, total_vqs;
> >   	const char **names;
> > +	u32 *sizes;
> >   	bool *ctx;
> >
> >   	/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
> > @@ -3011,10 +3035,15 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >   		ctx = NULL;
> >   	}
> >
> > +	sizes = kmalloc_array(total_vqs, sizeof(*sizes), GFP_KERNEL);
> > +	if (!sizes)
> > +		goto err_sizes;
> > +
> >   	/* Parameters for control virtqueue, if any */
> >   	if (vi->has_cvq) {
> >   		callbacks[total_vqs - 1] = NULL;
> >   		names[total_vqs - 1] = "control";
> > +		sizes[total_vqs - 1] = 0;
>
>
> Nit: Do we need a sane value for the control vq? (e.g 64)


I think it can.

Thanks.

>
> Thanks
>
>
> >   	}
> >
> >   	/* Allocate/initialize parameters for send/receive virtqueues */
> > @@ -3029,8 +3058,10 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >   			ctx[rxq2vq(i)] = true;
> >   	}
> >
> > -	ret = virtio_find_vqs_ctx(vi->vdev, total_vqs, vqs, callbacks,
> > -				  names, ctx, NULL);
> > +	virtnet_config_sizes(vi, sizes);
> > +
> > +	ret = virtio_find_vqs_ctx_size(vi->vdev, total_vqs, vqs, callbacks,
> > +				       names, ctx, NULL, sizes);
> >   	if (ret)
> >   		goto err_find;
> >
> > @@ -3050,6 +3081,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >
> >
> >   err_find:
> > +	kfree(sizes);
> > +err_sizes:
> >   	kfree(ctx);
> >   err_ctx:
> >   	kfree(names);
> > @@ -3368,6 +3401,9 @@ static int virtnet_probe(struct virtio_device *vdev)
> >   		vi->curr_queue_pairs = num_online_cpus();
> >   	vi->max_queue_pairs = max_queue_pairs;
> >
> > +	virtnet_init_settings(dev);
> > +	virtnet_update_settings(vi);
> > +
> >   	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
> >   	err = init_vqs(vi);
> >   	if (err)
> > @@ -3380,8 +3416,6 @@ static int virtnet_probe(struct virtio_device *vdev)
> >   	netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs);
> >   	netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs);
> >
> > -	virtnet_init_settings(dev);
> > -
> >   	if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
> >   		vi->failover = net_failover_create(vi->dev);
> >   		if (IS_ERR(vi->failover)) {
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 25/26] virtio_net: set the default max ring size by find_vqs()
@ 2022-03-09  9:35       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:35 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 17:28:21 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Use virtio_find_vqs_ctx_size() to specify the maximum ring size of tx,
> > rx at the same time.
> >
> >                           | rx/tx ring size
> > -------------------------------------------
> > speed == UNKNOWN or < 10G| 1024
> > speed < 40G              | 4096
> > speed >= 40G             | 8192
> >
> > Call virtnet_update_settings() once before calling init_vqs() to update
> > speed.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 42 ++++++++++++++++++++++++++++++++++++----
> >   1 file changed, 38 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index ffff323dcef0..f1bdc6ce21c3 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -2977,6 +2977,29 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
> >   		   (unsigned int)GOOD_PACKET_LEN);
> >   }
> >
> > +static void virtnet_config_sizes(struct virtnet_info *vi, u32 *sizes)
> > +{
> > +	u32 i, rx_size, tx_size;
> > +
> > +	if (vi->speed == SPEED_UNKNOWN || vi->speed < SPEED_10000) {
> > +		rx_size = 1024;
> > +		tx_size = 1024;
> > +
> > +	} else if (vi->speed < SPEED_40000) {
> > +		rx_size = 1024 * 4;
> > +		tx_size = 1024 * 4;
> > +
> > +	} else {
> > +		rx_size = 1024 * 8;
> > +		tx_size = 1024 * 8;
> > +	}
> > +
> > +	for (i = 0; i < vi->max_queue_pairs; i++) {
> > +		sizes[rxq2vq(i)] = rx_size;
> > +		sizes[txq2vq(i)] = tx_size;
> > +	}
> > +}
> > +
> >   static int virtnet_find_vqs(struct virtnet_info *vi)
> >   {
> >   	vq_callback_t **callbacks;
> > @@ -2984,6 +3007,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >   	int ret = -ENOMEM;
> >   	int i, total_vqs;
> >   	const char **names;
> > +	u32 *sizes;
> >   	bool *ctx;
> >
> >   	/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
> > @@ -3011,10 +3035,15 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >   		ctx = NULL;
> >   	}
> >
> > +	sizes = kmalloc_array(total_vqs, sizeof(*sizes), GFP_KERNEL);
> > +	if (!sizes)
> > +		goto err_sizes;
> > +
> >   	/* Parameters for control virtqueue, if any */
> >   	if (vi->has_cvq) {
> >   		callbacks[total_vqs - 1] = NULL;
> >   		names[total_vqs - 1] = "control";
> > +		sizes[total_vqs - 1] = 0;
>
>
> Nit: Do we need a sane value for the control vq? (e.g 64)


I think it can.

Thanks.

>
> Thanks
>
>
> >   	}
> >
> >   	/* Allocate/initialize parameters for send/receive virtqueues */
> > @@ -3029,8 +3058,10 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >   			ctx[rxq2vq(i)] = true;
> >   	}
> >
> > -	ret = virtio_find_vqs_ctx(vi->vdev, total_vqs, vqs, callbacks,
> > -				  names, ctx, NULL);
> > +	virtnet_config_sizes(vi, sizes);
> > +
> > +	ret = virtio_find_vqs_ctx_size(vi->vdev, total_vqs, vqs, callbacks,
> > +				       names, ctx, NULL, sizes);
> >   	if (ret)
> >   		goto err_find;
> >
> > @@ -3050,6 +3081,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >
> >
> >   err_find:
> > +	kfree(sizes);
> > +err_sizes:
> >   	kfree(ctx);
> >   err_ctx:
> >   	kfree(names);
> > @@ -3368,6 +3401,9 @@ static int virtnet_probe(struct virtio_device *vdev)
> >   		vi->curr_queue_pairs = num_online_cpus();
> >   	vi->max_queue_pairs = max_queue_pairs;
> >
> > +	virtnet_init_settings(dev);
> > +	virtnet_update_settings(vi);
> > +
> >   	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
> >   	err = init_vqs(vi);
> >   	if (err)
> > @@ -3380,8 +3416,6 @@ static int virtnet_probe(struct virtio_device *vdev)
> >   	netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs);
> >   	netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs);
> >
> > -	virtnet_init_settings(dev);
> > -
> >   	if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
> >   		vi->failover = net_failover_create(vi->dev);
> >   		if (IS_ERR(vi->failover)) {
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 25/26] virtio_net: set the default max ring size by find_vqs()
@ 2022-03-09  9:35       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:35 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 17:28:21 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Use virtio_find_vqs_ctx_size() to specify the maximum ring size of tx,
> > rx at the same time.
> >
> >                           | rx/tx ring size
> > -------------------------------------------
> > speed == UNKNOWN or < 10G| 1024
> > speed < 40G              | 4096
> > speed >= 40G             | 8192
> >
> > Call virtnet_update_settings() once before calling init_vqs() to update
> > speed.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 42 ++++++++++++++++++++++++++++++++++++----
> >   1 file changed, 38 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index ffff323dcef0..f1bdc6ce21c3 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -2977,6 +2977,29 @@ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqu
> >   		   (unsigned int)GOOD_PACKET_LEN);
> >   }
> >
> > +static void virtnet_config_sizes(struct virtnet_info *vi, u32 *sizes)
> > +{
> > +	u32 i, rx_size, tx_size;
> > +
> > +	if (vi->speed == SPEED_UNKNOWN || vi->speed < SPEED_10000) {
> > +		rx_size = 1024;
> > +		tx_size = 1024;
> > +
> > +	} else if (vi->speed < SPEED_40000) {
> > +		rx_size = 1024 * 4;
> > +		tx_size = 1024 * 4;
> > +
> > +	} else {
> > +		rx_size = 1024 * 8;
> > +		tx_size = 1024 * 8;
> > +	}
> > +
> > +	for (i = 0; i < vi->max_queue_pairs; i++) {
> > +		sizes[rxq2vq(i)] = rx_size;
> > +		sizes[txq2vq(i)] = tx_size;
> > +	}
> > +}
> > +
> >   static int virtnet_find_vqs(struct virtnet_info *vi)
> >   {
> >   	vq_callback_t **callbacks;
> > @@ -2984,6 +3007,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >   	int ret = -ENOMEM;
> >   	int i, total_vqs;
> >   	const char **names;
> > +	u32 *sizes;
> >   	bool *ctx;
> >
> >   	/* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
> > @@ -3011,10 +3035,15 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >   		ctx = NULL;
> >   	}
> >
> > +	sizes = kmalloc_array(total_vqs, sizeof(*sizes), GFP_KERNEL);
> > +	if (!sizes)
> > +		goto err_sizes;
> > +
> >   	/* Parameters for control virtqueue, if any */
> >   	if (vi->has_cvq) {
> >   		callbacks[total_vqs - 1] = NULL;
> >   		names[total_vqs - 1] = "control";
> > +		sizes[total_vqs - 1] = 0;
>
>
> Nit: Do we need a sane value for the control vq? (e.g 64)


I think it can.

Thanks.

>
> Thanks
>
>
> >   	}
> >
> >   	/* Allocate/initialize parameters for send/receive virtqueues */
> > @@ -3029,8 +3058,10 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >   			ctx[rxq2vq(i)] = true;
> >   	}
> >
> > -	ret = virtio_find_vqs_ctx(vi->vdev, total_vqs, vqs, callbacks,
> > -				  names, ctx, NULL);
> > +	virtnet_config_sizes(vi, sizes);
> > +
> > +	ret = virtio_find_vqs_ctx_size(vi->vdev, total_vqs, vqs, callbacks,
> > +				       names, ctx, NULL, sizes);
> >   	if (ret)
> >   		goto err_find;
> >
> > @@ -3050,6 +3081,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
> >
> >
> >   err_find:
> > +	kfree(sizes);
> > +err_sizes:
> >   	kfree(ctx);
> >   err_ctx:
> >   	kfree(names);
> > @@ -3368,6 +3401,9 @@ static int virtnet_probe(struct virtio_device *vdev)
> >   		vi->curr_queue_pairs = num_online_cpus();
> >   	vi->max_queue_pairs = max_queue_pairs;
> >
> > +	virtnet_init_settings(dev);
> > +	virtnet_update_settings(vi);
> > +
> >   	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
> >   	err = init_vqs(vi);
> >   	if (err)
> > @@ -3380,8 +3416,6 @@ static int virtnet_probe(struct virtio_device *vdev)
> >   	netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs);
> >   	netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs);
> >
> > -	virtnet_init_settings(dev);
> > -
> >   	if (virtio_has_feature(vdev, VIRTIO_NET_F_STANDBY)) {
> >   		vi->failover = net_failover_create(vi->dev);
> >   		if (IS_ERR(vi->failover)) {
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 26/26] virtio_net: support set_ringparam
  2022-03-09  9:29     ` Jason Wang
  (?)
@ 2022-03-09  9:48       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:48 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 17:29:28 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Support set_ringparam based on virtio queue reset.
> >
> > The rx,tx_pending required to be passed must be power of 2.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 47 ++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 47 insertions(+)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index f1bdc6ce21c3..1fa2d632a994 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -2290,6 +2290,52 @@ static void virtnet_get_ringparam(struct net_device *dev,
> >   	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
> >   }
> >
> > +static int virtnet_set_ringparam(struct net_device *dev,
> > +				 struct ethtool_ringparam *ring,
> > +				 struct kernel_ethtool_ringparam *kernel_ring,
> > +				 struct netlink_ext_ack *extack)
> > +{
> > +	struct virtnet_info *vi = netdev_priv(dev);
> > +	u32 rx_pending, tx_pending;
> > +	struct receive_queue *rq;
> > +	struct send_queue *sq;
> > +	int i, err;
> > +
> > +	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
> > +		return -EINVAL;
>
>
> Any chance that we may hit this EINVAL?

This is definitely not the case at present.

I think this can be kept, this makes sense.

I can remove it in the next version if you think it should be removed.

Thanks.

>
> Thanks
>
>
> > +
> > +	rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
> > +	tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
> > +
> > +	if (ring->rx_pending == rx_pending &&
> > +	    ring->tx_pending == tx_pending)
> > +		return 0;
> > +
> > +	if (ring->rx_pending > virtqueue_get_vring_max_size(vi->rq[0].vq))
> > +		return -EINVAL;
> > +
> > +	if (ring->tx_pending > virtqueue_get_vring_max_size(vi->sq[0].vq))
> > +		return -EINVAL;
> > +
> > +	for (i = 0; i < vi->max_queue_pairs; i++) {
> > +		rq = vi->rq + i;
> > +		sq = vi->sq + i;
> > +
> > +		if (ring->tx_pending != tx_pending) {
> > +			err = virtnet_tx_vq_reset(vi, sq, ring->tx_pending);
> > +			if (err)
> > +				return err;
> > +		}
> > +
> > +		if (ring->rx_pending != rx_pending) {
> > +			err = virtnet_rx_vq_reset(vi, rq, ring->rx_pending);
> > +			if (err)
> > +				return err;
> > +		}
> > +	}
> > +
> > +	return 0;
> > +}
> >
> >   static void virtnet_get_drvinfo(struct net_device *dev,
> >   				struct ethtool_drvinfo *info)
> > @@ -2523,6 +2569,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
> >   	.get_drvinfo = virtnet_get_drvinfo,
> >   	.get_link = ethtool_op_get_link,
> >   	.get_ringparam = virtnet_get_ringparam,
> > +	.set_ringparam = virtnet_set_ringparam,
> >   	.get_strings = virtnet_get_strings,
> >   	.get_sset_count = virtnet_get_sset_count,
> >   	.get_ethtool_stats = virtnet_get_ethtool_stats,
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 26/26] virtio_net: support set_ringparam
@ 2022-03-09  9:48       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:48 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 17:29:28 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Support set_ringparam based on virtio queue reset.
> >
> > The rx,tx_pending required to be passed must be power of 2.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 47 ++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 47 insertions(+)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index f1bdc6ce21c3..1fa2d632a994 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -2290,6 +2290,52 @@ static void virtnet_get_ringparam(struct net_device *dev,
> >   	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
> >   }
> >
> > +static int virtnet_set_ringparam(struct net_device *dev,
> > +				 struct ethtool_ringparam *ring,
> > +				 struct kernel_ethtool_ringparam *kernel_ring,
> > +				 struct netlink_ext_ack *extack)
> > +{
> > +	struct virtnet_info *vi = netdev_priv(dev);
> > +	u32 rx_pending, tx_pending;
> > +	struct receive_queue *rq;
> > +	struct send_queue *sq;
> > +	int i, err;
> > +
> > +	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
> > +		return -EINVAL;
>
>
> Any chance that we may hit this EINVAL?

This is definitely not the case at present.

I think this can be kept, this makes sense.

I can remove it in the next version if you think it should be removed.

Thanks.

>
> Thanks
>
>
> > +
> > +	rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
> > +	tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
> > +
> > +	if (ring->rx_pending == rx_pending &&
> > +	    ring->tx_pending == tx_pending)
> > +		return 0;
> > +
> > +	if (ring->rx_pending > virtqueue_get_vring_max_size(vi->rq[0].vq))
> > +		return -EINVAL;
> > +
> > +	if (ring->tx_pending > virtqueue_get_vring_max_size(vi->sq[0].vq))
> > +		return -EINVAL;
> > +
> > +	for (i = 0; i < vi->max_queue_pairs; i++) {
> > +		rq = vi->rq + i;
> > +		sq = vi->sq + i;
> > +
> > +		if (ring->tx_pending != tx_pending) {
> > +			err = virtnet_tx_vq_reset(vi, sq, ring->tx_pending);
> > +			if (err)
> > +				return err;
> > +		}
> > +
> > +		if (ring->rx_pending != rx_pending) {
> > +			err = virtnet_rx_vq_reset(vi, rq, ring->rx_pending);
> > +			if (err)
> > +				return err;
> > +		}
> > +	}
> > +
> > +	return 0;
> > +}
> >
> >   static void virtnet_get_drvinfo(struct net_device *dev,
> >   				struct ethtool_drvinfo *info)
> > @@ -2523,6 +2569,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
> >   	.get_drvinfo = virtnet_get_drvinfo,
> >   	.get_link = ethtool_op_get_link,
> >   	.get_ringparam = virtnet_get_ringparam,
> > +	.set_ringparam = virtnet_set_ringparam,
> >   	.get_strings = virtnet_get_strings,
> >   	.get_sset_count = virtnet_get_sset_count,
> >   	.get_ethtool_stats = virtnet_get_ethtool_stats,
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 26/26] virtio_net: support set_ringparam
@ 2022-03-09  9:48       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:48 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 17:29:28 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Support set_ringparam based on virtio queue reset.
> >
> > The rx,tx_pending required to be passed must be power of 2.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 47 ++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 47 insertions(+)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index f1bdc6ce21c3..1fa2d632a994 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -2290,6 +2290,52 @@ static void virtnet_get_ringparam(struct net_device *dev,
> >   	ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
> >   }
> >
> > +static int virtnet_set_ringparam(struct net_device *dev,
> > +				 struct ethtool_ringparam *ring,
> > +				 struct kernel_ethtool_ringparam *kernel_ring,
> > +				 struct netlink_ext_ack *extack)
> > +{
> > +	struct virtnet_info *vi = netdev_priv(dev);
> > +	u32 rx_pending, tx_pending;
> > +	struct receive_queue *rq;
> > +	struct send_queue *sq;
> > +	int i, err;
> > +
> > +	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
> > +		return -EINVAL;
>
>
> Any chance that we may hit this EINVAL?

This is definitely not the case at present.

I think this can be kept, this makes sense.

I can remove it in the next version if you think it should be removed.

Thanks.

>
> Thanks
>
>
> > +
> > +	rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
> > +	tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
> > +
> > +	if (ring->rx_pending == rx_pending &&
> > +	    ring->tx_pending == tx_pending)
> > +		return 0;
> > +
> > +	if (ring->rx_pending > virtqueue_get_vring_max_size(vi->rq[0].vq))
> > +		return -EINVAL;
> > +
> > +	if (ring->tx_pending > virtqueue_get_vring_max_size(vi->sq[0].vq))
> > +		return -EINVAL;
> > +
> > +	for (i = 0; i < vi->max_queue_pairs; i++) {
> > +		rq = vi->rq + i;
> > +		sq = vi->sq + i;
> > +
> > +		if (ring->tx_pending != tx_pending) {
> > +			err = virtnet_tx_vq_reset(vi, sq, ring->tx_pending);
> > +			if (err)
> > +				return err;
> > +		}
> > +
> > +		if (ring->rx_pending != rx_pending) {
> > +			err = virtnet_rx_vq_reset(vi, rq, ring->rx_pending);
> > +			if (err)
> > +				return err;
> > +		}
> > +	}
> > +
> > +	return 0;
> > +}
> >
> >   static void virtnet_get_drvinfo(struct net_device *dev,
> >   				struct ethtool_drvinfo *info)
> > @@ -2523,6 +2569,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = {
> >   	.get_drvinfo = virtnet_get_drvinfo,
> >   	.get_link = ethtool_op_get_link,
> >   	.get_ringparam = virtnet_get_ringparam,
> > +	.set_ringparam = virtnet_set_ringparam,
> >   	.get_strings = virtnet_get_strings,
> >   	.get_sset_count = virtnet_get_sset_count,
> >   	.get_ethtool_stats = virtnet_get_ethtool_stats,
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 21/26] virtio: add helper virtio_find_vqs_ctx_size()
  2022-03-09  9:04     ` Jason Wang
  (?)
@ 2022-03-09  9:58       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:58 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 17:04:12 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Introduce helper virtio_find_vqs_ctx_size() to call find_vqs and specify
> > the maximum size of each vq ring.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   include/linux/virtio_config.h | 12 ++++++++++++
> >   1 file changed, 12 insertions(+)
> >
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index 5157524d8036..921d8610db0c 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -233,6 +233,18 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
> >   				      desc, NULL);
> >   }
> >
> > +static inline
> > +int virtio_find_vqs_ctx_size(struct virtio_device *vdev, u32 nvqs,
> > +				 struct virtqueue *vqs[],
> > +				 vq_callback_t *callbacks[],
> > +				 const char * const names[],
> > +				 const bool *ctx, struct irq_affinity *desc,
> > +				 u32 sizes[])
> > +{
> > +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> > +				      desc, sizes);
> > +}
>
>
> Do we need to convert all the open coded direct call to find_vqs() other
> than net?


Do you mean calling find_vqs without a helper? The kernel doesn't do that
anymore.

Thanks.


>
> Thanks
>
>
> > +
> >   /**
> >    * virtio_reset_vq - reset a queue individually
> >    * @vq: the virtqueue
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 21/26] virtio: add helper virtio_find_vqs_ctx_size()
@ 2022-03-09  9:58       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:58 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 17:04:12 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Introduce helper virtio_find_vqs_ctx_size() to call find_vqs and specify
> > the maximum size of each vq ring.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   include/linux/virtio_config.h | 12 ++++++++++++
> >   1 file changed, 12 insertions(+)
> >
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index 5157524d8036..921d8610db0c 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -233,6 +233,18 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
> >   				      desc, NULL);
> >   }
> >
> > +static inline
> > +int virtio_find_vqs_ctx_size(struct virtio_device *vdev, u32 nvqs,
> > +				 struct virtqueue *vqs[],
> > +				 vq_callback_t *callbacks[],
> > +				 const char * const names[],
> > +				 const bool *ctx, struct irq_affinity *desc,
> > +				 u32 sizes[])
> > +{
> > +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> > +				      desc, sizes);
> > +}
>
>
> Do we need to convert all the open coded direct call to find_vqs() other
> than net?


Do you mean calling find_vqs without a helper? The kernel doesn't do that
anymore.

Thanks.


>
> Thanks
>
>
> > +
> >   /**
> >    * virtio_reset_vq - reset a queue individually
> >    * @vq: the virtqueue
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 21/26] virtio: add helper virtio_find_vqs_ctx_size()
@ 2022-03-09  9:58       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09  9:58 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 17:04:12 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > Introduce helper virtio_find_vqs_ctx_size() to call find_vqs and specify
> > the maximum size of each vq ring.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   include/linux/virtio_config.h | 12 ++++++++++++
> >   1 file changed, 12 insertions(+)
> >
> > diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> > index 5157524d8036..921d8610db0c 100644
> > --- a/include/linux/virtio_config.h
> > +++ b/include/linux/virtio_config.h
> > @@ -233,6 +233,18 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
> >   				      desc, NULL);
> >   }
> >
> > +static inline
> > +int virtio_find_vqs_ctx_size(struct virtio_device *vdev, u32 nvqs,
> > +				 struct virtqueue *vqs[],
> > +				 vq_callback_t *callbacks[],
> > +				 const char * const names[],
> > +				 const bool *ctx, struct irq_affinity *desc,
> > +				 u32 sizes[])
> > +{
> > +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> > +				      desc, sizes);
> > +}
>
>
> Do we need to convert all the open coded direct call to find_vqs() other
> than net?


Do you mean calling find_vqs without a helper? The kernel doesn't do that
anymore.

Thanks.


>
> Thanks
>
>
> > +
> >   /**
> >    * virtio_reset_vq - reset a queue individually
> >    * @vq: the virtqueue
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 24/26] virtio_net: support rx/tx queue reset
  2022-03-09  9:14     ` Jason Wang
  (?)
@ 2022-03-09 10:05       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09 10:05 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 17:14:34 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements the reset function of the rx, tx queues.
> >
> > Based on this function, it is possible to modify the ring num of the
> > queue. And quickly recycle the buffer in the queue.
> >
> > In the process of the queue disable, in theory, as long as virtio
> > supports queue reset, there will be no exceptions.
> >
> > However, in the process of the queue enable, there may be exceptions due to
> > memory allocation.  In this case, vq is not available, but we still have
> > to execute napi_enable(). Because napi_disable is similar to a lock,
> > napi_enable must be called after calling napi_disable.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 107 insertions(+)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index 409a8e180918..ffff323dcef0 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -251,6 +251,11 @@ struct padded_vnet_hdr {
> >   	char padding[4];
> >   };
> >
> > +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct send_queue *sq);
> > +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct receive_queue *rq);
> > +
> >   static bool is_xdp_frame(void *ptr)
> >   {
> >   	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
> > @@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
> >   {
> >   	napi_enable(napi);
> >
> > +	if (vq->reset)
> > +		return;
> > +
>
>
> Let's WARN_ONCE() here?
>
>
> >   	/* If all buffers were filled by other side before we napi_enabled, we
> >   	 * won't get another interrupt, so process any outstanding packets now.
> >   	 * Call local_bh_enable after to trigger softIRQ processing.
> > @@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
> >   		struct receive_queue *rq = &vi->rq[i];
> >
> >   		napi_disable(&rq->napi);
> > +		if (rq->vq->reset) {
> > +			virtnet_napi_enable(rq->vq, &rq->napi);
> > +			continue;
> > +		}
>
>
> This seems racy and it's a hint that we need sync with the refill work
> during reset like what we did in virtnet_close():
>
>          /* Make sure refill_work doesn't re-enable napi! */
>          cancel_delayed_work_sync(&vi->refill);
>
>
> >   		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
> >   		virtnet_napi_enable(rq->vq, &rq->napi);
> >
> > @@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
> >   	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
> >   		return;
> >
> > +	if (sq->vq->reset)
> > +		return;
>
>
> It looks to me we'd better either WARN or just remove this. Since it
> looks like a workaround for the un-synchronized NAPI somehow.
>

During the reset process, both ring reset and enable may fail. In the case of
failure, vq will be unavailable. All three cases prevent this situation.

Even if it fails, napi still needs to be enabled. This is to prevent
napi_disable from being stuck when the network card is closed.


So the first and second cases above are that napi is enabled, but vq has not
been reset successfully or is still in reset.

And the third case is to deal with tx in reset, and rx is in working state, then
here will access the vq of sq.




>
> > +
> >   	if (__netif_tx_trylock(txq)) {
> >   		do {
> >   			virtqueue_disable_cb(sq->vq);
> > @@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
> >   	return NETDEV_TX_OK;
> >   }
> >
> > +static int virtnet_rx_vq_reset(struct virtnet_info *vi,
> > +			       struct receive_queue *rq, u32 ring_num)
>
>
> It's better to rename this as virtnet_rx_resize().


I don't think resize is good enough, because I think resize is an effect of
reset. Inside af_xdp, we will call it just to reset to free the buffer without
resize with ring_num == 0.

So virtnet_rx_reset() might be better.

>
>
> > +{
> > +	int err;
> > +
> > +	/* stop napi */
> > +	napi_disable(&rq->napi);
> > +
>
>
> Here, as discussed above, we need synchronize with the refill work.
>
>
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(rq->vq);
> > +	if (err)
> > +		goto err;
>
>
> Btw, most comment of this function seems useless since code already
> explain themselves.

OK, I will remove these.

>
>
> > +
> > +	/* free bufs */
> > +	virtnet_rq_free_unused_bufs(vi, rq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(rq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(rq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* fill recv */
> > +	if (!try_fill_recv(vi, rq, GFP_KERNEL))
> > +		schedule_delayed_work(&vi->refill, 0);
> > +
> > +	/* enable napi */
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
> > +		   rq - vi->rq, err);
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return err;
> > +}
> > +
> > +static int virtnet_tx_vq_reset(struct virtnet_info *vi,
> > +			       struct send_queue *sq, u32 ring_num)
> > +{
>
>
> It looks to me it's better to rename this as "virtnet_rx_resize()"
>
>
> > +	struct netdev_queue *txq;
> > +	int err, qindex;
> > +
> > +	qindex = sq - vi->sq;
> > +
> > +	txq = netdev_get_tx_queue(vi->dev, qindex);
> > +	__netif_tx_lock_bh(txq);
> > +
> > +	/* stop tx queue and napi */
> > +	netif_stop_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_disable(&sq->napi);
>
>
> There's no need to hold tx lock for napi disable.

tx lock 的主要目的是等待其它的 xmit 调用结束.
并设置 netif_stop_subqueue()

The main purpose of tx lock is to wait for other xmit calls to end. And set
netif_stop_subqueue()

Thanks.

>
> Thanks
>
>
> > +
> > +	__netif_tx_unlock_bh(txq);
> > +
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(sq->vq);
> > +	if (err) {
> > +		netif_start_subqueue(vi->dev, qindex);
> > +		goto err;
> > +	}
> > +
> > +	/* free bufs */
> > +	virtnet_sq_free_unused_bufs(vi, sq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(sq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(sq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* start tx queue and napi */
> > +	netif_start_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
> > +		   sq - vi->sq, err);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return err;
> > +}
> > +
> >   /*
> >    * Send command via the control virtqueue and check status.  Commands
> >    * supported by the hypervisor, as indicated by feature bits, should
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 24/26] virtio_net: support rx/tx queue reset
@ 2022-03-09 10:05       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09 10:05 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 17:14:34 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements the reset function of the rx, tx queues.
> >
> > Based on this function, it is possible to modify the ring num of the
> > queue. And quickly recycle the buffer in the queue.
> >
> > In the process of the queue disable, in theory, as long as virtio
> > supports queue reset, there will be no exceptions.
> >
> > However, in the process of the queue enable, there may be exceptions due to
> > memory allocation.  In this case, vq is not available, but we still have
> > to execute napi_enable(). Because napi_disable is similar to a lock,
> > napi_enable must be called after calling napi_disable.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 107 insertions(+)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index 409a8e180918..ffff323dcef0 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -251,6 +251,11 @@ struct padded_vnet_hdr {
> >   	char padding[4];
> >   };
> >
> > +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct send_queue *sq);
> > +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct receive_queue *rq);
> > +
> >   static bool is_xdp_frame(void *ptr)
> >   {
> >   	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
> > @@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
> >   {
> >   	napi_enable(napi);
> >
> > +	if (vq->reset)
> > +		return;
> > +
>
>
> Let's WARN_ONCE() here?
>
>
> >   	/* If all buffers were filled by other side before we napi_enabled, we
> >   	 * won't get another interrupt, so process any outstanding packets now.
> >   	 * Call local_bh_enable after to trigger softIRQ processing.
> > @@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
> >   		struct receive_queue *rq = &vi->rq[i];
> >
> >   		napi_disable(&rq->napi);
> > +		if (rq->vq->reset) {
> > +			virtnet_napi_enable(rq->vq, &rq->napi);
> > +			continue;
> > +		}
>
>
> This seems racy and it's a hint that we need sync with the refill work
> during reset like what we did in virtnet_close():
>
>          /* Make sure refill_work doesn't re-enable napi! */
>          cancel_delayed_work_sync(&vi->refill);
>
>
> >   		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
> >   		virtnet_napi_enable(rq->vq, &rq->napi);
> >
> > @@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
> >   	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
> >   		return;
> >
> > +	if (sq->vq->reset)
> > +		return;
>
>
> It looks to me we'd better either WARN or just remove this. Since it
> looks like a workaround for the un-synchronized NAPI somehow.
>

During the reset process, both ring reset and enable may fail. In the case of
failure, vq will be unavailable. All three cases prevent this situation.

Even if it fails, napi still needs to be enabled. This is to prevent
napi_disable from being stuck when the network card is closed.


So the first and second cases above are that napi is enabled, but vq has not
been reset successfully or is still in reset.

And the third case is to deal with tx in reset, and rx is in working state, then
here will access the vq of sq.




>
> > +
> >   	if (__netif_tx_trylock(txq)) {
> >   		do {
> >   			virtqueue_disable_cb(sq->vq);
> > @@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
> >   	return NETDEV_TX_OK;
> >   }
> >
> > +static int virtnet_rx_vq_reset(struct virtnet_info *vi,
> > +			       struct receive_queue *rq, u32 ring_num)
>
>
> It's better to rename this as virtnet_rx_resize().


I don't think resize is good enough, because I think resize is an effect of
reset. Inside af_xdp, we will call it just to reset to free the buffer without
resize with ring_num == 0.

So virtnet_rx_reset() might be better.

>
>
> > +{
> > +	int err;
> > +
> > +	/* stop napi */
> > +	napi_disable(&rq->napi);
> > +
>
>
> Here, as discussed above, we need synchronize with the refill work.
>
>
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(rq->vq);
> > +	if (err)
> > +		goto err;
>
>
> Btw, most comment of this function seems useless since code already
> explain themselves.

OK, I will remove these.

>
>
> > +
> > +	/* free bufs */
> > +	virtnet_rq_free_unused_bufs(vi, rq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(rq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(rq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* fill recv */
> > +	if (!try_fill_recv(vi, rq, GFP_KERNEL))
> > +		schedule_delayed_work(&vi->refill, 0);
> > +
> > +	/* enable napi */
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
> > +		   rq - vi->rq, err);
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return err;
> > +}
> > +
> > +static int virtnet_tx_vq_reset(struct virtnet_info *vi,
> > +			       struct send_queue *sq, u32 ring_num)
> > +{
>
>
> It looks to me it's better to rename this as "virtnet_rx_resize()"
>
>
> > +	struct netdev_queue *txq;
> > +	int err, qindex;
> > +
> > +	qindex = sq - vi->sq;
> > +
> > +	txq = netdev_get_tx_queue(vi->dev, qindex);
> > +	__netif_tx_lock_bh(txq);
> > +
> > +	/* stop tx queue and napi */
> > +	netif_stop_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_disable(&sq->napi);
>
>
> There's no need to hold tx lock for napi disable.

tx lock 的主要目的是等待其它的 xmit 调用结束.
并设置 netif_stop_subqueue()

The main purpose of tx lock is to wait for other xmit calls to end. And set
netif_stop_subqueue()

Thanks.

>
> Thanks
>
>
> > +
> > +	__netif_tx_unlock_bh(txq);
> > +
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(sq->vq);
> > +	if (err) {
> > +		netif_start_subqueue(vi->dev, qindex);
> > +		goto err;
> > +	}
> > +
> > +	/* free bufs */
> > +	virtnet_sq_free_unused_bufs(vi, sq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(sq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(sq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* start tx queue and napi */
> > +	netif_start_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
> > +		   sq - vi->sq, err);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return err;
> > +}
> > +
> >   /*
> >    * Send command via the control virtqueue and check status.  Commands
> >    * supported by the hypervisor, as indicated by feature bits, should
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 24/26] virtio_net: support rx/tx queue reset
@ 2022-03-09 10:05       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09 10:05 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 17:14:34 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements the reset function of the rx, tx queues.
> >
> > Based on this function, it is possible to modify the ring num of the
> > queue. And quickly recycle the buffer in the queue.
> >
> > In the process of the queue disable, in theory, as long as virtio
> > supports queue reset, there will be no exceptions.
> >
> > However, in the process of the queue enable, there may be exceptions due to
> > memory allocation.  In this case, vq is not available, but we still have
> > to execute napi_enable(). Because napi_disable is similar to a lock,
> > napi_enable must be called after calling napi_disable.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 107 insertions(+)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index 409a8e180918..ffff323dcef0 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -251,6 +251,11 @@ struct padded_vnet_hdr {
> >   	char padding[4];
> >   };
> >
> > +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct send_queue *sq);
> > +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct receive_queue *rq);
> > +
> >   static bool is_xdp_frame(void *ptr)
> >   {
> >   	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
> > @@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
> >   {
> >   	napi_enable(napi);
> >
> > +	if (vq->reset)
> > +		return;
> > +
>
>
> Let's WARN_ONCE() here?
>
>
> >   	/* If all buffers were filled by other side before we napi_enabled, we
> >   	 * won't get another interrupt, so process any outstanding packets now.
> >   	 * Call local_bh_enable after to trigger softIRQ processing.
> > @@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
> >   		struct receive_queue *rq = &vi->rq[i];
> >
> >   		napi_disable(&rq->napi);
> > +		if (rq->vq->reset) {
> > +			virtnet_napi_enable(rq->vq, &rq->napi);
> > +			continue;
> > +		}
>
>
> This seems racy and it's a hint that we need sync with the refill work
> during reset like what we did in virtnet_close():
>
>          /* Make sure refill_work doesn't re-enable napi! */
>          cancel_delayed_work_sync(&vi->refill);
>
>
> >   		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
> >   		virtnet_napi_enable(rq->vq, &rq->napi);
> >
> > @@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
> >   	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
> >   		return;
> >
> > +	if (sq->vq->reset)
> > +		return;
>
>
> It looks to me we'd better either WARN or just remove this. Since it
> looks like a workaround for the un-synchronized NAPI somehow.
>

During the reset process, both ring reset and enable may fail. In the case of
failure, vq will be unavailable. All three cases prevent this situation.

Even if it fails, napi still needs to be enabled. This is to prevent
napi_disable from being stuck when the network card is closed.


So the first and second cases above are that napi is enabled, but vq has not
been reset successfully or is still in reset.

And the third case is to deal with tx in reset, and rx is in working state, then
here will access the vq of sq.




>
> > +
> >   	if (__netif_tx_trylock(txq)) {
> >   		do {
> >   			virtqueue_disable_cb(sq->vq);
> > @@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
> >   	return NETDEV_TX_OK;
> >   }
> >
> > +static int virtnet_rx_vq_reset(struct virtnet_info *vi,
> > +			       struct receive_queue *rq, u32 ring_num)
>
>
> It's better to rename this as virtnet_rx_resize().


I don't think resize is good enough, because I think resize is an effect of
reset. Inside af_xdp, we will call it just to reset to free the buffer without
resize with ring_num == 0.

So virtnet_rx_reset() might be better.

>
>
> > +{
> > +	int err;
> > +
> > +	/* stop napi */
> > +	napi_disable(&rq->napi);
> > +
>
>
> Here, as discussed above, we need synchronize with the refill work.
>
>
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(rq->vq);
> > +	if (err)
> > +		goto err;
>
>
> Btw, most comment of this function seems useless since code already
> explain themselves.

OK, I will remove these.

>
>
> > +
> > +	/* free bufs */
> > +	virtnet_rq_free_unused_bufs(vi, rq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(rq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(rq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* fill recv */
> > +	if (!try_fill_recv(vi, rq, GFP_KERNEL))
> > +		schedule_delayed_work(&vi->refill, 0);
> > +
> > +	/* enable napi */
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
> > +		   rq - vi->rq, err);
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return err;
> > +}
> > +
> > +static int virtnet_tx_vq_reset(struct virtnet_info *vi,
> > +			       struct send_queue *sq, u32 ring_num)
> > +{
>
>
> It looks to me it's better to rename this as "virtnet_rx_resize()"
>
>
> > +	struct netdev_queue *txq;
> > +	int err, qindex;
> > +
> > +	qindex = sq - vi->sq;
> > +
> > +	txq = netdev_get_tx_queue(vi->dev, qindex);
> > +	__netif_tx_lock_bh(txq);
> > +
> > +	/* stop tx queue and napi */
> > +	netif_stop_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_disable(&sq->napi);
>
>
> There's no need to hold tx lock for napi disable.

tx lock 的主要目的是等待其它的 xmit 调用结束.
并设置 netif_stop_subqueue()

The main purpose of tx lock is to wait for other xmit calls to end. And set
netif_stop_subqueue()

Thanks.

>
> Thanks
>
>
> > +
> > +	__netif_tx_unlock_bh(txq);
> > +
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(sq->vq);
> > +	if (err) {
> > +		netif_start_subqueue(vi->dev, qindex);
> > +		goto err;
> > +	}
> > +
> > +	/* free bufs */
> > +	virtnet_sq_free_unused_bufs(vi, sq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(sq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(sq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* start tx queue and napi */
> > +	netif_start_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
> > +		   sq - vi->sq, err);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return err;
> > +}
> > +
> >   /*
> >    * Send command via the control virtqueue and check status.  Commands
> >    * supported by the hypervisor, as indicated by feature bits, should
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 24/26] virtio_net: support rx/tx queue reset
  2022-03-09  9:14     ` Jason Wang
  (?)
@ 2022-03-09 10:16       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09 10:16 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

Sorry, the last reply email was too fast, with some Chinese mixed in. So send
another email.

On Wed, 9 Mar 2022 17:14:34 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements the reset function of the rx, tx queues.
> >
> > Based on this function, it is possible to modify the ring num of the
> > queue. And quickly recycle the buffer in the queue.
> >
> > In the process of the queue disable, in theory, as long as virtio
> > supports queue reset, there will be no exceptions.
> >
> > However, in the process of the queue enable, there may be exceptions due to
> > memory allocation.  In this case, vq is not available, but we still have
> > to execute napi_enable(). Because napi_disable is similar to a lock,
> > napi_enable must be called after calling napi_disable.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 107 insertions(+)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index 409a8e180918..ffff323dcef0 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -251,6 +251,11 @@ struct padded_vnet_hdr {
> >   	char padding[4];
> >   };
> >
> > +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct send_queue *sq);
> > +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct receive_queue *rq);
> > +
> >   static bool is_xdp_frame(void *ptr)
> >   {
> >   	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
> > @@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
> >   {
> >   	napi_enable(napi);
> >
> > +	if (vq->reset)
> > +		return;
> > +
>
>
> Let's WARN_ONCE() here?
>
>
> >   	/* If all buffers were filled by other side before we napi_enabled, we
> >   	 * won't get another interrupt, so process any outstanding packets now.
> >   	 * Call local_bh_enable after to trigger softIRQ processing.
> > @@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
> >   		struct receive_queue *rq = &vi->rq[i];
> >
> >   		napi_disable(&rq->napi);
> > +		if (rq->vq->reset) {
> > +			virtnet_napi_enable(rq->vq, &rq->napi);
> > +			continue;
> > +		}
>
>
> This seems racy and it's a hint that we need sync with the refill work
> during reset like what we did in virtnet_close():
>
>          /* Make sure refill_work doesn't re-enable napi! */
>          cancel_delayed_work_sync(&vi->refill);
>
>
> >   		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
> >   		virtnet_napi_enable(rq->vq, &rq->napi);
> >
> > @@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
> >   	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
> >   		return;
> >
> > +	if (sq->vq->reset)
> > +		return;
>
>
> It looks to me we'd better either WARN or just remove this. Since it
> looks like a workaround for the un-synchronized NAPI somehow.

During the reset process, both ring reset and enable may fail. In the case of
failure, vq will be unavailable. All three cases prevent this situation.

Even if it fails, napi still needs to be enabled. This is to prevent
napi_disable from being stuck when the network card is closed.


So the first and second cases above are that napi is enabled, but vq has not
been reset successfully or is still in reset.

And the third case is to deal with tx in reset, and rx is in working state, then
here will access the vq of sq.

>
>
> > +
> >   	if (__netif_tx_trylock(txq)) {
> >   		do {
> >   			virtqueue_disable_cb(sq->vq);
> > @@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
> >   	return NETDEV_TX_OK;
> >   }
> >
> > +static int virtnet_rx_vq_reset(struct virtnet_info *vi,
> > +			       struct receive_queue *rq, u32 ring_num)
>
>
> It's better to rename this as virtnet_rx_resize().

I don't think resize is good enough, because I think resize is an effect of
reset. Inside af_xdp, we will call it just to reset to free the buffer without
resize with ring_num == 0.

So virtnet_rx_reset() might be better.


>
>
> > +{
> > +	int err;
> > +
> > +	/* stop napi */
> > +	napi_disable(&rq->napi);
> > +
>
>
> Here, as discussed above, we need synchronize with the refill work.
>
>
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(rq->vq);
> > +	if (err)
> > +		goto err;
>
>
> Btw, most comment of this function seems useless since code already
> explain themselves.
>

OK, I will remove these.

>
> > +
> > +	/* free bufs */
> > +	virtnet_rq_free_unused_bufs(vi, rq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(rq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(rq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* fill recv */
> > +	if (!try_fill_recv(vi, rq, GFP_KERNEL))
> > +		schedule_delayed_work(&vi->refill, 0);
> > +
> > +	/* enable napi */
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
> > +		   rq - vi->rq, err);
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return err;
> > +}
> > +
> > +static int virtnet_tx_vq_reset(struct virtnet_info *vi,
> > +			       struct send_queue *sq, u32 ring_num)
> > +{
>
>
> It looks to me it's better to rename this as "virtnet_rx_resize()"
>
>
> > +	struct netdev_queue *txq;
> > +	int err, qindex;
> > +
> > +	qindex = sq - vi->sq;
> > +
> > +	txq = netdev_get_tx_queue(vi->dev, qindex);
> > +	__netif_tx_lock_bh(txq);
> > +
> > +	/* stop tx queue and napi */
> > +	netif_stop_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_disable(&sq->napi);
>
>
> There's no need to hold tx lock for napi disable.

The main purpose of tx lock is to wait for other xmit calls to end. And set
netif_stop_subqueue()

Thanks.

>
> Thanks
>
>
> > +
> > +	__netif_tx_unlock_bh(txq);
> > +
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(sq->vq);
> > +	if (err) {
> > +		netif_start_subqueue(vi->dev, qindex);
> > +		goto err;
> > +	}
> > +
> > +	/* free bufs */
> > +	virtnet_sq_free_unused_bufs(vi, sq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(sq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(sq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* start tx queue and napi */
> > +	netif_start_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
> > +		   sq - vi->sq, err);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return err;
> > +}
> > +
> >   /*
> >    * Send command via the control virtqueue and check status.  Commands
> >    * supported by the hypervisor, as indicated by feature bits, should
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 24/26] virtio_net: support rx/tx queue reset
@ 2022-03-09 10:16       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09 10:16 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

Sorry, the last reply email was too fast, with some Chinese mixed in. So send
another email.

On Wed, 9 Mar 2022 17:14:34 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements the reset function of the rx, tx queues.
> >
> > Based on this function, it is possible to modify the ring num of the
> > queue. And quickly recycle the buffer in the queue.
> >
> > In the process of the queue disable, in theory, as long as virtio
> > supports queue reset, there will be no exceptions.
> >
> > However, in the process of the queue enable, there may be exceptions due to
> > memory allocation.  In this case, vq is not available, but we still have
> > to execute napi_enable(). Because napi_disable is similar to a lock,
> > napi_enable must be called after calling napi_disable.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 107 insertions(+)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index 409a8e180918..ffff323dcef0 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -251,6 +251,11 @@ struct padded_vnet_hdr {
> >   	char padding[4];
> >   };
> >
> > +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct send_queue *sq);
> > +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct receive_queue *rq);
> > +
> >   static bool is_xdp_frame(void *ptr)
> >   {
> >   	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
> > @@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
> >   {
> >   	napi_enable(napi);
> >
> > +	if (vq->reset)
> > +		return;
> > +
>
>
> Let's WARN_ONCE() here?
>
>
> >   	/* If all buffers were filled by other side before we napi_enabled, we
> >   	 * won't get another interrupt, so process any outstanding packets now.
> >   	 * Call local_bh_enable after to trigger softIRQ processing.
> > @@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
> >   		struct receive_queue *rq = &vi->rq[i];
> >
> >   		napi_disable(&rq->napi);
> > +		if (rq->vq->reset) {
> > +			virtnet_napi_enable(rq->vq, &rq->napi);
> > +			continue;
> > +		}
>
>
> This seems racy and it's a hint that we need sync with the refill work
> during reset like what we did in virtnet_close():
>
>          /* Make sure refill_work doesn't re-enable napi! */
>          cancel_delayed_work_sync(&vi->refill);
>
>
> >   		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
> >   		virtnet_napi_enable(rq->vq, &rq->napi);
> >
> > @@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
> >   	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
> >   		return;
> >
> > +	if (sq->vq->reset)
> > +		return;
>
>
> It looks to me we'd better either WARN or just remove this. Since it
> looks like a workaround for the un-synchronized NAPI somehow.

During the reset process, both ring reset and enable may fail. In the case of
failure, vq will be unavailable. All three cases prevent this situation.

Even if it fails, napi still needs to be enabled. This is to prevent
napi_disable from being stuck when the network card is closed.


So the first and second cases above are that napi is enabled, but vq has not
been reset successfully or is still in reset.

And the third case is to deal with tx in reset, and rx is in working state, then
here will access the vq of sq.

>
>
> > +
> >   	if (__netif_tx_trylock(txq)) {
> >   		do {
> >   			virtqueue_disable_cb(sq->vq);
> > @@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
> >   	return NETDEV_TX_OK;
> >   }
> >
> > +static int virtnet_rx_vq_reset(struct virtnet_info *vi,
> > +			       struct receive_queue *rq, u32 ring_num)
>
>
> It's better to rename this as virtnet_rx_resize().

I don't think resize is good enough, because I think resize is an effect of
reset. Inside af_xdp, we will call it just to reset to free the buffer without
resize with ring_num == 0.

So virtnet_rx_reset() might be better.


>
>
> > +{
> > +	int err;
> > +
> > +	/* stop napi */
> > +	napi_disable(&rq->napi);
> > +
>
>
> Here, as discussed above, we need synchronize with the refill work.
>
>
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(rq->vq);
> > +	if (err)
> > +		goto err;
>
>
> Btw, most comment of this function seems useless since code already
> explain themselves.
>

OK, I will remove these.

>
> > +
> > +	/* free bufs */
> > +	virtnet_rq_free_unused_bufs(vi, rq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(rq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(rq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* fill recv */
> > +	if (!try_fill_recv(vi, rq, GFP_KERNEL))
> > +		schedule_delayed_work(&vi->refill, 0);
> > +
> > +	/* enable napi */
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
> > +		   rq - vi->rq, err);
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return err;
> > +}
> > +
> > +static int virtnet_tx_vq_reset(struct virtnet_info *vi,
> > +			       struct send_queue *sq, u32 ring_num)
> > +{
>
>
> It looks to me it's better to rename this as "virtnet_rx_resize()"
>
>
> > +	struct netdev_queue *txq;
> > +	int err, qindex;
> > +
> > +	qindex = sq - vi->sq;
> > +
> > +	txq = netdev_get_tx_queue(vi->dev, qindex);
> > +	__netif_tx_lock_bh(txq);
> > +
> > +	/* stop tx queue and napi */
> > +	netif_stop_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_disable(&sq->napi);
>
>
> There's no need to hold tx lock for napi disable.

The main purpose of tx lock is to wait for other xmit calls to end. And set
netif_stop_subqueue()

Thanks.

>
> Thanks
>
>
> > +
> > +	__netif_tx_unlock_bh(txq);
> > +
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(sq->vq);
> > +	if (err) {
> > +		netif_start_subqueue(vi->dev, qindex);
> > +		goto err;
> > +	}
> > +
> > +	/* free bufs */
> > +	virtnet_sq_free_unused_bufs(vi, sq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(sq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(sq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* start tx queue and napi */
> > +	netif_start_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
> > +		   sq - vi->sq, err);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return err;
> > +}
> > +
> >   /*
> >    * Send command via the control virtqueue and check status.  Commands
> >    * supported by the hypervisor, as indicated by feature bits, should
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 24/26] virtio_net: support rx/tx queue reset
@ 2022-03-09 10:16       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-09 10:16 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

Sorry, the last reply email was too fast, with some Chinese mixed in. So send
another email.

On Wed, 9 Mar 2022 17:14:34 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements the reset function of the rx, tx queues.
> >
> > Based on this function, it is possible to modify the ring num of the
> > queue. And quickly recycle the buffer in the queue.
> >
> > In the process of the queue disable, in theory, as long as virtio
> > supports queue reset, there will be no exceptions.
> >
> > However, in the process of the queue enable, there may be exceptions due to
> > memory allocation.  In this case, vq is not available, but we still have
> > to execute napi_enable(). Because napi_disable is similar to a lock,
> > napi_enable must be called after calling napi_disable.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/net/virtio_net.c | 107 +++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 107 insertions(+)
> >
> > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
> > index 409a8e180918..ffff323dcef0 100644
> > --- a/drivers/net/virtio_net.c
> > +++ b/drivers/net/virtio_net.c
> > @@ -251,6 +251,11 @@ struct padded_vnet_hdr {
> >   	char padding[4];
> >   };
> >
> > +static void virtnet_sq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct send_queue *sq);
> > +static void virtnet_rq_free_unused_bufs(struct virtnet_info *vi,
> > +					struct receive_queue *rq);
> > +
> >   static bool is_xdp_frame(void *ptr)
> >   {
> >   	return (unsigned long)ptr & VIRTIO_XDP_FLAG;
> > @@ -1369,6 +1374,9 @@ static void virtnet_napi_enable(struct virtqueue *vq, struct napi_struct *napi)
> >   {
> >   	napi_enable(napi);
> >
> > +	if (vq->reset)
> > +		return;
> > +
>
>
> Let's WARN_ONCE() here?
>
>
> >   	/* If all buffers were filled by other side before we napi_enabled, we
> >   	 * won't get another interrupt, so process any outstanding packets now.
> >   	 * Call local_bh_enable after to trigger softIRQ processing.
> > @@ -1413,6 +1421,10 @@ static void refill_work(struct work_struct *work)
> >   		struct receive_queue *rq = &vi->rq[i];
> >
> >   		napi_disable(&rq->napi);
> > +		if (rq->vq->reset) {
> > +			virtnet_napi_enable(rq->vq, &rq->napi);
> > +			continue;
> > +		}
>
>
> This seems racy and it's a hint that we need sync with the refill work
> during reset like what we did in virtnet_close():
>
>          /* Make sure refill_work doesn't re-enable napi! */
>          cancel_delayed_work_sync(&vi->refill);
>
>
> >   		still_empty = !try_fill_recv(vi, rq, GFP_KERNEL);
> >   		virtnet_napi_enable(rq->vq, &rq->napi);
> >
> > @@ -1523,6 +1535,9 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
> >   	if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
> >   		return;
> >
> > +	if (sq->vq->reset)
> > +		return;
>
>
> It looks to me we'd better either WARN or just remove this. Since it
> looks like a workaround for the un-synchronized NAPI somehow.

During the reset process, both ring reset and enable may fail. In the case of
failure, vq will be unavailable. All three cases prevent this situation.

Even if it fails, napi still needs to be enabled. This is to prevent
napi_disable from being stuck when the network card is closed.


So the first and second cases above are that napi is enabled, but vq has not
been reset successfully or is still in reset.

And the third case is to deal with tx in reset, and rx is in working state, then
here will access the vq of sq.

>
>
> > +
> >   	if (__netif_tx_trylock(txq)) {
> >   		do {
> >   			virtqueue_disable_cb(sq->vq);
> > @@ -1769,6 +1784,98 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
> >   	return NETDEV_TX_OK;
> >   }
> >
> > +static int virtnet_rx_vq_reset(struct virtnet_info *vi,
> > +			       struct receive_queue *rq, u32 ring_num)
>
>
> It's better to rename this as virtnet_rx_resize().

I don't think resize is good enough, because I think resize is an effect of
reset. Inside af_xdp, we will call it just to reset to free the buffer without
resize with ring_num == 0.

So virtnet_rx_reset() might be better.


>
>
> > +{
> > +	int err;
> > +
> > +	/* stop napi */
> > +	napi_disable(&rq->napi);
> > +
>
>
> Here, as discussed above, we need synchronize with the refill work.
>
>
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(rq->vq);
> > +	if (err)
> > +		goto err;
>
>
> Btw, most comment of this function seems useless since code already
> explain themselves.
>

OK, I will remove these.

>
> > +
> > +	/* free bufs */
> > +	virtnet_rq_free_unused_bufs(vi, rq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(rq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(rq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* fill recv */
> > +	if (!try_fill_recv(vi, rq, GFP_KERNEL))
> > +		schedule_delayed_work(&vi->refill, 0);
> > +
> > +	/* enable napi */
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset rx reset vq fail: rx queue index: %ld err: %d\n",
> > +		   rq - vi->rq, err);
> > +	virtnet_napi_enable(rq->vq, &rq->napi);
> > +	return err;
> > +}
> > +
> > +static int virtnet_tx_vq_reset(struct virtnet_info *vi,
> > +			       struct send_queue *sq, u32 ring_num)
> > +{
>
>
> It looks to me it's better to rename this as "virtnet_rx_resize()"
>
>
> > +	struct netdev_queue *txq;
> > +	int err, qindex;
> > +
> > +	qindex = sq - vi->sq;
> > +
> > +	txq = netdev_get_tx_queue(vi->dev, qindex);
> > +	__netif_tx_lock_bh(txq);
> > +
> > +	/* stop tx queue and napi */
> > +	netif_stop_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_disable(&sq->napi);
>
>
> There's no need to hold tx lock for napi disable.

The main purpose of tx lock is to wait for other xmit calls to end. And set
netif_stop_subqueue()

Thanks.

>
> Thanks
>
>
> > +
> > +	__netif_tx_unlock_bh(txq);
> > +
> > +	/* reset the queue */
> > +	err = virtio_reset_vq(sq->vq);
> > +	if (err) {
> > +		netif_start_subqueue(vi->dev, qindex);
> > +		goto err;
> > +	}
> > +
> > +	/* free bufs */
> > +	virtnet_sq_free_unused_bufs(vi, sq);
> > +
> > +	/* reset vring. */
> > +	err = virtqueue_reset_vring(sq->vq, ring_num);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* enable reset queue */
> > +	err = virtio_enable_resetq(sq->vq);
> > +	if (err)
> > +		goto err;
> > +
> > +	/* start tx queue and napi */
> > +	netif_start_subqueue(vi->dev, qindex);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return 0;
> > +
> > +err:
> > +	netdev_err(vi->dev,
> > +		   "reset tx reset vq fail: tx queue index: %ld err: %d\n",
> > +		   sq - vi->sq, err);
> > +	virtnet_napi_tx_enable(vi, sq->vq, &sq->napi);
> > +	return err;
> > +}
> > +
> >   /*
> >    * Send command via the control virtqueue and check status.  Commands
> >    * supported by the hypervisor, as indicated by feature bits, should
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 18/26] virtio: find_vqs() add arg sizes
  2022-03-08 12:35   ` Xuan Zhuo
@ 2022-03-09 18:18     ` Mathieu Poirier
  -1 siblings, 0 replies; 218+ messages in thread
From: Mathieu Poirier @ 2022-03-09 18:18 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Michael S. Tsirkin, Jason Wang, David S. Miller,
	Jakub Kicinski, Hans de Goede, Mark Gross, Vadim Pasternak,
	Bjorn Andersson, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Tue, Mar 08, 2022 at 08:35:10PM +0800, Xuan Zhuo wrote:
> find_vqs() adds a new parameter sizes to specify the size of each vq
> vring.
> 
> 0 means use the maximum size supported by the backend.
> 
> In the split scenario, the meaning of size is the largest size, because
> it may be limited by memory, the virtio core will try a smaller size.
> And the size is power of 2.
> 
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>  arch/um/drivers/virtio_uml.c             |  2 +-
>  drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
>  drivers/remoteproc/remoteproc_virtio.c   |  2 +-

For the remoteproc changes:

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>

>  drivers/s390/virtio/virtio_ccw.c         |  2 +-
>  drivers/virtio/virtio_mmio.c             |  2 +-
>  drivers/virtio/virtio_pci_common.c       |  2 +-
>  drivers/virtio/virtio_pci_common.h       |  2 +-
>  drivers/virtio/virtio_pci_modern.c       |  5 +++--
>  drivers/virtio/virtio_vdpa.c             |  2 +-
>  include/linux/virtio_config.h            | 11 +++++++----
>  10 files changed, 19 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> index ba562d68dc04..055b91ccbe8a 100644
> --- a/arch/um/drivers/virtio_uml.c
> +++ b/arch/um/drivers/virtio_uml.c
> @@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
>  static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		       const char * const names[], const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
>  	int i, queue_idx = 0, rc;
> diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
> index 38800e86ed8a..aea7aa218b22 100644
> --- a/drivers/platform/mellanox/mlxbf-tmfifo.c
> +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
> @@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
>  					vq_callback_t *callbacks[],
>  					const char * const names[],
>  					const bool *ctx,
> -					struct irq_affinity *desc)
> +					struct irq_affinity *desc,
> +					u32 sizes[])
>  {
>  	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
>  	struct mlxbf_tmfifo_vring *vring;
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index 70ab496d0431..3a167bec5b09 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
>  				 vq_callback_t *callbacks[],
>  				 const char * const names[],
>  				 const bool * ctx,
> -				 struct irq_affinity *desc)
> +				 struct irq_affinity *desc, u32 sizes[])
>  {
>  	int i, ret, queue_idx = 0;
>  
> diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
> index d35e7a3f7067..b74e08c71534 100644
> --- a/drivers/s390/virtio/virtio_ccw.c
> +++ b/drivers/s390/virtio/virtio_ccw.c
> @@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			       vq_callback_t *callbacks[],
>  			       const char * const names[],
>  			       const bool *ctx,
> -			       struct irq_affinity *desc)
> +			       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
>  	unsigned long *indicatorp = NULL;
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index a41abc8051b9..55d575f6ef2d 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		       vq_callback_t *callbacks[],
>  		       const char * const names[],
>  		       const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
>  	int irq = platform_get_irq(vm_dev->pdev, 0);
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 863d3a8a0956..8e8fa7e5ad80 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
>  int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc)
> +		struct irq_affinity *desc, u32 sizes[])
>  {
>  	int err;
>  
> diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> index 23f6c5c678d5..9dbf1d555dff 100644
> --- a/drivers/virtio/virtio_pci_common.h
> +++ b/drivers/virtio/virtio_pci_common.h
> @@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
>  int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc);
> +		struct irq_affinity *desc, u32 sizes[]);
>  const char *vp_bus_name(struct virtio_device *vdev);
>  
>  /* Setup the affinity for a virtqueue:
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 3c67d3607802..342795175c29 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			      struct virtqueue *vqs[],
>  			      vq_callback_t *callbacks[],
>  			      const char * const names[], const bool *ctx,
> -			      struct irq_affinity *desc)
> +			      struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
>  	struct virtqueue *vq;
> -	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
> +	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
> +			     sizes);
>  
>  	if (rc)
>  		return rc;
> diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
> index 7767a7f0119b..ee08d01ee8b1 100644
> --- a/drivers/virtio/virtio_vdpa.c
> +++ b/drivers/virtio/virtio_vdpa.c
> @@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  				vq_callback_t *callbacks[],
>  				const char * const names[],
>  				const bool *ctx,
> -				struct irq_affinity *desc)
> +				struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
>  	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 0b81fbe17c85..5157524d8036 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -57,6 +57,7 @@ struct virtio_shm_region {
>   *		include a NULL entry for vqs that do not need a callback
>   *	names: array of virtqueue names (mainly for debugging)
>   *		include a NULL entry for vqs unused by driver
> + *	sizes: array of virtqueue sizes
>   *	Returns 0 on success or error status
>   * @del_vqs: free virtqueues found by find_vqs().
>   * @get_features: get the array of feature bits for this device.
> @@ -98,7 +99,8 @@ struct virtio_config_ops {
>  	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
>  			struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  			const char * const names[], const bool *ctx,
> -			struct irq_affinity *desc);
> +			struct irq_affinity *desc,
> +			u32 sizes[]);
>  	void (*del_vqs)(struct virtio_device *);
>  	u64 (*get_features)(struct virtio_device *vdev);
>  	int (*finalize_features)(struct virtio_device *vdev);
> @@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
>  	const char *names[] = { n };
>  	struct virtqueue *vq;
>  	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
> -					 NULL);
> +					 NULL, NULL);
>  	if (err < 0)
>  		return ERR_PTR(err);
>  	return vq;
> @@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			const char * const names[],
>  			struct irq_affinity *desc)
>  {
> -	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
> +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
> +				      desc, NULL);
>  }
>  
>  static inline
> @@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>  			struct irq_affinity *desc)
>  {
>  	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> -				      desc);
> +				      desc, NULL);
>  }
>  
>  /**
> -- 
> 2.31.0
> 

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 18/26] virtio: find_vqs() add arg sizes
@ 2022-03-09 18:18     ` Mathieu Poirier
  0 siblings, 0 replies; 218+ messages in thread
From: Mathieu Poirier @ 2022-03-09 18:18 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Michael S. Tsirkin, Jason Wang, David S. Miller,
	Jakub Kicinski, Hans de Goede, Mark Gross, Vadim Pasternak,
	Bjorn Andersson, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Tue, Mar 08, 2022 at 08:35:10PM +0800, Xuan Zhuo wrote:
> find_vqs() adds a new parameter sizes to specify the size of each vq
> vring.
> 
> 0 means use the maximum size supported by the backend.
> 
> In the split scenario, the meaning of size is the largest size, because
> it may be limited by memory, the virtio core will try a smaller size.
> And the size is power of 2.
> 
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>  arch/um/drivers/virtio_uml.c             |  2 +-
>  drivers/platform/mellanox/mlxbf-tmfifo.c |  3 ++-
>  drivers/remoteproc/remoteproc_virtio.c   |  2 +-

For the remoteproc changes:

Reviewed-by: Mathieu Poirier <mathieu.poirier@linaro.org>

>  drivers/s390/virtio/virtio_ccw.c         |  2 +-
>  drivers/virtio/virtio_mmio.c             |  2 +-
>  drivers/virtio/virtio_pci_common.c       |  2 +-
>  drivers/virtio/virtio_pci_common.h       |  2 +-
>  drivers/virtio/virtio_pci_modern.c       |  5 +++--
>  drivers/virtio/virtio_vdpa.c             |  2 +-
>  include/linux/virtio_config.h            | 11 +++++++----
>  10 files changed, 19 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
> index ba562d68dc04..055b91ccbe8a 100644
> --- a/arch/um/drivers/virtio_uml.c
> +++ b/arch/um/drivers/virtio_uml.c
> @@ -998,7 +998,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device *vdev,
>  static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		       struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		       const char * const names[], const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
>  	int i, queue_idx = 0, rc;
> diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
> index 38800e86ed8a..aea7aa218b22 100644
> --- a/drivers/platform/mellanox/mlxbf-tmfifo.c
> +++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
> @@ -929,7 +929,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct virtio_device *vdev,
>  					vq_callback_t *callbacks[],
>  					const char * const names[],
>  					const bool *ctx,
> -					struct irq_affinity *desc)
> +					struct irq_affinity *desc,
> +					u32 sizes[])
>  {
>  	struct mlxbf_tmfifo_vdev *tm_vdev = mlxbf_vdev_to_tmfifo(vdev);
>  	struct mlxbf_tmfifo_vring *vring;
> diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c
> index 70ab496d0431..3a167bec5b09 100644
> --- a/drivers/remoteproc/remoteproc_virtio.c
> +++ b/drivers/remoteproc/remoteproc_virtio.c
> @@ -157,7 +157,7 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
>  				 vq_callback_t *callbacks[],
>  				 const char * const names[],
>  				 const bool * ctx,
> -				 struct irq_affinity *desc)
> +				 struct irq_affinity *desc, u32 sizes[])
>  {
>  	int i, ret, queue_idx = 0;
>  
> diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
> index d35e7a3f7067..b74e08c71534 100644
> --- a/drivers/s390/virtio/virtio_ccw.c
> +++ b/drivers/s390/virtio/virtio_ccw.c
> @@ -632,7 +632,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			       vq_callback_t *callbacks[],
>  			       const char * const names[],
>  			       const bool *ctx,
> -			       struct irq_affinity *desc)
> +			       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_ccw_device *vcdev = to_vc_device(vdev);
>  	unsigned long *indicatorp = NULL;
> diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
> index a41abc8051b9..55d575f6ef2d 100644
> --- a/drivers/virtio/virtio_mmio.c
> +++ b/drivers/virtio/virtio_mmio.c
> @@ -462,7 +462,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		       vq_callback_t *callbacks[],
>  		       const char * const names[],
>  		       const bool *ctx,
> -		       struct irq_affinity *desc)
> +		       struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
>  	int irq = platform_get_irq(vm_dev->pdev, 0);
> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> index 863d3a8a0956..8e8fa7e5ad80 100644
> --- a/drivers/virtio/virtio_pci_common.c
> +++ b/drivers/virtio/virtio_pci_common.c
> @@ -428,7 +428,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
>  int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc)
> +		struct irq_affinity *desc, u32 sizes[])
>  {
>  	int err;
>  
> diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
> index 23f6c5c678d5..9dbf1d555dff 100644
> --- a/drivers/virtio/virtio_pci_common.h
> +++ b/drivers/virtio/virtio_pci_common.h
> @@ -114,7 +114,7 @@ void vp_del_vqs(struct virtio_device *vdev);
>  int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  		struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  		const char * const names[], const bool *ctx,
> -		struct irq_affinity *desc);
> +		struct irq_affinity *desc, u32 sizes[]);
>  const char *vp_bus_name(struct virtio_device *vdev);
>  
>  /* Setup the affinity for a virtqueue:
> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> index 3c67d3607802..342795175c29 100644
> --- a/drivers/virtio/virtio_pci_modern.c
> +++ b/drivers/virtio/virtio_pci_modern.c
> @@ -343,11 +343,12 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			      struct virtqueue *vqs[],
>  			      vq_callback_t *callbacks[],
>  			      const char * const names[], const bool *ctx,
> -			      struct irq_affinity *desc)
> +			      struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_pci_device *vp_dev = to_vp_device(vdev);
>  	struct virtqueue *vq;
> -	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
> +	int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc,
> +			     sizes);
>  
>  	if (rc)
>  		return rc;
> diff --git a/drivers/virtio/virtio_vdpa.c b/drivers/virtio/virtio_vdpa.c
> index 7767a7f0119b..ee08d01ee8b1 100644
> --- a/drivers/virtio/virtio_vdpa.c
> +++ b/drivers/virtio/virtio_vdpa.c
> @@ -268,7 +268,7 @@ static int virtio_vdpa_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  				vq_callback_t *callbacks[],
>  				const char * const names[],
>  				const bool *ctx,
> -				struct irq_affinity *desc)
> +				struct irq_affinity *desc, u32 sizes[])
>  {
>  	struct virtio_vdpa_device *vd_dev = to_virtio_vdpa_device(vdev);
>  	struct vdpa_device *vdpa = vd_get_vdpa(vdev);
> diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
> index 0b81fbe17c85..5157524d8036 100644
> --- a/include/linux/virtio_config.h
> +++ b/include/linux/virtio_config.h
> @@ -57,6 +57,7 @@ struct virtio_shm_region {
>   *		include a NULL entry for vqs that do not need a callback
>   *	names: array of virtqueue names (mainly for debugging)
>   *		include a NULL entry for vqs unused by driver
> + *	sizes: array of virtqueue sizes
>   *	Returns 0 on success or error status
>   * @del_vqs: free virtqueues found by find_vqs().
>   * @get_features: get the array of feature bits for this device.
> @@ -98,7 +99,8 @@ struct virtio_config_ops {
>  	int (*find_vqs)(struct virtio_device *, unsigned nvqs,
>  			struct virtqueue *vqs[], vq_callback_t *callbacks[],
>  			const char * const names[], const bool *ctx,
> -			struct irq_affinity *desc);
> +			struct irq_affinity *desc,
> +			u32 sizes[]);
>  	void (*del_vqs)(struct virtio_device *);
>  	u64 (*get_features)(struct virtio_device *vdev);
>  	int (*finalize_features)(struct virtio_device *vdev);
> @@ -205,7 +207,7 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
>  	const char *names[] = { n };
>  	struct virtqueue *vq;
>  	int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
> -					 NULL);
> +					 NULL, NULL);
>  	if (err < 0)
>  		return ERR_PTR(err);
>  	return vq;
> @@ -217,7 +219,8 @@ int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
>  			const char * const names[],
>  			struct irq_affinity *desc)
>  {
> -	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
> +	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL,
> +				      desc, NULL);
>  }
>  
>  static inline
> @@ -227,7 +230,7 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
>  			struct irq_affinity *desc)
>  {
>  	return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
> -				      desc);
> +				      desc, NULL);
>  }
>  
>  /**
> -- 
> 2.31.0
> 

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-09  7:55     ` Jason Wang
  (?)
@ 2022-03-10  4:46       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  4:46 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 15:55:44 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > virtio ring supports reset.
> >
> > Queue reset is divided into several stages.
> >
> > 1. notify device queue reset
> > 2. vring release
> > 3. attach new vring
> > 4. notify device queue re-enable
> >
> > After the first step is completed, the vring reset operation can be
> > performed. If the newly set vring num does not change, then just reset
> > the vq related value.
> >
> > Otherwise, the vring will be released and the vring will be reallocated.
> > And the vring will be attached to the vq. If this process fails, the
> > function will exit, and the state of the vq will be the vring release
> > state. You can call this function again to reallocate the vring.
> >
> > In addition, vring_align, may_reduce_num are necessary for reallocating
> > vring, so they are retained when creating vq.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> >   1 file changed, 69 insertions(+)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index e0422c04c903..148fb1fd3d5a 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> >   			/* DMA address and size information */
> >   			dma_addr_t queue_dma_addr;
> >   			size_t queue_size_in_bytes;
> > +
> > +			/* The parameters for creating vrings are reserved for
> > +			 * creating new vrings when enabling reset queue.
> > +			 */
> > +			u32 vring_align;
> > +			bool may_reduce_num;
> >   		} split;
> >
> >   		/* Available for packed ring */
> > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> >   #endif
> >   };
> >
> > +static void vring_free(struct virtqueue *vq);
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev);
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring);
> >
> >   /*
> >    * Helpers.
> > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   		return NULL;
> >   	}
> >
> > +	to_vvq(vq)->split.vring_align = vring_align;
> > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> >   	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> >   	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >   	to_vvq(vq)->we_own_ring = true;
> > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   	return vq;
> >   }
> >
> > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > +{
>
>
> So what this function does is to resize the virtqueue actually, I
> suggest to rename it as virtqueue_resize_split().

In addition to resize, when num is 0, the function is to reinitialize vq ring
related variables. For example avail_idx_shadow.

So I think 'reset' is more appropriate.

Thanks.

>
>
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +	struct virtio_device *vdev = _vq->vdev;
> > +	struct vring_split vring;
> > +	int err;
> > +
> > +	if (num > _vq->num_max)
> > +		return -E2BIG;
> > +
> > +	switch (vq->vq.reset) {
> > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > +		return -ENOENT;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > +		if (vq->split.vring.num == num || !num)
> > +			break;
> > +
> > +		vring_free(_vq);
> > +
> > +		fallthrough;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > +		if (!num)
> > +			num = vq->split.vring.num;
> > +
> > +		err = vring_create_vring_split(&vring, vdev,
> > +					       vq->split.vring_align,
> > +					       vq->weak_barriers,
> > +					       vq->split.may_reduce_num, num);
> > +		if (err)
> > +			return -ENOMEM;
>
>
> We'd better need a safe fallback here like:
>
> If we can't allocate new memory, we can keep using the current one.
> Otherwise an ethtool -G fail may make the device not usable.
>
> This could be done by not freeing the old vring and virtqueue states
> until new is allocated.
>
>
> > +
> > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > +		if (err) {
> > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > +					 vring.queue,
> > +					 vring.dma_addr);
> > +			return -ENOMEM;
> > +		}
> > +
> > +		vq->split.queue_dma_addr = vring.dma_addr;
> > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > +	}
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> > +	vq->we_own_ring = true;
>
>
> This seems wrong, we have the transport (rproc/mlxtbf) that allocate the
> vring by themselves. I think we need to fail the resize for we_own_ring
> == false.
>
> Thanks
>
>
>
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > +
> > +	return 0;
> > +}
> > +
> >
> >   /*
> >    * Packed ring specific functions - *_packed().
> > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> >   static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> >   					 struct virtio_device *vdev)
> >   {
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> >   	vq->packed_ring = false;
> >   	vq->we_own_ring = false;
> >   	vq->broken = false;
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10  4:46       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  4:46 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 15:55:44 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > virtio ring supports reset.
> >
> > Queue reset is divided into several stages.
> >
> > 1. notify device queue reset
> > 2. vring release
> > 3. attach new vring
> > 4. notify device queue re-enable
> >
> > After the first step is completed, the vring reset operation can be
> > performed. If the newly set vring num does not change, then just reset
> > the vq related value.
> >
> > Otherwise, the vring will be released and the vring will be reallocated.
> > And the vring will be attached to the vq. If this process fails, the
> > function will exit, and the state of the vq will be the vring release
> > state. You can call this function again to reallocate the vring.
> >
> > In addition, vring_align, may_reduce_num are necessary for reallocating
> > vring, so they are retained when creating vq.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> >   1 file changed, 69 insertions(+)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index e0422c04c903..148fb1fd3d5a 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> >   			/* DMA address and size information */
> >   			dma_addr_t queue_dma_addr;
> >   			size_t queue_size_in_bytes;
> > +
> > +			/* The parameters for creating vrings are reserved for
> > +			 * creating new vrings when enabling reset queue.
> > +			 */
> > +			u32 vring_align;
> > +			bool may_reduce_num;
> >   		} split;
> >
> >   		/* Available for packed ring */
> > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> >   #endif
> >   };
> >
> > +static void vring_free(struct virtqueue *vq);
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev);
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring);
> >
> >   /*
> >    * Helpers.
> > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   		return NULL;
> >   	}
> >
> > +	to_vvq(vq)->split.vring_align = vring_align;
> > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> >   	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> >   	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >   	to_vvq(vq)->we_own_ring = true;
> > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   	return vq;
> >   }
> >
> > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > +{
>
>
> So what this function does is to resize the virtqueue actually, I
> suggest to rename it as virtqueue_resize_split().

In addition to resize, when num is 0, the function is to reinitialize vq ring
related variables. For example avail_idx_shadow.

So I think 'reset' is more appropriate.

Thanks.

>
>
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +	struct virtio_device *vdev = _vq->vdev;
> > +	struct vring_split vring;
> > +	int err;
> > +
> > +	if (num > _vq->num_max)
> > +		return -E2BIG;
> > +
> > +	switch (vq->vq.reset) {
> > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > +		return -ENOENT;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > +		if (vq->split.vring.num == num || !num)
> > +			break;
> > +
> > +		vring_free(_vq);
> > +
> > +		fallthrough;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > +		if (!num)
> > +			num = vq->split.vring.num;
> > +
> > +		err = vring_create_vring_split(&vring, vdev,
> > +					       vq->split.vring_align,
> > +					       vq->weak_barriers,
> > +					       vq->split.may_reduce_num, num);
> > +		if (err)
> > +			return -ENOMEM;
>
>
> We'd better need a safe fallback here like:
>
> If we can't allocate new memory, we can keep using the current one.
> Otherwise an ethtool -G fail may make the device not usable.
>
> This could be done by not freeing the old vring and virtqueue states
> until new is allocated.
>
>
> > +
> > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > +		if (err) {
> > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > +					 vring.queue,
> > +					 vring.dma_addr);
> > +			return -ENOMEM;
> > +		}
> > +
> > +		vq->split.queue_dma_addr = vring.dma_addr;
> > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > +	}
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> > +	vq->we_own_ring = true;
>
>
> This seems wrong, we have the transport (rproc/mlxtbf) that allocate the
> vring by themselves. I think we need to fail the resize for we_own_ring
> == false.
>
> Thanks
>
>
>
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > +
> > +	return 0;
> > +}
> > +
> >
> >   /*
> >    * Packed ring specific functions - *_packed().
> > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> >   static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> >   					 struct virtio_device *vdev)
> >   {
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> >   	vq->packed_ring = false;
> >   	vq->we_own_ring = false;
> >   	vq->broken = false;
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10  4:46       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  4:46 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 15:55:44 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > virtio ring supports reset.
> >
> > Queue reset is divided into several stages.
> >
> > 1. notify device queue reset
> > 2. vring release
> > 3. attach new vring
> > 4. notify device queue re-enable
> >
> > After the first step is completed, the vring reset operation can be
> > performed. If the newly set vring num does not change, then just reset
> > the vq related value.
> >
> > Otherwise, the vring will be released and the vring will be reallocated.
> > And the vring will be attached to the vq. If this process fails, the
> > function will exit, and the state of the vq will be the vring release
> > state. You can call this function again to reallocate the vring.
> >
> > In addition, vring_align, may_reduce_num are necessary for reallocating
> > vring, so they are retained when creating vq.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> >   1 file changed, 69 insertions(+)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index e0422c04c903..148fb1fd3d5a 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> >   			/* DMA address and size information */
> >   			dma_addr_t queue_dma_addr;
> >   			size_t queue_size_in_bytes;
> > +
> > +			/* The parameters for creating vrings are reserved for
> > +			 * creating new vrings when enabling reset queue.
> > +			 */
> > +			u32 vring_align;
> > +			bool may_reduce_num;
> >   		} split;
> >
> >   		/* Available for packed ring */
> > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> >   #endif
> >   };
> >
> > +static void vring_free(struct virtqueue *vq);
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev);
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring);
> >
> >   /*
> >    * Helpers.
> > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   		return NULL;
> >   	}
> >
> > +	to_vvq(vq)->split.vring_align = vring_align;
> > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> >   	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> >   	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >   	to_vvq(vq)->we_own_ring = true;
> > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> >   	return vq;
> >   }
> >
> > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > +{
>
>
> So what this function does is to resize the virtqueue actually, I
> suggest to rename it as virtqueue_resize_split().

In addition to resize, when num is 0, the function is to reinitialize vq ring
related variables. For example avail_idx_shadow.

So I think 'reset' is more appropriate.

Thanks.

>
>
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +	struct virtio_device *vdev = _vq->vdev;
> > +	struct vring_split vring;
> > +	int err;
> > +
> > +	if (num > _vq->num_max)
> > +		return -E2BIG;
> > +
> > +	switch (vq->vq.reset) {
> > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > +		return -ENOENT;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > +		if (vq->split.vring.num == num || !num)
> > +			break;
> > +
> > +		vring_free(_vq);
> > +
> > +		fallthrough;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > +		if (!num)
> > +			num = vq->split.vring.num;
> > +
> > +		err = vring_create_vring_split(&vring, vdev,
> > +					       vq->split.vring_align,
> > +					       vq->weak_barriers,
> > +					       vq->split.may_reduce_num, num);
> > +		if (err)
> > +			return -ENOMEM;
>
>
> We'd better need a safe fallback here like:
>
> If we can't allocate new memory, we can keep using the current one.
> Otherwise an ethtool -G fail may make the device not usable.
>
> This could be done by not freeing the old vring and virtqueue states
> until new is allocated.
>
>
> > +
> > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > +		if (err) {
> > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > +					 vring.queue,
> > +					 vring.dma_addr);
> > +			return -ENOMEM;
> > +		}
> > +
> > +		vq->split.queue_dma_addr = vring.dma_addr;
> > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > +	}
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> > +	vq->we_own_ring = true;
>
>
> This seems wrong, we have the transport (rproc/mlxtbf) that allocate the
> vring by themselves. I think we need to fail the resize for we_own_ring
> == false.
>
> Thanks
>
>
>
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > +
> > +	return 0;
> > +}
> > +
> >
> >   /*
> >    * Packed ring specific functions - *_packed().
> > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> >   static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> >   					 struct virtio_device *vdev)
> >   {
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> >   	vq->packed_ring = false;
> >   	vq->we_own_ring = false;
> >   	vq->broken = false;
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-08 12:35   ` Xuan Zhuo
  (?)
@ 2022-03-10  7:00     ` Michael S. Tsirkin
  -1 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10  7:00 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Vadim Pasternak, linux-remoteproc, Alexei Starovoitov,
	virtualization, Alexander Gordeev, Anton Ivanov, linux-s390,
	Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, platform-driver-x86, Jesper Dangaard Brouer,
	Vasily Gorbik, Jeff Dike, linux-um, Mark Gross, Hans de Goede,
	kvm, Bjorn Andersson, Mathieu Poirier, netdev, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> virtio ring supports reset.
> 
> Queue reset is divided into several stages.
> 
> 1. notify device queue reset
> 2. vring release
> 3. attach new vring
> 4. notify device queue re-enable
> 
> After the first step is completed, the vring reset operation can be
> performed. If the newly set vring num does not change, then just reset
> the vq related value.
> 
> Otherwise, the vring will be released and the vring will be reallocated.
> And the vring will be attached to the vq. If this process fails, the
> function will exit, and the state of the vq will be the vring release
> state. You can call this function again to reallocate the vring.
> 
> In addition, vring_align, may_reduce_num are necessary for reallocating
> vring, so they are retained when creating vq.
> 
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 69 insertions(+)
> 
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index e0422c04c903..148fb1fd3d5a 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -158,6 +158,12 @@ struct vring_virtqueue {
>  			/* DMA address and size information */
>  			dma_addr_t queue_dma_addr;
>  			size_t queue_size_in_bytes;
> +
> +			/* The parameters for creating vrings are reserved for
> +			 * creating new vrings when enabling reset queue.
> +			 */
> +			u32 vring_align;
> +			bool may_reduce_num;
>  		} split;
>  
>  		/* Available for packed ring */
> @@ -217,6 +223,12 @@ struct vring_virtqueue {
>  #endif
>  };
>  
> +static void vring_free(struct virtqueue *vq);
> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> +					 struct virtio_device *vdev);
> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> +					  struct virtio_device *vdev,
> +					  struct vring vring);
>  
>  /*
>   * Helpers.
> @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
>  		return NULL;
>  	}
>  
> +	to_vvq(vq)->split.vring_align = vring_align;
> +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
>  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
>  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>  	to_vvq(vq)->we_own_ring = true;
> @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
>  	return vq;
>  }
>  
> +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> +{
> +	struct vring_virtqueue *vq = to_vvq(_vq);
> +	struct virtio_device *vdev = _vq->vdev;
> +	struct vring_split vring;
> +	int err;
> +
> +	if (num > _vq->num_max)
> +		return -E2BIG;
> +
> +	switch (vq->vq.reset) {
> +	case VIRTIO_VQ_RESET_STEP_NONE:
> +		return -ENOENT;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> +		if (vq->split.vring.num == num || !num)
> +			break;
> +
> +		vring_free(_vq);
> +
> +		fallthrough;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> +		if (!num)
> +			num = vq->split.vring.num;
> +
> +		err = vring_create_vring_split(&vring, vdev,
> +					       vq->split.vring_align,
> +					       vq->weak_barriers,
> +					       vq->split.may_reduce_num, num);
> +		if (err)
> +			return -ENOMEM;
> +
> +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> +		if (err) {
> +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> +					 vring.queue,
> +					 vring.dma_addr);
> +			return -ENOMEM;
> +		}
> +
> +		vq->split.queue_dma_addr = vring.dma_addr;
> +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> +	}
> +
> +	__vring_virtqueue_init_split(vq, vdev);
> +	vq->we_own_ring = true;
> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> +
> +	return 0;
> +}
> +

I kind of dislike this state machine.

Hacks like special-casing num = 0 to mean "reset" are especially
confusing.

And as Jason points out, when we want a resize then yes this currently
implies reset but that is an implementation detail.

There should be a way to just make these cases separate functions
and then use them to compose consistent external APIs.

If we additionally want to track state for debugging then bool flags
seem more appropriate for this, though from experience that is
not always worth the extra code.



>  /*
>   * Packed ring specific functions - *_packed().
> @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>  					 struct virtio_device *vdev)
>  {
> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> +
>  	vq->packed_ring = false;
>  	vq->we_own_ring = false;
>  	vq->broken = false;
> -- 
> 2.31.0

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10  7:00     ` Michael S. Tsirkin
  0 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10  7:00 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> virtio ring supports reset.
> 
> Queue reset is divided into several stages.
> 
> 1. notify device queue reset
> 2. vring release
> 3. attach new vring
> 4. notify device queue re-enable
> 
> After the first step is completed, the vring reset operation can be
> performed. If the newly set vring num does not change, then just reset
> the vq related value.
> 
> Otherwise, the vring will be released and the vring will be reallocated.
> And the vring will be attached to the vq. If this process fails, the
> function will exit, and the state of the vq will be the vring release
> state. You can call this function again to reallocate the vring.
> 
> In addition, vring_align, may_reduce_num are necessary for reallocating
> vring, so they are retained when creating vq.
> 
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 69 insertions(+)
> 
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index e0422c04c903..148fb1fd3d5a 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -158,6 +158,12 @@ struct vring_virtqueue {
>  			/* DMA address and size information */
>  			dma_addr_t queue_dma_addr;
>  			size_t queue_size_in_bytes;
> +
> +			/* The parameters for creating vrings are reserved for
> +			 * creating new vrings when enabling reset queue.
> +			 */
> +			u32 vring_align;
> +			bool may_reduce_num;
>  		} split;
>  
>  		/* Available for packed ring */
> @@ -217,6 +223,12 @@ struct vring_virtqueue {
>  #endif
>  };
>  
> +static void vring_free(struct virtqueue *vq);
> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> +					 struct virtio_device *vdev);
> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> +					  struct virtio_device *vdev,
> +					  struct vring vring);
>  
>  /*
>   * Helpers.
> @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
>  		return NULL;
>  	}
>  
> +	to_vvq(vq)->split.vring_align = vring_align;
> +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
>  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
>  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>  	to_vvq(vq)->we_own_ring = true;
> @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
>  	return vq;
>  }
>  
> +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> +{
> +	struct vring_virtqueue *vq = to_vvq(_vq);
> +	struct virtio_device *vdev = _vq->vdev;
> +	struct vring_split vring;
> +	int err;
> +
> +	if (num > _vq->num_max)
> +		return -E2BIG;
> +
> +	switch (vq->vq.reset) {
> +	case VIRTIO_VQ_RESET_STEP_NONE:
> +		return -ENOENT;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> +		if (vq->split.vring.num == num || !num)
> +			break;
> +
> +		vring_free(_vq);
> +
> +		fallthrough;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> +		if (!num)
> +			num = vq->split.vring.num;
> +
> +		err = vring_create_vring_split(&vring, vdev,
> +					       vq->split.vring_align,
> +					       vq->weak_barriers,
> +					       vq->split.may_reduce_num, num);
> +		if (err)
> +			return -ENOMEM;
> +
> +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> +		if (err) {
> +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> +					 vring.queue,
> +					 vring.dma_addr);
> +			return -ENOMEM;
> +		}
> +
> +		vq->split.queue_dma_addr = vring.dma_addr;
> +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> +	}
> +
> +	__vring_virtqueue_init_split(vq, vdev);
> +	vq->we_own_ring = true;
> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> +
> +	return 0;
> +}
> +

I kind of dislike this state machine.

Hacks like special-casing num = 0 to mean "reset" are especially
confusing.

And as Jason points out, when we want a resize then yes this currently
implies reset but that is an implementation detail.

There should be a way to just make these cases separate functions
and then use them to compose consistent external APIs.

If we additionally want to track state for debugging then bool flags
seem more appropriate for this, though from experience that is
not always worth the extra code.



>  /*
>   * Packed ring specific functions - *_packed().
> @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>  					 struct virtio_device *vdev)
>  {
> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> +
>  	vq->packed_ring = false;
>  	vq->we_own_ring = false;
>  	vq->broken = false;
> -- 
> 2.31.0


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10  7:00     ` Michael S. Tsirkin
  0 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10  7:00 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> virtio ring supports reset.
> 
> Queue reset is divided into several stages.
> 
> 1. notify device queue reset
> 2. vring release
> 3. attach new vring
> 4. notify device queue re-enable
> 
> After the first step is completed, the vring reset operation can be
> performed. If the newly set vring num does not change, then just reset
> the vq related value.
> 
> Otherwise, the vring will be released and the vring will be reallocated.
> And the vring will be attached to the vq. If this process fails, the
> function will exit, and the state of the vq will be the vring release
> state. You can call this function again to reallocate the vring.
> 
> In addition, vring_align, may_reduce_num are necessary for reallocating
> vring, so they are retained when creating vq.
> 
> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> ---
>  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
>  1 file changed, 69 insertions(+)
> 
> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> index e0422c04c903..148fb1fd3d5a 100644
> --- a/drivers/virtio/virtio_ring.c
> +++ b/drivers/virtio/virtio_ring.c
> @@ -158,6 +158,12 @@ struct vring_virtqueue {
>  			/* DMA address and size information */
>  			dma_addr_t queue_dma_addr;
>  			size_t queue_size_in_bytes;
> +
> +			/* The parameters for creating vrings are reserved for
> +			 * creating new vrings when enabling reset queue.
> +			 */
> +			u32 vring_align;
> +			bool may_reduce_num;
>  		} split;
>  
>  		/* Available for packed ring */
> @@ -217,6 +223,12 @@ struct vring_virtqueue {
>  #endif
>  };
>  
> +static void vring_free(struct virtqueue *vq);
> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> +					 struct virtio_device *vdev);
> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> +					  struct virtio_device *vdev,
> +					  struct vring vring);
>  
>  /*
>   * Helpers.
> @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
>  		return NULL;
>  	}
>  
> +	to_vvq(vq)->split.vring_align = vring_align;
> +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
>  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
>  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>  	to_vvq(vq)->we_own_ring = true;
> @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
>  	return vq;
>  }
>  
> +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> +{
> +	struct vring_virtqueue *vq = to_vvq(_vq);
> +	struct virtio_device *vdev = _vq->vdev;
> +	struct vring_split vring;
> +	int err;
> +
> +	if (num > _vq->num_max)
> +		return -E2BIG;
> +
> +	switch (vq->vq.reset) {
> +	case VIRTIO_VQ_RESET_STEP_NONE:
> +		return -ENOENT;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> +		if (vq->split.vring.num == num || !num)
> +			break;
> +
> +		vring_free(_vq);
> +
> +		fallthrough;
> +
> +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> +		if (!num)
> +			num = vq->split.vring.num;
> +
> +		err = vring_create_vring_split(&vring, vdev,
> +					       vq->split.vring_align,
> +					       vq->weak_barriers,
> +					       vq->split.may_reduce_num, num);
> +		if (err)
> +			return -ENOMEM;
> +
> +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> +		if (err) {
> +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> +					 vring.queue,
> +					 vring.dma_addr);
> +			return -ENOMEM;
> +		}
> +
> +		vq->split.queue_dma_addr = vring.dma_addr;
> +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> +	}
> +
> +	__vring_virtqueue_init_split(vq, vdev);
> +	vq->we_own_ring = true;
> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> +
> +	return 0;
> +}
> +

I kind of dislike this state machine.

Hacks like special-casing num = 0 to mean "reset" are especially
confusing.

And as Jason points out, when we want a resize then yes this currently
implies reset but that is an implementation detail.

There should be a way to just make these cases separate functions
and then use them to compose consistent external APIs.

If we additionally want to track state for debugging then bool flags
seem more appropriate for this, though from experience that is
not always worth the extra code.



>  /*
>   * Packed ring specific functions - *_packed().
> @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>  					 struct virtio_device *vdev)
>  {
> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> +
>  	vq->packed_ring = false;
>  	vq->we_own_ring = false;
>  	vq->broken = false;
> -- 
> 2.31.0


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-10  7:00     ` Michael S. Tsirkin
  (?)
@ 2022-03-10  7:17       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  7:17 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > virtio ring supports reset.
> >
> > Queue reset is divided into several stages.
> >
> > 1. notify device queue reset
> > 2. vring release
> > 3. attach new vring
> > 4. notify device queue re-enable
> >
> > After the first step is completed, the vring reset operation can be
> > performed. If the newly set vring num does not change, then just reset
> > the vq related value.
> >
> > Otherwise, the vring will be released and the vring will be reallocated.
> > And the vring will be attached to the vq. If this process fails, the
> > function will exit, and the state of the vq will be the vring release
> > state. You can call this function again to reallocate the vring.
> >
> > In addition, vring_align, may_reduce_num are necessary for reallocating
> > vring, so they are retained when creating vq.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> >  1 file changed, 69 insertions(+)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index e0422c04c903..148fb1fd3d5a 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> >  			/* DMA address and size information */
> >  			dma_addr_t queue_dma_addr;
> >  			size_t queue_size_in_bytes;
> > +
> > +			/* The parameters for creating vrings are reserved for
> > +			 * creating new vrings when enabling reset queue.
> > +			 */
> > +			u32 vring_align;
> > +			bool may_reduce_num;
> >  		} split;
> >
> >  		/* Available for packed ring */
> > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> >  #endif
> >  };
> >
> > +static void vring_free(struct virtqueue *vq);
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev);
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring);
> >
> >  /*
> >   * Helpers.
> > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> >  		return NULL;
> >  	}
> >
> > +	to_vvq(vq)->split.vring_align = vring_align;
> > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >  	to_vvq(vq)->we_own_ring = true;
> > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> >  	return vq;
> >  }
> >
> > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > +{
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +	struct virtio_device *vdev = _vq->vdev;
> > +	struct vring_split vring;
> > +	int err;
> > +
> > +	if (num > _vq->num_max)
> > +		return -E2BIG;
> > +
> > +	switch (vq->vq.reset) {
> > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > +		return -ENOENT;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > +		if (vq->split.vring.num == num || !num)
> > +			break;
> > +
> > +		vring_free(_vq);
> > +
> > +		fallthrough;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > +		if (!num)
> > +			num = vq->split.vring.num;
> > +
> > +		err = vring_create_vring_split(&vring, vdev,
> > +					       vq->split.vring_align,
> > +					       vq->weak_barriers,
> > +					       vq->split.may_reduce_num, num);
> > +		if (err)
> > +			return -ENOMEM;
> > +
> > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > +		if (err) {
> > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > +					 vring.queue,
> > +					 vring.dma_addr);
> > +			return -ENOMEM;
> > +		}
> > +
> > +		vq->split.queue_dma_addr = vring.dma_addr;
> > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > +	}
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> > +	vq->we_own_ring = true;
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > +
> > +	return 0;
> > +}
> > +
>
> I kind of dislike this state machine.
>
> Hacks like special-casing num = 0 to mean "reset" are especially
> confusing.

I'm removing it. I'll say in the function description that this function is
currently only called when vq has been reset. I'm no longer checking it based on
state.

>
> And as Jason points out, when we want a resize then yes this currently
> implies reset but that is an implementation detail.
>
> There should be a way to just make these cases separate functions
> and then use them to compose consistent external APIs.

Yes, virtqueue_resize_split() is fine for ethtool -G.

But in the case of AF_XDP, just execute reset to free the buffer. The name
virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
to handle both scenarios?

Or can anyone think of a better name. ^_^

Thanks.

>
> If we additionally want to track state for debugging then bool flags
> seem more appropriate for this, though from experience that is
> not always worth the extra code.
>
>
>
> >  /*
> >   * Packed ring specific functions - *_packed().
> > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> >  					 struct virtio_device *vdev)
> >  {
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> >  	vq->packed_ring = false;
> >  	vq->we_own_ring = false;
> >  	vq->broken = false;
> > --
> > 2.31.0
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10  7:17       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  7:17 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Vadim Pasternak, linux-remoteproc, Alexei Starovoitov,
	virtualization, Alexander Gordeev, Anton Ivanov, linux-s390,
	Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, platform-driver-x86, Jesper Dangaard Brouer,
	Vasily Gorbik, Jeff Dike, linux-um, Mark Gross, Hans de Goede,
	kvm, Bjorn Andersson, Mathieu Poirier, netdev, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > virtio ring supports reset.
> >
> > Queue reset is divided into several stages.
> >
> > 1. notify device queue reset
> > 2. vring release
> > 3. attach new vring
> > 4. notify device queue re-enable
> >
> > After the first step is completed, the vring reset operation can be
> > performed. If the newly set vring num does not change, then just reset
> > the vq related value.
> >
> > Otherwise, the vring will be released and the vring will be reallocated.
> > And the vring will be attached to the vq. If this process fails, the
> > function will exit, and the state of the vq will be the vring release
> > state. You can call this function again to reallocate the vring.
> >
> > In addition, vring_align, may_reduce_num are necessary for reallocating
> > vring, so they are retained when creating vq.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> >  1 file changed, 69 insertions(+)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index e0422c04c903..148fb1fd3d5a 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> >  			/* DMA address and size information */
> >  			dma_addr_t queue_dma_addr;
> >  			size_t queue_size_in_bytes;
> > +
> > +			/* The parameters for creating vrings are reserved for
> > +			 * creating new vrings when enabling reset queue.
> > +			 */
> > +			u32 vring_align;
> > +			bool may_reduce_num;
> >  		} split;
> >
> >  		/* Available for packed ring */
> > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> >  #endif
> >  };
> >
> > +static void vring_free(struct virtqueue *vq);
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev);
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring);
> >
> >  /*
> >   * Helpers.
> > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> >  		return NULL;
> >  	}
> >
> > +	to_vvq(vq)->split.vring_align = vring_align;
> > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >  	to_vvq(vq)->we_own_ring = true;
> > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> >  	return vq;
> >  }
> >
> > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > +{
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +	struct virtio_device *vdev = _vq->vdev;
> > +	struct vring_split vring;
> > +	int err;
> > +
> > +	if (num > _vq->num_max)
> > +		return -E2BIG;
> > +
> > +	switch (vq->vq.reset) {
> > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > +		return -ENOENT;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > +		if (vq->split.vring.num == num || !num)
> > +			break;
> > +
> > +		vring_free(_vq);
> > +
> > +		fallthrough;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > +		if (!num)
> > +			num = vq->split.vring.num;
> > +
> > +		err = vring_create_vring_split(&vring, vdev,
> > +					       vq->split.vring_align,
> > +					       vq->weak_barriers,
> > +					       vq->split.may_reduce_num, num);
> > +		if (err)
> > +			return -ENOMEM;
> > +
> > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > +		if (err) {
> > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > +					 vring.queue,
> > +					 vring.dma_addr);
> > +			return -ENOMEM;
> > +		}
> > +
> > +		vq->split.queue_dma_addr = vring.dma_addr;
> > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > +	}
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> > +	vq->we_own_ring = true;
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > +
> > +	return 0;
> > +}
> > +
>
> I kind of dislike this state machine.
>
> Hacks like special-casing num = 0 to mean "reset" are especially
> confusing.

I'm removing it. I'll say in the function description that this function is
currently only called when vq has been reset. I'm no longer checking it based on
state.

>
> And as Jason points out, when we want a resize then yes this currently
> implies reset but that is an implementation detail.
>
> There should be a way to just make these cases separate functions
> and then use them to compose consistent external APIs.

Yes, virtqueue_resize_split() is fine for ethtool -G.

But in the case of AF_XDP, just execute reset to free the buffer. The name
virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
to handle both scenarios?

Or can anyone think of a better name. ^_^

Thanks.

>
> If we additionally want to track state for debugging then bool flags
> seem more appropriate for this, though from experience that is
> not always worth the extra code.
>
>
>
> >  /*
> >   * Packed ring specific functions - *_packed().
> > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> >  					 struct virtio_device *vdev)
> >  {
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> >  	vq->packed_ring = false;
> >  	vq->we_own_ring = false;
> >  	vq->broken = false;
> > --
> > 2.31.0
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10  7:17       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  7:17 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > virtio ring supports reset.
> >
> > Queue reset is divided into several stages.
> >
> > 1. notify device queue reset
> > 2. vring release
> > 3. attach new vring
> > 4. notify device queue re-enable
> >
> > After the first step is completed, the vring reset operation can be
> > performed. If the newly set vring num does not change, then just reset
> > the vq related value.
> >
> > Otherwise, the vring will be released and the vring will be reallocated.
> > And the vring will be attached to the vq. If this process fails, the
> > function will exit, and the state of the vq will be the vring release
> > state. You can call this function again to reallocate the vring.
> >
> > In addition, vring_align, may_reduce_num are necessary for reallocating
> > vring, so they are retained when creating vq.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> >  1 file changed, 69 insertions(+)
> >
> > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > index e0422c04c903..148fb1fd3d5a 100644
> > --- a/drivers/virtio/virtio_ring.c
> > +++ b/drivers/virtio/virtio_ring.c
> > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> >  			/* DMA address and size information */
> >  			dma_addr_t queue_dma_addr;
> >  			size_t queue_size_in_bytes;
> > +
> > +			/* The parameters for creating vrings are reserved for
> > +			 * creating new vrings when enabling reset queue.
> > +			 */
> > +			u32 vring_align;
> > +			bool may_reduce_num;
> >  		} split;
> >
> >  		/* Available for packed ring */
> > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> >  #endif
> >  };
> >
> > +static void vring_free(struct virtqueue *vq);
> > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > +					 struct virtio_device *vdev);
> > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > +					  struct virtio_device *vdev,
> > +					  struct vring vring);
> >
> >  /*
> >   * Helpers.
> > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> >  		return NULL;
> >  	}
> >
> > +	to_vvq(vq)->split.vring_align = vring_align;
> > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> >  	to_vvq(vq)->we_own_ring = true;
> > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> >  	return vq;
> >  }
> >
> > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > +{
> > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > +	struct virtio_device *vdev = _vq->vdev;
> > +	struct vring_split vring;
> > +	int err;
> > +
> > +	if (num > _vq->num_max)
> > +		return -E2BIG;
> > +
> > +	switch (vq->vq.reset) {
> > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > +		return -ENOENT;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > +		if (vq->split.vring.num == num || !num)
> > +			break;
> > +
> > +		vring_free(_vq);
> > +
> > +		fallthrough;
> > +
> > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > +		if (!num)
> > +			num = vq->split.vring.num;
> > +
> > +		err = vring_create_vring_split(&vring, vdev,
> > +					       vq->split.vring_align,
> > +					       vq->weak_barriers,
> > +					       vq->split.may_reduce_num, num);
> > +		if (err)
> > +			return -ENOMEM;
> > +
> > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > +		if (err) {
> > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > +					 vring.queue,
> > +					 vring.dma_addr);
> > +			return -ENOMEM;
> > +		}
> > +
> > +		vq->split.queue_dma_addr = vring.dma_addr;
> > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > +	}
> > +
> > +	__vring_virtqueue_init_split(vq, vdev);
> > +	vq->we_own_ring = true;
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > +
> > +	return 0;
> > +}
> > +
>
> I kind of dislike this state machine.
>
> Hacks like special-casing num = 0 to mean "reset" are especially
> confusing.

I'm removing it. I'll say in the function description that this function is
currently only called when vq has been reset. I'm no longer checking it based on
state.

>
> And as Jason points out, when we want a resize then yes this currently
> implies reset but that is an implementation detail.
>
> There should be a way to just make these cases separate functions
> and then use them to compose consistent external APIs.

Yes, virtqueue_resize_split() is fine for ethtool -G.

But in the case of AF_XDP, just execute reset to free the buffer. The name
virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
to handle both scenarios?

Or can anyone think of a better name. ^_^

Thanks.

>
> If we additionally want to track state for debugging then bool flags
> seem more appropriate for this, though from experience that is
> not always worth the extra code.
>
>
>
> >  /*
> >   * Packed ring specific functions - *_packed().
> > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> >  					 struct virtio_device *vdev)
> >  {
> > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > +
> >  	vq->packed_ring = false;
> >  	vq->we_own_ring = false;
> >  	vq->broken = false;
> > --
> > 2.31.0
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-10  7:17       ` Xuan Zhuo
  (?)
@ 2022-03-10  8:07         ` Michael S. Tsirkin
  -1 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10  8:07 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > virtio ring supports reset.
> > >
> > > Queue reset is divided into several stages.
> > >
> > > 1. notify device queue reset
> > > 2. vring release
> > > 3. attach new vring
> > > 4. notify device queue re-enable
> > >
> > > After the first step is completed, the vring reset operation can be
> > > performed. If the newly set vring num does not change, then just reset
> > > the vq related value.
> > >
> > > Otherwise, the vring will be released and the vring will be reallocated.
> > > And the vring will be attached to the vq. If this process fails, the
> > > function will exit, and the state of the vq will be the vring release
> > > state. You can call this function again to reallocate the vring.
> > >
> > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > vring, so they are retained when creating vq.
> > >
> > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > ---
> > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 69 insertions(+)
> > >
> > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > index e0422c04c903..148fb1fd3d5a 100644
> > > --- a/drivers/virtio/virtio_ring.c
> > > +++ b/drivers/virtio/virtio_ring.c
> > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > >  			/* DMA address and size information */
> > >  			dma_addr_t queue_dma_addr;
> > >  			size_t queue_size_in_bytes;
> > > +
> > > +			/* The parameters for creating vrings are reserved for
> > > +			 * creating new vrings when enabling reset queue.
> > > +			 */
> > > +			u32 vring_align;
> > > +			bool may_reduce_num;
> > >  		} split;
> > >
> > >  		/* Available for packed ring */
> > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > >  #endif
> > >  };
> > >
> > > +static void vring_free(struct virtqueue *vq);
> > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > +					 struct virtio_device *vdev);
> > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > +					  struct virtio_device *vdev,
> > > +					  struct vring vring);
> > >
> > >  /*
> > >   * Helpers.
> > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > >  		return NULL;
> > >  	}
> > >
> > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > >  	to_vvq(vq)->we_own_ring = true;
> > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > >  	return vq;
> > >  }
> > >
> > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > +{
> > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > +	struct virtio_device *vdev = _vq->vdev;
> > > +	struct vring_split vring;
> > > +	int err;
> > > +
> > > +	if (num > _vq->num_max)
> > > +		return -E2BIG;
> > > +
> > > +	switch (vq->vq.reset) {
> > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > +		return -ENOENT;
> > > +
> > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > +		if (vq->split.vring.num == num || !num)
> > > +			break;
> > > +
> > > +		vring_free(_vq);
> > > +
> > > +		fallthrough;
> > > +
> > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > +		if (!num)
> > > +			num = vq->split.vring.num;
> > > +
> > > +		err = vring_create_vring_split(&vring, vdev,
> > > +					       vq->split.vring_align,
> > > +					       vq->weak_barriers,
> > > +					       vq->split.may_reduce_num, num);
> > > +		if (err)
> > > +			return -ENOMEM;
> > > +
> > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > +		if (err) {
> > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > +					 vring.queue,
> > > +					 vring.dma_addr);
> > > +			return -ENOMEM;
> > > +		}
> > > +
> > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > +	}
> > > +
> > > +	__vring_virtqueue_init_split(vq, vdev);
> > > +	vq->we_own_ring = true;
> > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > +
> > > +	return 0;
> > > +}
> > > +
> >
> > I kind of dislike this state machine.
> >
> > Hacks like special-casing num = 0 to mean "reset" are especially
> > confusing.
> 
> I'm removing it. I'll say in the function description that this function is
> currently only called when vq has been reset. I'm no longer checking it based on
> state.
> 
> >
> > And as Jason points out, when we want a resize then yes this currently
> > implies reset but that is an implementation detail.
> >
> > There should be a way to just make these cases separate functions
> > and then use them to compose consistent external APIs.
> 
> Yes, virtqueue_resize_split() is fine for ethtool -G.
> 
> But in the case of AF_XDP, just execute reset to free the buffer. The name
> virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> to handle both scenarios?
> 
> Or can anyone think of a better name. ^_^
> 
> Thanks.


I'd say resize should be called resize and reset should be called reset.

The big issue is a sane API for resize. Ideally it would resubmit
buffers which did not get used. Question is what to do
about buffers which don't fit (if ring has been downsized)?
Maybe a callback that will handle them?
And then what? Queue them up and readd later? Drop?
If we drop we should drop from the head not the tail ...


> >
> > If we additionally want to track state for debugging then bool flags
> > seem more appropriate for this, though from experience that is
> > not always worth the extra code.
> >
> >
> >
> > >  /*
> > >   * Packed ring specific functions - *_packed().
> > > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > >  					 struct virtio_device *vdev)
> > >  {
> > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > > +
> > >  	vq->packed_ring = false;
> > >  	vq->we_own_ring = false;
> > >  	vq->broken = false;
> > > --
> > > 2.31.0
> >


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10  8:07         ` Michael S. Tsirkin
  0 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10  8:07 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Vadim Pasternak, linux-remoteproc, Alexei Starovoitov,
	virtualization, Alexander Gordeev, Anton Ivanov, linux-s390,
	Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, platform-driver-x86, Jesper Dangaard Brouer,
	Vasily Gorbik, Jeff Dike, linux-um, Mark Gross, Hans de Goede,
	kvm, Bjorn Andersson, Mathieu Poirier, netdev, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > virtio ring supports reset.
> > >
> > > Queue reset is divided into several stages.
> > >
> > > 1. notify device queue reset
> > > 2. vring release
> > > 3. attach new vring
> > > 4. notify device queue re-enable
> > >
> > > After the first step is completed, the vring reset operation can be
> > > performed. If the newly set vring num does not change, then just reset
> > > the vq related value.
> > >
> > > Otherwise, the vring will be released and the vring will be reallocated.
> > > And the vring will be attached to the vq. If this process fails, the
> > > function will exit, and the state of the vq will be the vring release
> > > state. You can call this function again to reallocate the vring.
> > >
> > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > vring, so they are retained when creating vq.
> > >
> > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > ---
> > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 69 insertions(+)
> > >
> > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > index e0422c04c903..148fb1fd3d5a 100644
> > > --- a/drivers/virtio/virtio_ring.c
> > > +++ b/drivers/virtio/virtio_ring.c
> > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > >  			/* DMA address and size information */
> > >  			dma_addr_t queue_dma_addr;
> > >  			size_t queue_size_in_bytes;
> > > +
> > > +			/* The parameters for creating vrings are reserved for
> > > +			 * creating new vrings when enabling reset queue.
> > > +			 */
> > > +			u32 vring_align;
> > > +			bool may_reduce_num;
> > >  		} split;
> > >
> > >  		/* Available for packed ring */
> > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > >  #endif
> > >  };
> > >
> > > +static void vring_free(struct virtqueue *vq);
> > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > +					 struct virtio_device *vdev);
> > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > +					  struct virtio_device *vdev,
> > > +					  struct vring vring);
> > >
> > >  /*
> > >   * Helpers.
> > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > >  		return NULL;
> > >  	}
> > >
> > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > >  	to_vvq(vq)->we_own_ring = true;
> > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > >  	return vq;
> > >  }
> > >
> > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > +{
> > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > +	struct virtio_device *vdev = _vq->vdev;
> > > +	struct vring_split vring;
> > > +	int err;
> > > +
> > > +	if (num > _vq->num_max)
> > > +		return -E2BIG;
> > > +
> > > +	switch (vq->vq.reset) {
> > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > +		return -ENOENT;
> > > +
> > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > +		if (vq->split.vring.num == num || !num)
> > > +			break;
> > > +
> > > +		vring_free(_vq);
> > > +
> > > +		fallthrough;
> > > +
> > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > +		if (!num)
> > > +			num = vq->split.vring.num;
> > > +
> > > +		err = vring_create_vring_split(&vring, vdev,
> > > +					       vq->split.vring_align,
> > > +					       vq->weak_barriers,
> > > +					       vq->split.may_reduce_num, num);
> > > +		if (err)
> > > +			return -ENOMEM;
> > > +
> > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > +		if (err) {
> > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > +					 vring.queue,
> > > +					 vring.dma_addr);
> > > +			return -ENOMEM;
> > > +		}
> > > +
> > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > +	}
> > > +
> > > +	__vring_virtqueue_init_split(vq, vdev);
> > > +	vq->we_own_ring = true;
> > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > +
> > > +	return 0;
> > > +}
> > > +
> >
> > I kind of dislike this state machine.
> >
> > Hacks like special-casing num = 0 to mean "reset" are especially
> > confusing.
> 
> I'm removing it. I'll say in the function description that this function is
> currently only called when vq has been reset. I'm no longer checking it based on
> state.
> 
> >
> > And as Jason points out, when we want a resize then yes this currently
> > implies reset but that is an implementation detail.
> >
> > There should be a way to just make these cases separate functions
> > and then use them to compose consistent external APIs.
> 
> Yes, virtqueue_resize_split() is fine for ethtool -G.
> 
> But in the case of AF_XDP, just execute reset to free the buffer. The name
> virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> to handle both scenarios?
> 
> Or can anyone think of a better name. ^_^
> 
> Thanks.


I'd say resize should be called resize and reset should be called reset.

The big issue is a sane API for resize. Ideally it would resubmit
buffers which did not get used. Question is what to do
about buffers which don't fit (if ring has been downsized)?
Maybe a callback that will handle them?
And then what? Queue them up and readd later? Drop?
If we drop we should drop from the head not the tail ...


> >
> > If we additionally want to track state for debugging then bool flags
> > seem more appropriate for this, though from experience that is
> > not always worth the extra code.
> >
> >
> >
> > >  /*
> > >   * Packed ring specific functions - *_packed().
> > > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > >  					 struct virtio_device *vdev)
> > >  {
> > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > > +
> > >  	vq->packed_ring = false;
> > >  	vq->we_own_ring = false;
> > >  	vq->broken = false;
> > > --
> > > 2.31.0
> >

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10  8:07         ` Michael S. Tsirkin
  0 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10  8:07 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > virtio ring supports reset.
> > >
> > > Queue reset is divided into several stages.
> > >
> > > 1. notify device queue reset
> > > 2. vring release
> > > 3. attach new vring
> > > 4. notify device queue re-enable
> > >
> > > After the first step is completed, the vring reset operation can be
> > > performed. If the newly set vring num does not change, then just reset
> > > the vq related value.
> > >
> > > Otherwise, the vring will be released and the vring will be reallocated.
> > > And the vring will be attached to the vq. If this process fails, the
> > > function will exit, and the state of the vq will be the vring release
> > > state. You can call this function again to reallocate the vring.
> > >
> > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > vring, so they are retained when creating vq.
> > >
> > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > ---
> > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > >  1 file changed, 69 insertions(+)
> > >
> > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > index e0422c04c903..148fb1fd3d5a 100644
> > > --- a/drivers/virtio/virtio_ring.c
> > > +++ b/drivers/virtio/virtio_ring.c
> > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > >  			/* DMA address and size information */
> > >  			dma_addr_t queue_dma_addr;
> > >  			size_t queue_size_in_bytes;
> > > +
> > > +			/* The parameters for creating vrings are reserved for
> > > +			 * creating new vrings when enabling reset queue.
> > > +			 */
> > > +			u32 vring_align;
> > > +			bool may_reduce_num;
> > >  		} split;
> > >
> > >  		/* Available for packed ring */
> > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > >  #endif
> > >  };
> > >
> > > +static void vring_free(struct virtqueue *vq);
> > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > +					 struct virtio_device *vdev);
> > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > +					  struct virtio_device *vdev,
> > > +					  struct vring vring);
> > >
> > >  /*
> > >   * Helpers.
> > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > >  		return NULL;
> > >  	}
> > >
> > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > >  	to_vvq(vq)->we_own_ring = true;
> > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > >  	return vq;
> > >  }
> > >
> > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > +{
> > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > +	struct virtio_device *vdev = _vq->vdev;
> > > +	struct vring_split vring;
> > > +	int err;
> > > +
> > > +	if (num > _vq->num_max)
> > > +		return -E2BIG;
> > > +
> > > +	switch (vq->vq.reset) {
> > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > +		return -ENOENT;
> > > +
> > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > +		if (vq->split.vring.num == num || !num)
> > > +			break;
> > > +
> > > +		vring_free(_vq);
> > > +
> > > +		fallthrough;
> > > +
> > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > +		if (!num)
> > > +			num = vq->split.vring.num;
> > > +
> > > +		err = vring_create_vring_split(&vring, vdev,
> > > +					       vq->split.vring_align,
> > > +					       vq->weak_barriers,
> > > +					       vq->split.may_reduce_num, num);
> > > +		if (err)
> > > +			return -ENOMEM;
> > > +
> > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > +		if (err) {
> > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > +					 vring.queue,
> > > +					 vring.dma_addr);
> > > +			return -ENOMEM;
> > > +		}
> > > +
> > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > +	}
> > > +
> > > +	__vring_virtqueue_init_split(vq, vdev);
> > > +	vq->we_own_ring = true;
> > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > +
> > > +	return 0;
> > > +}
> > > +
> >
> > I kind of dislike this state machine.
> >
> > Hacks like special-casing num = 0 to mean "reset" are especially
> > confusing.
> 
> I'm removing it. I'll say in the function description that this function is
> currently only called when vq has been reset. I'm no longer checking it based on
> state.
> 
> >
> > And as Jason points out, when we want a resize then yes this currently
> > implies reset but that is an implementation detail.
> >
> > There should be a way to just make these cases separate functions
> > and then use them to compose consistent external APIs.
> 
> Yes, virtqueue_resize_split() is fine for ethtool -G.
> 
> But in the case of AF_XDP, just execute reset to free the buffer. The name
> virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> to handle both scenarios?
> 
> Or can anyone think of a better name. ^_^
> 
> Thanks.


I'd say resize should be called resize and reset should be called reset.

The big issue is a sane API for resize. Ideally it would resubmit
buffers which did not get used. Question is what to do
about buffers which don't fit (if ring has been downsized)?
Maybe a callback that will handle them?
And then what? Queue them up and readd later? Drop?
If we drop we should drop from the head not the tail ...


> >
> > If we additionally want to track state for debugging then bool flags
> > seem more appropriate for this, though from experience that is
> > not always worth the extra code.
> >
> >
> >
> > >  /*
> > >   * Packed ring specific functions - *_packed().
> > > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > >  					 struct virtio_device *vdev)
> > >  {
> > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > > +
> > >  	vq->packed_ring = false;
> > >  	vq->we_own_ring = false;
> > >  	vq->broken = false;
> > > --
> > > 2.31.0
> >


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-10  8:07         ` Michael S. Tsirkin
  (?)
@ 2022-03-10  8:14           ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  8:14 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > virtio ring supports reset.
> > > >
> > > > Queue reset is divided into several stages.
> > > >
> > > > 1. notify device queue reset
> > > > 2. vring release
> > > > 3. attach new vring
> > > > 4. notify device queue re-enable
> > > >
> > > > After the first step is completed, the vring reset operation can be
> > > > performed. If the newly set vring num does not change, then just reset
> > > > the vq related value.
> > > >
> > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > And the vring will be attached to the vq. If this process fails, the
> > > > function will exit, and the state of the vq will be the vring release
> > > > state. You can call this function again to reallocate the vring.
> > > >
> > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > vring, so they are retained when creating vq.
> > > >
> > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > ---
> > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > >  1 file changed, 69 insertions(+)
> > > >
> > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > --- a/drivers/virtio/virtio_ring.c
> > > > +++ b/drivers/virtio/virtio_ring.c
> > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > >  			/* DMA address and size information */
> > > >  			dma_addr_t queue_dma_addr;
> > > >  			size_t queue_size_in_bytes;
> > > > +
> > > > +			/* The parameters for creating vrings are reserved for
> > > > +			 * creating new vrings when enabling reset queue.
> > > > +			 */
> > > > +			u32 vring_align;
> > > > +			bool may_reduce_num;
> > > >  		} split;
> > > >
> > > >  		/* Available for packed ring */
> > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > >  #endif
> > > >  };
> > > >
> > > > +static void vring_free(struct virtqueue *vq);
> > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > +					 struct virtio_device *vdev);
> > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > +					  struct virtio_device *vdev,
> > > > +					  struct vring vring);
> > > >
> > > >  /*
> > > >   * Helpers.
> > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > >  		return NULL;
> > > >  	}
> > > >
> > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > >  	to_vvq(vq)->we_own_ring = true;
> > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > >  	return vq;
> > > >  }
> > > >
> > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > +{
> > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > +	struct vring_split vring;
> > > > +	int err;
> > > > +
> > > > +	if (num > _vq->num_max)
> > > > +		return -E2BIG;
> > > > +
> > > > +	switch (vq->vq.reset) {
> > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > +		return -ENOENT;
> > > > +
> > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > +		if (vq->split.vring.num == num || !num)
> > > > +			break;
> > > > +
> > > > +		vring_free(_vq);
> > > > +
> > > > +		fallthrough;
> > > > +
> > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > +		if (!num)
> > > > +			num = vq->split.vring.num;
> > > > +
> > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > +					       vq->split.vring_align,
> > > > +					       vq->weak_barriers,
> > > > +					       vq->split.may_reduce_num, num);
> > > > +		if (err)
> > > > +			return -ENOMEM;
> > > > +
> > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > +		if (err) {
> > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > +					 vring.queue,
> > > > +					 vring.dma_addr);
> > > > +			return -ENOMEM;
> > > > +		}
> > > > +
> > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > +	}
> > > > +
> > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > +	vq->we_own_ring = true;
> > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > >
> > > I kind of dislike this state machine.
> > >
> > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > confusing.
> >
> > I'm removing it. I'll say in the function description that this function is
> > currently only called when vq has been reset. I'm no longer checking it based on
> > state.
> >
> > >
> > > And as Jason points out, when we want a resize then yes this currently
> > > implies reset but that is an implementation detail.
> > >
> > > There should be a way to just make these cases separate functions
> > > and then use them to compose consistent external APIs.
> >
> > Yes, virtqueue_resize_split() is fine for ethtool -G.
> >
> > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > to handle both scenarios?
> >
> > Or can anyone think of a better name. ^_^
> >
> > Thanks.
>
>
> I'd say resize should be called resize and reset should be called reset.


OK, I'll change it to resize here.

But I want to know that when I implement virtio-net to support AF_XDP, its
requirement is to release all submitted buffers. Then should I add a new api
such as virtqueue_reset_vring()?

>
> The big issue is a sane API for resize. Ideally it would resubmit
> buffers which did not get used. Question is what to do
> about buffers which don't fit (if ring has been downsized)?
> Maybe a callback that will handle them?
> And then what? Queue them up and readd later? Drop?
> If we drop we should drop from the head not the tail ...

It's a good idea, let's implement it later.

Thanks.

>
>
> > >
> > > If we additionally want to track state for debugging then bool flags
> > > seem more appropriate for this, though from experience that is
> > > not always worth the extra code.
> > >
> > >
> > >
> > > >  /*
> > > >   * Packed ring specific functions - *_packed().
> > > > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > >  					 struct virtio_device *vdev)
> > > >  {
> > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > > > +
> > > >  	vq->packed_ring = false;
> > > >  	vq->we_own_ring = false;
> > > >  	vq->broken = false;
> > > > --
> > > > 2.31.0
> > >
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10  8:14           ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  8:14 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Vadim Pasternak, linux-remoteproc, Alexei Starovoitov,
	virtualization, Alexander Gordeev, Anton Ivanov, linux-s390,
	Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, platform-driver-x86, Jesper Dangaard Brouer,
	Vasily Gorbik, Jeff Dike, linux-um, Mark Gross, Hans de Goede,
	kvm, Bjorn Andersson, Mathieu Poirier, netdev, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > virtio ring supports reset.
> > > >
> > > > Queue reset is divided into several stages.
> > > >
> > > > 1. notify device queue reset
> > > > 2. vring release
> > > > 3. attach new vring
> > > > 4. notify device queue re-enable
> > > >
> > > > After the first step is completed, the vring reset operation can be
> > > > performed. If the newly set vring num does not change, then just reset
> > > > the vq related value.
> > > >
> > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > And the vring will be attached to the vq. If this process fails, the
> > > > function will exit, and the state of the vq will be the vring release
> > > > state. You can call this function again to reallocate the vring.
> > > >
> > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > vring, so they are retained when creating vq.
> > > >
> > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > ---
> > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > >  1 file changed, 69 insertions(+)
> > > >
> > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > --- a/drivers/virtio/virtio_ring.c
> > > > +++ b/drivers/virtio/virtio_ring.c
> > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > >  			/* DMA address and size information */
> > > >  			dma_addr_t queue_dma_addr;
> > > >  			size_t queue_size_in_bytes;
> > > > +
> > > > +			/* The parameters for creating vrings are reserved for
> > > > +			 * creating new vrings when enabling reset queue.
> > > > +			 */
> > > > +			u32 vring_align;
> > > > +			bool may_reduce_num;
> > > >  		} split;
> > > >
> > > >  		/* Available for packed ring */
> > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > >  #endif
> > > >  };
> > > >
> > > > +static void vring_free(struct virtqueue *vq);
> > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > +					 struct virtio_device *vdev);
> > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > +					  struct virtio_device *vdev,
> > > > +					  struct vring vring);
> > > >
> > > >  /*
> > > >   * Helpers.
> > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > >  		return NULL;
> > > >  	}
> > > >
> > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > >  	to_vvq(vq)->we_own_ring = true;
> > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > >  	return vq;
> > > >  }
> > > >
> > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > +{
> > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > +	struct vring_split vring;
> > > > +	int err;
> > > > +
> > > > +	if (num > _vq->num_max)
> > > > +		return -E2BIG;
> > > > +
> > > > +	switch (vq->vq.reset) {
> > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > +		return -ENOENT;
> > > > +
> > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > +		if (vq->split.vring.num == num || !num)
> > > > +			break;
> > > > +
> > > > +		vring_free(_vq);
> > > > +
> > > > +		fallthrough;
> > > > +
> > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > +		if (!num)
> > > > +			num = vq->split.vring.num;
> > > > +
> > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > +					       vq->split.vring_align,
> > > > +					       vq->weak_barriers,
> > > > +					       vq->split.may_reduce_num, num);
> > > > +		if (err)
> > > > +			return -ENOMEM;
> > > > +
> > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > +		if (err) {
> > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > +					 vring.queue,
> > > > +					 vring.dma_addr);
> > > > +			return -ENOMEM;
> > > > +		}
> > > > +
> > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > +	}
> > > > +
> > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > +	vq->we_own_ring = true;
> > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > >
> > > I kind of dislike this state machine.
> > >
> > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > confusing.
> >
> > I'm removing it. I'll say in the function description that this function is
> > currently only called when vq has been reset. I'm no longer checking it based on
> > state.
> >
> > >
> > > And as Jason points out, when we want a resize then yes this currently
> > > implies reset but that is an implementation detail.
> > >
> > > There should be a way to just make these cases separate functions
> > > and then use them to compose consistent external APIs.
> >
> > Yes, virtqueue_resize_split() is fine for ethtool -G.
> >
> > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > to handle both scenarios?
> >
> > Or can anyone think of a better name. ^_^
> >
> > Thanks.
>
>
> I'd say resize should be called resize and reset should be called reset.


OK, I'll change it to resize here.

But I want to know that when I implement virtio-net to support AF_XDP, its
requirement is to release all submitted buffers. Then should I add a new api
such as virtqueue_reset_vring()?

>
> The big issue is a sane API for resize. Ideally it would resubmit
> buffers which did not get used. Question is what to do
> about buffers which don't fit (if ring has been downsized)?
> Maybe a callback that will handle them?
> And then what? Queue them up and readd later? Drop?
> If we drop we should drop from the head not the tail ...

It's a good idea, let's implement it later.

Thanks.

>
>
> > >
> > > If we additionally want to track state for debugging then bool flags
> > > seem more appropriate for this, though from experience that is
> > > not always worth the extra code.
> > >
> > >
> > >
> > > >  /*
> > > >   * Packed ring specific functions - *_packed().
> > > > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > >  					 struct virtio_device *vdev)
> > > >  {
> > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > > > +
> > > >  	vq->packed_ring = false;
> > > >  	vq->we_own_ring = false;
> > > >  	vq->broken = false;
> > > > --
> > > > 2.31.0
> > >
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10  8:14           ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  8:14 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > virtio ring supports reset.
> > > >
> > > > Queue reset is divided into several stages.
> > > >
> > > > 1. notify device queue reset
> > > > 2. vring release
> > > > 3. attach new vring
> > > > 4. notify device queue re-enable
> > > >
> > > > After the first step is completed, the vring reset operation can be
> > > > performed. If the newly set vring num does not change, then just reset
> > > > the vq related value.
> > > >
> > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > And the vring will be attached to the vq. If this process fails, the
> > > > function will exit, and the state of the vq will be the vring release
> > > > state. You can call this function again to reallocate the vring.
> > > >
> > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > vring, so they are retained when creating vq.
> > > >
> > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > ---
> > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > >  1 file changed, 69 insertions(+)
> > > >
> > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > --- a/drivers/virtio/virtio_ring.c
> > > > +++ b/drivers/virtio/virtio_ring.c
> > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > >  			/* DMA address and size information */
> > > >  			dma_addr_t queue_dma_addr;
> > > >  			size_t queue_size_in_bytes;
> > > > +
> > > > +			/* The parameters for creating vrings are reserved for
> > > > +			 * creating new vrings when enabling reset queue.
> > > > +			 */
> > > > +			u32 vring_align;
> > > > +			bool may_reduce_num;
> > > >  		} split;
> > > >
> > > >  		/* Available for packed ring */
> > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > >  #endif
> > > >  };
> > > >
> > > > +static void vring_free(struct virtqueue *vq);
> > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > +					 struct virtio_device *vdev);
> > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > +					  struct virtio_device *vdev,
> > > > +					  struct vring vring);
> > > >
> > > >  /*
> > > >   * Helpers.
> > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > >  		return NULL;
> > > >  	}
> > > >
> > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > >  	to_vvq(vq)->we_own_ring = true;
> > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > >  	return vq;
> > > >  }
> > > >
> > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > +{
> > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > +	struct vring_split vring;
> > > > +	int err;
> > > > +
> > > > +	if (num > _vq->num_max)
> > > > +		return -E2BIG;
> > > > +
> > > > +	switch (vq->vq.reset) {
> > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > +		return -ENOENT;
> > > > +
> > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > +		if (vq->split.vring.num == num || !num)
> > > > +			break;
> > > > +
> > > > +		vring_free(_vq);
> > > > +
> > > > +		fallthrough;
> > > > +
> > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > +		if (!num)
> > > > +			num = vq->split.vring.num;
> > > > +
> > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > +					       vq->split.vring_align,
> > > > +					       vq->weak_barriers,
> > > > +					       vq->split.may_reduce_num, num);
> > > > +		if (err)
> > > > +			return -ENOMEM;
> > > > +
> > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > +		if (err) {
> > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > +					 vring.queue,
> > > > +					 vring.dma_addr);
> > > > +			return -ENOMEM;
> > > > +		}
> > > > +
> > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > +	}
> > > > +
> > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > +	vq->we_own_ring = true;
> > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > +
> > > > +	return 0;
> > > > +}
> > > > +
> > >
> > > I kind of dislike this state machine.
> > >
> > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > confusing.
> >
> > I'm removing it. I'll say in the function description that this function is
> > currently only called when vq has been reset. I'm no longer checking it based on
> > state.
> >
> > >
> > > And as Jason points out, when we want a resize then yes this currently
> > > implies reset but that is an implementation detail.
> > >
> > > There should be a way to just make these cases separate functions
> > > and then use them to compose consistent external APIs.
> >
> > Yes, virtqueue_resize_split() is fine for ethtool -G.
> >
> > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > to handle both scenarios?
> >
> > Or can anyone think of a better name. ^_^
> >
> > Thanks.
>
>
> I'd say resize should be called resize and reset should be called reset.


OK, I'll change it to resize here.

But I want to know that when I implement virtio-net to support AF_XDP, its
requirement is to release all submitted buffers. Then should I add a new api
such as virtqueue_reset_vring()?

>
> The big issue is a sane API for resize. Ideally it would resubmit
> buffers which did not get used. Question is what to do
> about buffers which don't fit (if ring has been downsized)?
> Maybe a callback that will handle them?
> And then what? Queue them up and readd later? Drop?
> If we drop we should drop from the head not the tail ...

It's a good idea, let's implement it later.

Thanks.

>
>
> > >
> > > If we additionally want to track state for debugging then bool flags
> > > seem more appropriate for this, though from experience that is
> > > not always worth the extra code.
> > >
> > >
> > >
> > > >  /*
> > > >   * Packed ring specific functions - *_packed().
> > > > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > >  					 struct virtio_device *vdev)
> > > >  {
> > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > > > +
> > > >  	vq->packed_ring = false;
> > > >  	vq->we_own_ring = false;
> > > >  	vq->broken = false;
> > > > --
> > > > 2.31.0
> > >
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
  2022-03-09  8:54     ` Jason Wang
  (?)
@ 2022-03-10  8:20       ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  8:20 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements virtio pci support for QUEUE RESET.
> >
> > Performing reset on a queue is divided into these steps:
> >
> >   1. virtio_reset_vq()              - notify the device to reset the queue
> >   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >   4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> >
> > This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
> > pci scenario.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_pci_common.c |  8 +--
> >   drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
> >   2 files changed, 88 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> > index fdbde1db5ec5..863d3a8a0956 100644
> > --- a/drivers/virtio/virtio_pci_common.c
> > +++ b/drivers/virtio/virtio_pci_common.c
> > @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
> >   	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
> >   	unsigned long flags;
> >
> > -	spin_lock_irqsave(&vp_dev->lock, flags);
> > -	list_del(&info->node);
> > -	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	if (!vq->reset) {
> > +		spin_lock_irqsave(&vp_dev->lock, flags);
> > +		list_del(&info->node);
> > +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	}
> >
> >   	vp_dev->del_vq(info);
> >   	kfree(info);
> > diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> > index 49a4493732cf..3c67d3607802 100644
> > --- a/drivers/virtio/virtio_pci_modern.c
> > +++ b/drivers/virtio/virtio_pci_modern.c
> > @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
> >   	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
> >   			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
> >   		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
> > +
> > +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
> > +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
> >   }
> >
> >   /* virtio config->finalize_features() implementation */
> > @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
> >   	return 0;
> >   }
> >
> > +static int vp_modern_reset_vq(struct virtqueue *vq)
> > +{
> > +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> > +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> > +	struct virtio_pci_vq_info *info;
> > +	unsigned long flags;
> > +	unsigned int irq;
> > +
> > +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> > +		return -ENOENT;
> > +
> > +	vp_modern_set_queue_reset(mdev, vq->index);
> > +
> > +	info = vp_dev->vqs[vq->index];
> > +
> > +	/* delete vq from irq handler */
> > +	spin_lock_irqsave(&vp_dev->lock, flags);
> > +	list_del(&info->node);
> > +	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +
> > +	INIT_LIST_HEAD(&info->node);
> > +
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
> > +
> > +	/* sync irq callback. */
> > +	if (vp_dev->intx_enabled) {
> > +		irq = vp_dev->pci_dev->irq;
> > +
> > +	} else {
> > +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
> > +			return 0;
> > +
> > +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
> > +	}
> > +
> > +	synchronize_irq(irq);
>
>
> Synchronize_irq() is not sufficient here since it breaks the effort of
> the interrupt hardening which is done by commits:
>
> 080cd7c3ac87 virtio-pci: harden INTX interrupts
> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>
> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
> used for the affinity managed irq but we're discussing a fix.
>


ok, I think disable_irq() is still used here.

I want to determine the solution for this detail first. So I posted the code, I
hope Jason can help confirm this point first.

There are three situations in which vq corresponds to an interrupt

1. intx
2. msix: per vq vectors
2. msix: share irq

Essentially can be divided into two categories: per vq vectors and share irq.

For share irq is based on virtqueues to find vq, so I think it is safe as long
as list_del() is executed under the protection of the lock.

In the case of per vq vectors, disable_irq() is used.

Thanks.

+static int vp_modern_reset_vq(struct virtqueue *vq)
+{
+       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+       struct virtio_pci_vq_info *info;
+       unsigned long flags;
+       unsigned int irq;
+
+       if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
+               return -ENOENT;
+
+       vp_modern_set_queue_reset(mdev, vq->index);
+
+       info = vp_dev->vqs[vq->index];
+
+       /* delete vq from irq handler */
+       spin_lock_irqsave(&vp_dev->lock, flags);
+       list_del(&info->node);
+       vp_modern_set_queue_reset(mdev, vq->index);
+
+       info = vp_dev->vqs[vq->index];
+
+       /* delete vq from irq handler */
+       spin_lock_irqsave(&vp_dev->lock, flags);
+       list_del(&info->node);
+       spin_unlock_irqrestore(&vp_dev->lock, flags);
+
+       INIT_LIST_HEAD(&info->node);
+
+       /* For the case where vq has an exclusive irq, to prevent the irq from
+        * being received again and the pending irq, call disable_irq().
+        *
+        * In the scenario based on shared interrupts, vq will be searched from
+        * the queue virtqueues. Since the previous list_del() has been deleted
+        * from the queue, it is impossible for vq to be called in this case.
+        * There is no need to close the corresponding interrupt.
+        */
+       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
+               disable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
+
+       vq->reset = true;
+
+       return 0;
+}
+
+static int vp_modern_enable_reset_vq(struct virtqueue *vq)
+{
+       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+       struct virtio_pci_vq_info *info;
+       unsigned long flags, index;
+       int err;
+
+       if (!vq->reset)
+               return -EBUSY;
+
+       index = vq->index;
+       info = vp_dev->vqs[index];
+
+       /* check queue reset status */
+       if (vp_modern_get_queue_reset(mdev, index) != 1)
+               return -EBUSY;
+
+       err = vp_active_vq(vq, info->msix_vector);
+       if (err)
+               return err;
+
+       if (vq->callback) {
+               spin_lock_irqsave(&vp_dev->lock, flags);
+               list_add(&info->node, &vp_dev->virtqueues);
+               spin_unlock_irqrestore(&vp_dev->lock, flags);
+       } else {
+               INIT_LIST_HEAD(&info->node);
+       }
+
+       vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
+       vq->reset = false;
+
+       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
+               enable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
+
+       return 0;
+}



^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-10  8:20       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  8:20 UTC (permalink / raw)
  To: Jason Wang
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller

On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements virtio pci support for QUEUE RESET.
> >
> > Performing reset on a queue is divided into these steps:
> >
> >   1. virtio_reset_vq()              - notify the device to reset the queue
> >   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >   4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> >
> > This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
> > pci scenario.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_pci_common.c |  8 +--
> >   drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
> >   2 files changed, 88 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> > index fdbde1db5ec5..863d3a8a0956 100644
> > --- a/drivers/virtio/virtio_pci_common.c
> > +++ b/drivers/virtio/virtio_pci_common.c
> > @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
> >   	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
> >   	unsigned long flags;
> >
> > -	spin_lock_irqsave(&vp_dev->lock, flags);
> > -	list_del(&info->node);
> > -	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	if (!vq->reset) {
> > +		spin_lock_irqsave(&vp_dev->lock, flags);
> > +		list_del(&info->node);
> > +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	}
> >
> >   	vp_dev->del_vq(info);
> >   	kfree(info);
> > diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> > index 49a4493732cf..3c67d3607802 100644
> > --- a/drivers/virtio/virtio_pci_modern.c
> > +++ b/drivers/virtio/virtio_pci_modern.c
> > @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
> >   	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
> >   			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
> >   		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
> > +
> > +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
> > +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
> >   }
> >
> >   /* virtio config->finalize_features() implementation */
> > @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
> >   	return 0;
> >   }
> >
> > +static int vp_modern_reset_vq(struct virtqueue *vq)
> > +{
> > +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> > +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> > +	struct virtio_pci_vq_info *info;
> > +	unsigned long flags;
> > +	unsigned int irq;
> > +
> > +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> > +		return -ENOENT;
> > +
> > +	vp_modern_set_queue_reset(mdev, vq->index);
> > +
> > +	info = vp_dev->vqs[vq->index];
> > +
> > +	/* delete vq from irq handler */
> > +	spin_lock_irqsave(&vp_dev->lock, flags);
> > +	list_del(&info->node);
> > +	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +
> > +	INIT_LIST_HEAD(&info->node);
> > +
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
> > +
> > +	/* sync irq callback. */
> > +	if (vp_dev->intx_enabled) {
> > +		irq = vp_dev->pci_dev->irq;
> > +
> > +	} else {
> > +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
> > +			return 0;
> > +
> > +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
> > +	}
> > +
> > +	synchronize_irq(irq);
>
>
> Synchronize_irq() is not sufficient here since it breaks the effort of
> the interrupt hardening which is done by commits:
>
> 080cd7c3ac87 virtio-pci: harden INTX interrupts
> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>
> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
> used for the affinity managed irq but we're discussing a fix.
>


ok, I think disable_irq() is still used here.

I want to determine the solution for this detail first. So I posted the code, I
hope Jason can help confirm this point first.

There are three situations in which vq corresponds to an interrupt

1. intx
2. msix: per vq vectors
2. msix: share irq

Essentially can be divided into two categories: per vq vectors and share irq.

For share irq is based on virtqueues to find vq, so I think it is safe as long
as list_del() is executed under the protection of the lock.

In the case of per vq vectors, disable_irq() is used.

Thanks.

+static int vp_modern_reset_vq(struct virtqueue *vq)
+{
+       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+       struct virtio_pci_vq_info *info;
+       unsigned long flags;
+       unsigned int irq;
+
+       if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
+               return -ENOENT;
+
+       vp_modern_set_queue_reset(mdev, vq->index);
+
+       info = vp_dev->vqs[vq->index];
+
+       /* delete vq from irq handler */
+       spin_lock_irqsave(&vp_dev->lock, flags);
+       list_del(&info->node);
+       vp_modern_set_queue_reset(mdev, vq->index);
+
+       info = vp_dev->vqs[vq->index];
+
+       /* delete vq from irq handler */
+       spin_lock_irqsave(&vp_dev->lock, flags);
+       list_del(&info->node);
+       spin_unlock_irqrestore(&vp_dev->lock, flags);
+
+       INIT_LIST_HEAD(&info->node);
+
+       /* For the case where vq has an exclusive irq, to prevent the irq from
+        * being received again and the pending irq, call disable_irq().
+        *
+        * In the scenario based on shared interrupts, vq will be searched from
+        * the queue virtqueues. Since the previous list_del() has been deleted
+        * from the queue, it is impossible for vq to be called in this case.
+        * There is no need to close the corresponding interrupt.
+        */
+       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
+               disable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
+
+       vq->reset = true;
+
+       return 0;
+}
+
+static int vp_modern_enable_reset_vq(struct virtqueue *vq)
+{
+       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+       struct virtio_pci_vq_info *info;
+       unsigned long flags, index;
+       int err;
+
+       if (!vq->reset)
+               return -EBUSY;
+
+       index = vq->index;
+       info = vp_dev->vqs[index];
+
+       /* check queue reset status */
+       if (vp_modern_get_queue_reset(mdev, index) != 1)
+               return -EBUSY;
+
+       err = vp_active_vq(vq, info->msix_vector);
+       if (err)
+               return err;
+
+       if (vq->callback) {
+               spin_lock_irqsave(&vp_dev->lock, flags);
+               list_add(&info->node, &vp_dev->virtqueues);
+               spin_unlock_irqrestore(&vp_dev->lock, flags);
+       } else {
+               INIT_LIST_HEAD(&info->node);
+       }
+
+       vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
+       vq->reset = false;
+
+       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
+               enable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
+
+       return 0;
+}


_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-10  8:20       ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10  8:20 UTC (permalink / raw)
  To: Jason Wang
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev

On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>
> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
> > This patch implements virtio pci support for QUEUE RESET.
> >
> > Performing reset on a queue is divided into these steps:
> >
> >   1. virtio_reset_vq()              - notify the device to reset the queue
> >   2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
> >   3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
> >   4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
> >
> > This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
> > pci scenario.
> >
> > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > ---
> >   drivers/virtio/virtio_pci_common.c |  8 +--
> >   drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
> >   2 files changed, 88 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
> > index fdbde1db5ec5..863d3a8a0956 100644
> > --- a/drivers/virtio/virtio_pci_common.c
> > +++ b/drivers/virtio/virtio_pci_common.c
> > @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
> >   	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
> >   	unsigned long flags;
> >
> > -	spin_lock_irqsave(&vp_dev->lock, flags);
> > -	list_del(&info->node);
> > -	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	if (!vq->reset) {
> > +		spin_lock_irqsave(&vp_dev->lock, flags);
> > +		list_del(&info->node);
> > +		spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +	}
> >
> >   	vp_dev->del_vq(info);
> >   	kfree(info);
> > diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
> > index 49a4493732cf..3c67d3607802 100644
> > --- a/drivers/virtio/virtio_pci_modern.c
> > +++ b/drivers/virtio/virtio_pci_modern.c
> > @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
> >   	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
> >   			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
> >   		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
> > +
> > +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
> > +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
> >   }
> >
> >   /* virtio config->finalize_features() implementation */
> > @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
> >   	return 0;
> >   }
> >
> > +static int vp_modern_reset_vq(struct virtqueue *vq)
> > +{
> > +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> > +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> > +	struct virtio_pci_vq_info *info;
> > +	unsigned long flags;
> > +	unsigned int irq;
> > +
> > +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> > +		return -ENOENT;
> > +
> > +	vp_modern_set_queue_reset(mdev, vq->index);
> > +
> > +	info = vp_dev->vqs[vq->index];
> > +
> > +	/* delete vq from irq handler */
> > +	spin_lock_irqsave(&vp_dev->lock, flags);
> > +	list_del(&info->node);
> > +	spin_unlock_irqrestore(&vp_dev->lock, flags);
> > +
> > +	INIT_LIST_HEAD(&info->node);
> > +
> > +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
> > +
> > +	/* sync irq callback. */
> > +	if (vp_dev->intx_enabled) {
> > +		irq = vp_dev->pci_dev->irq;
> > +
> > +	} else {
> > +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
> > +			return 0;
> > +
> > +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
> > +	}
> > +
> > +	synchronize_irq(irq);
>
>
> Synchronize_irq() is not sufficient here since it breaks the effort of
> the interrupt hardening which is done by commits:
>
> 080cd7c3ac87 virtio-pci: harden INTX interrupts
> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>
> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
> used for the affinity managed irq but we're discussing a fix.
>


ok, I think disable_irq() is still used here.

I want to determine the solution for this detail first. So I posted the code, I
hope Jason can help confirm this point first.

There are three situations in which vq corresponds to an interrupt

1. intx
2. msix: per vq vectors
2. msix: share irq

Essentially can be divided into two categories: per vq vectors and share irq.

For share irq is based on virtqueues to find vq, so I think it is safe as long
as list_del() is executed under the protection of the lock.

In the case of per vq vectors, disable_irq() is used.

Thanks.

+static int vp_modern_reset_vq(struct virtqueue *vq)
+{
+       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+       struct virtio_pci_vq_info *info;
+       unsigned long flags;
+       unsigned int irq;
+
+       if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
+               return -ENOENT;
+
+       vp_modern_set_queue_reset(mdev, vq->index);
+
+       info = vp_dev->vqs[vq->index];
+
+       /* delete vq from irq handler */
+       spin_lock_irqsave(&vp_dev->lock, flags);
+       list_del(&info->node);
+       vp_modern_set_queue_reset(mdev, vq->index);
+
+       info = vp_dev->vqs[vq->index];
+
+       /* delete vq from irq handler */
+       spin_lock_irqsave(&vp_dev->lock, flags);
+       list_del(&info->node);
+       spin_unlock_irqrestore(&vp_dev->lock, flags);
+
+       INIT_LIST_HEAD(&info->node);
+
+       /* For the case where vq has an exclusive irq, to prevent the irq from
+        * being received again and the pending irq, call disable_irq().
+        *
+        * In the scenario based on shared interrupts, vq will be searched from
+        * the queue virtqueues. Since the previous list_del() has been deleted
+        * from the queue, it is impossible for vq to be called in this case.
+        * There is no need to close the corresponding interrupt.
+        */
+       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
+               disable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
+
+       vq->reset = true;
+
+       return 0;
+}
+
+static int vp_modern_enable_reset_vq(struct virtqueue *vq)
+{
+       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
+       struct virtio_pci_vq_info *info;
+       unsigned long flags, index;
+       int err;
+
+       if (!vq->reset)
+               return -EBUSY;
+
+       index = vq->index;
+       info = vp_dev->vqs[index];
+
+       /* check queue reset status */
+       if (vp_modern_get_queue_reset(mdev, index) != 1)
+               return -EBUSY;
+
+       err = vp_active_vq(vq, info->msix_vector);
+       if (err)
+               return err;
+
+       if (vq->callback) {
+               spin_lock_irqsave(&vp_dev->lock, flags);
+               list_add(&info->node, &vp_dev->virtqueues);
+               spin_unlock_irqrestore(&vp_dev->lock, flags);
+       } else {
+               INIT_LIST_HEAD(&info->node);
+       }
+
+       vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
+       vq->reset = false;
+
+       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
+               enable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
+
+       return 0;
+}



_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-10  8:14           ` Xuan Zhuo
  (?)
@ 2022-03-10 12:17             ` Michael S. Tsirkin
  -1 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10 12:17 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > virtio ring supports reset.
> > > > >
> > > > > Queue reset is divided into several stages.
> > > > >
> > > > > 1. notify device queue reset
> > > > > 2. vring release
> > > > > 3. attach new vring
> > > > > 4. notify device queue re-enable
> > > > >
> > > > > After the first step is completed, the vring reset operation can be
> > > > > performed. If the newly set vring num does not change, then just reset
> > > > > the vq related value.
> > > > >
> > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > function will exit, and the state of the vq will be the vring release
> > > > > state. You can call this function again to reallocate the vring.
> > > > >
> > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > vring, so they are retained when creating vq.
> > > > >
> > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > ---
> > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > >  1 file changed, 69 insertions(+)
> > > > >
> > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > >  			/* DMA address and size information */
> > > > >  			dma_addr_t queue_dma_addr;
> > > > >  			size_t queue_size_in_bytes;
> > > > > +
> > > > > +			/* The parameters for creating vrings are reserved for
> > > > > +			 * creating new vrings when enabling reset queue.
> > > > > +			 */
> > > > > +			u32 vring_align;
> > > > > +			bool may_reduce_num;
> > > > >  		} split;
> > > > >
> > > > >  		/* Available for packed ring */
> > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > >  #endif
> > > > >  };
> > > > >
> > > > > +static void vring_free(struct virtqueue *vq);
> > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > +					 struct virtio_device *vdev);
> > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > +					  struct virtio_device *vdev,
> > > > > +					  struct vring vring);
> > > > >
> > > > >  /*
> > > > >   * Helpers.
> > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > >  		return NULL;
> > > > >  	}
> > > > >
> > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > >  	return vq;
> > > > >  }
> > > > >
> > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > +{
> > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > +	struct vring_split vring;
> > > > > +	int err;
> > > > > +
> > > > > +	if (num > _vq->num_max)
> > > > > +		return -E2BIG;
> > > > > +
> > > > > +	switch (vq->vq.reset) {
> > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > +		return -ENOENT;
> > > > > +
> > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > +		if (vq->split.vring.num == num || !num)
> > > > > +			break;
> > > > > +
> > > > > +		vring_free(_vq);
> > > > > +
> > > > > +		fallthrough;
> > > > > +
> > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > +		if (!num)
> > > > > +			num = vq->split.vring.num;
> > > > > +
> > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > +					       vq->split.vring_align,
> > > > > +					       vq->weak_barriers,
> > > > > +					       vq->split.may_reduce_num, num);
> > > > > +		if (err)
> > > > > +			return -ENOMEM;
> > > > > +
> > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > +		if (err) {
> > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > +					 vring.queue,
> > > > > +					 vring.dma_addr);
> > > > > +			return -ENOMEM;
> > > > > +		}
> > > > > +
> > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > +	}
> > > > > +
> > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > +	vq->we_own_ring = true;
> > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > +
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > >
> > > > I kind of dislike this state machine.
> > > >
> > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > confusing.
> > >
> > > I'm removing it. I'll say in the function description that this function is
> > > currently only called when vq has been reset. I'm no longer checking it based on
> > > state.
> > >
> > > >
> > > > And as Jason points out, when we want a resize then yes this currently
> > > > implies reset but that is an implementation detail.
> > > >
> > > > There should be a way to just make these cases separate functions
> > > > and then use them to compose consistent external APIs.
> > >
> > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > >
> > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > to handle both scenarios?
> > >
> > > Or can anyone think of a better name. ^_^
> > >
> > > Thanks.
> >
> >
> > I'd say resize should be called resize and reset should be called reset.
> 
> 
> OK, I'll change it to resize here.
> 
> But I want to know that when I implement virtio-net to support AF_XDP, its
> requirement is to release all submitted buffers. Then should I add a new api
> such as virtqueue_reset_vring()?

Sounds like a reasonable name.

> >
> > The big issue is a sane API for resize. Ideally it would resubmit
> > buffers which did not get used. Question is what to do
> > about buffers which don't fit (if ring has been downsized)?
> > Maybe a callback that will handle them?
> > And then what? Queue them up and readd later? Drop?
> > If we drop we should drop from the head not the tail ...
> 
> It's a good idea, let's implement it later.
> 
> Thanks.

Well ... not sure how you are going to support resize
if you don't know what to do with buffers that were
in the ring.

> >
> >
> > > >
> > > > If we additionally want to track state for debugging then bool flags
> > > > seem more appropriate for this, though from experience that is
> > > > not always worth the extra code.
> > > >
> > > >
> > > >
> > > > >  /*
> > > > >   * Packed ring specific functions - *_packed().
> > > > > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > >  					 struct virtio_device *vdev)
> > > > >  {
> > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > > > > +
> > > > >  	vq->packed_ring = false;
> > > > >  	vq->we_own_ring = false;
> > > > >  	vq->broken = false;
> > > > > --
> > > > > 2.31.0
> > > >
> >


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10 12:17             ` Michael S. Tsirkin
  0 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10 12:17 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Vadim Pasternak, linux-remoteproc, Alexei Starovoitov,
	virtualization, Alexander Gordeev, Anton Ivanov, linux-s390,
	Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, platform-driver-x86, Jesper Dangaard Brouer,
	Vasily Gorbik, Jeff Dike, linux-um, Mark Gross, Hans de Goede,
	kvm, Bjorn Andersson, Mathieu Poirier, netdev, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > virtio ring supports reset.
> > > > >
> > > > > Queue reset is divided into several stages.
> > > > >
> > > > > 1. notify device queue reset
> > > > > 2. vring release
> > > > > 3. attach new vring
> > > > > 4. notify device queue re-enable
> > > > >
> > > > > After the first step is completed, the vring reset operation can be
> > > > > performed. If the newly set vring num does not change, then just reset
> > > > > the vq related value.
> > > > >
> > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > function will exit, and the state of the vq will be the vring release
> > > > > state. You can call this function again to reallocate the vring.
> > > > >
> > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > vring, so they are retained when creating vq.
> > > > >
> > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > ---
> > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > >  1 file changed, 69 insertions(+)
> > > > >
> > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > >  			/* DMA address and size information */
> > > > >  			dma_addr_t queue_dma_addr;
> > > > >  			size_t queue_size_in_bytes;
> > > > > +
> > > > > +			/* The parameters for creating vrings are reserved for
> > > > > +			 * creating new vrings when enabling reset queue.
> > > > > +			 */
> > > > > +			u32 vring_align;
> > > > > +			bool may_reduce_num;
> > > > >  		} split;
> > > > >
> > > > >  		/* Available for packed ring */
> > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > >  #endif
> > > > >  };
> > > > >
> > > > > +static void vring_free(struct virtqueue *vq);
> > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > +					 struct virtio_device *vdev);
> > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > +					  struct virtio_device *vdev,
> > > > > +					  struct vring vring);
> > > > >
> > > > >  /*
> > > > >   * Helpers.
> > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > >  		return NULL;
> > > > >  	}
> > > > >
> > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > >  	return vq;
> > > > >  }
> > > > >
> > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > +{
> > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > +	struct vring_split vring;
> > > > > +	int err;
> > > > > +
> > > > > +	if (num > _vq->num_max)
> > > > > +		return -E2BIG;
> > > > > +
> > > > > +	switch (vq->vq.reset) {
> > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > +		return -ENOENT;
> > > > > +
> > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > +		if (vq->split.vring.num == num || !num)
> > > > > +			break;
> > > > > +
> > > > > +		vring_free(_vq);
> > > > > +
> > > > > +		fallthrough;
> > > > > +
> > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > +		if (!num)
> > > > > +			num = vq->split.vring.num;
> > > > > +
> > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > +					       vq->split.vring_align,
> > > > > +					       vq->weak_barriers,
> > > > > +					       vq->split.may_reduce_num, num);
> > > > > +		if (err)
> > > > > +			return -ENOMEM;
> > > > > +
> > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > +		if (err) {
> > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > +					 vring.queue,
> > > > > +					 vring.dma_addr);
> > > > > +			return -ENOMEM;
> > > > > +		}
> > > > > +
> > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > +	}
> > > > > +
> > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > +	vq->we_own_ring = true;
> > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > +
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > >
> > > > I kind of dislike this state machine.
> > > >
> > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > confusing.
> > >
> > > I'm removing it. I'll say in the function description that this function is
> > > currently only called when vq has been reset. I'm no longer checking it based on
> > > state.
> > >
> > > >
> > > > And as Jason points out, when we want a resize then yes this currently
> > > > implies reset but that is an implementation detail.
> > > >
> > > > There should be a way to just make these cases separate functions
> > > > and then use them to compose consistent external APIs.
> > >
> > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > >
> > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > to handle both scenarios?
> > >
> > > Or can anyone think of a better name. ^_^
> > >
> > > Thanks.
> >
> >
> > I'd say resize should be called resize and reset should be called reset.
> 
> 
> OK, I'll change it to resize here.
> 
> But I want to know that when I implement virtio-net to support AF_XDP, its
> requirement is to release all submitted buffers. Then should I add a new api
> such as virtqueue_reset_vring()?

Sounds like a reasonable name.

> >
> > The big issue is a sane API for resize. Ideally it would resubmit
> > buffers which did not get used. Question is what to do
> > about buffers which don't fit (if ring has been downsized)?
> > Maybe a callback that will handle them?
> > And then what? Queue them up and readd later? Drop?
> > If we drop we should drop from the head not the tail ...
> 
> It's a good idea, let's implement it later.
> 
> Thanks.

Well ... not sure how you are going to support resize
if you don't know what to do with buffers that were
in the ring.

> >
> >
> > > >
> > > > If we additionally want to track state for debugging then bool flags
> > > > seem more appropriate for this, though from experience that is
> > > > not always worth the extra code.
> > > >
> > > >
> > > >
> > > > >  /*
> > > > >   * Packed ring specific functions - *_packed().
> > > > > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > >  					 struct virtio_device *vdev)
> > > > >  {
> > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > > > > +
> > > > >  	vq->packed_ring = false;
> > > > >  	vq->we_own_ring = false;
> > > > >  	vq->broken = false;
> > > > > --
> > > > > 2.31.0
> > > >
> >

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10 12:17             ` Michael S. Tsirkin
  0 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10 12:17 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > virtio ring supports reset.
> > > > >
> > > > > Queue reset is divided into several stages.
> > > > >
> > > > > 1. notify device queue reset
> > > > > 2. vring release
> > > > > 3. attach new vring
> > > > > 4. notify device queue re-enable
> > > > >
> > > > > After the first step is completed, the vring reset operation can be
> > > > > performed. If the newly set vring num does not change, then just reset
> > > > > the vq related value.
> > > > >
> > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > function will exit, and the state of the vq will be the vring release
> > > > > state. You can call this function again to reallocate the vring.
> > > > >
> > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > vring, so they are retained when creating vq.
> > > > >
> > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > ---
> > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > >  1 file changed, 69 insertions(+)
> > > > >
> > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > >  			/* DMA address and size information */
> > > > >  			dma_addr_t queue_dma_addr;
> > > > >  			size_t queue_size_in_bytes;
> > > > > +
> > > > > +			/* The parameters for creating vrings are reserved for
> > > > > +			 * creating new vrings when enabling reset queue.
> > > > > +			 */
> > > > > +			u32 vring_align;
> > > > > +			bool may_reduce_num;
> > > > >  		} split;
> > > > >
> > > > >  		/* Available for packed ring */
> > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > >  #endif
> > > > >  };
> > > > >
> > > > > +static void vring_free(struct virtqueue *vq);
> > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > +					 struct virtio_device *vdev);
> > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > +					  struct virtio_device *vdev,
> > > > > +					  struct vring vring);
> > > > >
> > > > >  /*
> > > > >   * Helpers.
> > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > >  		return NULL;
> > > > >  	}
> > > > >
> > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > >  	return vq;
> > > > >  }
> > > > >
> > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > +{
> > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > +	struct vring_split vring;
> > > > > +	int err;
> > > > > +
> > > > > +	if (num > _vq->num_max)
> > > > > +		return -E2BIG;
> > > > > +
> > > > > +	switch (vq->vq.reset) {
> > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > +		return -ENOENT;
> > > > > +
> > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > +		if (vq->split.vring.num == num || !num)
> > > > > +			break;
> > > > > +
> > > > > +		vring_free(_vq);
> > > > > +
> > > > > +		fallthrough;
> > > > > +
> > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > +		if (!num)
> > > > > +			num = vq->split.vring.num;
> > > > > +
> > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > +					       vq->split.vring_align,
> > > > > +					       vq->weak_barriers,
> > > > > +					       vq->split.may_reduce_num, num);
> > > > > +		if (err)
> > > > > +			return -ENOMEM;
> > > > > +
> > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > +		if (err) {
> > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > +					 vring.queue,
> > > > > +					 vring.dma_addr);
> > > > > +			return -ENOMEM;
> > > > > +		}
> > > > > +
> > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > +	}
> > > > > +
> > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > +	vq->we_own_ring = true;
> > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > +
> > > > > +	return 0;
> > > > > +}
> > > > > +
> > > >
> > > > I kind of dislike this state machine.
> > > >
> > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > confusing.
> > >
> > > I'm removing it. I'll say in the function description that this function is
> > > currently only called when vq has been reset. I'm no longer checking it based on
> > > state.
> > >
> > > >
> > > > And as Jason points out, when we want a resize then yes this currently
> > > > implies reset but that is an implementation detail.
> > > >
> > > > There should be a way to just make these cases separate functions
> > > > and then use them to compose consistent external APIs.
> > >
> > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > >
> > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > to handle both scenarios?
> > >
> > > Or can anyone think of a better name. ^_^
> > >
> > > Thanks.
> >
> >
> > I'd say resize should be called resize and reset should be called reset.
> 
> 
> OK, I'll change it to resize here.
> 
> But I want to know that when I implement virtio-net to support AF_XDP, its
> requirement is to release all submitted buffers. Then should I add a new api
> such as virtqueue_reset_vring()?

Sounds like a reasonable name.

> >
> > The big issue is a sane API for resize. Ideally it would resubmit
> > buffers which did not get used. Question is what to do
> > about buffers which don't fit (if ring has been downsized)?
> > Maybe a callback that will handle them?
> > And then what? Queue them up and readd later? Drop?
> > If we drop we should drop from the head not the tail ...
> 
> It's a good idea, let's implement it later.
> 
> Thanks.

Well ... not sure how you are going to support resize
if you don't know what to do with buffers that were
in the ring.

> >
> >
> > > >
> > > > If we additionally want to track state for debugging then bool flags
> > > > seem more appropriate for this, though from experience that is
> > > > not always worth the extra code.
> > > >
> > > >
> > > >
> > > > >  /*
> > > > >   * Packed ring specific functions - *_packed().
> > > > > @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > >  static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > >  					 struct virtio_device *vdev)
> > > > >  {
> > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
> > > > > +
> > > > >  	vq->packed_ring = false;
> > > > >  	vq->we_own_ring = false;
> > > > >  	vq->broken = false;
> > > > > --
> > > > > 2.31.0
> > > >
> >


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-10 12:17             ` Michael S. Tsirkin
  (?)
@ 2022-03-10 12:33               ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10 12:33 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, 10 Mar 2022 07:17:09 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> > On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > > virtio ring supports reset.
> > > > > >
> > > > > > Queue reset is divided into several stages.
> > > > > >
> > > > > > 1. notify device queue reset
> > > > > > 2. vring release
> > > > > > 3. attach new vring
> > > > > > 4. notify device queue re-enable
> > > > > >
> > > > > > After the first step is completed, the vring reset operation can be
> > > > > > performed. If the newly set vring num does not change, then just reset
> > > > > > the vq related value.
> > > > > >
> > > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > > function will exit, and the state of the vq will be the vring release
> > > > > > state. You can call this function again to reallocate the vring.
> > > > > >
> > > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > > vring, so they are retained when creating vq.
> > > > > >
> > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > ---
> > > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > > >  1 file changed, 69 insertions(+)
> > > > > >
> > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > > >  			/* DMA address and size information */
> > > > > >  			dma_addr_t queue_dma_addr;
> > > > > >  			size_t queue_size_in_bytes;
> > > > > > +
> > > > > > +			/* The parameters for creating vrings are reserved for
> > > > > > +			 * creating new vrings when enabling reset queue.
> > > > > > +			 */
> > > > > > +			u32 vring_align;
> > > > > > +			bool may_reduce_num;
> > > > > >  		} split;
> > > > > >
> > > > > >  		/* Available for packed ring */
> > > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > > >  #endif
> > > > > >  };
> > > > > >
> > > > > > +static void vring_free(struct virtqueue *vq);
> > > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > > +					 struct virtio_device *vdev);
> > > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > > +					  struct virtio_device *vdev,
> > > > > > +					  struct vring vring);
> > > > > >
> > > > > >  /*
> > > > > >   * Helpers.
> > > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > >  		return NULL;
> > > > > >  	}
> > > > > >
> > > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > >  	return vq;
> > > > > >  }
> > > > > >
> > > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > > +{
> > > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > > +	struct vring_split vring;
> > > > > > +	int err;
> > > > > > +
> > > > > > +	if (num > _vq->num_max)
> > > > > > +		return -E2BIG;
> > > > > > +
> > > > > > +	switch (vq->vq.reset) {
> > > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > > +		return -ENOENT;
> > > > > > +
> > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > > +		if (vq->split.vring.num == num || !num)
> > > > > > +			break;
> > > > > > +
> > > > > > +		vring_free(_vq);
> > > > > > +
> > > > > > +		fallthrough;
> > > > > > +
> > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > > +		if (!num)
> > > > > > +			num = vq->split.vring.num;
> > > > > > +
> > > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > > +					       vq->split.vring_align,
> > > > > > +					       vq->weak_barriers,
> > > > > > +					       vq->split.may_reduce_num, num);
> > > > > > +		if (err)
> > > > > > +			return -ENOMEM;
> > > > > > +
> > > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > > +		if (err) {
> > > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > > +					 vring.queue,
> > > > > > +					 vring.dma_addr);
> > > > > > +			return -ENOMEM;
> > > > > > +		}
> > > > > > +
> > > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > +	}
> > > > > > +
> > > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > > +	vq->we_own_ring = true;
> > > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > > +
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > >
> > > > > I kind of dislike this state machine.
> > > > >
> > > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > > confusing.
> > > >
> > > > I'm removing it. I'll say in the function description that this function is
> > > > currently only called when vq has been reset. I'm no longer checking it based on
> > > > state.
> > > >
> > > > >
> > > > > And as Jason points out, when we want a resize then yes this currently
> > > > > implies reset but that is an implementation detail.
> > > > >
> > > > > There should be a way to just make these cases separate functions
> > > > > and then use them to compose consistent external APIs.
> > > >
> > > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > > >
> > > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > > to handle both scenarios?
> > > >
> > > > Or can anyone think of a better name. ^_^
> > > >
> > > > Thanks.
> > >
> > >
> > > I'd say resize should be called resize and reset should be called reset.
> >
> >
> > OK, I'll change it to resize here.
> >
> > But I want to know that when I implement virtio-net to support AF_XDP, its
> > requirement is to release all submitted buffers. Then should I add a new api
> > such as virtqueue_reset_vring()?
>
> Sounds like a reasonable name.
>
> > >
> > > The big issue is a sane API for resize. Ideally it would resubmit
> > > buffers which did not get used. Question is what to do
> > > about buffers which don't fit (if ring has been downsized)?
> > > Maybe a callback that will handle them?
> > > And then what? Queue them up and readd later? Drop?
> > > If we drop we should drop from the head not the tail ...
> >
> > It's a good idea, let's implement it later.
> >
> > Thanks.
>
> Well ... not sure how you are going to support resize
> if you don't know what to do with buffers that were
> in the ring.

The current solution is to call virtqueue_detach_unused_buf() to release buffers
before resize ring.

Thanks.


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10 12:33               ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10 12:33 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Vadim Pasternak, linux-remoteproc, Alexei Starovoitov,
	virtualization, Alexander Gordeev, Anton Ivanov, linux-s390,
	Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, platform-driver-x86, Jesper Dangaard Brouer,
	Vasily Gorbik, Jeff Dike, linux-um, Mark Gross, Hans de Goede,
	kvm, Bjorn Andersson, Mathieu Poirier, netdev, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

On Thu, 10 Mar 2022 07:17:09 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> > On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > > virtio ring supports reset.
> > > > > >
> > > > > > Queue reset is divided into several stages.
> > > > > >
> > > > > > 1. notify device queue reset
> > > > > > 2. vring release
> > > > > > 3. attach new vring
> > > > > > 4. notify device queue re-enable
> > > > > >
> > > > > > After the first step is completed, the vring reset operation can be
> > > > > > performed. If the newly set vring num does not change, then just reset
> > > > > > the vq related value.
> > > > > >
> > > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > > function will exit, and the state of the vq will be the vring release
> > > > > > state. You can call this function again to reallocate the vring.
> > > > > >
> > > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > > vring, so they are retained when creating vq.
> > > > > >
> > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > ---
> > > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > > >  1 file changed, 69 insertions(+)
> > > > > >
> > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > > >  			/* DMA address and size information */
> > > > > >  			dma_addr_t queue_dma_addr;
> > > > > >  			size_t queue_size_in_bytes;
> > > > > > +
> > > > > > +			/* The parameters for creating vrings are reserved for
> > > > > > +			 * creating new vrings when enabling reset queue.
> > > > > > +			 */
> > > > > > +			u32 vring_align;
> > > > > > +			bool may_reduce_num;
> > > > > >  		} split;
> > > > > >
> > > > > >  		/* Available for packed ring */
> > > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > > >  #endif
> > > > > >  };
> > > > > >
> > > > > > +static void vring_free(struct virtqueue *vq);
> > > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > > +					 struct virtio_device *vdev);
> > > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > > +					  struct virtio_device *vdev,
> > > > > > +					  struct vring vring);
> > > > > >
> > > > > >  /*
> > > > > >   * Helpers.
> > > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > >  		return NULL;
> > > > > >  	}
> > > > > >
> > > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > >  	return vq;
> > > > > >  }
> > > > > >
> > > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > > +{
> > > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > > +	struct vring_split vring;
> > > > > > +	int err;
> > > > > > +
> > > > > > +	if (num > _vq->num_max)
> > > > > > +		return -E2BIG;
> > > > > > +
> > > > > > +	switch (vq->vq.reset) {
> > > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > > +		return -ENOENT;
> > > > > > +
> > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > > +		if (vq->split.vring.num == num || !num)
> > > > > > +			break;
> > > > > > +
> > > > > > +		vring_free(_vq);
> > > > > > +
> > > > > > +		fallthrough;
> > > > > > +
> > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > > +		if (!num)
> > > > > > +			num = vq->split.vring.num;
> > > > > > +
> > > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > > +					       vq->split.vring_align,
> > > > > > +					       vq->weak_barriers,
> > > > > > +					       vq->split.may_reduce_num, num);
> > > > > > +		if (err)
> > > > > > +			return -ENOMEM;
> > > > > > +
> > > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > > +		if (err) {
> > > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > > +					 vring.queue,
> > > > > > +					 vring.dma_addr);
> > > > > > +			return -ENOMEM;
> > > > > > +		}
> > > > > > +
> > > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > +	}
> > > > > > +
> > > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > > +	vq->we_own_ring = true;
> > > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > > +
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > >
> > > > > I kind of dislike this state machine.
> > > > >
> > > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > > confusing.
> > > >
> > > > I'm removing it. I'll say in the function description that this function is
> > > > currently only called when vq has been reset. I'm no longer checking it based on
> > > > state.
> > > >
> > > > >
> > > > > And as Jason points out, when we want a resize then yes this currently
> > > > > implies reset but that is an implementation detail.
> > > > >
> > > > > There should be a way to just make these cases separate functions
> > > > > and then use them to compose consistent external APIs.
> > > >
> > > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > > >
> > > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > > to handle both scenarios?
> > > >
> > > > Or can anyone think of a better name. ^_^
> > > >
> > > > Thanks.
> > >
> > >
> > > I'd say resize should be called resize and reset should be called reset.
> >
> >
> > OK, I'll change it to resize here.
> >
> > But I want to know that when I implement virtio-net to support AF_XDP, its
> > requirement is to release all submitted buffers. Then should I add a new api
> > such as virtqueue_reset_vring()?
>
> Sounds like a reasonable name.
>
> > >
> > > The big issue is a sane API for resize. Ideally it would resubmit
> > > buffers which did not get used. Question is what to do
> > > about buffers which don't fit (if ring has been downsized)?
> > > Maybe a callback that will handle them?
> > > And then what? Queue them up and readd later? Drop?
> > > If we drop we should drop from the head not the tail ...
> >
> > It's a good idea, let's implement it later.
> >
> > Thanks.
>
> Well ... not sure how you are going to support resize
> if you don't know what to do with buffers that were
> in the ring.

The current solution is to call virtqueue_detach_unused_buf() to release buffers
before resize ring.

Thanks.

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10 12:33               ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10 12:33 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, 10 Mar 2022 07:17:09 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> > On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > > virtio ring supports reset.
> > > > > >
> > > > > > Queue reset is divided into several stages.
> > > > > >
> > > > > > 1. notify device queue reset
> > > > > > 2. vring release
> > > > > > 3. attach new vring
> > > > > > 4. notify device queue re-enable
> > > > > >
> > > > > > After the first step is completed, the vring reset operation can be
> > > > > > performed. If the newly set vring num does not change, then just reset
> > > > > > the vq related value.
> > > > > >
> > > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > > function will exit, and the state of the vq will be the vring release
> > > > > > state. You can call this function again to reallocate the vring.
> > > > > >
> > > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > > vring, so they are retained when creating vq.
> > > > > >
> > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > ---
> > > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > > >  1 file changed, 69 insertions(+)
> > > > > >
> > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > > >  			/* DMA address and size information */
> > > > > >  			dma_addr_t queue_dma_addr;
> > > > > >  			size_t queue_size_in_bytes;
> > > > > > +
> > > > > > +			/* The parameters for creating vrings are reserved for
> > > > > > +			 * creating new vrings when enabling reset queue.
> > > > > > +			 */
> > > > > > +			u32 vring_align;
> > > > > > +			bool may_reduce_num;
> > > > > >  		} split;
> > > > > >
> > > > > >  		/* Available for packed ring */
> > > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > > >  #endif
> > > > > >  };
> > > > > >
> > > > > > +static void vring_free(struct virtqueue *vq);
> > > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > > +					 struct virtio_device *vdev);
> > > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > > +					  struct virtio_device *vdev,
> > > > > > +					  struct vring vring);
> > > > > >
> > > > > >  /*
> > > > > >   * Helpers.
> > > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > >  		return NULL;
> > > > > >  	}
> > > > > >
> > > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > >  	return vq;
> > > > > >  }
> > > > > >
> > > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > > +{
> > > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > > +	struct vring_split vring;
> > > > > > +	int err;
> > > > > > +
> > > > > > +	if (num > _vq->num_max)
> > > > > > +		return -E2BIG;
> > > > > > +
> > > > > > +	switch (vq->vq.reset) {
> > > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > > +		return -ENOENT;
> > > > > > +
> > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > > +		if (vq->split.vring.num == num || !num)
> > > > > > +			break;
> > > > > > +
> > > > > > +		vring_free(_vq);
> > > > > > +
> > > > > > +		fallthrough;
> > > > > > +
> > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > > +		if (!num)
> > > > > > +			num = vq->split.vring.num;
> > > > > > +
> > > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > > +					       vq->split.vring_align,
> > > > > > +					       vq->weak_barriers,
> > > > > > +					       vq->split.may_reduce_num, num);
> > > > > > +		if (err)
> > > > > > +			return -ENOMEM;
> > > > > > +
> > > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > > +		if (err) {
> > > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > > +					 vring.queue,
> > > > > > +					 vring.dma_addr);
> > > > > > +			return -ENOMEM;
> > > > > > +		}
> > > > > > +
> > > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > +	}
> > > > > > +
> > > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > > +	vq->we_own_ring = true;
> > > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > > +
> > > > > > +	return 0;
> > > > > > +}
> > > > > > +
> > > > >
> > > > > I kind of dislike this state machine.
> > > > >
> > > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > > confusing.
> > > >
> > > > I'm removing it. I'll say in the function description that this function is
> > > > currently only called when vq has been reset. I'm no longer checking it based on
> > > > state.
> > > >
> > > > >
> > > > > And as Jason points out, when we want a resize then yes this currently
> > > > > implies reset but that is an implementation detail.
> > > > >
> > > > > There should be a way to just make these cases separate functions
> > > > > and then use them to compose consistent external APIs.
> > > >
> > > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > > >
> > > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > > to handle both scenarios?
> > > >
> > > > Or can anyone think of a better name. ^_^
> > > >
> > > > Thanks.
> > >
> > >
> > > I'd say resize should be called resize and reset should be called reset.
> >
> >
> > OK, I'll change it to resize here.
> >
> > But I want to know that when I implement virtio-net to support AF_XDP, its
> > requirement is to release all submitted buffers. Then should I add a new api
> > such as virtqueue_reset_vring()?
>
> Sounds like a reasonable name.
>
> > >
> > > The big issue is a sane API for resize. Ideally it would resubmit
> > > buffers which did not get used. Question is what to do
> > > about buffers which don't fit (if ring has been downsized)?
> > > Maybe a callback that will handle them?
> > > And then what? Queue them up and readd later? Drop?
> > > If we drop we should drop from the head not the tail ...
> >
> > It's a good idea, let's implement it later.
> >
> > Thanks.
>
> Well ... not sure how you are going to support resize
> if you don't know what to do with buffers that were
> in the ring.

The current solution is to call virtqueue_detach_unused_buf() to release buffers
before resize ring.

Thanks.


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-10 12:33               ` Xuan Zhuo
  (?)
@ 2022-03-10 13:04                 ` Michael S. Tsirkin
  -1 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10 13:04 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, Mar 10, 2022 at 08:33:30PM +0800, Xuan Zhuo wrote:
> On Thu, 10 Mar 2022 07:17:09 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> > > On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > > > virtio ring supports reset.
> > > > > > >
> > > > > > > Queue reset is divided into several stages.
> > > > > > >
> > > > > > > 1. notify device queue reset
> > > > > > > 2. vring release
> > > > > > > 3. attach new vring
> > > > > > > 4. notify device queue re-enable
> > > > > > >
> > > > > > > After the first step is completed, the vring reset operation can be
> > > > > > > performed. If the newly set vring num does not change, then just reset
> > > > > > > the vq related value.
> > > > > > >
> > > > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > > > function will exit, and the state of the vq will be the vring release
> > > > > > > state. You can call this function again to reallocate the vring.
> > > > > > >
> > > > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > > > vring, so they are retained when creating vq.
> > > > > > >
> > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > ---
> > > > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > > > >  1 file changed, 69 insertions(+)
> > > > > > >
> > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > > > >  			/* DMA address and size information */
> > > > > > >  			dma_addr_t queue_dma_addr;
> > > > > > >  			size_t queue_size_in_bytes;
> > > > > > > +
> > > > > > > +			/* The parameters for creating vrings are reserved for
> > > > > > > +			 * creating new vrings when enabling reset queue.
> > > > > > > +			 */
> > > > > > > +			u32 vring_align;
> > > > > > > +			bool may_reduce_num;
> > > > > > >  		} split;
> > > > > > >
> > > > > > >  		/* Available for packed ring */
> > > > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > > > >  #endif
> > > > > > >  };
> > > > > > >
> > > > > > > +static void vring_free(struct virtqueue *vq);
> > > > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > > > +					 struct virtio_device *vdev);
> > > > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > > > +					  struct virtio_device *vdev,
> > > > > > > +					  struct vring vring);
> > > > > > >
> > > > > > >  /*
> > > > > > >   * Helpers.
> > > > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > >  		return NULL;
> > > > > > >  	}
> > > > > > >
> > > > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > >  	return vq;
> > > > > > >  }
> > > > > > >
> > > > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > > > +{
> > > > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > > > +	struct vring_split vring;
> > > > > > > +	int err;
> > > > > > > +
> > > > > > > +	if (num > _vq->num_max)
> > > > > > > +		return -E2BIG;
> > > > > > > +
> > > > > > > +	switch (vq->vq.reset) {
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > > > +		return -ENOENT;
> > > > > > > +
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > > > +		if (vq->split.vring.num == num || !num)
> > > > > > > +			break;
> > > > > > > +
> > > > > > > +		vring_free(_vq);
> > > > > > > +
> > > > > > > +		fallthrough;
> > > > > > > +
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > > > +		if (!num)
> > > > > > > +			num = vq->split.vring.num;
> > > > > > > +
> > > > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > > > +					       vq->split.vring_align,
> > > > > > > +					       vq->weak_barriers,
> > > > > > > +					       vq->split.may_reduce_num, num);
> > > > > > > +		if (err)
> > > > > > > +			return -ENOMEM;
> > > > > > > +
> > > > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > > > +		if (err) {
> > > > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > > > +					 vring.queue,
> > > > > > > +					 vring.dma_addr);
> > > > > > > +			return -ENOMEM;
> > > > > > > +		}
> > > > > > > +
> > > > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > > > +	vq->we_own_ring = true;
> > > > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > > > +
> > > > > > > +	return 0;
> > > > > > > +}
> > > > > > > +
> > > > > >
> > > > > > I kind of dislike this state machine.
> > > > > >
> > > > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > > > confusing.
> > > > >
> > > > > I'm removing it. I'll say in the function description that this function is
> > > > > currently only called when vq has been reset. I'm no longer checking it based on
> > > > > state.
> > > > >
> > > > > >
> > > > > > And as Jason points out, when we want a resize then yes this currently
> > > > > > implies reset but that is an implementation detail.
> > > > > >
> > > > > > There should be a way to just make these cases separate functions
> > > > > > and then use them to compose consistent external APIs.
> > > > >
> > > > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > > > >
> > > > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > > > to handle both scenarios?
> > > > >
> > > > > Or can anyone think of a better name. ^_^
> > > > >
> > > > > Thanks.
> > > >
> > > >
> > > > I'd say resize should be called resize and reset should be called reset.
> > >
> > >
> > > OK, I'll change it to resize here.
> > >
> > > But I want to know that when I implement virtio-net to support AF_XDP, its
> > > requirement is to release all submitted buffers. Then should I add a new api
> > > such as virtqueue_reset_vring()?
> >
> > Sounds like a reasonable name.
> >
> > > >
> > > > The big issue is a sane API for resize. Ideally it would resubmit
> > > > buffers which did not get used. Question is what to do
> > > > about buffers which don't fit (if ring has been downsized)?
> > > > Maybe a callback that will handle them?
> > > > And then what? Queue them up and readd later? Drop?
> > > > If we drop we should drop from the head not the tail ...
> > >
> > > It's a good idea, let's implement it later.
> > >
> > > Thanks.
> >
> > Well ... not sure how you are going to support resize
> > if you don't know what to do with buffers that were
> > in the ring.
> 
> The current solution is to call virtqueue_detach_unused_buf() to release buffers
> before resize ring.
> 
> Thanks.

This requires basically a richer api:
- stop
- detach
- resize
- start

with a callback you would just have a resize, and the fact
it resets internally becomes an implementation detail.

-- 
MST


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10 13:04                 ` Michael S. Tsirkin
  0 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10 13:04 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Vadim Pasternak, linux-remoteproc, Alexei Starovoitov,
	virtualization, Alexander Gordeev, Anton Ivanov, linux-s390,
	Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, platform-driver-x86, Jesper Dangaard Brouer,
	Vasily Gorbik, Jeff Dike, linux-um, Mark Gross, Hans de Goede,
	kvm, Bjorn Andersson, Mathieu Poirier, netdev, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

On Thu, Mar 10, 2022 at 08:33:30PM +0800, Xuan Zhuo wrote:
> On Thu, 10 Mar 2022 07:17:09 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> > > On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > > > virtio ring supports reset.
> > > > > > >
> > > > > > > Queue reset is divided into several stages.
> > > > > > >
> > > > > > > 1. notify device queue reset
> > > > > > > 2. vring release
> > > > > > > 3. attach new vring
> > > > > > > 4. notify device queue re-enable
> > > > > > >
> > > > > > > After the first step is completed, the vring reset operation can be
> > > > > > > performed. If the newly set vring num does not change, then just reset
> > > > > > > the vq related value.
> > > > > > >
> > > > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > > > function will exit, and the state of the vq will be the vring release
> > > > > > > state. You can call this function again to reallocate the vring.
> > > > > > >
> > > > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > > > vring, so they are retained when creating vq.
> > > > > > >
> > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > ---
> > > > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > > > >  1 file changed, 69 insertions(+)
> > > > > > >
> > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > > > >  			/* DMA address and size information */
> > > > > > >  			dma_addr_t queue_dma_addr;
> > > > > > >  			size_t queue_size_in_bytes;
> > > > > > > +
> > > > > > > +			/* The parameters for creating vrings are reserved for
> > > > > > > +			 * creating new vrings when enabling reset queue.
> > > > > > > +			 */
> > > > > > > +			u32 vring_align;
> > > > > > > +			bool may_reduce_num;
> > > > > > >  		} split;
> > > > > > >
> > > > > > >  		/* Available for packed ring */
> > > > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > > > >  #endif
> > > > > > >  };
> > > > > > >
> > > > > > > +static void vring_free(struct virtqueue *vq);
> > > > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > > > +					 struct virtio_device *vdev);
> > > > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > > > +					  struct virtio_device *vdev,
> > > > > > > +					  struct vring vring);
> > > > > > >
> > > > > > >  /*
> > > > > > >   * Helpers.
> > > > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > >  		return NULL;
> > > > > > >  	}
> > > > > > >
> > > > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > >  	return vq;
> > > > > > >  }
> > > > > > >
> > > > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > > > +{
> > > > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > > > +	struct vring_split vring;
> > > > > > > +	int err;
> > > > > > > +
> > > > > > > +	if (num > _vq->num_max)
> > > > > > > +		return -E2BIG;
> > > > > > > +
> > > > > > > +	switch (vq->vq.reset) {
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > > > +		return -ENOENT;
> > > > > > > +
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > > > +		if (vq->split.vring.num == num || !num)
> > > > > > > +			break;
> > > > > > > +
> > > > > > > +		vring_free(_vq);
> > > > > > > +
> > > > > > > +		fallthrough;
> > > > > > > +
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > > > +		if (!num)
> > > > > > > +			num = vq->split.vring.num;
> > > > > > > +
> > > > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > > > +					       vq->split.vring_align,
> > > > > > > +					       vq->weak_barriers,
> > > > > > > +					       vq->split.may_reduce_num, num);
> > > > > > > +		if (err)
> > > > > > > +			return -ENOMEM;
> > > > > > > +
> > > > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > > > +		if (err) {
> > > > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > > > +					 vring.queue,
> > > > > > > +					 vring.dma_addr);
> > > > > > > +			return -ENOMEM;
> > > > > > > +		}
> > > > > > > +
> > > > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > > > +	vq->we_own_ring = true;
> > > > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > > > +
> > > > > > > +	return 0;
> > > > > > > +}
> > > > > > > +
> > > > > >
> > > > > > I kind of dislike this state machine.
> > > > > >
> > > > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > > > confusing.
> > > > >
> > > > > I'm removing it. I'll say in the function description that this function is
> > > > > currently only called when vq has been reset. I'm no longer checking it based on
> > > > > state.
> > > > >
> > > > > >
> > > > > > And as Jason points out, when we want a resize then yes this currently
> > > > > > implies reset but that is an implementation detail.
> > > > > >
> > > > > > There should be a way to just make these cases separate functions
> > > > > > and then use them to compose consistent external APIs.
> > > > >
> > > > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > > > >
> > > > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > > > to handle both scenarios?
> > > > >
> > > > > Or can anyone think of a better name. ^_^
> > > > >
> > > > > Thanks.
> > > >
> > > >
> > > > I'd say resize should be called resize and reset should be called reset.
> > >
> > >
> > > OK, I'll change it to resize here.
> > >
> > > But I want to know that when I implement virtio-net to support AF_XDP, its
> > > requirement is to release all submitted buffers. Then should I add a new api
> > > such as virtqueue_reset_vring()?
> >
> > Sounds like a reasonable name.
> >
> > > >
> > > > The big issue is a sane API for resize. Ideally it would resubmit
> > > > buffers which did not get used. Question is what to do
> > > > about buffers which don't fit (if ring has been downsized)?
> > > > Maybe a callback that will handle them?
> > > > And then what? Queue them up and readd later? Drop?
> > > > If we drop we should drop from the head not the tail ...
> > >
> > > It's a good idea, let's implement it later.
> > >
> > > Thanks.
> >
> > Well ... not sure how you are going to support resize
> > if you don't know what to do with buffers that were
> > in the ring.
> 
> The current solution is to call virtqueue_detach_unused_buf() to release buffers
> before resize ring.
> 
> Thanks.

This requires basically a richer api:
- stop
- detach
- resize
- start

with a callback you would just have a resize, and the fact
it resets internally becomes an implementation detail.

-- 
MST

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10 13:04                 ` Michael S. Tsirkin
  0 siblings, 0 replies; 218+ messages in thread
From: Michael S. Tsirkin @ 2022-03-10 13:04 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, Mar 10, 2022 at 08:33:30PM +0800, Xuan Zhuo wrote:
> On Thu, 10 Mar 2022 07:17:09 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> > > On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > > > virtio ring supports reset.
> > > > > > >
> > > > > > > Queue reset is divided into several stages.
> > > > > > >
> > > > > > > 1. notify device queue reset
> > > > > > > 2. vring release
> > > > > > > 3. attach new vring
> > > > > > > 4. notify device queue re-enable
> > > > > > >
> > > > > > > After the first step is completed, the vring reset operation can be
> > > > > > > performed. If the newly set vring num does not change, then just reset
> > > > > > > the vq related value.
> > > > > > >
> > > > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > > > function will exit, and the state of the vq will be the vring release
> > > > > > > state. You can call this function again to reallocate the vring.
> > > > > > >
> > > > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > > > vring, so they are retained when creating vq.
> > > > > > >
> > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > ---
> > > > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > > > >  1 file changed, 69 insertions(+)
> > > > > > >
> > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > > > >  			/* DMA address and size information */
> > > > > > >  			dma_addr_t queue_dma_addr;
> > > > > > >  			size_t queue_size_in_bytes;
> > > > > > > +
> > > > > > > +			/* The parameters for creating vrings are reserved for
> > > > > > > +			 * creating new vrings when enabling reset queue.
> > > > > > > +			 */
> > > > > > > +			u32 vring_align;
> > > > > > > +			bool may_reduce_num;
> > > > > > >  		} split;
> > > > > > >
> > > > > > >  		/* Available for packed ring */
> > > > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > > > >  #endif
> > > > > > >  };
> > > > > > >
> > > > > > > +static void vring_free(struct virtqueue *vq);
> > > > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > > > +					 struct virtio_device *vdev);
> > > > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > > > +					  struct virtio_device *vdev,
> > > > > > > +					  struct vring vring);
> > > > > > >
> > > > > > >  /*
> > > > > > >   * Helpers.
> > > > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > >  		return NULL;
> > > > > > >  	}
> > > > > > >
> > > > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > >  	return vq;
> > > > > > >  }
> > > > > > >
> > > > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > > > +{
> > > > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > > > +	struct vring_split vring;
> > > > > > > +	int err;
> > > > > > > +
> > > > > > > +	if (num > _vq->num_max)
> > > > > > > +		return -E2BIG;
> > > > > > > +
> > > > > > > +	switch (vq->vq.reset) {
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > > > +		return -ENOENT;
> > > > > > > +
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > > > +		if (vq->split.vring.num == num || !num)
> > > > > > > +			break;
> > > > > > > +
> > > > > > > +		vring_free(_vq);
> > > > > > > +
> > > > > > > +		fallthrough;
> > > > > > > +
> > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > > > +		if (!num)
> > > > > > > +			num = vq->split.vring.num;
> > > > > > > +
> > > > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > > > +					       vq->split.vring_align,
> > > > > > > +					       vq->weak_barriers,
> > > > > > > +					       vq->split.may_reduce_num, num);
> > > > > > > +		if (err)
> > > > > > > +			return -ENOMEM;
> > > > > > > +
> > > > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > > > +		if (err) {
> > > > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > > > +					 vring.queue,
> > > > > > > +					 vring.dma_addr);
> > > > > > > +			return -ENOMEM;
> > > > > > > +		}
> > > > > > > +
> > > > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > > +	}
> > > > > > > +
> > > > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > > > +	vq->we_own_ring = true;
> > > > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > > > +
> > > > > > > +	return 0;
> > > > > > > +}
> > > > > > > +
> > > > > >
> > > > > > I kind of dislike this state machine.
> > > > > >
> > > > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > > > confusing.
> > > > >
> > > > > I'm removing it. I'll say in the function description that this function is
> > > > > currently only called when vq has been reset. I'm no longer checking it based on
> > > > > state.
> > > > >
> > > > > >
> > > > > > And as Jason points out, when we want a resize then yes this currently
> > > > > > implies reset but that is an implementation detail.
> > > > > >
> > > > > > There should be a way to just make these cases separate functions
> > > > > > and then use them to compose consistent external APIs.
> > > > >
> > > > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > > > >
> > > > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > > > to handle both scenarios?
> > > > >
> > > > > Or can anyone think of a better name. ^_^
> > > > >
> > > > > Thanks.
> > > >
> > > >
> > > > I'd say resize should be called resize and reset should be called reset.
> > >
> > >
> > > OK, I'll change it to resize here.
> > >
> > > But I want to know that when I implement virtio-net to support AF_XDP, its
> > > requirement is to release all submitted buffers. Then should I add a new api
> > > such as virtqueue_reset_vring()?
> >
> > Sounds like a reasonable name.
> >
> > > >
> > > > The big issue is a sane API for resize. Ideally it would resubmit
> > > > buffers which did not get used. Question is what to do
> > > > about buffers which don't fit (if ring has been downsized)?
> > > > Maybe a callback that will handle them?
> > > > And then what? Queue them up and readd later? Drop?
> > > > If we drop we should drop from the head not the tail ...
> > >
> > > It's a good idea, let's implement it later.
> > >
> > > Thanks.
> >
> > Well ... not sure how you are going to support resize
> > if you don't know what to do with buffers that were
> > in the ring.
> 
> The current solution is to call virtqueue_detach_unused_buf() to release buffers
> before resize ring.
> 
> Thanks.

This requires basically a richer api:
- stop
- detach
- resize
- start

with a callback you would just have a resize, and the fact
it resets internally becomes an implementation detail.

-- 
MST


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-10 13:04                 ` Michael S. Tsirkin
  (?)
@ 2022-03-10 14:09                   ` Xuan Zhuo
  -1 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10 14:09 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: Vadim Pasternak, linux-remoteproc, Alexei Starovoitov,
	virtualization, Alexander Gordeev, Anton Ivanov, linux-s390,
	Johannes Berg, Daniel Borkmann, Richard Weinberger,
	Vincent Whitchurch, John Fastabend, Halil Pasic, Jakub Kicinski,
	Heiko Carstens, platform-driver-x86, Jesper Dangaard Brouer,
	Vasily Gorbik, Jeff Dike, linux-um, Mark Gross, Hans de Goede,
	kvm, Bjorn Andersson, Mathieu Poirier, netdev, Cornelia Huck,
	Sven Schnelle, bpf, David S. Miller

On Thu, 10 Mar 2022 08:04:27 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Thu, Mar 10, 2022 at 08:33:30PM +0800, Xuan Zhuo wrote:
> > On Thu, 10 Mar 2022 07:17:09 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> > > > On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > > > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > > > > virtio ring supports reset.
> > > > > > > >
> > > > > > > > Queue reset is divided into several stages.
> > > > > > > >
> > > > > > > > 1. notify device queue reset
> > > > > > > > 2. vring release
> > > > > > > > 3. attach new vring
> > > > > > > > 4. notify device queue re-enable
> > > > > > > >
> > > > > > > > After the first step is completed, the vring reset operation can be
> > > > > > > > performed. If the newly set vring num does not change, then just reset
> > > > > > > > the vq related value.
> > > > > > > >
> > > > > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > > > > function will exit, and the state of the vq will be the vring release
> > > > > > > > state. You can call this function again to reallocate the vring.
> > > > > > > >
> > > > > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > > > > vring, so they are retained when creating vq.
> > > > > > > >
> > > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > > ---
> > > > > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > > > > >  1 file changed, 69 insertions(+)
> > > > > > > >
> > > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > > > > >  			/* DMA address and size information */
> > > > > > > >  			dma_addr_t queue_dma_addr;
> > > > > > > >  			size_t queue_size_in_bytes;
> > > > > > > > +
> > > > > > > > +			/* The parameters for creating vrings are reserved for
> > > > > > > > +			 * creating new vrings when enabling reset queue.
> > > > > > > > +			 */
> > > > > > > > +			u32 vring_align;
> > > > > > > > +			bool may_reduce_num;
> > > > > > > >  		} split;
> > > > > > > >
> > > > > > > >  		/* Available for packed ring */
> > > > > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > > > > >  #endif
> > > > > > > >  };
> > > > > > > >
> > > > > > > > +static void vring_free(struct virtqueue *vq);
> > > > > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > > > > +					 struct virtio_device *vdev);
> > > > > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > > > > +					  struct virtio_device *vdev,
> > > > > > > > +					  struct vring vring);
> > > > > > > >
> > > > > > > >  /*
> > > > > > > >   * Helpers.
> > > > > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > > >  		return NULL;
> > > > > > > >  	}
> > > > > > > >
> > > > > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > > >  	return vq;
> > > > > > > >  }
> > > > > > > >
> > > > > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > > > > +{
> > > > > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > > > > +	struct vring_split vring;
> > > > > > > > +	int err;
> > > > > > > > +
> > > > > > > > +	if (num > _vq->num_max)
> > > > > > > > +		return -E2BIG;
> > > > > > > > +
> > > > > > > > +	switch (vq->vq.reset) {
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > > > > +		return -ENOENT;
> > > > > > > > +
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > > > > +		if (vq->split.vring.num == num || !num)
> > > > > > > > +			break;
> > > > > > > > +
> > > > > > > > +		vring_free(_vq);
> > > > > > > > +
> > > > > > > > +		fallthrough;
> > > > > > > > +
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > > > > +		if (!num)
> > > > > > > > +			num = vq->split.vring.num;
> > > > > > > > +
> > > > > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > > > > +					       vq->split.vring_align,
> > > > > > > > +					       vq->weak_barriers,
> > > > > > > > +					       vq->split.may_reduce_num, num);
> > > > > > > > +		if (err)
> > > > > > > > +			return -ENOMEM;
> > > > > > > > +
> > > > > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > > > > +		if (err) {
> > > > > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > > > > +					 vring.queue,
> > > > > > > > +					 vring.dma_addr);
> > > > > > > > +			return -ENOMEM;
> > > > > > > > +		}
> > > > > > > > +
> > > > > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > > > +	}
> > > > > > > > +
> > > > > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > > > > +	vq->we_own_ring = true;
> > > > > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > > > > +
> > > > > > > > +	return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > >
> > > > > > > I kind of dislike this state machine.
> > > > > > >
> > > > > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > > > > confusing.
> > > > > >
> > > > > > I'm removing it. I'll say in the function description that this function is
> > > > > > currently only called when vq has been reset. I'm no longer checking it based on
> > > > > > state.
> > > > > >
> > > > > > >
> > > > > > > And as Jason points out, when we want a resize then yes this currently
> > > > > > > implies reset but that is an implementation detail.
> > > > > > >
> > > > > > > There should be a way to just make these cases separate functions
> > > > > > > and then use them to compose consistent external APIs.
> > > > > >
> > > > > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > > > > >
> > > > > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > > > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > > > > to handle both scenarios?
> > > > > >
> > > > > > Or can anyone think of a better name. ^_^
> > > > > >
> > > > > > Thanks.
> > > > >
> > > > >
> > > > > I'd say resize should be called resize and reset should be called reset.
> > > >
> > > >
> > > > OK, I'll change it to resize here.
> > > >
> > > > But I want to know that when I implement virtio-net to support AF_XDP, its
> > > > requirement is to release all submitted buffers. Then should I add a new api
> > > > such as virtqueue_reset_vring()?
> > >
> > > Sounds like a reasonable name.
> > >
> > > > >
> > > > > The big issue is a sane API for resize. Ideally it would resubmit
> > > > > buffers which did not get used. Question is what to do
> > > > > about buffers which don't fit (if ring has been downsized)?
> > > > > Maybe a callback that will handle them?
> > > > > And then what? Queue them up and readd later? Drop?
> > > > > If we drop we should drop from the head not the tail ...
> > > >
> > > > It's a good idea, let's implement it later.
> > > >
> > > > Thanks.
> > >
> > > Well ... not sure how you are going to support resize
> > > if you don't know what to do with buffers that were
> > > in the ring.
> >
> > The current solution is to call virtqueue_detach_unused_buf() to release buffers
> > before resize ring.
> >
> > Thanks.
>
> This requires basically a richer api:
> - stop
> - detach
> - resize
> - start

Yes, that's how it is currently implemented.

>
> with a callback you would just have a resize, and the fact
> it resets internally becomes an implementation detail.


I think, I understand what you mean, we encapsulate the following code into a
function as an external interface.

int virtqueue_resize(vq, callback)
{
	err = virtqueue_reset(sq->vq);
	if (err) {
		netif_start_subqueue(vi->dev, qindex);
		goto err;
	}

	/* detach */
	while ((buf = virtqueue_detach_unused_buf(sq->vq)) != NULL) {
		callback(vq, buf);
	}

	err = virtqueue_resize(sq->vq, ring_num);
	if (err)
		goto err;

	err = virtqueue_enable_resetq(sq->vq);
	if (err)
		goto err;
}

Thanks.

>
> --
> MST
>
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10 14:09                   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10 14:09 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, 10 Mar 2022 08:04:27 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Thu, Mar 10, 2022 at 08:33:30PM +0800, Xuan Zhuo wrote:
> > On Thu, 10 Mar 2022 07:17:09 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> > > > On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > > > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > > > > virtio ring supports reset.
> > > > > > > >
> > > > > > > > Queue reset is divided into several stages.
> > > > > > > >
> > > > > > > > 1. notify device queue reset
> > > > > > > > 2. vring release
> > > > > > > > 3. attach new vring
> > > > > > > > 4. notify device queue re-enable
> > > > > > > >
> > > > > > > > After the first step is completed, the vring reset operation can be
> > > > > > > > performed. If the newly set vring num does not change, then just reset
> > > > > > > > the vq related value.
> > > > > > > >
> > > > > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > > > > function will exit, and the state of the vq will be the vring release
> > > > > > > > state. You can call this function again to reallocate the vring.
> > > > > > > >
> > > > > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > > > > vring, so they are retained when creating vq.
> > > > > > > >
> > > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > > ---
> > > > > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > > > > >  1 file changed, 69 insertions(+)
> > > > > > > >
> > > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > > > > >  			/* DMA address and size information */
> > > > > > > >  			dma_addr_t queue_dma_addr;
> > > > > > > >  			size_t queue_size_in_bytes;
> > > > > > > > +
> > > > > > > > +			/* The parameters for creating vrings are reserved for
> > > > > > > > +			 * creating new vrings when enabling reset queue.
> > > > > > > > +			 */
> > > > > > > > +			u32 vring_align;
> > > > > > > > +			bool may_reduce_num;
> > > > > > > >  		} split;
> > > > > > > >
> > > > > > > >  		/* Available for packed ring */
> > > > > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > > > > >  #endif
> > > > > > > >  };
> > > > > > > >
> > > > > > > > +static void vring_free(struct virtqueue *vq);
> > > > > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > > > > +					 struct virtio_device *vdev);
> > > > > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > > > > +					  struct virtio_device *vdev,
> > > > > > > > +					  struct vring vring);
> > > > > > > >
> > > > > > > >  /*
> > > > > > > >   * Helpers.
> > > > > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > > >  		return NULL;
> > > > > > > >  	}
> > > > > > > >
> > > > > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > > >  	return vq;
> > > > > > > >  }
> > > > > > > >
> > > > > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > > > > +{
> > > > > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > > > > +	struct vring_split vring;
> > > > > > > > +	int err;
> > > > > > > > +
> > > > > > > > +	if (num > _vq->num_max)
> > > > > > > > +		return -E2BIG;
> > > > > > > > +
> > > > > > > > +	switch (vq->vq.reset) {
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > > > > +		return -ENOENT;
> > > > > > > > +
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > > > > +		if (vq->split.vring.num == num || !num)
> > > > > > > > +			break;
> > > > > > > > +
> > > > > > > > +		vring_free(_vq);
> > > > > > > > +
> > > > > > > > +		fallthrough;
> > > > > > > > +
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > > > > +		if (!num)
> > > > > > > > +			num = vq->split.vring.num;
> > > > > > > > +
> > > > > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > > > > +					       vq->split.vring_align,
> > > > > > > > +					       vq->weak_barriers,
> > > > > > > > +					       vq->split.may_reduce_num, num);
> > > > > > > > +		if (err)
> > > > > > > > +			return -ENOMEM;
> > > > > > > > +
> > > > > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > > > > +		if (err) {
> > > > > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > > > > +					 vring.queue,
> > > > > > > > +					 vring.dma_addr);
> > > > > > > > +			return -ENOMEM;
> > > > > > > > +		}
> > > > > > > > +
> > > > > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > > > +	}
> > > > > > > > +
> > > > > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > > > > +	vq->we_own_ring = true;
> > > > > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > > > > +
> > > > > > > > +	return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > >
> > > > > > > I kind of dislike this state machine.
> > > > > > >
> > > > > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > > > > confusing.
> > > > > >
> > > > > > I'm removing it. I'll say in the function description that this function is
> > > > > > currently only called when vq has been reset. I'm no longer checking it based on
> > > > > > state.
> > > > > >
> > > > > > >
> > > > > > > And as Jason points out, when we want a resize then yes this currently
> > > > > > > implies reset but that is an implementation detail.
> > > > > > >
> > > > > > > There should be a way to just make these cases separate functions
> > > > > > > and then use them to compose consistent external APIs.
> > > > > >
> > > > > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > > > > >
> > > > > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > > > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > > > > to handle both scenarios?
> > > > > >
> > > > > > Or can anyone think of a better name. ^_^
> > > > > >
> > > > > > Thanks.
> > > > >
> > > > >
> > > > > I'd say resize should be called resize and reset should be called reset.
> > > >
> > > >
> > > > OK, I'll change it to resize here.
> > > >
> > > > But I want to know that when I implement virtio-net to support AF_XDP, its
> > > > requirement is to release all submitted buffers. Then should I add a new api
> > > > such as virtqueue_reset_vring()?
> > >
> > > Sounds like a reasonable name.
> > >
> > > > >
> > > > > The big issue is a sane API for resize. Ideally it would resubmit
> > > > > buffers which did not get used. Question is what to do
> > > > > about buffers which don't fit (if ring has been downsized)?
> > > > > Maybe a callback that will handle them?
> > > > > And then what? Queue them up and readd later? Drop?
> > > > > If we drop we should drop from the head not the tail ...
> > > >
> > > > It's a good idea, let's implement it later.
> > > >
> > > > Thanks.
> > >
> > > Well ... not sure how you are going to support resize
> > > if you don't know what to do with buffers that were
> > > in the ring.
> >
> > The current solution is to call virtqueue_detach_unused_buf() to release buffers
> > before resize ring.
> >
> > Thanks.
>
> This requires basically a richer api:
> - stop
> - detach
> - resize
> - start

Yes, that's how it is currently implemented.

>
> with a callback you would just have a resize, and the fact
> it resets internally becomes an implementation detail.


I think, I understand what you mean, we encapsulate the following code into a
function as an external interface.

int virtqueue_resize(vq, callback)
{
	err = virtqueue_reset(sq->vq);
	if (err) {
		netif_start_subqueue(vi->dev, qindex);
		goto err;
	}

	/* detach */
	while ((buf = virtqueue_detach_unused_buf(sq->vq)) != NULL) {
		callback(vq, buf);
	}

	err = virtqueue_resize(sq->vq, ring_num);
	if (err)
		goto err;

	err = virtqueue_enable_resetq(sq->vq);
	if (err)
		goto err;
}

Thanks.

>
> --
> MST
>

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-10 14:09                   ` Xuan Zhuo
  0 siblings, 0 replies; 218+ messages in thread
From: Xuan Zhuo @ 2022-03-10 14:09 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtualization, netdev, Jeff Dike, Richard Weinberger,
	Anton Ivanov, Jason Wang, David S. Miller, Jakub Kicinski,
	Hans de Goede, Mark Gross, Vadim Pasternak, Bjorn Andersson,
	Mathieu Poirier, Cornelia Huck, Halil Pasic, Heiko Carstens,
	Vasily Gorbik, Christian Borntraeger, Alexander Gordeev,
	Sven Schnelle, Alexei Starovoitov, Daniel Borkmann,
	Jesper Dangaard Brouer, John Fastabend, Johannes Berg,
	Vincent Whitchurch, linux-um, platform-driver-x86,
	linux-remoteproc, linux-s390, kvm, bpf

On Thu, 10 Mar 2022 08:04:27 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> On Thu, Mar 10, 2022 at 08:33:30PM +0800, Xuan Zhuo wrote:
> > On Thu, 10 Mar 2022 07:17:09 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > On Thu, Mar 10, 2022 at 04:14:16PM +0800, Xuan Zhuo wrote:
> > > > On Thu, 10 Mar 2022 03:07:22 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > On Thu, Mar 10, 2022 at 03:17:03PM +0800, Xuan Zhuo wrote:
> > > > > > On Thu, 10 Mar 2022 02:00:39 -0500, "Michael S. Tsirkin" <mst@redhat.com> wrote:
> > > > > > > On Tue, Mar 08, 2022 at 08:35:01PM +0800, Xuan Zhuo wrote:
> > > > > > > > virtio ring supports reset.
> > > > > > > >
> > > > > > > > Queue reset is divided into several stages.
> > > > > > > >
> > > > > > > > 1. notify device queue reset
> > > > > > > > 2. vring release
> > > > > > > > 3. attach new vring
> > > > > > > > 4. notify device queue re-enable
> > > > > > > >
> > > > > > > > After the first step is completed, the vring reset operation can be
> > > > > > > > performed. If the newly set vring num does not change, then just reset
> > > > > > > > the vq related value.
> > > > > > > >
> > > > > > > > Otherwise, the vring will be released and the vring will be reallocated.
> > > > > > > > And the vring will be attached to the vq. If this process fails, the
> > > > > > > > function will exit, and the state of the vq will be the vring release
> > > > > > > > state. You can call this function again to reallocate the vring.
> > > > > > > >
> > > > > > > > In addition, vring_align, may_reduce_num are necessary for reallocating
> > > > > > > > vring, so they are retained when creating vq.
> > > > > > > >
> > > > > > > > Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
> > > > > > > > ---
> > > > > > > >  drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
> > > > > > > >  1 file changed, 69 insertions(+)
> > > > > > > >
> > > > > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
> > > > > > > > index e0422c04c903..148fb1fd3d5a 100644
> > > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > > @@ -158,6 +158,12 @@ struct vring_virtqueue {
> > > > > > > >  			/* DMA address and size information */
> > > > > > > >  			dma_addr_t queue_dma_addr;
> > > > > > > >  			size_t queue_size_in_bytes;
> > > > > > > > +
> > > > > > > > +			/* The parameters for creating vrings are reserved for
> > > > > > > > +			 * creating new vrings when enabling reset queue.
> > > > > > > > +			 */
> > > > > > > > +			u32 vring_align;
> > > > > > > > +			bool may_reduce_num;
> > > > > > > >  		} split;
> > > > > > > >
> > > > > > > >  		/* Available for packed ring */
> > > > > > > > @@ -217,6 +223,12 @@ struct vring_virtqueue {
> > > > > > > >  #endif
> > > > > > > >  };
> > > > > > > >
> > > > > > > > +static void vring_free(struct virtqueue *vq);
> > > > > > > > +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
> > > > > > > > +					 struct virtio_device *vdev);
> > > > > > > > +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
> > > > > > > > +					  struct virtio_device *vdev,
> > > > > > > > +					  struct vring vring);
> > > > > > > >
> > > > > > > >  /*
> > > > > > > >   * Helpers.
> > > > > > > > @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > > >  		return NULL;
> > > > > > > >  	}
> > > > > > > >
> > > > > > > > +	to_vvq(vq)->split.vring_align = vring_align;
> > > > > > > > +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
> > > > > > > >  	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
> > > > > > > >  	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > > >  	to_vvq(vq)->we_own_ring = true;
> > > > > > > > @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
> > > > > > > >  	return vq;
> > > > > > > >  }
> > > > > > > >
> > > > > > > > +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
> > > > > > > > +{
> > > > > > > > +	struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > > +	struct virtio_device *vdev = _vq->vdev;
> > > > > > > > +	struct vring_split vring;
> > > > > > > > +	int err;
> > > > > > > > +
> > > > > > > > +	if (num > _vq->num_max)
> > > > > > > > +		return -E2BIG;
> > > > > > > > +
> > > > > > > > +	switch (vq->vq.reset) {
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_NONE:
> > > > > > > > +		return -ENOENT;
> > > > > > > > +
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_DEVICE:
> > > > > > > > +		if (vq->split.vring.num == num || !num)
> > > > > > > > +			break;
> > > > > > > > +
> > > > > > > > +		vring_free(_vq);
> > > > > > > > +
> > > > > > > > +		fallthrough;
> > > > > > > > +
> > > > > > > > +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
> > > > > > > > +		if (!num)
> > > > > > > > +			num = vq->split.vring.num;
> > > > > > > > +
> > > > > > > > +		err = vring_create_vring_split(&vring, vdev,
> > > > > > > > +					       vq->split.vring_align,
> > > > > > > > +					       vq->weak_barriers,
> > > > > > > > +					       vq->split.may_reduce_num, num);
> > > > > > > > +		if (err)
> > > > > > > > +			return -ENOMEM;
> > > > > > > > +
> > > > > > > > +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
> > > > > > > > +		if (err) {
> > > > > > > > +			vring_free_queue(vdev, vring.queue_size_in_bytes,
> > > > > > > > +					 vring.queue,
> > > > > > > > +					 vring.dma_addr);
> > > > > > > > +			return -ENOMEM;
> > > > > > > > +		}
> > > > > > > > +
> > > > > > > > +		vq->split.queue_dma_addr = vring.dma_addr;
> > > > > > > > +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
> > > > > > > > +	}
> > > > > > > > +
> > > > > > > > +	__vring_virtqueue_init_split(vq, vdev);
> > > > > > > > +	vq->we_own_ring = true;
> > > > > > > > +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
> > > > > > > > +
> > > > > > > > +	return 0;
> > > > > > > > +}
> > > > > > > > +
> > > > > > >
> > > > > > > I kind of dislike this state machine.
> > > > > > >
> > > > > > > Hacks like special-casing num = 0 to mean "reset" are especially
> > > > > > > confusing.
> > > > > >
> > > > > > I'm removing it. I'll say in the function description that this function is
> > > > > > currently only called when vq has been reset. I'm no longer checking it based on
> > > > > > state.
> > > > > >
> > > > > > >
> > > > > > > And as Jason points out, when we want a resize then yes this currently
> > > > > > > implies reset but that is an implementation detail.
> > > > > > >
> > > > > > > There should be a way to just make these cases separate functions
> > > > > > > and then use them to compose consistent external APIs.
> > > > > >
> > > > > > Yes, virtqueue_resize_split() is fine for ethtool -G.
> > > > > >
> > > > > > But in the case of AF_XDP, just execute reset to free the buffer. The name
> > > > > > virtqueue_reset_vring_split() I think can cover both cases. Or we use two apis
> > > > > > to handle both scenarios?
> > > > > >
> > > > > > Or can anyone think of a better name. ^_^
> > > > > >
> > > > > > Thanks.
> > > > >
> > > > >
> > > > > I'd say resize should be called resize and reset should be called reset.
> > > >
> > > >
> > > > OK, I'll change it to resize here.
> > > >
> > > > But I want to know that when I implement virtio-net to support AF_XDP, its
> > > > requirement is to release all submitted buffers. Then should I add a new api
> > > > such as virtqueue_reset_vring()?
> > >
> > > Sounds like a reasonable name.
> > >
> > > > >
> > > > > The big issue is a sane API for resize. Ideally it would resubmit
> > > > > buffers which did not get used. Question is what to do
> > > > > about buffers which don't fit (if ring has been downsized)?
> > > > > Maybe a callback that will handle them?
> > > > > And then what? Queue them up and readd later? Drop?
> > > > > If we drop we should drop from the head not the tail ...
> > > >
> > > > It's a good idea, let's implement it later.
> > > >
> > > > Thanks.
> > >
> > > Well ... not sure how you are going to support resize
> > > if you don't know what to do with buffers that were
> > > in the ring.
> >
> > The current solution is to call virtqueue_detach_unused_buf() to release buffers
> > before resize ring.
> >
> > Thanks.
>
> This requires basically a richer api:
> - stop
> - detach
> - resize
> - start

Yes, that's how it is currently implemented.

>
> with a callback you would just have a resize, and the fact
> it resets internally becomes an implementation detail.


I think, I understand what you mean, we encapsulate the following code into a
function as an external interface.

int virtqueue_resize(vq, callback)
{
	err = virtqueue_reset(sq->vq);
	if (err) {
		netif_start_subqueue(vi->dev, qindex);
		goto err;
	}

	/* detach */
	while ((buf = virtqueue_detach_unused_buf(sq->vq)) != NULL) {
		callback(vq, buf);
	}

	err = virtqueue_resize(sq->vq, ring_num);
	if (err)
		goto err;

	err = virtqueue_enable_resetq(sq->vq);
	if (err)
		goto err;
}

Thanks.

>
> --
> MST
>

_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
  2022-03-10  4:46       ` Xuan Zhuo
  (?)
@ 2022-03-11  5:01         ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-11  5:01 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev


在 2022/3/10 下午12:46, Xuan Zhuo 写道:
> On Wed, 9 Mar 2022 15:55:44 +0800, Jason Wang <jasowang@redhat.com> wrote:
>> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
>>> virtio ring supports reset.
>>>
>>> Queue reset is divided into several stages.
>>>
>>> 1. notify device queue reset
>>> 2. vring release
>>> 3. attach new vring
>>> 4. notify device queue re-enable
>>>
>>> After the first step is completed, the vring reset operation can be
>>> performed. If the newly set vring num does not change, then just reset
>>> the vq related value.
>>>
>>> Otherwise, the vring will be released and the vring will be reallocated.
>>> And the vring will be attached to the vq. If this process fails, the
>>> function will exit, and the state of the vq will be the vring release
>>> state. You can call this function again to reallocate the vring.
>>>
>>> In addition, vring_align, may_reduce_num are necessary for reallocating
>>> vring, so they are retained when creating vq.
>>>
>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>>> ---
>>>    drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
>>>    1 file changed, 69 insertions(+)
>>>
>>> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
>>> index e0422c04c903..148fb1fd3d5a 100644
>>> --- a/drivers/virtio/virtio_ring.c
>>> +++ b/drivers/virtio/virtio_ring.c
>>> @@ -158,6 +158,12 @@ struct vring_virtqueue {
>>>    			/* DMA address and size information */
>>>    			dma_addr_t queue_dma_addr;
>>>    			size_t queue_size_in_bytes;
>>> +
>>> +			/* The parameters for creating vrings are reserved for
>>> +			 * creating new vrings when enabling reset queue.
>>> +			 */
>>> +			u32 vring_align;
>>> +			bool may_reduce_num;
>>>    		} split;
>>>
>>>    		/* Available for packed ring */
>>> @@ -217,6 +223,12 @@ struct vring_virtqueue {
>>>    #endif
>>>    };
>>>
>>> +static void vring_free(struct virtqueue *vq);
>>> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>>> +					 struct virtio_device *vdev);
>>> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>>> +					  struct virtio_device *vdev,
>>> +					  struct vring vring);
>>>
>>>    /*
>>>     * Helpers.
>>> @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
>>>    		return NULL;
>>>    	}
>>>
>>> +	to_vvq(vq)->split.vring_align = vring_align;
>>> +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
>>>    	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
>>>    	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>>>    	to_vvq(vq)->we_own_ring = true;
>>> @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
>>>    	return vq;
>>>    }
>>>
>>> +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
>>> +{
>>
>> So what this function does is to resize the virtqueue actually, I
>> suggest to rename it as virtqueue_resize_split().
> In addition to resize, when num is 0, the function is to reinitialize vq ring
> related variables. For example avail_idx_shadow.


We need to move those logic to virtio_reset_vq() (I think we agree to 
have a better name of it).


> So I think 'reset' is more appropriate.


The name is confusing at least to me, since we've already had 
virtio_reset_vq() and most of the logic is to do the resize.

Thanks


>
> Thanks.
>
>>
>>> +	struct vring_virtqueue *vq = to_vvq(_vq);
>>> +	struct virtio_device *vdev = _vq->vdev;
>>> +	struct vring_split vring;
>>> +	int err;
>>> +
>>> +	if (num > _vq->num_max)
>>> +		return -E2BIG;
>>> +
>>> +	switch (vq->vq.reset) {
>>> +	case VIRTIO_VQ_RESET_STEP_NONE:
>>> +		return -ENOENT;
>>> +
>>> +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
>>> +	case VIRTIO_VQ_RESET_STEP_DEVICE:
>>> +		if (vq->split.vring.num == num || !num)
>>> +			break;
>>> +
>>> +		vring_free(_vq);
>>> +
>>> +		fallthrough;
>>> +
>>> +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
>>> +		if (!num)
>>> +			num = vq->split.vring.num;
>>> +
>>> +		err = vring_create_vring_split(&vring, vdev,
>>> +					       vq->split.vring_align,
>>> +					       vq->weak_barriers,
>>> +					       vq->split.may_reduce_num, num);
>>> +		if (err)
>>> +			return -ENOMEM;
>>
>> We'd better need a safe fallback here like:
>>
>> If we can't allocate new memory, we can keep using the current one.
>> Otherwise an ethtool -G fail may make the device not usable.
>>
>> This could be done by not freeing the old vring and virtqueue states
>> until new is allocated.
>>
>>
>>> +
>>> +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
>>> +		if (err) {
>>> +			vring_free_queue(vdev, vring.queue_size_in_bytes,
>>> +					 vring.queue,
>>> +					 vring.dma_addr);
>>> +			return -ENOMEM;
>>> +		}
>>> +
>>> +		vq->split.queue_dma_addr = vring.dma_addr;
>>> +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>>> +	}
>>> +
>>> +	__vring_virtqueue_init_split(vq, vdev);
>>> +	vq->we_own_ring = true;
>>
>> This seems wrong, we have the transport (rproc/mlxtbf) that allocate the
>> vring by themselves. I think we need to fail the resize for we_own_ring
>> == false.
>>
>> Thanks
>>
>>
>>
>>> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>
>>>    /*
>>>     * Packed ring specific functions - *_packed().
>>> @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>>>    static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>>>    					 struct virtio_device *vdev)
>>>    {
>>> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
>>> +
>>>    	vq->packed_ring = false;
>>>    	vq->we_own_ring = false;
>>>    	vq->broken = false;


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-11  5:01         ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-11  5:01 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/10 下午12:46, Xuan Zhuo 写道:
> On Wed, 9 Mar 2022 15:55:44 +0800, Jason Wang <jasowang@redhat.com> wrote:
>> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
>>> virtio ring supports reset.
>>>
>>> Queue reset is divided into several stages.
>>>
>>> 1. notify device queue reset
>>> 2. vring release
>>> 3. attach new vring
>>> 4. notify device queue re-enable
>>>
>>> After the first step is completed, the vring reset operation can be
>>> performed. If the newly set vring num does not change, then just reset
>>> the vq related value.
>>>
>>> Otherwise, the vring will be released and the vring will be reallocated.
>>> And the vring will be attached to the vq. If this process fails, the
>>> function will exit, and the state of the vq will be the vring release
>>> state. You can call this function again to reallocate the vring.
>>>
>>> In addition, vring_align, may_reduce_num are necessary for reallocating
>>> vring, so they are retained when creating vq.
>>>
>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>>> ---
>>>    drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
>>>    1 file changed, 69 insertions(+)
>>>
>>> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
>>> index e0422c04c903..148fb1fd3d5a 100644
>>> --- a/drivers/virtio/virtio_ring.c
>>> +++ b/drivers/virtio/virtio_ring.c
>>> @@ -158,6 +158,12 @@ struct vring_virtqueue {
>>>    			/* DMA address and size information */
>>>    			dma_addr_t queue_dma_addr;
>>>    			size_t queue_size_in_bytes;
>>> +
>>> +			/* The parameters for creating vrings are reserved for
>>> +			 * creating new vrings when enabling reset queue.
>>> +			 */
>>> +			u32 vring_align;
>>> +			bool may_reduce_num;
>>>    		} split;
>>>
>>>    		/* Available for packed ring */
>>> @@ -217,6 +223,12 @@ struct vring_virtqueue {
>>>    #endif
>>>    };
>>>
>>> +static void vring_free(struct virtqueue *vq);
>>> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>>> +					 struct virtio_device *vdev);
>>> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>>> +					  struct virtio_device *vdev,
>>> +					  struct vring vring);
>>>
>>>    /*
>>>     * Helpers.
>>> @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
>>>    		return NULL;
>>>    	}
>>>
>>> +	to_vvq(vq)->split.vring_align = vring_align;
>>> +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
>>>    	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
>>>    	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>>>    	to_vvq(vq)->we_own_ring = true;
>>> @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
>>>    	return vq;
>>>    }
>>>
>>> +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
>>> +{
>>
>> So what this function does is to resize the virtqueue actually, I
>> suggest to rename it as virtqueue_resize_split().
> In addition to resize, when num is 0, the function is to reinitialize vq ring
> related variables. For example avail_idx_shadow.


We need to move those logic to virtio_reset_vq() (I think we agree to 
have a better name of it).


> So I think 'reset' is more appropriate.


The name is confusing at least to me, since we've already had 
virtio_reset_vq() and most of the logic is to do the resize.

Thanks


>
> Thanks.
>
>>
>>> +	struct vring_virtqueue *vq = to_vvq(_vq);
>>> +	struct virtio_device *vdev = _vq->vdev;
>>> +	struct vring_split vring;
>>> +	int err;
>>> +
>>> +	if (num > _vq->num_max)
>>> +		return -E2BIG;
>>> +
>>> +	switch (vq->vq.reset) {
>>> +	case VIRTIO_VQ_RESET_STEP_NONE:
>>> +		return -ENOENT;
>>> +
>>> +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
>>> +	case VIRTIO_VQ_RESET_STEP_DEVICE:
>>> +		if (vq->split.vring.num == num || !num)
>>> +			break;
>>> +
>>> +		vring_free(_vq);
>>> +
>>> +		fallthrough;
>>> +
>>> +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
>>> +		if (!num)
>>> +			num = vq->split.vring.num;
>>> +
>>> +		err = vring_create_vring_split(&vring, vdev,
>>> +					       vq->split.vring_align,
>>> +					       vq->weak_barriers,
>>> +					       vq->split.may_reduce_num, num);
>>> +		if (err)
>>> +			return -ENOMEM;
>>
>> We'd better need a safe fallback here like:
>>
>> If we can't allocate new memory, we can keep using the current one.
>> Otherwise an ethtool -G fail may make the device not usable.
>>
>> This could be done by not freeing the old vring and virtqueue states
>> until new is allocated.
>>
>>
>>> +
>>> +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
>>> +		if (err) {
>>> +			vring_free_queue(vdev, vring.queue_size_in_bytes,
>>> +					 vring.queue,
>>> +					 vring.dma_addr);
>>> +			return -ENOMEM;
>>> +		}
>>> +
>>> +		vq->split.queue_dma_addr = vring.dma_addr;
>>> +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>>> +	}
>>> +
>>> +	__vring_virtqueue_init_split(vq, vdev);
>>> +	vq->we_own_ring = true;
>>
>> This seems wrong, we have the transport (rproc/mlxtbf) that allocate the
>> vring by themselves. I think we need to fail the resize for we_own_ring
>> == false.
>>
>> Thanks
>>
>>
>>
>>> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>
>>>    /*
>>>     * Packed ring specific functions - *_packed().
>>> @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>>>    static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>>>    					 struct virtio_device *vdev)
>>>    {
>>> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
>>> +
>>>    	vq->packed_ring = false;
>>>    	vq->we_own_ring = false;
>>>    	vq->broken = false;

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split()
@ 2022-03-11  5:01         ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-11  5:01 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev


在 2022/3/10 下午12:46, Xuan Zhuo 写道:
> On Wed, 9 Mar 2022 15:55:44 +0800, Jason Wang <jasowang@redhat.com> wrote:
>> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
>>> virtio ring supports reset.
>>>
>>> Queue reset is divided into several stages.
>>>
>>> 1. notify device queue reset
>>> 2. vring release
>>> 3. attach new vring
>>> 4. notify device queue re-enable
>>>
>>> After the first step is completed, the vring reset operation can be
>>> performed. If the newly set vring num does not change, then just reset
>>> the vq related value.
>>>
>>> Otherwise, the vring will be released and the vring will be reallocated.
>>> And the vring will be attached to the vq. If this process fails, the
>>> function will exit, and the state of the vq will be the vring release
>>> state. You can call this function again to reallocate the vring.
>>>
>>> In addition, vring_align, may_reduce_num are necessary for reallocating
>>> vring, so they are retained when creating vq.
>>>
>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>>> ---
>>>    drivers/virtio/virtio_ring.c | 69 ++++++++++++++++++++++++++++++++++++
>>>    1 file changed, 69 insertions(+)
>>>
>>> diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
>>> index e0422c04c903..148fb1fd3d5a 100644
>>> --- a/drivers/virtio/virtio_ring.c
>>> +++ b/drivers/virtio/virtio_ring.c
>>> @@ -158,6 +158,12 @@ struct vring_virtqueue {
>>>    			/* DMA address and size information */
>>>    			dma_addr_t queue_dma_addr;
>>>    			size_t queue_size_in_bytes;
>>> +
>>> +			/* The parameters for creating vrings are reserved for
>>> +			 * creating new vrings when enabling reset queue.
>>> +			 */
>>> +			u32 vring_align;
>>> +			bool may_reduce_num;
>>>    		} split;
>>>
>>>    		/* Available for packed ring */
>>> @@ -217,6 +223,12 @@ struct vring_virtqueue {
>>>    #endif
>>>    };
>>>
>>> +static void vring_free(struct virtqueue *vq);
>>> +static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>>> +					 struct virtio_device *vdev);
>>> +static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>>> +					  struct virtio_device *vdev,
>>> +					  struct vring vring);
>>>
>>>    /*
>>>     * Helpers.
>>> @@ -1012,6 +1024,8 @@ static struct virtqueue *vring_create_virtqueue_split(
>>>    		return NULL;
>>>    	}
>>>
>>> +	to_vvq(vq)->split.vring_align = vring_align;
>>> +	to_vvq(vq)->split.may_reduce_num = may_reduce_num;
>>>    	to_vvq(vq)->split.queue_dma_addr = vring.dma_addr;
>>>    	to_vvq(vq)->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>>>    	to_vvq(vq)->we_own_ring = true;
>>> @@ -1019,6 +1033,59 @@ static struct virtqueue *vring_create_virtqueue_split(
>>>    	return vq;
>>>    }
>>>
>>> +static int virtqueue_reset_vring_split(struct virtqueue *_vq, u32 num)
>>> +{
>>
>> So what this function does is to resize the virtqueue actually, I
>> suggest to rename it as virtqueue_resize_split().
> In addition to resize, when num is 0, the function is to reinitialize vq ring
> related variables. For example avail_idx_shadow.


We need to move those logic to virtio_reset_vq() (I think we agree to 
have a better name of it).


> So I think 'reset' is more appropriate.


The name is confusing at least to me, since we've already had 
virtio_reset_vq() and most of the logic is to do the resize.

Thanks


>
> Thanks.
>
>>
>>> +	struct vring_virtqueue *vq = to_vvq(_vq);
>>> +	struct virtio_device *vdev = _vq->vdev;
>>> +	struct vring_split vring;
>>> +	int err;
>>> +
>>> +	if (num > _vq->num_max)
>>> +		return -E2BIG;
>>> +
>>> +	switch (vq->vq.reset) {
>>> +	case VIRTIO_VQ_RESET_STEP_NONE:
>>> +		return -ENOENT;
>>> +
>>> +	case VIRTIO_VQ_RESET_STEP_VRING_ATTACH:
>>> +	case VIRTIO_VQ_RESET_STEP_DEVICE:
>>> +		if (vq->split.vring.num == num || !num)
>>> +			break;
>>> +
>>> +		vring_free(_vq);
>>> +
>>> +		fallthrough;
>>> +
>>> +	case VIRTIO_VQ_RESET_STEP_VRING_RELEASE:
>>> +		if (!num)
>>> +			num = vq->split.vring.num;
>>> +
>>> +		err = vring_create_vring_split(&vring, vdev,
>>> +					       vq->split.vring_align,
>>> +					       vq->weak_barriers,
>>> +					       vq->split.may_reduce_num, num);
>>> +		if (err)
>>> +			return -ENOMEM;
>>
>> We'd better need a safe fallback here like:
>>
>> If we can't allocate new memory, we can keep using the current one.
>> Otherwise an ethtool -G fail may make the device not usable.
>>
>> This could be done by not freeing the old vring and virtqueue states
>> until new is allocated.
>>
>>
>>> +
>>> +		err = __vring_virtqueue_attach_split(vq, vdev, vring.vring);
>>> +		if (err) {
>>> +			vring_free_queue(vdev, vring.queue_size_in_bytes,
>>> +					 vring.queue,
>>> +					 vring.dma_addr);
>>> +			return -ENOMEM;
>>> +		}
>>> +
>>> +		vq->split.queue_dma_addr = vring.dma_addr;
>>> +		vq->split.queue_size_in_bytes = vring.queue_size_in_bytes;
>>> +	}
>>> +
>>> +	__vring_virtqueue_init_split(vq, vdev);
>>> +	vq->we_own_ring = true;
>>
>> This seems wrong, we have the transport (rproc/mlxtbf) that allocate the
>> vring by themselves. I think we need to fail the resize for we_own_ring
>> == false.
>>
>> Thanks
>>
>>
>>
>>> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_VRING_ATTACH;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>
>>>    /*
>>>     * Packed ring specific functions - *_packed().
>>> @@ -2317,6 +2384,8 @@ static int __vring_virtqueue_attach_split(struct vring_virtqueue *vq,
>>>    static void __vring_virtqueue_init_split(struct vring_virtqueue *vq,
>>>    					 struct virtio_device *vdev)
>>>    {
>>> +	vq->vq.reset = VIRTIO_VQ_RESET_STEP_NONE;
>>> +
>>>    	vq->packed_ring = false;
>>>    	vq->we_own_ring = false;
>>>    	vq->broken = false;


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
  2022-03-09  9:32       ` Xuan Zhuo
  (?)
@ 2022-03-11  5:05         ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-11  5:05 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev


在 2022/3/9 下午5:32, Xuan Zhuo 写道:
> On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
>>> This patch implements virtio pci support for QUEUE RESET.
>>>
>>> Performing reset on a queue is divided into these steps:
>>>
>>>    1. virtio_reset_vq()              - notify the device to reset the queue
>>>    2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>>>    3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>>>    4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>>>
>>> This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
>>> pci scenario.
>>>
>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>>> ---
>>>    drivers/virtio/virtio_pci_common.c |  8 +--
>>>    drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
>>>    2 files changed, 88 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
>>> index fdbde1db5ec5..863d3a8a0956 100644
>>> --- a/drivers/virtio/virtio_pci_common.c
>>> +++ b/drivers/virtio/virtio_pci_common.c
>>> @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
>>>    	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
>>>    	unsigned long flags;
>>>
>>> -	spin_lock_irqsave(&vp_dev->lock, flags);
>>> -	list_del(&info->node);
>>> -	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	if (!vq->reset) {
>>> +		spin_lock_irqsave(&vp_dev->lock, flags);
>>> +		list_del(&info->node);
>>> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	}
>>>
>>>    	vp_dev->del_vq(info);
>>>    	kfree(info);
>>> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
>>> index 49a4493732cf..3c67d3607802 100644
>>> --- a/drivers/virtio/virtio_pci_modern.c
>>> +++ b/drivers/virtio/virtio_pci_modern.c
>>> @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
>>>    	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
>>>    			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
>>>    		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
>>> +
>>> +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
>>> +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
>>>    }
>>>
>>>    /* virtio config->finalize_features() implementation */
>>> @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
>>>    	return 0;
>>>    }
>>>
>>> +static int vp_modern_reset_vq(struct virtqueue *vq)
>>> +{
>>> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
>>> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
>>> +	struct virtio_pci_vq_info *info;
>>> +	unsigned long flags;
>>> +	unsigned int irq;
>>> +
>>> +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
>>> +		return -ENOENT;
>>> +
>>> +	vp_modern_set_queue_reset(mdev, vq->index);
>>> +
>>> +	info = vp_dev->vqs[vq->index];
>>> +
>>> +	/* delete vq from irq handler */
>>> +	spin_lock_irqsave(&vp_dev->lock, flags);
>>> +	list_del(&info->node);
>>> +	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +
>>> +	INIT_LIST_HEAD(&info->node);
>>> +
>>> +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
>>> +
>>> +	/* sync irq callback. */
>>> +	if (vp_dev->intx_enabled) {
>>> +		irq = vp_dev->pci_dev->irq;
>>> +
>>> +	} else {
>>> +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
>>> +			return 0;
>>> +
>>> +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
>>> +	}
>>> +
>>> +	synchronize_irq(irq);
>>
>> Synchronize_irq() is not sufficient here since it breaks the effort of
>> the interrupt hardening which is done by commits:
>>
>> 080cd7c3ac87 virtio-pci: harden INTX interrupts
>> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>>
>> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
>> used for the affinity managed irq but we're discussing a fix.
> I need to understand it first.
>
>>
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
>>> +{
>>> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
>>> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
>>> +	struct virtio_pci_vq_info *info;
>>> +	unsigned long flags, index;
>>> +	int err;
>>> +
>>> +	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
>>> +		return -EBUSY;
>>> +
>>> +	index = vq->index;
>>> +	info = vp_dev->vqs[index];
>>> +
>>> +	/* check queue reset status */
>>> +	if (vp_modern_get_queue_reset(mdev, index) != 1)
>>> +		return -EBUSY;
>>> +
>>> +	err = vp_active_vq(vq, info->msix_vector);
>>> +	if (err)
>>> +		return err;
>>> +
>>> +	if (vq->callback) {
>>> +		spin_lock_irqsave(&vp_dev->lock, flags);
>>> +		list_add(&info->node, &vp_dev->virtqueues);
>>> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	} else {
>>> +		INIT_LIST_HEAD(&info->node);
>>> +	}
>>> +
>>> +	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
>>
>> Any reason we need to check queue_enable() here?
> The purpose of this function is to enable a reset vq, so call queue_enable() to
> activate it.


Ok, this is what spec mandate.

Thanks


>
> Thanks.
>
>> Thanks
>>
>>
>>> +	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>    static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
>>>    {
>>>    	return vp_modern_config_vector(&vp_dev->mdev, vector);
>>> @@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
>>>    	.set_vq_affinity = vp_set_vq_affinity,
>>>    	.get_vq_affinity = vp_get_vq_affinity,
>>>    	.get_shm_region  = vp_get_shm_region,
>>> +	.reset_vq	 = vp_modern_reset_vq,
>>> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>>>    };
>>>
>>>    static const struct virtio_config_ops virtio_pci_config_ops = {
>>> @@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
>>>    	.set_vq_affinity = vp_set_vq_affinity,
>>>    	.get_vq_affinity = vp_get_vq_affinity,
>>>    	.get_shm_region  = vp_get_shm_region,
>>> +	.reset_vq	 = vp_modern_reset_vq,
>>> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>>>    };
>>>
>>>    /* the PCI probing function */


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-11  5:05         ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-11  5:05 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/9 下午5:32, Xuan Zhuo 写道:
> On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
>>> This patch implements virtio pci support for QUEUE RESET.
>>>
>>> Performing reset on a queue is divided into these steps:
>>>
>>>    1. virtio_reset_vq()              - notify the device to reset the queue
>>>    2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>>>    3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>>>    4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>>>
>>> This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
>>> pci scenario.
>>>
>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>>> ---
>>>    drivers/virtio/virtio_pci_common.c |  8 +--
>>>    drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
>>>    2 files changed, 88 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
>>> index fdbde1db5ec5..863d3a8a0956 100644
>>> --- a/drivers/virtio/virtio_pci_common.c
>>> +++ b/drivers/virtio/virtio_pci_common.c
>>> @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
>>>    	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
>>>    	unsigned long flags;
>>>
>>> -	spin_lock_irqsave(&vp_dev->lock, flags);
>>> -	list_del(&info->node);
>>> -	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	if (!vq->reset) {
>>> +		spin_lock_irqsave(&vp_dev->lock, flags);
>>> +		list_del(&info->node);
>>> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	}
>>>
>>>    	vp_dev->del_vq(info);
>>>    	kfree(info);
>>> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
>>> index 49a4493732cf..3c67d3607802 100644
>>> --- a/drivers/virtio/virtio_pci_modern.c
>>> +++ b/drivers/virtio/virtio_pci_modern.c
>>> @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
>>>    	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
>>>    			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
>>>    		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
>>> +
>>> +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
>>> +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
>>>    }
>>>
>>>    /* virtio config->finalize_features() implementation */
>>> @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
>>>    	return 0;
>>>    }
>>>
>>> +static int vp_modern_reset_vq(struct virtqueue *vq)
>>> +{
>>> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
>>> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
>>> +	struct virtio_pci_vq_info *info;
>>> +	unsigned long flags;
>>> +	unsigned int irq;
>>> +
>>> +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
>>> +		return -ENOENT;
>>> +
>>> +	vp_modern_set_queue_reset(mdev, vq->index);
>>> +
>>> +	info = vp_dev->vqs[vq->index];
>>> +
>>> +	/* delete vq from irq handler */
>>> +	spin_lock_irqsave(&vp_dev->lock, flags);
>>> +	list_del(&info->node);
>>> +	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +
>>> +	INIT_LIST_HEAD(&info->node);
>>> +
>>> +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
>>> +
>>> +	/* sync irq callback. */
>>> +	if (vp_dev->intx_enabled) {
>>> +		irq = vp_dev->pci_dev->irq;
>>> +
>>> +	} else {
>>> +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
>>> +			return 0;
>>> +
>>> +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
>>> +	}
>>> +
>>> +	synchronize_irq(irq);
>>
>> Synchronize_irq() is not sufficient here since it breaks the effort of
>> the interrupt hardening which is done by commits:
>>
>> 080cd7c3ac87 virtio-pci: harden INTX interrupts
>> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>>
>> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
>> used for the affinity managed irq but we're discussing a fix.
> I need to understand it first.
>
>>
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
>>> +{
>>> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
>>> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
>>> +	struct virtio_pci_vq_info *info;
>>> +	unsigned long flags, index;
>>> +	int err;
>>> +
>>> +	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
>>> +		return -EBUSY;
>>> +
>>> +	index = vq->index;
>>> +	info = vp_dev->vqs[index];
>>> +
>>> +	/* check queue reset status */
>>> +	if (vp_modern_get_queue_reset(mdev, index) != 1)
>>> +		return -EBUSY;
>>> +
>>> +	err = vp_active_vq(vq, info->msix_vector);
>>> +	if (err)
>>> +		return err;
>>> +
>>> +	if (vq->callback) {
>>> +		spin_lock_irqsave(&vp_dev->lock, flags);
>>> +		list_add(&info->node, &vp_dev->virtqueues);
>>> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	} else {
>>> +		INIT_LIST_HEAD(&info->node);
>>> +	}
>>> +
>>> +	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
>>
>> Any reason we need to check queue_enable() here?
> The purpose of this function is to enable a reset vq, so call queue_enable() to
> activate it.


Ok, this is what spec mandate.

Thanks


>
> Thanks.
>
>> Thanks
>>
>>
>>> +	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>    static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
>>>    {
>>>    	return vp_modern_config_vector(&vp_dev->mdev, vector);
>>> @@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
>>>    	.set_vq_affinity = vp_set_vq_affinity,
>>>    	.get_vq_affinity = vp_get_vq_affinity,
>>>    	.get_shm_region  = vp_get_shm_region,
>>> +	.reset_vq	 = vp_modern_reset_vq,
>>> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>>>    };
>>>
>>>    static const struct virtio_config_ops virtio_pci_config_ops = {
>>> @@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
>>>    	.set_vq_affinity = vp_set_vq_affinity,
>>>    	.get_vq_affinity = vp_get_vq_affinity,
>>>    	.get_shm_region  = vp_get_shm_region,
>>> +	.reset_vq	 = vp_modern_reset_vq,
>>> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>>>    };
>>>
>>>    /* the PCI probing function */

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-11  5:05         ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-11  5:05 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev


在 2022/3/9 下午5:32, Xuan Zhuo 写道:
> On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
>>> This patch implements virtio pci support for QUEUE RESET.
>>>
>>> Performing reset on a queue is divided into these steps:
>>>
>>>    1. virtio_reset_vq()              - notify the device to reset the queue
>>>    2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>>>    3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>>>    4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>>>
>>> This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
>>> pci scenario.
>>>
>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>>> ---
>>>    drivers/virtio/virtio_pci_common.c |  8 +--
>>>    drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
>>>    2 files changed, 88 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
>>> index fdbde1db5ec5..863d3a8a0956 100644
>>> --- a/drivers/virtio/virtio_pci_common.c
>>> +++ b/drivers/virtio/virtio_pci_common.c
>>> @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
>>>    	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
>>>    	unsigned long flags;
>>>
>>> -	spin_lock_irqsave(&vp_dev->lock, flags);
>>> -	list_del(&info->node);
>>> -	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	if (!vq->reset) {
>>> +		spin_lock_irqsave(&vp_dev->lock, flags);
>>> +		list_del(&info->node);
>>> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	}
>>>
>>>    	vp_dev->del_vq(info);
>>>    	kfree(info);
>>> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
>>> index 49a4493732cf..3c67d3607802 100644
>>> --- a/drivers/virtio/virtio_pci_modern.c
>>> +++ b/drivers/virtio/virtio_pci_modern.c
>>> @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
>>>    	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
>>>    			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
>>>    		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
>>> +
>>> +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
>>> +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
>>>    }
>>>
>>>    /* virtio config->finalize_features() implementation */
>>> @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
>>>    	return 0;
>>>    }
>>>
>>> +static int vp_modern_reset_vq(struct virtqueue *vq)
>>> +{
>>> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
>>> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
>>> +	struct virtio_pci_vq_info *info;
>>> +	unsigned long flags;
>>> +	unsigned int irq;
>>> +
>>> +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
>>> +		return -ENOENT;
>>> +
>>> +	vp_modern_set_queue_reset(mdev, vq->index);
>>> +
>>> +	info = vp_dev->vqs[vq->index];
>>> +
>>> +	/* delete vq from irq handler */
>>> +	spin_lock_irqsave(&vp_dev->lock, flags);
>>> +	list_del(&info->node);
>>> +	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +
>>> +	INIT_LIST_HEAD(&info->node);
>>> +
>>> +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
>>> +
>>> +	/* sync irq callback. */
>>> +	if (vp_dev->intx_enabled) {
>>> +		irq = vp_dev->pci_dev->irq;
>>> +
>>> +	} else {
>>> +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
>>> +			return 0;
>>> +
>>> +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
>>> +	}
>>> +
>>> +	synchronize_irq(irq);
>>
>> Synchronize_irq() is not sufficient here since it breaks the effort of
>> the interrupt hardening which is done by commits:
>>
>> 080cd7c3ac87 virtio-pci: harden INTX interrupts
>> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>>
>> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
>> used for the affinity managed irq but we're discussing a fix.
> I need to understand it first.
>
>>
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
>>> +{
>>> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
>>> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
>>> +	struct virtio_pci_vq_info *info;
>>> +	unsigned long flags, index;
>>> +	int err;
>>> +
>>> +	if (vq->reset != VIRTIO_VQ_RESET_STEP_VRING_ATTACH)
>>> +		return -EBUSY;
>>> +
>>> +	index = vq->index;
>>> +	info = vp_dev->vqs[index];
>>> +
>>> +	/* check queue reset status */
>>> +	if (vp_modern_get_queue_reset(mdev, index) != 1)
>>> +		return -EBUSY;
>>> +
>>> +	err = vp_active_vq(vq, info->msix_vector);
>>> +	if (err)
>>> +		return err;
>>> +
>>> +	if (vq->callback) {
>>> +		spin_lock_irqsave(&vp_dev->lock, flags);
>>> +		list_add(&info->node, &vp_dev->virtqueues);
>>> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	} else {
>>> +		INIT_LIST_HEAD(&info->node);
>>> +	}
>>> +
>>> +	vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
>>
>> Any reason we need to check queue_enable() here?
> The purpose of this function is to enable a reset vq, so call queue_enable() to
> activate it.


Ok, this is what spec mandate.

Thanks


>
> Thanks.
>
>> Thanks
>>
>>
>>> +	vq->reset = VIRTIO_VQ_RESET_STEP_NONE;
>>> +
>>> +	return 0;
>>> +}
>>> +
>>>    static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
>>>    {
>>>    	return vp_modern_config_vector(&vp_dev->mdev, vector);
>>> @@ -407,6 +486,8 @@ static const struct virtio_config_ops virtio_pci_config_nodev_ops = {
>>>    	.set_vq_affinity = vp_set_vq_affinity,
>>>    	.get_vq_affinity = vp_get_vq_affinity,
>>>    	.get_shm_region  = vp_get_shm_region,
>>> +	.reset_vq	 = vp_modern_reset_vq,
>>> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>>>    };
>>>
>>>    static const struct virtio_config_ops virtio_pci_config_ops = {
>>> @@ -425,6 +506,8 @@ static const struct virtio_config_ops virtio_pci_config_ops = {
>>>    	.set_vq_affinity = vp_set_vq_affinity,
>>>    	.get_vq_affinity = vp_get_vq_affinity,
>>>    	.get_shm_region  = vp_get_shm_region,
>>> +	.reset_vq	 = vp_modern_reset_vq,
>>> +	.enable_reset_vq = vp_modern_enable_reset_vq,
>>>    };
>>>
>>>    /* the PCI probing function */


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
  2022-03-10  8:20       ` Xuan Zhuo
  (?)
@ 2022-03-11  5:09         ` Jason Wang
  -1 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-11  5:09 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev


在 2022/3/10 下午4:20, Xuan Zhuo 写道:
> On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
>>> This patch implements virtio pci support for QUEUE RESET.
>>>
>>> Performing reset on a queue is divided into these steps:
>>>
>>>    1. virtio_reset_vq()              - notify the device to reset the queue
>>>    2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>>>    3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>>>    4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>>>
>>> This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
>>> pci scenario.
>>>
>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>>> ---
>>>    drivers/virtio/virtio_pci_common.c |  8 +--
>>>    drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
>>>    2 files changed, 88 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
>>> index fdbde1db5ec5..863d3a8a0956 100644
>>> --- a/drivers/virtio/virtio_pci_common.c
>>> +++ b/drivers/virtio/virtio_pci_common.c
>>> @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
>>>    	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
>>>    	unsigned long flags;
>>>
>>> -	spin_lock_irqsave(&vp_dev->lock, flags);
>>> -	list_del(&info->node);
>>> -	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	if (!vq->reset) {
>>> +		spin_lock_irqsave(&vp_dev->lock, flags);
>>> +		list_del(&info->node);
>>> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	}
>>>
>>>    	vp_dev->del_vq(info);
>>>    	kfree(info);
>>> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
>>> index 49a4493732cf..3c67d3607802 100644
>>> --- a/drivers/virtio/virtio_pci_modern.c
>>> +++ b/drivers/virtio/virtio_pci_modern.c
>>> @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
>>>    	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
>>>    			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
>>>    		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
>>> +
>>> +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
>>> +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
>>>    }
>>>
>>>    /* virtio config->finalize_features() implementation */
>>> @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
>>>    	return 0;
>>>    }
>>>
>>> +static int vp_modern_reset_vq(struct virtqueue *vq)
>>> +{
>>> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
>>> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
>>> +	struct virtio_pci_vq_info *info;
>>> +	unsigned long flags;
>>> +	unsigned int irq;
>>> +
>>> +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
>>> +		return -ENOENT;
>>> +
>>> +	vp_modern_set_queue_reset(mdev, vq->index);
>>> +
>>> +	info = vp_dev->vqs[vq->index];
>>> +
>>> +	/* delete vq from irq handler */
>>> +	spin_lock_irqsave(&vp_dev->lock, flags);
>>> +	list_del(&info->node);
>>> +	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +
>>> +	INIT_LIST_HEAD(&info->node);
>>> +
>>> +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
>>> +
>>> +	/* sync irq callback. */
>>> +	if (vp_dev->intx_enabled) {
>>> +		irq = vp_dev->pci_dev->irq;
>>> +
>>> +	} else {
>>> +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
>>> +			return 0;
>>> +
>>> +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
>>> +	}
>>> +
>>> +	synchronize_irq(irq);
>>
>> Synchronize_irq() is not sufficient here since it breaks the effort of
>> the interrupt hardening which is done by commits:
>>
>> 080cd7c3ac87 virtio-pci: harden INTX interrupts
>> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>>
>> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
>> used for the affinity managed irq but we're discussing a fix.
>>
>
> ok, I think disable_irq() is still used here.
>
> I want to determine the solution for this detail first. So I posted the code, I
> hope Jason can help confirm this point first.
>
> There are three situations in which vq corresponds to an interrupt
>
> 1. intx
> 2. msix: per vq vectors
> 2. msix: share irq
>
> Essentially can be divided into two categories: per vq vectors and share irq.
>
> For share irq is based on virtqueues to find vq, so I think it is safe as long
> as list_del() is executed under the protection of the lock.
>
> In the case of per vq vectors, disable_irq() is used.


See the discussion here[1], disable_irq() could be problematic for the 
block and scsi device that using affinity managed irq. We're waiting for 
the IRQ maintainer to comment on a solution. Other looks sane.

Thanks

[1] https://lkml.org/lkml/2022/3/8/743


>
> Thanks.
>
> +static int vp_modern_reset_vq(struct virtqueue *vq)
> +{
> +       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +       struct virtio_pci_vq_info *info;
> +       unsigned long flags;
> +       unsigned int irq;
> +
> +       if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> +               return -ENOENT;
> +
> +       vp_modern_set_queue_reset(mdev, vq->index);
> +
> +       info = vp_dev->vqs[vq->index];
> +
> +       /* delete vq from irq handler */
> +       spin_lock_irqsave(&vp_dev->lock, flags);
> +       list_del(&info->node);
> +       vp_modern_set_queue_reset(mdev, vq->index);
> +
> +       info = vp_dev->vqs[vq->index];
> +
> +       /* delete vq from irq handler */
> +       spin_lock_irqsave(&vp_dev->lock, flags);
> +       list_del(&info->node);
> +       spin_unlock_irqrestore(&vp_dev->lock, flags);
> +
> +       INIT_LIST_HEAD(&info->node);
> +
> +       /* For the case where vq has an exclusive irq, to prevent the irq from
> +        * being received again and the pending irq, call disable_irq().
> +        *
> +        * In the scenario based on shared interrupts, vq will be searched from
> +        * the queue virtqueues. Since the previous list_del() has been deleted
> +        * from the queue, it is impossible for vq to be called in this case.
> +        * There is no need to close the corresponding interrupt.
> +        */
> +       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
> +               disable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
> +
> +       vq->reset = true;
> +
> +       return 0;
> +}
> +
> +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
> +{
> +       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +       struct virtio_pci_vq_info *info;
> +       unsigned long flags, index;
> +       int err;
> +
> +       if (!vq->reset)
> +               return -EBUSY;
> +
> +       index = vq->index;
> +       info = vp_dev->vqs[index];
> +
> +       /* check queue reset status */
> +       if (vp_modern_get_queue_reset(mdev, index) != 1)
> +               return -EBUSY;
> +
> +       err = vp_active_vq(vq, info->msix_vector);
> +       if (err)
> +               return err;
> +
> +       if (vq->callback) {
> +               spin_lock_irqsave(&vp_dev->lock, flags);
> +               list_add(&info->node, &vp_dev->virtqueues);
> +               spin_unlock_irqrestore(&vp_dev->lock, flags);
> +       } else {
> +               INIT_LIST_HEAD(&info->node);
> +       }
> +
> +       vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
> +       vq->reset = false;
> +
> +       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
> +               enable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
> +
> +       return 0;
> +}
>
>


^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-11  5:09         ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-11  5:09 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Vadim Pasternak, Michael S. Tsirkin, linux-remoteproc,
	Alexei Starovoitov, Bjorn Andersson, Alexander Gordeev,
	Anton Ivanov, linux-s390, Johannes Berg, Daniel Borkmann,
	Richard Weinberger, Vincent Whitchurch, John Fastabend,
	Halil Pasic, Jakub Kicinski, virtualization, Heiko Carstens,
	Jesper Dangaard Brouer, Vasily Gorbik, Jeff Dike, linux-um,
	Mark Gross, Hans de Goede, kvm, platform-driver-x86,
	Mathieu Poirier, netdev, Cornelia Huck, Sven Schnelle, bpf,
	David S. Miller


在 2022/3/10 下午4:20, Xuan Zhuo 写道:
> On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
>>> This patch implements virtio pci support for QUEUE RESET.
>>>
>>> Performing reset on a queue is divided into these steps:
>>>
>>>    1. virtio_reset_vq()              - notify the device to reset the queue
>>>    2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>>>    3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>>>    4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>>>
>>> This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
>>> pci scenario.
>>>
>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>>> ---
>>>    drivers/virtio/virtio_pci_common.c |  8 +--
>>>    drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
>>>    2 files changed, 88 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
>>> index fdbde1db5ec5..863d3a8a0956 100644
>>> --- a/drivers/virtio/virtio_pci_common.c
>>> +++ b/drivers/virtio/virtio_pci_common.c
>>> @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
>>>    	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
>>>    	unsigned long flags;
>>>
>>> -	spin_lock_irqsave(&vp_dev->lock, flags);
>>> -	list_del(&info->node);
>>> -	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	if (!vq->reset) {
>>> +		spin_lock_irqsave(&vp_dev->lock, flags);
>>> +		list_del(&info->node);
>>> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	}
>>>
>>>    	vp_dev->del_vq(info);
>>>    	kfree(info);
>>> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
>>> index 49a4493732cf..3c67d3607802 100644
>>> --- a/drivers/virtio/virtio_pci_modern.c
>>> +++ b/drivers/virtio/virtio_pci_modern.c
>>> @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
>>>    	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
>>>    			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
>>>    		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
>>> +
>>> +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
>>> +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
>>>    }
>>>
>>>    /* virtio config->finalize_features() implementation */
>>> @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
>>>    	return 0;
>>>    }
>>>
>>> +static int vp_modern_reset_vq(struct virtqueue *vq)
>>> +{
>>> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
>>> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
>>> +	struct virtio_pci_vq_info *info;
>>> +	unsigned long flags;
>>> +	unsigned int irq;
>>> +
>>> +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
>>> +		return -ENOENT;
>>> +
>>> +	vp_modern_set_queue_reset(mdev, vq->index);
>>> +
>>> +	info = vp_dev->vqs[vq->index];
>>> +
>>> +	/* delete vq from irq handler */
>>> +	spin_lock_irqsave(&vp_dev->lock, flags);
>>> +	list_del(&info->node);
>>> +	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +
>>> +	INIT_LIST_HEAD(&info->node);
>>> +
>>> +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
>>> +
>>> +	/* sync irq callback. */
>>> +	if (vp_dev->intx_enabled) {
>>> +		irq = vp_dev->pci_dev->irq;
>>> +
>>> +	} else {
>>> +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
>>> +			return 0;
>>> +
>>> +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
>>> +	}
>>> +
>>> +	synchronize_irq(irq);
>>
>> Synchronize_irq() is not sufficient here since it breaks the effort of
>> the interrupt hardening which is done by commits:
>>
>> 080cd7c3ac87 virtio-pci: harden INTX interrupts
>> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>>
>> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
>> used for the affinity managed irq but we're discussing a fix.
>>
>
> ok, I think disable_irq() is still used here.
>
> I want to determine the solution for this detail first. So I posted the code, I
> hope Jason can help confirm this point first.
>
> There are three situations in which vq corresponds to an interrupt
>
> 1. intx
> 2. msix: per vq vectors
> 2. msix: share irq
>
> Essentially can be divided into two categories: per vq vectors and share irq.
>
> For share irq is based on virtqueues to find vq, so I think it is safe as long
> as list_del() is executed under the protection of the lock.
>
> In the case of per vq vectors, disable_irq() is used.


See the discussion here[1], disable_irq() could be problematic for the 
block and scsi device that using affinity managed irq. We're waiting for 
the IRQ maintainer to comment on a solution. Other looks sane.

Thanks

[1] https://lkml.org/lkml/2022/3/8/743


>
> Thanks.
>
> +static int vp_modern_reset_vq(struct virtqueue *vq)
> +{
> +       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +       struct virtio_pci_vq_info *info;
> +       unsigned long flags;
> +       unsigned int irq;
> +
> +       if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> +               return -ENOENT;
> +
> +       vp_modern_set_queue_reset(mdev, vq->index);
> +
> +       info = vp_dev->vqs[vq->index];
> +
> +       /* delete vq from irq handler */
> +       spin_lock_irqsave(&vp_dev->lock, flags);
> +       list_del(&info->node);
> +       vp_modern_set_queue_reset(mdev, vq->index);
> +
> +       info = vp_dev->vqs[vq->index];
> +
> +       /* delete vq from irq handler */
> +       spin_lock_irqsave(&vp_dev->lock, flags);
> +       list_del(&info->node);
> +       spin_unlock_irqrestore(&vp_dev->lock, flags);
> +
> +       INIT_LIST_HEAD(&info->node);
> +
> +       /* For the case where vq has an exclusive irq, to prevent the irq from
> +        * being received again and the pending irq, call disable_irq().
> +        *
> +        * In the scenario based on shared interrupts, vq will be searched from
> +        * the queue virtqueues. Since the previous list_del() has been deleted
> +        * from the queue, it is impossible for vq to be called in this case.
> +        * There is no need to close the corresponding interrupt.
> +        */
> +       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
> +               disable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
> +
> +       vq->reset = true;
> +
> +       return 0;
> +}
> +
> +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
> +{
> +       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +       struct virtio_pci_vq_info *info;
> +       unsigned long flags, index;
> +       int err;
> +
> +       if (!vq->reset)
> +               return -EBUSY;
> +
> +       index = vq->index;
> +       info = vp_dev->vqs[index];
> +
> +       /* check queue reset status */
> +       if (vp_modern_get_queue_reset(mdev, index) != 1)
> +               return -EBUSY;
> +
> +       err = vp_active_vq(vq, info->msix_vector);
> +       if (err)
> +               return err;
> +
> +       if (vq->callback) {
> +               spin_lock_irqsave(&vp_dev->lock, flags);
> +               list_add(&info->node, &vp_dev->virtqueues);
> +               spin_unlock_irqrestore(&vp_dev->lock, flags);
> +       } else {
> +               INIT_LIST_HEAD(&info->node);
> +       }
> +
> +       vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
> +       vq->reset = false;
> +
> +       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
> +               enable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
> +
> +       return 0;
> +}
>
>

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply	[flat|nested] 218+ messages in thread

* Re: [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET
@ 2022-03-11  5:09         ` Jason Wang
  0 siblings, 0 replies; 218+ messages in thread
From: Jason Wang @ 2022-03-11  5:09 UTC (permalink / raw)
  To: Xuan Zhuo
  Cc: Jeff Dike, Richard Weinberger, Anton Ivanov, Michael S. Tsirkin,
	David S. Miller, Jakub Kicinski, Hans de Goede, Mark Gross,
	Vadim Pasternak, Bjorn Andersson, Mathieu Poirier, Cornelia Huck,
	Halil Pasic, Heiko Carstens, Vasily Gorbik,
	Christian Borntraeger, Alexander Gordeev, Sven Schnelle,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, Johannes Berg, Vincent Whitchurch, linux-um,
	platform-driver-x86, linux-remoteproc, linux-s390, kvm, bpf,
	virtualization, netdev


在 2022/3/10 下午4:20, Xuan Zhuo 写道:
> On Wed, 9 Mar 2022 16:54:10 +0800, Jason Wang <jasowang@redhat.com> wrote:
>> 在 2022/3/8 下午8:35, Xuan Zhuo 写道:
>>> This patch implements virtio pci support for QUEUE RESET.
>>>
>>> Performing reset on a queue is divided into these steps:
>>>
>>>    1. virtio_reset_vq()              - notify the device to reset the queue
>>>    2. virtqueue_detach_unused_buf()  - recycle the buffer submitted
>>>    3. virtqueue_reset_vring()        - reset the vring (may re-alloc)
>>>    4. virtio_enable_resetq()         - mmap vring to device, and enable the queue
>>>
>>> This patch implements virtio_reset_vq(), virtio_enable_resetq() in the
>>> pci scenario.
>>>
>>> Signed-off-by: Xuan Zhuo <xuanzhuo@linux.alibaba.com>
>>> ---
>>>    drivers/virtio/virtio_pci_common.c |  8 +--
>>>    drivers/virtio/virtio_pci_modern.c | 83 ++++++++++++++++++++++++++++++
>>>    2 files changed, 88 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
>>> index fdbde1db5ec5..863d3a8a0956 100644
>>> --- a/drivers/virtio/virtio_pci_common.c
>>> +++ b/drivers/virtio/virtio_pci_common.c
>>> @@ -248,9 +248,11 @@ static void vp_del_vq(struct virtqueue *vq)
>>>    	struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
>>>    	unsigned long flags;
>>>
>>> -	spin_lock_irqsave(&vp_dev->lock, flags);
>>> -	list_del(&info->node);
>>> -	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	if (!vq->reset) {
>>> +		spin_lock_irqsave(&vp_dev->lock, flags);
>>> +		list_del(&info->node);
>>> +		spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +	}
>>>
>>>    	vp_dev->del_vq(info);
>>>    	kfree(info);
>>> diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
>>> index 49a4493732cf..3c67d3607802 100644
>>> --- a/drivers/virtio/virtio_pci_modern.c
>>> +++ b/drivers/virtio/virtio_pci_modern.c
>>> @@ -34,6 +34,9 @@ static void vp_transport_features(struct virtio_device *vdev, u64 features)
>>>    	if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
>>>    			pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
>>>    		__virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
>>> +
>>> +	if (features & BIT_ULL(VIRTIO_F_RING_RESET))
>>> +		__virtio_set_bit(vdev, VIRTIO_F_RING_RESET);
>>>    }
>>>
>>>    /* virtio config->finalize_features() implementation */
>>> @@ -199,6 +202,82 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
>>>    	return 0;
>>>    }
>>>
>>> +static int vp_modern_reset_vq(struct virtqueue *vq)
>>> +{
>>> +	struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
>>> +	struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
>>> +	struct virtio_pci_vq_info *info;
>>> +	unsigned long flags;
>>> +	unsigned int irq;
>>> +
>>> +	if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
>>> +		return -ENOENT;
>>> +
>>> +	vp_modern_set_queue_reset(mdev, vq->index);
>>> +
>>> +	info = vp_dev->vqs[vq->index];
>>> +
>>> +	/* delete vq from irq handler */
>>> +	spin_lock_irqsave(&vp_dev->lock, flags);
>>> +	list_del(&info->node);
>>> +	spin_unlock_irqrestore(&vp_dev->lock, flags);
>>> +
>>> +	INIT_LIST_HEAD(&info->node);
>>> +
>>> +	vq->reset = VIRTIO_VQ_RESET_STEP_DEVICE;
>>> +
>>> +	/* sync irq callback. */
>>> +	if (vp_dev->intx_enabled) {
>>> +		irq = vp_dev->pci_dev->irq;
>>> +
>>> +	} else {
>>> +		if (info->msix_vector == VIRTIO_MSI_NO_VECTOR)
>>> +			return 0;
>>> +
>>> +		irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
>>> +	}
>>> +
>>> +	synchronize_irq(irq);
>>
>> Synchronize_irq() is not sufficient here since it breaks the effort of
>> the interrupt hardening which is done by commits:
>>
>> 080cd7c3ac87 virtio-pci: harden INTX interrupts
>> 9e35276a5344 virtio_pci: harden MSI-X interrupts
>>
>> Unfortunately  080cd7c3ac87 introduces an issue that disable_irq() were
>> used for the affinity managed irq but we're discussing a fix.
>>
>
> ok, I think disable_irq() is still used here.
>
> I want to determine the solution for this detail first. So I posted the code, I
> hope Jason can help confirm this point first.
>
> There are three situations in which vq corresponds to an interrupt
>
> 1. intx
> 2. msix: per vq vectors
> 2. msix: share irq
>
> Essentially can be divided into two categories: per vq vectors and share irq.
>
> For share irq is based on virtqueues to find vq, so I think it is safe as long
> as list_del() is executed under the protection of the lock.
>
> In the case of per vq vectors, disable_irq() is used.


See the discussion here[1], disable_irq() could be problematic for the 
block and scsi device that using affinity managed irq. We're waiting for 
the IRQ maintainer to comment on a solution. Other looks sane.

Thanks

[1] https://lkml.org/lkml/2022/3/8/743


>
> Thanks.
>
> +static int vp_modern_reset_vq(struct virtqueue *vq)
> +{
> +       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +       struct virtio_pci_vq_info *info;
> +       unsigned long flags;
> +       unsigned int irq;
> +
> +       if (!virtio_has_feature(vq->vdev, VIRTIO_F_RING_RESET))
> +               return -ENOENT;
> +
> +       vp_modern_set_queue_reset(mdev, vq->index);
> +
> +       info = vp_dev->vqs[vq->index];
> +
> +       /* delete vq from irq handler */
> +       spin_lock_irqsave(&vp_dev->lock, flags);
> +       list_del(&info->node);
> +       vp_modern_set_queue_reset(mdev, vq->index);
> +
> +       info = vp_dev->vqs[vq->index];
> +
> +       /* delete vq from irq handler */
> +       spin_lock_irqsave(&vp_dev->lock, flags);
> +       list_del(&info->node);
> +       spin_unlock_irqrestore(&vp_dev->lock, flags);
> +
> +       INIT_LIST_HEAD(&info->node);
> +
> +       /* For the case where vq has an exclusive irq, to prevent the irq from
> +        * being received again and the pending irq, call disable_irq().
> +        *
> +        * In the scenario based on shared interrupts, vq will be searched from
> +        * the queue virtqueues. Since the previous list_del() has been deleted
> +        * from the queue, it is impossible for vq to be called in this case.
> +        * There is no need to close the corresponding interrupt.
> +        */
> +       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
> +               disable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
> +
> +       vq->reset = true;
> +
> +       return 0;
> +}
> +
> +static int vp_modern_enable_reset_vq(struct virtqueue *vq)
> +{
> +       struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
> +       struct virtio_pci_modern_device *mdev = &vp_dev->mdev;
> +       struct virtio_pci_vq_info *info;
> +       unsigned long flags, index;
> +       int err;
> +
> +       if (!vq->reset)
> +               return -EBUSY;
> +
> +       index = vq->index;
> +       info = vp_dev->vqs[index];
> +
> +       /* check queue reset status */
> +       if (vp_modern_get_queue_reset(mdev, index) != 1)
> +               return -EBUSY;
> +
> +       err = vp_active_vq(vq, info->msix_vector);
> +       if (err)
> +               return err;
> +
> +       if (vq->callback) {
> +               spin_lock_irqsave(&vp_dev->lock, flags);
> +               list_add(&info->node, &vp_dev->virtqueues);
> +               spin_unlock_irqrestore(&vp_dev->lock, flags);
> +       } else {
> +               INIT_LIST_HEAD(&info->node);
> +       }
> +
> +       vp_modern_set_queue_enable(&vp_dev->mdev, index, true);
> +       vq->reset = false;
> +
> +       if (vp_dev->per_vq_vectors && msix_vec != VIRTIO_MSI_NO_VECTOR)
> +               enable_irq(pci_irq_vector(vp_dev->pci_dev, info->msix_vector));
> +
> +       return 0;
> +}
>
>


_______________________________________________
linux-um mailing list
linux-um@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-um

^ permalink raw reply	[flat|nested] 218+ messages in thread

end of thread, other threads:[~2022-03-11  5:09 UTC | newest]

Thread overview: 218+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-08 12:34 [PATCH v7 00/26] virtio pci support VIRTIO_F_RING_RESET Xuan Zhuo
2022-03-08 12:34 ` Xuan Zhuo
2022-03-08 12:34 ` Xuan Zhuo
2022-03-08 12:34 ` [PATCH v7 01/26] virtio_pci: struct virtio_pci_common_cfg add queue_notify_data Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-09  4:48   ` Jason Wang
2022-03-09  4:48     ` Jason Wang
2022-03-09  4:48     ` Jason Wang
2022-03-08 12:34 ` [PATCH v7 02/26] virtio: queue_reset: add VIRTIO_F_RING_RESET Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-09  6:14   ` Jason Wang
2022-03-09  6:14     ` Jason Wang
2022-03-09  6:14     ` Jason Wang
2022-03-08 12:34 ` [PATCH v7 03/26] virtio: add helper virtqueue_get_vring_max_size() Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-09  6:16   ` Jason Wang
2022-03-09  6:16     ` Jason Wang
2022-03-09  6:16     ` Jason Wang
2022-03-08 12:34 ` [PATCH v7 04/26] virtio_ring: split: extract the logic of creating vring Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-09  6:46   ` Jason Wang
2022-03-09  6:46     ` Jason Wang
2022-03-09  6:46     ` Jason Wang
2022-03-09  9:20     ` Xuan Zhuo
2022-03-09  9:20       ` Xuan Zhuo
2022-03-09  9:20       ` Xuan Zhuo
2022-03-08 12:34 ` [PATCH v7 05/26] virtio_ring: split: extract the logic of init vq and attach vring Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-09  7:36   ` Jason Wang
2022-03-09  7:36     ` Jason Wang
2022-03-09  7:36     ` Jason Wang
2022-03-09  9:21     ` Xuan Zhuo
2022-03-09  9:21       ` Xuan Zhuo
2022-03-09  9:21       ` Xuan Zhuo
2022-03-08 12:34 ` [PATCH v7 06/26] virtio_ring: packed: extract the logic of creating vring Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-08 12:34 ` [PATCH v7 07/26] virtio_ring: packed: extract the logic of init vq and attach vring Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-08 12:34   ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 08/26] virtio_ring: extract the logic of freeing vring Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-09  7:51   ` Jason Wang
2022-03-09  7:51     ` Jason Wang
2022-03-09  7:51     ` Jason Wang
2022-03-09  9:22     ` Xuan Zhuo
2022-03-09  9:22       ` Xuan Zhuo
2022-03-09  9:22       ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 09/26] virtio_ring: split: implement virtqueue_reset_vring_split() Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-09  7:55   ` Jason Wang
2022-03-09  7:55     ` Jason Wang
2022-03-09  7:55     ` Jason Wang
2022-03-09  9:24     ` Xuan Zhuo
2022-03-09  9:24       ` Xuan Zhuo
2022-03-09  9:24       ` Xuan Zhuo
2022-03-10  4:46     ` Xuan Zhuo
2022-03-10  4:46       ` Xuan Zhuo
2022-03-10  4:46       ` Xuan Zhuo
2022-03-11  5:01       ` Jason Wang
2022-03-11  5:01         ` Jason Wang
2022-03-11  5:01         ` Jason Wang
2022-03-10  7:00   ` Michael S. Tsirkin
2022-03-10  7:00     ` Michael S. Tsirkin
2022-03-10  7:00     ` Michael S. Tsirkin
2022-03-10  7:17     ` Xuan Zhuo
2022-03-10  7:17       ` Xuan Zhuo
2022-03-10  7:17       ` Xuan Zhuo
2022-03-10  8:07       ` Michael S. Tsirkin
2022-03-10  8:07         ` Michael S. Tsirkin
2022-03-10  8:07         ` Michael S. Tsirkin
2022-03-10  8:14         ` Xuan Zhuo
2022-03-10  8:14           ` Xuan Zhuo
2022-03-10  8:14           ` Xuan Zhuo
2022-03-10 12:17           ` Michael S. Tsirkin
2022-03-10 12:17             ` Michael S. Tsirkin
2022-03-10 12:17             ` Michael S. Tsirkin
2022-03-10 12:33             ` Xuan Zhuo
2022-03-10 12:33               ` Xuan Zhuo
2022-03-10 12:33               ` Xuan Zhuo
2022-03-10 13:04               ` Michael S. Tsirkin
2022-03-10 13:04                 ` Michael S. Tsirkin
2022-03-10 13:04                 ` Michael S. Tsirkin
2022-03-10 14:09                 ` Xuan Zhuo
2022-03-10 14:09                   ` Xuan Zhuo
2022-03-10 14:09                   ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 10/26] virtio_ring: packed: implement virtqueue_reset_vring_packed() Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 11/26] virtio_ring: introduce virtqueue_reset_vring() Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 12/26] virtio_ring: update the document of the virtqueue_detach_unused_buf for queue reset Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 13/26] virtio: queue_reset: struct virtio_config_ops add callbacks for queue_reset Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-09  8:47   ` Jason Wang
2022-03-09  8:47     ` Jason Wang
2022-03-09  8:47     ` Jason Wang
2022-03-09  9:25     ` Xuan Zhuo
2022-03-09  9:25       ` Xuan Zhuo
2022-03-09  9:25       ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 14/26] virtio: add helper for queue reset Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-09  8:48   ` Jason Wang
2022-03-09  8:48     ` Jason Wang
2022-03-09  8:48     ` Jason Wang
2022-03-09  9:27     ` Xuan Zhuo
2022-03-09  9:27       ` Xuan Zhuo
2022-03-09  9:27       ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 15/26] virtio_pci: queue_reset: update struct virtio_pci_common_cfg and option functions Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 16/26] virtio_pci: queue_reset: extract the logic of active vq for modern pci Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 17/26] virtio_pci: queue_reset: support VIRTIO_F_RING_RESET Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-09  8:54   ` Jason Wang
2022-03-09  8:54     ` Jason Wang
2022-03-09  8:54     ` Jason Wang
2022-03-09  9:32     ` Xuan Zhuo
2022-03-09  9:32       ` Xuan Zhuo
2022-03-09  9:32       ` Xuan Zhuo
2022-03-11  5:05       ` Jason Wang
2022-03-11  5:05         ` Jason Wang
2022-03-11  5:05         ` Jason Wang
2022-03-10  8:20     ` Xuan Zhuo
2022-03-10  8:20       ` Xuan Zhuo
2022-03-10  8:20       ` Xuan Zhuo
2022-03-11  5:09       ` Jason Wang
2022-03-11  5:09         ` Jason Wang
2022-03-11  5:09         ` Jason Wang
2022-03-08 12:35 ` [PATCH v7 18/26] virtio: find_vqs() add arg sizes Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 13:13   ` Hans de Goede
2022-03-08 13:13     ` Hans de Goede
2022-03-08 13:13     ` Hans de Goede
2022-03-09  8:59   ` Jason Wang
2022-03-09  8:59     ` Jason Wang
2022-03-09  8:59     ` Jason Wang
2022-03-09  9:34     ` Xuan Zhuo
2022-03-09  9:34       ` Xuan Zhuo
2022-03-09  9:34       ` Xuan Zhuo
2022-03-09 18:18   ` Mathieu Poirier
2022-03-09 18:18     ` Mathieu Poirier
2022-03-08 12:35 ` [PATCH v7 19/26] virtio_pci: support the arg sizes of find_vqs() Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 20/26] virtio_mmio: " Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 21/26] virtio: add helper virtio_find_vqs_ctx_size() Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-09  9:04   ` Jason Wang
2022-03-09  9:04     ` Jason Wang
2022-03-09  9:04     ` Jason Wang
2022-03-09  9:58     ` Xuan Zhuo
2022-03-09  9:58       ` Xuan Zhuo
2022-03-09  9:58       ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 22/26] virtio_net: get ringparam by virtqueue_get_vring_max_size() Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 23/26] virtio_net: split free_unused_bufs() Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-09  9:06   ` Jason Wang
2022-03-09  9:06     ` Jason Wang
2022-03-09  9:06     ` Jason Wang
2022-03-08 12:35 ` [PATCH v7 24/26] virtio_net: support rx/tx queue reset Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-09  9:14   ` Jason Wang
2022-03-09  9:14     ` Jason Wang
2022-03-09  9:14     ` Jason Wang
2022-03-09 10:05     ` Xuan Zhuo
2022-03-09 10:05       ` Xuan Zhuo
2022-03-09 10:05       ` Xuan Zhuo
2022-03-09 10:16     ` Xuan Zhuo
2022-03-09 10:16       ` Xuan Zhuo
2022-03-09 10:16       ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 25/26] virtio_net: set the default max ring size by find_vqs() Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-09  9:28   ` Jason Wang
2022-03-09  9:28     ` Jason Wang
2022-03-09  9:28     ` Jason Wang
2022-03-09  9:35     ` Xuan Zhuo
2022-03-09  9:35       ` Xuan Zhuo
2022-03-09  9:35       ` Xuan Zhuo
2022-03-08 12:35 ` [PATCH v7 26/26] virtio_net: support set_ringparam Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-08 12:35   ` Xuan Zhuo
2022-03-09  9:29   ` Jason Wang
2022-03-09  9:29     ` Jason Wang
2022-03-09  9:29     ` Jason Wang
2022-03-09  9:48     ` Xuan Zhuo
2022-03-09  9:48       ` Xuan Zhuo
2022-03-09  9:48       ` Xuan Zhuo
2022-03-09  4:45 ` [PATCH v7 00/26] virtio pci support VIRTIO_F_RING_RESET Jason Wang
2022-03-09  4:45   ` Jason Wang
2022-03-09  4:45   ` Jason Wang
2022-03-09  9:02   ` Michael S. Tsirkin
2022-03-09  9:02     ` Michael S. Tsirkin
2022-03-09  9:02     ` Michael S. Tsirkin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.