mirror of
https://github.com/torvalds/linux.git
synced 2024-11-08 21:21:47 +00:00
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>
This commit is contained in:
parent
1f70e079c7
commit
f816f27243
@ -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;
|
||||
if (!priv->gpu)
|
||||
return 0;
|
||||
|
||||
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 (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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user