@@ -499,25 +499,41 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
struct timespec *timeout)
{
struct msm_drm_private *priv = dev->dev_private;
- unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
- unsigned long start_jiffies = jiffies;
- unsigned long remaining_jiffies;
int ret;
- if (time_after(start_jiffies, timeout_jiffies))
- remaining_jiffies = 0;
- else
- remaining_jiffies = timeout_jiffies - start_jiffies;
-
- ret = wait_event_interruptible_timeout(priv->fence_event,
- priv->completed_fence >= fence,
- remaining_jiffies);
- if (ret == 0) {
- DBG("timeout waiting for fence: %u (completed: %u)",
- fence, priv->completed_fence);
- ret = -ETIMEDOUT;
- } else if (ret != -ERESTARTSYS) {
- ret = 0;
+ if (!priv->gpu)
+ return 0;
+
+ if (fence > priv->gpu->submitted_fence) {
+ DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
+ fence, priv->gpu->submitted_fence);
+ return -EINVAL;
+ }
+
+ if (!timeout) {
+ /* no-wait: */
+ ret = fence_completed(dev, fence) ? 0 : -EBUSY;
+ } else {
+ unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
+ unsigned long start_jiffies = jiffies;
+ unsigned long remaining_jiffies;
+
+ if (time_after(start_jiffies, timeout_jiffies))
+ remaining_jiffies = 0;
+ else
+ remaining_jiffies = timeout_jiffies - start_jiffies;
+
+ ret = wait_event_interruptible_timeout(priv->fence_event,
+ fence_completed(dev, fence),
+ remaining_jiffies);
+
+ if (ret == 0) {
+ DBG("timeout waiting for fence: %u (completed: %u)",
+ fence, priv->completed_fence);
+ ret = -ETIMEDOUT;
+ } else if (ret != -ERESTARTSYS) {
+ ret = 0;
+ }
}
return ret;
@@ -191,6 +191,12 @@ u32 msm_readl(const void __iomem *addr);
#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
+static inline bool fence_completed(struct drm_device *dev, uint32_t fence)
+{
+ struct msm_drm_private *priv = dev->dev_private;
+ return priv->completed_fence >= fence;
+}
+
static inline int align_pitch(int width, int bpp)
{
int bytespp = (bpp + 7) / 8;
@@ -437,12 +437,16 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
struct msm_gem_object *msm_obj = to_msm_bo(obj);
int ret = 0;
- if (is_active(msm_obj) && !(op & MSM_PREP_NOSYNC)) {
+ if (is_active(msm_obj)) {
uint32_t fence = 0;
+
if (op & MSM_PREP_READ)
fence = msm_obj->write_fence;
if (op & MSM_PREP_WRITE)
fence = max(fence, msm_obj->read_fence);
+ if (op & MSM_PREP_NOSYNC)
+ timeout = NULL;
+
ret = msm_wait_fence_interruptable(dev, fence, timeout);
}
When we CPU_PREP a bo with NOSYNC flag (for example, to implement PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE), an -EBUSY return indicates to userspace that the bo is still busy. Previously it was incorrectly returning 0 in this case. And while we're in there throw in an bit of extra sanity checking in case userspace tries to wait for a bogus fence. Signed-off-by: Rob Clark <robdclark@gmail.com> --- drivers/gpu/drm/msm/msm_drv.c | 50 ++++++++++++++++++++++++++++--------------- drivers/gpu/drm/msm/msm_drv.h | 6 ++++++ drivers/gpu/drm/msm/msm_gem.c | 6 +++++- 3 files changed, 44 insertions(+), 18 deletions(-)