Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b8f0be0 authored by Eric Anholt's avatar Eric Anholt
Browse files

Merge remote branch 'airlied/drm-next' into drm-intel-next

parents 43bcd61f 4fe9676d
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -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;
+96 −2
Original line number Original line Diff line number Diff line
@@ -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);
@@ -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.
 *
 *
@@ -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);


@@ -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);
+95 −0
Original line number Original line Diff line number Diff line
@@ -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.
 *
 *
@@ -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;
@@ -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
@@ -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);
+2 −0
Original line number Original line Diff line number Diff line
@@ -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);
+1 −0
Original line number Original line Diff line number Diff line
@@ -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