Re: [RFC PATCH v2 0/9] vsock: updates for SO_RCVLOWAT handling

2022-08-01 Thread Vishnu Dasa via Virtualization


> On Jul 27, 2022, at 5:37 AM, Stefano Garzarella  wrote:
> 
> Hi Arseniy,
> 
> On Mon, Jul 25, 2022 at 07:54:05AM +, Arseniy Krasnov wrote:
>> Hello,
>> 
>> This patchset includes some updates for SO_RCVLOWAT:
>> 
>> 1) af_vsock:
>>  During my experiments with zerocopy receive, i found, that in some
>>  cases, poll() implementation violates POSIX: when socket has non-
>>  default SO_RCVLOWAT(e.g. not 1), poll() will always set POLLIN and
>>  POLLRDNORM bits in 'revents' even number of bytes available to read
>>  on socket is smaller than SO_RCVLOWAT value. In this case,user sees
>>  POLLIN flag and then tries to read data(for example using  'read()'
>>  call), but read call will be blocked, because  SO_RCVLOWAT logic is
>>  supported in dequeue loop in af_vsock.c. But the same time,  POSIX
>>  requires that:
>> 
>>  "POLLIN Data other than high-priority data may be read without
>>  blocking.
>>   POLLRDNORM Normal data may be read without blocking."
>> 
>>  See 
>> https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fopen%2Fn4217.pdfdata=05%7C01%7Cvdasa%40vmware.com%7C5ad2c6759fd8439e938708da6fccbee4%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C0%7C1%7C637945222450930014%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=60hG3DiYufOCv1DuufSdujiLEKDNou1Ztyah3GPbOLI%3Dreserved=0,
>>  page 293.
>> 
>>  So, we have, that poll() syscall returns POLLIN, but read call will
>>  be blocked.
>> 
>>  Also in man page socket(7) i found that:
>> 
>>  "Since Linux 2.6.28, select(2), poll(2), and epoll(7) indicate a
>>  socket as readable only if at least SO_RCVLOWAT bytes are available."
>> 
>>  I checked TCP callback for poll()(net/ipv4/tcp.c, tcp_poll()), it
>>  uses SO_RCVLOWAT value to set POLLIN bit, also i've tested TCP with
>>  this case for TCP socket, it works as POSIX required.
>> 
>>  I've added some fixes to af_vsock.c and virtio_transport_common.c,
>>  test is also implemented.
>> 
>> 2) virtio/vsock:
>>  It adds some optimization to wake ups, when new data arrived. Now,
>>  SO_RCVLOWAT is considered before wake up sleepers who wait new data.
>>  There is no sense, to kick waiter, when number of available bytes
>>  in socket's queue < SO_RCVLOWAT, because if we wake up reader in
>>  this case, it will wait for SO_RCVLOWAT data anyway during dequeue,
>>  or in poll() case, POLLIN/POLLRDNORM bits won't be set, so such
>>  exit from poll() will be "spurious". This logic is also used in TCP
>>  sockets.
> 
> Nice, it looks good!
> 
>> 
>> 3) vmci/vsock:
>>  Same as 2), but i'm not sure about this changes. Will be very good,
>>  to get comments from someone who knows this code.
> 
> I CCed VMCI maintainers to the patch and also to this cover, maybe
> better to keep them in the loop for next versions.
> 
> (Jorgen's and Rajesh's emails bounced back, so I'm CCing here only
> Bryan, Vishnu, and pv-driv...@vmware.com)

Hi Stefano,
Jorgen and Rajesh are no longer with VMware.  There's a patch in
flight to remove Rajesh from the MAINTAINERS file (Jorgen is already
removed).

Thanks,
Vishnu
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


Re: [RFC PATCH v2 0/9] vsock: updates for SO_RCVLOWAT handling

2022-08-01 Thread Vishnu Dasa via Virtualization



> On Jul 27, 2022, at 11:08 PM, Arseniy Krasnov  
> wrote:
> 
> On 27.07.2022 15:37, Stefano Garzarella wrote:
>> Hi Arseniy,
>> 
>> On Mon, Jul 25, 2022 at 07:54:05AM +, Arseniy Krasnov wrote:
>>> Hello,
>>> 
>>> This patchset includes some updates for SO_RCVLOWAT:
>>> 
>>> 1) af_vsock:
>>> During my experiments with zerocopy receive, i found, that in some
>>> cases, poll() implementation violates POSIX: when socket has non-
>>> default SO_RCVLOWAT(e.g. not 1), poll() will always set POLLIN and
>>> POLLRDNORM bits in 'revents' even number of bytes available to read
>>> on socket is smaller than SO_RCVLOWAT value. In this case,user sees
>>> POLLIN flag and then tries to read data(for example using 'read()'
>>> call), but read call will be blocked, because SO_RCVLOWAT logic is
>>> supported in dequeue loop in af_vsock.c. But the same time, POSIX
>>> requires that:
>>> 
>>> "POLLIN Data other than high-priority data may be read without
>>> blocking.
>>> POLLRDNORM Normal data may be read without blocking."
>>> 
>>> See 
>>> https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fopen%2Fn4217.pdfdata=05%7C01%7Cvdasa%40vmware.com%7Cae83621d8709421de14b08da705faa9c%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C0%7C1%7C637945853473740235%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=NrbycCcVXV9Tz8NRDYBpnDx7KpFF6BZpSRbuhz1IfJ4%3Dreserved=0,
>>>  page 293.
>>> 
>>> So, we have, that poll() syscall returns POLLIN, but read call will
>>> be blocked.
>>> 
>>> Also in man page socket(7) i found that:
>>> 
>>> "Since Linux 2.6.28, select(2), poll(2), and epoll(7) indicate a
>>> socket as readable only if at least SO_RCVLOWAT bytes are available."
>>> 
>>> I checked TCP callback for poll()(net/ipv4/tcp.c, tcp_poll()), it
>>> uses SO_RCVLOWAT value to set POLLIN bit, also i've tested TCP with
>>> this case for TCP socket, it works as POSIX required.
>>> 
>>> I've added some fixes to af_vsock.c and virtio_transport_common.c,
>>> test is also implemented.
>>> 
>>> 2) virtio/vsock:
>>> It adds some optimization to wake ups, when new data arrived. Now,
>>> SO_RCVLOWAT is considered before wake up sleepers who wait new data.
>>> There is no sense, to kick waiter, when number of available bytes
>>> in socket's queue < SO_RCVLOWAT, because if we wake up reader in
>>> this case, it will wait for SO_RCVLOWAT data anyway during dequeue,
>>> or in poll() case, POLLIN/POLLRDNORM bits won't be set, so such
>>> exit from poll() will be "spurious". This logic is also used in TCP
>>> sockets.
>> 
>> Nice, it looks good!
> Thank You!
>> 
>>> 
>>> 3) vmci/vsock:
>>> Same as 2), but i'm not sure about this changes. Will be very good,
>>> to get comments from someone who knows this code.
>> 
>> I CCed VMCI maintainers to the patch and also to this cover, maybe better to 
>> keep them in the loop for next versions.
>> 
>> (Jorgen's and Rajesh's emails bounced back, so I'm CCing here only Bryan, 
>> Vishnu, and pv-driv...@vmware.com)
> Ok, i'll CC them in the next version
>> 
>>> 
>>> 4) Hyper-V:
>>> As Dexuan Cui mentioned, for Hyper-V transport it is difficult to
>>> support SO_RCVLOWAT, so he suggested to disable this feature for
>>> Hyper-V.
>> 
>> I left a couple of comments in some patches, but it seems to me to be in a 
>> good state :-)
>> 
>> I would just suggest a bit of a re-organization of the series (the patches 
>> are fine, just the order):
>> - introduce vsock_set_rcvlowat()
>> - disabling it for hv_sock
>> - use 'target' in virtio transports
>> - use 'target' in vmci transports
>> - use sock_rcvlowat in vsock_poll()
>> I think is better to pass sock_rcvlowat() as 'target' when the
>> transports are already able to use it
>> - add vsock_data_ready()
>> - use vsock_data_ready() in virtio transports
>> - use vsock_data_ready() in vmci transports
>> - tests
>> 
>> What do you think?
> No problem! I think i can wait for reply from VMWare guys before preparing v3

Looks fine to me, especially the VMCI parts.  Please send v3, and we can test it
from VMCI point of view as well.

Thanks,
Vishnu
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


Re: [PATCH V3 4/6] vDPA: !FEATURES_OK should not block querying device config space

2022-08-01 Thread Si-Wei Liu



On 8/1/2022 3:53 PM, Si-Wei Liu wrote:



On 7/31/2022 9:44 PM, Jason Wang wrote:


在 2022/7/30 04:55, Si-Wei Liu 写道:



On 7/28/2022 7:04 PM, Zhu, Lingshan wrote:



On 7/29/2022 5:48 AM, Si-Wei Liu wrote:



On 7/27/2022 7:43 PM, Zhu, Lingshan wrote:



On 7/28/2022 8:56 AM, Si-Wei Liu wrote:



On 7/27/2022 4:47 AM, Zhu, Lingshan wrote:



On 7/27/2022 5:43 PM, Si-Wei Liu wrote:
Sorry to chime in late in the game. For some reason I couldn't 
get to most emails for this discussion (I only subscribed to 
the virtualization list), while I was taking off amongst the 
past few weeks.


It looks to me this patch is incomplete. Noted down the way in 
vdpa_dev_net_config_fill(), we have the following:

 features = vdev->config->get_driver_features(vdev);
 if (nla_put_u64_64bit(msg, 
VDPA_ATTR_DEV_NEGOTIATED_FEATURES, features,

   VDPA_ATTR_PAD))
 return -EMSGSIZE;

Making call to .get_driver_features() doesn't make sense when 
feature negotiation isn't complete. Neither should present 
negotiated_features to userspace before negotiation is done.


Similarly, max_vqp through vdpa_dev_net_mq_config_fill() 
probably should not show before negotiation is done - it 
depends on driver features negotiated.
I have another patch in this series introduces device_features 
and will report device_features to the userspace even features 
negotiation not done. Because the spec says we should allow 
driver access the config space before FEATURES_OK.
The config space can be accessed by guest before features_ok 
doesn't necessarily mean the value is valid. You may want to 
double check with Michael for what he quoted earlier:
that's why I proposed to fix these issues, e.g., if no _F_MAC, 
vDPA kernel should not return a mac to the userspace, there is 
not a default value for mac.
Then please show us the code, as I can only comment based on your 
latest (v4) patch and it was not there.. To be honest, I don't 
understand the motivation and the use cases you have, is it for 
debugging/monitoring or there's really a use case for live 
migration? For the former, you can do a direct dump on all config 
space fields regardless of endianess and feature negotiation 
without having to worry about validity (meaningful to present to 
admin user). To me these are conflict asks that is impossible to 
mix in exact one command.
This bug just has been revealed two days, and you will see the 
patch soon.


There are something to clarify:
1) we need to read the device features, or how can you pick a 
proper LM destination



So it's probably not very efficient to use this, the manager layer 
should have the knowledge about the compatibility before doing 
migration other than try-and-fail.


And it's the task of the management to gather the nodes whose devices 
could be live migrated to each other as something like "cluster" 
which we've already used in the case of cpuflags.


1) during node bootstrap, the capability of each node and devices was 
reported to management layer
2) management layer decide the cluster and make sure the migration 
can only done among the nodes insides the cluster

3) before migration, the vDPA needs to be provisioned on the destination


2) vdpa dev config show can show both device features and driver 
features, there just need a patch for iproute2
3) To process information like MQ, we don't just dump the config 
space, MST has explained before
So, it's for live migration... Then why not export those config 
parameters specified for vdpa creation (as well as device feature 
bits) to the output of "vdpa dev show" command? That's where device 
side config lives and is static across vdpa's life cycle. "vdpa dev 
config show" is mostly for dynamic driver side config, and the 
validity is subject to feature negotiation. I suppose this should 
suit your need of LM, e.g.



I think so.




$ vdpa dev add name vdpa1 mgmtdev pci/:41:04.2 max_vqp 7 mtu 2000
$ vdpa dev show vdpa1
vdpa1: type network mgmtdev pci/:41:04.2 vendor_id  max_vqs 
15 max_vq_size 256

  max_vqp 7 mtu 2000
  dev_features CSUM GUEST_CSUM MTU HOST_TSO4 HOST_TSO6 STATUS 
CTRL_VQ MQ CTRL_MAC_ADDR VERSION_1 RING_PACKED



Note that the mgmt should know this destination have those 
capability/features before the provisioning.

Yes, mgmt software should have to check the above from source.


On destination mgmt software can run below to check vdpa mgmtdev's 
capability/features:


$ vdpa mgmtdev show pci/:41:04.3
pci/:41:04.3:
  supported_classes net
  max_supported_vqs 257
  dev_features CSUM GUEST_CSUM MTU HOST_TSO4 HOST_TSO6 STATUS CTRL_VQ 
MQ CTRL_MAC_ADDR VERSION_1 RING_PACKED







For it to work, you'd want to pass "struct vdpa_dev_set_config" to 
_vdpa_register_device() during registration, and get it saved there 
in "struct vdpa_device". Then in vdpa_dev_fill() show each field 
conditionally subject to "struct vdpa_dev_set_config.mask".


Thanks,
-Siwei



Thanks





Re: [PATCH V3 4/6] vDPA: !FEATURES_OK should not block querying device config space

2022-08-01 Thread Si-Wei Liu



On 7/31/2022 9:44 PM, Jason Wang wrote:


在 2022/7/30 04:55, Si-Wei Liu 写道:



On 7/28/2022 7:04 PM, Zhu, Lingshan wrote:



On 7/29/2022 5:48 AM, Si-Wei Liu wrote:



On 7/27/2022 7:43 PM, Zhu, Lingshan wrote:



On 7/28/2022 8:56 AM, Si-Wei Liu wrote:



On 7/27/2022 4:47 AM, Zhu, Lingshan wrote:



On 7/27/2022 5:43 PM, Si-Wei Liu wrote:
Sorry to chime in late in the game. For some reason I couldn't 
get to most emails for this discussion (I only subscribed to 
the virtualization list), while I was taking off amongst the 
past few weeks.


It looks to me this patch is incomplete. Noted down the way in 
vdpa_dev_net_config_fill(), we have the following:

 features = vdev->config->get_driver_features(vdev);
 if (nla_put_u64_64bit(msg, 
VDPA_ATTR_DEV_NEGOTIATED_FEATURES, features,

   VDPA_ATTR_PAD))
 return -EMSGSIZE;

Making call to .get_driver_features() doesn't make sense when 
feature negotiation isn't complete. Neither should present 
negotiated_features to userspace before negotiation is done.


Similarly, max_vqp through vdpa_dev_net_mq_config_fill() 
probably should not show before negotiation is done - it 
depends on driver features negotiated.
I have another patch in this series introduces device_features 
and will report device_features to the userspace even features 
negotiation not done. Because the spec says we should allow 
driver access the config space before FEATURES_OK.
The config space can be accessed by guest before features_ok 
doesn't necessarily mean the value is valid. You may want to 
double check with Michael for what he quoted earlier:
that's why I proposed to fix these issues, e.g., if no _F_MAC, 
vDPA kernel should not return a mac to the userspace, there is not 
a default value for mac.
Then please show us the code, as I can only comment based on your 
latest (v4) patch and it was not there.. To be honest, I don't 
understand the motivation and the use cases you have, is it for 
debugging/monitoring or there's really a use case for live 
migration? For the former, you can do a direct dump on all config 
space fields regardless of endianess and feature negotiation 
without having to worry about validity (meaningful to present to 
admin user). To me these are conflict asks that is impossible to 
mix in exact one command.
This bug just has been revealed two days, and you will see the patch 
soon.


There are something to clarify:
1) we need to read the device features, or how can you pick a proper 
LM destination



