From 5f521722a2a2391d693afccdf6e12be2754382d8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 7 Sep 2018 12:28:51 +0100 Subject: drm/i915: Missed interrupt simulation is no more, tell the world Using the guc, we cannot disable the user interrupt generation as we use it for driving submission. And from Icelake, we no longer have the ability to individually mask interrupt generation from each engine, disabling our ability to fake missed interrupts. In both cases, report back to userspace that the missed interrupt generator is no longer available. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180907112856.28242-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_debugfs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1f7051e97afb..b4744a68cd88 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -4117,6 +4117,17 @@ i915_ring_test_irq_set(void *data, u64 val) { struct drm_i915_private *i915 = data; + /* GuC keeps the user interrupt permanently enabled for submission */ + if (USES_GUC_SUBMISSION(i915)) + return -ENODEV; + + /* + * From icl, we can no longer individually mask interrupt generation + * from each engine. + */ + if (INTEL_GEN(i915) >= 11) + return -ENODEV; + val &= INTEL_INFO(i915)->ring_mask; DRM_DEBUG_DRIVER("Masking interrupts on rings 0x%08llx\n", val); -- cgit From b84d9ab0b7239b22cb9a079e54b01f69b37bc211 Mon Sep 17 00:00:00 2001 From: Michal Wajdeczko Date: Mon, 10 Sep 2018 10:41:49 +0000 Subject: drm/i915/guc: Update GuC power domain states We should update GuC power domain states also when GuC submission is disabled, otherwise GuC might complain or ignore our requests. This seems to be required for all currently released GuC firmwares. v2: it is only needed by pre-Gen11 firmwares Signed-off-by: Michal Wajdeczko Cc: John Spotswood Cc: Anusha Srivatsa Cc: Tomasz Lis Cc: Daniele Ceraolo Spurio Reviewed-by: Anusha Srivatsa Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180910104150.101752-1-michal.wajdeczko@intel.com --- drivers/gpu/drm/i915/intel_uc.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c index 7c95697e1a35..b1b3e81b6e24 100644 --- a/drivers/gpu/drm/i915/intel_uc.c +++ b/drivers/gpu/drm/i915/intel_uc.c @@ -401,6 +401,10 @@ int intel_uc_init_hw(struct drm_i915_private *i915) ret = intel_guc_submission_enable(guc); if (ret) goto err_communication; + } else if (INTEL_GEN(i915) < 11) { + ret = intel_guc_sample_forcewake(guc); + if (ret) + goto err_communication; } dev_info(i915->drm.dev, "GuC firmware version %u.%u\n", -- cgit From c59d2da8ec189489a30b351d7fdb5923bcb9ca5f Mon Sep 17 00:00:00 2001 From: P Raviraj Sitaram Date: Mon, 10 Sep 2018 19:57:14 +0530 Subject: drm/i915/chv: Update csc coefficient matrix during modeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During modeset, previously configured csc coefficient matrix,if any, will not persist. This can result in blank screen as csc mode will be programmed while loading LUT but csc coefficient matrix remains unprogrammed. Changes since V1: - Removed platform check Signed-off-by: P Raviraj Sitaram Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/1536589634-29680-1-git-send-email-raviraj.p.sitaram@intel.com --- drivers/gpu/drm/i915/intel_display.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1c7321dadd84..ba8a955c4cd2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6013,6 +6013,8 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, i9xx_set_pipeconf(intel_crtc); + intel_color_set_csc(&pipe_config->base); + intel_crtc->active = true; intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); -- cgit From c8124d399224d626728e2ffb95a1d564a7c06968 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 6 Sep 2018 20:01:43 +0100 Subject: drm/i915/overlay: Allocate physical registers from stolen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given that we are now reasonably confident in our ability to detect and reserve the stolen memory (physical memory reserved for graphics by the BIOS) for ourselves on most machines, we can put it to use. In this case, we need a page to hold the overlay registers. On an i915g running MythTv, H Buus noticed that commit 6a2c4232ece145d8b5a8f95f767bd6d0d2d2f2bb Author: Chris Wilson Date: Tue Nov 4 04:51:40 2014 -0800 drm/i915: Make the physical object coherent with GTT introduced stuttering into his video playback. After discarding the likely suspect of it being the physical cursor updates, we were left with the use of the phys object for the overlay. And lo, if we completely avoid using the phys object (allocated just once on module load!) by switching to stolen memory, the stuttering goes away. For lack of a better explanation, claim victory and kill two birds with one stone. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107600 Fixes: 6a2c4232ece1 ("drm/i915: Make the physical object coherent with GTT") Signed-off-by: Chris Wilson Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180906190144.1272-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_overlay.c | 228 ++++++++++++----------------------- 1 file changed, 75 insertions(+), 153 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index c2f10d899329..443dfaefd7a6 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -181,8 +181,9 @@ struct intel_overlay { u32 brightness, contrast, saturation; u32 old_xscale, old_yscale; /* register access */ - u32 flip_addr; struct drm_i915_gem_object *reg_bo; + struct overlay_registers __iomem *regs; + u32 flip_addr; /* flip handling */ struct i915_gem_active last_flip; }; @@ -210,29 +211,6 @@ static void i830_overlay_clock_gating(struct drm_i915_private *dev_priv, PCI_DEVFN(0, 0), I830_CLOCK_GATE, val); } -static struct overlay_registers __iomem * -intel_overlay_map_regs(struct intel_overlay *overlay) -{ - struct drm_i915_private *dev_priv = overlay->i915; - struct overlay_registers __iomem *regs; - - if (OVERLAY_NEEDS_PHYSICAL(dev_priv)) - regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr; - else - regs = io_mapping_map_wc(&dev_priv->ggtt.iomap, - overlay->flip_addr, - PAGE_SIZE); - - return regs; -} - -static void intel_overlay_unmap_regs(struct intel_overlay *overlay, - struct overlay_registers __iomem *regs) -{ - if (!OVERLAY_NEEDS_PHYSICAL(overlay->i915)) - io_mapping_unmap(regs); -} - static void intel_overlay_submit_request(struct intel_overlay *overlay, struct i915_request *rq, i915_gem_retire_fn retire) @@ -784,13 +762,13 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, struct drm_i915_gem_object *new_bo, struct put_image_params *params) { - int ret, tmp_width; - struct overlay_registers __iomem *regs; - bool scale_changed = false; + struct overlay_registers __iomem *regs = overlay->regs; struct drm_i915_private *dev_priv = overlay->i915; u32 swidth, swidthsw, sheight, ostride; enum pipe pipe = overlay->crtc->pipe; + bool scale_changed = false; struct i915_vma *vma; + int ret, tmp_width; lockdep_assert_held(&dev_priv->drm.struct_mutex); WARN_ON(!drm_modeset_is_locked(&dev_priv->drm.mode_config.connection_mutex)); @@ -815,30 +793,19 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, if (!overlay->active) { u32 oconfig; - regs = intel_overlay_map_regs(overlay); - if (!regs) { - ret = -ENOMEM; - goto out_unpin; - } + oconfig = OCONF_CC_OUT_8BIT; if (IS_GEN4(dev_priv)) oconfig |= OCONF_CSC_MODE_BT709; oconfig |= pipe == 0 ? OCONF_PIPE_A : OCONF_PIPE_B; iowrite32(oconfig, ®s->OCONFIG); - intel_overlay_unmap_regs(overlay, regs); ret = intel_overlay_on(overlay); if (ret != 0) goto out_unpin; } - regs = intel_overlay_map_regs(overlay); - if (!regs) { - ret = -ENOMEM; - goto out_unpin; - } - iowrite32((params->dst_y << 16) | params->dst_x, ®s->DWINPOS); iowrite32((params->dst_h << 16) | params->dst_w, ®s->DWINSZ); @@ -882,8 +849,6 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, iowrite32(overlay_cmd_reg(params), ®s->OCMD); - intel_overlay_unmap_regs(overlay, regs); - ret = intel_overlay_continue(overlay, vma, scale_changed); if (ret) goto out_unpin; @@ -901,7 +866,6 @@ out_pin_section: int intel_overlay_switch_off(struct intel_overlay *overlay) { struct drm_i915_private *dev_priv = overlay->i915; - struct overlay_registers __iomem *regs; int ret; lockdep_assert_held(&dev_priv->drm.struct_mutex); @@ -918,9 +882,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay) if (ret != 0) return ret; - regs = intel_overlay_map_regs(overlay); - iowrite32(0, ®s->OCMD); - intel_overlay_unmap_regs(overlay, regs); + iowrite32(0, &overlay->regs->OCMD); return intel_overlay_off(overlay); } @@ -1305,7 +1267,6 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data, struct drm_intel_overlay_attrs *attrs = data; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_overlay *overlay; - struct overlay_registers __iomem *regs; int ret; overlay = dev_priv->overlay; @@ -1345,15 +1306,7 @@ int intel_overlay_attrs_ioctl(struct drm_device *dev, void *data, overlay->contrast = attrs->contrast; overlay->saturation = attrs->saturation; - regs = intel_overlay_map_regs(overlay); - if (!regs) { - ret = -ENOMEM; - goto out_unlock; - } - - update_reg_attrs(overlay, regs); - - intel_overlay_unmap_regs(overlay, regs); + update_reg_attrs(overlay, overlay->regs); if (attrs->flags & I915_OVERLAY_UPDATE_GAMMA) { if (IS_GEN2(dev_priv)) @@ -1386,12 +1339,47 @@ out_unlock: return ret; } +static int get_registers(struct intel_overlay *overlay, bool use_phys) +{ + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + int err; + + obj = i915_gem_object_create_stolen(overlay->i915, PAGE_SIZE); + if (obj == NULL) + obj = i915_gem_object_create_internal(overlay->i915, PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto err_put_bo; + } + + if (use_phys) + overlay->flip_addr = sg_dma_address(obj->mm.pages->sgl); + else + overlay->flip_addr = i915_ggtt_offset(vma); + overlay->regs = i915_vma_pin_iomap(vma); + i915_vma_unpin(vma); + + if (IS_ERR(overlay->regs)) { + err = PTR_ERR(overlay->regs); + goto err_put_bo; + } + + overlay->reg_bo = obj; + return 0; + +err_put_bo: + i915_gem_object_put(obj); + return err; +} + void intel_setup_overlay(struct drm_i915_private *dev_priv) { struct intel_overlay *overlay; - struct drm_i915_gem_object *reg_bo; - struct overlay_registers __iomem *regs; - struct i915_vma *vma = NULL; int ret; if (!HAS_OVERLAY(dev_priv)) @@ -1401,46 +1389,8 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv) if (!overlay) return; - mutex_lock(&dev_priv->drm.struct_mutex); - if (WARN_ON(dev_priv->overlay)) - goto out_free; - overlay->i915 = dev_priv; - reg_bo = NULL; - if (!OVERLAY_NEEDS_PHYSICAL(dev_priv)) - reg_bo = i915_gem_object_create_stolen(dev_priv, PAGE_SIZE); - if (reg_bo == NULL) - reg_bo = i915_gem_object_create(dev_priv, PAGE_SIZE); - if (IS_ERR(reg_bo)) - goto out_free; - overlay->reg_bo = reg_bo; - - if (OVERLAY_NEEDS_PHYSICAL(dev_priv)) { - ret = i915_gem_object_attach_phys(reg_bo, PAGE_SIZE); - if (ret) { - DRM_ERROR("failed to attach phys overlay regs\n"); - goto out_free_bo; - } - overlay->flip_addr = reg_bo->phys_handle->busaddr; - } else { - vma = i915_gem_object_ggtt_pin(reg_bo, NULL, - 0, PAGE_SIZE, PIN_MAPPABLE); - if (IS_ERR(vma)) { - DRM_ERROR("failed to pin overlay register bo\n"); - ret = PTR_ERR(vma); - goto out_free_bo; - } - overlay->flip_addr = i915_ggtt_offset(vma); - - ret = i915_gem_object_set_to_gtt_domain(reg_bo, true); - if (ret) { - DRM_ERROR("failed to move overlay register bo into the GTT\n"); - goto out_unpin_bo; - } - } - - /* init all values */ overlay->color_key = 0x0101fe; overlay->color_key_enabled = true; overlay->brightness = -19; @@ -1449,44 +1399,51 @@ void intel_setup_overlay(struct drm_i915_private *dev_priv) init_request_active(&overlay->last_flip, NULL); - regs = intel_overlay_map_regs(overlay); - if (!regs) - goto out_unpin_bo; + mutex_lock(&dev_priv->drm.struct_mutex); + + ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(dev_priv)); + if (ret) + goto out_free; + + ret = i915_gem_object_set_to_gtt_domain(overlay->reg_bo, true); + if (ret) + goto out_reg_bo; - memset_io(regs, 0, sizeof(struct overlay_registers)); - update_polyphase_filter(regs); - update_reg_attrs(overlay, regs); + mutex_unlock(&dev_priv->drm.struct_mutex); - intel_overlay_unmap_regs(overlay, regs); + memset_io(overlay->regs, 0, sizeof(struct overlay_registers)); + update_polyphase_filter(overlay->regs); + update_reg_attrs(overlay, overlay->regs); dev_priv->overlay = overlay; - mutex_unlock(&dev_priv->drm.struct_mutex); - DRM_INFO("initialized overlay support\n"); + DRM_INFO("Initialized overlay support.\n"); return; -out_unpin_bo: - if (vma) - i915_vma_unpin(vma); -out_free_bo: - i915_gem_object_put(reg_bo); +out_reg_bo: + i915_gem_object_put(overlay->reg_bo); out_free: mutex_unlock(&dev_priv->drm.struct_mutex); kfree(overlay); - return; } void intel_cleanup_overlay(struct drm_i915_private *dev_priv) { - if (!dev_priv->overlay) + struct intel_overlay *overlay; + + overlay = fetch_and_zero(&dev_priv->overlay); + if (!overlay) return; - /* The bo's should be free'd by the generic code already. + /* + * The bo's should be free'd by the generic code already. * Furthermore modesetting teardown happens beforehand so the - * hardware should be off already */ - WARN_ON(dev_priv->overlay->active); + * hardware should be off already. + */ + WARN_ON(overlay->active); + + i915_gem_object_put(overlay->reg_bo); - i915_gem_object_put(dev_priv->overlay->reg_bo); - kfree(dev_priv->overlay); + kfree(overlay); } #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) @@ -1498,37 +1455,11 @@ struct intel_overlay_error_state { u32 isr; }; -static struct overlay_registers __iomem * -intel_overlay_map_regs_atomic(struct intel_overlay *overlay) -{ - struct drm_i915_private *dev_priv = overlay->i915; - struct overlay_registers __iomem *regs; - - if (OVERLAY_NEEDS_PHYSICAL(dev_priv)) - /* Cast to make sparse happy, but it's wc memory anyway, so - * equivalent to the wc io mapping on X86. */ - regs = (struct overlay_registers __iomem *) - overlay->reg_bo->phys_handle->vaddr; - else - regs = io_mapping_map_atomic_wc(&dev_priv->ggtt.iomap, - overlay->flip_addr); - - return regs; -} - -static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay, - struct overlay_registers __iomem *regs) -{ - if (!OVERLAY_NEEDS_PHYSICAL(overlay->i915)) - io_mapping_unmap_atomic(regs); -} - struct intel_overlay_error_state * intel_overlay_capture_error_state(struct drm_i915_private *dev_priv) { struct intel_overlay *overlay = dev_priv->overlay; struct intel_overlay_error_state *error; - struct overlay_registers __iomem *regs; if (!overlay || !overlay->active) return NULL; @@ -1541,18 +1472,9 @@ intel_overlay_capture_error_state(struct drm_i915_private *dev_priv) error->isr = I915_READ(ISR); error->base = overlay->flip_addr; - regs = intel_overlay_map_regs_atomic(overlay); - if (!regs) - goto err; - - memcpy_fromio(&error->regs, regs, sizeof(struct overlay_registers)); - intel_overlay_unmap_regs_atomic(overlay, regs); + memcpy_fromio(&error->regs, overlay->regs, sizeof(error->regs)); return error; - -err: - kfree(error); - return NULL; } void -- cgit From f9055e74f8976e47ccd81d7988cb491b5dc75339 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 6 Sep 2018 20:01:44 +0100 Subject: drm/i915/overlay: Use the ioctl parameters directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The user parameters to put_image are not copied back to userspace (DRM_IOW), and so we can modify the ioctl parameters (having already been copied to a temporary kernel struct) directly and use those in place, avoiding another temporary malloc and lots of manual copying. Signed-off-by: Chris Wilson Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180906190144.1272-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_overlay.c | 147 +++++++++++++---------------------- 1 file changed, 54 insertions(+), 93 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 443dfaefd7a6..72eb7e48e8bc 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -487,23 +487,6 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv) overlay->active = false; } -struct put_image_params { - int format; - short dst_x; - short dst_y; - short dst_w; - short dst_h; - short src_w; - short src_scan_h; - short src_scan_w; - short src_h; - short stride_Y; - short stride_UV; - int offset_Y; - int offset_U; - int offset_V; -}; - static int packed_depth_bytes(u32 format) { switch (format & I915_OVERLAY_DEPTH_MASK) { @@ -618,25 +601,25 @@ static void update_polyphase_filter(struct overlay_registers __iomem *regs) static bool update_scaling_factors(struct intel_overlay *overlay, struct overlay_registers __iomem *regs, - struct put_image_params *params) + struct drm_intel_overlay_put_image *params) { /* fixed point with a 12 bit shift */ u32 xscale, yscale, xscale_UV, yscale_UV; #define FP_SHIFT 12 #define FRACT_MASK 0xfff bool scale_changed = false; - int uv_hscale = uv_hsubsampling(params->format); - int uv_vscale = uv_vsubsampling(params->format); + int uv_hscale = uv_hsubsampling(params->flags); + int uv_vscale = uv_vsubsampling(params->flags); - if (params->dst_w > 1) - xscale = ((params->src_scan_w - 1) << FP_SHIFT) - /(params->dst_w); + if (params->dst_width > 1) + xscale = ((params->src_scan_width - 1) << FP_SHIFT) / + params->dst_width; else xscale = 1 << FP_SHIFT; - if (params->dst_h > 1) - yscale = ((params->src_scan_h - 1) << FP_SHIFT) - /(params->dst_h); + if (params->dst_height > 1) + yscale = ((params->src_scan_height - 1) << FP_SHIFT) / + params->dst_height; else yscale = 1 << FP_SHIFT; @@ -713,12 +696,12 @@ static void update_colorkey(struct intel_overlay *overlay, iowrite32(flags, ®s->DCLRKM); } -static u32 overlay_cmd_reg(struct put_image_params *params) +static u32 overlay_cmd_reg(struct drm_intel_overlay_put_image *params) { u32 cmd = OCMD_ENABLE | OCMD_BUF_TYPE_FRAME | OCMD_BUFFER0; - if (params->format & I915_OVERLAY_YUV_PLANAR) { - switch (params->format & I915_OVERLAY_DEPTH_MASK) { + if (params->flags & I915_OVERLAY_YUV_PLANAR) { + switch (params->flags & I915_OVERLAY_DEPTH_MASK) { case I915_OVERLAY_YUV422: cmd |= OCMD_YUV_422_PLANAR; break; @@ -731,7 +714,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params) break; } } else { /* YUV packed */ - switch (params->format & I915_OVERLAY_DEPTH_MASK) { + switch (params->flags & I915_OVERLAY_DEPTH_MASK) { case I915_OVERLAY_YUV422: cmd |= OCMD_YUV_422_PACKED; break; @@ -740,7 +723,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params) break; } - switch (params->format & I915_OVERLAY_SWAP_MASK) { + switch (params->flags & I915_OVERLAY_SWAP_MASK) { case I915_OVERLAY_NO_SWAP: break; case I915_OVERLAY_UV_SWAP: @@ -760,7 +743,7 @@ static u32 overlay_cmd_reg(struct put_image_params *params) static int intel_overlay_do_put_image(struct intel_overlay *overlay, struct drm_i915_gem_object *new_bo, - struct put_image_params *params) + struct drm_intel_overlay_put_image *params) { struct overlay_registers __iomem *regs = overlay->regs; struct drm_i915_private *dev_priv = overlay->i915; @@ -806,35 +789,40 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay, goto out_unpin; } - iowrite32((params->dst_y << 16) | params->dst_x, ®s->DWINPOS); - iowrite32((params->dst_h << 16) | params->dst_w, ®s->DWINSZ); + iowrite32(params->dst_y << 16 | params->dst_x, ®s->DWINPOS); + iowrite32(params->dst_height << 16 | params->dst_width, ®s->DWINSZ); - if (params->format & I915_OVERLAY_YUV_PACKED) - tmp_width = packed_width_bytes(params->format, params->src_w); + if (params->flags & I915_OVERLAY_YUV_PACKED) + tmp_width = packed_width_bytes(params->flags, + params->src_width); else - tmp_width = params->src_w; + tmp_width = params->src_width; - swidth = params->src_w; + swidth = params->src_width; swidthsw = calc_swidthsw(dev_priv, params->offset_Y, tmp_width); - sheight = params->src_h; + sheight = params->src_height; iowrite32(i915_ggtt_offset(vma) + params->offset_Y, ®s->OBUF_0Y); ostride = params->stride_Y; - if (params->format & I915_OVERLAY_YUV_PLANAR) { - int uv_hscale = uv_hsubsampling(params->format); - int uv_vscale = uv_vsubsampling(params->format); + if (params->flags & I915_OVERLAY_YUV_PLANAR) { + int uv_hscale = uv_hsubsampling(params->flags); + int uv_vscale = uv_vsubsampling(params->flags); u32 tmp_U, tmp_V; - swidth |= (params->src_w/uv_hscale) << 16; + + swidth |= (params->src_width / uv_hscale) << 16; + sheight |= (params->src_height / uv_vscale) << 16; + tmp_U = calc_swidthsw(dev_priv, params->offset_U, - params->src_w/uv_hscale); + params->src_width / uv_hscale); tmp_V = calc_swidthsw(dev_priv, params->offset_V, - params->src_w/uv_hscale); - swidthsw |= max_t(u32, tmp_U, tmp_V) << 16; - sheight |= (params->src_h/uv_vscale) << 16; + params->src_width / uv_hscale); + swidthsw |= max(tmp_U, tmp_V) << 16; + iowrite32(i915_ggtt_offset(vma) + params->offset_U, ®s->OBUF_0U); iowrite32(i915_ggtt_offset(vma) + params->offset_V, ®s->OBUF_0V); + ostride |= params->stride_UV << 16; } @@ -938,15 +926,16 @@ static int check_overlay_dst(struct intel_overlay *overlay, return -EINVAL; } -static int check_overlay_scaling(struct put_image_params *rec) +static int check_overlay_scaling(struct drm_intel_overlay_put_image *rec) { u32 tmp; /* downscaling limit is 8.0 */ - tmp = ((rec->src_scan_h << 16) / rec->dst_h) >> 16; + tmp = ((rec->src_scan_height << 16) / rec->dst_height) >> 16; if (tmp > 7) return -EINVAL; - tmp = ((rec->src_scan_w << 16) / rec->dst_w) >> 16; + + tmp = ((rec->src_scan_width << 16) / rec->dst_width) >> 16; if (tmp > 7) return -EINVAL; @@ -1067,13 +1056,12 @@ static int check_overlay_src(struct drm_i915_private *dev_priv, int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_intel_overlay_put_image *put_image_rec = data; + struct drm_intel_overlay_put_image *params = data; struct drm_i915_private *dev_priv = to_i915(dev); struct intel_overlay *overlay; struct drm_crtc *drmmode_crtc; struct intel_crtc *crtc; struct drm_i915_gem_object *new_bo; - struct put_image_params *params; int ret; overlay = dev_priv->overlay; @@ -1082,7 +1070,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, return -ENODEV; } - if (!(put_image_rec->flags & I915_OVERLAY_ENABLE)) { + if (!(params->flags & I915_OVERLAY_ENABLE)) { drm_modeset_lock_all(dev); mutex_lock(&dev->struct_mutex); @@ -1094,22 +1082,14 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, return ret; } - params = kmalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - - drmmode_crtc = drm_crtc_find(dev, file_priv, put_image_rec->crtc_id); - if (!drmmode_crtc) { - ret = -ENOENT; - goto out_free; - } + drmmode_crtc = drm_crtc_find(dev, file_priv, params->crtc_id); + if (!drmmode_crtc) + return -ENOENT; crtc = to_intel_crtc(drmmode_crtc); - new_bo = i915_gem_object_lookup(file_priv, put_image_rec->bo_handle); - if (!new_bo) { - ret = -ENOENT; - goto out_free; - } + new_bo = i915_gem_object_lookup(file_priv, params->bo_handle); + if (!new_bo) + return -ENOENT; drm_modeset_lock_all(dev); mutex_lock(&dev->struct_mutex); @@ -1145,42 +1125,27 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, overlay->pfit_active = false; } - ret = check_overlay_dst(overlay, put_image_rec); + ret = check_overlay_dst(overlay, params); if (ret != 0) goto out_unlock; if (overlay->pfit_active) { - params->dst_y = ((((u32)put_image_rec->dst_y) << 12) / + params->dst_y = (((u32)params->dst_y << 12) / overlay->pfit_vscale_ratio); /* shifting right rounds downwards, so add 1 */ - params->dst_h = ((((u32)put_image_rec->dst_height) << 12) / + params->dst_height = (((u32)params->dst_height << 12) / overlay->pfit_vscale_ratio) + 1; - } else { - params->dst_y = put_image_rec->dst_y; - params->dst_h = put_image_rec->dst_height; } - params->dst_x = put_image_rec->dst_x; - params->dst_w = put_image_rec->dst_width; - - params->src_w = put_image_rec->src_width; - params->src_h = put_image_rec->src_height; - params->src_scan_w = put_image_rec->src_scan_width; - params->src_scan_h = put_image_rec->src_scan_height; - if (params->src_scan_h > params->src_h || - params->src_scan_w > params->src_w) { + + if (params->src_scan_height > params->src_height || + params->src_scan_width > params->src_width) { ret = -EINVAL; goto out_unlock; } - ret = check_overlay_src(dev_priv, put_image_rec, new_bo); + ret = check_overlay_src(dev_priv, params, new_bo); if (ret != 0) goto out_unlock; - params->format = put_image_rec->flags & ~I915_OVERLAY_FLAGS_MASK; - params->stride_Y = put_image_rec->stride_Y; - params->stride_UV = put_image_rec->stride_UV; - params->offset_Y = put_image_rec->offset_Y; - params->offset_U = put_image_rec->offset_U; - params->offset_V = put_image_rec->offset_V; /* Check scaling after src size to prevent a divide-by-zero. */ ret = check_overlay_scaling(params); @@ -1195,16 +1160,12 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, drm_modeset_unlock_all(dev); i915_gem_object_put(new_bo); - kfree(params); - return 0; out_unlock: mutex_unlock(&dev->struct_mutex); drm_modeset_unlock_all(dev); i915_gem_object_put(new_bo); -out_free: - kfree(params); return ret; } -- cgit From 146cdf3fad9c4b4653a4dfc6c79619c62ab27c15 Mon Sep 17 00:00:00 2001 From: Madhav Chauhan Date: Tue, 10 Jul 2018 15:10:05 +0530 Subject: drm/i915/icl: Define T_INIT_MASTER registers This patch defines DSI_T_INIT_MASTER register for DSI ports 0/1 which will be used in dphy programming. Signed-off-by: Madhav Chauhan Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/1531215614-6828-5-git-send-email-madhav.chauhan@intel.com --- drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 09bc8e730ee1..c80e56959e21 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -10231,6 +10231,12 @@ enum skl_power_gate { #define PREPARE_COUNT_SHIFT 0 #define PREPARE_COUNT_MASK (0x3f << 0) +#define _ICL_DSI_T_INIT_MASTER_0 0x6b088 +#define _ICL_DSI_T_INIT_MASTER_1 0x6b888 +#define ICL_DSI_T_INIT_MASTER(port) _MMIO_PORT(port, \ + _ICL_DSI_T_INIT_MASTER_0,\ + _ICL_DSI_T_INIT_MASTER_1) + /* bits 31:0 */ #define _MIPIA_DBI_BW_CTRL (dev_priv->mipi_mmio_base + 0xb084) #define _MIPIC_DBI_BW_CTRL (dev_priv->mipi_mmio_base + 0xb884) -- cgit From d3f3e5e438d3ce47505db8b0a63d55629e48167e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 11 Sep 2018 14:22:06 +0100 Subject: drm/i915: Nuke struct_mutex from context_setparam Userspace should be free to race against itself and shoot itself in the foot if it so desires to adjust a parameter at the same time as submitting a batch to that context. As such, the struct_mutex in context setparam is only being used to serialise userspace against itself and not for any protection of internal structs and so is superfluous. v2: Separate user_flags from internal flags to reduce chance of interference; and use locked bit ops for user updates. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180911132206.23032-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_context.c | 20 +++++++----------- drivers/gpu/drm/i915/i915_gem_context.h | 33 +++++++++++++++++------------- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- 3 files changed, 27 insertions(+), 28 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 747b8170a15a..f772593b99ab 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -862,7 +862,7 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, ret = -EINVAL; break; case I915_CONTEXT_PARAM_NO_ZEROMAP: - args->value = ctx->flags & CONTEXT_NO_ZEROMAP; + args->value = test_bit(UCONTEXT_NO_ZEROMAP, &ctx->user_flags); break; case I915_CONTEXT_PARAM_GTT_SIZE: if (ctx->ppgtt) @@ -896,27 +896,23 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, struct drm_i915_file_private *file_priv = file->driver_priv; struct drm_i915_gem_context_param *args = data; struct i915_gem_context *ctx; - int ret; + int ret = 0; ctx = i915_gem_context_lookup(file_priv, args->ctx_id); if (!ctx) return -ENOENT; - ret = i915_mutex_lock_interruptible(dev); - if (ret) - goto out; - switch (args->param) { case I915_CONTEXT_PARAM_BAN_PERIOD: ret = -EINVAL; break; case I915_CONTEXT_PARAM_NO_ZEROMAP: - if (args->size) { + if (args->size) ret = -EINVAL; - } else { - ctx->flags &= ~CONTEXT_NO_ZEROMAP; - ctx->flags |= args->value ? CONTEXT_NO_ZEROMAP : 0; - } + else if (args->value) + set_bit(UCONTEXT_NO_ZEROMAP, &ctx->user_flags); + else + clear_bit(UCONTEXT_NO_ZEROMAP, &ctx->user_flags); break; case I915_CONTEXT_PARAM_NO_ERROR_CAPTURE: if (args->size) @@ -960,9 +956,7 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, ret = -EINVAL; break; } - mutex_unlock(&dev->struct_mutex); -out: i915_gem_context_put(ctx); return ret; } diff --git a/drivers/gpu/drm/i915/i915_gem_context.h b/drivers/gpu/drm/i915/i915_gem_context.h index e09673ca731d..08165f6a0a84 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.h +++ b/drivers/gpu/drm/i915/i915_gem_context.h @@ -116,16 +116,21 @@ struct i915_gem_context { */ struct rcu_head rcu; + /** + * @user_flags: small set of booleans controlled by the user + */ + unsigned long user_flags; +#define UCONTEXT_NO_ZEROMAP 0 +#define UCONTEXT_NO_ERROR_CAPTURE 1 +#define UCONTEXT_BANNABLE 2 + /** * @flags: small set of booleans */ unsigned long flags; -#define CONTEXT_NO_ZEROMAP BIT(0) -#define CONTEXT_NO_ERROR_CAPTURE 1 -#define CONTEXT_CLOSED 2 -#define CONTEXT_BANNABLE 3 -#define CONTEXT_BANNED 4 -#define CONTEXT_FORCE_SINGLE_SUBMISSION 5 +#define CONTEXT_BANNED 0 +#define CONTEXT_CLOSED 1 +#define CONTEXT_FORCE_SINGLE_SUBMISSION 2 /** * @hw_id: - unique identifier for the context @@ -209,37 +214,37 @@ static inline bool i915_gem_context_is_closed(const struct i915_gem_context *ctx static inline void i915_gem_context_set_closed(struct i915_gem_context *ctx) { GEM_BUG_ON(i915_gem_context_is_closed(ctx)); - __set_bit(CONTEXT_CLOSED, &ctx->flags); + set_bit(CONTEXT_CLOSED, &ctx->flags); } static inline bool i915_gem_context_no_error_capture(const struct i915_gem_context *ctx) { - return test_bit(CONTEXT_NO_ERROR_CAPTURE, &ctx->flags); + return test_bit(UCONTEXT_NO_ERROR_CAPTURE, &ctx->user_flags); } static inline void i915_gem_context_set_no_error_capture(struct i915_gem_context *ctx) { - __set_bit(CONTEXT_NO_ERROR_CAPTURE, &ctx->flags); + set_bit(UCONTEXT_NO_ERROR_CAPTURE, &ctx->user_flags); } static inline void i915_gem_context_clear_no_error_capture(struct i915_gem_context *ctx) { - __clear_bit(CONTEXT_NO_ERROR_CAPTURE, &ctx->flags); + clear_bit(UCONTEXT_NO_ERROR_CAPTURE, &ctx->user_flags); } static inline bool i915_gem_context_is_bannable(const struct i915_gem_context *ctx) { - return test_bit(CONTEXT_BANNABLE, &ctx->flags); + return test_bit(UCONTEXT_BANNABLE, &ctx->user_flags); } static inline void i915_gem_context_set_bannable(struct i915_gem_context *ctx) { - __set_bit(CONTEXT_BANNABLE, &ctx->flags); + set_bit(UCONTEXT_BANNABLE, &ctx->user_flags); } static inline void i915_gem_context_clear_bannable(struct i915_gem_context *ctx) { - __clear_bit(CONTEXT_BANNABLE, &ctx->flags); + clear_bit(UCONTEXT_BANNABLE, &ctx->user_flags); } static inline bool i915_gem_context_is_banned(const struct i915_gem_context *ctx) @@ -249,7 +254,7 @@ static inline bool i915_gem_context_is_banned(const struct i915_gem_context *ctx static inline void i915_gem_context_set_banned(struct i915_gem_context *ctx) { - __set_bit(CONTEXT_BANNED, &ctx->flags); + set_bit(CONTEXT_BANNED, &ctx->flags); } static inline bool i915_gem_context_force_single_submission(const struct i915_gem_context *ctx) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 7d0b3a2c30e2..094c3b1cf202 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -743,7 +743,7 @@ static int eb_select_context(struct i915_execbuffer *eb) } eb->context_flags = 0; - if (ctx->flags & CONTEXT_NO_ZEROMAP) + if (test_bit(UCONTEXT_NO_ZEROMAP, &ctx->user_flags)) eb->context_flags |= __EXEC_OBJECT_NEEDS_BIAS; return 0; -- cgit From e2a13d1b24073fe183ebe858ebb4fc827faded56 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 10 Sep 2018 14:08:08 +0100 Subject: drm/i915/ringbuffer: Reload PDs harder on byt/bcs Baytrail takes a little more convincing that it needs to actually reload its Page Directoy (ppGTT) before the context switch, so repeat it until it gets the message. Once again the arbitrary values here are empirically derived. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107861 Testcase: igt/gem_exec_parallel/fds Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20180910130808.10809-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_ringbuffer.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 472939f5c18f..d0ef50bf930a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1677,9 +1677,26 @@ static int switch_context(struct i915_request *rq) GEM_BUG_ON(HAS_EXECLISTS(rq->i915)); if (ppgtt) { - ret = load_pd_dir(rq, ppgtt); - if (ret) - goto err; + int loops; + + /* + * Baytail takes a little more convincing that it really needs + * to reload the PD between contexts. It is not just a little + * longer, as adding more stalls after the load_pd_dir (i.e. + * adding a long loop around flush_pd_dir) is not as effective + * as reloading the PD umpteen times. 32 is derived from + * experimentation (gem_exec_parallel/fds) and has no good + * explanation. + */ + loops = 1; + if (engine->id == BCS && IS_VALLEYVIEW(engine->i915)) + loops = 32; + + do { + ret = load_pd_dir(rq, ppgtt); + if (ret) + goto err; + } while (--loops); if (intel_engine_flag(engine) & ppgtt->pd_dirty_rings) { unwind_mm = intel_engine_flag(engine); -- cgit From 35e882a4441e73c347aab2c42559e55a1d857fa1 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 12 Sep 2018 11:11:33 +0100 Subject: drm/i915: Reorder execobject[] to insert non-48b objects into the low 4G If the caller supplies more than 4G of objects and than one that has to be in the low 4G, it is possible for the low 4G to be full before we attempt to find room for the last object that must be there. As we don't reorder the two types, every pass hits the same problem and we fail with ENOSPC. However, if we impose a little bit of ordering between the two classes of objects, on the second pass we will be able to fit the special object as we do it first. For setups that only use !48b objects, we now reverse the order between passes, hopefully making the subsequent passes more likely to succeed given that we are trying a different order (rather than repeating the previous pass!) v2: Quick one line explanation for the relative priorities given to reservations. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20180912101133.31377-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 094c3b1cf202..bb0980793b48 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -693,9 +693,14 @@ static int eb_reserve(struct i915_execbuffer *eb) eb_unreserve_vma(vma, &eb->flags[i]); if (flags & EXEC_OBJECT_PINNED) + /* Pinned must have their slot */ list_add(&vma->exec_link, &eb->unbound); else if (flags & __EXEC_OBJECT_NEEDS_MAP) + /* Map require the lowest 256MiB (aperture) */ list_add_tail(&vma->exec_link, &eb->unbound); + else if (!(flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS)) + /* Prioritise 4GiB region for restricted bo */ + list_add(&vma->exec_link, &last); else list_add_tail(&vma->exec_link, &last); } -- cgit From 6d19a44ccee6aa7a4c65375d0e8284afee98f3b9 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:01 +0300 Subject: drm/i915: s/tile_offset/aligned_offset/ etc. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename some of the tile_offset() functions to aligned_offset() since they operate on both linear and tiled functions. And we'll include _plane_ in the name of all the variants that take a plane state. Should make it more clear which function to use where. v2: Pimp the patch subject a bit (José) Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-2-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 123 ++++++++++++++++++----------------- drivers/gpu/drm/i915/intel_drv.h | 2 - 2 files changed, 63 insertions(+), 62 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ba8a955c4cd2..b011b8c4e643 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2229,13 +2229,13 @@ void intel_add_fb_offsets(int *x, int *y, } } -static u32 __intel_adjust_tile_offset(int *x, int *y, - unsigned int tile_width, - unsigned int tile_height, - unsigned int tile_size, - unsigned int pitch_tiles, - u32 old_offset, - u32 new_offset) +static u32 intel_adjust_tile_offset(int *x, int *y, + unsigned int tile_width, + unsigned int tile_height, + unsigned int tile_size, + unsigned int pitch_tiles, + u32 old_offset, + u32 new_offset) { unsigned int pitch_pixels = pitch_tiles * tile_width; unsigned int tiles; @@ -2256,12 +2256,12 @@ static u32 __intel_adjust_tile_offset(int *x, int *y, return new_offset; } -static u32 _intel_adjust_tile_offset(int *x, int *y, - const struct drm_framebuffer *fb, int plane, - unsigned int rotation, - u32 old_offset, u32 new_offset) +static u32 intel_adjust_aligned_offset(int *x, int *y, + const struct drm_framebuffer *fb, int plane, + unsigned int rotation, + u32 old_offset, u32 new_offset) { - const struct drm_i915_private *dev_priv = to_i915(fb->dev); + struct drm_i915_private *dev_priv = to_i915(fb->dev); unsigned int cpp = fb->format->cpp[plane]; unsigned int pitch = intel_fb_pitch(fb, plane, rotation); @@ -2281,9 +2281,9 @@ static u32 _intel_adjust_tile_offset(int *x, int *y, pitch_tiles = pitch / (tile_width * cpp); } - __intel_adjust_tile_offset(x, y, tile_width, tile_height, - tile_size, pitch_tiles, - old_offset, new_offset); + intel_adjust_tile_offset(x, y, tile_width, tile_height, + tile_size, pitch_tiles, + old_offset, new_offset); } else { old_offset += *y * pitch + *x * cpp; @@ -2298,17 +2298,18 @@ static u32 _intel_adjust_tile_offset(int *x, int *y, * Adjust the tile offset by moving the difference into * the x/y offsets. */ -static u32 intel_adjust_tile_offset(int *x, int *y, - const struct intel_plane_state *state, int plane, - u32 old_offset, u32 new_offset) +static u32 intel_plane_adjust_aligned_offset(int *x, int *y, + const struct intel_plane_state *state, + int plane, + u32 old_offset, u32 new_offset) { - return _intel_adjust_tile_offset(x, y, state->base.fb, plane, - state->base.rotation, - old_offset, new_offset); + return intel_adjust_aligned_offset(x, y, state->base.fb, plane, + state->base.rotation, + old_offset, new_offset); } /* - * Computes the linear offset to the base tile and adjusts + * Computes the aligned offset to the base tile and adjusts * x, y. bytes per pixel is assumed to be a power-of-two. * * In the 90/270 rotated case, x and y are assumed @@ -2321,12 +2322,12 @@ static u32 intel_adjust_tile_offset(int *x, int *y, * used. This is why the user has to pass in the pitch since it * is specified in the rotated orientation. */ -static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv, - int *x, int *y, - const struct drm_framebuffer *fb, int plane, - unsigned int pitch, - unsigned int rotation, - u32 alignment) +static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv, + int *x, int *y, + const struct drm_framebuffer *fb, int plane, + unsigned int pitch, + unsigned int rotation, + u32 alignment) { uint64_t fb_modifier = fb->modifier; unsigned int cpp = fb->format->cpp[plane]; @@ -2358,9 +2359,9 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv, offset = (tile_rows * pitch_tiles + tiles) * tile_size; offset_aligned = offset & ~alignment; - __intel_adjust_tile_offset(x, y, tile_width, tile_height, - tile_size, pitch_tiles, - offset, offset_aligned); + intel_adjust_tile_offset(x, y, tile_width, tile_height, + tile_size, pitch_tiles, + offset, offset_aligned); } else { offset = *y * pitch + *x * cpp; offset_aligned = offset & ~alignment; @@ -2372,9 +2373,9 @@ static u32 _intel_compute_tile_offset(const struct drm_i915_private *dev_priv, return offset_aligned; } -u32 intel_compute_tile_offset(int *x, int *y, - const struct intel_plane_state *state, - int plane) +static u32 intel_plane_compute_aligned_offset(int *x, int *y, + const struct intel_plane_state *state, + int plane) { struct intel_plane *intel_plane = to_intel_plane(state->base.plane); struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev); @@ -2388,8 +2389,8 @@ u32 intel_compute_tile_offset(int *x, int *y, else alignment = intel_surf_alignment(fb, plane); - return _intel_compute_tile_offset(dev_priv, x, y, fb, plane, pitch, - rotation, alignment); + return intel_compute_aligned_offset(dev_priv, x, y, fb, plane, + pitch, rotation, alignment); } /* Convert the fb->offset[] into x/y offsets */ @@ -2405,9 +2406,9 @@ static int intel_fb_offset_to_xy(int *x, int *y, *x = 0; *y = 0; - _intel_adjust_tile_offset(x, y, - fb, plane, DRM_MODE_ROTATE_0, - fb->offsets[plane], 0); + intel_adjust_aligned_offset(x, y, + fb, plane, DRM_MODE_ROTATE_0, + fb->offsets[plane], 0); return 0; } @@ -2564,9 +2565,10 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, intel_fb->normal[i].x = x; intel_fb->normal[i].y = y; - offset = _intel_compute_tile_offset(dev_priv, &x, &y, - fb, i, fb->pitches[i], - DRM_MODE_ROTATE_0, tile_size); + offset = intel_compute_aligned_offset(dev_priv, &x, &y, fb, i, + fb->pitches[i], + DRM_MODE_ROTATE_0, + tile_size); offset /= tile_size; if (fb->modifier != DRM_FORMAT_MOD_LINEAR) { @@ -2613,10 +2615,10 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, * We only keep the x/y offsets, so push all of the * gtt offset into the x/y offsets. */ - __intel_adjust_tile_offset(&x, &y, - tile_width, tile_height, - tile_size, pitch_tiles, - gtt_offset_rotated * tile_size, 0); + intel_adjust_tile_offset(&x, &y, + tile_width, tile_height, + tile_size, pitch_tiles, + gtt_offset_rotated * tile_size, 0); gtt_offset_rotated += rot_info->plane[i].width * rot_info->plane[i].height; @@ -2965,8 +2967,8 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state x = aux_x / hsub; y = aux_y / vsub; - aux_offset = intel_adjust_tile_offset(&x, &y, plane_state, 1, - aux_offset, aux_offset - alignment); + aux_offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 1, + aux_offset, aux_offset - alignment); aux_x = x * hsub + aux_x % hsub; aux_y = y * vsub + aux_y % vsub; } @@ -3024,7 +3026,7 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, } intel_add_fb_offsets(&x, &y, plane_state, 0); - offset = intel_compute_tile_offset(&x, &y, plane_state, 0); + offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 0); alignment = intel_surf_alignment(fb, 0); /* @@ -3033,8 +3035,8 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, * sure that is what we will get. */ if (offset > aux_offset) - offset = intel_adjust_tile_offset(&x, &y, plane_state, 0, - offset, aux_offset & ~(alignment - 1)); + offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0, + offset, aux_offset & ~(alignment - 1)); /* * When using an X-tiled surface, the plane blows up @@ -3051,8 +3053,8 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, return -EINVAL; } - offset = intel_adjust_tile_offset(&x, &y, plane_state, 0, - offset, offset - alignment); + offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0, + offset, offset - alignment); } } @@ -3065,8 +3067,8 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, if (offset == 0) break; - offset = intel_adjust_tile_offset(&x, &y, plane_state, 0, - offset, offset - alignment); + offset = intel_plane_adjust_aligned_offset(&x, &y, plane_state, 0, + offset, offset - alignment); } if (x != plane_state->aux.x || y != plane_state->aux.y) { @@ -3118,7 +3120,7 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) u32 offset; intel_add_fb_offsets(&x, &y, plane_state, 1); - offset = intel_compute_tile_offset(&x, &y, plane_state, 1); + offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1); /* FIXME not quite sure how/if these apply to the chroma plane */ if (w > max_width || h > max_height) { @@ -3152,7 +3154,7 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) } intel_add_fb_offsets(&x, &y, plane_state, 1); - offset = intel_compute_tile_offset(&x, &y, plane_state, 1); + offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1); plane_state->aux.offset = offset; plane_state->aux.x = x * hsub + src_x % hsub; @@ -3284,8 +3286,8 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) intel_add_fb_offsets(&src_x, &src_y, plane_state, 0); if (INTEL_GEN(dev_priv) >= 4) - offset = intel_compute_tile_offset(&src_x, &src_y, - plane_state, 0); + offset = intel_plane_compute_aligned_offset(&src_x, &src_y, + plane_state, 0); else offset = 0; @@ -9666,7 +9668,8 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, src_y = plane_state->base.src_y >> 16; intel_add_fb_offsets(&src_x, &src_y, plane_state, 0); - offset = intel_compute_tile_offset(&src_x, &src_y, plane_state, 0); + offset = intel_plane_compute_aligned_offset(&src_x, &src_y, + plane_state, 0); if (src_x != 0 || src_y != 0) { DRM_DEBUG_KMS("Arbitrary cursor panning not supported\n"); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 9d0ca1715d81..7901be755710 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1612,8 +1612,6 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, void assert_pipe(struct drm_i915_private *dev_priv, enum pipe pipe, bool state); #define assert_pipe_enabled(d, p) assert_pipe(d, p, true) #define assert_pipe_disabled(d, p) assert_pipe(d, p, false) -u32 intel_compute_tile_offset(int *x, int *y, - const struct intel_plane_state *state, int plane); void intel_prepare_reset(struct drm_i915_private *dev_priv); void intel_finish_reset(struct drm_i915_private *dev_priv); void hsw_enable_pc8(struct drm_i915_private *dev_priv); -- cgit From ddd5713d6e56ec283de25a3f3943c3f5bf341f56 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:02 +0300 Subject: drm/i915: Add .max_stride() plane hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each plane may have different stride limitations. Let's add a new plane function to retutn the maximum stride for each plane. There's going to be some use for this outside the .atomic_check() stuff hence the separate hook. v2: Fix ilk+ x-tiled max stride to be 32k (José) Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 48 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_drv.h | 10 ++++++++ drivers/gpu/drm/i915/intel_sprite.c | 34 +++++++++++++++++++++++-- 3 files changed, 90 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b011b8c4e643..a92e6bc86b6f 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3213,6 +3213,33 @@ int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, return 0; } +unsigned int +i9xx_plane_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + + if (!HAS_GMCH_DISPLAY(dev_priv)) { + return 32*1024; + } else if (INTEL_GEN(dev_priv) >= 4) { + if (modifier == I915_FORMAT_MOD_X_TILED) + return 16*1024; + else + return 32*1024; + } else if (INTEL_GEN(dev_priv) >= 3) { + if (modifier == I915_FORMAT_MOD_X_TILED) + return 8*1024; + else + return 16*1024; + } else { + if (plane->i9xx_plane == PLANE_C) + return 4*1024; + else + return 8*1024; + } +} + static u32 i9xx_plane_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { @@ -9681,6 +9708,14 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, return 0; } +static unsigned int +i845_cursor_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation) +{ + return 2048; +} + static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { @@ -9813,6 +9848,14 @@ static bool i845_cursor_get_hw_state(struct intel_plane *plane, return ret; } +static unsigned int +i9xx_cursor_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation) +{ + return plane->base.dev->mode_config.cursor_width * 4; +} + static u32 i9xx_cursor_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { @@ -13727,6 +13770,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) else modifiers = skl_format_modifiers_noccs; + primary->max_stride = skl_plane_max_stride; primary->update_plane = skl_update_plane; primary->disable_plane = skl_disable_plane; primary->get_hw_state = skl_plane_get_hw_state; @@ -13737,6 +13781,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) num_formats = ARRAY_SIZE(i965_primary_formats); modifiers = i9xx_format_modifiers; + primary->max_stride = i9xx_plane_max_stride; primary->update_plane = i9xx_update_plane; primary->disable_plane = i9xx_disable_plane; primary->get_hw_state = i9xx_plane_get_hw_state; @@ -13747,6 +13792,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) num_formats = ARRAY_SIZE(i8xx_primary_formats); modifiers = i9xx_format_modifiers; + primary->max_stride = i9xx_plane_max_stride; primary->update_plane = i9xx_update_plane; primary->disable_plane = i9xx_disable_plane; primary->get_hw_state = i9xx_plane_get_hw_state; @@ -13854,11 +13900,13 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, cursor->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, cursor->id); if (IS_I845G(dev_priv) || IS_I865G(dev_priv)) { + cursor->max_stride = i845_cursor_max_stride; cursor->update_plane = i845_update_cursor; cursor->disable_plane = i845_disable_cursor; cursor->get_hw_state = i845_cursor_get_hw_state; cursor->check_plane = i845_check_cursor; } else { + cursor->max_stride = i9xx_cursor_max_stride; cursor->update_plane = i9xx_update_cursor; cursor->disable_plane = i9xx_disable_cursor; cursor->get_hw_state = i9xx_cursor_get_hw_state; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 7901be755710..a93231c2ea78 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -965,6 +965,9 @@ struct intel_plane { * the intel_plane_state structure and accessed via plane_state. */ + unsigned int (*max_stride)(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation); void (*update_plane)(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); @@ -1660,6 +1663,9 @@ int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); int i9xx_check_plane_surface(struct intel_plane_state *plane_state); int skl_format_to_fourcc(int format, bool rgb_order, bool alpha); +unsigned int i9xx_plane_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation); /* intel_csr.c */ void intel_csr_ucode_init(struct drm_i915_private *); @@ -2127,6 +2133,10 @@ bool skl_plane_has_ccs(struct drm_i915_private *dev_priv, enum pipe pipe, enum plane_id plane_id); bool skl_plane_has_planar(struct drm_i915_private *dev_priv, enum pipe pipe, enum plane_id plane_id); +unsigned int skl_plane_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation); + /* intel_tv.c */ void intel_tv_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 9600ccfc5b76..9c6278792755 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -230,6 +230,23 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) #endif } +unsigned int +skl_plane_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation) +{ + int cpp = drm_format_plane_cpp(pixel_format, 0); + + /* + * "The stride in bytes must not exceed the + * of the size of 8K pixels and 32K bytes." + */ + if (drm_rotation_90_or_270(rotation)) + return min(8192, 32768 / cpp); + else + return min(8192 * cpp, 32768); +} + void skl_update_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, @@ -800,6 +817,14 @@ ivb_plane_get_hw_state(struct intel_plane *plane, return ret; } +static unsigned int +g4x_sprite_max_stride(struct intel_plane *plane, + u32 pixel_format, u64 modifier, + unsigned int rotation) +{ + return 16384; +} + static u32 g4x_sprite_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { @@ -966,7 +991,6 @@ intel_check_sprite_plane(struct intel_crtc_state *crtc_state, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_framebuffer *fb = state->base.fb; - int max_stride = INTEL_GEN(dev_priv) >= 9 ? 32768 : 16384; int max_scale, min_scale; bool can_scale; int ret; @@ -984,7 +1008,9 @@ intel_check_sprite_plane(struct intel_crtc_state *crtc_state, } /* FIXME check all gen limits */ - if (fb->width < 3 || fb->height < 3 || fb->pitches[0] > max_stride) { + if (fb->width < 3 || fb->height < 3 || + fb->pitches[0] > plane->max_stride(plane, fb->format->format, + fb->modifier, DRM_MODE_ROTATE_0)) { DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); return -EINVAL; } @@ -1529,6 +1555,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, PLANE_SPRITE0 + plane); + intel_plane->max_stride = skl_plane_max_stride; intel_plane->update_plane = skl_update_plane; intel_plane->disable_plane = skl_disable_plane; intel_plane->get_hw_state = skl_plane_get_hw_state; @@ -1552,6 +1579,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->can_scale = false; intel_plane->max_downscale = 1; + intel_plane->max_stride = i9xx_plane_max_stride; intel_plane->update_plane = vlv_update_plane; intel_plane->disable_plane = vlv_disable_plane; intel_plane->get_hw_state = vlv_plane_get_hw_state; @@ -1570,6 +1598,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->max_downscale = 1; } + intel_plane->max_stride = g4x_sprite_max_stride; intel_plane->update_plane = ivb_update_plane; intel_plane->disable_plane = ivb_disable_plane; intel_plane->get_hw_state = ivb_plane_get_hw_state; @@ -1583,6 +1612,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->can_scale = true; intel_plane->max_downscale = 16; + intel_plane->max_stride = g4x_sprite_max_stride; intel_plane->update_plane = g4x_update_plane; intel_plane->disable_plane = g4x_disable_plane; intel_plane->get_hw_state = g4x_plane_get_hw_state; -- cgit From 645d91f6060cdd336b495616fe677b120c6e2ebd Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:03 +0300 Subject: drm/i915: Use pipe A primary plane .max_stride() as the global stride limit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's assume that the primary plane for pipe A has the highest max stride of all planes, and we'll use that as the global limit when creating a new framebuffer. Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-4-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a92e6bc86b6f..c8b68984815e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -14432,31 +14432,18 @@ static u32 intel_fb_pitch_limit(struct drm_i915_private *dev_priv, uint64_t fb_modifier, uint32_t pixel_format) { - u32 gen = INTEL_GEN(dev_priv); + struct intel_crtc *crtc; + struct intel_plane *plane; - if (gen >= 9) { - int cpp = drm_format_plane_cpp(pixel_format, 0); + /* + * We assume the primary plane for pipe A has + * the highest stride limits of them all. + */ + crtc = intel_get_crtc_for_pipe(dev_priv, PIPE_A); + plane = to_intel_plane(crtc->base.primary); - /* "The stride in bytes must not exceed the of the size of 8K - * pixels and 32K bytes." - */ - return min(8192 * cpp, 32768); - } else if (gen >= 5 && !HAS_GMCH_DISPLAY(dev_priv)) { - return 32*1024; - } else if (gen >= 4) { - if (fb_modifier == I915_FORMAT_MOD_X_TILED) - return 16*1024; - else - return 32*1024; - } else if (gen >= 3) { - if (fb_modifier == I915_FORMAT_MOD_X_TILED) - return 8*1024; - else - return 16*1024; - } else { - /* XXX DSPC is limited to 4k tiled */ - return 8*1024; - } + return plane->max_stride(plane, pixel_format, fb_modifier, + DRM_MODE_ROTATE_0); } static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, -- cgit From c11ada0776b982bf3757b13c2775106bb06a3a9d Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:04 +0300 Subject: drm/i915: Rename the plane_state->main/aux to plane_state->color_plane[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the main/aux surface stuff a bit more generic by using an array of structures. This will allow us to deal with both the main and aux surfaces with common code. Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 56 ++++++++++++++++++------------------ drivers/gpu/drm/i915/intel_drv.h | 6 +--- drivers/gpu/drm/i915/intel_fbc.c | 4 +-- drivers/gpu/drm/i915/intel_sprite.c | 29 ++++++++++--------- 4 files changed, 46 insertions(+), 49 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c8b68984815e..f6828dc14cc9 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2951,9 +2951,9 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state const struct drm_framebuffer *fb = plane_state->base.fb; int hsub = fb->format->hsub; int vsub = fb->format->vsub; - int aux_x = plane_state->aux.x; - int aux_y = plane_state->aux.y; - u32 aux_offset = plane_state->aux.offset; + int aux_x = plane_state->color_plane[1].x; + int aux_y = plane_state->color_plane[1].y; + u32 aux_offset = plane_state->color_plane[1].offset; u32 alignment = intel_surf_alignment(fb, 1); while (aux_offset >= main_offset && aux_y <= main_y) { @@ -2976,9 +2976,9 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state if (aux_x != main_x || aux_y != main_y) return false; - plane_state->aux.offset = aux_offset; - plane_state->aux.x = aux_x; - plane_state->aux.y = aux_y; + plane_state->color_plane[1].offset = aux_offset; + plane_state->color_plane[1].x = aux_x; + plane_state->color_plane[1].y = aux_y; return true; } @@ -2999,7 +2999,7 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, int pipe_src_w = crtc_state->pipe_src_w; int max_width = skl_max_plane_width(fb, 0, rotation); int max_height = 4096; - u32 alignment, offset, aux_offset = plane_state->aux.offset; + u32 alignment, offset, aux_offset = plane_state->color_plane[1].offset; if (w > max_width || h > max_height) { DRM_DEBUG_KMS("requested Y/RGB source size %dx%d too big (limit %dx%d)\n", @@ -3071,15 +3071,15 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, offset, offset - alignment); } - if (x != plane_state->aux.x || y != plane_state->aux.y) { + if (x != plane_state->color_plane[1].x || y != plane_state->color_plane[1].y) { DRM_DEBUG_KMS("Unable to find suitable display surface offset due to CCS\n"); return -EINVAL; } } - plane_state->main.offset = offset; - plane_state->main.x = x; - plane_state->main.y = y; + plane_state->color_plane[0].offset = offset; + plane_state->color_plane[0].x = x; + plane_state->color_plane[0].y = y; return 0; } @@ -3129,9 +3129,9 @@ static int skl_check_nv12_aux_surface(struct intel_plane_state *plane_state) return -EINVAL; } - plane_state->aux.offset = offset; - plane_state->aux.x = x; - plane_state->aux.y = y; + plane_state->color_plane[1].offset = offset; + plane_state->color_plane[1].x = x; + plane_state->color_plane[1].y = y; return 0; } @@ -3156,9 +3156,9 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) intel_add_fb_offsets(&x, &y, plane_state, 1); offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1); - plane_state->aux.offset = offset; - plane_state->aux.x = x * hsub + src_x % hsub; - plane_state->aux.y = y * vsub + src_y % vsub; + plane_state->color_plane[1].offset = offset; + plane_state->color_plane[1].x = x * hsub + src_x % hsub; + plane_state->color_plane[1].y = y * vsub + src_y % vsub; return 0; } @@ -3201,9 +3201,9 @@ int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, if (ret) return ret; } else { - plane_state->aux.offset = ~0xfff; - plane_state->aux.x = 0; - plane_state->aux.y = 0; + plane_state->color_plane[1].offset = ~0xfff; + plane_state->color_plane[1].x = 0; + plane_state->color_plane[1].y = 0; } ret = skl_check_main_surface(crtc_state, plane_state); @@ -3332,9 +3332,9 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) } } - plane_state->main.offset = offset; - plane_state->main.x = src_x; - plane_state->main.y = src_y; + plane_state->color_plane[0].offset = offset; + plane_state->color_plane[0].x = src_x; + plane_state->color_plane[0].y = src_y; return 0; } @@ -3349,15 +3349,15 @@ static void i9xx_update_plane(struct intel_plane *plane, u32 linear_offset; u32 dspcntr = plane_state->ctl; i915_reg_t reg = DSPCNTR(i9xx_plane); - int x = plane_state->main.x; - int y = plane_state->main.y; + int x = plane_state->color_plane[0].x; + int y = plane_state->color_plane[0].y; unsigned long irqflags; u32 dspaddr_offset; linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); if (INTEL_GEN(dev_priv) >= 4) - dspaddr_offset = plane_state->main.offset; + dspaddr_offset = plane_state->color_plane[0].offset; else dspaddr_offset = linear_offset; @@ -9624,7 +9624,7 @@ static u32 intel_cursor_base(const struct intel_plane_state *plane_state) else base = intel_plane_ggtt_offset(plane_state); - base += plane_state->main.offset; + base += plane_state->color_plane[0].offset; /* ILK+ do this automagically */ if (HAS_GMCH_DISPLAY(dev_priv) && @@ -9703,7 +9703,7 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, return -EINVAL; } - plane_state->main.offset = offset; + plane_state->color_plane[0].offset = offset; return 0; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a93231c2ea78..0c7a046b4f26 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -503,11 +503,7 @@ struct intel_plane_state { struct { u32 offset; int x, y; - } main; - struct { - u32 offset; - int x, y; - } aux; + } color_plane[2]; /* plane control register */ u32 ctl; diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 01d1d2088f04..74d425c700ef 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -670,8 +670,8 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->plane.src_w = drm_rect_width(&plane_state->base.src) >> 16; cache->plane.src_h = drm_rect_height(&plane_state->base.src) >> 16; cache->plane.visible = plane_state->base.visible; - cache->plane.adjusted_x = plane_state->main.x; - cache->plane.adjusted_y = plane_state->main.y; + cache->plane.adjusted_x = plane_state->color_plane[0].x; + cache->plane.adjusted_y = plane_state->color_plane[0].y; cache->plane.y = plane_state->base.src.y1 >> 16; if (!cache->plane.visible) diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 9c6278792755..df0cf3d2ea98 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -258,7 +258,7 @@ skl_update_plane(struct intel_plane *plane, enum pipe pipe = plane->pipe; u32 plane_ctl = plane_state->ctl; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; - u32 surf_addr = plane_state->main.offset; + u32 surf_addr = plane_state->color_plane[0].offset; unsigned int rotation = plane_state->base.rotation; u32 stride = skl_plane_stride(fb, 0, rotation); u32 aux_stride = skl_plane_stride(fb, 1, rotation); @@ -266,8 +266,8 @@ skl_update_plane(struct intel_plane *plane, int crtc_y = plane_state->base.dst.y1; uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); - uint32_t x = plane_state->main.x; - uint32_t y = plane_state->main.y; + uint32_t x = plane_state->color_plane[0].x; + uint32_t y = plane_state->color_plane[0].y; uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; unsigned long irqflags; @@ -294,9 +294,10 @@ skl_update_plane(struct intel_plane *plane, I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride); I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w); I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), - (plane_state->aux.offset - surf_addr) | aux_stride); + (plane_state->color_plane[1].offset - surf_addr) | aux_stride); I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id), - (plane_state->aux.y << 16) | plane_state->aux.x); + (plane_state->color_plane[1].y << 16) | + plane_state->color_plane[1].x); /* program plane scaler */ if (plane_state->scaler_id >= 0) { @@ -562,15 +563,15 @@ vlv_update_plane(struct intel_plane *plane, enum pipe pipe = plane->pipe; enum plane_id plane_id = plane->id; u32 sprctl = plane_state->ctl; - u32 sprsurf_offset = plane_state->main.offset; + u32 sprsurf_offset = plane_state->color_plane[0].offset; u32 linear_offset; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->base.dst.x1; int crtc_y = plane_state->base.dst.y1; uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); - uint32_t x = plane_state->main.x; - uint32_t y = plane_state->main.y; + uint32_t x = plane_state->color_plane[0].x; + uint32_t y = plane_state->color_plane[0].y; unsigned long irqflags; /* Sizes are 0 based */ @@ -721,15 +722,15 @@ ivb_update_plane(struct intel_plane *plane, const struct drm_framebuffer *fb = plane_state->base.fb; enum pipe pipe = plane->pipe; u32 sprctl = plane_state->ctl, sprscale = 0; - u32 sprsurf_offset = plane_state->main.offset; + u32 sprsurf_offset = plane_state->color_plane[0].offset; u32 linear_offset; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->base.dst.x1; int crtc_y = plane_state->base.dst.y1; uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); - uint32_t x = plane_state->main.x; - uint32_t y = plane_state->main.y; + uint32_t x = plane_state->color_plane[0].x; + uint32_t y = plane_state->color_plane[0].y; uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; unsigned long irqflags; @@ -893,15 +894,15 @@ g4x_update_plane(struct intel_plane *plane, const struct drm_framebuffer *fb = plane_state->base.fb; enum pipe pipe = plane->pipe; u32 dvscntr = plane_state->ctl, dvsscale = 0; - u32 dvssurf_offset = plane_state->main.offset; + u32 dvssurf_offset = plane_state->color_plane[0].offset; u32 linear_offset; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; int crtc_x = plane_state->base.dst.x1; int crtc_y = plane_state->base.dst.y1; uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); - uint32_t x = plane_state->main.x; - uint32_t y = plane_state->main.y; + uint32_t x = plane_state->color_plane[0].x; + uint32_t y = plane_state->color_plane[0].y; uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; uint32_t src_h = drm_rect_height(&plane_state->base.src) >> 16; unsigned long irqflags; -- cgit From df79cf44191029a72a6fca908437e5be6f81b878 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 11 Sep 2018 18:01:39 +0300 Subject: drm/i915: Store the final plane stride in plane_state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's store the final plane stride in the plane state. This avoids having to pick between the normal vs. rotated stride during hardware programming. And once we get GTT remapping the plane stride will no longer match the fb stride so we'll need a place to store it anyway. v2: Keep checking fb->pitches[0] for cursor as later on we won't populate plane_state->color_plane[0].stride for invisible planes and we have been checking the cursor fb stride even for invisible planes v3: s/betwen/between in commit msg (José) v4: Check color_plane[0].stride instead of fb->pitches[0] in the skl_check_main_surface() X-tiling kludge Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180911150139.23922-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 47 ++++++++++++++++++++++++------------ drivers/gpu/drm/i915/intel_drv.h | 10 ++++++-- drivers/gpu/drm/i915/intel_sprite.c | 12 ++++----- 3 files changed, 46 insertions(+), 23 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f6828dc14cc9..3fc90db7ae97 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2202,7 +2202,7 @@ u32 intel_fb_xy_to_linear(int x, int y, { const struct drm_framebuffer *fb = state->base.fb; unsigned int cpp = fb->format->cpp[plane]; - unsigned int pitch = fb->pitches[plane]; + unsigned int pitch = state->color_plane[plane].stride; return y * pitch + x * cpp; } @@ -2259,11 +2259,11 @@ static u32 intel_adjust_tile_offset(int *x, int *y, static u32 intel_adjust_aligned_offset(int *x, int *y, const struct drm_framebuffer *fb, int plane, unsigned int rotation, + unsigned int pitch, u32 old_offset, u32 new_offset) { struct drm_i915_private *dev_priv = to_i915(fb->dev); unsigned int cpp = fb->format->cpp[plane]; - unsigned int pitch = intel_fb_pitch(fb, plane, rotation); WARN_ON(new_offset > old_offset); @@ -2305,6 +2305,7 @@ static u32 intel_plane_adjust_aligned_offset(int *x, int *y, { return intel_adjust_aligned_offset(x, y, state->base.fb, plane, state->base.rotation, + state->color_plane[plane].stride, old_offset, new_offset); } @@ -2381,7 +2382,7 @@ static u32 intel_plane_compute_aligned_offset(int *x, int *y, struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev); const struct drm_framebuffer *fb = state->base.fb; unsigned int rotation = state->base.rotation; - int pitch = intel_fb_pitch(fb, plane, rotation); + int pitch = state->color_plane[plane].stride; u32 alignment; if (intel_plane->id == PLANE_CURSOR) @@ -2408,6 +2409,7 @@ static int intel_fb_offset_to_xy(int *x, int *y, intel_adjust_aligned_offset(x, y, fb, plane, DRM_MODE_ROTATE_0, + fb->pitches[0], fb->offsets[plane], 0); return 0; @@ -2854,6 +2856,9 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, return; valid_fb: + intel_state->color_plane[0].stride = + intel_fb_pitch(fb, 0, intel_state->base.rotation); + mutex_lock(&dev->struct_mutex); intel_state->vma = intel_pin_and_fence_fb_obj(fb, @@ -3047,7 +3052,7 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, if (fb->modifier == I915_FORMAT_MOD_X_TILED) { int cpp = fb->format->cpp[0]; - while ((x + w) * cpp > fb->pitches[0]) { + while ((x + w) * cpp > plane_state->color_plane[0].stride) { if (offset == 0) { DRM_DEBUG_KMS("Unable to find suitable display surface offset due to X-tiling\n"); return -EINVAL; @@ -3170,6 +3175,9 @@ int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, unsigned int rotation = plane_state->base.rotation; int ret; + plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation); + plane_state->color_plane[1].stride = intel_fb_pitch(fb, 1, rotation); + if (rotation & DRM_MODE_REFLECT_X && fb->modifier == DRM_FORMAT_MOD_LINEAR) { DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n"); @@ -3306,10 +3314,14 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane_state->base.plane->dev); + const struct drm_framebuffer *fb = plane_state->base.fb; + unsigned int rotation = plane_state->base.rotation; int src_x = plane_state->base.src.x1 >> 16; int src_y = plane_state->base.src.y1 >> 16; u32 offset; + plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation); + intel_add_fb_offsets(&src_x, &src_y, plane_state, 0); if (INTEL_GEN(dev_priv) >= 4) @@ -3320,7 +3332,6 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) /* HSW/BDW do this automagically in hardware */ if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) { - unsigned int rotation = plane_state->base.rotation; int src_w = drm_rect_width(&plane_state->base.src) >> 16; int src_h = drm_rect_height(&plane_state->base.src) >> 16; @@ -3344,7 +3355,6 @@ static void i9xx_update_plane(struct intel_plane *plane, const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - const struct drm_framebuffer *fb = plane_state->base.fb; enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; u32 linear_offset; u32 dspcntr = plane_state->ctl; @@ -3381,7 +3391,7 @@ static void i9xx_update_plane(struct intel_plane *plane, I915_WRITE_FW(reg, dspcntr); - I915_WRITE_FW(DSPSTRIDE(i9xx_plane), fb->pitches[0]); + I915_WRITE_FW(DSPSTRIDE(i9xx_plane), plane_state->color_plane[0].stride); if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { I915_WRITE_FW(DSPSURF(i9xx_plane), intel_plane_ggtt_offset(plane_state) + @@ -3491,16 +3501,16 @@ static void skl_detach_scalers(struct intel_crtc *intel_crtc) } } -u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, - unsigned int rotation) +u32 skl_plane_stride(const struct intel_plane_state *plane_state, + int plane) { - u32 stride; + const struct drm_framebuffer *fb = plane_state->base.fb; + unsigned int rotation = plane_state->base.rotation; + u32 stride = plane_state->color_plane[plane].stride; if (plane >= fb->format->num_planes) return 0; - stride = intel_fb_pitch(fb, plane, rotation); - /* * The stride is either expressed as a multiple of 64 bytes chunks for * linear buffers or in number of tiles for tiled buffers. @@ -9671,6 +9681,7 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { const struct drm_framebuffer *fb = plane_state->base.fb; + unsigned int rotation = plane_state->base.rotation; int src_x, src_y; u32 offset; int ret; @@ -9691,6 +9702,8 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, return -EINVAL; } + plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation); + src_x = plane_state->base.src_x >> 16; src_y = plane_state->base.src_y >> 16; @@ -9719,12 +9732,10 @@ i845_cursor_max_stride(struct intel_plane *plane, static u32 i845_cursor_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) { - const struct drm_framebuffer *fb = plane_state->base.fb; - return CURSOR_ENABLE | CURSOR_GAMMA_ENABLE | CURSOR_FORMAT_ARGB | - CURSOR_STRIDE(fb->pitches[0]); + CURSOR_STRIDE(plane_state->color_plane[0].stride); } static bool i845_cursor_size_ok(const struct intel_plane_state *plane_state) @@ -9760,6 +9771,9 @@ static int i845_check_cursor(struct intel_crtc_state *crtc_state, return -EINVAL; } + WARN_ON(plane_state->base.visible && + plane_state->color_plane[0].stride != fb->pitches[0]); + switch (fb->pitches[0]) { case 256: case 512: @@ -9961,6 +9975,9 @@ static int i9xx_check_cursor(struct intel_crtc_state *crtc_state, return -EINVAL; } + WARN_ON(plane_state->base.visible && + plane_state->color_plane[0].stride != fb->pitches[0]); + if (fb->pitches[0] != plane_state->base.crtc_w * fb->format->cpp[0]) { DRM_DEBUG_KMS("Invalid cursor stride (%u) (cursor width %d)\n", fb->pitches[0], plane_state->base.crtc_w); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0c7a046b4f26..2e06f9831ff4 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -502,6 +502,12 @@ struct intel_plane_state { struct { u32 offset; + /* + * Plane stride in: + * bytes for 0/180 degree rotation + * pixels for 90/270 degree rotation + */ + u32 stride; int x, y; } color_plane[2]; @@ -1653,8 +1659,8 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state, u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); u32 glk_color_ctl(const struct intel_plane_state *plane_state); -u32 skl_plane_stride(const struct drm_framebuffer *fb, int plane, - unsigned int rotation); +u32 skl_plane_stride(const struct intel_plane_state *plane_state, + int plane); int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); int i9xx_check_plane_surface(struct intel_plane_state *plane_state); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index df0cf3d2ea98..ee98c7bc2f9d 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -259,9 +259,8 @@ skl_update_plane(struct intel_plane *plane, u32 plane_ctl = plane_state->ctl; const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; u32 surf_addr = plane_state->color_plane[0].offset; - unsigned int rotation = plane_state->base.rotation; - u32 stride = skl_plane_stride(fb, 0, rotation); - u32 aux_stride = skl_plane_stride(fb, 1, rotation); + u32 stride = skl_plane_stride(plane_state, 0); + u32 aux_stride = skl_plane_stride(plane_state, 1); int crtc_x = plane_state->base.dst.x1; int crtc_y = plane_state->base.dst.y1; uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); @@ -592,7 +591,8 @@ vlv_update_plane(struct intel_plane *plane, I915_WRITE_FW(SPKEYMAXVAL(pipe, plane_id), key->max_value); I915_WRITE_FW(SPKEYMSK(pipe, plane_id), key->channel_mask); } - I915_WRITE_FW(SPSTRIDE(pipe, plane_id), fb->pitches[0]); + I915_WRITE_FW(SPSTRIDE(pipe, plane_id), + plane_state->color_plane[0].stride); I915_WRITE_FW(SPPOS(pipe, plane_id), (crtc_y << 16) | crtc_x); if (fb->modifier == I915_FORMAT_MOD_X_TILED) @@ -754,7 +754,7 @@ ivb_update_plane(struct intel_plane *plane, I915_WRITE_FW(SPRKEYMSK(pipe), key->channel_mask); } - I915_WRITE_FW(SPRSTRIDE(pipe), fb->pitches[0]); + I915_WRITE_FW(SPRSTRIDE(pipe), plane_state->color_plane[0].stride); I915_WRITE_FW(SPRPOS(pipe), (crtc_y << 16) | crtc_x); /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET @@ -926,7 +926,7 @@ g4x_update_plane(struct intel_plane *plane, I915_WRITE_FW(DVSKEYMSK(pipe), key->channel_mask); } - I915_WRITE_FW(DVSSTRIDE(pipe), fb->pitches[0]); + I915_WRITE_FW(DVSSTRIDE(pipe), plane_state->color_plane[0].stride); I915_WRITE_FW(DVSPOS(pipe), (crtc_y << 16) | crtc_x); if (fb->modifier == I915_FORMAT_MOD_X_TILED) -- cgit From f5929c5309a6a434f6f55969aa186d7a906f92bc Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:06 +0300 Subject: drm/i915: Store ggtt_view in plane_state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stash the gtt_view structure into the plane state. This will become useful when we do GTT remapping as the gtt_view will not come directly from the fb anymore. Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 16 +++++++++------- drivers/gpu/drm/i915/intel_drv.h | 3 ++- drivers/gpu/drm/i915/intel_fbdev.c | 6 ++++-- 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3fc90db7ae97..aa10e5b703f0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2079,14 +2079,13 @@ static bool intel_plane_uses_fence(const struct intel_plane_state *plane_state) struct i915_vma * intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, - unsigned int rotation, + const struct i915_ggtt_view *view, bool uses_fence, unsigned long *out_flags) { struct drm_device *dev = fb->dev; struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_gem_object *obj = intel_fb_obj(fb); - struct i915_ggtt_view view; struct i915_vma *vma; unsigned int pinctl; u32 alignment; @@ -2095,8 +2094,6 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, alignment = intel_surf_alignment(fb, 0); - intel_fill_fb_ggtt_view(&view, fb, rotation); - /* Note that the w/a also requires 64 PTE of padding following the * bo. We currently fill all unused PTE with the shadow page and so * we should always have valid PTE following the scanout preventing @@ -2129,7 +2126,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, pinctl |= PIN_MAPPABLE; vma = i915_gem_object_pin_to_display_plane(obj, - alignment, &view, pinctl); + alignment, view, pinctl); if (IS_ERR(vma)) goto err; @@ -2856,13 +2853,15 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, return; valid_fb: + intel_fill_fb_ggtt_view(&intel_state->view, fb, + intel_state->base.rotation); intel_state->color_plane[0].stride = intel_fb_pitch(fb, 0, intel_state->base.rotation); mutex_lock(&dev->struct_mutex); intel_state->vma = intel_pin_and_fence_fb_obj(fb, - primary->state->rotation, + &intel_state->view, intel_plane_uses_fence(intel_state), &intel_state->flags); mutex_unlock(&dev->struct_mutex); @@ -3175,6 +3174,7 @@ int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, unsigned int rotation = plane_state->base.rotation; int ret; + intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation); plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation); plane_state->color_plane[1].stride = intel_fb_pitch(fb, 1, rotation); @@ -3320,6 +3320,7 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) int src_y = plane_state->base.src.y1 >> 16; u32 offset; + intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation); plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation); intel_add_fb_offsets(&src_x, &src_y, plane_state, 0); @@ -9702,6 +9703,7 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, return -EINVAL; } + intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation); plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation); src_x = plane_state->base.src_x >> 16; @@ -13046,7 +13048,7 @@ static int intel_plane_pin_fb(struct intel_plane_state *plane_state) } vma = intel_pin_and_fence_fb_obj(fb, - plane_state->base.rotation, + &plane_state->view, intel_plane_uses_fence(plane_state), &plane_state->flags); if (IS_ERR(vma)) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2e06f9831ff4..178d3157f0ed 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -496,6 +496,7 @@ struct intel_atomic_state { struct intel_plane_state { struct drm_plane_state base; + struct i915_ggtt_view view; struct i915_vma *vma; unsigned long flags; #define PLANE_HAS_FENCE BIT(0) @@ -1568,7 +1569,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx); struct i915_vma * intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, - unsigned int rotation, + const struct i915_ggtt_view *view, bool uses_fence, unsigned long *out_flags); void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index fb2f9fce34cd..f99332972b7a 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -175,6 +175,9 @@ static int intelfb_create(struct drm_fb_helper *helper, struct drm_i915_private *dev_priv = to_i915(dev); struct pci_dev *pdev = dev_priv->drm.pdev; struct i915_ggtt *ggtt = &dev_priv->ggtt; + const struct i915_ggtt_view view = { + .type = I915_GGTT_VIEW_NORMAL, + }; struct fb_info *info; struct drm_framebuffer *fb; struct i915_vma *vma; @@ -214,8 +217,7 @@ static int intelfb_create(struct drm_fb_helper *helper, * BIOS is suitable for own access. */ vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, - DRM_MODE_ROTATE_0, - false, &flags); + &view, false, &flags); if (IS_ERR(vma)) { ret = PTR_ERR(vma); goto out_unlock; -- cgit From 5d2a19507cb6655ac45a9dc4535cad7930fbb0d7 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:07 +0300 Subject: drm/i915: s/int plane/int color_plane/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To reduce the confusion between a drm plane and the planes of framebuffers let's desiginate the latter as "color plane". Weak-Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 106 ++++++++++++++++++----------------- drivers/gpu/drm/i915/intel_drv.h | 2 +- 2 files changed, 56 insertions(+), 52 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index aa10e5b703f0..31ce15677838 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1916,10 +1916,10 @@ static unsigned int intel_tile_size(const struct drm_i915_private *dev_priv) } static unsigned int -intel_tile_width_bytes(const struct drm_framebuffer *fb, int plane) +intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) { struct drm_i915_private *dev_priv = to_i915(fb->dev); - unsigned int cpp = fb->format->cpp[plane]; + unsigned int cpp = fb->format->cpp[color_plane]; switch (fb->modifier) { case DRM_FORMAT_MOD_LINEAR: @@ -1930,7 +1930,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int plane) else return 512; case I915_FORMAT_MOD_Y_TILED_CCS: - if (plane == 1) + if (color_plane == 1) return 128; /* fall through */ case I915_FORMAT_MOD_Y_TILED: @@ -1939,7 +1939,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int plane) else return 512; case I915_FORMAT_MOD_Yf_TILED_CCS: - if (plane == 1) + if (color_plane == 1) return 128; /* fall through */ case I915_FORMAT_MOD_Yf_TILED: @@ -1964,22 +1964,22 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int plane) } static unsigned int -intel_tile_height(const struct drm_framebuffer *fb, int plane) +intel_tile_height(const struct drm_framebuffer *fb, int color_plane) { if (fb->modifier == DRM_FORMAT_MOD_LINEAR) return 1; else return intel_tile_size(to_i915(fb->dev)) / - intel_tile_width_bytes(fb, plane); + intel_tile_width_bytes(fb, color_plane); } /* Return the tile dimensions in pixel units */ -static void intel_tile_dims(const struct drm_framebuffer *fb, int plane, +static void intel_tile_dims(const struct drm_framebuffer *fb, int color_plane, unsigned int *tile_width, unsigned int *tile_height) { - unsigned int tile_width_bytes = intel_tile_width_bytes(fb, plane); - unsigned int cpp = fb->format->cpp[plane]; + unsigned int tile_width_bytes = intel_tile_width_bytes(fb, color_plane); + unsigned int cpp = fb->format->cpp[color_plane]; *tile_width = tile_width_bytes / cpp; *tile_height = intel_tile_size(to_i915(fb->dev)) / tile_width_bytes; @@ -1987,9 +1987,9 @@ static void intel_tile_dims(const struct drm_framebuffer *fb, int plane, unsigned int intel_fb_align_height(const struct drm_framebuffer *fb, - int plane, unsigned int height) + int color_plane, unsigned int height) { - unsigned int tile_height = intel_tile_height(fb, plane); + unsigned int tile_height = intel_tile_height(fb, color_plane); return ALIGN(height, tile_height); } @@ -2043,12 +2043,12 @@ static unsigned int intel_linear_alignment(const struct drm_i915_private *dev_pr } static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, - int plane) + int color_plane) { struct drm_i915_private *dev_priv = to_i915(fb->dev); /* AUX_DIST needs only 4K alignment */ - if (plane == 1) + if (color_plane == 1) return 4096; switch (fb->modifier) { @@ -2178,13 +2178,13 @@ void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags) i915_vma_put(vma); } -static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane, +static int intel_fb_pitch(const struct drm_framebuffer *fb, int color_plane, unsigned int rotation) { if (drm_rotation_90_or_270(rotation)) - return to_intel_framebuffer(fb)->rotated[plane].pitch; + return to_intel_framebuffer(fb)->rotated[color_plane].pitch; else - return fb->pitches[plane]; + return fb->pitches[color_plane]; } /* @@ -2195,11 +2195,11 @@ static int intel_fb_pitch(const struct drm_framebuffer *fb, int plane, */ u32 intel_fb_xy_to_linear(int x, int y, const struct intel_plane_state *state, - int plane) + int color_plane) { const struct drm_framebuffer *fb = state->base.fb; - unsigned int cpp = fb->format->cpp[plane]; - unsigned int pitch = state->color_plane[plane].stride; + unsigned int cpp = fb->format->cpp[color_plane]; + unsigned int pitch = state->color_plane[color_plane].stride; return y * pitch + x * cpp; } @@ -2211,18 +2211,18 @@ u32 intel_fb_xy_to_linear(int x, int y, */ void intel_add_fb_offsets(int *x, int *y, const struct intel_plane_state *state, - int plane) + int color_plane) { const struct intel_framebuffer *intel_fb = to_intel_framebuffer(state->base.fb); unsigned int rotation = state->base.rotation; if (drm_rotation_90_or_270(rotation)) { - *x += intel_fb->rotated[plane].x; - *y += intel_fb->rotated[plane].y; + *x += intel_fb->rotated[color_plane].x; + *y += intel_fb->rotated[color_plane].y; } else { - *x += intel_fb->normal[plane].x; - *y += intel_fb->normal[plane].y; + *x += intel_fb->normal[color_plane].x; + *y += intel_fb->normal[color_plane].y; } } @@ -2254,13 +2254,14 @@ static u32 intel_adjust_tile_offset(int *x, int *y, } static u32 intel_adjust_aligned_offset(int *x, int *y, - const struct drm_framebuffer *fb, int plane, + const struct drm_framebuffer *fb, + int color_plane, unsigned int rotation, unsigned int pitch, u32 old_offset, u32 new_offset) { struct drm_i915_private *dev_priv = to_i915(fb->dev); - unsigned int cpp = fb->format->cpp[plane]; + unsigned int cpp = fb->format->cpp[color_plane]; WARN_ON(new_offset > old_offset); @@ -2269,7 +2270,7 @@ static u32 intel_adjust_aligned_offset(int *x, int *y, unsigned int pitch_tiles; tile_size = intel_tile_size(dev_priv); - intel_tile_dims(fb, plane, &tile_width, &tile_height); + intel_tile_dims(fb, color_plane, &tile_width, &tile_height); if (drm_rotation_90_or_270(rotation)) { pitch_tiles = pitch / tile_height; @@ -2297,12 +2298,12 @@ static u32 intel_adjust_aligned_offset(int *x, int *y, */ static u32 intel_plane_adjust_aligned_offset(int *x, int *y, const struct intel_plane_state *state, - int plane, + int color_plane, u32 old_offset, u32 new_offset) { - return intel_adjust_aligned_offset(x, y, state->base.fb, plane, + return intel_adjust_aligned_offset(x, y, state->base.fb, color_plane, state->base.rotation, - state->color_plane[plane].stride, + state->color_plane[color_plane].stride, old_offset, new_offset); } @@ -2322,13 +2323,14 @@ static u32 intel_plane_adjust_aligned_offset(int *x, int *y, */ static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv, int *x, int *y, - const struct drm_framebuffer *fb, int plane, + const struct drm_framebuffer *fb, + int color_plane, unsigned int pitch, unsigned int rotation, u32 alignment) { uint64_t fb_modifier = fb->modifier; - unsigned int cpp = fb->format->cpp[plane]; + unsigned int cpp = fb->format->cpp[color_plane]; u32 offset, offset_aligned; if (alignment) @@ -2339,7 +2341,7 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv, unsigned int tile_rows, tiles, pitch_tiles; tile_size = intel_tile_size(dev_priv); - intel_tile_dims(fb, plane, &tile_width, &tile_height); + intel_tile_dims(fb, color_plane, &tile_width, &tile_height); if (drm_rotation_90_or_270(rotation)) { pitch_tiles = pitch / tile_height; @@ -2373,41 +2375,42 @@ static u32 intel_compute_aligned_offset(struct drm_i915_private *dev_priv, static u32 intel_plane_compute_aligned_offset(int *x, int *y, const struct intel_plane_state *state, - int plane) + int color_plane) { struct intel_plane *intel_plane = to_intel_plane(state->base.plane); struct drm_i915_private *dev_priv = to_i915(intel_plane->base.dev); const struct drm_framebuffer *fb = state->base.fb; unsigned int rotation = state->base.rotation; - int pitch = state->color_plane[plane].stride; + int pitch = state->color_plane[color_plane].stride; u32 alignment; if (intel_plane->id == PLANE_CURSOR) alignment = intel_cursor_alignment(dev_priv); else - alignment = intel_surf_alignment(fb, plane); + alignment = intel_surf_alignment(fb, color_plane); - return intel_compute_aligned_offset(dev_priv, x, y, fb, plane, + return intel_compute_aligned_offset(dev_priv, x, y, fb, color_plane, pitch, rotation, alignment); } /* Convert the fb->offset[] into x/y offsets */ static int intel_fb_offset_to_xy(int *x, int *y, - const struct drm_framebuffer *fb, int plane) + const struct drm_framebuffer *fb, + int color_plane) { struct drm_i915_private *dev_priv = to_i915(fb->dev); if (fb->modifier != DRM_FORMAT_MOD_LINEAR && - fb->offsets[plane] % intel_tile_size(dev_priv)) + fb->offsets[color_plane] % intel_tile_size(dev_priv)) return -EINVAL; *x = 0; *y = 0; intel_adjust_aligned_offset(x, y, - fb, plane, DRM_MODE_ROTATE_0, - fb->pitches[0], - fb->offsets[plane], 0); + fb, color_plane, DRM_MODE_ROTATE_0, + fb->pitches[color_plane], + fb->offsets[color_plane], 0); return 0; } @@ -2904,10 +2907,11 @@ valid_fb: &obj->frontbuffer_bits); } -static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane, +static int skl_max_plane_width(const struct drm_framebuffer *fb, + int color_plane, unsigned int rotation) { - int cpp = fb->format->cpp[plane]; + int cpp = fb->format->cpp[color_plane]; switch (fb->modifier) { case DRM_FORMAT_MOD_LINEAR: @@ -3467,12 +3471,12 @@ static bool i9xx_plane_get_hw_state(struct intel_plane *plane, } static u32 -intel_fb_stride_alignment(const struct drm_framebuffer *fb, int plane) +intel_fb_stride_alignment(const struct drm_framebuffer *fb, int color_plane) { if (fb->modifier == DRM_FORMAT_MOD_LINEAR) return 64; else - return intel_tile_width_bytes(fb, plane); + return intel_tile_width_bytes(fb, color_plane); } static void skl_detach_scaler(struct intel_crtc *intel_crtc, int id) @@ -3503,13 +3507,13 @@ static void skl_detach_scalers(struct intel_crtc *intel_crtc) } u32 skl_plane_stride(const struct intel_plane_state *plane_state, - int plane) + int color_plane) { const struct drm_framebuffer *fb = plane_state->base.fb; unsigned int rotation = plane_state->base.rotation; - u32 stride = plane_state->color_plane[plane].stride; + u32 stride = plane_state->color_plane[color_plane].stride; - if (plane >= fb->format->num_planes) + if (color_plane >= fb->format->num_planes) return 0; /* @@ -3517,9 +3521,9 @@ u32 skl_plane_stride(const struct intel_plane_state *plane_state, * linear buffers or in number of tiles for tiled buffers. */ if (drm_rotation_90_or_270(rotation)) - stride /= intel_tile_height(fb, plane); + stride /= intel_tile_height(fb, color_plane); else - stride /= intel_fb_stride_alignment(fb, plane); + stride /= intel_fb_stride_alignment(fb, color_plane); return stride; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 178d3157f0ed..025d026b08e6 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1446,7 +1446,7 @@ void icl_unmap_plls_to_ports(struct drm_crtc *crtc, struct drm_atomic_state *old_state); unsigned int intel_fb_align_height(const struct drm_framebuffer *fb, - int plane, unsigned int height); + int color_plane, unsigned int height); /* intel_audio.c */ void intel_init_audio_hooks(struct drm_i915_private *dev_priv); -- cgit From fd6e3c6c21f42bc895749bc970151f7c078302b1 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:08 +0300 Subject: drm/i915: Nuke plane->can_scale/min_downscale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can easily calculate the plane can_scale/min_downscale on demand. And later on we'll probably want to start calculating these dynamically based on the cdclk just as skl already does. Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-9-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 8 +------- drivers/gpu/drm/i915/intel_drv.h | 2 -- drivers/gpu/drm/i915/intel_sprite.c | 38 ++++++++++++------------------------ 3 files changed, 13 insertions(+), 35 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 31ce15677838..f1f0a25a6db3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -13742,12 +13742,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->base.state = &state->base; - primary->can_scale = false; - primary->max_downscale = 1; - if (INTEL_GEN(dev_priv) >= 9) { - primary->can_scale = true; + if (INTEL_GEN(dev_priv) >= 9) state->scaler_id = -1; - } primary->pipe = pipe; /* * On gen2/3 only plane A can do FBC, but the panel fitter and LVDS @@ -13915,8 +13911,6 @@ intel_cursor_plane_create(struct drm_i915_private *dev_priv, cursor->base.state = &state->base; - cursor->can_scale = false; - cursor->max_downscale = 1; cursor->pipe = pipe; cursor->i9xx_plane = (enum i9xx_plane_id) pipe; cursor->id = PLANE_CURSOR; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 025d026b08e6..2afe30748d38 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -952,10 +952,8 @@ struct intel_plane { enum i9xx_plane_id i9xx_plane; enum plane_id id; enum pipe pipe; - bool can_scale; bool has_fbc; bool has_ccs; - int max_downscale; uint32_t frontbuffer_bit; struct { diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index ee98c7bc2f9d..aa4d82e7245b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -767,7 +767,7 @@ ivb_update_plane(struct intel_plane *plane, I915_WRITE_FW(SPRLINOFF(pipe), linear_offset); I915_WRITE_FW(SPRSIZE(pipe), (crtc_h << 16) | crtc_w); - if (plane->can_scale) + if (IS_IVYBRIDGE(dev_priv)) I915_WRITE_FW(SPRSCALE(pipe), sprscale); I915_WRITE_FW(SPRCTL(pipe), sprctl); I915_WRITE_FW(SPRSURF(pipe), @@ -788,7 +788,7 @@ ivb_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) I915_WRITE_FW(SPRCTL(pipe), 0); /* Can't leave the scaler enabled... */ - if (plane->can_scale) + if (IS_IVYBRIDGE(dev_priv)) I915_WRITE_FW(SPRSCALE(pipe), 0); I915_WRITE_FW(SPRSURF(pipe), 0); @@ -993,7 +993,6 @@ intel_check_sprite_plane(struct intel_crtc_state *crtc_state, struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); struct drm_framebuffer *fb = state->base.fb; int max_scale, min_scale; - bool can_scale; int ret; uint32_t pixel_format = 0; @@ -1016,25 +1015,29 @@ intel_check_sprite_plane(struct intel_crtc_state *crtc_state, return -EINVAL; } - /* setup can_scale, min_scale, max_scale */ if (INTEL_GEN(dev_priv) >= 9) { if (state->base.fb) pixel_format = state->base.fb->format->format; /* use scaler when colorkey is not required */ if (!state->ckey.flags) { - can_scale = 1; min_scale = 1; max_scale = skl_max_scale(crtc, crtc_state, pixel_format); } else { - can_scale = 0; min_scale = DRM_PLANE_HELPER_NO_SCALING; max_scale = DRM_PLANE_HELPER_NO_SCALING; } } else { - can_scale = plane->can_scale; - max_scale = plane->max_downscale << 16; - min_scale = plane->can_scale ? 1 : (1 << 16); + if (INTEL_GEN(dev_priv) < 7) { + min_scale = 1; + max_scale = 16 << 16; + } else if (IS_IVYBRIDGE(dev_priv)) { + min_scale = 1; + max_scale = 2 << 16; + } else { + min_scale = DRM_PLANE_HELPER_NO_SCALING; + max_scale = DRM_PLANE_HELPER_NO_SCALING; + } } ret = drm_atomic_helper_check_plane_state(&state->base, @@ -1080,8 +1083,6 @@ intel_check_sprite_plane(struct intel_crtc_state *crtc_state, unsigned int width_bytes; int cpp = fb->format->cpp[0]; - WARN_ON(!can_scale); - width_bytes = ((src_x * cpp) & 63) + src_w * cpp; /* FIXME interlacing min height is 6 */ @@ -1550,7 +1551,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->base.state = &state->base; if (INTEL_GEN(dev_priv) >= 9) { - intel_plane->can_scale = true; state->scaler_id = -1; intel_plane->has_ccs = skl_plane_has_ccs(dev_priv, pipe, @@ -1577,9 +1577,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane_funcs = &skl_plane_funcs; } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - intel_plane->can_scale = false; - intel_plane->max_downscale = 1; - intel_plane->max_stride = i9xx_plane_max_stride; intel_plane->update_plane = vlv_update_plane; intel_plane->disable_plane = vlv_disable_plane; @@ -1591,14 +1588,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane_funcs = &vlv_sprite_funcs; } else if (INTEL_GEN(dev_priv) >= 7) { - if (IS_IVYBRIDGE(dev_priv)) { - intel_plane->can_scale = true; - intel_plane->max_downscale = 2; - } else { - intel_plane->can_scale = false; - intel_plane->max_downscale = 1; - } - intel_plane->max_stride = g4x_sprite_max_stride; intel_plane->update_plane = ivb_update_plane; intel_plane->disable_plane = ivb_disable_plane; @@ -1610,9 +1599,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, plane_funcs = &snb_sprite_funcs; } else { - intel_plane->can_scale = true; - intel_plane->max_downscale = 16; - intel_plane->max_stride = g4x_sprite_max_stride; intel_plane->update_plane = g4x_update_plane; intel_plane->disable_plane = g4x_disable_plane; -- cgit From 4e0b83a567e28ab11e0c41b399615fd82c02664a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:09 +0300 Subject: drm/i915: Extract per-platform plane->check() functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split up intel_check_primary_plane() and intel_check_sprite_plane() into per-platform variants. This way we can get a unified behaviour between the SKL universal planes, and we stop checking for non-SKL specific scaling limits for the "sprite" planes. And we now get a natural place where to add more plarform specific checks. v2: Split the .check_plane() calling convention change out (José) Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-10-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 116 ++++++-------- drivers/gpu/drm/i915/intel_drv.h | 8 +- drivers/gpu/drm/i915/intel_sprite.c | 303 ++++++++++++++++++++++------------- 3 files changed, 243 insertions(+), 184 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f1f0a25a6db3..7738c1a0eab0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3355,6 +3355,36 @@ int i9xx_check_plane_surface(struct intel_plane_state *plane_state) return 0; } +static int +i9xx_plane_check(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) +{ + int ret; + + ret = drm_atomic_helper_check_plane_state(&plane_state->base, + &crtc_state->base, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + false, true); + if (ret) + return ret; + + if (!plane_state->base.visible) + return 0; + + ret = intel_plane_check_src_coordinates(plane_state); + if (ret) + return ret; + + ret = i9xx_check_plane_surface(plane_state); + if (ret) + return ret; + + plane_state->ctl = i9xx_plane_ctl(crtc_state, plane_state); + + return 0; +} + static void i9xx_update_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) @@ -9691,6 +9721,11 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, u32 offset; int ret; + if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) { + DRM_DEBUG_KMS("cursor cannot be tiled\n"); + return -EINVAL; + } + ret = drm_atomic_helper_check_plane_state(&plane_state->base, &crtc_state->base, DRM_PLANE_HELPER_NO_SCALING, @@ -9699,13 +9734,12 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, if (ret) return ret; - if (!fb) + if (!plane_state->base.visible) return 0; - if (fb->modifier != DRM_FORMAT_MOD_LINEAR) { - DRM_DEBUG_KMS("cursor cannot be tiled\n"); - return -EINVAL; - } + ret = intel_plane_check_src_coordinates(plane_state); + if (ret) + return ret; intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation); plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation); @@ -13230,19 +13264,17 @@ intel_cleanup_plane_fb(struct drm_plane *plane, } int -skl_max_scale(struct intel_crtc *intel_crtc, - struct intel_crtc_state *crtc_state, - uint32_t pixel_format) +skl_max_scale(const struct intel_crtc_state *crtc_state, + u32 pixel_format) { - struct drm_i915_private *dev_priv; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); int max_scale, mult; int crtc_clock, max_dotclk, tmpclk1, tmpclk2; - if (!intel_crtc || !crtc_state->base.enable) + if (!crtc_state->base.enable) return DRM_PLANE_HELPER_NO_SCALING; - dev_priv = to_i915(intel_crtc->base.dev); - crtc_clock = crtc_state->base.adjusted_mode.crtc_clock; max_dotclk = to_intel_atomic_state(crtc_state->base.state)->cdclk.logical.cdclk; @@ -13266,61 +13298,6 @@ skl_max_scale(struct intel_crtc *intel_crtc, return max_scale; } -static int -intel_check_primary_plane(struct intel_crtc_state *crtc_state, - struct intel_plane_state *state) -{ - struct intel_plane *plane = to_intel_plane(state->base.plane); - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - struct drm_crtc *crtc = state->base.crtc; - int min_scale = DRM_PLANE_HELPER_NO_SCALING; - int max_scale = DRM_PLANE_HELPER_NO_SCALING; - bool can_position = false; - int ret; - uint32_t pixel_format = 0; - - if (INTEL_GEN(dev_priv) >= 9) { - /* use scaler when colorkey is not required */ - if (!state->ckey.flags) { - min_scale = 1; - if (state->base.fb) - pixel_format = state->base.fb->format->format; - max_scale = skl_max_scale(to_intel_crtc(crtc), - crtc_state, pixel_format); - } - can_position = true; - } - - ret = drm_atomic_helper_check_plane_state(&state->base, - &crtc_state->base, - min_scale, max_scale, - can_position, true); - if (ret) - return ret; - - if (!state->base.fb) - return 0; - - if (INTEL_GEN(dev_priv) >= 9) { - ret = skl_check_plane_surface(crtc_state, state); - if (ret) - return ret; - - state->ctl = skl_plane_ctl(crtc_state, state); - } else { - ret = i9xx_check_plane_surface(state); - if (ret) - return ret; - - state->ctl = i9xx_plane_ctl(crtc_state, state); - } - - if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) - state->color_ctl = glk_plane_color_ctl(crtc_state, state); - - return 0; -} - static void intel_begin_crtc_commit(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { @@ -13770,8 +13747,6 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) fbc->possible_framebuffer_bits |= primary->frontbuffer_bit; } - primary->check_plane = intel_check_primary_plane; - if (INTEL_GEN(dev_priv) >= 9) { primary->has_ccs = skl_plane_has_ccs(dev_priv, pipe, PLANE_PRIMARY); @@ -13793,6 +13768,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->update_plane = skl_update_plane; primary->disable_plane = skl_disable_plane; primary->get_hw_state = skl_plane_get_hw_state; + primary->check_plane = skl_plane_check; plane_funcs = &skl_plane_funcs; } else if (INTEL_GEN(dev_priv) >= 4) { @@ -13804,6 +13780,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->update_plane = i9xx_update_plane; primary->disable_plane = i9xx_disable_plane; primary->get_hw_state = i9xx_plane_get_hw_state; + primary->check_plane = i9xx_plane_check; plane_funcs = &i965_plane_funcs; } else { @@ -13815,6 +13792,7 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) primary->update_plane = i9xx_update_plane; primary->disable_plane = i9xx_disable_plane; primary->get_hw_state = i9xx_plane_get_hw_state; + primary->check_plane = i9xx_plane_check; plane_funcs = &i8xx_plane_funcs; } diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 2afe30748d38..f5cc0dc1695a 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1645,8 +1645,8 @@ void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc, u16 skl_scaler_calc_phase(int sub, bool chroma_center); int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state); -int skl_max_scale(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state, - uint32_t pixel_format); +int skl_max_scale(const struct intel_crtc_state *crtc_state, + u32 pixel_format); static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *state) { @@ -2137,7 +2137,9 @@ bool skl_plane_has_planar(struct drm_i915_private *dev_priv, unsigned int skl_plane_max_stride(struct intel_plane *plane, u32 pixel_format, u64 modifier, unsigned int rotation); - +int skl_plane_check(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state); +int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state); /* intel_tv.c */ void intel_tv_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index aa4d82e7245b..505d85291ee6 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -230,6 +230,39 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) #endif } +int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) +{ + const struct drm_framebuffer *fb = plane_state->base.fb; + struct drm_rect *src = &plane_state->base.src; + u32 src_x, src_y, src_w, src_h; + + /* + * Hardware doesn't handle subpixel coordinates. + * Adjust to (macro)pixel boundary, but be careful not to + * increase the source viewport size, because that could + * push the downscaling factor out of bounds. + */ + src_x = src->x1 >> 16; + src_w = drm_rect_width(src) >> 16; + src_y = src->y1 >> 16; + src_h = drm_rect_height(src) >> 16; + + src->x1 = src_x << 16; + src->x2 = (src_x + src_w) << 16; + src->y1 = src_y << 16; + src->y2 = (src_y + src_h) << 16; + + if (fb->format->is_yuv && + fb->format->format != DRM_FORMAT_NV12 && + (src_x & 1 || src_w & 1)) { + DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", + src_x, src_w); + return -EINVAL; + } + + return 0; +} + unsigned int skl_plane_max_stride(struct intel_plane *plane, u32 pixel_format, u64 modifier, @@ -985,146 +1018,189 @@ g4x_plane_get_hw_state(struct intel_plane *plane, } static int -intel_check_sprite_plane(struct intel_crtc_state *crtc_state, - struct intel_plane_state *state) +g4x_sprite_check_scaling(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) { - struct intel_plane *plane = to_intel_plane(state->base.plane); - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - struct drm_framebuffer *fb = state->base.fb; - int max_scale, min_scale; - int ret; - uint32_t pixel_format = 0; - - if (!fb) { - state->base.visible = false; + const struct drm_framebuffer *fb = plane_state->base.fb; + const struct drm_rect *src = &plane_state->base.src; + const struct drm_rect *dst = &plane_state->base.dst; + int src_x, src_y, src_w, src_h, crtc_w, crtc_h; + const struct drm_display_mode *adjusted_mode = + &crtc_state->base.adjusted_mode; + unsigned int cpp = fb->format->cpp[0]; + unsigned int width_bytes; + int min_width, min_height; + + crtc_w = drm_rect_width(dst); + crtc_h = drm_rect_height(dst); + + src_x = src->x1 >> 16; + src_y = src->y1 >> 16; + src_w = drm_rect_width(src) >> 16; + src_h = drm_rect_height(src) >> 16; + + if (src_w == crtc_w && src_h == crtc_h) return 0; + + min_width = 3; + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + if (src_h & 1) { + DRM_DEBUG_KMS("Source height must be even with interlaced modes\n"); + return -EINVAL; + } + min_height = 6; + } else { + min_height = 3; } - /* Don't modify another pipe's plane */ - if (plane->pipe != crtc->pipe) { - DRM_DEBUG_KMS("Wrong plane <-> crtc mapping\n"); + width_bytes = ((src_x * cpp) & 63) + src_w * cpp; + + if (src_w < min_width || src_h < min_height || + src_w > 2048 || src_h > 2048) { + DRM_DEBUG_KMS("Source dimensions (%dx%d) exceed hardware limits (%dx%d - %dx%d)\n", + src_w, src_h, min_width, min_height, 2048, 2048); return -EINVAL; } - /* FIXME check all gen limits */ - if (fb->width < 3 || fb->height < 3 || - fb->pitches[0] > plane->max_stride(plane, fb->format->format, - fb->modifier, DRM_MODE_ROTATE_0)) { - DRM_DEBUG_KMS("Unsuitable framebuffer for plane\n"); + if (width_bytes > 4096) { + DRM_DEBUG_KMS("Fetch width (%d) exceeds hardware max with scaling (%u)\n", + width_bytes, 4096); return -EINVAL; } - if (INTEL_GEN(dev_priv) >= 9) { - if (state->base.fb) - pixel_format = state->base.fb->format->format; - /* use scaler when colorkey is not required */ - if (!state->ckey.flags) { - min_scale = 1; - max_scale = - skl_max_scale(crtc, crtc_state, pixel_format); - } else { - min_scale = DRM_PLANE_HELPER_NO_SCALING; - max_scale = DRM_PLANE_HELPER_NO_SCALING; - } + if (width_bytes > 4096 || fb->pitches[0] > 4096) { + DRM_DEBUG_KMS("Stride (%u) exceeds hardware max with scaling (%u)\n", + fb->pitches[0], 4096); + return -EINVAL; + } + + return 0; +} + +static int +g4x_sprite_check(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) +{ + struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + int max_scale, min_scale; + int ret; + + if (INTEL_GEN(dev_priv) < 7) { + min_scale = 1; + max_scale = 16 << 16; + } else if (IS_IVYBRIDGE(dev_priv)) { + min_scale = 1; + max_scale = 2 << 16; } else { - if (INTEL_GEN(dev_priv) < 7) { - min_scale = 1; - max_scale = 16 << 16; - } else if (IS_IVYBRIDGE(dev_priv)) { - min_scale = 1; - max_scale = 2 << 16; - } else { - min_scale = DRM_PLANE_HELPER_NO_SCALING; - max_scale = DRM_PLANE_HELPER_NO_SCALING; - } + min_scale = DRM_PLANE_HELPER_NO_SCALING; + max_scale = DRM_PLANE_HELPER_NO_SCALING; } - ret = drm_atomic_helper_check_plane_state(&state->base, + ret = drm_atomic_helper_check_plane_state(&plane_state->base, &crtc_state->base, min_scale, max_scale, true, true); if (ret) return ret; - if (state->base.visible) { - struct drm_rect *src = &state->base.src; - struct drm_rect *dst = &state->base.dst; - unsigned int crtc_w = drm_rect_width(dst); - unsigned int crtc_h = drm_rect_height(dst); - uint32_t src_x, src_y, src_w, src_h; + if (!plane_state->base.visible) + return 0; - /* - * Hardware doesn't handle subpixel coordinates. - * Adjust to (macro)pixel boundary, but be careful not to - * increase the source viewport size, because that could - * push the downscaling factor out of bounds. - */ - src_x = src->x1 >> 16; - src_w = drm_rect_width(src) >> 16; - src_y = src->y1 >> 16; - src_h = drm_rect_height(src) >> 16; - - src->x1 = src_x << 16; - src->x2 = (src_x + src_w) << 16; - src->y1 = src_y << 16; - src->y2 = (src_y + src_h) << 16; - - if (fb->format->is_yuv && - fb->format->format != DRM_FORMAT_NV12 && - (src_x % 2 || src_w % 2)) { - DRM_DEBUG_KMS("src x/w (%u, %u) must be a multiple of 2 for YUV planes\n", - src_x, src_w); - return -EINVAL; - } + ret = intel_plane_check_src_coordinates(plane_state); + if (ret) + return ret; - /* Check size restrictions when scaling */ - if (src_w != crtc_w || src_h != crtc_h) { - unsigned int width_bytes; - int cpp = fb->format->cpp[0]; - - width_bytes = ((src_x * cpp) & 63) + src_w * cpp; - - /* FIXME interlacing min height is 6 */ - if (INTEL_GEN(dev_priv) < 9 && ( - src_w < 3 || src_h < 3 || - src_w > 2048 || src_h > 2048 || - crtc_w < 3 || crtc_h < 3 || - width_bytes > 4096 || fb->pitches[0] > 4096)) { - DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); - return -EINVAL; - } - } - } + ret = g4x_sprite_check_scaling(crtc_state, plane_state); + if (ret) + return ret; - if (INTEL_GEN(dev_priv) >= 9) { - ret = skl_check_plane_surface(crtc_state, state); - if (ret) - return ret; + ret = i9xx_check_plane_surface(plane_state); + if (ret) + return ret; - state->ctl = skl_plane_ctl(crtc_state, state); - } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - ret = i9xx_check_plane_surface(state); - if (ret) - return ret; + if (INTEL_GEN(dev_priv) >= 7) + plane_state->ctl = ivb_sprite_ctl(crtc_state, plane_state); + else + plane_state->ctl = g4x_sprite_ctl(crtc_state, plane_state); - state->ctl = vlv_sprite_ctl(crtc_state, state); - } else if (INTEL_GEN(dev_priv) >= 7) { - ret = i9xx_check_plane_surface(state); - if (ret) - return ret; + return 0; +} - state->ctl = ivb_sprite_ctl(crtc_state, state); - } else { - ret = i9xx_check_plane_surface(state); - if (ret) - return ret; +static int +vlv_sprite_check(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) +{ + int ret; + + ret = drm_atomic_helper_check_plane_state(&plane_state->base, + &crtc_state->base, + DRM_PLANE_HELPER_NO_SCALING, + DRM_PLANE_HELPER_NO_SCALING, + true, true); + if (ret) + return ret; + + if (!plane_state->base.visible) + return 0; + + ret = intel_plane_check_src_coordinates(plane_state); + if (ret) + return ret; + + ret = i9xx_check_plane_surface(plane_state); + if (ret) + return ret; + + plane_state->ctl = vlv_sprite_ctl(crtc_state, plane_state); - state->ctl = g4x_sprite_ctl(crtc_state, state); + return 0; +} + +int skl_plane_check(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) +{ + struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + int max_scale, min_scale; + int ret; + + /* use scaler when colorkey is not required */ + if (!plane_state->ckey.flags) { + const struct drm_framebuffer *fb = plane_state->base.fb; + + min_scale = 1; + max_scale = skl_max_scale(crtc_state, + fb ? fb->format->format : 0); + } else { + min_scale = DRM_PLANE_HELPER_NO_SCALING; + max_scale = DRM_PLANE_HELPER_NO_SCALING; } + ret = drm_atomic_helper_check_plane_state(&plane_state->base, + &crtc_state->base, + min_scale, max_scale, + true, true); + if (ret) + return ret; + + if (!plane_state->base.visible) + return 0; + + ret = intel_plane_check_src_coordinates(plane_state); + if (ret) + return ret; + + ret = skl_check_plane_surface(crtc_state, plane_state); + if (ret) + return ret; + + plane_state->ctl = skl_plane_ctl(crtc_state, plane_state); + if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) - state->color_ctl = glk_plane_color_ctl(crtc_state, state); + plane_state->color_ctl = glk_plane_color_ctl(crtc_state, + plane_state); return 0; } @@ -1560,6 +1636,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = skl_update_plane; intel_plane->disable_plane = skl_disable_plane; intel_plane->get_hw_state = skl_plane_get_hw_state; + intel_plane->check_plane = skl_plane_check; if (skl_plane_has_planar(dev_priv, pipe, PLANE_SPRITE0 + plane)) { @@ -1581,6 +1658,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = vlv_update_plane; intel_plane->disable_plane = vlv_disable_plane; intel_plane->get_hw_state = vlv_plane_get_hw_state; + intel_plane->check_plane = vlv_sprite_check; plane_formats = vlv_plane_formats; num_plane_formats = ARRAY_SIZE(vlv_plane_formats); @@ -1592,6 +1670,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = ivb_update_plane; intel_plane->disable_plane = ivb_disable_plane; intel_plane->get_hw_state = ivb_plane_get_hw_state; + intel_plane->check_plane = g4x_sprite_check; plane_formats = snb_plane_formats; num_plane_formats = ARRAY_SIZE(snb_plane_formats); @@ -1603,6 +1682,7 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->update_plane = g4x_update_plane; intel_plane->disable_plane = g4x_disable_plane; intel_plane->get_hw_state = g4x_plane_get_hw_state; + intel_plane->check_plane = g4x_sprite_check; modifiers = i9xx_plane_format_modifiers; if (IS_GEN6(dev_priv)) { @@ -1635,7 +1715,6 @@ intel_sprite_plane_create(struct drm_i915_private *dev_priv, intel_plane->i9xx_plane = plane; intel_plane->id = PLANE_SPRITE0 + plane; intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER(pipe, intel_plane->id); - intel_plane->check_plane = intel_check_sprite_plane; possible_crtcs = (1 << pipe); -- cgit From e21c2d33101871b85fe9fbb2fc6ef365b2773b67 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:10 +0300 Subject: drm/i915: Move skl plane fb related checks into a better place MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the skl+ specific framebuffer related checks from intel_plane_atomic_check_with_state() into a new function (skl_plane_check_fb()) which we'll simply call from the skl plane->check() hook. v2: Split out the Y/Yf+CCS vs. interlaced change (José) Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-11-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic_plane.c | 44 --------------------- drivers/gpu/drm/i915/intel_display.c | 12 ------ drivers/gpu/drm/i915/intel_sprite.c | 66 +++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 56 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index fa7df5fe154b..7c0873060934 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -116,40 +116,11 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ struct drm_i915_private *dev_priv = to_i915(plane->dev); struct drm_plane_state *state = &intel_state->base; struct intel_plane *intel_plane = to_intel_plane(plane); - const struct drm_display_mode *adjusted_mode = - &crtc_state->base.adjusted_mode; int ret; if (!intel_state->base.crtc && !old_plane_state->base.crtc) return 0; - if (state->fb && drm_rotation_90_or_270(state->rotation)) { - struct drm_format_name_buf format_name; - - if (state->fb->modifier != I915_FORMAT_MOD_Y_TILED && - state->fb->modifier != I915_FORMAT_MOD_Yf_TILED) { - DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n"); - return -EINVAL; - } - - /* - * 90/270 is not allowed with RGB64 16:16:16:16, - * RGB 16-bit 5:6:5, and Indexed 8-bit. - * TBD: Add RGB64 case once its added in supported format list. - */ - switch (state->fb->format->format) { - case DRM_FORMAT_C8: - case DRM_FORMAT_RGB565: - DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", - drm_get_format_name(state->fb->format->format, - &format_name)); - return -EINVAL; - - default: - break; - } - } - /* CHV ignores the mirror bit when the rotate bit is set :( */ if (IS_CHERRYVIEW(dev_priv) && state->rotation & DRM_MODE_ROTATE_180 && @@ -163,21 +134,6 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ if (ret) return ret; - /* - * Y-tiling is not supported in IF-ID Interlace mode in - * GEN9 and above. - */ - if (state->fb && INTEL_GEN(dev_priv) >= 9 && crtc_state->base.enable && - adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { - if (state->fb->modifier == I915_FORMAT_MOD_Y_TILED || - state->fb->modifier == I915_FORMAT_MOD_Yf_TILED || - state->fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || - state->fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS) { - DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n"); - return -EINVAL; - } - } - /* FIXME pre-g4x don't work like this */ if (state->visible) crtc_state->active_planes |= BIT(intel_plane->id); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7738c1a0eab0..ca1d07c88771 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3155,12 +3155,6 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) int y = src_y / vsub; u32 offset; - if (plane_state->base.rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180)) { - DRM_DEBUG_KMS("RC support only with 0/180 degree rotation %x\n", - plane_state->base.rotation); - return -EINVAL; - } - intel_add_fb_offsets(&x, &y, plane_state, 1); offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 1); @@ -3182,12 +3176,6 @@ int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation); plane_state->color_plane[1].stride = intel_fb_pitch(fb, 1, rotation); - if (rotation & DRM_MODE_REFLECT_X && - fb->modifier == DRM_FORMAT_MOD_LINEAR) { - DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n"); - return -EINVAL; - } - if (!plane_state->base.visible) return 0; diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 505d85291ee6..5fd425ac1b3b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1158,6 +1158,68 @@ vlv_sprite_check(struct intel_crtc_state *crtc_state, return 0; } +static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + const struct drm_framebuffer *fb = plane_state->base.fb; + unsigned int rotation = plane_state->base.rotation; + struct drm_format_name_buf format_name; + + if (!fb) + return 0; + + if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) && + (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS && + fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) { + DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n", + rotation); + return -EINVAL; + } + + if (rotation & DRM_MODE_REFLECT_X && + fb->modifier == DRM_FORMAT_MOD_LINEAR) { + DRM_DEBUG_KMS("horizontal flip is not supported with linear surface formats\n"); + return -EINVAL; + } + + if (drm_rotation_90_or_270(rotation)) { + if (fb->modifier != I915_FORMAT_MOD_Y_TILED && + fb->modifier != I915_FORMAT_MOD_Yf_TILED) { + DRM_DEBUG_KMS("Y/Yf tiling required for 90/270!\n"); + return -EINVAL; + } + + /* + * 90/270 is not allowed with RGB64 16:16:16:16, + * RGB 16-bit 5:6:5, and Indexed 8-bit. + * TBD: Add RGB64 case once its added in supported format list. + */ + switch (fb->format->format) { + case DRM_FORMAT_C8: + case DRM_FORMAT_RGB565: + DRM_DEBUG_KMS("Unsupported pixel format %s for 90/270!\n", + drm_get_format_name(fb->format->format, + &format_name)); + return -EINVAL; + default: + break; + } + } + + /* Y-tiling is not supported in IF-ID Interlace mode */ + if (crtc_state->base.enable && + crtc_state->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE && + (fb->modifier == I915_FORMAT_MOD_Y_TILED || + fb->modifier == I915_FORMAT_MOD_Yf_TILED || + fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || + fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) { + DRM_DEBUG_KMS("Y/Yf tiling not supported in IF-ID mode\n"); + return -EINVAL; + } + + return 0; +} + int skl_plane_check(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { @@ -1166,6 +1228,10 @@ int skl_plane_check(struct intel_crtc_state *crtc_state, int max_scale, min_scale; int ret; + ret = skl_plane_check_fb(crtc_state, plane_state); + if (ret) + return ret; + /* use scaler when colorkey is not required */ if (!plane_state->ckey.flags) { const struct drm_framebuffer *fb = plane_state->base.fb; -- cgit From 7326659513fae805c13f71e8b956ef52abaa289a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:11 +0300 Subject: drm/i915: Move display w/a #1175 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the display w/a #1175 to a better place. That place being the new skl+ specific plane->check() hook. This leaves the skl_check_plane_surface() stuff to deal with the gtt offset and src coordinate stuff as originally envisioned. Reviewed-by: Rodrigo Vivi Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-12-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 36 +++++------------------------------- drivers/gpu/drm/i915/intel_drv.h | 3 +-- drivers/gpu/drm/i915/intel_sprite.c | 36 +++++++++++++++++++++++++++++++++++- 3 files changed, 41 insertions(+), 34 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index ca1d07c88771..791314b698fb 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2991,20 +2991,14 @@ static bool skl_check_main_ccs_coordinates(struct intel_plane_state *plane_state return true; } -static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state) +static int skl_check_main_surface(struct intel_plane_state *plane_state) { - struct drm_i915_private *dev_priv = - to_i915(plane_state->base.plane->dev); const struct drm_framebuffer *fb = plane_state->base.fb; unsigned int rotation = plane_state->base.rotation; int x = plane_state->base.src.x1 >> 16; int y = plane_state->base.src.y1 >> 16; int w = drm_rect_width(&plane_state->base.src) >> 16; int h = drm_rect_height(&plane_state->base.src) >> 16; - int dst_x = plane_state->base.dst.x1; - int dst_w = drm_rect_width(&plane_state->base.dst); - int pipe_src_w = crtc_state->pipe_src_w; int max_width = skl_max_plane_width(fb, 0, rotation); int max_height = 4096; u32 alignment, offset, aux_offset = plane_state->color_plane[1].offset; @@ -3015,24 +3009,6 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, return -EINVAL; } - /* - * Display WA #1175: cnl,glk - * Planes other than the cursor may cause FIFO underflow and display - * corruption if starting less than 4 pixels from the right edge of - * the screen. - * Besides the above WA fix the similar problem, where planes other - * than the cursor ending less than 4 pixels from the left edge of the - * screen may cause FIFO underflow and display corruption. - */ - if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) && - (dst_x + dst_w < 4 || dst_x > pipe_src_w - 4)) { - DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n", - dst_x + dst_w < 4 ? "end" : "start", - dst_x + dst_w < 4 ? dst_x + dst_w : dst_x, - 4, pipe_src_w - 4); - return -ERANGE; - } - intel_add_fb_offsets(&x, &y, plane_state, 0); offset = intel_plane_compute_aligned_offset(&x, &y, plane_state, 0); alignment = intel_surf_alignment(fb, 0); @@ -3093,8 +3069,7 @@ static int skl_check_main_surface(const struct intel_crtc_state *crtc_state, } static int -skl_check_nv12_surface(const struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state) +skl_check_nv12_surface(struct intel_plane_state *plane_state) { /* Display WA #1106 */ if (plane_state->base.rotation != @@ -3165,8 +3140,7 @@ static int skl_check_ccs_aux_surface(struct intel_plane_state *plane_state) return 0; } -int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state) +int skl_check_plane_surface(struct intel_plane_state *plane_state) { const struct drm_framebuffer *fb = plane_state->base.fb; unsigned int rotation = plane_state->base.rotation; @@ -3190,7 +3164,7 @@ int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, * the main surface setup depends on it. */ if (fb->format->format == DRM_FORMAT_NV12) { - ret = skl_check_nv12_surface(crtc_state, plane_state); + ret = skl_check_nv12_surface(plane_state); if (ret) return ret; ret = skl_check_nv12_aux_surface(plane_state); @@ -3206,7 +3180,7 @@ int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, plane_state->color_plane[1].y = 0; } - ret = skl_check_main_surface(crtc_state, plane_state); + ret = skl_check_main_surface(plane_state); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f5cc0dc1695a..d72d5a66c05f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -1660,8 +1660,7 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, u32 glk_color_ctl(const struct intel_plane_state *plane_state); u32 skl_plane_stride(const struct intel_plane_state *plane_state, int plane); -int skl_check_plane_surface(const struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state); +int skl_check_plane_surface(struct intel_plane_state *plane_state); int i9xx_check_plane_surface(struct intel_plane_state *plane_state); int skl_format_to_fourcc(int format, bool rgb_order, bool alpha); unsigned int i9xx_plane_max_stride(struct intel_plane *plane, diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 5fd425ac1b3b..206e9d055272 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1220,6 +1220,36 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, return 0; } +static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + struct drm_i915_private *dev_priv = + to_i915(plane_state->base.plane->dev); + int crtc_x = plane_state->base.dst.x1; + int crtc_w = drm_rect_width(&plane_state->base.dst); + int pipe_src_w = crtc_state->pipe_src_w; + + /* + * Display WA #1175: cnl,glk + * Planes other than the cursor may cause FIFO underflow and display + * corruption if starting less than 4 pixels from the right edge of + * the screen. + * Besides the above WA fix the similar problem, where planes other + * than the cursor ending less than 4 pixels from the left edge of the + * screen may cause FIFO underflow and display corruption. + */ + if ((IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) && + (crtc_x + crtc_w < 4 || crtc_x > pipe_src_w - 4)) { + DRM_DEBUG_KMS("requested plane X %s position %d invalid (valid range %d-%d)\n", + crtc_x + crtc_w < 4 ? "end" : "start", + crtc_x + crtc_w < 4 ? crtc_x + crtc_w : crtc_x, + 4, pipe_src_w - 4); + return -ERANGE; + } + + return 0; +} + int skl_plane_check(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { @@ -1254,11 +1284,15 @@ int skl_plane_check(struct intel_crtc_state *crtc_state, if (!plane_state->base.visible) return 0; + ret = skl_plane_check_dst_coordinates(crtc_state, plane_state); + if (ret) + return ret; + ret = intel_plane_check_src_coordinates(plane_state); if (ret) return ret; - ret = skl_check_plane_surface(crtc_state, plane_state); + ret = skl_check_plane_surface(plane_state); if (ret) return ret; -- cgit From 25721f820bebfb901ae66523332ddd9bcb568821 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:12 +0300 Subject: drm/i915: Move chv rotation checks to plane->check() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the chv rotation vs. reflections checks to the plane->check() hook, away from the (now) platform agnostic intel_plane_atomic_check_with_state(). Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-13-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_atomic_plane.c | 9 --------- drivers/gpu/drm/i915/intel_display.c | 4 ++++ drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_sprite.c | 21 +++++++++++++++++++++ 4 files changed, 26 insertions(+), 9 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_atomic_plane.c b/drivers/gpu/drm/i915/intel_atomic_plane.c index 7c0873060934..aabebe0d2e9b 100644 --- a/drivers/gpu/drm/i915/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/intel_atomic_plane.c @@ -113,7 +113,6 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ struct intel_plane_state *intel_state) { struct drm_plane *plane = intel_state->base.plane; - struct drm_i915_private *dev_priv = to_i915(plane->dev); struct drm_plane_state *state = &intel_state->base; struct intel_plane *intel_plane = to_intel_plane(plane); int ret; @@ -121,14 +120,6 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ if (!intel_state->base.crtc && !old_plane_state->base.crtc) return 0; - /* CHV ignores the mirror bit when the rotate bit is set :( */ - if (IS_CHERRYVIEW(dev_priv) && - state->rotation & DRM_MODE_ROTATE_180 && - state->rotation & DRM_MODE_REFLECT_X) { - DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n"); - return -EINVAL; - } - intel_state->base.visible = false; ret = intel_plane->check_plane(crtc_state, intel_state); if (ret) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 791314b698fb..f21faa0f87d4 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3323,6 +3323,10 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state, { int ret; + ret = chv_plane_check_rotation(plane_state); + if (ret) + return ret; + ret = drm_atomic_helper_check_plane_state(&plane_state->base, &crtc_state->base, DRM_PLANE_HELPER_NO_SCALING, diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index d72d5a66c05f..521d6aaa2d44 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -2139,6 +2139,7 @@ unsigned int skl_plane_max_stride(struct intel_plane *plane, int skl_plane_check(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state); int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state); +int chv_plane_check_rotation(const struct intel_plane_state *plane_state); /* intel_tv.c */ void intel_tv_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 206e9d055272..8821e59b70ea 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1128,12 +1128,33 @@ g4x_sprite_check(struct intel_crtc_state *crtc_state, return 0; } +int chv_plane_check_rotation(const struct intel_plane_state *plane_state) +{ + struct intel_plane *plane = to_intel_plane(plane_state->base.plane); + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + unsigned int rotation = plane_state->base.rotation; + + /* CHV ignores the mirror bit when the rotate bit is set :( */ + if (IS_CHERRYVIEW(dev_priv) && + rotation & DRM_MODE_ROTATE_180 && + rotation & DRM_MODE_REFLECT_X) { + DRM_DEBUG_KMS("Cannot rotate and reflect at the same time\n"); + return -EINVAL; + } + + return 0; +} + static int vlv_sprite_check(struct intel_crtc_state *crtc_state, struct intel_plane_state *plane_state) { int ret; + ret = chv_plane_check_rotation(plane_state); + if (ret) + return ret; + ret = drm_atomic_helper_check_plane_state(&plane_state->base, &crtc_state->base, DRM_PLANE_HELPER_NO_SCALING, -- cgit From fce8d235e2ef733d00f3c94e8b23e274d61397be Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Fri, 7 Sep 2018 18:24:13 +0300 Subject: drm/i915: Extract intel_cursor_check_surface() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract intel_cursor_check_surface() to better match the code layout of the other plane types. Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180907152413.15761-14-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 47 ++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f21faa0f87d4..807784d8f5e2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9678,13 +9678,37 @@ static bool intel_cursor_size_ok(const struct intel_plane_state *plane_state) height > 0 && height <= config->cursor_height; } -static int intel_check_cursor(struct intel_crtc_state *crtc_state, - struct intel_plane_state *plane_state) +static int intel_cursor_check_surface(struct intel_plane_state *plane_state) { const struct drm_framebuffer *fb = plane_state->base.fb; unsigned int rotation = plane_state->base.rotation; int src_x, src_y; u32 offset; + + intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation); + plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation); + + src_x = plane_state->base.src_x >> 16; + src_y = plane_state->base.src_y >> 16; + + intel_add_fb_offsets(&src_x, &src_y, plane_state, 0); + offset = intel_plane_compute_aligned_offset(&src_x, &src_y, + plane_state, 0); + + if (src_x != 0 || src_y != 0) { + DRM_DEBUG_KMS("Arbitrary cursor panning not supported\n"); + return -EINVAL; + } + + plane_state->color_plane[0].offset = offset; + + return 0; +} + +static int intel_check_cursor(struct intel_crtc_state *crtc_state, + struct intel_plane_state *plane_state) +{ + const struct drm_framebuffer *fb = plane_state->base.fb; int ret; if (fb && fb->modifier != DRM_FORMAT_MOD_LINEAR) { @@ -9707,22 +9731,9 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, if (ret) return ret; - intel_fill_fb_ggtt_view(&plane_state->view, fb, rotation); - plane_state->color_plane[0].stride = intel_fb_pitch(fb, 0, rotation); - - src_x = plane_state->base.src_x >> 16; - src_y = plane_state->base.src_y >> 16; - - intel_add_fb_offsets(&src_x, &src_y, plane_state, 0); - offset = intel_plane_compute_aligned_offset(&src_x, &src_y, - plane_state, 0); - - if (src_x != 0 || src_y != 0) { - DRM_DEBUG_KMS("Arbitrary cursor panning not supported\n"); - return -EINVAL; - } - - plane_state->color_plane[0].offset = offset; + ret = intel_cursor_check_surface(plane_state); + if (ret) + return ret; return 0; } -- cgit From 722f3de39e03fe123243ef24049fcdd5491f8da3 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Wed, 12 Sep 2018 16:29:30 +0100 Subject: i915/oa: Simplify updating contexts We can remove the update-via-batch-buffer code path, which is basically an effective duplicate of update-via-context-image path, if we notice that after we have idled the GPU, we can update the context image even of the kernel context directly. (Update-via-batch-buffer path existed only to solve the problem of how to update the kernel context image.) Only additional thing needed is to activate the edited configuration by sending one empty request down the pipe. This accomplishes context restore of the updated kernel context and so the OA configuration gets written out to it's control registers. Signed-off-by: Tvrtko Ursulin Cc: Lionel Landwerlin Cc: Matthew Auld Cc: Chris Wilson Reviewed-by: Lionel Landwerlin Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180912152930.28237-1-tvrtko.ursulin@linux.intel.com --- drivers/gpu/drm/i915/i915_perf.c | 122 +++++---------------------------------- 1 file changed, 13 insertions(+), 109 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index ccb20230df2c..3d7a052b4cca 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1679,107 +1679,6 @@ static void gen8_update_reg_state_unlocked(struct i915_gem_context *ctx, } } -/* - * Same as gen8_update_reg_state_unlocked only through the batchbuffer. This - * is only used by the kernel context. - */ -static int gen8_emit_oa_config(struct i915_request *rq, - const struct i915_oa_config *oa_config) -{ - struct drm_i915_private *dev_priv = rq->i915; - /* The MMIO offsets for Flex EU registers aren't contiguous */ - u32 flex_mmio[] = { - i915_mmio_reg_offset(EU_PERF_CNTL0), - i915_mmio_reg_offset(EU_PERF_CNTL1), - i915_mmio_reg_offset(EU_PERF_CNTL2), - i915_mmio_reg_offset(EU_PERF_CNTL3), - i915_mmio_reg_offset(EU_PERF_CNTL4), - i915_mmio_reg_offset(EU_PERF_CNTL5), - i915_mmio_reg_offset(EU_PERF_CNTL6), - }; - u32 *cs; - int i; - - cs = intel_ring_begin(rq, ARRAY_SIZE(flex_mmio) * 2 + 4); - if (IS_ERR(cs)) - return PTR_ERR(cs); - - *cs++ = MI_LOAD_REGISTER_IMM(ARRAY_SIZE(flex_mmio) + 1); - - *cs++ = i915_mmio_reg_offset(GEN8_OACTXCONTROL); - *cs++ = (dev_priv->perf.oa.period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) | - (dev_priv->perf.oa.periodic ? GEN8_OA_TIMER_ENABLE : 0) | - GEN8_OA_COUNTER_RESUME; - - for (i = 0; i < ARRAY_SIZE(flex_mmio); i++) { - u32 mmio = flex_mmio[i]; - - /* - * This arbitrary default will select the 'EU FPU0 Pipeline - * Active' event. In the future it's anticipated that there - * will be an explicit 'No Event' we can select, but not - * yet... - */ - u32 value = 0; - - if (oa_config) { - u32 j; - - for (j = 0; j < oa_config->flex_regs_len; j++) { - if (i915_mmio_reg_offset(oa_config->flex_regs[j].addr) == mmio) { - value = oa_config->flex_regs[j].value; - break; - } - } - } - - *cs++ = mmio; - *cs++ = value; - } - - *cs++ = MI_NOOP; - intel_ring_advance(rq, cs); - - return 0; -} - -static int gen8_switch_to_updated_kernel_context(struct drm_i915_private *dev_priv, - const struct i915_oa_config *oa_config) -{ - struct intel_engine_cs *engine = dev_priv->engine[RCS]; - struct i915_timeline *timeline; - struct i915_request *rq; - int ret; - - lockdep_assert_held(&dev_priv->drm.struct_mutex); - - i915_retire_requests(dev_priv); - - rq = i915_request_alloc(engine, dev_priv->kernel_context); - if (IS_ERR(rq)) - return PTR_ERR(rq); - - ret = gen8_emit_oa_config(rq, oa_config); - if (ret) { - i915_request_add(rq); - return ret; - } - - /* Queue this switch after all other activity */ - list_for_each_entry(timeline, &dev_priv->gt.timelines, link) { - struct i915_request *prev; - - prev = i915_gem_active_raw(&timeline->last_request, - &dev_priv->drm.struct_mutex); - if (prev) - i915_request_await_dma_fence(rq, &prev->fence); - } - - i915_request_add(rq); - - return 0; -} - /* * Manages updating the per-context aspects of the OA stream * configuration across all contexts. @@ -1809,16 +1708,11 @@ static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, { struct intel_engine_cs *engine = dev_priv->engine[RCS]; struct i915_gem_context *ctx; + struct i915_request *rq; int ret; - unsigned int wait_flags = I915_WAIT_LOCKED; lockdep_assert_held(&dev_priv->drm.struct_mutex); - /* Switch away from any user context. */ - ret = gen8_switch_to_updated_kernel_context(dev_priv, oa_config); - if (ret) - return ret; - /* * The OA register config is setup through the context image. This image * might be written to by the GPU on context switch (in particular on @@ -1833,7 +1727,7 @@ static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, * the GPU from any submitted work. */ ret = i915_gem_wait_for_idle(dev_priv, - wait_flags, + I915_WAIT_LOCKED, MAX_SCHEDULE_TIMEOUT); if (ret) return ret; @@ -1859,7 +1753,17 @@ static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, i915_gem_object_unpin_map(ce->state->obj); } - return ret; + /* + * Apply the configuration by doing one context restore of the edited + * context image. + */ + rq = i915_request_alloc(engine, dev_priv->kernel_context); + if (IS_ERR(rq)) + return PTR_ERR(rq); + + i915_request_add(rq); + + return 0; } static int gen8_enable_metric_set(struct drm_i915_private *dev_priv, -- cgit From f6e35cda66146106cfeb85ed65696e0f8e793fee Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 13 Sep 2018 18:04:05 +0300 Subject: drm/i915: Replace some PAGE_SIZE with I915_GTT_PAGE_SIZE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use I915_GTT_PAGE_SIZE when talking about GTT pages rather than physical pages. There are some PAGE_SHIFTs left though. Not sure if we want to introduce I915_GTT_PAGE_SHIFT or what? Cc: Chris Wilson Suggested-by: Chris Wilson # at least some of it :) Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180913150405.706-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2ccb982a5dba..5ee283811b57 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2283,7 +2283,7 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg) #define for_each_sgt_dma(__dmap, __iter, __sgt) \ for ((__iter) = __sgt_iter((__sgt)->sgl, true); \ ((__dmap) = (__iter).dma + (__iter).curr); \ - (((__iter).curr += PAGE_SIZE) >= (__iter).max) ? \ + (((__iter).curr += I915_GTT_PAGE_SIZE) >= (__iter).max) ? \ (__iter) = __sgt_iter(__sg_next((__iter).sgp), true), 0 : 0) /** diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index eb0e446d6482..8be1acd097db 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1050,7 +1050,7 @@ gen8_ppgtt_insert_pte_entries(struct i915_hw_ppgtt *ppgtt, do { vaddr[idx->pte] = pte_encode | iter->dma; - iter->dma += PAGE_SIZE; + iter->dma += I915_GTT_PAGE_SIZE; if (iter->dma >= iter->max) { iter->sg = __sg_next(iter->sg); if (!iter->sg) { @@ -1759,7 +1759,7 @@ static void gen6_dump_ppgtt(struct i915_hw_ppgtt *base, struct seq_file *m) seq_printf(m, "\t\t(%03d, %04d) %08lx: ", pde, pte, - (pde * GEN6_PTES + pte) * PAGE_SIZE); + (pde * GEN6_PTES + pte) * I915_GTT_PAGE_SIZE); for (i = 0; i < 4; i++) { if (vaddr[pte + i] != scratch_pte) seq_printf(m, " %08x", vaddr[pte + i]); @@ -1899,7 +1899,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, do { vaddr[act_pte] = pte_encode | GEN6_PTE_ADDR_ENCODE(iter.dma); - iter.dma += PAGE_SIZE; + iter.dma += I915_GTT_PAGE_SIZE; if (iter.dma == iter.max) { iter.sg = __sg_next(iter.sg); if (!iter.sg) @@ -2037,7 +2037,7 @@ static int pd_vma_bind(struct i915_vma *vma, { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vma->vm); struct gen6_hw_ppgtt *ppgtt = vma->private; - u32 ggtt_offset = i915_ggtt_offset(vma) / PAGE_SIZE; + u32 ggtt_offset = i915_ggtt_offset(vma) / I915_GTT_PAGE_SIZE; struct i915_page_table *pt; unsigned int pde; @@ -2163,7 +2163,7 @@ static struct i915_hw_ppgtt *gen6_ppgtt_create(struct drm_i915_private *i915) ppgtt->base.vm.i915 = i915; ppgtt->base.vm.dma = &i915->drm.pdev->dev; - ppgtt->base.vm.total = I915_PDES * GEN6_PTES * PAGE_SIZE; + ppgtt->base.vm.total = I915_PDES * GEN6_PTES * I915_GTT_PAGE_SIZE; i915_address_space_init(&ppgtt->base.vm, i915); @@ -3023,7 +3023,7 @@ static unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl) bdw_gmch_ctl = 1 << bdw_gmch_ctl; #ifdef CONFIG_X86_32 - /* Limit 32b platforms to a 2GB GGTT: 4 << 20 / pte size * PAGE_SIZE */ + /* Limit 32b platforms to a 2GB GGTT: 4 << 20 / pte size * I915_GTT_PAGE_SIZE */ if (bdw_gmch_ctl > 4) bdw_gmch_ctl = 4; #endif @@ -3727,9 +3727,9 @@ rotate_pages(const dma_addr_t *in, unsigned int offset, * the entries so the sg list can be happily traversed. * The only thing we need are DMA addresses. */ - sg_set_page(sg, NULL, PAGE_SIZE, 0); + sg_set_page(sg, NULL, I915_GTT_PAGE_SIZE, 0); sg_dma_address(sg) = in[offset + src_idx]; - sg_dma_len(sg) = PAGE_SIZE; + sg_dma_len(sg) = I915_GTT_PAGE_SIZE; sg = sg_next(sg); src_idx -= stride; } @@ -3742,7 +3742,7 @@ static noinline struct sg_table * intel_rotate_pages(struct intel_rotation_info *rot_info, struct drm_i915_gem_object *obj) { - const unsigned long n_pages = obj->base.size / PAGE_SIZE; + const unsigned long n_pages = obj->base.size / I915_GTT_PAGE_SIZE; unsigned int size = intel_rotation_info_size(rot_info); struct sgt_iter sgt_iter; dma_addr_t dma_addr; -- cgit From 4e05047d3e0099c9b802eb643a5de0c60feccf17 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Wed, 12 Sep 2018 21:04:43 +0300 Subject: drm/i915: Fix a potential integer overflow with framebuffers extending past 4 GiB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If we have framebuffers that are >= 4GiB in size we will overflow the fb size check in intel_fill_fb_info(). Currently that is only possible with NV12 and CCS as offsets[1] may be anything between 0 and 0xffffffff. offsets[0] is currently required to be 0 so we can't hit the overflow with any single plane format (thanks to max fb size of 8kx8k and max stride of 32 KiB). In the future we may allow almost any framebuffer to exceed 4GiB in size so we really should fix the overflow. Not that the overflow is particularly dangerous. It's mostly just a sanity check against insane userspace. The display engine can't write to memory anyway so I suppose in the worst case we might anger the hw by attempting scanout past the end of the ggtt, or we might scan out some data that we're not supposed to see from other parts of the ggtt. Note that triggering this overflow depends on the driver aligning the fb height to the next tile boundary to push the calculated size above 4GiB. With linear buffers the effective tile height is one so that never happens, and the core already has a check for 32bit overflow of offsets[]+pitches[]*height. v2: Drop the unnecessary cast (Chris) Testcase: igt/kms_big_fb/x-tiled-addfb-size-offset-overflow Testcase: igt/kms_big_fb/y-tiled-addfb-size-offset-overflow Signed-off-by: Ville Syrjälä Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180912180443.28649-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 807784d8f5e2..7e206e5e60cd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2639,9 +2639,9 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv, max_size = max(max_size, offset + size); } - if (max_size * tile_size > obj->base.size) { - DRM_DEBUG_KMS("fb too big for bo (need %u bytes, have %zu bytes)\n", - max_size * tile_size, obj->base.size); + if (mul_u32_u32(max_size, tile_size) > obj->base.size) { + DRM_DEBUG_KMS("fb too big for bo (need %llu bytes, have %zu bytes)\n", + mul_u32_u32(max_size, tile_size), obj->base.size); return -EINVAL; } -- cgit From 4445930f1c4a7c38da90a64a0fd7c7cc494c55a9 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Mon, 27 Aug 2018 17:38:44 -0700 Subject: firmware/dmc/icl: load v1.07 on icelake. Add Support to load DMC on Icelake. While at it, also add support to load the firmware during system resume. v2: load firmware during system resume.(Imre) v3: enable has_csr for icelake.(Jyoti) v4: Only load the firmware in this patch Cc: Jyoti Yadav Cc: Imre Deak Cc: Rodrigo Vivi Cc: Paulo Zanoni Signed-off-by: Anusha Srivatsa Reviewed-by: Imre Deak Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180828003844.4682-2-anusha.srivatsa@intel.com --- drivers/gpu/drm/i915/intel_csr.c | 7 +++++++ drivers/gpu/drm/i915/intel_runtime_pm.c | 3 +++ 2 files changed, 10 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 14cf4c367e36..4aa8f3d6b64c 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -34,6 +34,9 @@ * low-power state and comes back to normal. */ +#define I915_CSR_ICL "i915/icl_dmc_ver1_07.bin" +#define ICL_CSR_VERSION_REQUIRED CSR_VERSION(1, 7) + #define I915_CSR_GLK "i915/glk_dmc_ver1_04.bin" MODULE_FIRMWARE(I915_CSR_GLK); #define GLK_CSR_VERSION_REQUIRED CSR_VERSION(1, 4) @@ -304,6 +307,8 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, if (csr->fw_path == i915_modparams.dmc_firmware_path) { /* Bypass version check for firmware override. */ required_version = csr->version; + } else if (IS_ICELAKE(dev_priv)) { + required_version = ICL_CSR_VERSION_REQUIRED; } else if (IS_CANNONLAKE(dev_priv)) { required_version = CNL_CSR_VERSION_REQUIRED; } else if (IS_GEMINILAKE(dev_priv)) { @@ -471,6 +476,8 @@ void intel_csr_ucode_init(struct drm_i915_private *dev_priv) if (i915_modparams.dmc_firmware_path) csr->fw_path = i915_modparams.dmc_firmware_path; + else if (IS_ICELAKE(dev_priv)) + csr->fw_path = I915_CSR_ICL; else if (IS_CANNONLAKE(dev_priv)) csr->fw_path = I915_CSR_CNL; else if (IS_GEMINILAKE(dev_priv)) diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 480dadb1047b..9bebec389de1 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -3563,6 +3563,9 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, /* 7. Setup MBUS. */ icl_mbus_init(dev_priv); + + if (resume && dev_priv->csr.dmc_payload) + intel_csr_load_program(dev_priv); } static void icl_display_core_uninit(struct drm_i915_private *dev_priv) -- cgit From cbfa59d4b331046d89c795c8e809922f345d9bd7 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Fri, 24 Aug 2018 15:02:21 +0530 Subject: drm/i915/bxt: Decode memory bandwidth and parameters This patch adds support to decode system memory bandwidth and other parameters for broxton platform, which will be used for arbitrated display memory bandwidth calculation in GEN9 based platforms and WM latency level-0 Work-around calculation on GEN9+ platforms. Changes since V1: - s/memdev_info/dram_info Changes since V2: - Adhere to i915 coding style (Rodrigo) Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180824093225.12598-2-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 117 ++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 11 ++++ drivers/gpu/drm/i915/i915_reg.h | 30 +++++++++++ 3 files changed, 158 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5dd7fc582e6f..52befc1e0912 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1063,6 +1063,117 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) intel_gvt_sanitize_options(dev_priv); } +static int +bxt_get_dram_info(struct drm_i915_private *dev_priv) +{ + struct dram_info *dram_info = &dev_priv->dram_info; + u32 dram_channels; + u32 mem_freq_khz, val; + u8 num_active_channels; + int i; + + val = I915_READ(BXT_P_CR_MC_BIOS_REQ_0_0_0); + mem_freq_khz = DIV_ROUND_UP((val & BXT_REQ_DATA_MASK) * + BXT_MEMORY_FREQ_MULTIPLIER_HZ, 1000); + + dram_channels = val & BXT_DRAM_CHANNEL_ACTIVE_MASK; + num_active_channels = hweight32(dram_channels); + + /* Each active bit represents 4-byte channel */ + dram_info->bandwidth_kbps = (mem_freq_khz * num_active_channels * 4); + + if (dram_info->bandwidth_kbps == 0) { + DRM_INFO("Couldn't get system memory bandwidth\n"); + return -EINVAL; + } + + /* + * Now read each DUNIT8/9/10/11 to check the rank of each dimms. + */ + for (i = BXT_D_CR_DRP0_DUNIT_START; i <= BXT_D_CR_DRP0_DUNIT_END; i++) { + u8 size, width; + enum dram_rank rank; + u32 tmp; + + val = I915_READ(BXT_D_CR_DRP0_DUNIT(i)); + if (val == 0xFFFFFFFF) + continue; + + dram_info->num_channels++; + tmp = val & BXT_DRAM_RANK_MASK; + + if (tmp == BXT_DRAM_RANK_SINGLE) + rank = I915_DRAM_RANK_SINGLE; + else if (tmp == BXT_DRAM_RANK_DUAL) + rank = I915_DRAM_RANK_DUAL; + else + rank = I915_DRAM_RANK_INVALID; + + tmp = val & BXT_DRAM_SIZE_MASK; + if (tmp == BXT_DRAM_SIZE_4GB) + size = 4; + else if (tmp == BXT_DRAM_SIZE_6GB) + size = 6; + else if (tmp == BXT_DRAM_SIZE_8GB) + size = 8; + else if (tmp == BXT_DRAM_SIZE_12GB) + size = 12; + else if (tmp == BXT_DRAM_SIZE_16GB) + size = 16; + else + size = 0; + + tmp = (val & BXT_DRAM_WIDTH_MASK) >> BXT_DRAM_WIDTH_SHIFT; + width = (1 << tmp) * 8; + DRM_DEBUG_KMS("dram size:%dGB width:X%d rank:%s\n", size, + width, rank == I915_DRAM_RANK_SINGLE ? "single" : + rank == I915_DRAM_RANK_DUAL ? "dual" : "unknown"); + + /* + * If any of the channel is single rank channel, + * worst case output will be same as if single rank + * memory, so consider single rank memory. + */ + if (dram_info->rank == I915_DRAM_RANK_INVALID) + dram_info->rank = rank; + else if (rank == I915_DRAM_RANK_SINGLE) + dram_info->rank = I915_DRAM_RANK_SINGLE; + } + + if (dram_info->rank == I915_DRAM_RANK_INVALID) { + DRM_INFO("couldn't get memory rank information\n"); + return -EINVAL; + } + + dram_info->valid = true; + return 0; +} + +static void +intel_get_dram_info(struct drm_i915_private *dev_priv) +{ + struct dram_info *dram_info = &dev_priv->dram_info; + int ret; + + dram_info->valid = false; + dram_info->rank = I915_DRAM_RANK_INVALID; + dram_info->bandwidth_kbps = 0; + dram_info->num_channels = 0; + + if (!IS_BROXTON(dev_priv)) + return; + + ret = bxt_get_dram_info(dev_priv); + if (ret) + return; + + DRM_DEBUG_KMS("DRAM bandwidth:%d KBps, total-channels: %u\n", + dram_info->bandwidth_kbps, dram_info->num_channels); + DRM_DEBUG_KMS("DRAM rank: %s rank\n", + (dram_info->rank == I915_DRAM_RANK_DUAL) ? + "dual" : "single"); +} + /** * i915_driver_init_hw - setup state requiring device access * @dev_priv: device private @@ -1180,6 +1291,12 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) goto err_msi; intel_opregion_setup(dev_priv); + /* + * Fill the dram structure to get the system raw bandwidth and + * dram info. This will be used for memory latency calculation. + */ + intel_get_dram_info(dev_priv); + return 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5ee283811b57..bf88006fa212 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1945,6 +1945,17 @@ struct drm_i915_private { bool distrust_bios_wm; } wm; + struct dram_info { + bool valid; + u8 num_channels; + enum dram_rank { + I915_DRAM_RANK_INVALID = 0, + I915_DRAM_RANK_SINGLE, + I915_DRAM_RANK_DUAL + } rank; + u32 bandwidth_kbps; + } dram_info; + struct i915_runtime_pm runtime_pm; struct { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c80e56959e21..a2bf669c1c34 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -9583,6 +9583,36 @@ enum skl_power_gate { #define DC_STATE_DEBUG_MASK_CORES (1 << 0) #define DC_STATE_DEBUG_MASK_MEMORY_UP (1 << 1) +#define BXT_P_CR_MC_BIOS_REQ_0_0_0 _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x7114) +#define BXT_REQ_DATA_MASK 0x3F +#define BXT_DRAM_CHANNEL_ACTIVE_SHIFT 12 +#define BXT_DRAM_CHANNEL_ACTIVE_MASK (0xF << 12) +#define BXT_MEMORY_FREQ_MULTIPLIER_HZ 133333333 + +#define BXT_D_CR_DRP0_DUNIT8 0x1000 +#define BXT_D_CR_DRP0_DUNIT9 0x1200 +#define BXT_D_CR_DRP0_DUNIT_START 8 +#define BXT_D_CR_DRP0_DUNIT_END 11 +#define BXT_D_CR_DRP0_DUNIT(x) _MMIO(MCHBAR_MIRROR_BASE_SNB + \ + _PICK_EVEN((x) - 8, BXT_D_CR_DRP0_DUNIT8,\ + BXT_D_CR_DRP0_DUNIT9)) +#define BXT_DRAM_RANK_MASK 0x3 +#define BXT_DRAM_RANK_SINGLE 0x1 +#define BXT_DRAM_RANK_DUAL 0x3 +#define BXT_DRAM_WIDTH_MASK (0x3 << 4) +#define BXT_DRAM_WIDTH_SHIFT 4 +#define BXT_DRAM_WIDTH_X8 (0x0 << 4) +#define BXT_DRAM_WIDTH_X16 (0x1 << 4) +#define BXT_DRAM_WIDTH_X32 (0x2 << 4) +#define BXT_DRAM_WIDTH_X64 (0x3 << 4) +#define BXT_DRAM_SIZE_MASK (0x7 << 6) +#define BXT_DRAM_SIZE_SHIFT 6 +#define BXT_DRAM_SIZE_4GB (0x0 << 6) +#define BXT_DRAM_SIZE_6GB (0x1 << 6) +#define BXT_DRAM_SIZE_8GB (0x2 << 6) +#define BXT_DRAM_SIZE_12GB (0x3 << 6) +#define BXT_DRAM_SIZE_16GB (0x4 << 6) + /* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register, * since on HSW we can't write to it using I915_WRITE. */ #define D_COMP_HSW _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5F0C) -- cgit From 5771caf885ae779ade0ea009ae5d5f363bb72a52 Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Fri, 24 Aug 2018 15:02:22 +0530 Subject: drm/i915/skl+: Decode memory bandwidth and parameters This patch adds support to decode system memory bandwidth and other parameters for skylake and Gen9+ platforms, which will be used for arbitrated display memory bandwidth calculation in GEN9 based platforms and WM latency level-0 Work-around calculation on GEN9+. Changes Since V1: - s/memdev_info/dram_info - create a struct to hold channel info Changes Since V2: - rewrite code to adhere i915 coding style - not valid for GLK Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180824093225.12598-3-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 145 ++++++++++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/i915_drv.h | 8 +++ drivers/gpu/drm/i915/i915_reg.h | 18 +++++ 3 files changed, 167 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 52befc1e0912..361dfcd44fe8 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1063,6 +1063,132 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) intel_gvt_sanitize_options(dev_priv); } +static enum dram_rank skl_get_dimm_rank(u8 size, u32 rank) +{ + if (size == 0) + return I915_DRAM_RANK_INVALID; + if (rank == SKL_DRAM_RANK_SINGLE) + return I915_DRAM_RANK_SINGLE; + else if (rank == SKL_DRAM_RANK_DUAL) + return I915_DRAM_RANK_DUAL; + + return I915_DRAM_RANK_INVALID; +} + +static int +skl_dram_get_channel_info(struct dram_channel_info *ch, u32 val) +{ + u32 tmp_l, tmp_s; + u32 s_val = val >> SKL_DRAM_S_SHIFT; + + if (!val) + return -EINVAL; + + tmp_l = val & SKL_DRAM_SIZE_MASK; + tmp_s = s_val & SKL_DRAM_SIZE_MASK; + + if (tmp_l == 0 && tmp_s == 0) + return -EINVAL; + + ch->l_info.size = tmp_l; + ch->s_info.size = tmp_s; + + tmp_l = (val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT; + tmp_s = (s_val & SKL_DRAM_WIDTH_MASK) >> SKL_DRAM_WIDTH_SHIFT; + ch->l_info.width = (1 << tmp_l) * 8; + ch->s_info.width = (1 << tmp_s) * 8; + + tmp_l = val & SKL_DRAM_RANK_MASK; + tmp_s = s_val & SKL_DRAM_RANK_MASK; + ch->l_info.rank = skl_get_dimm_rank(ch->l_info.size, tmp_l); + ch->s_info.rank = skl_get_dimm_rank(ch->s_info.size, tmp_s); + + if (ch->l_info.rank == I915_DRAM_RANK_DUAL || + ch->s_info.rank == I915_DRAM_RANK_DUAL) + ch->rank = I915_DRAM_RANK_DUAL; + else if (ch->l_info.rank == I915_DRAM_RANK_SINGLE && + ch->s_info.rank == I915_DRAM_RANK_SINGLE) + ch->rank = I915_DRAM_RANK_DUAL; + else + ch->rank = I915_DRAM_RANK_SINGLE; + + DRM_DEBUG_KMS("(size:width:rank) L(%dGB:X%d:%s) S(%dGB:X%d:%s)\n", + ch->l_info.size, ch->l_info.width, + ch->l_info.rank ? "dual" : "single", + ch->s_info.size, ch->s_info.width, + ch->s_info.rank ? "dual" : "single"); + + return 0; +} + +static int +skl_dram_get_channels_info(struct drm_i915_private *dev_priv) +{ + struct dram_info *dram_info = &dev_priv->dram_info; + struct dram_channel_info ch0, ch1; + u32 val; + int ret; + + val = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(&ch0, val); + if (ret == 0) + dram_info->num_channels++; + + val = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(&ch1, val); + if (ret == 0) + dram_info->num_channels++; + + if (dram_info->num_channels == 0) { + DRM_INFO("Number of memory channels is zero\n"); + return -EINVAL; + } + + /* + * If any of the channel is single rank channel, worst case output + * will be same as if single rank memory, so consider single rank + * memory. + */ + if (ch0.rank == I915_DRAM_RANK_SINGLE || + ch1.rank == I915_DRAM_RANK_SINGLE) + dram_info->rank = I915_DRAM_RANK_SINGLE; + else + dram_info->rank = max(ch0.rank, ch1.rank); + + if (dram_info->rank == I915_DRAM_RANK_INVALID) { + DRM_INFO("couldn't get memory rank information\n"); + return -EINVAL; + } + return 0; +} + +static int +skl_get_dram_info(struct drm_i915_private *dev_priv) +{ + struct dram_info *dram_info = &dev_priv->dram_info; + u32 mem_freq_khz, val; + int ret; + + ret = skl_dram_get_channels_info(dev_priv); + if (ret) + return ret; + + val = I915_READ(SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU); + mem_freq_khz = DIV_ROUND_UP((val & SKL_REQ_DATA_MASK) * + SKL_MEMORY_FREQ_MULTIPLIER_HZ, 1000); + + dram_info->bandwidth_kbps = dram_info->num_channels * + mem_freq_khz * 8; + + if (dram_info->bandwidth_kbps == 0) { + DRM_INFO("Couldn't get system memory bandwidth\n"); + return -EINVAL; + } + + dram_info->valid = true; + return 0; +} + static int bxt_get_dram_info(struct drm_i915_private *dev_priv) { @@ -1153,6 +1279,7 @@ static void intel_get_dram_info(struct drm_i915_private *dev_priv) { struct dram_info *dram_info = &dev_priv->dram_info; + char bandwidth_str[32]; int ret; dram_info->valid = false; @@ -1160,15 +1287,25 @@ intel_get_dram_info(struct drm_i915_private *dev_priv) dram_info->bandwidth_kbps = 0; dram_info->num_channels = 0; - if (!IS_BROXTON(dev_priv)) + if (INTEL_GEN(dev_priv) < 9 || IS_GEMINILAKE(dev_priv)) return; - ret = bxt_get_dram_info(dev_priv); + /* Need to calculate bandwidth only for Gen9 */ + if (IS_BROXTON(dev_priv)) + ret = bxt_get_dram_info(dev_priv); + else if (INTEL_GEN(dev_priv) == 9) + ret = skl_get_dram_info(dev_priv); + else + ret = skl_dram_get_channels_info(dev_priv); if (ret) return; - DRM_DEBUG_KMS("DRAM bandwidth:%d KBps, total-channels: %u\n", - dram_info->bandwidth_kbps, dram_info->num_channels); + if (dram_info->bandwidth_kbps) + sprintf(bandwidth_str, "%d KBps", dram_info->bandwidth_kbps); + else + sprintf(bandwidth_str, "unknown"); + DRM_DEBUG_KMS("DRAM bandwidth:%s, total-channels: %u\n", + bandwidth_str, dram_info->num_channels); DRM_DEBUG_KMS("DRAM rank: %s rank\n", (dram_info->rank == I915_DRAM_RANK_DUAL) ? "dual" : "single"); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bf88006fa212..e7eb04b01b08 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2169,6 +2169,14 @@ struct drm_i915_private { */ }; +struct dram_channel_info { + struct info { + u8 size, width; + enum dram_rank rank; + } l_info, s_info; + enum dram_rank rank; +}; + static inline struct drm_i915_private *to_i915(const struct drm_device *dev) { return container_of(dev, struct drm_i915_private, drm); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a2bf669c1c34..4948b352bf4c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -9613,6 +9613,24 @@ enum skl_power_gate { #define BXT_DRAM_SIZE_12GB (0x3 << 6) #define BXT_DRAM_SIZE_16GB (0x4 << 6) +#define SKL_MEMORY_FREQ_MULTIPLIER_HZ 266666666 +#define SKL_MC_BIOS_DATA_0_0_0_MCHBAR_PCU _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5E04) +#define SKL_REQ_DATA_MASK (0xF << 0) + +#define SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x500C) +#define SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5010) +#define SKL_DRAM_S_SHIFT 16 +#define SKL_DRAM_SIZE_MASK 0x3F +#define SKL_DRAM_WIDTH_MASK (0x3 << 8) +#define SKL_DRAM_WIDTH_SHIFT 8 +#define SKL_DRAM_WIDTH_X8 (0x0 << 8) +#define SKL_DRAM_WIDTH_X16 (0x1 << 8) +#define SKL_DRAM_WIDTH_X32 (0x2 << 8) +#define SKL_DRAM_RANK_MASK (0x1 << 10) +#define SKL_DRAM_RANK_SHIFT 10 +#define SKL_DRAM_RANK_SINGLE (0x0 << 10) +#define SKL_DRAM_RANK_DUAL (0x1 << 10) + /* Please see hsw_read_dcomp() and hsw_write_dcomp() before using this register, * since on HSW we can't write to it using I915_WRITE. */ #define D_COMP_HSW _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5F0C) -- cgit From 86b592876cb6b277e5cb3c988fc5f748fdafa16f Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Fri, 31 Aug 2018 16:39:42 +0530 Subject: drm/i915: Implement 16GB dimm wa for latency level-0 Memory with 16GB dimms require an increase of 1us in level-0 latency. This patch implements the same. Bspec: 4381 changes since V1: - s/memdev_info/dram_info - make skl_is_16gb_dimm pure function Changes since V2: - make is_16gb_dimm more generic - rebase Changes since V3: - Simplify condition (Maarten) Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180831110942.9234-1-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 33 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/intel_pm.c | 10 ++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 361dfcd44fe8..c293341a6ad6 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1075,6 +1075,21 @@ static enum dram_rank skl_get_dimm_rank(u8 size, u32 rank) return I915_DRAM_RANK_INVALID; } +static bool +skl_is_16gb_dimm(enum dram_rank rank, u8 size, u8 width) +{ + if (rank == I915_DRAM_RANK_SINGLE && width == 8 && size == 16) + return true; + else if (rank == I915_DRAM_RANK_DUAL && width == 8 && size == 32) + return true; + else if (rank == SKL_DRAM_RANK_SINGLE && width == 16 && size == 8) + return true; + else if (rank == SKL_DRAM_RANK_DUAL && width == 16 && size == 16) + return true; + + return false; +} + static int skl_dram_get_channel_info(struct dram_channel_info *ch, u32 val) { @@ -1112,6 +1127,11 @@ skl_dram_get_channel_info(struct dram_channel_info *ch, u32 val) else ch->rank = I915_DRAM_RANK_SINGLE; + ch->is_16gb_dimm = skl_is_16gb_dimm(ch->l_info.rank, ch->l_info.size, + ch->l_info.width) || + skl_is_16gb_dimm(ch->s_info.rank, ch->s_info.size, + ch->s_info.width); + DRM_DEBUG_KMS("(size:width:rank) L(%dGB:X%d:%s) S(%dGB:X%d:%s)\n", ch->l_info.size, ch->l_info.width, ch->l_info.rank ? "dual" : "single", @@ -1144,6 +1164,8 @@ skl_dram_get_channels_info(struct drm_i915_private *dev_priv) return -EINVAL; } + dram_info->valid_dimm = true; + /* * If any of the channel is single rank channel, worst case output * will be same as if single rank memory, so consider single rank @@ -1159,6 +1181,10 @@ skl_dram_get_channels_info(struct drm_i915_private *dev_priv) DRM_INFO("couldn't get memory rank information\n"); return -EINVAL; } + + if (ch0.is_16gb_dimm || ch1.is_16gb_dimm) + dram_info->is_16gb_dimm = true; + return 0; } @@ -1271,6 +1297,7 @@ bxt_get_dram_info(struct drm_i915_private *dev_priv) return -EINVAL; } + dram_info->valid_dimm = true; dram_info->valid = true; return 0; } @@ -1283,6 +1310,8 @@ intel_get_dram_info(struct drm_i915_private *dev_priv) int ret; dram_info->valid = false; + dram_info->valid_dimm = false; + dram_info->is_16gb_dimm = false; dram_info->rank = I915_DRAM_RANK_INVALID; dram_info->bandwidth_kbps = 0; dram_info->num_channels = 0; @@ -1306,9 +1335,9 @@ intel_get_dram_info(struct drm_i915_private *dev_priv) sprintf(bandwidth_str, "unknown"); DRM_DEBUG_KMS("DRAM bandwidth:%s, total-channels: %u\n", bandwidth_str, dram_info->num_channels); - DRM_DEBUG_KMS("DRAM rank: %s rank\n", + DRM_DEBUG_KMS("DRAM rank: %s rank 16GB-dimm:%s\n", (dram_info->rank == I915_DRAM_RANK_DUAL) ? - "dual" : "single"); + "dual" : "single", yesno(dram_info->is_16gb_dimm)); } /** diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e7eb04b01b08..89366c20196a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1947,6 +1947,8 @@ struct drm_i915_private { struct dram_info { bool valid; + bool valid_dimm; + bool is_16gb_dimm; u8 num_channels; enum dram_rank { I915_DRAM_RANK_INVALID = 0, @@ -2175,6 +2177,7 @@ struct dram_channel_info { enum dram_rank rank; } l_info, s_info; enum dram_rank rank; + bool is_16gb_dimm; }; static inline struct drm_i915_private *to_i915(const struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index d99e5fabe93c..09463e3d7948 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2875,6 +2875,16 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv, } } + /* + * WA Level-0 adjustment for 16GB DIMMs: SKL+ + * If we could not get dimm info enable this WA to prevent from + * any underrun. If not able to get Dimm info assume 16GB dimm + * to avoid any underrun. + */ + if (!dev_priv->dram_info.valid_dimm || + dev_priv->dram_info.is_16gb_dimm) + wm[0] += 1; + } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { uint64_t sskpd = I915_READ64(MCH_SSKPD); -- cgit From f361912aa9bfefbdf875b185fc93f2454d917b4a Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Fri, 24 Aug 2018 15:02:24 +0530 Subject: drm/i915/skl+: don't trust IPC value set by BIOS If KMS decide to disable IPC make sure we override IPC configuration set by BIOS. Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180824093225.12598-5-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 09463e3d7948..ac8177032faf 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6118,10 +6118,8 @@ void intel_enable_ipc(struct drm_i915_private *dev_priv) u32 val; /* Display WA #0477 WaDisableIPC: skl */ - if (IS_SKYLAKE(dev_priv)) { + if (IS_SKYLAKE(dev_priv)) dev_priv->ipc_enabled = false; - return; - } val = I915_READ(DISP_ARB_CTL2); -- cgit From 8a6c5447635c4039eb51801fb5dcdb8c7ef93cfb Mon Sep 17 00:00:00 2001 From: Mahesh Kumar Date: Fri, 24 Aug 2018 15:02:25 +0530 Subject: drm/i915/kbl+: Enable IPC only for symmetric memory configurations IPC may cause underflows if not used with dual channel symmetric memory configuration. Disable IPC for non symmetric configurations in affected platforms. Display WA #1141 Changes Since V1: - Re-arrange the code. - update wrapper to return if memory is symmetric (Rodrigo) Signed-off-by: Mahesh Kumar Reviewed-by: Maarten Lankhorst Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180824093225.12598-6-mahesh1.kumar@intel.com --- drivers/gpu/drm/i915/i915_drv.c | 27 ++++++++++++++++++++++----- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 5 +++++ 3 files changed, 28 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c293341a6ad6..dbe40b21fef8 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1141,21 +1141,32 @@ skl_dram_get_channel_info(struct dram_channel_info *ch, u32 val) return 0; } +static bool +intel_is_dram_symmetric(u32 val_ch0, u32 val_ch1, + struct dram_channel_info *ch0) +{ + return (val_ch0 == val_ch1 && + (ch0->s_info.size == 0 || + (ch0->l_info.size == ch0->s_info.size && + ch0->l_info.width == ch0->s_info.width && + ch0->l_info.rank == ch0->s_info.rank))); +} + static int skl_dram_get_channels_info(struct drm_i915_private *dev_priv) { struct dram_info *dram_info = &dev_priv->dram_info; struct dram_channel_info ch0, ch1; - u32 val; + u32 val_ch0, val_ch1; int ret; - val = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(&ch0, val); + val_ch0 = I915_READ(SKL_MAD_DIMM_CH0_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(&ch0, val_ch0); if (ret == 0) dram_info->num_channels++; - val = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); - ret = skl_dram_get_channel_info(&ch1, val); + val_ch1 = I915_READ(SKL_MAD_DIMM_CH1_0_0_0_MCHBAR_MCMAIN); + ret = skl_dram_get_channel_info(&ch1, val_ch1); if (ret == 0) dram_info->num_channels++; @@ -1185,6 +1196,12 @@ skl_dram_get_channels_info(struct drm_i915_private *dev_priv) if (ch0.is_16gb_dimm || ch1.is_16gb_dimm) dram_info->is_16gb_dimm = true; + dev_priv->dram_info.symmetric_memory = intel_is_dram_symmetric(val_ch0, + val_ch1, + &ch0); + + DRM_DEBUG_KMS("memory configuration is %sSymmetric memory\n", + dev_priv->dram_info.symmetric_memory ? "" : "not "); return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 89366c20196a..ea6c6f715ca6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1956,6 +1956,7 @@ struct drm_i915_private { I915_DRAM_RANK_DUAL } rank; u32 bandwidth_kbps; + bool symmetric_memory; } dram_info; struct i915_runtime_pm runtime_pm; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index ac8177032faf..1db9b8328275 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6121,6 +6121,11 @@ void intel_enable_ipc(struct drm_i915_private *dev_priv) if (IS_SKYLAKE(dev_priv)) dev_priv->ipc_enabled = false; + /* Display WA #1141: SKL:all KBL:all CFL */ + if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) && + !dev_priv->dram_info.symmetric_memory) + dev_priv->ipc_enabled = false; + val = I915_READ(DISP_ARB_CTL2); if (dev_priv->ipc_enabled) -- cgit From 430317881795172144a606b47744baf2a19b79bb Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 13 Sep 2018 14:16:26 +0100 Subject: drm/i915: Mark up a couple of KMS debug messages as such For finding the panel fitter and PLL for a particular modeset is a part of that modeset and should be included with the reset of the DRM_DEBUG_KMS. Signed-off-by: Chris Wilson Reviewed-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180913131629.3978-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_display.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 7e206e5e60cd..376173eb733d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6154,8 +6154,8 @@ static void i9xx_pfit_disable(struct intel_crtc *crtc) assert_pipe_disabled(dev_priv, crtc->pipe); - DRM_DEBUG_DRIVER("disabling pfit, current: 0x%08x\n", - I915_READ(PFIT_CONTROL)); + DRM_DEBUG_KMS("disabling pfit, current: 0x%08x\n", + I915_READ(PFIT_CONTROL)); I915_WRITE(PFIT_CONTROL, 0); } @@ -8677,8 +8677,8 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, ironlake_compute_dpll(crtc, crtc_state, NULL); if (!intel_get_shared_dpll(crtc, crtc_state, NULL)) { - DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", - pipe_name(crtc->pipe)); + DRM_DEBUG_KMS("failed to find PLL for pipe %c\n", + pipe_name(crtc->pipe)); return -EINVAL; } @@ -9245,8 +9245,8 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc, intel_get_crtc_new_encoder(state, crtc_state); if (!intel_get_shared_dpll(crtc, crtc_state, encoder)) { - DRM_DEBUG_DRIVER("failed to find PLL for pipe %c\n", - pipe_name(crtc->pipe)); + DRM_DEBUG_KMS("failed to find PLL for pipe %c\n", + pipe_name(crtc->pipe)); return -EINVAL; } } -- cgit From 11abf0c5a021af683b8fe12b0d30fb1226d60e0f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 14 Sep 2018 09:00:15 +0100 Subject: drm/i915: Limit the backpressure for i915_request allocation If we try and fail to allocate a i915_request, we apply some backpressure on the clients to throttle the memory allocations coming from i915.ko. Currently, we wait until completely idle, but this is far too heavy and leads to some situations where the only escape is to declare a client hung and reset the GPU. The intent is to only ratelimit the allocation requests and to allow ourselves to recycle requests and memory from any long queues built up by a client hog. Although the system memory is inherently a global resources, we don't want to overly penalize an unlucky client to pay the price of reaping a hog. To reduce the influence of one client on another, we can instead of waiting for the entire GPU to idle, impose a barrier on the local client. (One end goal for request allocation is for scalability to many concurrent allocators; simultaneous execbufs.) To prevent ourselves from getting caught out by long running requests (requests that may never finish without userspace intervention, whom we are blocking) we need to impose a finite timeout, ideally shorter than hangcheck. A long time ago Paul McKenney suggested that RCU users should ratelimit themselves using judicious use of cond_synchronize_rcu(). This gives us the opportunity to reduce our indefinite wait for the GPU to idle to a wait for the RCU grace period of the previous allocation along this timeline to expire, satisfying both the local and finite properties we desire for our ratelimiting. There are still a few global steps (reclaim not least amongst those!) when we exhaust the immediate slab pool, at least now the wait is itself decoupled from struct_mutex for our glorious highly parallel future! Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=106680 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Cc: Daniel Vetter Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180914080017.30308-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_request.c | 14 ++++++++------ drivers/gpu/drm/i915/i915_request.h | 8 ++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 09ed48833b54..a492385b2089 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -732,13 +732,13 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx) rq = kmem_cache_alloc(i915->requests, GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN); if (unlikely(!rq)) { + i915_retire_requests(i915); + /* Ratelimit ourselves to prevent oom from malicious clients */ - ret = i915_gem_wait_for_idle(i915, - I915_WAIT_LOCKED | - I915_WAIT_INTERRUPTIBLE, - MAX_SCHEDULE_TIMEOUT); - if (ret) - goto err_unreserve; + rq = i915_gem_active_raw(&ce->ring->timeline->last_request, + &i915->drm.struct_mutex); + if (rq) + cond_synchronize_rcu(rq->rcustate); /* * We've forced the client to stall and catch up with whatever @@ -758,6 +758,8 @@ i915_request_alloc(struct intel_engine_cs *engine, struct i915_gem_context *ctx) } } + rq->rcustate = get_state_synchronize_rcu(); + INIT_LIST_HEAD(&rq->active_list); rq->i915 = i915; rq->engine = engine; diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index 9898301ab7ef..7fa94b024968 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -100,6 +100,14 @@ struct i915_request { struct i915_timeline *timeline; struct intel_signal_node signaling; + /* + * The rcu epoch of when this request was allocated. Used to judiciously + * apply backpressure on future allocations to ensure that under + * mempressure there is sufficient RCU ticks for us to reclaim our + * RCU protected slabs. + */ + unsigned long rcustate; + /* * Fences for the various phases in the request's lifetime. * -- cgit From 22495b68f954c9018fd52bc620292cc80df2e418 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 14 Sep 2018 09:00:16 +0100 Subject: drm/i915: Flush the tasklet when checking for idle In order to reduce latency when checking for idle we kick the tasklet directly. Sometimes this is not enough as it is queued on another cpu and so to improve the accuracy of this idle-check (and so to reduce latency overall by avoiding another pass, or worse declaring a timeout!) wait for the tasklet to complete. References: https://bugs.freedesktop.org/show_bug.cgi?id=107916 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Cc: Michel Thierry Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180914080017.30308-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_engine_cs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 10cd051ba29e..217ed3ee1cab 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -990,6 +990,9 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine) } local_bh_enable(); + /* Otherwise flush the tasklet if it was on another cpu */ + tasklet_unlock_wait(t); + if (READ_ONCE(engine->execlists.active)) return false; } -- cgit From dee60ca1f35234d890977c095410ed6ac1dcfc33 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 14 Sep 2018 13:35:02 +0100 Subject: drm/i915/execlists: Delay updating ring register state after resume Now that we reload both RING_HEAD and RING_TAIL when rebinding the context, we do not need to scrub those registers immediately on resume. v2: Handle the perma-pinned contexts. v3: Set RING_TAIL on context-pin so that we always have known state in the context image for the ring registers and all parties have similar code (ripe for refactoring). Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180914123504.2062-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 9b1f0e5211a0..d7fcbba8e982 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1338,11 +1338,13 @@ __execlists_context_pin(struct intel_engine_cs *engine, intel_lr_context_descriptor_update(ctx, engine, ce); + GEM_BUG_ON(!intel_ring_offset_valid(ce->ring, ce->ring->head)); + ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = i915_ggtt_offset(ce->ring->vma); - GEM_BUG_ON(!intel_ring_offset_valid(ce->ring, ce->ring->head)); - ce->lrc_reg_state[CTX_RING_HEAD+1] = ce->ring->head; + ce->lrc_reg_state[CTX_RING_HEAD + 1] = ce->ring->head; + ce->lrc_reg_state[CTX_RING_TAIL + 1] = ce->ring->tail; ce->state->obj->pin_global++; i915_gem_context_get(ctx); @@ -2841,13 +2843,14 @@ error_deref_obj: return ret; } -void intel_lr_context_resume(struct drm_i915_private *dev_priv) +void intel_lr_context_resume(struct drm_i915_private *i915) { struct intel_engine_cs *engine; struct i915_gem_context *ctx; enum intel_engine_id id; - /* Because we emit WA_TAIL_DWORDS there may be a disparity + /* + * Because we emit WA_TAIL_DWORDS there may be a disparity * between our bookkeeping in ce->ring->head and ce->ring->tail and * that stored in context. As we only write new commands from * ce->ring->tail onwards, everything before that is junk. If the GPU @@ -2857,28 +2860,22 @@ void intel_lr_context_resume(struct drm_i915_private *dev_priv) * So to avoid that we reset the context images upon resume. For * simplicity, we just zero everything out. */ - list_for_each_entry(ctx, &dev_priv->contexts.list, link) { - for_each_engine(engine, dev_priv, id) { + list_for_each_entry(ctx, &i915->contexts.list, link) { + for_each_engine(engine, i915, id) { struct intel_context *ce = to_intel_context(ctx, engine); - u32 *reg; if (!ce->state) continue; - reg = i915_gem_object_pin_map(ce->state->obj, - I915_MAP_WB); - if (WARN_ON(IS_ERR(reg))) - continue; - - reg += LRC_STATE_PN * PAGE_SIZE / sizeof(*reg); - reg[CTX_RING_HEAD+1] = 0; - reg[CTX_RING_TAIL+1] = 0; + intel_ring_reset(ce->ring, 0); - ce->state->obj->mm.dirty = true; - i915_gem_object_unpin_map(ce->state->obj); + if (ce->pin_count) { /* otherwise done in context_pin */ + u32 *regs = ce->lrc_reg_state; - intel_ring_reset(ce->ring, 0); + regs[CTX_RING_HEAD + 1] = ce->ring->head; + regs[CTX_RING_TAIL + 1] = ce->ring->tail; + } } } } -- cgit From 37d7c9cc2eb6620bf1130de1ca28eb1da0b8ede8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 14 Sep 2018 13:35:03 +0100 Subject: drm/i915: Check engine->default_state mapping on module load Check we can indeed acquire a WB mapping of the context image on module load. Later this will give us the opportunity to validate that we can switch from WC to WB as required. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180914123504.2062-2-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 89834ce19acd..d276fb302d4e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5416,6 +5416,7 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915) for_each_engine(engine, i915, id) { struct i915_vma *state; + void *vaddr; state = to_intel_context(ctx, engine)->state; if (!state) @@ -5438,6 +5439,16 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915) goto err_active; engine->default_state = i915_gem_object_get(state->obj); + + /* Check we can acquire the image of the context state */ + vaddr = i915_gem_object_pin_map(engine->default_state, + I915_MAP_WB); + if (IS_ERR(vaddr)) { + err = PTR_ERR(vaddr); + goto err_active; + } + + i915_gem_object_unpin_map(engine->default_state); } if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) { -- cgit From 666424abfb863e3e51fcd35baad5f242fc69d314 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 14 Sep 2018 13:35:04 +0100 Subject: drm/i915/execlists: Use coherent writes into the context image That we use a WB mapping for updating the RING_TAIL register inside the context image even on !llc machines has been a source of consternation for every reader. It appears to work on bsw+, but it may just have been that we have been incredibly bad at detecting the errors. v2: With extra enthusiasm. v3: Drop force of map type for pinned default_state as by the time we pin it, the map type is always WB and doesn't conflict with the earlier use by ce->state. v4: Transfer engine->default_state from MAP_WC to MAP_WB on creation so we do not need the MAP_FORCE littered around the backends Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180914123504.2062-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_drv.h | 6 ++++++ drivers/gpu/drm/i915/i915_gem.c | 4 +++- drivers/gpu/drm/i915/i915_perf.c | 3 ++- drivers/gpu/drm/i915/intel_lrc.c | 6 ++++-- 4 files changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ea6c6f715ca6..0509fd086130 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3096,6 +3096,12 @@ enum i915_map_type { I915_MAP_FORCE_WC = I915_MAP_WC | I915_MAP_OVERRIDE, }; +static inline enum i915_map_type +i915_coherent_map_type(struct drm_i915_private *i915) +{ + return HAS_LLC(i915) ? I915_MAP_WB : I915_MAP_WC; +} + /** * i915_gem_object_pin_map - return a contiguous mapping of the entire object * @obj: the object to map into kernel address space diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d276fb302d4e..e3c2492438b8 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5418,6 +5418,8 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915) struct i915_vma *state; void *vaddr; + GEM_BUG_ON(to_intel_context(ctx, engine)->pin_count); + state = to_intel_context(ctx, engine)->state; if (!state) continue; @@ -5442,7 +5444,7 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915) /* Check we can acquire the image of the context state */ vaddr = i915_gem_object_pin_map(engine->default_state, - I915_MAP_WB); + I915_MAP_FORCE_WB); if (IS_ERR(vaddr)) { err = PTR_ERR(vaddr); goto err_active; diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 3d7a052b4cca..664b96bb65a3 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1707,6 +1707,7 @@ static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, const struct i915_oa_config *oa_config) { struct intel_engine_cs *engine = dev_priv->engine[RCS]; + unsigned int map_type = i915_coherent_map_type(dev_priv); struct i915_gem_context *ctx; struct i915_request *rq; int ret; @@ -1741,7 +1742,7 @@ static int gen8_configure_all_contexts(struct drm_i915_private *dev_priv, if (!ce->state) continue; - regs = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB); + regs = i915_gem_object_pin_map(ce->state->obj, map_type); if (IS_ERR(regs)) return PTR_ERR(regs); diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index d7fcbba8e982..a51be16ddaac 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -1294,7 +1294,7 @@ static int __context_pin(struct i915_gem_context *ctx, struct i915_vma *vma) * on an active context (which by nature is already on the GPU). */ if (!(vma->flags & I915_VMA_GLOBAL_BIND)) { - err = i915_gem_object_set_to_gtt_domain(vma->obj, true); + err = i915_gem_object_set_to_wc_domain(vma->obj, true); if (err) return err; } @@ -1322,7 +1322,9 @@ __execlists_context_pin(struct intel_engine_cs *engine, if (ret) goto err; - vaddr = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB); + vaddr = i915_gem_object_pin_map(ce->state->obj, + i915_coherent_map_type(ctx->i915) | + I915_MAP_OVERRIDE); if (IS_ERR(vaddr)) { ret = PTR_ERR(vaddr); goto unpin_vma; -- cgit From 5791bad4bc1f624969c875616d1032227f23c25e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 14 Sep 2018 13:40:07 +0100 Subject: drm/i915: Include fence-hint for timeout warning If an asynchronous wait on a foriegn fence, we print a warning indicating which fence was not signaled. As i915_sw_fences become more common, include the debug hint (the symbol-name of the target) to help identify the waiter. E.g. [ 31.968144] Asynchronous wait on fence sw_sync:gem_eio:1 timed out (hint:submit_notify [i915]) We also want to downgrade from a warning to a notice (normal but significant condition) as the timeout is imposed and controlled by the caller (i.e. it is deliberate) and can be provoked by userspace. Signed-off-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20180914124007.18790-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_sw_fence.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 1de5173e53a2..6dbeed079ae5 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -24,13 +24,13 @@ enum { DEBUG_FENCE_NOTIFY, }; -#ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS - static void *i915_sw_fence_debug_hint(void *addr) { return (void *)(((struct i915_sw_fence *)addr)->flags & I915_SW_FENCE_MASK); } +#ifdef CONFIG_DRM_I915_SW_FENCE_DEBUG_OBJECTS + static struct debug_obj_descr i915_sw_fence_debug_descr = { .name = "i915_sw_fence", .debug_hint = i915_sw_fence_debug_hint, @@ -393,10 +393,11 @@ static void timer_i915_sw_fence_wake(struct timer_list *t) if (!fence) return; - pr_warn("asynchronous wait on fence %s:%s:%x timed out\n", - cb->dma->ops->get_driver_name(cb->dma), - cb->dma->ops->get_timeline_name(cb->dma), - cb->dma->seqno); + pr_notice("Asynchronous wait on fence %s:%s:%x timed out (hint:%pS)\n", + cb->dma->ops->get_driver_name(cb->dma), + cb->dma->ops->get_timeline_name(cb->dma), + cb->dma->seqno, + i915_sw_fence_debug_hint(fence)); i915_sw_fence_complete(fence); } -- cgit From 8db601f09127eb974e6fcf7fb30c70344d5727f6 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 14 Sep 2018 09:00:17 +0100 Subject: drm/i915/execlists: Reset CSB pointers on canceling requests (wedging) The prior assumption was that we did not need to reset the CSB on wedging when cancelling the outstanding requests as it would be cleaned up in the subsequent reset prior to restarting the GPU. However, what was not accounted for was that in preparing for the reset, we would try to process the outstanding CSB entries. If the GPU happened to complete a CS event just as we were performing the cancellation of requests, that event would be kept in the CSB until the reset -- but our bookkeeping was cleared, causing confusion when trying to complete the CS event. v2: Use a sanitize on unwedge to avoid interfering with eio suspend (where we intentionally disable GPU reset). Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107925 Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Joonas Lahtinen Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180914080017.30308-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e3c2492438b8..a94d5a308c4d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3438,6 +3438,9 @@ bool i915_gem_unset_wedged(struct drm_i915_private *i915) i915_retire_requests(i915); GEM_BUG_ON(i915->gt.active_requests); + if (!intel_gpu_reset(i915, ALL_ENGINES)) + intel_engines_sanitize(i915); + /* * Undo nop_submit_request. We prevent all new i915 requests from * being queued (by disallowing execbuf whilst wedged) so having -- cgit From 8e3ffa8d027554b5ba41131a31fcd96d248d1991 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 11 Sep 2018 12:57:47 +0100 Subject: drm/i915: Limit number of capture objects If we fail to allocate an array for a large number of user requested capture objects, reduce the array size and try to grab at least some of the objects! Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180911115810.8917-3-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gpu_error.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 8c81cf3aa182..1175fec08fe1 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1391,15 +1391,20 @@ static void request_record_user_bo(struct i915_request *request, { struct i915_capture_list *c; struct drm_i915_error_object **bo; - long count; + long count, max; - count = 0; + max = 0; for (c = request->capture_list; c; c = c->next) - count++; + max++; + if (!max) + return; - bo = NULL; - if (count) - bo = kcalloc(count, sizeof(*bo), GFP_ATOMIC); + bo = kmalloc_array(max, sizeof(*bo), GFP_ATOMIC); + if (!bo) { + /* If we can't capture everything, try to capture something. */ + max = min_t(long, max, PAGE_SIZE / sizeof(*bo)); + bo = kmalloc_array(max, sizeof(*bo), GFP_ATOMIC); + } if (!bo) return; @@ -1408,7 +1413,8 @@ static void request_record_user_bo(struct i915_request *request, bo[count] = i915_error_object_create(request->i915, c->vma); if (!bo[count]) break; - count++; + if (++count == max) + break; } ee->user_bo = bo; -- cgit From 21c62a9d16252725ec1f26707bf7db6b8ec59c7f Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 17 Sep 2018 20:14:14 +0300 Subject: drm/i915: Replace some PAGE_SHIFTs with I915_GTT_PAGE_SIZE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clean up some cases where we're dealing with GTT pages instead of system pages to use I915_GTT_PAGE_SIZE instead of PAGE_SHIT. So just replace the the shifts with mul/div as appropriate. These are the easy ones, the rest probably need some actual thought. No real changes in the generated asm. Only gen8_ppgtt_insert_4lvl() was affected as gcc decided to do the following change: - be9: 89 d9 mov %ebx,%ecx - beb: c1 e1 0c shl $0xc,%ecx - bee: 48 63 c9 movslq %ecx,%rcx + be9: 48 63 cb movslq %ebx,%rcx + bec: 48 c1 e1 0c shl $0xc,%rcx and that then shifted a bunch of the offset by one byte. I presume the sign extensions in the asm are due to integer promotions from u16 etc. Hopefully someone has confirmed that those don't end up doing the wrong thing for us. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180917171414.19220-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson --- drivers/gpu/drm/i915/i915_gem_gtt.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 8be1acd097db..4877d4d582c2 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1144,7 +1144,7 @@ static void gen8_ppgtt_insert_huge_entries(struct i915_vma *vma, vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K && IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) && (IS_ALIGNED(rem, I915_GTT_PAGE_SIZE_64K) || - rem >= (max - index) << PAGE_SHIFT)) + rem >= (max - index) * I915_GTT_PAGE_SIZE)) maybe_64K = true; vaddr = kmap_atomic_px(pt); @@ -1169,7 +1169,7 @@ static void gen8_ppgtt_insert_huge_entries(struct i915_vma *vma, if (maybe_64K && index < max && !(IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) && (IS_ALIGNED(rem, I915_GTT_PAGE_SIZE_64K) || - rem >= (max - index) << PAGE_SHIFT))) + rem >= (max - index) * I915_GTT_PAGE_SIZE))) maybe_64K = false; if (unlikely(!IS_ALIGNED(iter->dma, page_size))) @@ -1842,10 +1842,10 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, u64 start, u64 length) { struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm)); - unsigned int first_entry = start >> PAGE_SHIFT; + unsigned int first_entry = start / I915_GTT_PAGE_SIZE; unsigned int pde = first_entry / GEN6_PTES; unsigned int pte = first_entry % GEN6_PTES; - unsigned int num_entries = length >> PAGE_SHIFT; + unsigned int num_entries = length / I915_GTT_PAGE_SIZE; const gen6_pte_t scratch_pte = ppgtt->scratch_pte; while (num_entries) { @@ -1886,7 +1886,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, u32 flags) { struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); - unsigned first_entry = vma->node.start >> PAGE_SHIFT; + unsigned first_entry = vma->node.start / I915_GTT_PAGE_SIZE; unsigned act_pt = first_entry / GEN6_PTES; unsigned act_pte = first_entry % GEN6_PTES; const u32 pte_encode = vm->pte_encode(0, cache_level, flags); @@ -2456,7 +2456,7 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm, { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); gen8_pte_t __iomem *pte = - (gen8_pte_t __iomem *)ggtt->gsm + (offset >> PAGE_SHIFT); + (gen8_pte_t __iomem *)ggtt->gsm + offset / I915_GTT_PAGE_SIZE; gen8_set_pte(pte, gen8_pte_encode(addr, level, 0)); @@ -2480,7 +2480,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, */ gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm; - gtt_entries += vma->node.start >> PAGE_SHIFT; + gtt_entries += vma->node.start / I915_GTT_PAGE_SIZE; for_each_sgt_dma(addr, sgt_iter, vma->pages) gen8_set_pte(gtt_entries++, pte_encode | addr); @@ -2499,7 +2499,7 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm, { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); gen6_pte_t __iomem *pte = - (gen6_pte_t __iomem *)ggtt->gsm + (offset >> PAGE_SHIFT); + (gen6_pte_t __iomem *)ggtt->gsm + offset / I915_GTT_PAGE_SIZE; iowrite32(vm->pte_encode(addr, level, flags), pte); @@ -2519,7 +2519,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); gen6_pte_t __iomem *entries = (gen6_pte_t __iomem *)ggtt->gsm; - unsigned int i = vma->node.start >> PAGE_SHIFT; + unsigned int i = vma->node.start / I915_GTT_PAGE_SIZE; struct sgt_iter iter; dma_addr_t addr; for_each_sgt_dma(addr, iter, vma->pages) @@ -2541,8 +2541,8 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, u64 start, u64 length) { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); - unsigned first_entry = start >> PAGE_SHIFT; - unsigned num_entries = length >> PAGE_SHIFT; + unsigned first_entry = start / I915_GTT_PAGE_SIZE; + unsigned num_entries = length / I915_GTT_PAGE_SIZE; const gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, I915_CACHE_LLC, 0); gen8_pte_t __iomem *gtt_base = @@ -2657,8 +2657,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, u64 start, u64 length) { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); - unsigned first_entry = start >> PAGE_SHIFT; - unsigned num_entries = length >> PAGE_SHIFT; + unsigned first_entry = start / I915_GTT_PAGE_SIZE; + unsigned num_entries = length / I915_GTT_PAGE_SIZE; gen6_pte_t scratch_pte, __iomem *gtt_base = (gen6_pte_t __iomem *)ggtt->gsm + first_entry; const int max_entries = ggtt_total_entries(ggtt) - first_entry; @@ -3398,7 +3398,7 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) else size = gen8_get_total_gtt_size(snb_gmch_ctl); - ggtt->vm.total = (size / sizeof(gen8_pte_t)) << PAGE_SHIFT; + ggtt->vm.total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE; ggtt->vm.cleanup = gen6_gmch_remove; ggtt->vm.insert_page = gen8_ggtt_insert_page; ggtt->vm.clear_range = nop_clear_range; @@ -3456,7 +3456,7 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt) pci_read_config_word(pdev, SNB_GMCH_CTRL, &snb_gmch_ctl); size = gen6_get_total_gtt_size(snb_gmch_ctl); - ggtt->vm.total = (size / sizeof(gen6_pte_t)) << PAGE_SHIFT; + ggtt->vm.total = (size / sizeof(gen6_pte_t)) * I915_GTT_PAGE_SIZE; ggtt->vm.clear_range = gen6_ggtt_clear_range; ggtt->vm.insert_page = gen6_ggtt_insert_page; -- cgit From 1ee516ffa73107f96c1355cce5880b6c38d22d51 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 18 Sep 2018 16:10:59 +0300 Subject: drm/i915: Fix logic fumble in rotation vs. ccs check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Smatch reports: ../drivers/gpu/drm/i915/intel_sprite.c:1192 skl_plane_check_fb() warn: was || intended here instead of &&? Obviously smatch is correct here since we're trying to check if we're using either of the ccs modifiers. Since we now have is_ccs_modifier() let's use it to fix this. Cc: Dan Carpenter Cc: José Roberto de Souza Reported-by: Dan Carpenter Fixes: e21c2d331018 ("drm/i915: Move skl plane fb related checks into a better place") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180918131059.793-1-ville.syrjala@linux.intel.com Reviewed-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/intel_sprite.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 8821e59b70ea..d4c8e10fc90b 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -1190,8 +1190,7 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, return 0; if (rotation & ~(DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_180) && - (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS && - fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) { + is_ccs_modifier(fb->modifier)) { DRM_DEBUG_KMS("RC support only with 0/180 degree rotation (%x)\n", rotation); return -EINVAL; -- cgit From aa2b88074a569ac6c626c36f31b566158a4939ff Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 17 Sep 2018 18:15:03 +0300 Subject: drm/i915/sdvo: Fix multi function encoder stuff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SDVO encoders can have multiple different types of outputs hanging off them. Currently the code tries to muck around with various is_foo flags in the encoder to figure out which type its driving. That doesn't work with atomic and other stuff, so let's nuke those flags and just look at which type of connector we're actually dealing with. The is_hdmi we'll need as that's not discoverable via the output flags, but we'll just move it under the connector. We'll also move the sdvo fixed mode handling out from the .get_modes() hook into the sdvo lvds init function so that we can bail out properly if there is no fixed mode to be found. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180917151504.8754-1-ville.syrjala@linux.intel.com Reviewed-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_sdvo.c | 101 +++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 57 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 812fe7b06f87..701372e512a8 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -99,31 +99,12 @@ struct intel_sdvo { */ uint16_t hotplug_active; - /** - * This is set if we're going to treat the device as TV-out. - * - * While we have these nice friendly flags for output types that ought - * to decide this for us, the S-Video output on our HDMI+S-Video card - * shows up as RGB1 (VGA). - */ - bool is_tv; - enum port port; - /** - * This is set if we treat the device as HDMI, instead of DVI. - */ - bool is_hdmi; bool has_hdmi_monitor; bool has_hdmi_audio; bool rgb_quant_range_selectable; - /** - * This is set if we detect output of sdvo device as LVDS and - * have a valid fixed mode to use with the panel. - */ - bool is_lvds; - /** * This is sdvo fixed pannel mode pointer */ @@ -172,6 +153,11 @@ struct intel_sdvo_connector { /* this is to get the range of margin.*/ u32 max_hscan, max_vscan; + + /** + * This is set if we treat the device as HDMI, instead of DVI. + */ + bool is_hdmi; }; struct intel_sdvo_connector_state { @@ -766,6 +752,7 @@ static bool intel_sdvo_get_input_timing(struct intel_sdvo *intel_sdvo, static bool intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo, + struct intel_sdvo_connector *intel_sdvo_connector, uint16_t clock, uint16_t width, uint16_t height) @@ -778,7 +765,7 @@ intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo, args.height = height; args.interlace = 0; - if (intel_sdvo->is_lvds && + if (IS_LVDS(intel_sdvo_connector) && (intel_sdvo->sdvo_lvds_fixed_mode->hdisplay != width || intel_sdvo->sdvo_lvds_fixed_mode->vdisplay != height)) args.scaled = 1; @@ -1067,6 +1054,7 @@ intel_sdvo_set_output_timings_from_mode(struct intel_sdvo *intel_sdvo, */ static bool intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, + struct intel_sdvo_connector *intel_sdvo_connector, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { @@ -1077,6 +1065,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, return false; if (!intel_sdvo_create_preferred_input_timing(intel_sdvo, + intel_sdvo_connector, mode->clock / 10, mode->hdisplay, mode->vdisplay)) @@ -1127,6 +1116,8 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, struct intel_sdvo *intel_sdvo = to_sdvo(encoder); struct intel_sdvo_connector_state *intel_sdvo_state = to_intel_sdvo_connector_state(conn_state); + struct intel_sdvo_connector *intel_sdvo_connector = + to_intel_sdvo_connector(conn_state->connector); struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; struct drm_display_mode *mode = &pipe_config->base.mode; @@ -1142,20 +1133,22 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, * timings, even though this isn't really the right place in * the sequence to do it. Oh well. */ - if (intel_sdvo->is_tv) { + if (IS_TV(intel_sdvo_connector)) { if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, mode)) return false; (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, + intel_sdvo_connector, mode, adjusted_mode); pipe_config->sdvo_tv_clock = true; - } else if (intel_sdvo->is_lvds) { + } else if (IS_LVDS(intel_sdvo_connector)) { if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, intel_sdvo->sdvo_lvds_fixed_mode)) return false; (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, + intel_sdvo_connector, mode, adjusted_mode); } @@ -1194,11 +1187,11 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, } /* Clock computation needs to happen after pixel multiplier. */ - if (intel_sdvo->is_tv) + if (IS_TV(intel_sdvo_connector)) i9xx_adjust_sdvo_tv_clock(pipe_config); /* Set user selected PAR to incoming mode's member */ - if (intel_sdvo->is_hdmi) + if (intel_sdvo_connector->is_hdmi) adjusted_mode->picture_aspect_ratio = conn_state->picture_aspect_ratio; return true; @@ -1275,6 +1268,8 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, const struct drm_display_mode *adjusted_mode = &crtc_state->base.adjusted_mode; const struct intel_sdvo_connector_state *sdvo_state = to_intel_sdvo_connector_state(conn_state); + const struct intel_sdvo_connector *intel_sdvo_connector = + to_intel_sdvo_connector(conn_state->connector); const struct drm_display_mode *mode = &crtc_state->base.mode; struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder); u32 sdvox; @@ -1304,7 +1299,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, return; /* lvds has a special fixed output timing. */ - if (intel_sdvo->is_lvds) + if (IS_LVDS(intel_sdvo_connector)) intel_sdvo_get_dtd_from_mode(&output_dtd, intel_sdvo->sdvo_lvds_fixed_mode); else @@ -1325,13 +1320,13 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, } else intel_sdvo_set_encode(intel_sdvo, SDVO_ENCODE_DVI); - if (intel_sdvo->is_tv && + if (IS_TV(intel_sdvo_connector) && !intel_sdvo_set_tv_format(intel_sdvo, conn_state)) return; intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode); - if (intel_sdvo->is_tv || intel_sdvo->is_lvds) + if (IS_TV(intel_sdvo_connector) || IS_LVDS(intel_sdvo_connector)) input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags; if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd)) DRM_INFO("Setting input timings on %s failed\n", @@ -1630,6 +1625,8 @@ intel_sdvo_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); + struct intel_sdvo_connector *intel_sdvo_connector = + to_intel_sdvo_connector(connector); int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) @@ -1644,7 +1641,7 @@ intel_sdvo_mode_valid(struct drm_connector *connector, if (mode->clock > max_dotclk) return MODE_CLOCK_HIGH; - if (intel_sdvo->is_lvds) { + if (IS_LVDS(intel_sdvo_connector)) { if (mode->hdisplay > intel_sdvo->sdvo_lvds_fixed_mode->hdisplay) return MODE_PANEL; @@ -1759,6 +1756,8 @@ static enum drm_connector_status intel_sdvo_tmds_sink_detect(struct drm_connector *connector) { struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector); + struct intel_sdvo_connector *intel_sdvo_connector = + to_intel_sdvo_connector(connector); enum drm_connector_status status; struct edid *edid; @@ -1797,7 +1796,7 @@ intel_sdvo_tmds_sink_detect(struct drm_connector *connector) /* DDC bus is shared, match EDID to connector type */ if (edid->input & DRM_EDID_INPUT_DIGITAL) { status = connector_status_connected; - if (intel_sdvo->is_hdmi) { + if (intel_sdvo_connector->is_hdmi) { intel_sdvo->has_hdmi_monitor = drm_detect_hdmi_monitor(edid); intel_sdvo->has_hdmi_audio = drm_detect_monitor_audio(edid); intel_sdvo->rgb_quant_range_selectable = @@ -1875,17 +1874,6 @@ intel_sdvo_detect(struct drm_connector *connector, bool force) ret = connector_status_connected; } - /* May update encoder flag for like clock for SDVO TV, etc.*/ - if (ret == connector_status_connected) { - intel_sdvo->is_tv = false; - intel_sdvo->is_lvds = false; - - if (response & SDVO_TV_MASK) - intel_sdvo->is_tv = true; - if (response & SDVO_LVDS_MASK) - intel_sdvo->is_lvds = intel_sdvo->sdvo_lvds_fixed_mode != NULL; - } - return ret; } @@ -2054,16 +2042,6 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) * arranged in priority order. */ intel_ddc_get_modes(connector, &intel_sdvo->ddc); - - list_for_each_entry(newmode, &connector->probed_modes, head) { - if (newmode->type & DRM_MODE_TYPE_PREFERRED) { - intel_sdvo->sdvo_lvds_fixed_mode = - drm_mode_duplicate(connector->dev, newmode); - - intel_sdvo->is_lvds = true; - break; - } - } } static int intel_sdvo_get_modes(struct drm_connector *connector) @@ -2555,7 +2533,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) if (INTEL_GEN(dev_priv) >= 4 && intel_sdvo_is_hdmi_connector(intel_sdvo, device)) { connector->connector_type = DRM_MODE_CONNECTOR_HDMIA; - intel_sdvo->is_hdmi = true; + intel_sdvo_connector->is_hdmi = true; } if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { @@ -2563,7 +2541,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) return false; } - if (intel_sdvo->is_hdmi) + if (intel_sdvo_connector->is_hdmi) intel_sdvo_add_hdmi_properties(intel_sdvo, intel_sdvo_connector); return true; @@ -2591,8 +2569,6 @@ intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type) intel_sdvo->controlled_output |= type; intel_sdvo_connector->output_flag = type; - intel_sdvo->is_tv = true; - if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) { kfree(intel_sdvo_connector); return false; @@ -2654,6 +2630,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) struct drm_connector *connector; struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; + struct drm_display_mode *mode; DRM_DEBUG_KMS("initialising LVDS device %d\n", device); @@ -2682,6 +2659,19 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) goto err; + intel_sdvo_get_lvds_modes(connector); + + list_for_each_entry(mode, &connector->probed_modes, head) { + if (mode->type & DRM_MODE_TYPE_PREFERRED) { + intel_sdvo->sdvo_lvds_fixed_mode = + drm_mode_duplicate(connector->dev, mode); + break; + } + } + + if (!intel_sdvo->sdvo_lvds_fixed_mode) + goto err; + return true; err: @@ -2692,9 +2682,6 @@ err: static bool intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags) { - intel_sdvo->is_tv = false; - intel_sdvo->is_lvds = false; - /* SDVO requires XXX1 function may not exist unless it has XXX0 function.*/ if (flags & SDVO_OUTPUT_TMDS0) -- cgit From 9e3b5ce948f611a16e8cf1d3aa7b5387ec88ecb8 Mon Sep 17 00:00:00 2001 From: Dhinakaran Pandiyan Date: Thu, 13 Sep 2018 17:18:22 -0700 Subject: drm/i915/psr: Enable AUX-A IO power well on ICL for PSR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PSR requires AUX IO power well to be enabled. This was already in place for CNL, extend this for ICL too. Not enabling the power well results in the aux error interrupts when the hardware exits PSR. Reported-by: Casey G Bowman Reported-by: Jyoti R Yadav Cc: Matt Atwood Cc: Jyoti R Yadav Cc: Casey G Bowman Tested-by: Casey G Bowman Signed-off-by: Dhinakaran Pandiyan Reviewed-by: Imre Deak Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20180914001822.2503-1-dhinakaran.pandiyan@intel.com --- drivers/gpu/drm/i915/intel_ddi.c | 2 +- drivers/gpu/drm/i915/intel_runtime_pm.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index cd01a09c5e0f..b6910c8b4e08 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -2077,7 +2077,7 @@ out: static inline enum intel_display_power_domain intel_ddi_main_link_aux_domain(struct intel_dp *intel_dp) { - /* CNL HW requires corresponding AUX IOs to be powered up for PSR with + /* CNL+ HW requires corresponding AUX IOs to be powered up for PSR with * DC states enabled at the same time, while for driver initiated AUX * transfers we need the same AUX IOs to be powered but with DC states * disabled. Accordingly use the AUX power domain here which leaves DC diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 9bebec389de1..0fdabce647ab 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -1996,6 +1996,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, BIT_ULL(POWER_DOMAIN_PORT_DDI_F_IO)) #define ICL_AUX_A_IO_POWER_DOMAINS ( \ + BIT_ULL(POWER_DOMAIN_AUX_IO_A) | \ BIT_ULL(POWER_DOMAIN_AUX_A)) #define ICL_AUX_B_IO_POWER_DOMAINS ( \ BIT_ULL(POWER_DOMAIN_AUX_B)) -- cgit From 82c7c4fcbf84a0943b92050e08daec85f1d9670f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Sep 2018 20:55:13 +0100 Subject: drm/i915/selftests: Free the batch along the contexts error path Remember to release the batch bo reference if we hit an error trying to submit our MI_STORE_DWORD_IMM. References: https://bugs.freedesktop.org/show_bug.cgi?id=107979 Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180919195544.1511-9-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/selftests/i915_gem_context.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index 1c92560d35da..07d700b7cb94 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -195,6 +195,7 @@ err_request: i915_request_add(rq); err_batch: i915_vma_unpin(batch); + i915_vma_put(batch); err_vma: i915_vma_unpin(vma); return err; -- cgit From a47cd45a37c94bb31ccf9bf6ec3d94cbcd57d6ee Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 20 Sep 2018 11:58:09 +0100 Subject: drm/i915/selftests: Basic stress test for rapid context switching We need to exercise the HW and submission paths for switching contexts rapidly to check that features such as execlists' wa_tail are adequate. Plus it's an interesting baseline latency metric. v2: Check the initial request for allocation errors v3: Use finite waits for more robust handling of broken code Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180920105809.1872-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/selftests/i915_gem_context.c | 195 ++++++++++++++++++++++ 1 file changed, 195 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index 07d700b7cb94..441a51d4aa54 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -22,6 +22,8 @@ * */ +#include + #include "../i915_selftest.h" #include "i915_random.h" #include "igt_flush_test.h" @@ -32,6 +34,198 @@ #define DW_PER_PAGE (PAGE_SIZE / sizeof(u32)) +struct live_test { + struct drm_i915_private *i915; + const char *func; + const char *name; + + unsigned int reset_count; +}; + +static int begin_live_test(struct live_test *t, + struct drm_i915_private *i915, + const char *func, + const char *name) +{ + int err; + + t->i915 = i915; + t->func = func; + t->name = name; + + err = i915_gem_wait_for_idle(i915, + I915_WAIT_LOCKED, + MAX_SCHEDULE_TIMEOUT); + if (err) { + pr_err("%s(%s): failed to idle before, with err=%d!", + func, name, err); + return err; + } + + i915->gpu_error.missed_irq_rings = 0; + t->reset_count = i915_reset_count(&i915->gpu_error); + + return 0; +} + +static int end_live_test(struct live_test *t) +{ + struct drm_i915_private *i915 = t->i915; + + if (igt_flush_test(i915, I915_WAIT_LOCKED)) + return -EIO; + + if (t->reset_count != i915_reset_count(&i915->gpu_error)) { + pr_err("%s(%s): GPU was reset %d times!\n", + t->func, t->name, + i915_reset_count(&i915->gpu_error) - t->reset_count); + return -EIO; + } + + if (i915->gpu_error.missed_irq_rings) { + pr_err("%s(%s): Missed interrupts on engines %lx\n", + t->func, t->name, i915->gpu_error.missed_irq_rings); + return -EIO; + } + + return 0; +} + +static int live_nop_switch(void *arg) +{ + const unsigned int nctx = 1024; + struct drm_i915_private *i915 = arg; + struct intel_engine_cs *engine; + struct i915_gem_context **ctx; + enum intel_engine_id id; + struct drm_file *file; + struct live_test t; + unsigned long n; + int err = -ENODEV; + + /* + * Create as many contexts as we can feasibly get away with + * and check we can switch between them rapidly. + * + * Serves as very simple stress test for submission and HW switching + * between contexts. + */ + + if (!DRIVER_CAPS(i915)->has_logical_contexts) + return 0; + + file = mock_file(i915); + if (IS_ERR(file)) + return PTR_ERR(file); + + mutex_lock(&i915->drm.struct_mutex); + + ctx = kcalloc(nctx, sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + err = -ENOMEM; + goto out_unlock; + } + + for (n = 0; n < nctx; n++) { + ctx[n] = i915_gem_create_context(i915, file->driver_priv); + if (IS_ERR(ctx[n])) { + err = PTR_ERR(ctx[n]); + goto out_unlock; + } + } + + for_each_engine(engine, i915, id) { + struct i915_request *rq; + unsigned long end_time, prime; + ktime_t times[2] = {}; + + times[0] = ktime_get_raw(); + for (n = 0; n < nctx; n++) { + rq = i915_request_alloc(engine, ctx[n]); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + goto out_unlock; + } + i915_request_add(rq); + } + if (i915_request_wait(rq, + I915_WAIT_LOCKED, + HZ / 5) < 0) { + pr_err("Failed to populated %d contexts\n", nctx); + i915_gem_set_wedged(i915); + err = -EIO; + goto out_unlock; + } + + times[1] = ktime_get_raw(); + + pr_info("Populated %d contexts on %s in %lluns\n", + nctx, engine->name, ktime_to_ns(times[1] - times[0])); + + err = begin_live_test(&t, i915, __func__, engine->name); + if (err) + goto out_unlock; + + end_time = jiffies + i915_selftest.timeout_jiffies; + for_each_prime_number_from(prime, 2, 8192) { + times[1] = ktime_get_raw(); + + for (n = 0; n < prime; n++) { + rq = i915_request_alloc(engine, ctx[n % nctx]); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + goto out_unlock; + } + + /* + * This space is left intentionally blank. + * + * We do not actually want to perform any + * action with this request, we just want + * to measure the latency in allocation + * and submission of our breadcrumbs - + * ensuring that the bare request is sufficient + * for the system to work (i.e. proper HEAD + * tracking of the rings, interrupt handling, + * etc). It also gives us the lowest bounds + * for latency. + */ + + i915_request_add(rq); + } + if (i915_request_wait(rq, + I915_WAIT_LOCKED, + HZ / 5) < 0) { + pr_err("Switching between %ld contexts timed out\n", + prime); + i915_gem_set_wedged(i915); + break; + } + + times[1] = ktime_sub(ktime_get_raw(), times[1]); + if (prime == 2) + times[0] = times[1]; + + if (__igt_timeout(end_time, NULL)) + break; + } + + err = end_live_test(&t); + if (err) + goto out_unlock; + + pr_info("Switch latencies on %s: 1 = %lluns, %lu = %lluns\n", + engine->name, + ktime_to_ns(times[0]), + prime - 1, div64_u64(ktime_to_ns(times[1]), prime - 1)); + } + +out_unlock: + mutex_unlock(&i915->drm.struct_mutex); + mock_file_free(i915, file); + return err; +} + static struct i915_vma * gpu_fill_dw(struct i915_vma *vma, u64 offset, unsigned long count, u32 value) { @@ -714,6 +908,7 @@ int i915_gem_context_live_selftests(struct drm_i915_private *dev_priv) { static const struct i915_subtest tests[] = { SUBTEST(igt_switch_to_kernel_context), + SUBTEST(live_nop_switch), SUBTEST(igt_ctx_exec), SUBTEST(igt_ctx_readonly), }; -- cgit From 8fcd86baab7724196ae8605e58c38dd17d598ef9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 19 Sep 2018 21:54:32 +0100 Subject: drm/i915/guc: Restore preempt-context across S3/S4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stolen memory is lost across S4 (hibernate) or S3-RST as it is a portion of ordinary volatile RAM. As we allocate our rings from stolen, this may include the rings used for our preempt context and their breadcrumb instructions. In order to allow preemption following hibernation and loss of stolen memory, we therefore need to repopulate the instructions inside the lost ring upon resume. To handle both module load and resume, we simply defer constructing the ring to first use. Testcase: igt/drv_selftest/live_gem Signed-off-by: Chris Wilson Cc: Michał Winiarski Cc: Michal Wajdeczko Reviewed-by: Michał Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/20180919205432.18394-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_guc_submission.c | 80 ++++++++++------------------- 1 file changed, 27 insertions(+), 53 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_guc_submission.c b/drivers/gpu/drm/i915/intel_guc_submission.c index 07b9d313b019..a81f04d46e87 100644 --- a/drivers/gpu/drm/i915/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/intel_guc_submission.c @@ -557,16 +557,36 @@ static void inject_preempt_context(struct work_struct *work) preempt_work[engine->id]); struct intel_guc_client *client = guc->preempt_client; struct guc_stage_desc *stage_desc = __get_stage_desc(client); - u32 ctx_desc = lower_32_bits(to_intel_context(client->owner, - engine)->lrc_desc); + struct intel_context *ce = to_intel_context(client->owner, engine); u32 data[7]; - /* - * The ring contains commands to write GUC_PREEMPT_FINISHED into HWSP. - * See guc_fill_preempt_context(). - */ + if (!ce->ring->emit) { /* recreate upon load/resume */ + u32 addr = intel_hws_preempt_done_address(engine); + u32 *cs; + + cs = ce->ring->vaddr; + if (engine->id == RCS) { + cs = gen8_emit_ggtt_write_rcs(cs, + GUC_PREEMPT_FINISHED, + addr); + } else { + cs = gen8_emit_ggtt_write(cs, + GUC_PREEMPT_FINISHED, + addr); + *cs++ = MI_NOOP; + *cs++ = MI_NOOP; + } + *cs++ = MI_USER_INTERRUPT; + *cs++ = MI_NOOP; + + ce->ring->emit = GUC_PREEMPT_BREADCRUMB_BYTES; + GEM_BUG_ON((void *)cs - ce->ring->vaddr != ce->ring->emit); + + flush_ggtt_writes(ce->ring->vma); + } + spin_lock_irq(&client->wq_lock); - guc_wq_item_append(client, engine->guc_id, ctx_desc, + guc_wq_item_append(client, engine->guc_id, lower_32_bits(ce->lrc_desc), GUC_PREEMPT_BREADCRUMB_BYTES / sizeof(u64), 0); spin_unlock_irq(&client->wq_lock); @@ -1044,50 +1064,6 @@ static inline bool ctx_save_restore_disabled(struct intel_context *ce) #undef SR_DISABLED } -static void guc_fill_preempt_context(struct intel_guc *guc) -{ - struct drm_i915_private *dev_priv = guc_to_i915(guc); - struct intel_guc_client *client = guc->preempt_client; - struct intel_engine_cs *engine; - enum intel_engine_id id; - - for_each_engine(engine, dev_priv, id) { - struct intel_context *ce = - to_intel_context(client->owner, engine); - u32 addr = intel_hws_preempt_done_address(engine); - u32 *cs; - - GEM_BUG_ON(!ce->pin_count); - - /* - * We rely on this context image *not* being saved after - * preemption. This ensures that the RING_HEAD / RING_TAIL - * remain pointing at initial values forever. - */ - GEM_BUG_ON(!ctx_save_restore_disabled(ce)); - - cs = ce->ring->vaddr; - if (id == RCS) { - cs = gen8_emit_ggtt_write_rcs(cs, - GUC_PREEMPT_FINISHED, - addr); - } else { - cs = gen8_emit_ggtt_write(cs, - GUC_PREEMPT_FINISHED, - addr); - *cs++ = MI_NOOP; - *cs++ = MI_NOOP; - } - *cs++ = MI_USER_INTERRUPT; - *cs++ = MI_NOOP; - - GEM_BUG_ON((void *)cs - ce->ring->vaddr != - GUC_PREEMPT_BREADCRUMB_BYTES); - - flush_ggtt_writes(ce->ring->vma); - } -} - static int guc_clients_create(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); @@ -1118,8 +1094,6 @@ static int guc_clients_create(struct intel_guc *guc) return PTR_ERR(client); } guc->preempt_client = client; - - guc_fill_preempt_context(guc); } return 0; -- cgit From c6d22ab61bfdeb9d8572859cbc670e7335853817 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Thu, 20 Sep 2018 15:27:06 +0100 Subject: drm/i915: don't assume struct page in i915_sg_trim If we copy all the contents of the sg across and not just the page link, we can then also put it to work in fake_get_huge_pages and beyond. Signed-off-by: Matthew Auld Cc: Tvrtko Ursulin Reviewed-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180920142707.19659-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/i915_gem.c | 4 +++- drivers/gpu/drm/i915/selftests/huge_pages.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a94d5a308c4d..b79362bbd97b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2506,7 +2506,9 @@ static bool i915_sg_trim(struct sg_table *orig_st) new_sg = new_st.sgl; for_each_sg(orig_st->sgl, sg, orig_st->nents, i) { sg_set_page(new_sg, sg_page(sg), sg->length, 0); - /* called before being DMA mapped, no need to copy sg->dma_* */ + sg_dma_address(new_sg) = sg_dma_address(sg); + sg_dma_len(new_sg) = sg_dma_len(sg); + new_sg = sg_next(new_sg); } GEM_BUG_ON(new_sg); /* Should walk exactly nents and hit the end */ diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c index e272127783fe..8d03f64eabd7 100644 --- a/drivers/gpu/drm/i915/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c @@ -235,6 +235,8 @@ static int fake_get_huge_pages(struct drm_i915_gem_object *obj) sg = sg_next(sg); } while (1); + i915_sg_trim(st); + obj->mm.madv = I915_MADV_DONTNEED; __i915_gem_object_set_pages(obj, st, sg_page_sizes); -- cgit From 8c01903c171d01066b2776168774406965184269 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Thu, 20 Sep 2018 15:27:07 +0100 Subject: drm/i915: pass dev_priv to i915_gem_cleanup_stolen It really wants dev_priv anyway, also now matches i915_gem_init_stolen. Signed-off-by: Matthew Auld Cc: Joonas Lahtinen Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180920142707.19659-2-matthew.auld@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/i915_gem_stolen.c | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0509fd086130..40ae9425da3c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3339,7 +3339,7 @@ int i915_gem_stolen_insert_node_in_range(struct drm_i915_private *dev_priv, void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv, struct drm_mm_node *node); int i915_gem_init_stolen(struct drm_i915_private *dev_priv); -void i915_gem_cleanup_stolen(struct drm_device *dev); +void i915_gem_cleanup_stolen(struct drm_i915_private *dev_priv); struct drm_i915_gem_object * i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, resource_size_t size); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 4877d4d582c2..56c7f8637311 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3005,7 +3005,7 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv) arch_phys_wc_del(ggtt->mtrr); io_mapping_fini(&ggtt->iomap); - i915_gem_cleanup_stolen(&dev_priv->drm); + i915_gem_cleanup_stolen(dev_priv); } static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 53440bf87650..f29a7ff7c362 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -167,10 +167,8 @@ static int i915_adjust_stolen(struct drm_i915_private *dev_priv, return 0; } -void i915_gem_cleanup_stolen(struct drm_device *dev) +void i915_gem_cleanup_stolen(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = to_i915(dev); - if (!drm_mm_initialized(&dev_priv->mm.stolen)) return; -- cgit From b8bdd9cc6049fe8d96178001da84ac98e697a5ba Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 20 Sep 2018 15:49:34 +0100 Subject: drm/i915/selftests: Live tests emit requests and so require rpm As we emit requests or touch HW directly for some of the live tests, the requirement is that we hold the rpm wakeref before doing so. We want a mix of granularity since we will want to test runtime suspend, so try to mark up only the critical sections where we need rpm for the live test. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108002 Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180920144934.16611-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/selftests/i915_gem_coherency.c | 2 ++ drivers/gpu/drm/i915/selftests/i915_gem_context.c | 6 ++++++ drivers/gpu/drm/i915/selftests/i915_request.c | 8 ++++++++ drivers/gpu/drm/i915/selftests/intel_guc.c | 4 ++++ drivers/gpu/drm/i915/selftests/intel_lrc.c | 8 ++++++++ drivers/gpu/drm/i915/selftests/intel_workarounds.c | 5 +++++ 6 files changed, 33 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c index 4e6a221063ac..f7392c1ffe75 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_coherency.c @@ -298,6 +298,7 @@ static int igt_gem_coherency(void *arg) values = offsets + ncachelines; mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); for (over = igt_coherency_mode; over->name; over++) { if (!over->set) continue; @@ -375,6 +376,7 @@ static int igt_gem_coherency(void *arg) } } unlock: + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); kfree(offsets); return err; diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index 441a51d4aa54..76df25aa90c9 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -119,6 +119,7 @@ static int live_nop_switch(void *arg) return PTR_ERR(file); mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); ctx = kcalloc(nctx, sizeof(*ctx), GFP_KERNEL); if (!ctx) { @@ -221,6 +222,7 @@ static int live_nop_switch(void *arg) } out_unlock: + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); mock_file_free(i915, file); return err; @@ -831,6 +833,8 @@ static int igt_switch_to_kernel_context(void *arg) */ mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); + ctx = kernel_context(i915); if (IS_ERR(ctx)) { mutex_unlock(&i915->drm.struct_mutex); @@ -853,6 +857,8 @@ out_unlock: GEM_TRACE_DUMP_ON(err); if (igt_flush_test(i915, I915_WAIT_LOCKED)) err = -EIO; + + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); kernel_context_close(ctx); diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index c4aac6141e04..07e557815308 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -342,6 +342,7 @@ static int live_nop_request(void *arg) */ mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); for_each_engine(engine, i915, id) { struct i915_request *request = NULL; @@ -402,6 +403,7 @@ static int live_nop_request(void *arg) } out_unlock: + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); return err; } @@ -487,6 +489,7 @@ static int live_empty_request(void *arg) */ mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); batch = empty_batch(i915); if (IS_ERR(batch)) { @@ -550,6 +553,7 @@ out_batch: i915_vma_unpin(batch); i915_vma_put(batch); out_unlock: + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); return err; } @@ -644,6 +648,7 @@ static int live_all_engines(void *arg) */ mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); err = begin_live_test(&t, i915, __func__, ""); if (err) @@ -726,6 +731,7 @@ out_request: i915_vma_unpin(batch); i915_vma_put(batch); out_unlock: + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); return err; } @@ -747,6 +753,7 @@ static int live_sequential_engines(void *arg) */ mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); err = begin_live_test(&t, i915, __func__, ""); if (err) @@ -853,6 +860,7 @@ out_request: i915_request_put(request[id]); } out_unlock: + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); return err; } diff --git a/drivers/gpu/drm/i915/selftests/intel_guc.c b/drivers/gpu/drm/i915/selftests/intel_guc.c index 90ba88c972cf..0c0ab82b6228 100644 --- a/drivers/gpu/drm/i915/selftests/intel_guc.c +++ b/drivers/gpu/drm/i915/selftests/intel_guc.c @@ -142,6 +142,7 @@ static int igt_guc_clients(void *args) GEM_BUG_ON(!HAS_GUC(dev_priv)); mutex_lock(&dev_priv->drm.struct_mutex); + intel_runtime_pm_get(dev_priv); guc = &dev_priv->guc; if (!guc) { @@ -269,6 +270,7 @@ out: guc_clients_create(guc); guc_clients_doorbell_init(guc); unlock: + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev_priv->drm.struct_mutex); return err; } @@ -287,6 +289,7 @@ static int igt_guc_doorbells(void *arg) GEM_BUG_ON(!HAS_GUC(dev_priv)); mutex_lock(&dev_priv->drm.struct_mutex); + intel_runtime_pm_get(dev_priv); guc = &dev_priv->guc; if (!guc) { @@ -379,6 +382,7 @@ out: guc_client_free(clients[i]); } unlock: + intel_runtime_pm_put(dev_priv); mutex_unlock(&dev_priv->drm.struct_mutex); return err; } diff --git a/drivers/gpu/drm/i915/selftests/intel_lrc.c b/drivers/gpu/drm/i915/selftests/intel_lrc.c index 582566faef09..1aea7a8f2224 100644 --- a/drivers/gpu/drm/i915/selftests/intel_lrc.c +++ b/drivers/gpu/drm/i915/selftests/intel_lrc.c @@ -221,6 +221,7 @@ static int live_sanitycheck(void *arg) return 0; mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); if (spinner_init(&spin, i915)) goto err_unlock; @@ -261,6 +262,7 @@ err_spin: spinner_fini(&spin); err_unlock: igt_flush_test(i915, I915_WAIT_LOCKED); + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); return err; } @@ -278,6 +280,7 @@ static int live_preempt(void *arg) return 0; mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); if (spinner_init(&spin_hi, i915)) goto err_unlock; @@ -350,6 +353,7 @@ err_spin_hi: spinner_fini(&spin_hi); err_unlock: igt_flush_test(i915, I915_WAIT_LOCKED); + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); return err; } @@ -368,6 +372,7 @@ static int live_late_preempt(void *arg) return 0; mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); if (spinner_init(&spin_hi, i915)) goto err_unlock; @@ -440,6 +445,7 @@ err_spin_hi: spinner_fini(&spin_hi); err_unlock: igt_flush_test(i915, I915_WAIT_LOCKED); + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); return err; @@ -467,6 +473,7 @@ static int live_preempt_hang(void *arg) return 0; mutex_lock(&i915->drm.struct_mutex); + intel_runtime_pm_get(i915); if (spinner_init(&spin_hi, i915)) goto err_unlock; @@ -561,6 +568,7 @@ err_spin_hi: spinner_fini(&spin_hi); err_unlock: igt_flush_test(i915, I915_WAIT_LOCKED); + intel_runtime_pm_put(i915); mutex_unlock(&i915->drm.struct_mutex); return err; } diff --git a/drivers/gpu/drm/i915/selftests/intel_workarounds.c b/drivers/gpu/drm/i915/selftests/intel_workarounds.c index 0d39b3bf0c0d..d1a0923d2f38 100644 --- a/drivers/gpu/drm/i915/selftests/intel_workarounds.c +++ b/drivers/gpu/drm/i915/selftests/intel_workarounds.c @@ -44,7 +44,9 @@ read_nonprivs(struct i915_gem_context *ctx, struct intel_engine_cs *engine) if (err) goto err_obj; + intel_runtime_pm_get(engine->i915); rq = i915_request_alloc(engine, ctx); + intel_runtime_pm_put(engine->i915); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto err_pin; @@ -175,7 +177,10 @@ static int switch_to_scratch_context(struct intel_engine_cs *engine) if (IS_ERR(ctx)) return PTR_ERR(ctx); + intel_runtime_pm_get(engine->i915); rq = i915_request_alloc(engine, ctx); + intel_runtime_pm_put(engine->i915); + kernel_context_close(ctx); if (IS_ERR(rq)) return PTR_ERR(rq); -- cgit From 8e1cb32d515bc6b691782104b00d9056a33127c8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 20 Sep 2018 17:13:43 +0100 Subject: drm/i915: Park the GPU on module load Once we have flushed the first request through the system to both load a context and record the default state; tell the GPU to park and idle itself, putting itself immediately (hopefully at least) into a powersaving state, and allowing ourselves to start from known state after setting up all our bookkeeping. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180920161343.1117-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/i915_gem.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b79362bbd97b..db9688d14912 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5419,6 +5419,14 @@ static int __intel_engines_record_defaults(struct drm_i915_private *i915) assert_kernel_context_is_current(i915); + /* + * Immediately park the GPU so that we enable powersaving and + * treat it as idle. The next time we issue a request, we will + * unpark and start using the engine->pinned_default_state, otherwise + * it is in limbo and an early reset may fail. + */ + __i915_gem_park(i915); + for_each_engine(engine, i915, id) { struct i915_vma *state; void *vaddr; -- cgit From b2164e48155607b8aa3c3004a03768cc30558d6e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 20 Sep 2018 20:59:48 +0100 Subject: drm/i915/execlists: Onion unwind for logical_ring_init() failure Fix up the error unwind for logical_ring_init() failing by moving the cleanup into the callers who own the various bits of state during initialisation, so we don't forget to free the state allocated by the caller. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180920195948.16448-1-chris@chris-wilson.co.uk --- drivers/gpu/drm/i915/intel_lrc.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index a51be16ddaac..43957bb37a42 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -2396,7 +2396,7 @@ static int logical_ring_init(struct intel_engine_cs *engine) ret = intel_engine_init_common(engine); if (ret) - goto error; + return ret; if (HAS_LOGICAL_RING_ELSQ(i915)) { execlists->submit_reg = i915->regs + @@ -2438,10 +2438,6 @@ static int logical_ring_init(struct intel_engine_cs *engine) reset_csb_pointers(execlists); return 0; - -error: - intel_logical_ring_cleanup(engine); - return ret; } int logical_render_ring_init(struct intel_engine_cs *engine) @@ -2464,10 +2460,14 @@ int logical_render_ring_init(struct intel_engine_cs *engine) engine->emit_breadcrumb = gen8_emit_breadcrumb_rcs; engine->emit_breadcrumb_sz = gen8_emit_breadcrumb_rcs_sz; - ret = intel_engine_create_scratch(engine, PAGE_SIZE); + ret = logical_ring_init(engine); if (ret) return ret; + ret = intel_engine_create_scratch(engine, PAGE_SIZE); + if (ret) + goto err_cleanup_common; + ret = intel_init_workaround_bb(engine); if (ret) { /* @@ -2479,7 +2479,11 @@ int logical_render_ring_init(struct intel_engine_cs *engine) ret); } - return logical_ring_init(engine); + return 0; + +err_cleanup_common: + intel_engine_cleanup_common(engine); + return ret; } int logical_xcs_ring_init(struct intel_engine_cs *engine) -- cgit From 8169671ababf306e22f8cf064184032ff74eb508 Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Fri, 21 Sep 2018 10:21:00 +0300 Subject: drm/i915: Update DRIVER_DATE to 20180921 Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 40ae9425da3c..d82b912bee9a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -86,8 +86,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20180906" -#define DRIVER_TIMESTAMP 1536242083 +#define DRIVER_DATE "20180921" +#define DRIVER_TIMESTAMP 1537514460 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and * WARN_ON()) for hw state sanity checks to check for unexpected conditions -- cgit From 448626103dad54ec5d06722e955586b5d557625d Mon Sep 17 00:00:00 2001 From: Joonas Lahtinen Date: Fri, 21 Sep 2018 12:26:37 +0300 Subject: drm/i915: Update DRIVER_DATE to 20180921 Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/i915') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d82b912bee9a..808204a7ca7c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -87,7 +87,7 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" #define DRIVER_DATE "20180921" -#define DRIVER_TIMESTAMP 1537514460 +#define DRIVER_TIMESTAMP 1537521997 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and * WARN_ON()) for hw state sanity checks to check for unexpected conditions -- cgit