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: Ben Widawsky <benjamin.widawsky@intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
615aaa5f96
commit
c9cddffc66
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue