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

Commit af6061af authored by Dave Airlie's avatar Dave Airlie
Browse files

Revert "drm/vbl rework: rework how the drm deals with vblank."



This reverts commit ac741ab7.

Okay this looks like wasn't as fully baked as I'd led myself to believe.

Revert for now for further baking.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent c0a18111
Loading
Loading
Loading
Loading
+0 −17
Original line number Diff line number Diff line
@@ -471,7 +471,6 @@ struct drm_irq_busid {
enum drm_vblank_seq_type {
	_DRM_VBLANK_ABSOLUTE = 0x0,	/**< Wait for specific vblank sequence number */
	_DRM_VBLANK_RELATIVE = 0x1,	/**< Wait for given number of vblanks */
	_DRM_VBLANK_FLIP = 0x8000000,	/**< Scheduled buffer swap should flip */
	_DRM_VBLANK_NEXTONMISS = 0x10000000,	/**< If missed, wait for next vblank */
	_DRM_VBLANK_SECONDARY = 0x20000000,	/**< Secondary display controller */
	_DRM_VBLANK_SIGNAL = 0x40000000	/**< Send signal instead of blocking */
@@ -504,21 +503,6 @@ union drm_wait_vblank {
	struct drm_wait_vblank_reply reply;
};

enum drm_modeset_ctl_cmd {
	_DRM_PRE_MODESET = 1,
	_DRM_POST_MODESET = 2,
};

/**
 * DRM_IOCTL_MODESET_CTL ioctl argument type
 *
 * \sa drmModesetCtl().
 */
struct drm_modeset_ctl {
	unsigned long arg;
	enum drm_modeset_ctl_cmd cmd;
};

/**
 * DRM_IOCTL_AGP_ENABLE ioctl argument type.
 *
@@ -603,7 +587,6 @@ struct drm_set_version {
#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, struct drm_client)
#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, struct drm_stats)
#define DRM_IOCTL_SET_VERSION		DRM_IOWR(0x07, struct drm_set_version)
#define DRM_IOCTL_MODESET_CTL           DRM_IOW(0x08, struct drm_modeset_ctl)

#define DRM_IOCTL_SET_UNIQUE		DRM_IOW( 0x10, struct drm_unique)
#define DRM_IOCTL_AUTH_MAGIC		DRM_IOW( 0x11, struct drm_auth)
+17 −74
Original line number Diff line number Diff line
@@ -100,8 +100,10 @@ struct drm_device;
#define DRIVER_HAVE_DMA    0x20
#define DRIVER_HAVE_IRQ    0x40
#define DRIVER_IRQ_SHARED  0x80
#define DRIVER_IRQ_VBL     0x100
#define DRIVER_DMA_QUEUE   0x200
#define DRIVER_FB_DMA      0x400
#define DRIVER_IRQ_VBL2    0x800

/***********************************************************************/
/** \name Begin the DRM... */
@@ -578,50 +580,8 @@ struct drm_driver {
	int (*kernel_context_switch) (struct drm_device *dev, int old,
				      int new);
	void (*kernel_context_switch_unlock) (struct drm_device *dev);
	/**
	 * get_vblank_counter - get raw hardware vblank counter
	 * @dev: DRM device
	 * @crtc: counter to fetch
	 *
	 * Driver callback for fetching a raw hardware vblank counter
	 * for @crtc.  If a device doesn't have a hardware counter, the
	 * driver can simply return the value of drm_vblank_count and
	 * make the enable_vblank() and disable_vblank() hooks into no-ops,
	 * leaving interrupts enabled at all times.
	 *
	 * Wraparound handling and loss of events due to modesetting is dealt
	 * with in the DRM core code.
	 *
	 * RETURNS
	 * Raw vblank counter value.
	 */
	u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);

	/**
	 * enable_vblank - enable vblank interrupt events
	 * @dev: DRM device
	 * @crtc: which irq to enable
	 *
	 * Enable vblank interrupts for @crtc.  If the device doesn't have
	 * a hardware vblank counter, this routine should be a no-op, since
	 * interrupts will have to stay on to keep the count accurate.
	 *
	 * RETURNS
	 * Zero on success, appropriate errno if the given @crtc's vblank
	 * interrupt cannot be enabled.
	 */
	int (*enable_vblank) (struct drm_device *dev, int crtc);

	/**
	 * disable_vblank - disable vblank interrupt events
	 * @dev: DRM device
	 * @crtc: which irq to enable
	 *
	 * Disable vblank interrupts for @crtc.  If the device doesn't have
	 * a hardware vblank counter, this routine should be a no-op, since
	 * interrupts will have to stay on to keep the count accurate.
	 */
	void (*disable_vblank) (struct drm_device *dev, int crtc);
	int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
	int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
	int (*dri_library_name) (struct drm_device *dev, char *buf);

	/**
@@ -641,7 +601,7 @@ struct drm_driver {

	irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
	void (*irq_preinstall) (struct drm_device *dev);
	int (*irq_postinstall) (struct drm_device *dev);
	void (*irq_postinstall) (struct drm_device *dev);
	void (*irq_uninstall) (struct drm_device *dev);
	void (*reclaim_buffers) (struct drm_device *dev,
				 struct drm_file * file_priv);
@@ -770,21 +730,13 @@ struct drm_device {
	/** \name VBLANK IRQ support */
	/*@{ */

	wait_queue_head_t *vbl_queue;	/**< VBLANK wait queue */
	atomic_t *_vblank_count;	/**< number of VBLANK interrupts (driver must alloc the right number of counters) */
	wait_queue_head_t vbl_queue;	/**< VBLANK wait queue */
	atomic_t vbl_received;
	atomic_t vbl_received2;		/**< number of secondary VBLANK interrupts */
	spinlock_t vbl_lock;
	struct list_head *vbl_sigs;		/**< signal list to send on VBLANK */
	atomic_t vbl_signal_pending;	/* number of signals pending on all crtcs*/
	atomic_t *vblank_refcount;	/* number of users of vblank interrupts per crtc */
	u32 *last_vblank;		/* protected by dev->vbl_lock, used */
					/* for wraparound handling */
	u32 *vblank_offset;		/* used to track how many vblanks */
	int *vblank_enabled;		/* so we don't call enable more than
					   once per disable */
	u32 *vblank_premodeset;		/*  were lost during modeset */
	struct timer_list vblank_disable_timer;

	unsigned long max_vblank_count; /**< size of vblank counter register */
	struct list_head vbl_sigs;		/**< signal list to send on VBLANK */
	struct list_head vbl_sigs2;	/**< signals to send on secondary VBLANK */
	unsigned int vbl_pending;
	spinlock_t tasklet_lock;	/**< For drm_locked_tasklet */
	void (*locked_tasklet_func)(struct drm_device *dev);

@@ -804,7 +756,6 @@ struct drm_device {
#ifdef __alpha__
	struct pci_controller *hose;
#endif
	int num_crtcs;			/**< Number of CRTCs on this device */
	struct drm_sg_mem *sg;	/**< Scatter gather memory */
	void *dev_private;		/**< device private data */
	struct drm_sigdata sigdata;	   /**< For block_all_signals */
@@ -1039,19 +990,11 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev);
extern void drm_driver_irq_postinstall(struct drm_device *dev);
extern void drm_driver_irq_uninstall(struct drm_device *dev);

extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp);
extern int drm_wait_vblank(struct drm_device *dev, void *data,
			   struct drm_file *file_priv);
extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
extern void drm_vbl_send_signals(struct drm_device *dev);
extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
extern void drm_update_vblank_count(struct drm_device *dev, int crtc);
extern void drm_handle_vblank(struct drm_device *dev, int crtc);
extern int drm_vblank_get(struct drm_device *dev, int crtc);
extern void drm_vblank_put(struct drm_device *dev, int crtc);

				/* Modesetting support */
extern int drm_modeset_ctl(struct drm_device *dev, void *data,
			   struct drm_file *file_priv);

				/* AGP/GART support (drm_agpsupport.h) */
extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
+56 −325
Original line number Diff line number Diff line
@@ -71,117 +71,6 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
	return 0;
}

