Skip to content

Commit

Permalink
drm/i915: BIOS and power context stolen mem handling for VLV v7
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Jesse Barnes authored and Daniel Vetter committed May 10, 2013
1 parent 615aaa5 commit c9cddff
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 2 deletions.
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
12 changes: 10 additions & 2 deletions drivers/gpu/drm/i915/i915_gem_stolen.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand All @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/i915_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
49 changes: 49 additions & 0 deletions drivers/gpu/drm/i915/intel_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down

0 comments on commit c9cddff

Please sign in to comment.