RE: [PATCH v2 2/2] drm/virtio: fence created per cursor/plane update

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi DW,

> Subject: [PATCH v2 2/2] drm/virtio: fence created per cursor/plane update
> 
> Having one fence for a vgfb would cause conflict in case there are
> multiple planes referencing the same vgfb (e.g. Xorg screen covering
> two displays in extended mode) being flushed simultaneously. So it makes
> sence to use a separated fence for each plane update to prevent this.
> 
> vgfb->fence is not required anymore with the suggested code change so
> both prepare_fb and cleanup_fb are removed since only fence creation/
> freeing are done in there.
> 
> v2: - use the fence always as long as guest_blob is enabled on the
>       scanout object
>     - obj and fence initialized as NULL ptrs to avoid uninitialzed
>       ptr problem (Reported by Dan Carpenter/kernel-test-robot)
> 
> Reported-by: kernel test robot <lkp@xxxxxxxxx>
> Reported-by: Dan Carpenter <dan.carpenter@xxxxxxxxxx>
> Cc: Gurchetan Singh <gurchetansingh@xxxxxxxxxxxx>
> Cc: Gerd Hoffmann <kraxel@xxxxxxxxxx>
> Cc: Vivek Kasireddy <vivek.kasireddy@xxxxxxxxx>
> Signed-off-by: Dongwon Kim <dongwon.kim@xxxxxxxxx>
> ---
>  drivers/gpu/drm/virtio/virtgpu_drv.h   |   1 -
>  drivers/gpu/drm/virtio/virtgpu_plane.c | 103 ++++++++++---------------
>  2 files changed, 39 insertions(+), 65 deletions(-)
> 
> diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
> index 0a194aaad419..4c59c1e67ca5 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_drv.h
> +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
> @@ -186,7 +186,6 @@ struct virtio_gpu_output {
> 
>  struct virtio_gpu_framebuffer {
>  	struct drm_framebuffer base;
> -	struct virtio_gpu_fence *fence;
>  };
>  #define to_virtio_gpu_framebuffer(x) \
>  	container_of(x, struct virtio_gpu_framebuffer, base)
> diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c
> index 6d3cc9e238a4..821023b7d57d 100644
> --- a/drivers/gpu/drm/virtio/virtgpu_plane.c
> +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c
> @@ -137,29 +137,37 @@ static void virtio_gpu_resource_flush(struct drm_plane *plane,
>  	struct virtio_gpu_device *vgdev = dev->dev_private;
>  	struct virtio_gpu_framebuffer *vgfb;
>  	struct virtio_gpu_object *bo;
> +	struct virtio_gpu_object_array *objs = NULL;
> +	struct virtio_gpu_fence *fence = NULL;
> 
>  	vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
>  	bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
> -	if (vgfb->fence) {
> -		struct virtio_gpu_object_array *objs;
> 
> +	if (!bo)
> +		return;
[Kasireddy, Vivek] I think you can drop the above check as bo is guaranteed
to be valid in resource_flush as the necessary checks are already done early
in virtio_gpu_primary_plane_update().

> +
> +	if (bo->dumb && bo->guest_blob)
> +		fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context,
> +					       0);
> +
> +	if (fence) {
>  		objs = virtio_gpu_array_alloc(1);
> -		if (!objs)
> +		if (!objs) {
> +			kfree(fence);
>  			return;
> +		}
>  		virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]);
>  		virtio_gpu_array_lock_resv(objs);
> -		virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle, x, y,
> -					      width, height, objs, vgfb->fence);
> -		virtio_gpu_notify(vgdev);
> +	}
> +
> +	virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle, x, y,
> +				      width, height, objs, fence);
> +	virtio_gpu_notify(vgdev);
[Kasireddy, Vivek] I think it is OK to retain the existing style where all the
statements relevant for if (fence) would be lumped together. I do understand that
the above two statements would be redundant in that case but it looks a bit cleaner.

