summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_fops.c18
-rw-r--r--include/drm/drmP.h2
2 files changed, 15 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index eb8702d39e7d..81df9ae95e2e 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -172,6 +172,8 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
init_waitqueue_head(&priv->event_wait);
priv->event_space = 4096; /* set aside 4k for event buffer */
+ mutex_init(&priv->event_read_lock);
+
if (drm_core_check_feature(dev, DRIVER_GEM))
drm_gem_open(dev, priv);
@@ -483,11 +485,15 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
{
struct drm_file *file_priv = filp->private_data;
struct drm_device *dev = file_priv->minor->dev;
- ssize_t ret = 0;
+ ssize_t ret;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
+ ret = mutex_lock_interruptible(&file_priv->event_read_lock);
+ if (ret)
+ return ret;
+
for (;;) {
struct drm_pending_event *e = NULL;
@@ -509,12 +515,13 @@ ssize_t drm_read(struct file *filp, char __user *buffer,
break;
}
+ mutex_unlock(&file_priv->event_read_lock);
ret = wait_event_interruptible(file_priv->event_wait,
!list_empty(&file_priv->event_list));
- if (ret < 0)
- break;
-
- ret = 0;
+ if (ret >= 0)
+ ret = mutex_lock_interruptible(&file_priv->event_read_lock);
+ if (ret)
+ return ret;
} else {
unsigned length = e->event->length;
@@ -537,6 +544,7 @@ put_back_event:
e->destroy(e);
}
}
+ mutex_unlock(&file_priv->event_read_lock);
return ret;
}
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 30d4a5a495e2..8e1df1f7057c 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -344,6 +344,8 @@ struct drm_file {
struct list_head event_list;
int event_space;
+ struct mutex event_read_lock;
+
struct drm_prime_file_private prime;
};