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

Commit c9cddffc authored by Jesse Barnes's avatar Jesse Barnes Committed by Daniel Vetter
Browse files

drm/i915: BIOS and power context stolen mem handling for VLV v7



But we need to get the right stolen base and make pre-allocated objects
for BIOS stuff so we don't clobber it.  If the BIOS hasn't allocated a
power context, we allocate one here too, from stolen space as required
by the docs.

v2: fix stolen to phys if ladder (Ben)
    keep BIOS reserved space out of allocator altogether (Ben)
v3: fix mask of stolen base (Ben)
v4: clean up preallocated object on unload (Ben)
    don't zero reg on unload (Jesse)
    fix mask harder (Jesse)
v5: use unref for freeing stolen bits (Chris)
    move alloc/free to intel_pm.c (Chris)
v6: NULL pctx at disable time so error paths work (Ben)
v7: use correct PCI device for config read (Jesse)

Reviewed-by: default avatarBen Widawsky <benjamin.widawsky@intel.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 615aaa5f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1073,6 +1073,8 @@ typedef struct drm_i915_private {

	struct i915_gpu_error gpu_error;

	struct drm_i915_gem_object *vlv_pctx;

	/* list of fbdev register on this device */
	struct intel_fbdev *fbdev;

+10 −2
Original line number Diff line number Diff line
@@ -62,7 +62,10 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
	 * its value of TOLUD.
	 */
	base = 0;
	if (INTEL_INFO(dev)->gen >= 6) {
	if (IS_VALLEYVIEW(dev)) {
		pci_read_config_dword(dev->pdev, 0x5c, &base);
		base &= ~((1<<20) - 1);
	} else if (INTEL_INFO(dev)->gen >= 6) {
		/* Read Base Data of Stolen Memory Register (BDSM) directly.
		 * Note that there is also a MCHBAR miror at 0x1080c0 or
		 * we could use device 2:0x5c instead.
@@ -183,6 +186,7 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
int i915_gem_init_stolen(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	int bios_reserved = 0;

	dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
	if (dev_priv->mm.stolen_base == 0)
@@ -191,8 +195,12 @@ int i915_gem_init_stolen(struct drm_device *dev)
	DRM_DEBUG_KMS("found %zd bytes of stolen memory at %08lx\n",
		      dev_priv->gtt.stolen_size, dev_priv->mm.stolen_base);

	if (IS_VALLEYVIEW(dev))
		bios_reserved = 1024*1024; /* top 1M on VLV/BYT */

	/* Basic memrange allocator for stolen space */
	drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size);
	drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size -
		    bios_reserved);

	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -700,6 +700,7 @@
#define VLV_IIR		(VLV_DISPLAY_BASE + 0x20a4)
#define VLV_IMR		(VLV_DISPLAY_BASE + 0x20a8)
#define VLV_ISR		(VLV_DISPLAY_BASE + 0x20ac)
#define VLV_PCBR	(VLV_DISPLAY_BASE + 0x2120)
#define   I915_PIPE_CONTROL_NOTIFY_INTERRUPT		(1<<18)
#define   I915_DISPLAY_PORT_INTERRUPT			(1<<17)
#define   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT	(1<<15)
+49 −0
Original line number Diff line number Diff line
@@ -2566,6 +2566,11 @@ static void valleyview_disable_rps(struct drm_device *dev)
	spin_unlock_irq(&dev_priv->rps.lock);

	I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));

	if (dev_priv->vlv_pctx) {
		drm_gem_object_unreference(&dev_priv->vlv_pctx->base);
		dev_priv->vlv_pctx = NULL;
	}
}

int intel_enable_rc6(const struct drm_device *dev)
@@ -2860,6 +2865,48 @@ static void vlv_rps_timer_work(struct work_struct *work)
	mutex_unlock(&dev_priv->rps.hw_lock);
}

static void valleyview_setup_pctx(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_gem_object *pctx;
	unsigned long pctx_paddr;
	u32 pcbr;
	int pctx_size = 24*1024;

	pcbr = I915_READ(VLV_PCBR);
	if (pcbr) {
		/* BIOS set it up already, grab the pre-alloc'd space */
		int pcbr_offset;

		pcbr_offset = (pcbr & (~4095)) - dev_priv->mm.stolen_base;
		pctx = i915_gem_object_create_stolen_for_preallocated(dev_priv->dev,
								      pcbr_offset,
								      pcbr_offset,
								      pctx_size);
		goto out;
	}

	/*
	 * From the Gunit register HAS:
	 * The Gfx driver is expected to program this register and ensure
	 * proper allocation within Gfx stolen memory.  For example, this
	 * register should be programmed such than the PCBR range does not
	 * overlap with other ranges, such as the frame buffer, protected
	 * memory, or any other relevant ranges.
	 */
	pctx = i915_gem_object_create_stolen(dev, pctx_size);
	if (!pctx) {
		DRM_DEBUG("not enough stolen space for PCTX, disabling\n");
		return;
	}

	pctx_paddr = dev_priv->mm.stolen_base + pctx->stolen->start;
	I915_WRITE(VLV_PCBR, pctx_paddr);

out:
	dev_priv->vlv_pctx = pctx;
}

static void valleyview_enable_rps(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2874,6 +2921,8 @@ static void valleyview_enable_rps(struct drm_device *dev)
		I915_WRITE(GTFIFODBG, gtfifodbg);
	}

	valleyview_setup_pctx(dev);

	gen6_gt_force_wake_get(dev_priv);

	I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400);