static void vblank_disable_fn(unsigned long arg)
{
	struct drm_device *dev = (struct drm_device *)arg;
	unsigned long irqflags;
	int i;

	for (i = 0; i < dev->num_crtcs; i++) {
		spin_lock_irqsave(&dev->vbl_lock, irqflags);
		if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
		    dev->vblank_enabled[i]) {
			dev->driver->disable_vblank(dev, i);
			dev->vblank_enabled[i] = 0;
		}
		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
	}
}

static void drm_vblank_cleanup(struct drm_device *dev)
{
	/* Bail if the driver didn't call drm_vblank_init() */
	if (dev->num_crtcs == 0)
		return;

	del_timer(&dev->vblank_disable_timer);

	vblank_disable_fn((unsigned long)dev);

	drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
		 DRM_MEM_DRIVER);
	drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
		 DRM_MEM_DRIVER);
	drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
		 dev->num_crtcs, DRM_MEM_DRIVER);
	drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
		 dev->num_crtcs, DRM_MEM_DRIVER);
	drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
		 dev->num_crtcs, DRM_MEM_DRIVER);
	drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
		 DRM_MEM_DRIVER);
	drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
		 dev->num_crtcs, DRM_MEM_DRIVER);
	drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs,
		 DRM_MEM_DRIVER);

	dev->num_crtcs = 0;
}

