summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drmP.h4
-rw-r--r--linux-core/drm_drv.c28
2 files changed, 31 insertions, 1 deletions
diff --git a/linux-core/drmP.h b/linux-core/drmP.h
index 37b93525..a3f9ca86 100644
--- a/linux-core/drmP.h
+++ b/linux-core/drmP.h
@@ -1129,7 +1129,9 @@ extern struct drm_sysfs_class *drm_class;
extern struct proc_dir_entry *drm_proc_root;
extern drm_local_map_t *drm_getsarea(struct drm_device *dev);
-
+extern int drm_wait_on(drm_device_t *dev, wait_queue_head_t *queue,
+ int timeout, int (*fn)(drm_device_t *dev, void *priv),
+ void *priv);
/* Proc support (drm_proc.h) */
extern int drm_proc_init(drm_device_t * dev,
int minor,
diff --git a/linux-core/drm_drv.c b/linux-core/drm_drv.c
index 3dc4d53c..e5788d76 100644
--- a/linux-core/drm_drv.c
+++ b/linux-core/drm_drv.c
@@ -623,6 +623,34 @@ err_i1:
}
EXPORT_SYMBOL(drm_ioctl);
+int drm_wait_on(drm_device_t *dev, wait_queue_head_t *queue, int timeout,
+ int (*fn)(drm_device_t *dev, void *priv), void *priv)
+{
+ DECLARE_WAITQUEUE(entry, current);
+ unsigned long end = jiffies + (timeout);
+ int ret = 0;
+ add_wait_queue(queue, &entry);
+
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+ if ((*fn)(dev, priv))
+ break;
+ if (time_after_eq(jiffies, end)) {
+ ret = -EBUSY;
+ break;
+ }
+ schedule_timeout((HZ/100 > 1) ? HZ/100 : 1);
+ if (signal_pending(current)) {
+ ret = -EINTR;
+ break;
+ }
+ }
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(queue, &entry);
+ return ret;
+}
+EXPORT_SYMBOL(drm_wait_on);
+
drm_local_map_t *drm_getsarea(struct drm_device *dev)
{
drm_map_list_t *entry;