So it's probably not very efficient to use this, the manager layer 
should have the knowledge about the compatibility before doing 
migration other than try-and-fail.


And it's the task of the management to gather the nodes whose devices 
could be live migrated to each other as something like "cluster" which 
we've already used in the case of cpuflags.


1) during node bootstrap, the capability of each node and devices was 
reported to management layer
2) management layer decide the cluster and make sure the migration can 
only done among the nodes insides the cluster

3) before migration, the vDPA needs to be provisioned on the destination


2) vdpa dev config show can show both device features and driver 
features, there just need a patch for iproute2
3) To process information like MQ, we don't just dump the config 
space, MST has explained before
So, it's for live migration... Then why not export those config 
parameters specified for vdpa creation (as well as device feature 
bits) to the output of "vdpa dev show" command? That's where device 
side config lives and is static across vdpa's life cycle. "vdpa dev 
config show" is mostly for dynamic driver side config, and the 
validity is subject to feature negotiation. I suppose this should 
suit your need of LM, e.g.



I think so.




$ vdpa dev add name vdpa1 mgmtdev pci/:41:04.2 max_vqp 7 mtu 2000
$ vdpa dev show vdpa1
vdpa1: type network mgmtdev pci/:41:04.2 vendor_id  max_vqs 
15 max_vq_size 256

  max_vqp 7 mtu 2000
  dev_features CSUM GUEST_CSUM MTU HOST_TSO4 HOST_TSO6 STATUS CTRL_VQ 
MQ CTRL_MAC_ADDR VERSION_1 RING_PACKED



Note that the mgmt should know this destination have those 
capability/features before the provisioning.

Yes, mgmt software should have to check the above from source.






For it to work, you'd want to pass "struct vdpa_dev_set_config" to 
_vdpa_register_device() during registration, and get it saved there 
in "struct vdpa_device". Then in vdpa_dev_fill() show each field 
conditionally subject to "struct vdpa_dev_set_config.mask".


Thanks,
-Siwei



Thanks




Thanks
Zhu Lingshan



Nope:

2.5.1  Driver Requirements: Device Configuration Space

...

For optional configuration space fields, the driver MUST check 
that the corresponding feature is offered

before accessing that part of the configuration space.


and how many driver bugs taking wrong assumption of the validity 
of config space field without 

Re: [PATCH v6 1/2] Create debugfs file with virtio balloon usage information

2022-08-01 Thread David Hildenbrand
>>> +
>>> +   if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
>>> +   num_pages = -num_pages;
>> With VIRTIO_BALLOON_F_DEFLATE_ON_OOM this will now always report "0".
>>
>> which would be the same as "num_pages = 0;" and would deserve a comment
>> explaining why we don't indicate that as "inflated: ".
>>
>> Thanks.
> 
> Except if "now"  refers to some commit that i am missing it does not report 0.

/me facepalm

I read "-= num_pages"

> 
> 
> with qemu-system-x86_64  -enable-kvm -device 
> virtio-balloon,id=balloon0,deflate-on-oom=on,notify_on_empty=on,page-per-vq=on
>  -m 3G 
> 
> / # cat /sys/kernel/debug/virtio-balloon
> inflated: 0 kB
> / # QEMU 4.2.1 monitor - type 'help' for more information
> (qemu) balloon 1024
> (qemu)
> 
> / # cat /sys/kernel/debug/virtio-balloon
> inflated: 2097152 kB
> / #
> 
> with qemu-system-x86_64  -enable-kvm -device 
> virtio-balloon,id=balloon0,deflate-on-oom=off,notify_on_empty=on,page-per-vq=on
>  
> -m 3G ...
> 
> / # cat /sys/kernel/debug/virtio-balloon
> inflated: 0 kB
> / # QEMU 4.2.1 monitor - type 'help' for more information
> (qemu) balloon 1024
> (qemu)
> / # cat /sys/kernel/debug/virtio-balloon
> inflated: -2097152 kB

What's the rationale of making it negative?

> 
> To join the threads:
> 
>>> Always account inflated memory as used for both cases - with and
>>> without deflate on oom. Do not change total ram which can confuse
>>> userspace and users.
> 
>> Sorry, but NAK.
> 
> Ok.
> 
>> This would affect existing users / user space / balloon stats. For example
>> HV just recently switch to properly using adjust_managed_page_count()
> 
> 
> I am wondering what's the rationale behind this i have never seen such users
> that expect it to work like this. Do you have any pointers to such users, so
> i can understood why they do so ?

We adjust total pages and managed pages to simulate what memory is
actually available to the system (just like during memory hot(un)plug).
Even though the pages are "allocated" by the driver, they are actually
unusable for the system, just as if they would have been offlined.
Strictly speaking, the guest OS can kill as many processes as it wants,
it cannot reclaim that memory, as it's logically no longer available.

There is nothing (valid, well, except driver unloading) the guest can do
to reuse these pages. The hypervisor has to get involved first to grant
access to some of these pages again (deflate the balloon).

It's different with deflate-on-oom: the guest will *itself* decide to
reuse inflated pages to deflate them. So the allocated pages can become
back usable easily. There was a recent discussion for virtio-balloon to
change that behavior when it's known that the hypervisor essentially
implements "deflate-on-oom" by looking at guest memory stats and
adjusting the balloon size accordingly; however, as long as we don't
know what the hypervisor does or doesn't do, we have to keep the
existing behavior.

Note that most balloon drivers under Linux share that behavior.

In case of Hyper-V I remember a customer BUG report that requested that
exact behavior, however, I'm not able to locate the BZ quickly.


[1]
https://lists.linuxfoundation.org/pipermail/virtualization/2021-November/057767.html
(note that I can't easily find the original mail in the archives)

Note: I suggested under [1] to expose inflated pages via /proc/meminfo
directly. We could do that consistently over all balloon drivers ...
doesn't sound too crazy.

-- 
Thanks,

David / dhildenb

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

[PATCH v1 1/1] iommu/virtio: Do not dereference fwnode in struct device

2022-08-01 Thread Andy Shevchenko
In order to make the underneath API easier to change in the future,
prevent users from dereferencing fwnode from struct device.
Instead, use the specific device_match_fwnode() API for that.

Signed-off-by: Andy Shevchenko 
---
 drivers/iommu/virtio-iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 08eeafc9529f..9fe723f55213 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -925,7 +925,7 @@ static struct virtio_driver virtio_iommu_drv;
 
 static int viommu_match_node(struct device *dev, const void *data)
 {
-   return dev->parent->fwnode == data;
+   return device_match_fwnode(dev->parent, data);
 }
 
 static struct viommu_dev *viommu_get_by_fwnode(struct fwnode_handle *fwnode)
-- 
2.35.1

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


Re: [PATCH v6 1/2] Create debugfs file with virtio balloon usage information

2022-08-01 Thread David Hildenbrand
On 26.07.22 16:08, Alexander Atanasov wrote:
> Allow the guest to know how much it is ballooned by the host
> and how that memory is accounted.
> 
> It is useful when debugging out of memory conditions,
> as well for userspace processes that monitor the memory pressure
> and for nested virtualization.
> 
> Depending on the deflate on oom flag memory is accounted in two ways.
> If the flag is set the inflated pages are accounted as used memory.
> If the flag is not set the inflated pages are substracted from totalram.
> To make clear how are inflated pages accounted sign prefix the value.
> Where negative means substracted from totalram and positive means
> they are accounted as used.
> 
> Signed-off-by: Alexander Atanasov 
> ---
>  drivers/virtio/virtio_balloon.c | 59 +
>  1 file changed, 59 insertions(+)
> 
> V2:
>   - fixed coding style
>   - removed pretty print
> V3:
>   - removed dublicate of features
>   - comment about balooned_pages more clear
>   - convert host pages to balloon pages
> V4:
>   - added a define for BALLOON_PAGE_SIZE to make things clear
> V5:
>   - Made the calculatons work properly for both ways of memory accounting
> with or without deflate_on_oom
>   - dropped comment
> V6:
>   - reduced the file to minimum
>   - unify accounting
> 
> I didn't understand if you agree to change the accounting to be the same
> so following part 2 is about it.
> 
> 
> diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
> index f4c34a2a6b8e..97d3b29cb9f1 100644
> --- a/drivers/virtio/virtio_balloon.c
> +++ b/drivers/virtio/virtio_balloon.c
> @@ -10,6 +10,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -731,6 +732,59 @@ static void report_free_page_func(struct work_struct 
> *work)
>   }
>  }
>  
> +/*
> + * DEBUGFS Interface
> + */
> +#ifdef CONFIG_DEBUG_FS
> +
> +/**
> + * virtio_balloon_debug_show - shows statistics of balloon operations.
> + * @f: pointer to the  seq_file.
> + * @offset: ignored.
> + *
> + * Provides the statistics that can be accessed in virtio-balloon in the 
> debugfs.
> + *
> + * Return: zero on success or an error code.
> + */
> +

Superfluous empty line. Personally, I'd just get rid of this
(comparatively obvious) documentation completely.

> +static int virtio_balloon_debug_show(struct seq_file *f, void *offset)
> +{
> + struct virtio_balloon *vb = f->private;
> + s64 num_pages = vb->num_pages << (VIRTIO_BALLOON_PFN_SHIFT - 10);

Rather call this "inflated_kb" then, it's no longer "pages".

> +
> + if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
> + num_pages = -num_pages;

With VIRTIO_BALLOON_F_DEFLATE_ON_OOM this will now always report "0".

which would be the same as "num_pages = 0;" and would deserve a comment
explaining why we don't indicate that as "inflated: ".

Thanks.

-- 
Thanks,

David / dhildenb

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


Re: [PATCH v6 2/2] Unify how inflated memory is accounted in virtio balloon driver

2022-08-01 Thread David Hildenbrand
On 26.07.22 16:10, Alexander Atanasov wrote:
> Always account inflated memory as used for both cases - with and
> without deflate on oom. Do not change total ram which can confuse
> userspace and users.

Sorry, but NAK.

This would affect existing users / user space / balloon stats. For example
HV just recently switch to properly using adjust_managed_page_count()


commit d1df458cbfdb0c3384c03c7fbcb1689bc02a746c
Author: Vitaly Kuznetsov 
Date:   Wed Dec 2 17:12:45 2020 +0100

hv_balloon: do adjust_managed_page_count() when ballooning/un-ballooning

Unlike virtio_balloon/virtio_mem/xen balloon drivers, Hyper-V balloon driver
does not adjust managed pages count when ballooning/un-ballooning and this 
leads
to incorrect stats being reported, e.g. unexpected 'free' output.

Note, the calculation in post_status() seems to remain correct: ballooned 
out
pages are never 'available' and we manually add dm->num_pages_ballooned to
'commited'.


-- 
Thanks,

David / dhildenb

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


[PATCH v14 42/42] virtio_net: support set_ringparam

2022-08-01 Thread Xuan Zhuo
Support set_ringparam based on virtio queue reset.

Users can use ethtool -G eth0  to modify the ring size of
virtio-net.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/net/virtio_net.c | 48 
 1 file changed, 48 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index d1e6940b46d8..59fc48c60403 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2329,6 +2329,53 @@ 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 > vi->rq[0].vq->num_max)
+   return -EINVAL;
+
+   if (ring->tx_pending > vi->sq[0].vq->num_max)
+   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_resize(vi, sq, ring->tx_pending);
+   if (err)
+   return err;
+   }
+
+   if (ring->rx_pending != rx_pending) {
+   err = virtnet_rx_resize(vi, rq, ring->rx_pending);
+   if (err)
+   return err;
+   }
+   }
+
+   return 0;
+}
+
 static bool virtnet_commit_rss_command(struct virtnet_info *vi)
 {
struct net_device *dev = vi->dev;
@@ -2816,6 +2863,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


[PATCH v14 41/42] virtio_net: support tx queue resize

2022-08-01 Thread Xuan Zhuo
This patch implements the resize function of the tx queues.
Based on this function, it is possible to modify the ring num of the
queue.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 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 1115a8b59a08..d1e6940b46d8 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -135,6 +135,9 @@ struct send_queue {
struct virtnet_sq_stats stats;
 
struct napi_struct napi;
+
+   /* Record whether sq is in reset state. */
+   bool reset;
 };
 
 /* Internal representation of a receive virtqueue */
@@ -279,6 +282,7 @@ struct padded_vnet_hdr {
 };
 
 static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf);
+static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf);
 
 static bool is_xdp_frame(void *ptr)
 {
@@ -1603,6 +1607,11 @@ static void virtnet_poll_cleantx(struct receive_queue 
*rq)
return;
 
if (__netif_tx_trylock(txq)) {
+   if (sq->reset) {
+   __netif_tx_unlock(txq);
+   return;
+   }
+
do {
virtqueue_disable_cb(sq->vq);
free_old_xmit_skbs(sq, true);
@@ -1868,6 +1877,44 @@ static int virtnet_rx_resize(struct virtnet_info *vi,
return err;
 }
 
+static int virtnet_tx_resize(struct virtnet_info *vi,
+struct send_queue *sq, u32 ring_num)
+{
+   struct netdev_queue *txq;
+   int err, qindex;
+
+   qindex = sq - vi->sq;
+
+   virtnet_napi_tx_disable(>napi);
+
+   txq = netdev_get_tx_queue(vi->dev, qindex);
+
+   /* 1. wait all ximt complete
+* 2. fix the race of netif_stop_subqueue() vs netif_start_subqueue()
+*/
+   __netif_tx_lock_bh(txq);
+
+   /* Prevent rx poll from accessing sq. */
+   sq->reset = true;
+
+   /* Prevent the upper layer from trying to send packets. */
+   netif_stop_subqueue(vi->dev, qindex);
+
+   __netif_tx_unlock_bh(txq);
+
+   err = virtqueue_resize(sq->vq, ring_num, virtnet_sq_free_unused_buf);
+   if (err)
+   netdev_err(vi->dev, "resize tx fail: tx queue index: %d err: 
%d\n", qindex, err);
+
+   __netif_tx_lock_bh(txq);
+   sq->reset = false;
+   netif_tx_wake_queue(txq);
+   __netif_tx_unlock_bh(txq);
+
+   virtnet_napi_tx_enable(vi, sq->vq, >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


[PATCH v14 40/42] virtio_net: support rx queue resize

2022-08-01 Thread Xuan Zhuo
This patch implements the resize function of the rx queues.
Based on this function, it is possible to modify the ring num of the
queue.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/net/virtio_net.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index fe4dc43c05a1..1115a8b59a08 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -278,6 +278,8 @@ struct padded_vnet_hdr {
char padding[12];
 };
 
+static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf);
+
 static bool is_xdp_frame(void *ptr)
 {
return (unsigned long)ptr & VIRTIO_XDP_FLAG;
@@ -1846,6 +1848,26 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, 
struct net_device *dev)
return NETDEV_TX_OK;
 }
 
+static int virtnet_rx_resize(struct virtnet_info *vi,
+struct receive_queue *rq, u32 ring_num)
+{
+   int err, qindex;
+
+   qindex = rq - vi->rq;
+
+   napi_disable(>napi);
+
+   err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_free_unused_buf);
+   if (err)
+   netdev_err(vi->dev, "resize rx fail: rx queue index: %d err: 
%d\n", qindex, err);
+
+   if (!try_fill_recv(vi, rq, GFP_KERNEL))
+   schedule_delayed_work(>refill, 0);
+
+   virtnet_napi_enable(rq->vq, >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


[PATCH v14 38/42] virtio_net: get ringparam by virtqueue_get_vring_max_size()

2022-08-01 Thread Xuan Zhuo
Use virtqueue_get_vring_max_size() in virtnet_get_ringparam() to set
tx,rx_max_pending.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 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 40532ecbe7fc..981ef8ea4d58 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2254,10 +2254,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 = vi->rq[0].vq->num_max;
+   ring->tx_max_pending = vi->sq[0].vq->num_max;
+   ring->rx_pending = virtqueue_get_vring_size(vi->rq[0].vq);
+   ring->tx_pending = virtqueue_get_vring_size(vi->sq[0].vq);
 }
 
 static bool virtnet_commit_rss_command(struct virtnet_info *vi)
-- 
2.31.0

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


[PATCH v14 39/42] virtio_net: split free_unused_bufs()

2022-08-01 Thread 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 
Acked-by: Jason Wang 
---
 drivers/net/virtio_net.c | 41 
 1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 981ef8ea4d58..fe4dc43c05a1 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3151,6 +3151,27 @@ static void free_receive_page_frags(struct virtnet_info 
*vi)
put_page(vi->rq[i].alloc_frag.page);
 }
 
+static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf)
+{
+   if (!is_xdp_frame(buf))
+   dev_kfree_skb(buf);
+   else
+   xdp_return_frame(ptr_to_xdp(buf));
+}
+
+static void virtnet_rq_free_unused_buf(struct virtqueue *vq, void *buf)
+{
+   struct virtnet_info *vi = vq->vdev->priv;
+   int i = vq2rxq(vq);
+
+   if (vi->mergeable_rx_bufs)
+   put_page(virt_to_head_page(buf));
+   else if (vi->big_packets)
+   give_pages(>rq[i], buf);
+   else
+   put_page(virt_to_head_page(buf));
+}
+
 static void free_unused_bufs(struct virtnet_info *vi)
 {
void *buf;
@@ -3158,26 +3179,14 @@ static void free_unused_bufs(struct virtnet_info *vi)
 
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(vq)) != NULL)
+   virtnet_sq_free_unused_buf(vq, 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(>rq[i], buf);
-   } else {
-   put_page(virt_to_head_page(buf));
-   }
-   }
+   while ((buf = virtqueue_detach_unused_buf(vq)) != NULL)
+   virtnet_rq_free_unused_buf(vq, buf);
}
 }
 