int drm_vblank_init(struct drm_device *dev, int num_crtcs)
{
	int i, ret = -ENOMEM;

	setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
		    (unsigned long)dev);
	spin_lock_init(&dev->vbl_lock);
	atomic_set(&dev->vbl_signal_pending, 0);
	dev->num_crtcs = num_crtcs;

	dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
				   DRM_MEM_DRIVER);
	if (!dev->vbl_queue)
		goto err;

	dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
				  DRM_MEM_DRIVER);
	if (!dev->vbl_sigs)
		goto err;

	dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
				      DRM_MEM_DRIVER);
	if (!dev->_vblank_count)
		goto err;

	dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
					 DRM_MEM_DRIVER);
	if (!dev->vblank_refcount)
		goto err;

	dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
					 DRM_MEM_DRIVER);
	if (!dev->vblank_enabled)
		goto err;

	dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
	if (!dev->last_vblank)
		goto err;

	dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32),
					    DRM_MEM_DRIVER);
	if (!dev->vblank_premodeset)
		goto err;

	dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
	if (!dev->vblank_offset)
		goto err;

	/* Zero per-crtc vblank stuff */
	for (i = 0; i < num_crtcs; i++) {
		init_waitqueue_head(&dev->vbl_queue[i]);
		INIT_LIST_HEAD(&dev->vbl_sigs[i]);
		atomic_set(&dev->_vblank_count[i], 0);
		atomic_set(&dev->vblank_refcount[i], 0);
	}

	return 0;

err:
	drm_vblank_cleanup(dev);
	return ret;
}
EXPORT_SYMBOL(drm_vblank_init);

/**
 * Install IRQ handler.
 *
@@ -220,6 +109,17 @@ static int drm_irq_install(struct drm_device * dev)

	DRM_DEBUG("irq=%d\n", dev->irq);

	if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
		init_waitqueue_head(&dev->vbl_queue);

		spin_lock_init(&dev->vbl_lock);

		INIT_LIST_HEAD(&dev->vbl_sigs);
		INIT_LIST_HEAD(&dev->vbl_sigs2);

		dev->vbl_pending = 0;
	}

	/* Before installing handler */
	dev->driver->irq_preinstall(dev);

@@ -237,14 +137,9 @@ static int drm_irq_install(struct drm_device * dev)
	}

	/* After installing handler */
	ret = dev->driver->irq_postinstall(dev);
	if (ret < 0) {
		mutex_lock(&dev->struct_mutex);
		dev->irq_enabled = 0;
		mutex_unlock(&dev->struct_mutex);
	}
	dev->driver->irq_postinstall(dev);

	return ret;
	return 0;
}

