drm: add new drm_wait_on function to replace macro
authorDave Airlie <airlied@linux.ie>
Sat, 28 Apr 2007 05:05:20 +0000 (15:05 +1000)
committerDave Airlie <airlied@linux.ie>
Sat, 28 Apr 2007 05:07:43 +0000 (15:07 +1000)
linux-core/drmP.h
linux-core/drm_drv.c

index 37b9352..a3f9ca8 100644 (file)
@@ -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,
index 3dc4d53..e5788d7 100644 (file)
@@ -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;