<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Jan 13, 2020 at 8:25 AM Rob Clark <<a href="mailto:robdclark@chromium.org">robdclark@chromium.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Mon, Jan 13, 2020 at 7:37 AM Brian Ho <<a href="mailto:brian@brkho.com" target="_blank">brian@brkho.com</a>> wrote:<br>
><br>
> Implements an ioctl to wait until a value at a given iova is greater<br>
> than or equal to a supplied value.<br>
><br>
> This will initially be used by turnip (open-source Vulkan driver for<br>
> QC in mesa) for occlusion queries where the userspace driver can<br>
> block on a query becoming available before continuing via<br>
> vkGetQueryPoolResults.<br>
><br>
> Signed-off-by: Brian Ho <<a href="mailto:brian@brkho.com" target="_blank">brian@brkho.com</a>><br>
> ---<br>
> drivers/gpu/drm/msm/msm_drv.c | 63 +++++++++++++++++++++++++++++++++--<br>
> include/uapi/drm/msm_drm.h | 13 ++++++++<br>
> 2 files changed, 74 insertions(+), 2 deletions(-)<br>
><br>
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c<br>
> index c84f0a8b3f2c..dcc46874a5a2 100644<br>
> --- a/drivers/gpu/drm/msm/msm_drv.c<br>
> +++ b/drivers/gpu/drm/msm/msm_drv.c<br>
> @@ -36,10 +36,11 @@<br>
> * MSM_GEM_INFO ioctl.<br>
> * - 1.4.0 - softpin, MSM_RELOC_BO_DUMP, and GEM_INFO support to set/get<br>
> * GEM object's debug name<br>
> - * - 1.5.0 - Add SUBMITQUERY_QUERY ioctl<br>
> + * - 1.5.0 - Add SUBMITQUEUE_QUERY ioctl<br>
> + * - 1.6.0 - Add WAIT_IOVA ioctl<br>
> */<br>
> #define MSM_VERSION_MAJOR 1<br>
> -#define MSM_VERSION_MINOR 5<br>
> +#define MSM_VERSION_MINOR 6<br>
> #define MSM_VERSION_PATCHLEVEL 0<br>
><br>
> static const struct drm_mode_config_funcs mode_config_funcs = {<br>
> @@ -952,6 +953,63 @@ static int msm_ioctl_submitqueue_close(struct drm_device *dev, void *data,<br>
> return msm_submitqueue_remove(file->driver_priv, id);<br>
> }<br>
><br>
> +static int msm_ioctl_wait_iova(struct drm_device *dev, void *data,<br>
> + struct drm_file *file)<br>
> +{<br>
> + struct msm_drm_private *priv = dev->dev_private;<br>
> + struct drm_gem_object *obj;<br>
> + struct drm_msm_wait_iova *args = data;<br>
> + ktime_t timeout = to_ktime(args->timeout);<br>
> + unsigned long remaining_jiffies = timeout_to_jiffies(&timeout);<br>
> + struct msm_gpu *gpu = priv->gpu;<br>
> + void *base_vaddr;<br>
> + uint64_t *vaddr;<br>
> + int ret;<br>
> +<br>
> + if (args->pad)<br>
> + return -EINVAL;<br>
> +<br>
> + if (!gpu)<br>
> + return 0;<br>
<br>
hmm, I'm not sure we should return zero in this case.. maybe -ENODEV?<br>
<br>
> +<br>
> + obj = drm_gem_object_lookup(file, args->handle);<br>
> + if (!obj)<br>
> + return -ENOENT;<br>
> +<br>
> + base_vaddr = msm_gem_get_vaddr(obj);<br>
> + if (IS_ERR(base_vaddr)) {<br>
> + ret = PTR_ERR(base_vaddr);<br>
> + goto err_put_gem_object;<br>
> + }<br>
> + if (args->offset + sizeof(*vaddr) > obj->size) {<br>
> + ret = -EINVAL;<br>
> + goto err_put_vaddr;<br>
> + }<br>
> +<br>
> + vaddr = base_vaddr + args->offset;<br>
> +<br>
> + /* Assumes WC mapping */<br>
> + ret = wait_event_interruptible_timeout(<br>
> + gpu->event, *vaddr >= args->value, remaining_jiffies);<br></blockquote><div><br></div><div>This needs to do the awkward looking</div><div><br></div><div> (int64_t)(*data - value) >= 0<br></div><div><br></div><div>to properly handle the wraparound case.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
> +<br>
> + if (ret == 0) {<br>
> + ret = -ETIMEDOUT;<br>
> + goto err_put_vaddr;<br>
> + } else if (ret == -ERESTARTSYS) {<br>
> + goto err_put_vaddr;<br>
> + }<br>
<br>
maybe:<br>
<br>
} else {<br>
ret = 0;<br>
}<br>
<br>
and then drop the next three lines?<br>
<br>
> +<br>
> + msm_gem_put_vaddr(obj);<br>
> + drm_gem_object_put_unlocked(obj);<br>
> + return 0;<br>
> +<br>
> +err_put_vaddr:<br>
> + msm_gem_put_vaddr(obj);<br>
> +err_put_gem_object:<br>
> + drm_gem_object_put_unlocked(obj);<br>
> + return ret;<br>
> +}<br>
> +<br>
> static const struct drm_ioctl_desc msm_ioctls[] = {<br>
> DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_RENDER_ALLOW),<br>
> DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_RENDER_ALLOW),<br>
> @@ -964,6 +1022,7 @@ static const struct drm_ioctl_desc msm_ioctls[] = {<br>
> DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW, msm_ioctl_submitqueue_new, DRM_RENDER_ALLOW),<br>
> DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_RENDER_ALLOW),<br>
> DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW),<br>
> + DRM_IOCTL_DEF_DRV(MSM_WAIT_IOVA, msm_ioctl_wait_iova, DRM_RENDER_ALLOW),<br>
> };<br>
><br>
> static const struct vm_operations_struct vm_ops = {<br>
> diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h<br>
> index 0b85ed6a3710..8477f28a4ee1 100644<br>
> --- a/include/uapi/drm/msm_drm.h<br>
> +++ b/include/uapi/drm/msm_drm.h<br>
> @@ -298,6 +298,17 @@ struct drm_msm_submitqueue_query {<br>
> __u32 pad;<br>
> };<br>
><br>
> +/* This ioctl blocks until the u64 value at bo + offset is greater than or<br>
> + * equal to the reference value.<br>
> + */<br>
> +struct drm_msm_wait_iova {<br>
> + __u32 handle; /* in, GEM handle */<br>
> + __u32 pad;<br>
> + struct drm_msm_timespec timeout; /* in */<br>
> + __u64 offset; /* offset into bo */<br>
> + __u64 value; /* reference value */<br>
<br>
Maybe we should go ahead and add a __u64 mask;<br>
<br>
that would let us wait for 32b values as well, and wait for bits in a bitmask<br></blockquote><div><br></div><div>I think we'd be OK to just default to 32 bit values instead, since most of the CP commands that this is intended to work with (CP_EVENT_WRITE, CP_WAIT_MEM_GTE etc) operate on 32 bit values. We could move 'value' to the slot right after 'handle' but then we'd not have any pad/reserved fields. Maybe we keep 'value' 64 bit but restrict it to 32 bits, with an option to add a 64 bit flag in 'pad' later on?</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Other than those minor comments, it looks pretty good to me<br>
<br>
BR,<br>
-R<br>
<br>
> +};<br>
> +<br>
> #define DRM_MSM_GET_PARAM 0x00<br>
> /* placeholder:<br>
> #define DRM_MSM_SET_PARAM 0x01<br>
> @@ -315,6 +326,7 @@ struct drm_msm_submitqueue_query {<br>
> #define DRM_MSM_SUBMITQUEUE_NEW 0x0A<br>
> #define DRM_MSM_SUBMITQUEUE_CLOSE 0x0B<br>
> #define DRM_MSM_SUBMITQUEUE_QUERY 0x0C<br>
> +#define DRM_MSM_WAIT_IOVA 0x0D<br>
><br>
> #define DRM_IOCTL_MSM_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param)<br>
> #define DRM_IOCTL_MSM_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_NEW, struct drm_msm_gem_new)<br>
> @@ -327,6 +339,7 @@ struct drm_msm_submitqueue_query {<br>
> #define DRM_IOCTL_MSM_SUBMITQUEUE_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_NEW, struct drm_msm_submitqueue)<br>
> #define DRM_IOCTL_MSM_SUBMITQUEUE_CLOSE DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_CLOSE, __u32)<br>
> #define DRM_IOCTL_MSM_SUBMITQUEUE_QUERY DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_SUBMITQUEUE_QUERY, struct drm_msm_submitqueue_query)<br>
> +#define DRM_IOCTL_MSM_WAIT_IOVA DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_WAIT_IOVA, struct drm_msm_wait_iova)<br>
><br>
> #if defined(__cplusplus)<br>
> }<br>
> --<br>
> 2.25.0.rc1.283.g88dfdc4193-goog<br>
><br>
</blockquote></div></div>