/**
@@ -275,8 +170,6 @@ int drm_irq_uninstall(struct drm_device * dev)

	free_irq(dev->irq, dev);

	drm_vblank_cleanup(dev);

	dev->locked_tasklet_func = NULL;

	return 0;
@@ -320,148 +213,6 @@ int drm_control(struct drm_device *dev, void *data,
	}
}

/**
 * drm_vblank_count - retrieve "cooked" vblank counter value
 * @dev: DRM device
 * @crtc: which counter to retrieve
 *
 * Fetches the "cooked" vblank count value that represents the number of
 * vblank events since the system was booted, including lost events due to
 * modesetting activity.
 */
u32 drm_vblank_count(struct drm_device *dev, int crtc)
{
	return atomic_read(&dev->_vblank_count[crtc]) +
		dev->vblank_offset[crtc];
}
EXPORT_SYMBOL(drm_vblank_count);

/**
 * drm_update_vblank_count - update the master vblank counter
 * @dev: DRM device
 * @crtc: counter to update
 *
 * Call back into the driver to update the appropriate vblank counter
 * (specified by @crtc).  Deal with wraparound, if it occurred, and
 * update the last read value so we can deal with wraparound on the next
 * call if necessary.
 */
void drm_update_vblank_count(struct drm_device *dev, int crtc)
{
	unsigned long irqflags;
	u32 cur_vblank, diff;

	/*
	 * Interrupts were disabled prior to this call, so deal with counter
	 * wrap if needed.
	 * NOTE!  It's possible we lost a full dev->max_vblank_count events
	 * here if the register is small or we had vblank interrupts off for
	 * a long time.
	 */
	cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
	spin_lock_irqsave(&dev->vbl_lock, irqflags);
	if (cur_vblank < dev->last_vblank[crtc]) {
		diff = dev->max_vblank_count -
			dev->last_vblank[crtc];
		diff += cur_vblank;
	} else {
		diff = cur_vblank - dev->last_vblank[crtc];
	}
	dev->last_vblank[crtc] = cur_vblank;
	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);

	atomic_add(diff, &dev->_vblank_count[crtc]);
}
EXPORT_SYMBOL(drm_update_vblank_count);

/**
 * drm_vblank_get - get a reference count on vblank events
 * @dev: DRM device
 * @crtc: which CRTC to own
 *
 * Acquire a reference count on vblank events to avoid having them disabled
 * while in use.  Note callers will probably want to update the master counter
 * using drm_update_vblank_count() above before calling this routine so that
 * wakeups occur on the right vblank event.
 *
 * RETURNS
 * Zero on success, nonzero on failure.
 */
int drm_vblank_get(struct drm_device *dev, int crtc)
{
	unsigned long irqflags;
	int ret = 0;

	spin_lock_irqsave(&dev->vbl_lock, irqflags);
	/* Going from 0->1 means we have to enable interrupts again */
	if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
	    !dev->vblank_enabled[crtc]) {
		ret = dev->driver->enable_vblank(dev, crtc);
		if (ret)
			atomic_dec(&dev->vblank_refcount[crtc]);
		else
			dev->vblank_enabled[crtc] = 1;
	}
	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);

	return ret;
}
EXPORT_SYMBOL(drm_vblank_get);

/**
 * drm_vblank_put - give up ownership of vblank events
 * @dev: DRM device
 * @crtc: which counter to give up
 *
 * Release ownership of a given vblank counter, turning off interrupts
 * if possible.
 */
void drm_vblank_put(struct drm_device *dev, int crtc)
{
	/* Last user schedules interrupt disable */
	if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
	    mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
}
EXPORT_SYMBOL(drm_vblank_put);

/**
 * drm_modeset_ctl - handle vblank event counter changes across mode switch
 * @DRM_IOCTL_ARGS: standard ioctl arguments
 *
 * Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
 * ioctls around modesetting so that any lost vblank events are accounted for.
 */
int drm_modeset_ctl(struct drm_device *dev, void *data,
		    struct drm_file *file_priv)
{
	struct drm_modeset_ctl *modeset = data;
	int crtc, ret = 0;
	u32 new;

