diff options
| author | Rob Clark <robdclark@gmail.com> | 2013-09-11 17:34:07 -0400 |
|---|---|---|
| committer | Rob Clark <robdclark@gmail.com> | 2013-09-11 17:36:28 -0400 |
| commit | f816f272437f3a2be0c9254d4ab8f917950d86a0 (patch) | |
| tree | 60a194cabed7ef5f367865d62daa99a62f5f6cf4 | |
| parent | 1f70e079c773b2c5988b0f0b4d314fc0f6c7a1b8 (diff) | |
drm/msm: return -EBUSY if bo still active
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>
| -rw-r--r-- | drivers/gpu/drm/msm/msm_drv.c | 50 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/msm_drv.h | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/msm/msm_gem.c | 6 |
3 files changed, 44 insertions, 18 deletions
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 864c9773636b..008d772384c7 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c | |||
| @@ -499,25 +499,41 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence, | |||
| 499 | struct timespec *timeout) | 499 | struct timespec *timeout) |
| 500 | { | 500 | { |
| 501 | struct msm_drm_private *priv = dev->dev_private; | 501 | struct msm_drm_private *priv = dev->dev_private; |
| 502 | unsigned long timeout_jiffies = timespec_to_jiffies(timeout); | ||
| 503 | unsigned long start_jiffies = jiffies; | ||
| 504 | unsigned long remaining_jiffies; | ||
| 505 | int ret; | 502 | int ret; |
| 506 | 503 | ||
| 507 | if (time_after(start_jiffies, timeout_jiffies)) | 504 | if (!priv->gpu) |
| 508 | remaining_jiffies = 0; | 505 | return 0; |
| 509 | else | 506 | |
| 510 | remaining_jiffies = timeout_jiffies - start_jiffies; | 507 | if (fence > priv->gpu->submitted_fence) { |
| 511 | 508 | DRM_ERROR("waiting on invalid fence: %u (of %u)\n", | |
| 512 | ret = wait_event_interruptible_timeout(priv->fence_event, | 509 | fence, priv->gpu->submitted_fence); |
| 513 | priv->completed_fence >= fence, | 510 | return -EINVAL; |
| 514 | remaining_jiffies); | 511 | } |
| 515 | if (ret == 0) { | 512 | |
| 516 | DBG("timeout waiting for fence: %u (completed: %u)", | 513 | if (!timeout) { |
| 517 | fence, priv->completed_fence); | 514 | /* no-wait: */ |
| 518 | ret = -ETIMEDOUT; | 515 | ret = fence_completed(dev, fence) ? 0 : -EBUSY; |
| 519 | } else if (ret != -ERESTARTSYS) { | 516 | } else { |
| 520 | ret = 0; | 517 | unsigned long timeout_jiffies = timespec_to_jiffies(timeout); |
| 518 | unsigned long start_jiffies = jiffies; | ||
| 519 | unsigned long remaining_jiffies; | ||
| 520 | |||
| 521 | if (time_after(start_jiffies, timeout_jiffies)) | ||
| 522 | remaining_jiffies = 0; | ||
| 523 | else | ||
| 524 | remaining_jiffies = timeout_jiffies - start_jiffies; | ||
| 525 | |||
| 526 | ret = wait_event_interruptible_timeout(priv->fence_event, | ||
| 527 | fence_completed(dev, fence), | ||
| 528 | remaining_jiffies); | ||
| 529 | |||
| 530 | if (ret == 0) { | ||
| 531 | DBG("timeout waiting for fence: %u (completed: %u)", | ||
| 532 | fence, priv->completed_fence); | ||
| 533 | ret = -ETIMEDOUT; | ||
| 534 | } else if (ret != -ERESTARTSYS) { | ||
| 535 | ret = 0; | ||
| 536 | } | ||
| 521 | } | 537 | } |
| 522 | 538 | ||
| 523 | return ret; | 539 | return ret; |
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 1ea9d46e01bc..df8f1d084bc1 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h | |||
| @@ -191,6 +191,12 @@ u32 msm_readl(const void __iomem *addr); | |||
| 191 | #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) | 191 | #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) |
| 192 | #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) | 192 | #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) |
| 193 | 193 | ||
| 194 | static inline bool fence_completed(struct drm_device *dev, uint32_t fence) | ||
| 195 | { | ||
| 196 | struct msm_drm_private *priv = dev->dev_private; | ||
| 197 | return priv->completed_fence >= fence; | ||
| 198 | } | ||
| 199 | |||
| 194 | static inline int align_pitch(int width, int bpp) | 200 | static inline int align_pitch(int width, int bpp) |
| 195 | { | 201 | { |
| 196 | int bytespp = (bpp + 7) / 8; | 202 | int bytespp = (bpp + 7) / 8; |
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 5999b67ec8f1..583286f39299 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c | |||
| @@ -437,12 +437,16 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, | |||
| 437 | struct msm_gem_object *msm_obj = to_msm_bo(obj); | 437 | struct msm_gem_object *msm_obj = to_msm_bo(obj); |
| 438 | int ret = 0; | 438 | int ret = 0; |
| 439 | 439 | ||
| 440 | if (is_active(msm_obj) && !(op & MSM_PREP_NOSYNC)) { | 440 | if (is_active(msm_obj)) { |
| 441 | uint32_t fence = 0; | 441 | uint32_t fence = 0; |
| 442 | |||
| 442 | if (op & MSM_PREP_READ) | 443 | if (op & MSM_PREP_READ) |
| 443 | fence = msm_obj->write_fence; | 444 | fence = msm_obj->write_fence; |
| 444 | if (op & MSM_PREP_WRITE) | 445 | if (op & MSM_PREP_WRITE) |
| 445 | fence = max(fence, msm_obj->read_fence); | 446 | fence = max(fence, msm_obj->read_fence); |
| 447 | if (op & MSM_PREP_NOSYNC) | ||
| 448 | timeout = NULL; | ||
| 449 | |||
| 446 | ret = msm_wait_fence_interruptable(dev, fence, timeout); | 450 | ret = msm_wait_fence_interruptable(dev, fence, timeout); |
| 447 | } | 451 | } |
| 448 | 452 | ||
