Loading drivers/gpu/drm/drm_fb_helper.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -707,7 +707,7 @@ int drm_fb_helper_set_par(struct fb_info *info) if (crtc->fb == fb_helper->crtc_info[i].mode_set.fb) { if (crtc->fb == fb_helper->crtc_info[i].mode_set.fb) { mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex); ret = crtc->funcs->set_config(&fb_helper->crtc_info->mode_set); ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set); mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex); if (ret) if (ret) return ret; return ret; Loading drivers/gpu/drm/drm_fops.c +96 −2 Original line number Original line Diff line number Diff line Loading @@ -257,6 +257,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp, INIT_LIST_HEAD(&priv->lhead); INIT_LIST_HEAD(&priv->lhead); INIT_LIST_HEAD(&priv->fbs); INIT_LIST_HEAD(&priv->fbs); INIT_LIST_HEAD(&priv->event_list); init_waitqueue_head(&priv->event_wait); priv->event_space = 4096; /* set aside 4k for event buffer */ if (dev->driver->driver_features & DRIVER_GEM) if (dev->driver->driver_features & DRIVER_GEM) drm_gem_open(dev, priv); drm_gem_open(dev, priv); Loading Loading @@ -413,6 +416,30 @@ static void drm_master_release(struct drm_device *dev, struct file *filp) } } } } static void drm_events_release(struct drm_file *file_priv) { struct drm_device *dev = file_priv->minor->dev; struct drm_pending_event *e, *et; struct drm_pending_vblank_event *v, *vt; unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); /* Remove pending flips */ list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link) if (v->base.file_priv == file_priv) { list_del(&v->base.link); drm_vblank_put(dev, v->pipe); v->base.destroy(&v->base); } /* Remove unconsumed events */ list_for_each_entry_safe(e, et, &file_priv->event_list, link) e->destroy(e); spin_unlock_irqrestore(&dev->event_lock, flags); } /** /** * Release file. * Release file. * * Loading Loading @@ -451,6 +478,8 @@ int drm_release(struct inode *inode, struct file *filp) if (file_priv->minor->master) if (file_priv->minor->master) drm_master_release(dev, filp); drm_master_release(dev, filp); drm_events_release(file_priv); if (dev->driver->driver_features & DRIVER_GEM) if (dev->driver->driver_features & DRIVER_GEM) drm_gem_release(dev, file_priv); drm_gem_release(dev, file_priv); Loading Loading @@ -544,9 +573,74 @@ int drm_release(struct inode *inode, struct file *filp) } } EXPORT_SYMBOL(drm_release); EXPORT_SYMBOL(drm_release); /** No-op. */ static bool drm_dequeue_event(struct drm_file *file_priv, size_t total, size_t max, struct drm_pending_event **out) { struct drm_device *dev = file_priv->minor->dev; struct drm_pending_event *e; unsigned long flags; bool ret = false; spin_lock_irqsave(&dev->event_lock, flags); *out = NULL; if (list_empty(&file_priv->event_list)) goto out; e = list_first_entry(&file_priv->event_list, struct drm_pending_event, link); if (e->event->length + total > max) goto out; file_priv->event_space += e->event->length; list_del(&e->link); *out = e; ret = true; out: spin_unlock_irqrestore(&dev->event_lock, flags); return ret; } ssize_t drm_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset) { struct drm_file *file_priv = filp->private_data; struct drm_pending_event *e; size_t total; ssize_t ret; ret = wait_event_interruptible(file_priv->event_wait, !list_empty(&file_priv->event_list)); if (ret < 0) return ret; total = 0; while (drm_dequeue_event(file_priv, total, count, &e)) { if (copy_to_user(buffer + total, e->event, e->event->length)) { total = -EFAULT; break; } total += e->event->length; e->destroy(e); } return total; } EXPORT_SYMBOL(drm_read); unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) { { return 0; struct drm_file *file_priv = filp->private_data; unsigned int mask = 0; poll_wait(filp, &file_priv->event_wait, wait); if (!list_empty(&file_priv->event_list)) mask |= POLLIN | POLLRDNORM; return mask; } } EXPORT_SYMBOL(drm_poll); EXPORT_SYMBOL(drm_poll); drivers/gpu/drm/drm_irq.c +95 −0 Original line number Original line Diff line number Diff line Loading @@ -550,6 +550,62 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, return ret; return ret; } } static int drm_queue_vblank_event(struct drm_device *dev, int pipe, union drm_wait_vblank *vblwait, struct drm_file *file_priv) { struct drm_pending_vblank_event *e; struct timeval now; unsigned long flags; unsigned int seq; e = kzalloc(sizeof *e, GFP_KERNEL); if (e == NULL) return -ENOMEM; e->pipe = pipe; e->event.base.type = DRM_EVENT_VBLANK; e->event.base.length = sizeof e->event; e->event.user_data = vblwait->request.signal; e->base.event = &e->event.base; e->base.file_priv = file_priv; e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; do_gettimeofday(&now); spin_lock_irqsave(&dev->event_lock, flags); if (file_priv->event_space < sizeof e->event) { spin_unlock_irqrestore(&dev->event_lock, flags); kfree(e); return -ENOMEM; } file_priv->event_space -= sizeof e->event; seq = drm_vblank_count(dev, pipe); if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && (seq - vblwait->request.sequence) <= (1 << 23)) { vblwait->request.sequence = seq + 1; } DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n", vblwait->request.sequence, seq, pipe); e->event.sequence = vblwait->request.sequence; if ((seq - vblwait->request.sequence) <= (1 << 23)) { e->event.tv_sec = now.tv_sec; e->event.tv_usec = now.tv_usec; drm_vblank_put(dev, e->pipe); list_add_tail(&e->base.link, &e->base.file_priv->event_list); wake_up_interruptible(&e->base.file_priv->event_wait); } else { list_add_tail(&e->base.link, &dev->vblank_event_list); } spin_unlock_irqrestore(&dev->event_lock, flags); return 0; } /** /** * Wait for VBLANK. * Wait for VBLANK. * * Loading Loading @@ -609,6 +665,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data, goto done; goto done; } } if (flags & _DRM_VBLANK_EVENT) return drm_queue_vblank_event(dev, crtc, vblwait, file_priv); if ((flags & _DRM_VBLANK_NEXTONMISS) && if ((flags & _DRM_VBLANK_NEXTONMISS) && (seq - vblwait->request.sequence) <= (1<<23)) { (seq - vblwait->request.sequence) <= (1<<23)) { vblwait->request.sequence = seq + 1; vblwait->request.sequence = seq + 1; Loading Loading @@ -641,6 +700,38 @@ int drm_wait_vblank(struct drm_device *dev, void *data, return ret; return ret; } } void drm_handle_vblank_events(struct drm_device *dev, int crtc) { struct drm_pending_vblank_event *e, *t; struct timeval now; unsigned long flags; unsigned int seq; do_gettimeofday(&now); seq = drm_vblank_count(dev, crtc); spin_lock_irqsave(&dev->event_lock, flags); list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { if (e->pipe != crtc) continue; if ((seq - e->event.sequence) > (1<<23)) continue; DRM_DEBUG("vblank event on %d, current %d\n", e->event.sequence, seq); e->event.sequence = seq; e->event.tv_sec = now.tv_sec; e->event.tv_usec = now.tv_usec; drm_vblank_put(dev, e->pipe); list_move_tail(&e->base.link, &e->base.file_priv->event_list); wake_up_interruptible(&e->base.file_priv->event_wait); } spin_unlock_irqrestore(&dev->event_lock, flags); } /** /** * drm_handle_vblank - handle a vblank event * drm_handle_vblank - handle a vblank event * @dev: DRM device * @dev: DRM device Loading @@ -651,7 +742,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data, */ */ void drm_handle_vblank(struct drm_device *dev, int crtc) void drm_handle_vblank(struct drm_device *dev, int crtc) { { if (!dev->num_crtcs) return; atomic_inc(&dev->_vblank_count[crtc]); atomic_inc(&dev->_vblank_count[crtc]); DRM_WAKEUP(&dev->vbl_queue[crtc]); DRM_WAKEUP(&dev->vbl_queue[crtc]); drm_handle_vblank_events(dev, crtc); } } EXPORT_SYMBOL(drm_handle_vblank); EXPORT_SYMBOL(drm_handle_vblank); drivers/gpu/drm/drm_stub.c +2 −0 Original line number Original line Diff line number Diff line Loading @@ -220,9 +220,11 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, INIT_LIST_HEAD(&dev->ctxlist); INIT_LIST_HEAD(&dev->ctxlist); INIT_LIST_HEAD(&dev->vmalist); INIT_LIST_HEAD(&dev->vmalist); INIT_LIST_HEAD(&dev->maplist); INIT_LIST_HEAD(&dev->maplist); INIT_LIST_HEAD(&dev->vblank_event_list); spin_lock_init(&dev->count_lock); spin_lock_init(&dev->count_lock); spin_lock_init(&dev->drw_lock); spin_lock_init(&dev->drw_lock); spin_lock_init(&dev->event_lock); init_timer(&dev->timer); init_timer(&dev->timer); mutex_init(&dev->struct_mutex); mutex_init(&dev->struct_mutex); mutex_init(&dev->ctxlist_mutex); mutex_init(&dev->ctxlist_mutex); Loading drivers/gpu/drm/i915/i915_drv.c +1 −0 Original line number Original line Diff line number Diff line Loading @@ -333,6 +333,7 @@ static struct drm_driver driver = { .mmap = drm_gem_mmap, .mmap = drm_gem_mmap, .poll = drm_poll, .poll = drm_poll, .fasync = drm_fasync, .fasync = drm_fasync, .read = drm_read, #ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT .compat_ioctl = i915_compat_ioctl, .compat_ioctl = i915_compat_ioctl, #endif #endif Loading Loading
drivers/gpu/drm/drm_fb_helper.c +1 −1 Original line number Original line Diff line number Diff line Loading @@ -707,7 +707,7 @@ int drm_fb_helper_set_par(struct fb_info *info) if (crtc->fb == fb_helper->crtc_info[i].mode_set.fb) { if (crtc->fb == fb_helper->crtc_info[i].mode_set.fb) { mutex_lock(&dev->mode_config.mutex); mutex_lock(&dev->mode_config.mutex); ret = crtc->funcs->set_config(&fb_helper->crtc_info->mode_set); ret = crtc->funcs->set_config(&fb_helper->crtc_info[i].mode_set); mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex); if (ret) if (ret) return ret; return ret; Loading
drivers/gpu/drm/drm_fops.c +96 −2 Original line number Original line Diff line number Diff line Loading @@ -257,6 +257,9 @@ static int drm_open_helper(struct inode *inode, struct file *filp, INIT_LIST_HEAD(&priv->lhead); INIT_LIST_HEAD(&priv->lhead); INIT_LIST_HEAD(&priv->fbs); INIT_LIST_HEAD(&priv->fbs); INIT_LIST_HEAD(&priv->event_list); init_waitqueue_head(&priv->event_wait); priv->event_space = 4096; /* set aside 4k for event buffer */ if (dev->driver->driver_features & DRIVER_GEM) if (dev->driver->driver_features & DRIVER_GEM) drm_gem_open(dev, priv); drm_gem_open(dev, priv); Loading Loading @@ -413,6 +416,30 @@ static void drm_master_release(struct drm_device *dev, struct file *filp) } } } } static void drm_events_release(struct drm_file *file_priv) { struct drm_device *dev = file_priv->minor->dev; struct drm_pending_event *e, *et; struct drm_pending_vblank_event *v, *vt; unsigned long flags; spin_lock_irqsave(&dev->event_lock, flags); /* Remove pending flips */ list_for_each_entry_safe(v, vt, &dev->vblank_event_list, base.link) if (v->base.file_priv == file_priv) { list_del(&v->base.link); drm_vblank_put(dev, v->pipe); v->base.destroy(&v->base); } /* Remove unconsumed events */ list_for_each_entry_safe(e, et, &file_priv->event_list, link) e->destroy(e); spin_unlock_irqrestore(&dev->event_lock, flags); } /** /** * Release file. * Release file. * * Loading Loading @@ -451,6 +478,8 @@ int drm_release(struct inode *inode, struct file *filp) if (file_priv->minor->master) if (file_priv->minor->master) drm_master_release(dev, filp); drm_master_release(dev, filp); drm_events_release(file_priv); if (dev->driver->driver_features & DRIVER_GEM) if (dev->driver->driver_features & DRIVER_GEM) drm_gem_release(dev, file_priv); drm_gem_release(dev, file_priv); Loading Loading @@ -544,9 +573,74 @@ int drm_release(struct inode *inode, struct file *filp) } } EXPORT_SYMBOL(drm_release); EXPORT_SYMBOL(drm_release); /** No-op. */ static bool drm_dequeue_event(struct drm_file *file_priv, size_t total, size_t max, struct drm_pending_event **out) { struct drm_device *dev = file_priv->minor->dev; struct drm_pending_event *e; unsigned long flags; bool ret = false; spin_lock_irqsave(&dev->event_lock, flags); *out = NULL; if (list_empty(&file_priv->event_list)) goto out; e = list_first_entry(&file_priv->event_list, struct drm_pending_event, link); if (e->event->length + total > max) goto out; file_priv->event_space += e->event->length; list_del(&e->link); *out = e; ret = true; out: spin_unlock_irqrestore(&dev->event_lock, flags); return ret; } ssize_t drm_read(struct file *filp, char __user *buffer, size_t count, loff_t *offset) { struct drm_file *file_priv = filp->private_data; struct drm_pending_event *e; size_t total; ssize_t ret; ret = wait_event_interruptible(file_priv->event_wait, !list_empty(&file_priv->event_list)); if (ret < 0) return ret; total = 0; while (drm_dequeue_event(file_priv, total, count, &e)) { if (copy_to_user(buffer + total, e->event, e->event->length)) { total = -EFAULT; break; } total += e->event->length; e->destroy(e); } return total; } EXPORT_SYMBOL(drm_read); unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) { { return 0; struct drm_file *file_priv = filp->private_data; unsigned int mask = 0; poll_wait(filp, &file_priv->event_wait, wait); if (!list_empty(&file_priv->event_list)) mask |= POLLIN | POLLRDNORM; return mask; } } EXPORT_SYMBOL(drm_poll); EXPORT_SYMBOL(drm_poll);
drivers/gpu/drm/drm_irq.c +95 −0 Original line number Original line Diff line number Diff line Loading @@ -550,6 +550,62 @@ int drm_modeset_ctl(struct drm_device *dev, void *data, return ret; return ret; } } static int drm_queue_vblank_event(struct drm_device *dev, int pipe, union drm_wait_vblank *vblwait, struct drm_file *file_priv) { struct drm_pending_vblank_event *e; struct timeval now; unsigned long flags; unsigned int seq; e = kzalloc(sizeof *e, GFP_KERNEL); if (e == NULL) return -ENOMEM; e->pipe = pipe; e->event.base.type = DRM_EVENT_VBLANK; e->event.base.length = sizeof e->event; e->event.user_data = vblwait->request.signal; e->base.event = &e->event.base; e->base.file_priv = file_priv; e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; do_gettimeofday(&now); spin_lock_irqsave(&dev->event_lock, flags); if (file_priv->event_space < sizeof e->event) { spin_unlock_irqrestore(&dev->event_lock, flags); kfree(e); return -ENOMEM; } file_priv->event_space -= sizeof e->event; seq = drm_vblank_count(dev, pipe); if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) && (seq - vblwait->request.sequence) <= (1 << 23)) { vblwait->request.sequence = seq + 1; } DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n", vblwait->request.sequence, seq, pipe); e->event.sequence = vblwait->request.sequence; if ((seq - vblwait->request.sequence) <= (1 << 23)) { e->event.tv_sec = now.tv_sec; e->event.tv_usec = now.tv_usec; drm_vblank_put(dev, e->pipe); list_add_tail(&e->base.link, &e->base.file_priv->event_list); wake_up_interruptible(&e->base.file_priv->event_wait); } else { list_add_tail(&e->base.link, &dev->vblank_event_list); } spin_unlock_irqrestore(&dev->event_lock, flags); return 0; } /** /** * Wait for VBLANK. * Wait for VBLANK. * * Loading Loading @@ -609,6 +665,9 @@ int drm_wait_vblank(struct drm_device *dev, void *data, goto done; goto done; } } if (flags & _DRM_VBLANK_EVENT) return drm_queue_vblank_event(dev, crtc, vblwait, file_priv); if ((flags & _DRM_VBLANK_NEXTONMISS) && if ((flags & _DRM_VBLANK_NEXTONMISS) && (seq - vblwait->request.sequence) <= (1<<23)) { (seq - vblwait->request.sequence) <= (1<<23)) { vblwait->request.sequence = seq + 1; vblwait->request.sequence = seq + 1; Loading Loading @@ -641,6 +700,38 @@ int drm_wait_vblank(struct drm_device *dev, void *data, return ret; return ret; } } void drm_handle_vblank_events(struct drm_device *dev, int crtc) { struct drm_pending_vblank_event *e, *t; struct timeval now; unsigned long flags; unsigned int seq; do_gettimeofday(&now); seq = drm_vblank_count(dev, crtc); spin_lock_irqsave(&dev->event_lock, flags); list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { if (e->pipe != crtc) continue; if ((seq - e->event.sequence) > (1<<23)) continue; DRM_DEBUG("vblank event on %d, current %d\n", e->event.sequence, seq); e->event.sequence = seq; e->event.tv_sec = now.tv_sec; e->event.tv_usec = now.tv_usec; drm_vblank_put(dev, e->pipe); list_move_tail(&e->base.link, &e->base.file_priv->event_list); wake_up_interruptible(&e->base.file_priv->event_wait); } spin_unlock_irqrestore(&dev->event_lock, flags); } /** /** * drm_handle_vblank - handle a vblank event * drm_handle_vblank - handle a vblank event * @dev: DRM device * @dev: DRM device Loading @@ -651,7 +742,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data, */ */ void drm_handle_vblank(struct drm_device *dev, int crtc) void drm_handle_vblank(struct drm_device *dev, int crtc) { { if (!dev->num_crtcs) return; atomic_inc(&dev->_vblank_count[crtc]); atomic_inc(&dev->_vblank_count[crtc]); DRM_WAKEUP(&dev->vbl_queue[crtc]); DRM_WAKEUP(&dev->vbl_queue[crtc]); drm_handle_vblank_events(dev, crtc); } } EXPORT_SYMBOL(drm_handle_vblank); EXPORT_SYMBOL(drm_handle_vblank);
drivers/gpu/drm/drm_stub.c +2 −0 Original line number Original line Diff line number Diff line Loading @@ -220,9 +220,11 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev, INIT_LIST_HEAD(&dev->ctxlist); INIT_LIST_HEAD(&dev->ctxlist); INIT_LIST_HEAD(&dev->vmalist); INIT_LIST_HEAD(&dev->vmalist); INIT_LIST_HEAD(&dev->maplist); INIT_LIST_HEAD(&dev->maplist); INIT_LIST_HEAD(&dev->vblank_event_list); spin_lock_init(&dev->count_lock); spin_lock_init(&dev->count_lock); spin_lock_init(&dev->drw_lock); spin_lock_init(&dev->drw_lock); spin_lock_init(&dev->event_lock); init_timer(&dev->timer); init_timer(&dev->timer); mutex_init(&dev->struct_mutex); mutex_init(&dev->struct_mutex); mutex_init(&dev->ctxlist_mutex); mutex_init(&dev->ctxlist_mutex); Loading
drivers/gpu/drm/i915/i915_drv.c +1 −0 Original line number Original line Diff line number Diff line Loading @@ -333,6 +333,7 @@ static struct drm_driver driver = { .mmap = drm_gem_mmap, .mmap = drm_gem_mmap, .poll = drm_poll, .poll = drm_poll, .fasync = drm_fasync, .fasync = drm_fasync, .read = drm_read, #ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT .compat_ioctl = i915_compat_ioctl, .compat_ioctl = i915_compat_ioctl, #endif #endif Loading