if (!access_ok(VERIFY_WRITE, buffer, count))
                return -EFAULT;
 
-       spin_lock_irq(&dev->event_lock);
        for (;;) {
-               if (list_empty(&file_priv->event_list)) {
+               struct drm_pending_event *e = NULL;
+
+               spin_lock_irq(&dev->event_lock);
+               if (!list_empty(&file_priv->event_list)) {
+                       e = list_first_entry(&file_priv->event_list,
+                                       struct drm_pending_event, link);
+                       file_priv->event_space += e->event->length;
+                       list_del(&e->link);
+               }
+               spin_unlock_irq(&dev->event_lock);
+
+               if (e == NULL) {
                        if (ret)
                                break;
 
                                break;
                        }
 
-                       spin_unlock_irq(&dev->event_lock);
                        ret = wait_event_interruptible(file_priv->event_wait,
                                                       !list_empty(&file_priv->event_list));
-                       spin_lock_irq(&dev->event_lock);
                        if (ret < 0)
                                break;
 
                        ret = 0;
                } else {
-                       struct drm_pending_event *e;
-
-                       e = list_first_entry(&file_priv->event_list,
-                                            struct drm_pending_event, link);
-                       if (e->event->length + ret > count)
+                       unsigned length = e->event->length;
+
+                       if (length > count - ret) {
+put_back_event:
+                               spin_lock_irq(&dev->event_lock);
+                               file_priv->event_space -= length;
+                               list_add(&e->link, &file_priv->event_list);
+                               spin_unlock_irq(&dev->event_lock);
                                break;
+                       }
 
-                       if (__copy_to_user_inatomic(buffer + ret,
-                                                   e->event, e->event->length)) {
+                       if (copy_to_user(buffer + ret, e->event, length)) {
                                if (ret == 0)
                                        ret = -EFAULT;
-                               break;
+                               goto put_back_event;
                        }
 
-                       file_priv->event_space += e->event->length;
-                       ret += e->event->length;
-                       list_del(&e->link);
+                       ret += length;
                        e->destroy(e);
                }
        }
-       spin_unlock_irq(&dev->event_lock);
 
        return ret;
 }