	crtc = modeset->arg;
	if (crtc >= dev->num_crtcs) {
		ret = -EINVAL;
		goto out;
	}

	switch (modeset->cmd) {
	case _DRM_PRE_MODESET:
		dev->vblank_premodeset[crtc] =
			dev->driver->get_vblank_counter(dev, crtc);
		break;
	case _DRM_POST_MODESET:
		new = dev->driver->get_vblank_counter(dev, crtc);
		dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new;
		break;
	default:
		ret = -EINVAL;
		break;
	}

out:
	return ret;
}

/**
 * Wait for VBLANK.
 *
@@ -481,13 +232,12 @@ out:
 *
 * If a signal is not requested, then calls vblank_wait().
 */
int drm_wait_vblank(struct drm_device *dev, void *data,
		    struct drm_file *file_priv)
int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
	union drm_wait_vblank *vblwait = data;
	struct timeval now;
	int ret = 0;
	unsigned int flags, seq, crtc;
	unsigned int flags, seq;

	if ((!dev->irq) || (!dev->irq_enabled))
		return -EINVAL;
@@ -501,13 +251,13 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
	}

	flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
	crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;

	if (crtc >= dev->num_crtcs)
	if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
				    DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
		return -EINVAL;

	drm_update_vblank_count(dev, crtc);
	seq = drm_vblank_count(dev, crtc);
	seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
			  : &dev->vbl_received);

	switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
	case _DRM_VBLANK_RELATIVE:
@@ -526,7 +276,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data,

	if (flags & _DRM_VBLANK_SIGNAL) {
		unsigned long irqflags;
		struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
		struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
				      ? &dev->vbl_sigs2 : &dev->vbl_sigs;
		struct drm_vbl_sig *vbl_sig;

		spin_lock_irqsave(&dev->vbl_lock, irqflags);
@@ -547,26 +298,22 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
			}
		}

		if (atomic_read(&dev->vbl_signal_pending) >= 100) {
		if (dev->vbl_pending >= 100) {
			spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
			return -EBUSY;
		}

		dev->vbl_pending++;

		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);

		vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),
				     DRM_MEM_DRIVER);
		if (!vbl_sig)
		if (!
		    (vbl_sig =
		     drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
			return -ENOMEM;

		ret = drm_vblank_get(dev, crtc);
		if (ret) {
			drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
				 DRM_MEM_DRIVER);
			return ret;
		}

		atomic_inc(&dev->vbl_signal_pending);
		memset((void *)vbl_sig, 0, sizeof(*vbl_sig));

		vbl_sig->sequence = vblwait->request.sequence;
		vbl_sig->info.si_signo = vblwait->request.signal;
@@ -580,20 +327,17 @@ int drm_wait_vblank(struct drm_device *dev, void *data,

		vblwait->reply.sequence = seq;
	} else {
		unsigned long cur_vblank;
		if (flags & _DRM_VBLANK_SECONDARY) {
			if (dev->driver->vblank_wait2)
				ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
		} else if (dev->driver->vblank_wait)
			ret =
			    dev->driver->vblank_wait(dev,
						     &vblwait->request.sequence);

		ret = drm_vblank_get(dev, crtc);
		if (ret)
			return ret;
		DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
			    (((cur_vblank = drm_vblank_count(dev, crtc))
			      - vblwait->request.sequence) <= (1 << 23)));
		drm_vblank_put(dev, crtc);
		do_gettimeofday(&now);

		vblwait->reply.tval_sec = now.tv_sec;
		vblwait->reply.tval_usec = now.tv_usec;
		vblwait->reply.sequence = cur_vblank;
	}

      done:
@@ -604,23 +348,23 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
 * Send the VBLANK signals.
 *
 * \param dev DRM device.
 * \param crtc CRTC where the vblank event occurred
 *
 * Sends a signal for each task in drm_device::vbl_sigs and empties the list.
 *
 * If a signal is not requested, then calls vblank_wait().
 */
