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 i915_gpu_error gpu_error;
|
||||||
|
|
||||||
|
struct drm_i915_gem_object *vlv_pctx;
|
||||||
|
|
||||||
/* list of fbdev register on this device */
|
/* list of fbdev register on this device */
|
||||||
struct intel_fbdev *fbdev;
|
struct intel_fbdev *fbdev;
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,10 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
|
||||||
* its value of TOLUD.
|
* its value of TOLUD.
|
||||||
*/
|
*/
|
||||||
base = 0;
|
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.
|
/* Read Base Data of Stolen Memory Register (BDSM) directly.
|
||||||
* Note that there is also a MCHBAR miror at 0x1080c0 or
|
* Note that there is also a MCHBAR miror at 0x1080c0 or
|
||||||
* we could use device 2:0x5c instead.
|
* 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)
|
int i915_gem_init_stolen(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||||
|
int bios_reserved = 0;
|
||||||
|
|
||||||
dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
|
dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
|
||||||
if (dev_priv->mm.stolen_base == 0)
|
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",
|
DRM_DEBUG_KMS("found %zd bytes of stolen memory at %08lx\n",
|
||||||
dev_priv->gtt.stolen_size, dev_priv->mm.stolen_base);
|
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 */
|
/* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -700,6 +700,7 @@
|
||||||
#define VLV_IIR (VLV_DISPLAY_BASE + 0x20a4)
|
#define VLV_IIR (VLV_DISPLAY_BASE + 0x20a4)
|
||||||
#define VLV_IMR (VLV_DISPLAY_BASE + 0x20a8)
|
#define VLV_IMR (VLV_DISPLAY_BASE + 0x20a8)
|
||||||
#define VLV_ISR (VLV_DISPLAY_BASE + 0x20ac)
|
#define VLV_ISR (VLV_DISPLAY_BASE + 0x20ac)
|
||||||
|
#define VLV_PCBR (VLV_DISPLAY_BASE + 0x2120)
|
||||||
#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18)
|
#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18)
|
||||||
#define I915_DISPLAY_PORT_INTERRUPT (1<<17)
|
#define I915_DISPLAY_PORT_INTERRUPT (1<<17)
|
||||||
#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15)
|
#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);
|
spin_unlock_irq(&dev_priv->rps.lock);
|
||||||
|
|
||||||
I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
|
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)
|
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);
|
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)
|
static void valleyview_enable_rps(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
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);
|
I915_WRITE(GTFIFODBG, gtfifodbg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
valleyview_setup_pctx(dev);
|
||||||
|
|
||||||
gen6_gt_force_wake_get(dev_priv);
|
gen6_gt_force_wake_get(dev_priv);
|
||||||
|
|
||||||
I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400);
|
I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400);
|
||||||
|
|
Loading…
Reference in New Issue