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

Commit 8639dad8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm/i915: Save/restore HWS_PGA on suspend/resume
  drm: move drm vblank initialization/cleanup to driver load/unload
  drm/i915: execbuffer pins objects, no need to ensure they're still in the GTT
  drm/i915: Always read pipestat in irq_handler
  drm/i915: Subtract total pinned bytes from available aperture size
  drm/i915: Avoid BUG_ONs on VT switch with a wedged chipset.
  drm/i915: Remove IMR masking during interrupt handler, and restart it if needed.
  drm/i915: Manage PIPESTAT to control vblank interrupts instead of IMR.
parents 9297524f 461cba2d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -305,6 +305,8 @@ static void drm_cleanup(struct drm_device * dev)
		return;
	}

	drm_vblank_cleanup(dev);

	drm_lastclose(dev);

	if (drm_core_has_MTRR(dev) && drm_core_has_AGP(dev) &&
+1 −3
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ static void vblank_disable_fn(unsigned long arg)
	}
}

static void drm_vblank_cleanup(struct drm_device *dev)
void drm_vblank_cleanup(struct drm_device *dev)
{
	/* Bail if the driver didn't call drm_vblank_init() */
	if (dev->num_crtcs == 0)
@@ -278,8 +278,6 @@ int drm_irq_uninstall(struct drm_device * dev)

	free_irq(dev->pdev->irq, dev);

	drm_vblank_cleanup(dev);

	return 0;
}
EXPORT_SYMBOL(drm_irq_uninstall);
+7 −0
Original line number Diff line number Diff line
@@ -856,6 +856,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)

	spin_lock_init(&dev_priv->user_irq_lock);

	ret = drm_vblank_init(dev, I915_NUM_PIPE);

	if (ret) {
		(void) i915_driver_unload(dev);
		return ret;
	}

	return ret;
}

+11 −0
Original line number Diff line number Diff line
@@ -47,6 +47,8 @@ enum pipe {
	PIPE_B,
};

#define I915_NUM_PIPE	2

/* Interface history:
 *
 * 1.1: Original.
@@ -132,6 +134,7 @@ typedef struct drm_i915_private {
	int user_irq_refcount;
	/** Cached value of IMR to avoid reads in updating the bitfield */
	u32 irq_mask_reg;
	u32 pipestat[2];

	int tex_lru_log_granularity;
	int allow_batchbuffer;
@@ -147,6 +150,7 @@ typedef struct drm_i915_private {
	u32 saveDSPBCNTR;
	u32 saveDSPARB;
	u32 saveRENDERSTANDBY;
	u32 saveHWS;
	u32 savePIPEACONF;
	u32 savePIPEBCONF;
	u32 savePIPEASRC;
@@ -446,6 +450,13 @@ extern int i915_vblank_swap(struct drm_device *dev, void *data,
			    struct drm_file *file_priv);
extern void i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask);

void
i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);

void
i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);


/* i915_mem.c */
extern int i915_mem_alloc(struct drm_device *dev, void *data,
			  struct drm_file *file_priv);
+41 −33
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@
#include "i915_drv.h"
#include <linux/swap.h>

#define I915_GEM_GPU_DOMAINS	(~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))

static int
i915_gem_object_set_domain(struct drm_gem_object *obj,
			    uint32_t read_domains,
@@ -83,20 +85,14 @@ int
i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
			    struct drm_file *file_priv)
{
	drm_i915_private_t *dev_priv = dev->dev_private;
	struct drm_i915_gem_get_aperture *args = data;
	struct drm_i915_gem_object *obj_priv;

	if (!(dev->driver->driver_features & DRIVER_GEM))
		return -ENODEV;

	args->aper_size = dev->gtt_total;
	args->aper_available_size = args->aper_size;

	list_for_each_entry(obj_priv, &dev_priv->mm.active_list, list) {
		if (obj_priv->pin_count > 0)
			args->aper_available_size -= obj_priv->obj->size;
	}
	args->aper_available_size = (args->aper_size -
				     atomic_read(&dev->pin_memory));

	return 0;
}
@@ -1870,17 +1866,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,

	for (i = 0; i < args->buffer_count; i++) {
		struct drm_gem_object *obj = object_list[i];
		struct drm_i915_gem_object *obj_priv = obj->driver_private;

		if (obj_priv->gtt_space == NULL) {
			/* We evicted the buffer in the process of validating
			 * our set of buffers in.  We could try to recover by
			 * kicking them everything out and trying again from
			 * the start.
			 */
			ret = -ENOMEM;
			goto err;
		}

		/* make sure all previous memory operations have passed */
		ret = i915_gem_object_set_domain(obj,
@@ -2299,29 +2284,52 @@ i915_gem_idle(struct drm_device *dev)

	i915_gem_retire_requests(dev);

	if (!dev_priv->mm.wedged) {
		/* Active and flushing should now be empty as we've
		 * waited for a sequence higher than any pending execbuffer
		 */
	BUG_ON(!list_empty(&dev_priv->mm.active_list));
	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));

		WARN_ON(!list_empty(&dev_priv->mm.active_list));
		WARN_ON(!list_empty(&dev_priv->mm.flushing_list));
		/* Request should now be empty as we've also waited
		 * for the last request in the list
		 */
	BUG_ON(!list_empty(&dev_priv->mm.request_list));
		WARN_ON(!list_empty(&dev_priv->mm.request_list));
	}

	/* Move all buffers out of the GTT. */
	/* Empty the active and flushing lists to inactive.  If there's
	 * anything left at this point, it means that we're wedged and
	 * nothing good's going to happen by leaving them there.  So strip
	 * the GPU domains and just stuff them onto inactive.
	 */
	while (!list_empty(&dev_priv->mm.active_list)) {
		struct drm_i915_gem_object *obj_priv;

		obj_priv = list_first_entry(&dev_priv->mm.active_list,
					    struct drm_i915_gem_object,
					    list);
		obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
		i915_gem_object_move_to_inactive(obj_priv->obj);
	}

	while (!list_empty(&dev_priv->mm.flushing_list)) {
		struct drm_i915_gem_object *obj_priv;

		obj_priv = list_first_entry(&dev_priv->mm.active_list,
					    struct drm_i915_gem_object,
					    list);
		obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
		i915_gem_object_move_to_inactive(obj_priv->obj);
	}


	/* Move all inactive buffers out of the GTT. */
	ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
	WARN_ON(!list_empty(&dev_priv->mm.inactive_list));
	if (ret) {
		mutex_unlock(&dev->struct_mutex);
		return ret;
	}

	BUG_ON(!list_empty(&dev_priv->mm.active_list));
	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
	BUG_ON(!list_empty(&dev_priv->mm.request_list));

	i915_gem_cleanup_ringbuffer(dev);
	mutex_unlock(&dev->struct_mutex);

Loading