static void drm_vbl_send_signals(struct drm_device * dev, int crtc)
void drm_vbl_send_signals(struct drm_device * dev)
{
	struct drm_vbl_sig *vbl_sig, *tmp;
	struct list_head *vbl_sigs;
	unsigned int vbl_seq;
	unsigned long flags;
	int i;

	spin_lock_irqsave(&dev->vbl_lock, flags);

	vbl_sigs = &dev->vbl_sigs[crtc];
	vbl_seq = drm_vblank_count(dev, crtc);
	for (i = 0; i < 2; i++) {
		struct drm_vbl_sig *vbl_sig, *tmp;
		struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
		unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
						   &dev->vbl_received);

		list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
			if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
@@ -632,29 +376,16 @@ static void drm_vbl_send_signals(struct drm_device * dev, int crtc)

				drm_free(vbl_sig, sizeof(*vbl_sig),
					 DRM_MEM_DRIVER);
		atomic_dec(&dev->vbl_signal_pending);
		drm_vblank_put(dev, crtc);

				dev->vbl_pending--;
			}
		}
	}

	spin_unlock_irqrestore(&dev->vbl_lock, flags);
}

/**
 * drm_handle_vblank - handle a vblank event
 * @dev: DRM device
 * @crtc: where this event occurred
 *
 * Drivers should call this routine in their vblank interrupt handlers to
 * update the vblank counter and send any signals that may be pending.
 */
void drm_handle_vblank(struct drm_device *dev, int crtc)
{
	drm_update_vblank_count(dev, crtc);
	DRM_WAKEUP(&dev->vbl_queue[crtc]);
	drm_vbl_send_signals(dev, crtc);
}
EXPORT_SYMBOL(drm_handle_vblank);
EXPORT_SYMBOL(drm_vbl_send_signals);

/**
 * Tasklet wrapper function.
+41 −119

File changed.

Preview size limit exceeded, changes collapsed.

+9 −36
Original line number Diff line number Diff line
@@ -105,29 +105,14 @@ typedef struct _drm_i915_sarea {
	unsigned int rotated_tiled;
	unsigned int rotated2_tiled;

	int planeA_x;
	int planeA_y;
	int planeA_w;
	int planeA_h;
	int planeB_x;
	int planeB_y;
	int planeB_w;
	int planeB_h;

	/* Triple buffering */
	drm_handle_t third_handle;
	int third_offset;
	int third_size;
	unsigned int third_tiled;

	/* buffer object handles for the static buffers.  May change
	 * over the lifetime of the client, though it doesn't in our current
	 * implementation.
	 */
	unsigned int front_bo_handle;
	unsigned int back_bo_handle;
	unsigned int third_bo_handle;
	unsigned int depth_bo_handle;
	int pipeA_x;
	int pipeA_y;
	int pipeA_w;
	int pipeA_h;
	int pipeB_x;
	int pipeB_y;
	int pipeB_w;
	int pipeB_h;
} drm_i915_sarea_t;

/* Flags for perf_boxes
@@ -161,7 +146,7 @@ typedef struct _drm_i915_sarea {

#define DRM_IOCTL_I915_INIT		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
#define DRM_IOCTL_I915_FLIP		DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FLIP, drm_i915_flip_t)
#define DRM_IOCTL_I915_FLIP		DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
#define DRM_IOCTL_I915_BATCHBUFFER	DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
#define DRM_IOCTL_I915_IRQ_EMIT         DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
#define DRM_IOCTL_I915_IRQ_WAIT         DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
@@ -176,18 +161,6 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GET_VBLANK_PIPE	DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
#define DRM_IOCTL_I915_VBLANK_SWAP	DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)

/* Asynchronous page flipping:
 */
typedef struct drm_i915_flip {
	/*
	 * This is really talking about planes, and we could rename it
	 * except for the fact that some of the duplicated i915_drm.h files
	 * out there check for HAVE_I915_FLIP and so might pick up this
	 * version.
	 */
	int pipes;
} drm_i915_flip_t;

/* Allow drivers to submit batchbuffers directly to hardware, relying
 * on the security mechanisms provided by hardware.
 */
Loading