-- 
2.31.0

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


[PATCH v14 37/42] virtio_net: set the default max ring size by find_vqs()

2022-08-01 Thread 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 
Acked-by: Jason Wang 
---
 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 8a5810bcb839..40532ecbe7fc 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -3208,6 +3208,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_1) {
+   rx_size = 1024;
+   tx_size = 1024;
+
+   } else if (vi->speed < SPEED_4) {
+   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;
@@ -3215,6 +3238,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
@@ -3242,10 +3266,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] = 64;
}
 
/* Allocate/initialize parameters for send/receive virtqueues */
@@ -3260,8 +3289,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, sizes, ctx, NULL);
if (ret)
goto err_find;
 
@@ -3281,6 +3312,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 
 
 err_find:
+   kfree(sizes);
+err_sizes:
kfree(ctx);
 err_ctx:
kfree(names);
@@ -3630,6 +3663,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)
@@ -3642,8 +3678,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


[PATCH v14 34/42] virtio_pci: support the arg sizes of find_vqs()

2022-08-01 Thread Xuan Zhuo
Virtio PCI supports new parameter sizes of find_vqs().

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 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 7ad734584823..00ad476a815d 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -174,6 +174,7 @@ static int vp_request_msix_vectors(struct virtio_device 
*vdev, int nvectors,
 static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned int 
index,
 void (*callback)(struct virtqueue *vq),
 const char *name,
+u32 size,
 bool ctx,
 u16 msix_vec)
 {
@@ -186,7 +187,7 @@ static struct virtqueue *vp_setup_vq(struct virtio_device 
*vdev, unsigned int in
if (!info)
return ERR_PTR(-ENOMEM);
 
-   vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx,
+   vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, size, ctx,
  msix_vec);
if (IS_ERR(vq))
goto out_info;
@@ -283,7 +284,7 @@ void vp_del_vqs(struct virtio_device *vdev)
 
 static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned int 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)
 {
@@ -326,8 +327,8 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, 
unsigned int 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;
@@ -357,7 +358,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, 
unsigned int nvqs,
 
 static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned int 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;
@@ -379,6 +380,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, 
unsigned int 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])) {
@@ -402,15 +404,15 @@ int vp_find_vqs(struct virtio_device *vdev, unsigned int 
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 a5ff838b85a5..c0448378b698 100644
--- a/drivers/virtio/virtio_pci_common.h
+++ b/drivers/virtio/virtio_pci_common.h
@@ -80,6 +80,7 @@ struct virtio_pci_device {
  unsigned int idx,
  void (*callback)(struct virtqueue *vq),
  const char *name,
+ u32 size,
  bool ctx,
  u16 msix_vec);
void (*del_vq)(struct 

[PATCH v14 35/42] virtio_mmio: support the arg sizes of find_vqs()

2022-08-01 Thread Xuan Zhuo
Virtio MMIO support the new parameter sizes of find_vqs().

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 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 5e3ba3cc7fd0..c888fee18caf 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -360,7 +360,7 @@ static void vm_synchronize_cbs(struct virtio_device *vdev)
 
 static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned int 
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;
@@ -395,8 +395,11 @@ static struct virtqueue *vm_setup_vq(struct virtio_device 
*vdev, unsigned int in
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;
@@ -497,6 +500,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned 
int 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


[PATCH v14 36/42] virtio: add helper virtio_find_vqs_ctx_size()

2022-08-01 Thread 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 
Acked-by: Jason Wang 
---
 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 888f7e96f0c7..6adff09f7170 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -241,6 +241,18 @@ int virtio_find_vqs_ctx(struct virtio_device *vdev, 
unsigned nvqs,
  ctx, desc);
 }
 
+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[],
+u32 sizes[],
+const bool *ctx, struct irq_affinity *desc)
+{
+   return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, sizes,
+ ctx, desc);
+}
+
 /**
  * virtio_synchronize_cbs - synchronize with virtqueue callbacks
  * @vdev: the device
-- 
2.31.0

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


[PATCH v14 33/42] virtio: find_vqs() add arg sizes

2022-08-01 Thread Xuan Zhuo
find_vqs() adds a new parameter sizes to specify the size of each vq
vring.

NULL as sizes means that all queues in find_vqs() use the maximum size.
A value in the array is 0, which means that the corresponding queue uses
the maximum size.

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 
Acked-by: Hans de Goede 
Reviewed-by: Mathieu Poirier 
Acked-by: Jason Wang 
---
 arch/um/drivers/virtio_uml.c |  2 +-
 drivers/platform/mellanox/mlxbf-tmfifo.c |  1 +
 drivers/remoteproc/remoteproc_virtio.c   |  1 +
 drivers/s390/virtio/virtio_ccw.c |  1 +
 drivers/virtio/virtio_mmio.c |  1 +
 drivers/virtio/virtio_pci_common.c   |  2 +-
 drivers/virtio/virtio_pci_common.h   |  2 +-
 drivers/virtio/virtio_pci_modern.c   |  7 +--
 drivers/virtio/virtio_vdpa.c |  1 +
 include/linux/virtio_config.h| 14 +-
 10 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
index e719af8bdf56..79e38afd4b91 100644
--- a/arch/um/drivers/virtio_uml.c
+++ b/arch/um/drivers/virtio_uml.c
@@ -1011,7 +1011,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,
+  const char * const names[], u32 sizes[], const bool *ctx,
   struct irq_affinity *desc)
 {
struct virtio_uml_device *vu_dev = to_virtio_uml_device(vdev);
diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c 
b/drivers/platform/mellanox/mlxbf-tmfifo.c
index 1ae3c56b66b0..8be13d416f48 100644
--- a/drivers/platform/mellanox/mlxbf-tmfifo.c
+++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
@@ -928,6 +928,7 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct 
virtio_device *vdev,
struct virtqueue *vqs[],
vq_callback_t *callbacks[],
const char * const names[],
+   u32 sizes[],
const bool *ctx,
struct irq_affinity *desc)
 {
diff --git a/drivers/remoteproc/remoteproc_virtio.c 
b/drivers/remoteproc/remoteproc_virtio.c
index 0f7706e23eb9..81c4f5776109 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -158,6 +158,7 @@ static int rproc_virtio_find_vqs(struct virtio_device 
*vdev, unsigned int nvqs,
 struct virtqueue *vqs[],
 vq_callback_t *callbacks[],
 const char * const names[],
+u32 sizes[],
 const bool * ctx,
 struct irq_affinity *desc)
 {
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index 6b86d0280d6b..72500cd2dbf5 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -635,6 +635,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, 
unsigned nvqs,
   struct virtqueue *vqs[],
   vq_callback_t *callbacks[],
   const char * const names[],
+  u32 sizes[],
   const bool *ctx,
   struct irq_affinity *desc)
 {
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index a20d5a6b5819..5e3ba3cc7fd0 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -474,6 +474,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned 
int nvqs,
   struct virtqueue *vqs[],
   vq_callback_t *callbacks[],
   const char * const names[],
+  u32 sizes[],
   const bool *ctx,
   struct irq_affinity *desc)
 {
diff --git a/drivers/virtio/virtio_pci_common.c 
b/drivers/virtio/virtio_pci_common.c
index ad258a9d3b9f..7ad734584823 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -396,7 +396,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, 
unsigned int nvqs,
 /* the config->find_vqs() implementation */
 int vp_find_vqs(struct virtio_device *vdev, unsigned int 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 irq_affinity *desc)
 {
int err;

[PATCH v14 31/42] virtio_pci: extract the logic of active vq for modern pci

2022-08-01 Thread Xuan Zhuo
Introduce vp_active_vq() to configure vring to backend after vq attach
vring. And configure vq vector if necessary.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 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 e7e0b8c850f6..9041d9a41b7d 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_synchronize_vectors(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 = _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(_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


[PATCH v14 32/42] virtio_pci: support VIRTIO_F_RING_RESET

2022-08-01 Thread Xuan Zhuo
This patch implements virtio pci support for QUEUE RESET.

Performing reset on a queue is divided into these steps:

 1. notify the device to reset the queue
 2. recycle the buffer submitted
 3. reset the vring (may re-alloc)
 4. 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 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_pci_common.c | 12 +++-
 drivers/virtio/virtio_pci_modern.c | 88 ++
 2 files changed, 97 insertions(+), 3 deletions(-)

diff --git a/drivers/virtio/virtio_pci_common.c 
b/drivers/virtio/virtio_pci_common.c
index ca51fcc9daab..ad258a9d3b9f 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -214,9 +214,15 @@ 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(_dev->lock, flags);
-   list_del(>node);
-   spin_unlock_irqrestore(_dev->lock, flags);
+   /*
+* If it fails during re-enable reset vq. This way we won't rejoin
+* info->node to the queue. Prevent unexpected irqs.
+*/
+   if (!vq->reset) {
+   spin_lock_irqsave(_dev->lock, flags);
+   list_del(>node);
+   spin_unlock_irqrestore(_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 9041d9a41b7d..c3b9f2761849 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,87 @@ static int vp_active_vq(struct virtqueue *vq, u16 msix_vec)
return 0;
 }
 
+static int vp_modern_disable_vq_and_reset(struct virtqueue *vq)
+{
+   struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+   struct virtio_pci_modern_device *mdev = _dev->mdev;
+   struct virtio_pci_vq_info *info;
+   unsigned long flags;
+
+   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(_dev->lock, flags);
+   list_del(>node);
+   spin_unlock_irqrestore(_dev->lock, flags);
+
+   INIT_LIST_HEAD(>node);
+
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
+   __virtqueue_break(vq);
+#endif
+
+   /* For the case where vq has an exclusive irq, call synchronize_irq() to
+* wait for completion.
+*
+* note: We can't use disable_irq() since it conflicts with the affinity
+* managed IRQ that is used by some drivers.
+*/
+   if (vp_dev->per_vq_vectors && info->msix_vector != VIRTIO_MSI_NO_VECTOR)
+   synchronize_irq(pci_irq_vector(vp_dev->pci_dev, 
info->msix_vector));
+
+   vq->reset = true;
+
+   return 0;
+}
+
+static int vp_modern_enable_vq_after_reset(struct virtqueue *vq)
+{
+   struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
+   struct virtio_pci_modern_device *mdev = _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];
+
+   if (vp_modern_get_queue_reset(mdev, index))
+   return -EBUSY;
+
+   if (vp_modern_get_queue_enable(mdev, index))
+   return -EBUSY;
+
+   err = vp_active_vq(vq, info->msix_vector);
+   if (err)
+   return err;
+
+   if (vq->callback) {
+   spin_lock_irqsave(_dev->lock, flags);
+   list_add(>node, _dev->virtqueues);
+   spin_unlock_irqrestore(_dev->lock, flags);
+   } else {
+   INIT_LIST_HEAD(>node);
+   }
+
+#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION
+   __virtqueue_unbreak(vq);
+#endif
+
+   vp_modern_set_queue_enable(_dev->mdev, index, true);
+   vq->reset = false;
+
+   return 0;
+}
+
 static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
 {
return vp_modern_config_vector(_dev->mdev, vector);
@@ -413,6 +497,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,
+   

[PATCH v14 29/42] virtio_pci: struct virtio_pci_common_cfg add queue_reset

2022-08-01 Thread Xuan Zhuo
Add queue_reset in virtio_pci_modern_common_cfg.

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

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 include/linux/virtio_pci_modern.h | 2 +-
 include/uapi/linux/virtio_pci.h   | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/linux/virtio_pci_modern.h 
b/include/linux/virtio_pci_modern.h
index 41f5a018bd94..05123b9a606f 100644
--- a/include/linux/virtio_pci_modern.h
+++ b/include/linux/virtio_pci_modern.h
@@ -9,7 +9,7 @@ struct virtio_pci_modern_common_cfg {
struct virtio_pci_common_cfg cfg;
 
__le16 queue_notify_data;   /* read-write */
-   __le16 padding;
+   __le16 queue_reset; /* read-write */
 };
 
 struct virtio_pci_modern_device {
diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
index f5981a874481..f703afc7ad31 100644
--- a/include/uapi/linux/virtio_pci.h
+++ b/include/uapi/linux/virtio_pci.h
@@ -203,6 +203,7 @@ struct virtio_pci_cfg_cap {
 #define VIRTIO_PCI_COMMON_Q_USEDLO 48
 #define VIRTIO_PCI_COMMON_Q_USEDHI 52
 #define VIRTIO_PCI_COMMON_Q_NDATA  56
+#define VIRTIO_PCI_COMMON_Q_RESET  58
 
 #endif /* VIRTIO_PCI_NO_MODERN */
 
-- 
2.31.0

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


[PATCH v14 30/42] virtio_pci: introduce helper to get/set queue reset

2022-08-01 Thread Xuan Zhuo
Introduce new helpers to implement queue reset and get queue reset
status.

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

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_pci_modern_dev.c | 39 ++
 include/linux/virtio_pci_modern.h  |  2 ++
 2 files changed, 41 insertions(+)

diff --git a/drivers/virtio/virtio_pci_modern_dev.c 
b/drivers/virtio/virtio_pci_modern_dev.c
index fa2a9445bb18..869cb46bef96 100644
--- a/drivers/virtio/virtio_pci_modern_dev.c
+++ b/drivers/virtio/virtio_pci_modern_dev.c
@@ -3,6 +3,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * vp_modern_map_capability - map a part of virtio pci capability
@@ -474,6 +475,44 @@ 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_modern_common_cfg __iomem *cfg;
+
+   cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common;
+
+   vp_iowrite16(index, >cfg.queue_select);
+   return vp_ioread16(>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_modern_common_cfg __iomem *cfg;
+
+   cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common;
+
+   vp_iowrite16(index, >cfg.queue_select);
+   vp_iowrite16(1, >queue_reset);
+
+   while (vp_ioread16(>queue_reset))
+   msleep(1);
+
+   while (vp_ioread16(>cfg.queue_enable))
+   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 05123b9a606f..c4eeb79b0139 100644
--- a/include/linux/virtio_pci_modern.h
+++ b/include/linux/virtio_pci_modern.h
@@ -113,4 +113,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
-- 
2.31.0

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


[PATCH v14 28/42] virtio_ring: struct virtqueue introduce reset

2022-08-01 Thread Xuan Zhuo
Introduce a new member reset to the structure virtqueue to determine
whether the current vq is in the reset state. Subsequent patches will
use it.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 2 ++
 include/linux/virtio.h   | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index accb3ae6cc95..d66c8e6d0ef3 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1996,6 +1996,7 @@ static struct virtqueue *vring_create_virtqueue_packed(
vq->vq.vdev = vdev;
vq->vq.name = name;
vq->vq.index = index;
+   vq->vq.reset = false;
vq->we_own_ring = true;
vq->notify = notify;
vq->weak_barriers = weak_barriers;
@@ -2481,6 +2482,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned 
int index,
vq->vq.vdev = vdev;
vq->vq.name = name;
vq->vq.index = index;
+   vq->vq.reset = false;
vq->we_own_ring = false;
vq->notify = notify;
vq->weak_barriers = weak_barriers;
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index d45ee82a4470..a3f73bb6733e 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -20,6 +20,7 @@
  * @index: the zero-based ordinal number for this queue.
  * @num_free: number of elements we expect to be able to fit.
  * @num_max: the maximum number of elements supported by the device.
+ * @reset: vq is in reset state or not.
  *
  * A note on @num_free: with indirect buffers, each buffer needs one
  * element in the queue, otherwise a buffer will need one element per
@@ -34,6 +35,7 @@ struct virtqueue {
unsigned int num_free;
unsigned int num_max;
void *priv;
+   bool 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


[PATCH v14 27/42] virtio: queue_reset: add VIRTIO_F_RING_RESET

2022-08-01 Thread Xuan Zhuo
Added VIRTIO_F_RING_RESET, it came from here

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

This feature indicates that the driver can reset a queue individually.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 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 f0fb0ae021c0..3c05162bc988 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
@@ -98,4 +98,9 @@
  * Does the device support Single Root I/O Virtualization?
  */
 #define VIRTIO_F_SR_IOV37
+
+/*
+ * This feature indicates that the driver can reset a queue individually.
+ */
+#define VIRTIO_F_RING_RESET40
 #endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */
-- 
2.31.0

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


[PATCH v14 25/42] virtio_pci: struct virtio_pci_common_cfg add queue_notify_data

2022-08-01 Thread 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

In order not to affect the API, add a dedicated structure struct
virtio_pci_modern_common_cfg to virtio_pci_modern.h.

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

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 include/linux/virtio_pci_modern.h | 7 +++
 include/uapi/linux/virtio_pci.h   | 1 +
 2 files changed, 8 insertions(+)

diff --git a/include/linux/virtio_pci_modern.h 
b/include/linux/virtio_pci_modern.h
index eb2bd9b4077d..41f5a018bd94 100644
--- a/include/linux/virtio_pci_modern.h
+++ b/include/linux/virtio_pci_modern.h
@@ -5,6 +5,13 @@
 #include 
 #include 
 
+struct virtio_pci_modern_common_cfg {
+   struct virtio_pci_common_cfg cfg;
+
+   __le16 queue_notify_data;   /* read-write */
+   __le16 padding;
+};
+
 struct virtio_pci_modern_device {
struct pci_dev *pci_dev;
 
diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
index 3a86f36d7e3d..f5981a874481 100644
--- a/include/uapi/linux/virtio_pci.h
+++ b/include/uapi/linux/virtio_pci.h
@@ -202,6 +202,7 @@ struct virtio_pci_cfg_cap {
 #define VIRTIO_PCI_COMMON_Q_AVAILHI44
 #define VIRTIO_PCI_COMMON_Q_USEDLO 48
 #define VIRTIO_PCI_COMMON_Q_USEDHI 52
+#define VIRTIO_PCI_COMMON_Q_NDATA  56
 
 #endif /* VIRTIO_PCI_NO_MODERN */
 
-- 
2.31.0

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


[PATCH v14 23/42] virtio_ring: packed: introduce virtqueue_resize_packed()

2022-08-01 Thread Xuan Zhuo
virtio ring packed supports resize.

Only after the new vring is successfully allocated based on the new num,
we will release the old vring. In any case, an error is returned,
indicating that the vring still points to the old vring.

In the case of an error, re-initialize(by virtqueue_reinit_packed()) the
virtqueue to ensure that the vring can be used.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index db06fb0ddfd6..bea5a3448217 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2036,6 +2036,36 @@ static struct virtqueue *vring_create_virtqueue_packed(
return NULL;
 }
 
+static int virtqueue_resize_packed(struct virtqueue *_vq, u32 num)
+{
+   struct vring_virtqueue_packed vring_packed = {};
+   struct vring_virtqueue *vq = to_vvq(_vq);
+   struct virtio_device *vdev = _vq->vdev;
+   int err;
+
+   if (vring_alloc_queue_packed(_packed, vdev, num))
+   goto err_ring;
+
+   err = vring_alloc_state_extra_packed(_packed);
+   if (err)
+   goto err_state_extra;
+
+   vring_free(>vq);
+
+   virtqueue_vring_init_packed(_packed, !!vq->vq.callback);
+
+   virtqueue_init(vq, vring_packed.vring.num);
+   virtqueue_vring_attach_packed(vq, _packed);
+
+   return 0;
+
+err_state_extra:
+   vring_free_packed(_packed, vdev);
+err_ring:
+   virtqueue_reinit_packed(vq);
+   return -ENOMEM;
+}
+
 
 /*
  * Generic functions and exported symbols.
-- 
2.31.0

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


[PATCH v14 26/42] virtio: allow to unbreak/break virtqueue individually

2022-08-01 Thread Xuan Zhuo
This patch allows the new introduced
__virtqueue_break()/__virtqueue_unbreak() to break/unbreak the
virtqueue.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 24 
 include/linux/virtio.h   |  3 +++
 2 files changed, 27 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 6447a09e2e38..accb3ae6cc95 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2724,6 +2724,30 @@ unsigned int virtqueue_get_vring_size(struct virtqueue 
*_vq)
 }
 EXPORT_SYMBOL_GPL(virtqueue_get_vring_size);
 
+/*
+ * This function should only be called by the core, not directly by the driver.
+ */
+void __virtqueue_break(struct virtqueue *_vq)
+{
+   struct vring_virtqueue *vq = to_vvq(_vq);
+
+   /* Pairs with READ_ONCE() in virtqueue_is_broken(). */
+   WRITE_ONCE(vq->broken, true);
+}
+EXPORT_SYMBOL_GPL(__virtqueue_break);
+
+/*
+ * This function should only be called by the core, not directly by the driver.
+ */
+void __virtqueue_unbreak(struct virtqueue *_vq)
+{
+   struct vring_virtqueue *vq = to_vvq(_vq);
+
+   /* Pairs with READ_ONCE() in virtqueue_is_broken(). */
+   WRITE_ONCE(vq->broken, false);
+}
+EXPORT_SYMBOL_GPL(__virtqueue_unbreak);
+
 bool virtqueue_is_broken(struct virtqueue *_vq)
 {
struct vring_virtqueue *vq = to_vvq(_vq);
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 62e31bca5602..d45ee82a4470 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -138,6 +138,9 @@ bool is_virtio_device(struct device *dev);
 void virtio_break_device(struct virtio_device *dev);
 void __virtio_unbreak_device(struct virtio_device *dev);
 
+void __virtqueue_break(struct virtqueue *_vq);
+void __virtqueue_unbreak(struct virtqueue *_vq);
+
 void virtio_config_changed(struct virtio_device *dev);
 #ifdef CONFIG_PM_SLEEP
 int virtio_device_freeze(struct virtio_device *dev);
-- 
2.31.0

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


[PATCH v14 24/42] virtio_ring: introduce virtqueue_resize()

2022-08-01 Thread Xuan Zhuo
Introduce virtqueue_resize() to implement the resize of vring.
Based on these, the driver can dynamically adjust the size of the vring.
For example: ethtool -G.

virtqueue_resize() implements resize based on the vq reset function. In
case of failure to allocate a new vring, it will give up resize and use
the original vring.

During this process, if the re-enable reset vq fails, the vq can no
longer be used. Although the probability of this situation is not high.

The parameter recycle is used to recycle the buffer that is no longer
used.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 69 
 include/linux/virtio.h   |  3 ++
 2 files changed, 72 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index bea5a3448217..6447a09e2e38 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2539,6 +2539,75 @@ struct virtqueue *vring_create_virtqueue(
 }
 EXPORT_SYMBOL_GPL(vring_create_virtqueue);
 
+/**
+ * virtqueue_resize - resize the vring of vq
+ * @_vq: the struct virtqueue we're talking about.
+ * @num: new ring num
+ * @recycle: callback for recycle the useless buffer
+ *
+ * When it is really necessary to create a new vring, it will set the current 
vq
+ * into the reset state. Then call the passed callback to recycle the buffer
+ * that is no longer used. Only after the new vring is successfully created, 
the
+ * old vring will be released.
+ *
+ * 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.
+ * 0: success.
+ * -ENOMEM: Failed to allocate a new ring, fall back to the original ring size.
+ *  vq can still work normally
+ * -EBUSY: Failed to sync with device, vq may not work properly
+ * -ENOENT: Transport or device not supported
+ * -E2BIG/-EINVAL: num error
+ * -EPERM: Operation not permitted
+ *
+ */
+int virtqueue_resize(struct virtqueue *_vq, u32 num,
+void (*recycle)(struct virtqueue *vq, void *buf))
+{
+   struct vring_virtqueue *vq = to_vvq(_vq);
+   struct virtio_device *vdev = vq->vq.vdev;
+   void *buf;
+   int err;
+
+   if (!vq->we_own_ring)
+   return -EPERM;
+
+   if (num > vq->vq.num_max)
+   return -E2BIG;
+
+   if (!num)
+   return -EINVAL;
+
+   if ((vq->packed_ring ? vq->packed.vring.num : vq->split.vring.num) == 
num)
+   return 0;
+
+   if (!vdev->config->disable_vq_and_reset)
+   return -ENOENT;
+
+   if (!vdev->config->enable_vq_after_reset)
+   return -ENOENT;
+
+   err = vdev->config->disable_vq_and_reset(_vq);
+   if (err)
+   return err;
+
+   while ((buf = virtqueue_detach_unused_buf(_vq)) != NULL)
+   recycle(_vq, buf);
+
+   if (vq->packed_ring)
+   err = virtqueue_resize_packed(_vq, num);
+   else
+   err = virtqueue_resize_split(_vq, num);
+
+   if (vdev->config->enable_vq_after_reset(_vq))
+   return -EBUSY;
+
+   return err;
+}
+EXPORT_SYMBOL_GPL(virtqueue_resize);
+
 /* 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 129bde7521e3..62e31bca5602 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -91,6 +91,9 @@ 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_resize(struct virtqueue *vq, u32 num,
+void (*recycle)(struct virtqueue *vq, void *buf));
+
 /**
  * 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


[PATCH v14 22/42] virtio_ring: packed: introduce virtqueue_reinit_packed()

2022-08-01 Thread Xuan Zhuo
Introduce a function to initialize vq without allocating new ring,
desc_state, desc_extra.

Subsequent patches will call this function after reset vq to
reinitialize vq.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 93d2a950f536..db06fb0ddfd6 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1957,6 +1957,18 @@ static void virtqueue_vring_attach_packed(struct 
vring_virtqueue *vq,
vq->free_head = 0;
 }
 
+static void virtqueue_reinit_packed(struct vring_virtqueue *vq)
+{
+   memset(vq->packed.vring.device, 0, vq->packed.event_size_in_bytes);
+   memset(vq->packed.vring.driver, 0, vq->packed.event_size_in_bytes);
+
+   /* we need to reset the desc.flags. For more, see is_used_desc_packed() 
*/
+   memset(vq->packed.vring.desc, 0, vq->packed.ring_size_in_bytes);
+
+   virtqueue_init(vq, vq->packed.vring.num);
+   virtqueue_vring_init_packed(>packed, !!vq->vq.callback);
+}
+
 static struct virtqueue *vring_create_virtqueue_packed(
unsigned int index,
unsigned int num,
-- 
2.31.0

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


[PATCH v14 19/42] virtio_ring: packed: extract the logic of alloc state and extra

2022-08-01 Thread Xuan Zhuo
Separate the logic for alloc desc_state and desc_extra, which will
be called separately by subsequent patches.

Use struct vring_packed to pass desc_state, desc_extra.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 48 +---
 1 file changed, 34 insertions(+), 14 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 8209923ea7d7..533af061d009 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1905,6 +1905,33 @@ static int vring_alloc_queue_packed(struct 
vring_virtqueue_packed *vring_packed,
return -ENOMEM;
 }
 
+static int vring_alloc_state_extra_packed(struct vring_virtqueue_packed 
*vring_packed)
+{
+   struct vring_desc_state_packed *state;
+   struct vring_desc_extra *extra;
+   u32 num = vring_packed->vring.num;
+
+   state = kmalloc_array(num, sizeof(struct vring_desc_state_packed), 
GFP_KERNEL);
+   if (!state)
+   goto err_desc_state;
+
+   memset(state, 0, num * sizeof(struct vring_desc_state_packed));
+
+   extra = vring_alloc_desc_extra(num);
+   if (!extra)
+   goto err_desc_extra;
+
+   vring_packed->desc_state = state;
+   vring_packed->desc_extra = extra;
+
+   return 0;
+
+err_desc_extra:
+   kfree(state);
+err_desc_state:
+   return -ENOMEM;
+}
+
 static struct virtqueue *vring_create_virtqueue_packed(
unsigned int index,
unsigned int num,
@@ -1919,6 +1946,7 @@ static struct virtqueue *vring_create_virtqueue_packed(
 {
struct vring_virtqueue_packed vring_packed = {};
struct vring_virtqueue *vq;
+   int err;
 
if (vring_alloc_queue_packed(_packed, vdev, num))
goto err_ring;
@@ -1963,21 +1991,15 @@ static struct virtqueue *vring_create_virtqueue_packed(
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));
+   err = vring_alloc_state_extra_packed(_packed);
+   if (err)
+   goto err_state_extra;
 
/* Put everything in free lists. */
vq->free_head = 0;
 
-   vq->packed.desc_extra = vring_alloc_desc_extra(num);
-   if (!vq->packed.desc_extra)
-   goto err_desc_extra;
+   vq->packed.desc_state = vring_packed.desc_state;
+   vq->packed.desc_extra = vring_packed.desc_extra;
 
/* No callback?  Tell other side not to bother us. */
if (!callback) {
@@ -1993,9 +2015,7 @@ static struct virtqueue *vring_create_virtqueue_packed(
spin_unlock(>vqs_list_lock);
return >vq;
 
-err_desc_extra:
-   kfree(vq->packed.desc_state);
-err_desc_state:
+err_state_extra:
kfree(vq);
 err_vq:
vring_free_packed(_packed, vdev);
-- 
2.31.0

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


[PATCH v14 21/42] virtio_ring: packed: extract the logic of attach vring

2022-08-01 Thread Xuan Zhuo
Separate the logic of attach vring, the subsequent patch will call it
separately.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 25 ++---
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index a6f90e6e621b..93d2a950f536 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1948,6 +1948,15 @@ static void virtqueue_vring_init_packed(struct 
vring_virtqueue_packed *vring_pac
}
 }
 
+static void virtqueue_vring_attach_packed(struct vring_virtqueue *vq,
+ struct vring_virtqueue_packed 
*vring_packed)
+{
+   vq->packed = *vring_packed;
+
+   /* Put everything in free lists. */
+   vq->free_head = 0;
+}
+
 static struct virtqueue *vring_create_virtqueue_packed(
unsigned int index,
unsigned int num,
@@ -1993,28 +2002,14 @@ 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 = vring_packed.ring_dma_addr;
-   vq->packed.driver_event_dma_addr = vring_packed.driver_event_dma_addr;
-   vq->packed.device_event_dma_addr = vring_packed.device_event_dma_addr;
-
-   vq->packed.ring_size_in_bytes = vring_packed.ring_size_in_bytes;
-   vq->packed.event_size_in_bytes = vring_packed.event_size_in_bytes;
-
-   vq->packed.vring = vring_packed.vring;
-
err = vring_alloc_state_extra_packed(_packed);
if (err)
goto err_state_extra;
 
-   /* Put everything in free lists. */
-   vq->free_head = 0;
-
-   vq->packed.desc_state = vring_packed.desc_state;
-   vq->packed.desc_extra = vring_packed.desc_extra;
-
virtqueue_vring_init_packed(_packed, !!callback);
 
virtqueue_init(vq, num);
+   virtqueue_vring_attach_packed(vq, _packed);
 
spin_lock(>vqs_list_lock);
list_add_tail(>vq.list, >vqs);
-- 
2.31.0

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


[PATCH v14 20/42] virtio_ring: packed: extract the logic of vring init

2022-08-01 Thread Xuan Zhuo
Separate the logic of initializing vring, and subsequent patches will
call it separately.

This function completes the variable initialization of packed vring. It
together with the logic of atatch constitutes the initialization of
vring.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 28 +---
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 533af061d009..a6f90e6e621b 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1932,6 +1932,22 @@ static int vring_alloc_state_extra_packed(struct 
vring_virtqueue_packed *vring_p
return -ENOMEM;
 }
 
+static void virtqueue_vring_init_packed(struct vring_virtqueue_packed 
*vring_packed,
+   bool callback)
+{
+   vring_packed->next_avail_idx = 0;
+   vring_packed->avail_wrap_counter = 1;
+   vring_packed->event_flags_shadow = 0;
+   vring_packed->avail_used_flags = 1 << VRING_PACKED_DESC_F_AVAIL;
+
+   /* No callback?  Tell other side not to bother us. */
+   if (!callback) {
+   vring_packed->event_flags_shadow = 
VRING_PACKED_EVENT_FLAG_DISABLE;
+   vring_packed->vring.driver->flags =
+   cpu_to_le16(vring_packed->event_flags_shadow);
+   }
+}
+
 static struct virtqueue *vring_create_virtqueue_packed(
unsigned int index,
unsigned int num,
@@ -1986,11 +2002,6 @@ static struct virtqueue *vring_create_virtqueue_packed(
 
vq->packed.vring = vring_packed.vring;
 
-   vq->packed.next_avail_idx = 0;
-   vq->packed.avail_wrap_counter = 1;
-   vq->packed.event_flags_shadow = 0;
-   vq->packed.avail_used_flags = 1 << VRING_PACKED_DESC_F_AVAIL;
-
err = vring_alloc_state_extra_packed(_packed);
if (err)
goto err_state_extra;
@@ -2001,12 +2012,7 @@ static struct virtqueue *vring_create_virtqueue_packed(
vq->packed.desc_state = vring_packed.desc_state;
vq->packed.desc_extra = vring_packed.desc_extra;
 
-   /* No callback?  Tell other side not to bother us. */
-   if (!callback) {
-   vq->packed.event_flags_shadow = VRING_PACKED_EVENT_FLAG_DISABLE;
-   vq->packed.vring.driver->flags =
-   cpu_to_le16(vq->packed.event_flags_shadow);
-   }
+   virtqueue_vring_init_packed(_packed, !!callback);
 
virtqueue_init(vq, num);
 
-- 
2.31.0

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


[PATCH v14 17/42] virtio_ring: packed: introduce vring_free_packed

2022-08-01 Thread Xuan Zhuo
Free the structure struct vring_vritqueue_packed.

Subsequent patches require it.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 1852912d711e..2993d817871a 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1832,6 +1832,28 @@ static struct vring_desc_extra 
*vring_alloc_desc_extra(unsigned int num)
return desc_extra;
 }
 
+static void vring_free_packed(struct vring_virtqueue_packed *vring_packed,
+ struct virtio_device *vdev)
+{
+   if (vring_packed->vring.desc)
+   vring_free_queue(vdev, vring_packed->ring_size_in_bytes,
+vring_packed->vring.desc,
+vring_packed->ring_dma_addr);
+
+   if (vring_packed->vring.driver)
+   vring_free_queue(vdev, vring_packed->event_size_in_bytes,
+vring_packed->vring.driver,
+vring_packed->driver_event_dma_addr);
+
+   if (vring_packed->vring.device)
+   vring_free_queue(vdev, vring_packed->event_size_in_bytes,
+vring_packed->vring.device,
+vring_packed->device_event_dma_addr);
+
+   kfree(vring_packed->desc_state);
+   kfree(vring_packed->desc_extra);
+}
+
 static struct virtqueue *vring_create_virtqueue_packed(
unsigned int index,
unsigned int num,
-- 
2.31.0

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


[PATCH v14 18/42] virtio_ring: packed: extract the logic of alloc queue

2022-08-01 Thread Xuan Zhuo
Separate the logic of packed to create vring queue.

This feature is required for subsequent virtuqueue reset vring.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 80 +++-
 1 file changed, 51 insertions(+), 29 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 2993d817871a..8209923ea7d7 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -1854,19 +1854,10 @@ static void vring_free_packed(struct 
vring_virtqueue_packed *vring_packed,
kfree(vring_packed->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 int vring_alloc_queue_packed(struct vring_virtqueue_packed 
*vring_packed,
+   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;
@@ -1878,7 +1869,11 @@ static struct virtqueue *vring_create_virtqueue_packed(
 _dma_addr,
 GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
if (!ring)
-   goto err_ring;
+   goto err;
+
+   vring_packed->vring.desc = ring;
+   vring_packed->ring_dma_addr  = ring_dma_addr;
+   vring_packed->ring_size_in_bytes = ring_size_in_bytes;
 
event_size_in_bytes = sizeof(struct vring_packed_desc_event);
 
@@ -1886,13 +1881,47 @@ static struct virtqueue *vring_create_virtqueue_packed(
   _event_dma_addr,
   GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
if (!driver)
-   goto err_driver;
+   goto err;
+
+   vring_packed->vring.driver  = driver;
+   vring_packed->event_size_in_bytes   = event_size_in_bytes;
+   vring_packed->driver_event_dma_addr = driver_event_dma_addr;
 
device = vring_alloc_queue(vdev, event_size_in_bytes,
   _event_dma_addr,
   GFP_KERNEL|__GFP_NOWARN|__GFP_ZERO);
if (!device)
-   goto err_device;
+   goto err;
+
+   vring_packed->vring.device  = device;
+   vring_packed->device_event_dma_addr = device_event_dma_addr;
+
+   vring_packed->vring.num = num;
+
+   return 0;
+
+err:
+   vring_free_packed(vring_packed, 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_packed vring_packed = {};
+   struct vring_virtqueue *vq;
+
+   if (vring_alloc_queue_packed(_packed, vdev, num))
+   goto err_ring;
 
vq = kmalloc(sizeof(*vq), GFP_KERNEL);
if (!vq)
@@ -1920,17 +1949,14 @@ 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_packed.ring_dma_addr;
+   vq->packed.driver_event_dma_addr = vring_packed.driver_event_dma_addr;
+   vq->packed.device_event_dma_addr = vring_packed.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_packed.ring_size_in_bytes;
+   vq->packed.event_size_in_bytes = vring_packed.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 = vring_packed.vring;
 
vq->packed.next_avail_idx = 0;
vq->packed.avail_wrap_counter = 1;
@@ -1972,11 +1998,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, 

[PATCH v14 16/42] virtio_ring: split: introduce virtqueue_resize_split()

2022-08-01 Thread Xuan Zhuo
virtio ring split supports resize.

Only after the new vring is successfully allocated based on the new num,
we will release the old vring. In any case, an error is returned,
indicating that the vring still points to the old vring.

In the case of an error, re-initialize(virtqueue_reinit_split()) the
virtqueue to ensure that the vring can be used.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 8cbb19cdb1ce..1852912d711e 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -220,6 +220,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int 
index,
   void (*callback)(struct 
virtqueue *),
   const char *name);
 static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
+static void vring_free(struct virtqueue *_vq);
 
 /*
  * Helpers.
@@ -1114,6 +1115,39 @@ static struct virtqueue *vring_create_virtqueue_split(
return vq;
 }
 
+static int virtqueue_resize_split(struct virtqueue *_vq, u32 num)
+{
+   struct vring_virtqueue_split vring_split = {};
+   struct vring_virtqueue *vq = to_vvq(_vq);
+   struct virtio_device *vdev = _vq->vdev;
+   int err;
+
+   err = vring_alloc_queue_split(_split, vdev, num,
+ vq->split.vring_align,
+ vq->split.may_reduce_num);
+   if (err)
+   goto err;
+
+   err = vring_alloc_state_extra_split(_split);
+   if (err)
+   goto err_state_extra;
+
+   vring_free(>vq);
+
+   virtqueue_vring_init_split(_split, vq);
+
+   virtqueue_init(vq, vring_split.vring.num);
+   virtqueue_vring_attach_split(vq, _split);
+
+   return 0;
+
+err_state_extra:
+   vring_free_split(_split, vdev);
+err:
+   virtqueue_reinit_split(vq);
+   return -ENOMEM;
+}
+
 
 /*
  * Packed ring specific functions - *_packed().
-- 
2.31.0

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


[PATCH v14 13/42] virtio_ring: split: extract the logic of attach vring

2022-08-01 Thread Xuan Zhuo
Separate the logic of attach vring, subsequent patches will call it
separately.

virtqueue_vring_init_split() completes the initialization of other
variables of vring split. We can directly use
vq->split = *vring_split to complete attach.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 23 ++-
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index e456cc16ea2a..d0df887c3ada 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -957,6 +957,15 @@ static void virtqueue_vring_init_split(struct 
vring_virtqueue_split *vring_split
}
 }
 
+static void virtqueue_vring_attach_split(struct vring_virtqueue *vq,
+struct vring_virtqueue_split 
*vring_split)
+{
+   vq->split = *vring_split;
+
+   /* Put everything in free lists. */
+   vq->free_head = 0;
+}
+
 static int vring_alloc_state_extra_split(struct vring_virtqueue_split 
*vring_split)
 {
struct vring_desc_state_split *state;
@@ -1067,8 +1076,6 @@ static struct virtqueue *vring_create_virtqueue_split(
return NULL;
}
 
-   to_vvq(vq)->split.queue_dma_addr = vring_split.queue_dma_addr;
-   to_vvq(vq)->split.queue_size_in_bytes = vring_split.queue_size_in_bytes;
to_vvq(vq)->we_own_ring = true;
 
return vq;
@@ -2317,26 +2324,16 @@ static struct virtqueue *__vring_new_virtqueue(unsigned 
int index,
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_split->vring;
-
err = vring_alloc_state_extra_split(vring_split);
if (err) {
kfree(vq);
return NULL;
}
 
-   /* Put everything in free lists. */
-   vq->free_head = 0;
-
-   vq->split.desc_state = vring_split->desc_state;
-   vq->split.desc_extra = vring_split->desc_extra;
-
virtqueue_vring_init_split(vring_split, vq);
 
virtqueue_init(vq, vring_split->vring.num);
+   virtqueue_vring_attach_split(vq, vring_split);
 
spin_lock(>vqs_list_lock);
list_add_tail(>vq.list, >vqs);
-- 
2.31.0

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


[PATCH v14 15/42] virtio_ring: split: reserve vring_align, may_reduce_num

2022-08-01 Thread Xuan Zhuo
In vring_alloc_queue_split() save vring_align, may_reduce_num to
structure vring_virtqueue_split. Used to create a new vring when
implementing resize.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 948f8da7b780..8cbb19cdb1ce 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -105,6 +105,13 @@ struct vring_virtqueue_split {
/* 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
+* vring.
+*/
+   u32 vring_align;
+   bool may_reduce_num;
 };
 
 struct vring_virtqueue_packed {
@@ -1068,6 +1075,9 @@ static int vring_alloc_queue_split(struct 
vring_virtqueue_split *vring_split,
vring_split->queue_dma_addr = dma_addr;
vring_split->queue_size_in_bytes = vring_size(num, vring_align);
 
+   vring_split->vring_align = vring_align;
+   vring_split->may_reduce_num = may_reduce_num;
+
return 0;
 }
 
-- 
2.31.0

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


[PATCH v14 14/42] virtio_ring: split: introduce virtqueue_reinit_split()

2022-08-01 Thread Xuan Zhuo
Introduce a function to initialize vq without allocating new ring,
desc_state, desc_extra.

Subsequent patches will call this function after reset vq to
reinitialize vq.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index d0df887c3ada..948f8da7b780 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -957,6 +957,29 @@ static void virtqueue_vring_init_split(struct 
vring_virtqueue_split *vring_split
}
 }
 
+static void virtqueue_reinit_split(struct vring_virtqueue *vq)
+{
+   int num;
+
+   num = vq->split.vring.num;
+
+   vq->split.vring.avail->flags = 0;
+   vq->split.vring.avail->idx = 0;
+
+   /* reset avail event */
+   vq->split.vring.avail->ring[num] = 0;
+
+   vq->split.vring.used->flags = 0;
+   vq->split.vring.used->idx = 0;
+
+   /* reset used event */
+   *(__virtio16 *)&(vq->split.vring.used->ring[num]) = 0;
+
+   virtqueue_init(vq, num);
+
+   virtqueue_vring_init_split(>split, vq);
+}
+
 static void virtqueue_vring_attach_split(struct vring_virtqueue *vq,
 struct vring_virtqueue_split 
*vring_split)
 {
-- 
2.31.0

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


[PATCH v14 11/42] virtio_ring: split: extract the logic of alloc state and extra

2022-08-01 Thread Xuan Zhuo
Separate the logic of creating desc_state, desc_extra, and subsequent
patches will call it independently.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 52 +---
 1 file changed, 36 insertions(+), 16 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 5597a9b9e518..03fc656b1f40 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -212,6 +212,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned int 
index,
   bool (*notify)(struct virtqueue 
*),
   void (*callback)(struct 
virtqueue *),
   const char *name);
+static struct vring_desc_extra *vring_alloc_desc_extra(unsigned int num);
 
 /*
  * Helpers.
@@ -937,6 +938,32 @@ static void *virtqueue_detach_unused_buf_split(struct 
virtqueue *_vq)
return NULL;
 }
 
+static int vring_alloc_state_extra_split(struct vring_virtqueue_split 
*vring_split)
+{
+   struct vring_desc_state_split *state;
+   struct vring_desc_extra *extra;
+   u32 num = vring_split->vring.num;
+
+   state = kmalloc_array(num, sizeof(struct vring_desc_state_split), 
GFP_KERNEL);
+   if (!state)
+   goto err_state;
+
+   extra = vring_alloc_desc_extra(num);
+   if (!extra)
+   goto err_extra;
+
+   memset(state, 0, num * sizeof(struct vring_desc_state_split));
+
+   vring_split->desc_state = state;
+   vring_split->desc_extra = extra;
+   return 0;
+
+err_extra:
+   kfree(state);
+err_state:
+   return -ENOMEM;
+}
+
 static void vring_free_split(struct vring_virtqueue_split *vring_split,
 struct virtio_device *vdev)
 {
@@ -2240,6 +2267,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned 
int index,
   const char *name)
 {
struct vring_virtqueue *vq;
+   int err;
 
if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
return NULL;
@@ -2285,19 +2313,17 @@ static struct virtqueue *__vring_new_virtqueue(unsigned 
int index,
vq->split.avail_flags_shadow);
}
 
-   vq->split.desc_state = kmalloc_array(vring_split->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(vring_split->vring.num);
-   if (!vq->split.desc_extra)
-   goto err_extra;
+   err = vring_alloc_state_extra_split(vring_split);
+   if (err) {
+   kfree(vq);
+   return NULL;
+   }
 
/* Put everything in free lists. */
vq->free_head = 0;
-   memset(vq->split.desc_state, 0, vring_split->vring.num *
-   sizeof(struct vring_desc_state_split));
+
+   vq->split.desc_state = vring_split->desc_state;
+   vq->split.desc_extra = vring_split->desc_extra;
 
virtqueue_init(vq, vring_split->vring.num);
 
@@ -2305,12 +2331,6 @@ static struct virtqueue *__vring_new_virtqueue(unsigned 
int index,
list_add_tail(>vq.list, >vqs);
spin_unlock(>vqs_list_lock);
return >vq;
-
-err_extra:
-   kfree(vq->split.desc_state);
-err_state:
-   kfree(vq);
-   return NULL;
 }
 
 struct virtqueue *vring_create_virtqueue(
-- 
2.31.0

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


[PATCH v14 12/42] virtio_ring: split: extract the logic of vring init

2022-08-01 Thread Xuan Zhuo
Separate the logic of initializing vring, and subsequent patches will
call it separately.

This function completes the variable initialization of split vring. It
together with the logic of atatch constitutes the initialization of
vring.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 31 +--
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 03fc656b1f40..e456cc16ea2a 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -938,6 +938,25 @@ static void *virtqueue_detach_unused_buf_split(struct 
virtqueue *_vq)
return NULL;
 }
 
+static void virtqueue_vring_init_split(struct vring_virtqueue_split 
*vring_split,
+  struct vring_virtqueue *vq)
+{
+   struct virtio_device *vdev;
+
+   vdev = vq->vq.vdev;
+
+   vring_split->avail_flags_shadow = 0;
+   vring_split->avail_idx_shadow = 0;
+
+   /* No callback?  Tell other side not to bother us. */
+   if (!vq->vq.callback) {
+   vring_split->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT;
+   if (!vq->event)
+   vring_split->vring.avail->flags = cpu_to_virtio16(vdev,
+   vring_split->avail_flags_shadow);
+   }
+}
+
 static int vring_alloc_state_extra_split(struct vring_virtqueue_split 
*vring_split)
 {
struct vring_desc_state_split *state;
@@ -2302,16 +2321,6 @@ static struct virtqueue *__vring_new_virtqueue(unsigned 
int index,
vq->split.queue_size_in_bytes = 0;
 
vq->split.vring = vring_split->vring;
-   vq->split.avail_flags_shadow = 0;
-   vq->split.avail_idx_shadow = 0;
-
-   /* No callback?  Tell other side not to bother us. */
-   if (!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);
-   }
 
err = vring_alloc_state_extra_split(vring_split);
if (err) {
@@ -2325,6 +2334,8 @@ static struct virtqueue *__vring_new_virtqueue(unsigned 
int index,
vq->split.desc_state = vring_split->desc_state;
vq->split.desc_extra = vring_split->desc_extra;
 
+   virtqueue_vring_init_split(vring_split, vq);
+
virtqueue_init(vq, vring_split->vring.num);
 
spin_lock(>vqs_list_lock);
-- 
2.31.0

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


[PATCH v14 10/42] virtio_ring: split: extract the logic of alloc queue

2022-08-01 Thread Xuan Zhuo
Separate the logic of split to create vring queue.

This feature is required for subsequent virtuqueue reset vring.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 65 ++--
 1 file changed, 40 insertions(+), 25 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 71cc7762ec51..5597a9b9e518 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -948,29 +948,19 @@ static void vring_free_split(struct vring_virtqueue_split 
*vring_split,
kfree(vring_split->desc_extra);
 }
 
-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_alloc_queue_split(struct vring_virtqueue_split *vring_split,
+  struct virtio_device *vdev,
+  u32 num,
+  unsigned int vring_align,
+  bool may_reduce_num)
 {
-   struct vring_virtqueue_split 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(>dev, "Bad virtqueue length %u\n", num);
-   return NULL;
+   return -EINVAL;
}
 
/* TODO: allocate each queue chunk individually */
@@ -981,11 +971,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! */
@@ -993,21 +983,46 @@ static struct virtqueue *vring_create_virtqueue_split(
  _addr, GFP_KERNEL|__GFP_ZERO);
}
if (!queue)
-   return NULL;
+   return -ENOMEM;
+
+   vring_init(_split->vring, num, queue, vring_align);
 
-   queue_size_in_bytes = vring_size(num, vring_align);
-   vring_init(_split.vring, num, queue, vring_align);
+   vring_split->queue_dma_addr = dma_addr;
+   vring_split->queue_size_in_bytes = vring_size(num, vring_align);
+
+   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_virtqueue_split vring_split = {};
+   struct virtqueue *vq;
+   int err;
+
+   err = vring_alloc_queue_split(_split, vdev, num, vring_align,
+ may_reduce_num);
+   if (err)
+   return NULL;
 
vq = __vring_new_virtqueue(index, _split, vdev, weak_barriers,
   context, notify, callback, name);
if (!vq) {
-   vring_free_queue(vdev, queue_size_in_bytes, queue,
-dma_addr);
+   vring_free_split(_split, vdev);
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_split.queue_dma_addr;
+   to_vvq(vq)->split.queue_size_in_bytes = vring_split.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


[PATCH v14 09/42] virtio_ring: split: introduce vring_free_split()

2022-08-01 Thread Xuan Zhuo
Free the structure struct vring_vritqueue_split.

Subsequent patches require it.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 1d51ed46b295..71cc7762ec51 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -937,6 +937,17 @@ static void *virtqueue_detach_unused_buf_split(struct 
virtqueue *_vq)
return NULL;
 }
 
+static void vring_free_split(struct vring_virtqueue_split *vring_split,
+struct virtio_device *vdev)
+{
+   vring_free_queue(vdev, vring_split->queue_size_in_bytes,
+vring_split->vring.desc,
+vring_split->queue_dma_addr);
+
+   kfree(vring_split->desc_state);
+   kfree(vring_split->desc_extra);
+}
+
 static struct virtqueue *vring_create_virtqueue_split(
unsigned int index,
unsigned int num,
-- 
2.31.0

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


[PATCH v14 08/42] virtio_ring: split: __vring_new_virtqueue() accept struct vring_virtqueue_split

2022-08-01 Thread Xuan Zhuo
__vring_new_virtqueue() instead accepts struct vring_virtqueue_split.

The purpose of this is to pass more information into
__vring_new_virtqueue() to make the code simpler and the structure
cleaner.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 29 +++--
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 8ce6cc73d814..1d51ed46b295 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -205,7 +205,7 @@ struct vring_virtqueue {
 };
 
 static struct virtqueue *__vring_new_virtqueue(unsigned int index,
-  struct vring vring,
+  struct vring_virtqueue_split 
*vring_split,
   struct virtio_device *vdev,
   bool weak_barriers,
   bool context,
@@ -949,6 +949,7 @@ static struct virtqueue *vring_create_virtqueue_split(
void (*callback)(struct virtqueue *),
const char *name)
 {
+   struct vring_virtqueue_split vring_split = {};
struct virtqueue *vq;
void *queue = NULL;
dma_addr_t dma_addr;
@@ -984,10 +985,10 @@ static struct virtqueue *vring_create_virtqueue_split(
return NULL;
 
queue_size_in_bytes = vring_size(num, vring_align);
-   vring_init(, num, queue, vring_align);
+   vring_init(_split.vring, num, queue, vring_align);
 
-   vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
-  notify, callback, name);
+   vq = __vring_new_virtqueue(index, _split, vdev, weak_barriers,
+  context, notify, callback, name);
if (!vq) {
vring_free_queue(vdev, queue_size_in_bytes, queue,
 dma_addr);
@@ -2204,7 +2205,7 @@ EXPORT_SYMBOL_GPL(vring_interrupt);
 
 /* Only available for split ring */
 static struct virtqueue *__vring_new_virtqueue(unsigned int index,
-  struct vring vring,
+  struct vring_virtqueue_split 
*vring_split,
   struct virtio_device *vdev,
   bool weak_barriers,
   bool context,
@@ -2246,7 +2247,7 @@ static struct virtqueue *__vring_new_virtqueue(unsigned 
int index,
vq->split.queue_dma_addr = 0;
vq->split.queue_size_in_bytes = 0;
 
-   vq->split.vring = vring;
+   vq->split.vring = vring_split->vring;
vq->split.avail_flags_shadow = 0;
vq->split.avail_idx_shadow = 0;
 
@@ -2258,21 +2259,21 @@ static struct virtqueue *__vring_new_virtqueue(unsigned 
int index,
vq->split.avail_flags_shadow);
}
 
-   vq->split.desc_state = kmalloc_array(vring.num,
+   vq->split.desc_state = kmalloc_array(vring_split->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(vring.num);
+   vq->split.desc_extra = vring_alloc_desc_extra(vring_split->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 *
+   memset(vq->split.desc_state, 0, vring_split->vring.num *
sizeof(struct vring_desc_state_split));
 
-   virtqueue_init(vq, vring.num);
+   virtqueue_init(vq, vring_split->vring.num);
 
spin_lock(>vqs_list_lock);
list_add_tail(>vq.list, >vqs);
@@ -2322,14 +2323,14 @@ struct virtqueue *vring_new_virtqueue(unsigned int 
index,
  void (*callback)(struct virtqueue *vq),
  const char *name)
 {
-   struct vring vring;
+   struct vring_virtqueue_split vring_split = {};
 
if (virtio_has_feature(vdev, VIRTIO_F_RING_PACKED))
return NULL;
 
-   vring_init(, num, pages, vring_align);
-   return __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
-notify, callback, name);
+   vring_init(_split.vring, num, pages, vring_align);
+   return __vring_new_virtqueue(index, _split, vdev, weak_barriers,
+context, notify, callback, name);
 }
 EXPORT_SYMBOL_GPL(vring_new_virtqueue);
 
-- 
2.31.0

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


[PATCH v14 07/42] virtio_ring: split: stop __vring_new_virtqueue as export symbol

2022-08-01 Thread Xuan Zhuo
There is currently only one place to reference __vring_new_virtqueue()
directly from the outside of virtio core. And here vring_new_virtqueue()
can be used instead.

Subsequent patches will modify __vring_new_virtqueue, so stop it as an
export symbol for now.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 25 -
 include/linux/virtio_ring.h  | 10 --
 tools/virtio/virtio_test.c   |  4 ++--
 3 files changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index a63ef2d99955..8ce6cc73d814 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -204,6 +204,14 @@ struct vring_virtqueue {
 #endif
 };
 
+static 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);
 
 /*
  * Helpers.
@@ -2195,14 +2203,14 @@ 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 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;
 
@@ -2277,7 +2285,6 @@ struct virtqueue *__vring_new_virtqueue(unsigned int 
index,
kfree(vq);
return NULL;
 }
-EXPORT_SYMBOL_GPL(__vring_new_virtqueue);
 
 struct virtqueue *vring_create_virtqueue(
unsigned int index,
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index b485b13fa50b..8b8af1a38991 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -76,16 +76,6 @@ struct virtqueue *vring_create_virtqueue(unsigned int index,
 void (*callback)(struct virtqueue *vq),
 const char *name);
 
-/* Creates a virtqueue with a custom layout. */
-struct virtqueue *__vring_new_virtqueue(unsigned int index,
-   struct vring vring,
-   struct virtio_device *vdev,
-   bool weak_barriers,
-   bool ctx,
-   bool (*notify)(struct virtqueue *),
-   void (*callback)(struct virtqueue *),
-   const char *name);
-
 /*
  * Creates a virtqueue with a standard layout but a caller-allocated
  * ring.
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c
index 23f142af544a..86a410ddcedd 100644
--- a/tools/virtio/virtio_test.c
+++ b/tools/virtio/virtio_test.c
@@ -102,8 +102,8 @@ static void vq_reset(struct vq_info *info, int num, struct 
virtio_device *vdev)
 
memset(info->ring, 0, vring_size(num, 4096));
vring_init(>vring, num, info->ring, 4096);
-   info->vq = __vring_new_virtqueue(info->idx, info->vring, vdev, true,
-false, vq_notify, vq_callback, "test");
+   info->vq = vring_new_virtqueue(info->idx, num, 4096, vdev, true, false,
+  info->ring, vq_notify, vq_callback, 
"test");
assert(info->vq);
info->vq->priv = info;
 }
-- 
2.31.0

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


[PATCH v14 06/42] virtio_ring: introduce virtqueue_init()

2022-08-01 Thread Xuan Zhuo
Separate the logic of virtqueue initialization. These variables should
be reset during reset.

This logic can be called independently when implementing resize/reset
later.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 38 +---
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 1bc5794e9739..a63ef2d99955 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -368,6 +368,24 @@ static int vring_mapping_error(const struct 
vring_virtqueue *vq,
return dma_mapping_error(vring_dma_dev(vq), addr);
 }
 
+static void virtqueue_init(struct vring_virtqueue *vq, u32 num)
+{
+   vq->vq.num_free = num;
+
+   if (vq->packed_ring)
+   vq->last_used_idx = 0 | (1 << VRING_PACKED_EVENT_F_WRAP_CTR);
+   else
+   vq->last_used_idx = 0;
+
+   vq->event_triggered = false;
+   vq->num_added = 0;
+
+#ifdef DEBUG
+   vq->in_use = false;
+   vq->last_add_time_valid = false;
+#endif
+}
+
 
 /*
  * Split ring specific functions - *_split().
@@ -1706,7 +1724,6 @@ static struct virtqueue *vring_create_virtqueue_packed(
vq->vq.callback = callback;
vq->vq.vdev = vdev;
vq->vq.name = name;
-   vq->vq.num_free = num;
vq->vq.index = index;
vq->we_own_ring = true;
vq->notify = notify;
@@ -1716,15 +1733,8 @@ static struct virtqueue *vring_create_virtqueue_packed(
 #else
vq->broken = false;
 #endif
-   vq->last_used_idx = 0 | (1 << VRING_PACKED_EVENT_F_WRAP_CTR);
-   vq->event_triggered = false;
-   vq->num_added = 0;
vq->packed_ring = true;
vq->use_dma_api = vring_use_dma_api(vdev);
-#ifdef DEBUG
-   vq->in_use = false;
-   vq->last_add_time_valid = false;
-#endif
 
vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
!context;
@@ -1773,6 +1783,8 @@ static struct virtqueue *vring_create_virtqueue_packed(
cpu_to_le16(vq->packed.event_flags_shadow);
}
 
+   virtqueue_init(vq, num);
+
spin_lock(>vqs_list_lock);
list_add_tail(>vq.list, >vqs);
spin_unlock(>vqs_list_lock);
@@ -2205,7 +2217,6 @@ struct virtqueue *__vring_new_virtqueue(unsigned int 
index,
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;
@@ -2215,14 +2226,7 @@ struct virtqueue *__vring_new_virtqueue(unsigned int 
index,
 #else
vq->broken = false;
 #endif
-   vq->last_used_idx = 0;
-   vq->event_triggered = false;
-   vq->num_added = 0;
vq->use_dma_api = vring_use_dma_api(vdev);
-#ifdef DEBUG
-   vq->in_use = false;
-   vq->last_add_time_valid = false;
-#endif
 
vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
!context;
@@ -2260,6 +2264,8 @@ struct virtqueue *__vring_new_virtqueue(unsigned int 
index,
memset(vq->split.desc_state, 0, vring.num *
sizeof(struct vring_desc_state_split));
 
+   virtqueue_init(vq, vring.num);
+
spin_lock(>vqs_list_lock);
list_add_tail(>vq.list, >vqs);
spin_unlock(>vqs_list_lock);
-- 
2.31.0

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


[PATCH v14 05/42] virtio_ring: split vring_virtqueue

2022-08-01 Thread Xuan Zhuo
Separate the two inline structures(split and packed) from the structure
vring_virtqueue.

In this way, we can use these two structures later to pass parameters
and retain temporary variables.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 116 ++-
 1 file changed, 60 insertions(+), 56 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index a3d76fd87983..1bc5794e9739 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -85,6 +85,64 @@ struct vring_desc_extra {
u16 next;   /* The next desc state in a list. */
 };
 
+struct vring_virtqueue_split {
+   /* Actual memory layout for this queue. */
+   struct vring vring;
+
+   /* Last written value to avail->flags */
+   u16 avail_flags_shadow;
+
+   /*
+* Last written value to avail->idx in
+* guest byte order.
+*/
+   u16 avail_idx_shadow;
+
+   /* Per-descriptor state. */
+   struct vring_desc_state_split *desc_state;
+   struct vring_desc_extra *desc_extra;
+
+   /* DMA address and size information */
+   dma_addr_t queue_dma_addr;
+   size_t queue_size_in_bytes;
+};
+
+struct vring_virtqueue_packed {
+   /* Actual memory layout for this queue. */
+   struct {
+   unsigned int num;
+   struct vring_packed_desc *desc;
+   struct vring_packed_desc_event *driver;
+   struct vring_packed_desc_event *device;
+   } vring;
+
+   /* Driver ring wrap counter. */
+   bool avail_wrap_counter;
+
+   /* Avail used flags. */
+   u16 avail_used_flags;
+
+   /* Index of the next avail descriptor. */
+   u16 next_avail_idx;
+
+   /*
+* Last written value to driver->flags in
+* guest byte order.
+*/
+   u16 event_flags_shadow;
+
+   /* Per-descriptor state. */
+   struct vring_desc_state_packed *desc_state;
+   struct vring_desc_extra *desc_extra;
+
+   /* DMA address and size information */
+   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;
 
@@ -124,64 +182,10 @@ struct vring_virtqueue {
 
union {
/* Available for split ring */
-   struct {
-   /* Actual memory layout for this queue. */
-   struct vring vring;
-
-   /* Last written value to avail->flags */
-   u16 avail_flags_shadow;
-
-   /*
-* Last written value to avail->idx in
-* guest byte order.
-*/
-   u16 avail_idx_shadow;
-
-   /* Per-descriptor state. */
-   struct vring_desc_state_split *desc_state;
-   struct vring_desc_extra *desc_extra;
-
-   /* DMA address and size information */
-   dma_addr_t queue_dma_addr;
-   size_t queue_size_in_bytes;
-   } split;
+   struct vring_virtqueue_split split;
 
/* Available for packed ring */
-   struct {
-   /* Actual memory layout for this queue. */
-   struct {
-   unsigned int num;
-   struct vring_packed_desc *desc;
-   struct vring_packed_desc_event *driver;
-   struct vring_packed_desc_event *device;
-   } vring;
-
-   /* Driver ring wrap counter. */
-   bool avail_wrap_counter;
-
-   /* Avail used flags. */
-   u16 avail_used_flags;
-
-   /* Index of the next avail descriptor. */
-   u16 next_avail_idx;
-
-   /*
-* Last written value to driver->flags in
-* guest byte order.
-*/
-   u16 event_flags_shadow;
-
-   /* Per-descriptor state. */
-   struct vring_desc_state_packed *desc_state;
-   struct vring_desc_extra *desc_extra;
-
-   /* DMA address and size information */
-   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;
-   } packed;
+   struct vring_virtqueue_packed packed;
};
 
/* How to 

[PATCH v14 04/42] virtio_ring: extract the logic of freeing vring

2022-08-01 Thread Xuan Zhuo
Introduce vring_free() to free the vring of vq.

Subsequent patches will use vring_free() alone.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 drivers/virtio/virtio_ring.c | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 17024389b62c..a3d76fd87983 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2316,14 +2316,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.vdev->vqs_list_lock);
-   list_del(&_vq->list);
-   spin_unlock(>vq.vdev->vqs_list_lock);
-
if (vq->we_own_ring) {
if (vq->packed_ring) {
vring_free_queue(vq->vq.vdev,
@@ -2354,6 +2350,18 @@ void vring_del_virtqueue(struct virtqueue *_vq)
kfree(vq->split.desc_state);
kfree(vq->split.desc_extra);
}
+}
+
+void vring_del_virtqueue(struct virtqueue *_vq)
+{
+   struct vring_virtqueue *vq = to_vvq(_vq);
+
+   spin_lock(>vq.vdev->vqs_list_lock);
+   list_del(&_vq->list);
+   spin_unlock(>vq.vdev->vqs_list_lock);
+
+   vring_free(_vq);
+
kfree(vq);
 }
 EXPORT_SYMBOL_GPL(vring_del_virtqueue);
-- 
2.31.0

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


[PATCH v14 03/42] virtio_ring: update the document of the virtqueue_detach_unused_buf for queue reset

2022-08-01 Thread Xuan Zhuo
Added documentation for virtqueue_detach_unused_buf, allowing it to be
called on queue reset.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 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 a5ec724c01d8..17024389b62c 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2130,8 +2130,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


[PATCH v14 01/42] virtio: record the maximum queue num supported by the device.

2022-08-01 Thread Xuan Zhuo
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 
Acked-by: Jason Wang 
---
 arch/um/drivers/virtio_uml.c | 1 +
 drivers/platform/mellanox/mlxbf-tmfifo.c | 2 ++
 drivers/remoteproc/remoteproc_virtio.c   | 2 ++
 drivers/s390/virtio/virtio_ccw.c | 3 +++
 drivers/virtio/virtio_mmio.c | 2 ++
 drivers/virtio/virtio_pci_legacy.c   | 2 ++
 drivers/virtio/virtio_pci_modern.c   | 2 ++
 drivers/virtio/virtio_vdpa.c | 2 ++
 include/linux/virtio.h   | 2 ++
 9 files changed, 18 insertions(+)

diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
index 82ff3785bf69..e719af8bdf56 100644
--- a/arch/um/drivers/virtio_uml.c
+++ b/arch/um/drivers/virtio_uml.c
@@ -958,6 +958,7 @@ static struct virtqueue *vu_setup_vq(struct virtio_device 
*vdev,
goto error_create;
}
vq->priv = info;
+   vq->num_max = num;
num = virtqueue_get_vring_size(vq);
 
if (vu_dev->protocol_features &
diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c 
b/drivers/platform/mellanox/mlxbf-tmfifo.c
index 38800e86ed8a..1ae3c56b66b0 100644
--- a/drivers/platform/mellanox/mlxbf-tmfifo.c
+++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
@@ -959,6 +959,8 @@ static int mlxbf_tmfifo_virtio_find_vqs(struct 
virtio_device *vdev,
goto error;
}
 
+   vq->num_max = vring->num;
+
vqs[i] = vq;
vring->vq = vq;
vq->priv = vring;
diff --git a/drivers/remoteproc/remoteproc_virtio.c 
b/drivers/remoteproc/remoteproc_virtio.c
index d43d74733f0a..0f7706e23eb9 100644
--- a/drivers/remoteproc/remoteproc_virtio.c
+++ b/drivers/remoteproc/remoteproc_virtio.c
@@ -125,6 +125,8 @@ static struct virtqueue *rp_find_vq(struct virtio_device 
*vdev,
return ERR_PTR(-ENOMEM);
}
 
+   vq->num_max = num;
+
rvring->vq = vq;
vq->priv = rvring;
 
diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
index 161d3b141f0d..6b86d0280d6b 100644
--- a/drivers/s390/virtio/virtio_ccw.c
+++ b/drivers/s390/virtio/virtio_ccw.c
@@ -530,6 +530,9 @@ static struct virtqueue *virtio_ccw_setup_vq(struct 
virtio_device *vdev,
err = -ENOMEM;
goto out_err;
}
+
+   vq->num_max = info->num;
+
/* it may have been reduced */
info->num = virtqueue_get_vring_size(vq);
 
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 083ff1eb743d..a20d5a6b5819 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -403,6 +403,8 @@ static struct virtqueue *vm_setup_vq(struct virtio_device 
*vdev, unsigned int in
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 a5e5721145c7..2257f1b3d8ae 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(_dev->pci_dev->dev,
diff --git a/drivers/virtio/virtio_pci_modern.c 
b/drivers/virtio/virtio_pci_modern.c
index 623906b4996c..e7e0b8c850f6 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_vdpa.c b/drivers/virtio/virtio_vdpa.c
index c40f7deb6b5a..9670cc79371d 100644
--- a/drivers/virtio/virtio_vdpa.c
+++ b/drivers/virtio/virtio_vdpa.c
@@ -183,6 +183,8 @@ virtio_vdpa_setup_vq(struct virtio_device *vdev, unsigned 
int index,
goto error_new_virtqueue;
}
 
+   vq->num_max = max_num;
+
/* Setup virtqueue callback */
cb.callback = callback ? virtio_vdpa_virtqueue_cb : NULL;
cb.private = info;
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index d8fdf170637c..129bde7521e3 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -19,6 +19,7 @@
  * @priv: a pointer for the virtqueue 

[PATCH v14 02/42] virtio: struct virtio_config_ops add callbacks for queue_reset

2022-08-01 Thread Xuan Zhuo
reset can be divided into the following four steps (example):
 1. transport: notify the device to reset the queue
 2. vring: recycle the buffer submitted
 3. vring: reset/resize the vring (may re-alloc)
 4. transport: mmap vring to device, and enable the queue

In order to support queue reset, add two callbacks in struct
virtio_config_ops to implement steps 1 and 4.

Signed-off-by: Xuan Zhuo 
Acked-by: Jason Wang 
---
 include/linux/virtio_config.h | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
index b47c2e7ed0ee..36ec7be1f480 100644
--- a/include/linux/virtio_config.h
+++ b/include/linux/virtio_config.h
@@ -78,6 +78,18 @@ 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.
+ * @disable_vq_and_reset: reset a queue individually (optional).
+ * vq: the virtqueue
+ * Returns 0 on success or error status
+ * disable_vq_and_reset will guarantee that the callbacks are disabled and
+ * synchronized.
+ * Except for the callback, the caller should guarantee that the vring is
+ * not accessed by any functions of virtqueue.
+ * @enable_vq_after_reset: enable a reset queue
+ * vq: the virtqueue
+ * Returns 0 on success or error status
+ * If disable_vq_and_reset is set, then enable_vq_after_reset must also be
+ * set.
  */
 typedef void vq_callback_t(struct virtqueue *);
 struct virtio_config_ops {
@@ -104,6 +116,8 @@ struct virtio_config_ops {
int index);
bool (*get_shm_region)(struct virtio_device *vdev,
   struct virtio_shm_region *region, u8 id);
+   int (*disable_vq_and_reset)(struct virtqueue *vq);
+   int (*enable_vq_after_reset)(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


[PATCH v14 00/42] virtio pci support VIRTIO_F_RING_RESET

2022-08-01 Thread 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
https://github.com/oasis-tcs/virtio-spec/issues/139

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

This patch set implements the refactoring of vring. Finally, the
virtuque_resize() interface is provided based on the reset function of the
transport layer.

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.

Qemu code:

https://github.com/fengidri/qemu/compare/89f3bfa3265554d1d591ee4d7f1197b6e3397e84...master

In order to simplify the review of this patch set, the function of reusing
the old buffers after resize will be introduced in subsequent patch sets.

Please review. Thanks.

v14:
  1. remove unnecessary memset from virtqueue_reinit_{split,packed}
  2. move free_head = 0 into virtqueue_vring_attach_{split,packed}

v13:
  1. virtqueue attached by vq->split = *vring_split / vq->packed = *vring_packed
  2. call __virtqueue_break() unconditionally

v12:
  1. access vq->num_max directly without helper
  2. rename the vq reset callbacks:
 int (*disable_vq_and_reset)(struct virtqueue *vq);
 int (*enable_vq_after_reset)(struct virtqueue *vq);

  3. rename vring to vring_split, vring_packed
  4. protect sq->reset by tx lock

v11:
  1. struct virtio_pci_common_cfg to virtio_pci_modern.h
  2. conflict resolution

v10:
  1. on top of the harden vring IRQ
  2. factor out split and packed from struct vring_virtqueue
  3. some suggest from @Jason Wang

v9:
  1. Provide a virtqueue_resize() interface directly
  2. A patch set including vring resize, virtio pci reset, virtio-net resize
  3. No more separate structs

v8:
  1. Provide a virtqueue_reset() interface directly
  2. Split the two patch sets, this is the first part
  3. Add independent allocation helper for allocating state, extra

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

Xuan Zhuo (42):
  virtio: record the maximum queue num supported by the device.
  virtio: struct virtio_config_ops add callbacks for queue_reset
  virtio_ring: update the document of the virtqueue_detach_unused_buf
for queue reset
  virtio_ring: extract the logic of freeing vring
  virtio_ring: split vring_virtqueue
  virtio_ring: introduce virtqueue_init()
  virtio_ring: split: stop __vring_new_virtqueue as export symbol
  virtio_ring: split: __vring_new_virtqueue() accept struct
vring_virtqueue_split
  virtio_ring: split: introduce vring_free_split()
  virtio_ring: split: extract the logic of alloc queue
  virtio_ring: split: extract the logic of alloc state and extra
  virtio_ring: split: extract the logic of vring init
  virtio_ring: split: extract the logic of attach vring
  virtio_ring: split: introduce virtqueue_reinit_split()
  virtio_ring: split: reserve vring_align, may_reduce_num
  virtio_ring: split: introduce virtqueue_resize_split()
  virtio_ring: packed: introduce vring_free_packed
  virtio_ring: packed: extract the logic of alloc queue
  virtio_ring: packed: extract the logic of alloc state and extra
  virtio_ring: packed: extract the logic of vring init
  virtio_ring: packed: extract the logic of attach vring
  virtio_ring: packed: introduce virtqueue_reinit_packed()
  virtio_ring: packed: introduce virtqueue_resize_packed()
  virtio_ring: introduce virtqueue_resize()
  virtio_pci: struct virtio_pci_common_cfg add queue_notify_data
  virtio: allow to unbreak/break virtqueue individually
  virtio: queue_reset: add VIRTIO_F_RING_RESET
  virtio_ring: struct virtqueue introduce reset
  virtio_pci: struct virtio_pci_common_cfg add queue_reset
  virtio_pci: introduce helper to get/set queue reset
  virtio_pci: extract the logic of active vq for modern pci
  virtio_pci: support VIRTIO_F_RING_RESET
  virtio: find_vqs() 

Re: [PATCH v13 16/42] virtio_ring: split: introduce virtqueue_resize_split()

2022-08-01 Thread Jason Wang
On Mon, Aug 1, 2022 at 2:13 PM Xuan Zhuo  wrote:
>
> On Mon, 1 Aug 2022 12:49:12 +0800, Jason Wang  wrote:
> > On Thu, Jul 28, 2022 at 7:27 PM Xuan Zhuo  
> > wrote:
> > >
> > > On Thu, 28 Jul 2022 17:04:36 +0800, Jason Wang  
> > > wrote:
> > > > On Thu, Jul 28, 2022 at 4:18 PM Xuan Zhuo  
> > > > wrote:
> > > > >
> > > > > On Thu, 28 Jul 2022 15:42:50 +0800, Jason Wang  
> > > > > wrote:
> > > > > > On Thu, Jul 28, 2022 at 3:24 PM Xuan Zhuo 
> > > > > >  wrote:
> > > > > > >
> > > > > > > On Thu, 28 Jul 2022 10:38:51 +0800, Jason Wang 
> > > > > > >  wrote:
> > > > > > > > On Wed, Jul 27, 2022 at 3:44 PM Xuan Zhuo 
> > > > > > > >  wrote:
> > > > > > > > >
> > > > > > > > > On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang 
> > > > > > > > >  wrote:
> > > > > > > > > >
> > > > > > > > > > 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > > > > > > > > > > virtio ring split supports resize.
> > > > > > > > > > >
> > > > > > > > > > > Only after the new vring is successfully allocated based 
> > > > > > > > > > > on the new num,
> > > > > > > > > > > we will release the old vring. In any case, an error is 
> > > > > > > > > > > returned,
> > > > > > > > > > > indicating that the vring still points to the old vring.
> > > > > > > > > > >
> > > > > > > > > > > In the case of an error, 
> > > > > > > > > > > re-initialize(virtqueue_reinit_split()) the
> > > > > > > > > > > virtqueue to ensure that the vring can be used.
> > > > > > > > > > >
> > > > > > > > > > > Signed-off-by: Xuan Zhuo 
> > > > > > > > > > > Acked-by: Jason Wang 
> > > > > > > > > > > ---
> > > > > > > > > > >   drivers/virtio/virtio_ring.c | 34 
> > > > > > > > > > > ++
> > > > > > > > > > >   1 file changed, 34 insertions(+)
> > > > > > > > > > >
> > > > > > > > > > > diff --git a/drivers/virtio/virtio_ring.c 
> > > > > > > > > > > b/drivers/virtio/virtio_ring.c
> > > > > > > > > > > index b6fda91c8059..58355e1ac7d7 100644
> > > > > > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > > > > > @@ -220,6 +220,7 @@ static struct virtqueue 
> > > > > > > > > > > *__vring_new_virtqueue(unsigned int index,
> > > > > > > > > > >void 
> > > > > > > > > > > (*callback)(struct virtqueue *),
> > > > > > > > > > >const char 
> > > > > > > > > > > *name);
> > > > > > > > > > >   static struct vring_desc_extra 
> > > > > > > > > > > *vring_alloc_desc_extra(unsigned int num);
> > > > > > > > > > > +static void vring_free(struct virtqueue *_vq);
> > > > > > > > > > >
> > > > > > > > > > >   /*
> > > > > > > > > > >* Helpers.
> > > > > > > > > > > @@ -1117,6 +1118,39 @@ static struct virtqueue 
> > > > > > > > > > > *vring_create_virtqueue_split(
> > > > > > > > > > > return vq;
> > > > > > > > > > >   }
> > > > > > > > > > >
> > > > > > > > > > > +static int virtqueue_resize_split(struct virtqueue *_vq, 
> > > > > > > > > > > u32 num)
> > > > > > > > > > > +{
> > > > > > > > > > > +   struct vring_virtqueue_split vring_split = {};
> > > > > > > > > > > +   struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > > > > > +   struct virtio_device *vdev = _vq->vdev;
> > > > > > > > > > > +   int err;
> > > > > > > > > > > +
> > > > > > > > > > > +   err = vring_alloc_queue_split(_split, vdev, num,
> > > > > > > > > > > + vq->split.vring_align,
> > > > > > > > > > > + 
> > > > > > > > > > > vq->split.may_reduce_num);
> > > > > > > > > > > +   if (err)
> > > > > > > > > > > +   goto err;
> > > > > > > > > >
> > > > > > > > > >
> > > > > > > > > > I think we don't need to do anything here?
> > > > > > > > >
> > > > > > > > > Am I missing something?
> > > > > > > >
> > > > > > > > I meant it looks to me most of the virtqueue_reinit() is 
> > > > > > > > unnecessary.
> > > > > > > > We probably only need to reinit avail/used idx there.
> > > > > > >
> > > > > > >
> > > > > > > In this function, we can indeed remove some code.
> > > > > > >
> > > > > > > >   static void virtqueue_reinit_split(struct vring_virtqueue 
> > > > > > > > *vq)
> > > > > > > >   {
> > > > > > > >   int size, i;
> > > > > > > >
> > > > > > > >   memset(vq->split.vring.desc, 0, 
> > > > > > > > vq->split.queue_size_in_bytes);
> > > > > > > >
> > > > > > > >   size = sizeof(struct vring_desc_state_split) * 
> > > > > > > > vq->split.vring.num;
> > > > > > > >   memset(vq->split.desc_state, 0, size);
> > > > > > > >
> > > > > > > >   size = sizeof(struct vring_desc_extra) * 
> > > > > > > > vq->split.vring.num;
> > > > > > > >   memset(vq->split.desc_extra, 0, size);
> > > > > > >
> > > > > > > These memsets can be removed, and theoretically it will not cause 
> > > > > > > any
> > > > > > > exceptions.
> > > > > >
> > > > > > Yes, otherwise we have bugs in 

Re: [PATCH V3 6/6] vDPA: fix 'cast to restricted le16' warnings in vdpa.c

2022-08-01 Thread Michael S. Tsirkin
On Mon, Aug 01, 2022 at 12:33:44PM +0800, Jason Wang wrote:
> 
> 在 2022/7/29 17:39, Michael S. Tsirkin 写道:
> > On Fri, Jul 29, 2022 at 05:35:09PM +0800, Zhu, Lingshan wrote:
> > > 
> > > On 7/29/2022 5:23 PM, Michael S. Tsirkin wrote:
> > > > On Fri, Jul 29, 2022 at 05:20:17PM +0800, Zhu, Lingshan wrote:
> > > > > On 7/29/2022 5:17 PM, Michael S. Tsirkin wrote:
> > > > > > On Fri, Jul 29, 2022 at 05:07:11PM +0800, Zhu, Lingshan wrote:
> > > > > > > On 7/29/2022 4:53 PM, Michael S. Tsirkin wrote:
> > > > > > > > On Fri, Jul 01, 2022 at 09:28:26PM +0800, Zhu Lingshan wrote:
> > > > > > > > > This commit fixes spars warnings: cast to restricted __le16
> > > > > > > > > in function vdpa_dev_net_config_fill() and
> > > > > > > > > vdpa_fill_stats_rec()
> > > > > > > > > 
> > > > > > > > > Signed-off-by: Zhu Lingshan 
> > > > > > > > > ---
> > > > > > > > >  drivers/vdpa/vdpa.c | 6 +++---
> > > > > > > > >  1 file changed, 3 insertions(+), 3 deletions(-)
> > > > > > > > > 
> > > > > > > > > diff --git a/drivers/vdpa/vdpa.c b/drivers/vdpa/vdpa.c
> > > > > > > > > index 846dd37f3549..ed49fe46a79e 100644
> > > > > > > > > --- a/drivers/vdpa/vdpa.c
> > > > > > > > > +++ b/drivers/vdpa/vdpa.c
> > > > > > > > > @@ -825,11 +825,11 @@ static int 
> > > > > > > > > vdpa_dev_net_config_fill(struct vdpa_device *vdev, struct 
> > > > > > > > > sk_buff *ms
> > > > > > > > >   config.mac))
> > > > > > > > >   return -EMSGSIZE;
> > > > > > > > > - val_u16 = le16_to_cpu(config.status);
> > > > > > > > > + val_u16 = __virtio16_to_cpu(true, config.status);
> > > > > > > > >   if (nla_put_u16(msg, VDPA_ATTR_DEV_NET_STATUS, val_u16))
> > > > > > > > >   return -EMSGSIZE;
> > > > > > > > > - val_u16 = le16_to_cpu(config.mtu);
> > > > > > > > > + val_u16 = __virtio16_to_cpu(true, config.mtu);
> > > > > > > > >   if (nla_put_u16(msg, VDPA_ATTR_DEV_NET_CFG_MTU, 
> > > > > > > > > val_u16))
> > > > > > > > >   return -EMSGSIZE;
> > > > > > > > Wrong on BE platforms with legacy interface, isn't it?
> > > > > > > > We generally don't handle legacy properly in VDPA so it's
> > > > > > > > not a huge deal, but maybe add a comment at least?
> > > > > > > Sure, I can add a comment here: this is for modern devices only.
> > > > > > > 
> > > > > > > Thanks,
> > > > > > > Zhu Lingshan
> > > > > > Hmm. what "this" is for modern devices only here?
> > > > > this cast, for LE modern devices.
> > > > I think status existed in legacy for sure, and it's possible that
> > > > some legacy devices backported mtu and max_virtqueue_pairs otherwise
> > > > we would have these fields as __le not as __virtio, right?
> > > yes, that's the reason why it is virtio_16 than just le16.
> > > 
> > > I may find a better solution to detect whether it is LE, or BE without a
> > > virtio_dev structure.
> > > Check whether vdpa_device->get_device_features() has VIRTIO_F_VERISON_1. 
> > > If
> > > the device offers _F_VERSION_1, then it is a LE device,
> > > or it is a BE device, then we use __virtio16_to_cpu(false, config.status).
> > > 
> > > Does this look good?
> > No since the question is can be a legacy driver with a transitional
> > device.  I don't have a good idea yet. vhost has VHOST_SET_VRING_ENDIAN
> > and maybe we need something like this for config as well?
> 
> 
> Not sure, and even if we had this, the query could happen before
> VHOST_SET_VRING_ENDIAN.
> 
> Actually, the patch should be fine itself, since the issue exist even before
> the patch (which assumes a le).
> 
> Thanks


I agree, let's just add a TODO comment.

> 
> > 
> > > > > > > > > @@ -911,7 +911,7 @@ static int vdpa_fill_stats_rec(struct 
> > > > > > > > > vdpa_device *vdev, struct sk_buff *msg,
> > > > > > > > >   }
> > > > > > > > >   vdpa_get_config_unlocked(vdev, 0, , 
> > > > > > > > > sizeof(config));
> > > > > > > > > - max_vqp = le16_to_cpu(config.max_virtqueue_pairs);
> > > > > > > > > + max_vqp = __virtio16_to_cpu(true, 
> > > > > > > > > config.max_virtqueue_pairs);
> > > > > > > > >   if (nla_put_u16(msg, VDPA_ATTR_DEV_NET_CFG_MAX_VQP, 
> > > > > > > > > max_vqp))
> > > > > > > > >   return -EMSGSIZE;
> > > > > > > > > -- 
> > > > > > > > > 2.31.1

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

Re: [PATCH v13 16/42] virtio_ring: split: introduce virtqueue_resize_split()

2022-08-01 Thread Xuan Zhuo
On Mon, 1 Aug 2022 12:49:12 +0800, Jason Wang  wrote:
> On Thu, Jul 28, 2022 at 7:27 PM Xuan Zhuo  wrote:
> >
> > On Thu, 28 Jul 2022 17:04:36 +0800, Jason Wang  wrote:
> > > On Thu, Jul 28, 2022 at 4:18 PM Xuan Zhuo  
> > > wrote:
> > > >
> > > > On Thu, 28 Jul 2022 15:42:50 +0800, Jason Wang  
> > > > wrote:
> > > > > On Thu, Jul 28, 2022 at 3:24 PM Xuan Zhuo 
> > > > >  wrote:
> > > > > >
> > > > > > On Thu, 28 Jul 2022 10:38:51 +0800, Jason Wang 
> > > > > >  wrote:
> > > > > > > On Wed, Jul 27, 2022 at 3:44 PM Xuan Zhuo 
> > > > > > >  wrote:
> > > > > > > >
> > > > > > > > On Wed, 27 Jul 2022 11:12:19 +0800, Jason Wang 
> > > > > > > >  wrote:
> > > > > > > > >
> > > > > > > > > 在 2022/7/26 15:21, Xuan Zhuo 写道:
> > > > > > > > > > virtio ring split supports resize.
> > > > > > > > > >
> > > > > > > > > > Only after the new vring is successfully allocated based on 
> > > > > > > > > > the new num,
> > > > > > > > > > we will release the old vring. In any case, an error is 
> > > > > > > > > > returned,
> > > > > > > > > > indicating that the vring still points to the old vring.
> > > > > > > > > >
> > > > > > > > > > In the case of an error, 
> > > > > > > > > > re-initialize(virtqueue_reinit_split()) the
> > > > > > > > > > virtqueue to ensure that the vring can be used.
> > > > > > > > > >
> > > > > > > > > > Signed-off-by: Xuan Zhuo 
> > > > > > > > > > Acked-by: Jason Wang 
> > > > > > > > > > ---
> > > > > > > > > >   drivers/virtio/virtio_ring.c | 34 
> > > > > > > > > > ++
> > > > > > > > > >   1 file changed, 34 insertions(+)
> > > > > > > > > >
> > > > > > > > > > diff --git a/drivers/virtio/virtio_ring.c 
> > > > > > > > > > b/drivers/virtio/virtio_ring.c
> > > > > > > > > > index b6fda91c8059..58355e1ac7d7 100644
> > > > > > > > > > --- a/drivers/virtio/virtio_ring.c
> > > > > > > > > > +++ b/drivers/virtio/virtio_ring.c
> > > > > > > > > > @@ -220,6 +220,7 @@ static struct virtqueue 
> > > > > > > > > > *__vring_new_virtqueue(unsigned int index,
> > > > > > > > > >void 
> > > > > > > > > > (*callback)(struct virtqueue *),
> > > > > > > > > >const char 
> > > > > > > > > > *name);
> > > > > > > > > >   static struct vring_desc_extra 
> > > > > > > > > > *vring_alloc_desc_extra(unsigned int num);
> > > > > > > > > > +static void vring_free(struct virtqueue *_vq);
> > > > > > > > > >
> > > > > > > > > >   /*
> > > > > > > > > >* Helpers.
> > > > > > > > > > @@ -1117,6 +1118,39 @@ static struct virtqueue 
> > > > > > > > > > *vring_create_virtqueue_split(
> > > > > > > > > > return vq;
> > > > > > > > > >   }
> > > > > > > > > >
> > > > > > > > > > +static int virtqueue_resize_split(struct virtqueue *_vq, 
> > > > > > > > > > u32 num)
> > > > > > > > > > +{
> > > > > > > > > > +   struct vring_virtqueue_split vring_split = {};
> > > > > > > > > > +   struct vring_virtqueue *vq = to_vvq(_vq);
> > > > > > > > > > +   struct virtio_device *vdev = _vq->vdev;
> > > > > > > > > > +   int err;
> > > > > > > > > > +
> > > > > > > > > > +   err = vring_alloc_queue_split(_split, vdev, num,
> > > > > > > > > > + vq->split.vring_align,
> > > > > > > > > > + vq->split.may_reduce_num);
> > > > > > > > > > +   if (err)
> > > > > > > > > > +   goto err;
> > > > > > > > >
> > > > > > > > >
> > > > > > > > > I think we don't need to do anything here?
> > > > > > > >
> > > > > > > > Am I missing something?
> > > > > > >
> > > > > > > I meant it looks to me most of the virtqueue_reinit() is 
> > > > > > > unnecessary.
> > > > > > > We probably only need to reinit avail/used idx there.
> > > > > >
> > > > > >
> > > > > > In this function, we can indeed remove some code.
> > > > > >
> > > > > > >   static void virtqueue_reinit_split(struct vring_virtqueue 
> > > > > > > *vq)
> > > > > > >   {
> > > > > > >   int size, i;
> > > > > > >
> > > > > > >   memset(vq->split.vring.desc, 0, 
> > > > > > > vq->split.queue_size_in_bytes);
> > > > > > >
> > > > > > >   size = sizeof(struct vring_desc_state_split) * 
> > > > > > > vq->split.vring.num;
> > > > > > >   memset(vq->split.desc_state, 0, size);
> > > > > > >
> > > > > > >   size = sizeof(struct vring_desc_extra) * 
> > > > > > > vq->split.vring.num;
> > > > > > >   memset(vq->split.desc_extra, 0, size);
> > > > > >
> > > > > > These memsets can be removed, and theoretically it will not cause 
> > > > > > any
> > > > > > exceptions.
> > > > >
> > > > > Yes, otherwise we have bugs in detach_buf().
> > > > >
> > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >   for (i = 0; i < vq->split.vring.num - 1; i++)
> > > > > > >   vq->split.desc_extra[i].next = i + 1;
> > > > > >
> > > > > > This can also be removed, but we need to record free_head that