Commit 9c4ce97d authored by Chris Wilson's avatar Chris Wilson

drm/i915/display: Be explicit in handling the preallocated vma

As only the display codes tries to pin its preallocated framebuffer into
an exact location in the GGTT, remove the convenience function and make
the pin management explicit in the display code. Then throughout the
display management, we track the framebuffer and its plane->vma; with
less single purpose code and ready for first class i915_vma.

In doing so, this should fix the BUG_ON(vma->pages) on fi-kbl-soraka.
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200204094801.877288-2-chris@chris-wilson.co.uk
parent 1586f620
...@@ -3389,6 +3389,67 @@ int skl_format_to_fourcc(int format, bool rgb_order, bool alpha) ...@@ -3389,6 +3389,67 @@ int skl_format_to_fourcc(int format, bool rgb_order, bool alpha)
} }
} }
static struct i915_vma *
initial_plane_vma(struct drm_i915_private *i915,
struct intel_initial_plane_config *plane_config)
{
struct drm_i915_gem_object *obj;
struct i915_vma *vma;
u32 base, size;
if (plane_config->size == 0)
return NULL;
base = round_down(plane_config->base,
I915_GTT_MIN_ALIGNMENT);
size = round_up(plane_config->base + plane_config->size,
I915_GTT_MIN_ALIGNMENT);
size -= base;
/*
* If the FB is too big, just don't use it since fbdev is not very
* important and we should probably use that space with FBC or other
* features.
*/
if (size * 2 > i915->stolen_usable_size)
return NULL;
obj = i915_gem_object_create_stolen_for_preallocated(i915, base, size);
if (IS_ERR(obj))
return NULL;
switch (plane_config->tiling) {
case I915_TILING_NONE:
break;
case I915_TILING_X:
case I915_TILING_Y:
obj->tiling_and_stride =
plane_config->fb->base.pitches[0] |
plane_config->tiling;
break;
default:
MISSING_CASE(plane_config->tiling);
goto err_obj;
}
vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
if (IS_ERR(vma))
goto err_obj;
if (i915_ggtt_pin(vma, 0, PIN_MAPPABLE | PIN_OFFSET_FIXED | base))
goto err_obj;
if (i915_gem_object_is_tiled(obj) &&
!i915_vma_is_map_and_fenceable(vma))
goto err_obj;
return vma;
err_obj:
i915_gem_object_put(obj);
return NULL;
}
static bool static bool
intel_alloc_initial_plane_obj(struct intel_crtc *crtc, intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
struct intel_initial_plane_config *plane_config) struct intel_initial_plane_config *plane_config)
...@@ -3397,22 +3458,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, ...@@ -3397,22 +3458,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_mode_fb_cmd2 mode_cmd = { 0 }; struct drm_mode_fb_cmd2 mode_cmd = { 0 };
struct drm_framebuffer *fb = &plane_config->fb->base; struct drm_framebuffer *fb = &plane_config->fb->base;
u32 base_aligned = round_down(plane_config->base, PAGE_SIZE); struct i915_vma *vma;
u32 size_aligned = round_up(plane_config->base + plane_config->size,
PAGE_SIZE);
struct drm_i915_gem_object *obj;
bool ret = false;
size_aligned -= base_aligned;
if (plane_config->size == 0)
return false;
/* If the FB is too big, just don't use it since fbdev is not very
* important and we should probably use that space with FBC or other
* features. */
if (size_aligned * 2 > dev_priv->stolen_usable_size)
return false;
switch (fb->modifier) { switch (fb->modifier) {
case DRM_FORMAT_MOD_LINEAR: case DRM_FORMAT_MOD_LINEAR:
...@@ -3426,25 +3472,10 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, ...@@ -3426,25 +3472,10 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
return false; return false;
} }
obj = i915_gem_object_create_stolen_for_preallocated(dev_priv, vma = initial_plane_vma(dev_priv, plane_config);
base_aligned, if (!vma)
base_aligned,
size_aligned);
if (IS_ERR(obj))
return false; return false;
switch (plane_config->tiling) {
case I915_TILING_NONE:
break;
case I915_TILING_X:
case I915_TILING_Y:
obj->tiling_and_stride = fb->pitches[0] | plane_config->tiling;
break;
default:
MISSING_CASE(plane_config->tiling);
goto out;
}
mode_cmd.pixel_format = fb->format->format; mode_cmd.pixel_format = fb->format->format;
mode_cmd.width = fb->width; mode_cmd.width = fb->width;
mode_cmd.height = fb->height; mode_cmd.height = fb->height;
...@@ -3452,17 +3483,18 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, ...@@ -3452,17 +3483,18 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc,
mode_cmd.modifier[0] = fb->modifier; mode_cmd.modifier[0] = fb->modifier;
mode_cmd.flags = DRM_MODE_FB_MODIFIERS; mode_cmd.flags = DRM_MODE_FB_MODIFIERS;
if (intel_framebuffer_init(to_intel_framebuffer(fb), obj, &mode_cmd)) { if (intel_framebuffer_init(to_intel_framebuffer(fb),
vma->obj, &mode_cmd)) {
drm_dbg_kms(&dev_priv->drm, "intel fb init failed\n"); drm_dbg_kms(&dev_priv->drm, "intel fb init failed\n");
goto out; goto err_vma;
} }
plane_config->vma = vma;
return true;
drm_dbg_kms(&dev_priv->drm, "initial plane fb obj %p\n", obj); err_vma:
ret = true; i915_vma_put(vma);
out: return false;
i915_gem_object_put(obj);
return ret;
} }
static void static void
...@@ -3561,12 +3593,14 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, ...@@ -3561,12 +3593,14 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
struct intel_plane_state *intel_state = struct intel_plane_state *intel_state =
to_intel_plane_state(plane_state); to_intel_plane_state(plane_state);
struct drm_framebuffer *fb; struct drm_framebuffer *fb;
struct i915_vma *vma;
if (!plane_config->fb) if (!plane_config->fb)
return; return;
if (intel_alloc_initial_plane_obj(intel_crtc, plane_config)) { if (intel_alloc_initial_plane_obj(intel_crtc, plane_config)) {
fb = &plane_config->fb->base; fb = &plane_config->fb->base;
vma = plane_config->vma;
goto valid_fb; goto valid_fb;
} }
...@@ -3589,6 +3623,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, ...@@ -3589,6 +3623,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
if (intel_plane_ggtt_offset(state) == plane_config->base) { if (intel_plane_ggtt_offset(state) == plane_config->base) {
fb = state->hw.fb; fb = state->hw.fb;
vma = state->vma;
goto valid_fb; goto valid_fb;
} }
} }
...@@ -3611,21 +3646,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, ...@@ -3611,21 +3646,11 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
intel_state->color_plane[0].stride = intel_state->color_plane[0].stride =
intel_fb_pitch(fb, 0, intel_state->hw.rotation); intel_fb_pitch(fb, 0, intel_state->hw.rotation);
intel_state->vma = __i915_vma_pin(vma);
intel_pin_and_fence_fb_obj(fb, intel_state->vma = i915_vma_get(vma);
&intel_state->view, if (intel_plane_uses_fence(intel_state) && i915_vma_pin_fence(vma) == 0)
intel_plane_uses_fence(intel_state), if (vma->fence)
&intel_state->flags); intel_state->flags |= PLANE_HAS_FENCE;
if (IS_ERR(intel_state->vma)) {
drm_err(&dev_priv->drm,
"failed to pin boot fb on pipe %d: %li\n",
intel_crtc->pipe, PTR_ERR(intel_state->vma));
intel_state->vma = NULL;
return;
}
intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_DIRTYFB);
plane_state->src_x = 0; plane_state->src_x = 0;
plane_state->src_y = 0; plane_state->src_y = 0;
...@@ -3649,6 +3674,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, ...@@ -3649,6 +3674,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
plane_state->crtc = &intel_crtc->base; plane_state->crtc = &intel_crtc->base;
intel_plane_copy_uapi_to_hw_state(intel_state, intel_state); intel_plane_copy_uapi_to_hw_state(intel_state, intel_state);
intel_frontbuffer_flush(to_intel_frontbuffer(fb), ORIGIN_DIRTYFB);
atomic_or(to_intel_plane(primary)->frontbuffer_bit, atomic_or(to_intel_plane(primary)->frontbuffer_bit,
&to_intel_frontbuffer(fb)->bits); &to_intel_frontbuffer(fb)->bits);
} }
...@@ -17863,6 +17890,9 @@ static void plane_config_fini(struct intel_initial_plane_config *plane_config) ...@@ -17863,6 +17890,9 @@ static void plane_config_fini(struct intel_initial_plane_config *plane_config)
else else
kfree(fb); kfree(fb);
} }
if (plane_config->vma)
i915_vma_put(plane_config->vma);
} }
int intel_modeset_init(struct drm_i915_private *i915) int intel_modeset_init(struct drm_i915_private *i915)
......
...@@ -592,6 +592,7 @@ struct intel_plane_state { ...@@ -592,6 +592,7 @@ struct intel_plane_state {
struct intel_initial_plane_config { struct intel_initial_plane_config {
struct intel_framebuffer *fb; struct intel_framebuffer *fb;
struct i915_vma *vma;
unsigned int tiling; unsigned int tiling;
int size; int size;
u32 base; u32 base;
......
...@@ -686,28 +686,24 @@ struct intel_memory_region *i915_gem_stolen_setup(struct drm_i915_private *i915) ...@@ -686,28 +686,24 @@ struct intel_memory_region *i915_gem_stolen_setup(struct drm_i915_private *i915)
struct drm_i915_gem_object * struct drm_i915_gem_object *
i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915, i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915,
resource_size_t stolen_offset, resource_size_t stolen_offset,
resource_size_t gtt_offset,
resource_size_t size) resource_size_t size)
{ {
struct intel_memory_region *mem = i915->mm.regions[INTEL_REGION_STOLEN]; struct intel_memory_region *mem = i915->mm.regions[INTEL_REGION_STOLEN];
struct i915_ggtt *ggtt = &i915->ggtt;
struct drm_i915_gem_object *obj; struct drm_i915_gem_object *obj;
struct drm_mm_node *stolen; struct drm_mm_node *stolen;
struct i915_vma *vma;
int ret; int ret;
if (!drm_mm_initialized(&i915->mm.stolen)) if (!drm_mm_initialized(&i915->mm.stolen))
return ERR_PTR(-ENODEV); return ERR_PTR(-ENODEV);
drm_dbg(&i915->drm, drm_dbg(&i915->drm,
"creating preallocated stolen object: stolen_offset=%pa, gtt_offset=%pa, size=%pa\n", "creating preallocated stolen object: stolen_offset=%pa, size=%pa\n",
&stolen_offset, &gtt_offset, &size); &stolen_offset, &size);
/* KISS and expect everything to be page-aligned */ /* KISS and expect everything to be page-aligned */
if (drm_WARN_ON(&i915->drm, size == 0) || if (GEM_WARN_ON(size == 0) ||
drm_WARN_ON(&i915->drm, !IS_ALIGNED(size, I915_GTT_PAGE_SIZE)) || GEM_WARN_ON(!IS_ALIGNED(size, I915_GTT_PAGE_SIZE)) ||
drm_WARN_ON(&i915->drm, GEM_WARN_ON(!IS_ALIGNED(stolen_offset, I915_GTT_MIN_ALIGNMENT)))
!IS_ALIGNED(stolen_offset, I915_GTT_MIN_ALIGNMENT)))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
stolen = kzalloc(sizeof(*stolen), GFP_KERNEL); stolen = kzalloc(sizeof(*stolen), GFP_KERNEL);
...@@ -720,68 +716,20 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915, ...@@ -720,68 +716,20 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915,
ret = drm_mm_reserve_node(&i915->mm.stolen, stolen); ret = drm_mm_reserve_node(&i915->mm.stolen, stolen);
mutex_unlock(&i915->mm.stolen_lock); mutex_unlock(&i915->mm.stolen_lock);
if (ret) { if (ret) {
drm_dbg(&i915->drm, "failed to allocate stolen space\n"); obj = ERR_PTR(ret);
kfree(stolen); goto err_free;
return ERR_PTR(ret);
} }
obj = __i915_gem_object_create_stolen(mem, stolen); obj = __i915_gem_object_create_stolen(mem, stolen);
if (IS_ERR(obj)) { if (IS_ERR(obj))
drm_dbg(&i915->drm, "failed to allocate stolen object\n"); goto err_stolen;
i915_gem_stolen_remove_node(i915, stolen);
kfree(stolen);
return obj;
}
/* Some objects just need physical mem from stolen space */
if (gtt_offset == I915_GTT_OFFSET_NONE)
return obj;
ret = i915_gem_object_pin_pages(obj);
if (ret)
goto err;
vma = i915_vma_instance(obj, &ggtt->vm, NULL);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto err_pages;
}
/* To simplify the initialisation sequence between KMS and GTT,
* we allow construction of the stolen object prior to
* setting up the GTT space. The actual reservation will occur
* later.
*/
mutex_lock(&ggtt->vm.mutex);
ret = i915_gem_gtt_reserve(&ggtt->vm, &vma->node,
size, gtt_offset, obj->cache_level,
0);
if (ret) {
drm_dbg(&i915->drm, "failed to allocate stolen GTT space\n");
mutex_unlock(&ggtt->vm.mutex);
goto err_pages;
}
GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));
GEM_BUG_ON(vma->pages);
vma->pages = obj->mm.pages;
atomic_set(&vma->pages_count, I915_VMA_PAGES_ACTIVE);
set_bit(I915_VMA_GLOBAL_BIND_BIT, __i915_vma_flags(vma));
__i915_vma_set_map_and_fenceable(vma);
list_add_tail(&vma->vm_link, &ggtt->vm.bound_list);
mutex_unlock(&ggtt->vm.mutex);
GEM_BUG_ON(i915_gem_object_is_shrinkable(obj));
atomic_inc(&obj->bind_count);
i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE);
return obj; return obj;
err_pages: err_stolen:
i915_gem_object_unpin_pages(obj); i915_gem_stolen_remove_node(i915, stolen);
err: err_free:
i915_gem_object_put(obj); kfree(stolen);
return ERR_PTR(ret); return obj;
} }
...@@ -28,7 +28,6 @@ i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, ...@@ -28,7 +28,6 @@ i915_gem_object_create_stolen(struct drm_i915_private *dev_priv,
struct drm_i915_gem_object * struct drm_i915_gem_object *
i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv, i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv,
resource_size_t stolen_offset, resource_size_t stolen_offset,
resource_size_t gtt_offset,
resource_size_t size); resource_size_t size);
#endif /* __I915_GEM_STOLEN_H__ */ #endif /* __I915_GEM_STOLEN_H__ */
...@@ -296,7 +296,6 @@ static int vlv_rc6_init(struct intel_rc6 *rc6) ...@@ -296,7 +296,6 @@ static int vlv_rc6_init(struct intel_rc6 *rc6)
pcbr_offset = (pcbr & ~4095) - i915->dsm.start; pcbr_offset = (pcbr & ~4095) - i915->dsm.start;
pctx = i915_gem_object_create_stolen_for_preallocated(i915, pctx = i915_gem_object_create_stolen_for_preallocated(i915,
pcbr_offset, pcbr_offset,
I915_GTT_OFFSET_NONE,
pctx_size); pctx_size);
if (IS_ERR(pctx)) if (IS_ERR(pctx))
return PTR_ERR(pctx); return PTR_ERR(pctx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment