diff mbox series

[v2,1/2] drm/virtio: Defer the host dumb buffer creation

Message ID 20240903075414.297622-1-jfalempe@redhat.com (mailing list archive)
State New, archived
Headers show
Series [v2,1/2] drm/virtio: Defer the host dumb buffer creation | expand

Commit Message

Jocelyn Falempe Sept. 3, 2024, 7:48 a.m. UTC
The host dumb buffer command needs a format, but the
DRM_IOCTL_MODE_CREATE_DUMB only provides a buffer size.
So wait for the DRM_IOCTL_MODE_ADDFB(2), to get the format, and create
the host resources at this time.

This will allow virtio-gpu to support multiple pixel formats.

This problem was noticed in commit 42fd9e6c29b39 ("drm/virtio: fix
DRM_FORMAT_* handling")

Suggested-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
---

v2:
 * Move virtio_gpu_object deferred field to its own block (Geerd Hoffmann)
 * Check that the size of the dumb buffer can hold the framebuffer (Geerd Hoffmann)

 drivers/gpu/drm/virtio/virtgpu_display.c | 33 ++++++++++++++++++++++++
 drivers/gpu/drm/virtio/virtgpu_drv.h     |  5 ++++
 drivers/gpu/drm/virtio/virtgpu_gem.c     |  1 -
 drivers/gpu/drm/virtio/virtgpu_object.c  | 13 +++++++---
 4 files changed, 47 insertions(+), 5 deletions(-)


base-commit: 9345e3aab7fef06b8908308634974ea32a29e276

Comments

Gerd Hoffmann Sept. 4, 2024, 7:10 a.m. UTC | #1
Hi,

> -	} else {
> -		virtio_gpu_cmd_create_resource(vgdev, bo, params,
> -					       objs, fence);
> -		virtio_gpu_object_attach(vgdev, bo, ents, nents);
> +	} else if (params->dumb) {
> +		/* Create the host resource in virtio_gpu_user_framebuffer_create()
> +		 * because the pixel format is not specified yet
> +		 */
> +		bo->ents = ents;
> +		bo->nents = nents;
> +		bo->deferred = true;
>  	}

else {
	return -EINVAL;
}

I think this should not happen, because non-dumb buffers are only
created with virgl being active.  Nevertheless we should catch this
case and return an error, maybe even have a WARN_ONCE() there.

Otherwise looks good to me, so with that fixed:

Reviewed-by: Gerd Hoffmann <kraxel@redhat.com>

take care,
  Gerd
Dmitry Osipenko Sept. 10, 2024, 10:09 p.m. UTC | #2
On 9/3/24 10:48, Jocelyn Falempe wrote:
> The host dumb buffer command needs a format, but the
> DRM_IOCTL_MODE_CREATE_DUMB only provides a buffer size.
> So wait for the DRM_IOCTL_MODE_ADDFB(2), to get the format, and create
> the host resources at this time.
> 
> This will allow virtio-gpu to support multiple pixel formats.
> 
> This problem was noticed in commit 42fd9e6c29b39 ("drm/virtio: fix
> DRM_FORMAT_* handling")
> 
> Suggested-by: Gerd Hoffmann <kraxel@redhat.com>
> Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
> ---
> 
> v2:
>  * Move virtio_gpu_object deferred field to its own block (Geerd Hoffmann)
>  * Check that the size of the dumb buffer can hold the framebuffer (Geerd Hoffmann)
> 
>  drivers/gpu/drm/virtio/virtgpu_display.c | 33 ++++++++++++++++++++++++
>  drivers/gpu/drm/virtio/virtgpu_drv.h     |  5 ++++
>  drivers/gpu/drm/virtio/virtgpu_gem.c     |  1 -
>  drivers/gpu/drm/virtio/virtgpu_object.c  | 13 +++++++---
>  4 files changed, 47 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
> index 64baf2f22d9f0..5e8ca742c6d00 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_display.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_display.c
> @@ -290,6 +290,30 @@ static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index)
>  	return 0;
>  }
>  
> +static int virtio_gpu_deferred_create(struct virtio_gpu_object *bo,
> +				      struct virtio_gpu_device *vgdev,
> +				      const struct drm_mode_fb_cmd2 *mode_cmd)
> +{
> +	struct virtio_gpu_object_params params = { 0 };
> +
> +	params.format = virtio_gpu_translate_format(mode_cmd->pixel_format);
> +	params.dumb = true;
> +	params.width = mode_cmd->width;
> +	params.height = mode_cmd->height;
> +	params.size = params.height * params.width * 4;
> +	params.size = ALIGN(params.size, PAGE_SIZE);
> +
> +	if (params.size > bo->base.base.size)
> +		return -EINVAL;
> +
> +	virtio_gpu_cmd_create_resource(vgdev, bo, &params, NULL, NULL);
> +	virtio_gpu_object_attach(vgdev, bo, bo->ents, bo->nents);
> +
> +	bo->deferred = false;
> +	bo->ents = NULL;
> +	return 0;
> +}
> +
>  static struct drm_framebuffer *
>  virtio_gpu_user_framebuffer_create(struct drm_device *dev,
>  				   struct drm_file *file_priv,
> @@ -297,6 +321,8 @@ virtio_gpu_user_framebuffer_create(struct drm_device *dev,
>  {
>  	struct drm_gem_object *obj = NULL;
>  	struct virtio_gpu_framebuffer *virtio_gpu_fb;
> +	struct virtio_gpu_device *vgdev = dev->dev_private;
> +	struct virtio_gpu_object *bo;
>  	int ret;
>  
>  	if (mode_cmd->pixel_format != DRM_FORMAT_HOST_XRGB8888 &&
> @@ -308,6 +334,13 @@ virtio_gpu_user_framebuffer_create(struct drm_device *dev,
>  	if (!obj)
>  		return ERR_PTR(-EINVAL);
>  
> +	bo = gem_to_virtio_gpu_obj(obj);
> +	if (bo->deferred) {
> +		ret = virtio_gpu_deferred_create(bo, vgdev, mode_cmd);
> +		if (ret)
> +			return ERR_PTR(ret);
> +	}
> +
>  	virtio_gpu_fb = kzalloc(sizeof(*virtio_gpu_fb), GFP_KERNEL);
>  	if (virtio_gpu_fb == NULL) {
>  		drm_gem_object_put(obj);
> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
> index 64c236169db88..4302933e5067c 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
> @@ -95,6 +95,11 @@ struct virtio_gpu_object {
>  	bool host3d_blob, guest_blob;
>  	uint32_t blob_mem, blob_flags;
>  
> +	/* For deferred dumb buffer creation */
> +	bool deferred;
> +	struct virtio_gpu_mem_entry *ents;
> +	unsigned int nents;
> +
>  	int uuid_state;
>  	uuid_t uuid;
>  };
> diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c
> index 7db48d17ee3a8..33ad15fed30f6 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_gem.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
> @@ -75,7 +75,6 @@ int virtio_gpu_mode_dumb_create(struct drm_file *file_priv,
>  	args->size = pitch * args->height;
>  	args->size = ALIGN(args->size, PAGE_SIZE);
>  
> -	params.format = virtio_gpu_translate_format(DRM_FORMAT_HOST_XRGB8888);

This will break the guest blob code path in virtio_gpu_object_create(),
AFAICT.

>  	params.width = args->width;
>  	params.height = args->height;
>  	params.size = args->size;
> diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c
> index c7e74cf130221..b5a537a761294 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_object.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_object.c
> @@ -67,6 +67,8 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo)
>  
>  	virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle);
>  	if (virtio_gpu_is_shmem(bo)) {
> +		if (bo->deferred)
> +			kvfree(bo->ents);
>  		drm_gem_shmem_free(&bo->base);
>  	} else if (virtio_gpu_is_vram(bo)) {
>  		struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo);
> @@ -228,10 +230,13 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
>  		virtio_gpu_cmd_resource_create_3d(vgdev, bo, params,
>  						  objs, fence);
>  		virtio_gpu_object_attach(vgdev, bo, ents, nents);
> -	} else {
> -		virtio_gpu_cmd_create_resource(vgdev, bo, params,
> -					       objs, fence);
> -		virtio_gpu_object_attach(vgdev, bo, ents, nents);
> +	} else if (params->dumb) {
> +		/* Create the host resource in virtio_gpu_user_framebuffer_create()
> +		 * because the pixel format is not specified yet
> +		 */
> +		bo->ents = ents;
> +		bo->nents = nents;
> +		bo->deferred = true;
>  	}

AFAICS, the "params.dumb = true" should be set in
virtio_gpu_mode_dumb_create() and not in virtio_gpu_deferred_create().
Was this patch tested?

Overall, this deferred resource creation doesn't look robust. Could be
better to either add SET_SCANOUT2 with the format info or add cmd that
overrides the res fmt.
Jocelyn Falempe Sept. 11, 2024, 8:04 a.m. UTC | #3
On 11/09/2024 00:09, Dmitry Osipenko wrote:
> On 9/3/24 10:48, Jocelyn Falempe wrote:
>> The host dumb buffer command needs a format, but the
>> DRM_IOCTL_MODE_CREATE_DUMB only provides a buffer size.
>> So wait for the DRM_IOCTL_MODE_ADDFB(2), to get the format, and create
>> the host resources at this time.
>>
>> This will allow virtio-gpu to support multiple pixel formats.
>>
>> This problem was noticed in commit 42fd9e6c29b39 ("drm/virtio: fix
>> DRM_FORMAT_* handling")
>>
>> Suggested-by: Gerd Hoffmann <kraxel@redhat.com>
>> Signed-off-by: Jocelyn Falempe <jfalempe@redhat.com>
>> ---
>>
>> v2:
>>   * Move virtio_gpu_object deferred field to its own block (Geerd Hoffmann)
>>   * Check that the size of the dumb buffer can hold the framebuffer (Geerd Hoffmann)
>>
>>   drivers/gpu/drm/virtio/virtgpu_display.c | 33 ++++++++++++++++++++++++
>>   drivers/gpu/drm/virtio/virtgpu_drv.h     |  5 ++++
>>   drivers/gpu/drm/virtio/virtgpu_gem.c     |  1 -
>>   drivers/gpu/drm/virtio/virtgpu_object.c  | 13 +++++++---
>>   4 files changed, 47 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
>> index 64baf2f22d9f0..5e8ca742c6d00 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_display.c
>> +++ b/drivers/gpu/drm/virtio/virtgpu_display.c
>> @@ -290,6 +290,30 @@ static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index)
>>   	return 0;
>>   }
>>   
>> +static int virtio_gpu_deferred_create(struct virtio_gpu_object *bo,
>> +				      struct virtio_gpu_device *vgdev,
>> +				      const struct drm_mode_fb_cmd2 *mode_cmd)
>> +{
>> +	struct virtio_gpu_object_params params = { 0 };
>> +
>> +	params.format = virtio_gpu_translate_format(mode_cmd->pixel_format);
>> +	params.dumb = true;
>> +	params.width = mode_cmd->width;
>> +	params.height = mode_cmd->height;
>> +	params.size = params.height * params.width * 4;
>> +	params.size = ALIGN(params.size, PAGE_SIZE);
>> +
>> +	if (params.size > bo->base.base.size)
>> +		return -EINVAL;
>> +
>> +	virtio_gpu_cmd_create_resource(vgdev, bo, &params, NULL, NULL);
>> +	virtio_gpu_object_attach(vgdev, bo, bo->ents, bo->nents);
>> +
>> +	bo->deferred = false;
>> +	bo->ents = NULL;
>> +	return 0;
>> +}
>> +
>>   static struct drm_framebuffer *
>>   virtio_gpu_user_framebuffer_create(struct drm_device *dev,
>>   				   struct drm_file *file_priv,
>> @@ -297,6 +321,8 @@ virtio_gpu_user_framebuffer_create(struct drm_device *dev,
>>   {
>>   	struct drm_gem_object *obj = NULL;
>>   	struct virtio_gpu_framebuffer *virtio_gpu_fb;
>> +	struct virtio_gpu_device *vgdev = dev->dev_private;
>> +	struct virtio_gpu_object *bo;
>>   	int ret;
>>   
>>   	if (mode_cmd->pixel_format != DRM_FORMAT_HOST_XRGB8888 &&
>> @@ -308,6 +334,13 @@ virtio_gpu_user_framebuffer_create(struct drm_device *dev,
>>   	if (!obj)
>>   		return ERR_PTR(-EINVAL);
>>   
>> +	bo = gem_to_virtio_gpu_obj(obj);
>> +	if (bo->deferred) {
>> +		ret = virtio_gpu_deferred_create(bo, vgdev, mode_cmd);
>> +		if (ret)
>> +			return ERR_PTR(ret);
>> +	}
>> +
>>   	virtio_gpu_fb = kzalloc(sizeof(*virtio_gpu_fb), GFP_KERNEL);
>>   	if (virtio_gpu_fb == NULL) {
>>   		drm_gem_object_put(obj);
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
>> index 64c236169db88..4302933e5067c 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
>> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
>> @@ -95,6 +95,11 @@ struct virtio_gpu_object {
>>   	bool host3d_blob, guest_blob;
>>   	uint32_t blob_mem, blob_flags;
>>   
>> +	/* For deferred dumb buffer creation */
>> +	bool deferred;
>> +	struct virtio_gpu_mem_entry *ents;
>> +	unsigned int nents;
>> +
>>   	int uuid_state;
>>   	uuid_t uuid;
>>   };
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c
>> index 7db48d17ee3a8..33ad15fed30f6 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_gem.c
>> +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
>> @@ -75,7 +75,6 @@ int virtio_gpu_mode_dumb_create(struct drm_file *file_priv,
>>   	args->size = pitch * args->height;
>>   	args->size = ALIGN(args->size, PAGE_SIZE);
>>   
>> -	params.format = virtio_gpu_translate_format(DRM_FORMAT_HOST_XRGB8888);
> 
> This will break the guest blob code path in virtio_gpu_object_create(),
> AFAICT.

The params.format is not used in virtio_gpu_cmd_resource_create_3d() nor 
in virtio_gpu_cmd_resource_create_blob(), it's only used for dumb buffer 
creation. So it shouldn't break the guest blob path.
> 
>>   	params.width = args->width;
>>   	params.height = args->height;
>>   	params.size = args->size;
>> diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c
>> index c7e74cf130221..b5a537a761294 100644
>> --- a/drivers/gpu/drm/virtio/virtgpu_object.c
>> +++ b/drivers/gpu/drm/virtio/virtgpu_object.c
>> @@ -67,6 +67,8 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo)
>>   
>>   	virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle);
>>   	if (virtio_gpu_is_shmem(bo)) {
>> +		if (bo->deferred)
>> +			kvfree(bo->ents);
>>   		drm_gem_shmem_free(&bo->base);
>>   	} else if (virtio_gpu_is_vram(bo)) {
>>   		struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo);
>> @@ -228,10 +230,13 @@ int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
>>   		virtio_gpu_cmd_resource_create_3d(vgdev, bo, params,
>>   						  objs, fence);
>>   		virtio_gpu_object_attach(vgdev, bo, ents, nents);
>> -	} else {
>> -		virtio_gpu_cmd_create_resource(vgdev, bo, params,
>> -					       objs, fence);
>> -		virtio_gpu_object_attach(vgdev, bo, ents, nents);
>> +	} else if (params->dumb) {
>> +		/* Create the host resource in virtio_gpu_user_framebuffer_create()
>> +		 * because the pixel format is not specified yet
>> +		 */
>> +		bo->ents = ents;
>> +		bo->nents = nents;
>> +		bo->deferred = true;
>>   	}
> 
> AFAICS, the "params.dumb = true" should be set in
> virtio_gpu_mode_dumb_create() and not in virtio_gpu_deferred_create().
> Was this patch tested?

You're right that params.dumb is not used in 
virtio_gpu_cmd_create_resource() so it's useless to set it in 
virtio_gpu_deferred_create(). I can remove that line.
But it's also set in virtio_gpu_mode_dumb_create() and I didn't change 
that with this patch.

I'm testing on a s390x machine, and it allows wayland compositor to 
work. (The colors are still a mess, but at least it starts with this patch).
> 
> Overall, this deferred resource creation doesn't look robust. Could be
> better to either add SET_SCANOUT2 with the format info or add cmd that
> overrides the res fmt.
> 
This would also need modification in the qemu code, so it looks much 
more complex than this patch.

Best regards,
Gerd Hoffmann Sept. 11, 2024, 9:49 a.m. UTC | #4
Hi,

> > +static int virtio_gpu_deferred_create(struct virtio_gpu_object *bo,
> > +				      struct virtio_gpu_device *vgdev,
> > +				      const struct drm_mode_fb_cmd2 *mode_cmd)
> > +{
> > +	struct virtio_gpu_object_params params = { 0 };
> > +
> > +	params.format = virtio_gpu_translate_format(mode_cmd->pixel_format);
> > +	params.dumb = true;

> > -	params.format = virtio_gpu_translate_format(DRM_FORMAT_HOST_XRGB8888);
> 
> This will break the guest blob code path in virtio_gpu_object_create(),
> AFAICT.

Good point.

> > +	} else if (params->dumb) {
> > +		/* Create the host resource in virtio_gpu_user_framebuffer_create()
> > +		 * because the pixel format is not specified yet
> > +		 */
> > +		bo->ents = ents;
> > +		bo->nents = nents;
> > +		bo->deferred = true;
> >  	}
> 
> AFAICS, the "params.dumb = true" should be set in
> virtio_gpu_mode_dumb_create() and not in virtio_gpu_deferred_create().
> Was this patch tested?

virtio_gpu_deferred_create re-creates params from scratch, so it must
set "params.dumb = true" too.  That looks fine to me.

> Overall, this deferred resource creation doesn't look robust. Could be
> better to either add SET_SCANOUT2 with the format info or add cmd that
> overrides the res fmt.

If we can solve this issue with a guest-side fix I'd very much prefer
that.  When adding device features for that the driver will have to
support both old + new devices, which I don't think will be better in
the end.

take care,
  Gerd

PS: Figured how using blob resources on s390x should work
    (tested in emulation only).
----------------------- cut here -----------------------
--- fedora-s390x-gfx.xml        2024-09-11 11:29:57.864900808 +0200
+++ fedora-s390x-gfx-blob.xml   2024-09-11 11:29:54.662935454 +0200
@@ -1,8 +1,11 @@
 <domain type='qemu'>
-  <name>fedora-s390x-gfx</name>
-  <uuid>00e1b01c-f220-4d95-9d25-cd52c4284238</uuid>
+  <name>fedora-s390x-gfx-blob</name>
+  <uuid>2dcfa930-019d-4c25-8636-65abeed741c0</uuid>
   <memory unit='KiB'>4194304</memory>
   <currentMemory unit='KiB'>4194304</currentMemory>
+  <memoryBacking>
+    <source type='memfd'/>
+  </memoryBacking>
   <vcpu placement='static'>2</vcpu>
   <os>
     <type arch='s390x' machine='s390-ccw-virtio-6.2'>hvm</type>
@@ -59,7 +62,7 @@
     </graphics>
     <audio id='1' type='none'/>
     <video>
-      <model type='virtio' heads='1' primary='yes'/>
+      <model type='virtio' heads='1' primary='yes' blob='on'/>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'>
         <zpci uid='0x0001' fid='0x00000000'/>
       </address>
Dmitry Osipenko Sept. 17, 2024, 10:25 p.m. UTC | #5
On 9/11/24 11:04, Jocelyn Falempe wrote:
...
>>> --- a/drivers/gpu/drm/virtio/virtgpu_gem.c
>>> +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
>>> @@ -75,7 +75,6 @@ int virtio_gpu_mode_dumb_create(struct drm_file
>>> *file_priv,
>>>       args->size = pitch * args->height;
>>>       args->size = ALIGN(args->size, PAGE_SIZE);
>>>   -    params.format =
>>> virtio_gpu_translate_format(DRM_FORMAT_HOST_XRGB8888);
>>
>> This will break the guest blob code path in virtio_gpu_object_create(),
>> AFAICT.
> 
> The params.format is not used in virtio_gpu_cmd_resource_create_3d() nor
> in virtio_gpu_cmd_resource_create_blob(), it's only used for dumb buffer
> creation. So it shouldn't break the guest blob path.

Indeed

>>>       params.width = args->width;
>>>       params.height = args->height;
>>>       params.size = args->size;
>>> diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c
>>> b/drivers/gpu/drm/virtio/virtgpu_object.c
>>> index c7e74cf130221..b5a537a761294 100644
>>> --- a/drivers/gpu/drm/virtio/virtgpu_object.c
>>> +++ b/drivers/gpu/drm/virtio/virtgpu_object.c
>>> @@ -67,6 +67,8 @@ void virtio_gpu_cleanup_object(struct
>>> virtio_gpu_object *bo)
>>>         virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle);
>>>       if (virtio_gpu_is_shmem(bo)) {
>>> +        if (bo->deferred)
>>> +            kvfree(bo->ents);
>>>           drm_gem_shmem_free(&bo->base);
>>>       } else if (virtio_gpu_is_vram(bo)) {
>>>           struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo);
>>> @@ -228,10 +230,13 @@ int virtio_gpu_object_create(struct
>>> virtio_gpu_device *vgdev,
>>>           virtio_gpu_cmd_resource_create_3d(vgdev, bo, params,
>>>                             objs, fence);
>>>           virtio_gpu_object_attach(vgdev, bo, ents, nents);
>>> -    } else {
>>> -        virtio_gpu_cmd_create_resource(vgdev, bo, params,
>>> -                           objs, fence);
>>> -        virtio_gpu_object_attach(vgdev, bo, ents, nents);
>>> +    } else if (params->dumb) {
>>> +        /* Create the host resource in
>>> virtio_gpu_user_framebuffer_create()
>>> +         * because the pixel format is not specified yet
>>> +         */
>>> +        bo->ents = ents;
>>> +        bo->nents = nents;
>>> +        bo->deferred = true;
>>>       }
>>
>> AFAICS, the "params.dumb = true" should be set in
>> virtio_gpu_mode_dumb_create() and not in virtio_gpu_deferred_create().
>> Was this patch tested?
> 
> You're right that params.dumb is not used in
> virtio_gpu_cmd_create_resource() so it's useless to set it in
> virtio_gpu_deferred_create(). I can remove that line.
> But it's also set in virtio_gpu_mode_dumb_create() and I didn't change
> that with this patch.
> 
> I'm testing on a s390x machine, and it allows wayland compositor to
> work. (The colors are still a mess, but at least it starts with this
> patch).

The commit message of patch #2 says that it's fbdev that doesn't work
because it uses BGRX8888, i.e. wayland should work without this patch,
isn't it?

Please try to find why colors are wrong, could become that we won't need
this patch anymore once you'll figure out the root of the problem.
diff mbox series

Patch

diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
index 64baf2f22d9f0..5e8ca742c6d00 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -290,6 +290,30 @@  static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index)
 	return 0;
 }
 
+static int virtio_gpu_deferred_create(struct virtio_gpu_object *bo,
+				      struct virtio_gpu_device *vgdev,
+				      const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+	struct virtio_gpu_object_params params = { 0 };
+
+	params.format = virtio_gpu_translate_format(mode_cmd->pixel_format);
+	params.dumb = true;
+	params.width = mode_cmd->width;
+	params.height = mode_cmd->height;
+	params.size = params.height * params.width * 4;
+	params.size = ALIGN(params.size, PAGE_SIZE);
+
+	if (params.size > bo->base.base.size)
+		return -EINVAL;
+
+	virtio_gpu_cmd_create_resource(vgdev, bo, &params, NULL, NULL);
+	virtio_gpu_object_attach(vgdev, bo, bo->ents, bo->nents);
+
+	bo->deferred = false;
+	bo->ents = NULL;
+	return 0;
+}
+
 static struct drm_framebuffer *
 virtio_gpu_user_framebuffer_create(struct drm_device *dev,
 				   struct drm_file *file_priv,
@@ -297,6 +321,8 @@  virtio_gpu_user_framebuffer_create(struct drm_device *dev,
 {
 	struct drm_gem_object *obj = NULL;
 	struct virtio_gpu_framebuffer *virtio_gpu_fb;
+	struct virtio_gpu_device *vgdev = dev->dev_private;
+	struct virtio_gpu_object *bo;
 	int ret;
 
 	if (mode_cmd->pixel_format != DRM_FORMAT_HOST_XRGB8888 &&
@@ -308,6 +334,13 @@  virtio_gpu_user_framebuffer_create(struct drm_device *dev,
 	if (!obj)
 		return ERR_PTR(-EINVAL);
 
+	bo = gem_to_virtio_gpu_obj(obj);
+	if (bo->deferred) {
+		ret = virtio_gpu_deferred_create(bo, vgdev, mode_cmd);
+		if (ret)
+			return ERR_PTR(ret);
+	}
+
 	virtio_gpu_fb = kzalloc(sizeof(*virtio_gpu_fb), GFP_KERNEL);
 	if (virtio_gpu_fb == NULL) {
 		drm_gem_object_put(obj);
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 64c236169db88..4302933e5067c 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -95,6 +95,11 @@  struct virtio_gpu_object {
 	bool host3d_blob, guest_blob;
 	uint32_t blob_mem, blob_flags;
 
+	/* For deferred dumb buffer creation */
+	bool deferred;
+	struct virtio_gpu_mem_entry *ents;
+	unsigned int nents;
+
 	int uuid_state;
 	uuid_t uuid;
 };
diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c
index 7db48d17ee3a8..33ad15fed30f6 100644
--- a/drivers/gpu/drm/virtio/virtgpu_gem.c
+++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
@@ -75,7 +75,6 @@  int virtio_gpu_mode_dumb_create(struct drm_file *file_priv,
 	args->size = pitch * args->height;
 	args->size = ALIGN(args->size, PAGE_SIZE);
 
-	params.format = virtio_gpu_translate_format(DRM_FORMAT_HOST_XRGB8888);
 	params.width = args->width;
 	params.height = args->height;
 	params.size = args->size;
diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c
index c7e74cf130221..b5a537a761294 100644
--- a/drivers/gpu/drm/virtio/virtgpu_object.c
+++ b/drivers/gpu/drm/virtio/virtgpu_object.c
@@ -67,6 +67,8 @@  void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo)
 
 	virtio_gpu_resource_id_put(vgdev, bo->hw_res_handle);
 	if (virtio_gpu_is_shmem(bo)) {
+		if (bo->deferred)
+			kvfree(bo->ents);
 		drm_gem_shmem_free(&bo->base);
 	} else if (virtio_gpu_is_vram(bo)) {
 		struct virtio_gpu_object_vram *vram = to_virtio_gpu_vram(bo);
@@ -228,10 +230,13 @@  int virtio_gpu_object_create(struct virtio_gpu_device *vgdev,
 		virtio_gpu_cmd_resource_create_3d(vgdev, bo, params,
 						  objs, fence);
 		virtio_gpu_object_attach(vgdev, bo, ents, nents);
-	} else {
-		virtio_gpu_cmd_create_resource(vgdev, bo, params,
-					       objs, fence);
-		virtio_gpu_object_attach(vgdev, bo, ents, nents);
+	} else if (params->dumb) {
+		/* Create the host resource in virtio_gpu_user_framebuffer_create()
+		 * because the pixel format is not specified yet
+		 */
+		bo->ents = ents;
+		bo->nents = nents;
+		bo->deferred = true;
 	}
 
 	*bo_ptr = bo;