> 
> -		dma_fence_wait_timeout(&vgfb->fence->f, true,
> +	if (fence) {
> +		dma_fence_wait_timeout(&fence->f, true,
>  				       msecs_to_jiffies(50));
> -		dma_fence_put(&vgfb->fence->f);
> -		vgfb->fence = NULL;
> -	} else {
> -		virtio_gpu_cmd_resource_flush(vgdev, bo->hw_res_handle, x, y,
> -					      width, height, NULL, NULL);
> -		virtio_gpu_notify(vgdev);
> +		dma_fence_put(&fence->f);
>  	}
>  }
> 
> @@ -239,47 +247,6 @@ static void virtio_gpu_primary_plane_update(struct drm_plane
> *plane,
>  				  rect.y2 - rect.y1);
>  }
> 
> -static int virtio_gpu_plane_prepare_fb(struct drm_plane *plane,
> -				       struct drm_plane_state *new_state)
> -{
> -	struct drm_device *dev = plane->dev;
> -	struct virtio_gpu_device *vgdev = dev->dev_private;
> -	struct virtio_gpu_framebuffer *vgfb;
> -	struct virtio_gpu_object *bo;
> -
> -	if (!new_state->fb)
> -		return 0;
> -
> -	vgfb = to_virtio_gpu_framebuffer(new_state->fb);
> -	bo = gem_to_virtio_gpu_obj(vgfb->base.obj[0]);
> -	if (!bo || (plane->type == DRM_PLANE_TYPE_PRIMARY && !bo->guest_blob))
> -		return 0;
> -
> -	if (bo->dumb && (plane->state->fb != new_state->fb)) {
> -		vgfb->fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context,
> -						     0);
> -		if (!vgfb->fence)
> -			return -ENOMEM;
> -	}
> -
> -	return 0;
> -}
> -
> -static void virtio_gpu_plane_cleanup_fb(struct drm_plane *plane,
> -					struct drm_plane_state *old_state)
> -{
> -	struct virtio_gpu_framebuffer *vgfb;
> -
> -	if (!plane->state->fb)
> -		return;
> -
> -	vgfb = to_virtio_gpu_framebuffer(plane->state->fb);
> -	if (vgfb->fence) {
> -		dma_fence_put(&vgfb->fence->f);
> -		vgfb->fence = NULL;
> -	}
> -}
> -
>  static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
>  					   struct drm_atomic_state *state)
>  {
> @@ -290,6 +257,8 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane
> *plane,
>  	struct virtio_gpu_output *output = NULL;
>  	struct virtio_gpu_framebuffer *vgfb;
>  	struct virtio_gpu_object *bo = NULL;
> +	struct virtio_gpu_object_array *objs = NULL;
> +	struct virtio_gpu_fence *fence = NULL;
>  	uint32_t handle;
> 
>  	if (plane->state->crtc)
> @@ -309,22 +278,32 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane
> *plane,
> 
>  	if (bo && bo->dumb && (plane->state->fb != old_state->fb)) {
>  		/* new cursor -- update & wait */
> -		struct virtio_gpu_object_array *objs;
> +		fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context,
> +					       0);
> +		if (!fence)
> +			return;
> 
>  		objs = virtio_gpu_array_alloc(1);
> -		if (!objs)
> +		if (!objs) {
> +			if (fence)
[Kasireddy, Vivek] I think you can drop the above check given that you checked it
earlier.

> +				kfree(fence);
> +
>  			return;
> +		}
> +
>  		virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]);
>  		virtio_gpu_array_lock_resv(objs);
>  		virtio_gpu_cmd_transfer_to_host_2d
>  			(vgdev, 0,
>  			 plane->state->crtc_w,
>  			 plane->state->crtc_h,
> -			 0, 0, objs, vgfb->fence);
> +			 0, 0, objs, fence);
>  		virtio_gpu_notify(vgdev);
> -		dma_fence_wait(&vgfb->fence->f, true);
> -		dma_fence_put(&vgfb->fence->f);
> -		vgfb->fence = NULL;
> +
> +		if (fence) {
[Kasireddy, Vivek] Same as above; i.e, you can drop the if (fence) check as we
wouldn't get here without a valid fence.

I think with the above changes, the diff may get smaller and simpler. Regardless,
this patch is Acked-by: Vivek Kasireddy <vivek.kasireddy@xxxxxxxxx>

> +			dma_fence_wait(&fence->f, true);
> +			dma_fence_put(&fence->f);
> +		}
>  	}
> 
>  	if (plane->state->fb != old_state->fb) {
> @@ -358,15 +337,11 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane
> *plane,
>  }
> 
>  static const struct drm_plane_helper_funcs virtio_gpu_primary_helper_funcs = {
> -	.prepare_fb		= virtio_gpu_plane_prepare_fb,
> -	.cleanup_fb		= virtio_gpu_plane_cleanup_fb,
>  	.atomic_check		= virtio_gpu_plane_atomic_check,
>  	.atomic_update		= virtio_gpu_primary_plane_update,
>  };
> 
>  static const struct drm_plane_helper_funcs virtio_gpu_cursor_helper_funcs = {
> -	.prepare_fb		= virtio_gpu_plane_prepare_fb,
> -	.cleanup_fb		= virtio_gpu_plane_cleanup_fb,
>  	.atomic_check		= virtio_gpu_plane_atomic_check,
>  	.atomic_update		= virtio_gpu_cursor_plane_update,
>  };
> --
> 2.20.1





[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux