From 0a1b60d76b0abcc2a0de4eb96d5dd379cd855f30 Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Fri, 31 Aug 2018 10:58:52 +0800 Subject: [PATCH 1/9] drm/i915/gvt: Fix life cycle reference on KVM mm Handle guest mm access life cycle properly with mmget()/mmput(). As noted by Linus, use_mm() depends on valid live page table but KVM's mmgrab() doesn't guarantee that. As vGPU usage depends on guest VM life cycle, need to make sure to use mmget()/mmput() to guarantee VM address access. v3: fix build v2: v1 caused a weird dependence issue which failed for vfio device release, which result invalid mdev vgpu and kvm state without proper release taken. This trys to put right reference around VM address space access instead. Cc: Linus Torvalds Cc: Paolo Bonzini Cc: Zhi Wang Reviewed-by: Zhi Wang Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/kvmgt.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index a45f46d8537f..c7afee37b2b8 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -1792,16 +1793,21 @@ static int kvmgt_rw_gpa(unsigned long handle, unsigned long gpa, info = (struct kvmgt_guest_info *)handle; kvm = info->kvm; - if (kthread) + if (kthread) { + if (!mmget_not_zero(kvm->mm)) + return -EFAULT; use_mm(kvm->mm); + } idx = srcu_read_lock(&kvm->srcu); ret = write ? kvm_write_guest(kvm, gpa, buf, len) : kvm_read_guest(kvm, gpa, buf, len); srcu_read_unlock(&kvm->srcu, idx); - if (kthread) + if (kthread) { unuse_mm(kvm->mm); + mmput(kvm->mm); + } return ret; } From 792fab2c0d45758ad3d187bd252570d2bb627fa9 Mon Sep 17 00:00:00 2001 From: Weinan Li Date: Tue, 4 Sep 2018 14:13:43 +0800 Subject: [PATCH 2/9] drm/i915/gvt: Fix the incorrect length of child_device_config issue GVT-g emualte the opregion for guest with bdb version as '186' which child_device_config length should be '33'. v2: split into 2 patch. 1st for issue fix, 2nd for code clean up.(Zhenyu) v3: add fixes tag.(Zhenyu) Fixes: 4023f301d28f ("drm/i915/gvt: opregion virtualization for win") CC: Xiaolin Zhang Reviewed-by: Xiaolin Zhang Signed-off-by: Weinan Li Signed-off-by: Zhenyu Wang --- drivers/gpu/drm/i915/gvt/opregion.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c index fa75a2eead90..b0d3a43ccd03 100644 --- a/drivers/gpu/drm/i915/gvt/opregion.c +++ b/drivers/gpu/drm/i915/gvt/opregion.c @@ -42,8 +42,6 @@ #define DEVICE_TYPE_EFP3 0x20 #define DEVICE_TYPE_EFP4 0x10 -#define DEV_SIZE 38 - struct opregion_header { u8 signature[16]; u32 size; @@ -63,6 +61,10 @@ struct bdb_data_header { u16 size; /* data size */ } __packed; +/* For supporting windows guest with opregion, here hardcode the emulated + * bdb header version as '186', and the corresponding child_device_config + * length should be '33' but not '38'. + */ struct efp_child_device_config { u16 handle; u16 device_type; @@ -109,12 +111,6 @@ struct efp_child_device_config { u8 mipi_bridge_type; /* 171 */ u16 device_class_ext; u8 dvo_function; - u8 dp_usb_type_c:1; /* 195 */ - u8 skip6:7; - u8 dp_usb_type_c_2x_gpio_index; /* 195 */ - u16 dp_usb_type_c_2x_gpio_pin; /* 195 */ - u8 iboost_dp:4; /* 196 */ - u8 iboost_hdmi:4; /* 196 */ } __packed; struct vbt { @@ -155,7 +151,7 @@ static void virt_vbt_generation(struct vbt *v) v->header.bdb_offset = offsetof(struct vbt, bdb_header); strcpy(&v->bdb_header.signature[0], "BIOS_DATA_BLOCK"); - v->bdb_header.version = 186; /* child_dev_size = 38 */ + v->bdb_header.version = 186; /* child_dev_size = 33 */ v->bdb_header.header_size = sizeof(v->bdb_header); v->bdb_header.bdb_size = sizeof(struct vbt) - sizeof(struct vbt_header) @@ -169,11 +165,13 @@ static void virt_vbt_generation(struct vbt *v) /* child device */ num_child = 4; /* each port has one child */ + v->general_definitions.child_dev_size = + sizeof(struct efp_child_device_config); v->general_definitions_header.id = BDB_GENERAL_DEFINITIONS; /* size will include child devices */ v->general_definitions_header.size = - sizeof(struct bdb_general_definitions) + num_child * DEV_SIZE; - v->general_definitions.child_dev_size = DEV_SIZE; + sizeof(struct bdb_general_definitions) + + num_child * v->general_definitions.child_dev_size; /* portA */ v->child0.handle = DEVICE_TYPE_EFP1; From 92a6803149465e2339f8f7f8f6415d75be80073d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 5 Sep 2018 13:00:05 +0300 Subject: [PATCH 3/9] drm/i915/bdw: Increase IPS disable timeout to 100ms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During IPS disabling the current 42ms timeout value leads to occasional timeouts, increase it to 100ms which seems to get rid of the problem. References: https://bugs.freedesktop.org/show_bug.cgi?id=107494 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=107562 Reported-by: Diego Viola Tested-by: Diego Viola Cc: Diego Viola Cc: Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20180905100005.7663-1-imre.deak@intel.com (cherry picked from commit acb3ef0ee40ea657280a4a11d9f60eb2937c0dca) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_display.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4a3c8ee9a973..d2951096bca0 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5079,10 +5079,14 @@ void hsw_disable_ips(const struct intel_crtc_state *crtc_state) mutex_lock(&dev_priv->pcu_lock); WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); mutex_unlock(&dev_priv->pcu_lock); - /* wait for pcode to finish disabling IPS, which may take up to 42ms */ + /* + * Wait for PCODE to finish disabling IPS. The BSpec specified + * 42ms timeout value leads to occasional timeouts so use 100ms + * instead. + */ if (intel_wait_for_register(dev_priv, IPS_CTL, IPS_ENABLE, 0, - 42)) + 100)) DRM_ERROR("Timed out waiting for IPS disable\n"); } else { I915_WRITE(IPS_CTL, 0); From b463d4e53ca9bdbf227e19b477fbfcdedaa14c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 3 Sep 2018 10:51:51 +0200 Subject: [PATCH 4/9] drm/amdgpu: fix amdgpu_mn_unlock() in the CS error path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid unlocking a lock we never locked. Signed-off-by: Christian König Reviewed-by: Junwei Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index b6e9df11115d..1b5a0a73d770 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1262,10 +1262,10 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, error_abort: dma_fence_put(&job->base.s_fence->finished); job->base.s_fence = NULL; + amdgpu_mn_unlock(p->mn); error_unlock: amdgpu_job_free(job); - amdgpu_mn_unlock(p->mn); return r; } From 68ebc13ea40656fddd3803735d621921a2d74a5e Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Fri, 7 Sep 2018 13:50:31 +0800 Subject: [PATCH 5/9] drm/amdgpu: Fix SDMA hang in prt mode v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix SDMA hang in prt mode, clear XNACK_WATERMARK in reg SDMA0_UTCL1_WATERMK to avoid the issue Affected ASICs: VEGA10 VEGA12 RV1 RV2 v2: add reg clear for SDMA1 Signed-off-by: Tao Zhou Tested-by: Yukun Li Reviewed-by: Hawking Zhang Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index e7ca4623cfb9..7c3b634d8d5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -70,6 +70,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = { SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_IB_CNTL, 0x800f0100, 0x00000100), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0), + SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_IB_CNTL, 0x800f0100, 0x00000100), @@ -81,7 +82,8 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = { SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_RLC0_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_RLC1_IB_CNTL, 0x800f0100, 0x00000100), SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000), - SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_PAGE, 0x000003ff, 0x000003c0) + SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_PAGE, 0x000003ff, 0x000003c0), + SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_UTCL1_WATERMK, 0xfc000000, 0x00000000) }; static const struct soc15_reg_golden golden_settings_sdma_vg10[] = { @@ -109,7 +111,8 @@ static const struct soc15_reg_golden golden_settings_sdma_4_1[] = SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), - SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0) + SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0), + SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000) }; static const struct soc15_reg_golden golden_settings_sdma_4_2[] = From 3a74987b24279d242d17f522f8435f1942a3c948 Mon Sep 17 00:00:00 2001 From: Emily Deng Date: Mon, 10 Sep 2018 17:51:31 +0800 Subject: [PATCH 6/9] drm/amdgpu: move PSP init prior to IH in gpu reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit since we use PSP to program IH regs now Signed-off-by: Monk Liu Acked-by: Christian König Reviewed-by: Huang Rui Signed-off-by: Emily Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 8ab5ccbc14ac..39bf2ce548c6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2063,6 +2063,7 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) static enum amd_ip_block_type ip_order[] = { AMD_IP_BLOCK_TYPE_GMC, AMD_IP_BLOCK_TYPE_COMMON, + AMD_IP_BLOCK_TYPE_PSP, AMD_IP_BLOCK_TYPE_IH, }; @@ -2093,7 +2094,6 @@ static int amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device *adev) static enum amd_ip_block_type ip_order[] = { AMD_IP_BLOCK_TYPE_SMC, - AMD_IP_BLOCK_TYPE_PSP, AMD_IP_BLOCK_TYPE_DCE, AMD_IP_BLOCK_TYPE_GFX, AMD_IP_BLOCK_TYPE_SDMA, From 17dc7af70e89db773a7213f0b4270c69236a63ab Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 6 Sep 2018 20:01:43 +0100 Subject: [PATCH 7/9] 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 (cherry picked from commit c8124d399224d626728e2ffb95a1d564a7c06968) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_overlay.c | 228 +++++++++------------------ 1 file changed, 75 insertions(+), 153 deletions(-) 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); - memset_io(regs, 0, sizeof(struct overlay_registers)); - update_polyphase_filter(regs); - update_reg_attrs(overlay, regs); + ret = get_registers(overlay, OVERLAY_NEEDS_PHYSICAL(dev_priv)); + if (ret) + goto out_free; - intel_overlay_unmap_regs(overlay, regs); + ret = i915_gem_object_set_to_gtt_domain(overlay->reg_bo, true); + if (ret) + goto out_reg_bo; + + mutex_unlock(&dev_priv->drm.struct_mutex); + + 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(dev_priv->overlay->reg_bo); - kfree(dev_priv->overlay); + i915_gem_object_put(overlay->reg_bo); + + 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 From 0165de983272d1fae0809ed9db47c46a412279bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 10 Sep 2018 15:52:55 +0200 Subject: [PATCH 8/9] drm/amdgpu: fix error handling in amdgpu_cs_user_fence_chunk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Slowly leaking memory one page at a time :) Signed-off-by: Christian König Reviewed-by: Andrey Grodzovsky Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 1b5a0a73d770..b31d121a876b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -39,6 +39,7 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p, { struct drm_gem_object *gobj; unsigned long size; + int r; gobj = drm_gem_object_lookup(p->filp, data->handle); if (gobj == NULL) @@ -50,20 +51,26 @@ static int amdgpu_cs_user_fence_chunk(struct amdgpu_cs_parser *p, p->uf_entry.tv.shared = true; p->uf_entry.user_pages = NULL; + drm_gem_object_put_unlocked(gobj); + size = amdgpu_bo_size(p->uf_entry.robj); - if (size != PAGE_SIZE || (data->offset + 8) > size) - return -EINVAL; + if (size != PAGE_SIZE || (data->offset + 8) > size) { + r = -EINVAL; + goto error_unref; + } + + if (amdgpu_ttm_tt_get_usermm(p->uf_entry.robj->tbo.ttm)) { + r = -EINVAL; + goto error_unref; + } *offset = data->offset; - drm_gem_object_put_unlocked(gobj); - - if (amdgpu_ttm_tt_get_usermm(p->uf_entry.robj->tbo.ttm)) { - amdgpu_bo_unref(&p->uf_entry.robj); - return -EINVAL; - } - return 0; + +error_unref: + amdgpu_bo_unref(&p->uf_entry.robj); + return r; } static int amdgpu_cs_bo_handles_chunk(struct amdgpu_cs_parser *p, From 3483f08106fcd0e8edad2b9f2fc4726d25177799 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 13 Sep 2018 10:56:38 +1000 Subject: [PATCH 9/9] drm/nouveau/devinit: fix warning when PMU/PRE_OS is missing Messed up when sending pull request and sent an outdated version of previous patch, this fixes it up to remove warnings. Signed-off-by: Ben Skeggs --- .../drm/nouveau/nvkm/subdev/devinit/gm200.c | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c index d65959ef0564..17235e940ca9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c @@ -86,10 +86,8 @@ pmu_load(struct nv50_devinit *init, u8 type, bool post, struct nvkm_bios *bios = subdev->device->bios; struct nvbios_pmuR pmu; - if (!nvbios_pmuRm(bios, type, &pmu)) { - nvkm_error(subdev, "VBIOS PMU fuc %02x not found\n", type); + if (!nvbios_pmuRm(bios, type, &pmu)) return -EINVAL; - } if (!post) return 0; @@ -124,29 +122,30 @@ gm200_devinit_post(struct nvkm_devinit *base, bool post) return -EINVAL; } + /* Upload DEVINIT application from VBIOS onto PMU. */ ret = pmu_load(init, 0x04, post, &exec, &args); - if (ret) + if (ret) { + nvkm_error(subdev, "VBIOS PMU/DEVINIT not found\n"); return ret; + } - /* upload first chunk of init data */ + /* Upload tables required by opcodes in boot scripts. */ if (post) { - // devinit tables u32 pmu = pmu_args(init, args + 0x08, 0x08); u32 img = nvbios_rd16(bios, bit_I.offset + 0x14); u32 len = nvbios_rd16(bios, bit_I.offset + 0x16); pmu_data(init, pmu, img, len); } - /* upload second chunk of init data */ + /* Upload boot scripts. */ if (post) { - // devinit boot scripts u32 pmu = pmu_args(init, args + 0x08, 0x10); u32 img = nvbios_rd16(bios, bit_I.offset + 0x18); u32 len = nvbios_rd16(bios, bit_I.offset + 0x1a); pmu_data(init, pmu, img, len); } - /* execute init tables */ + /* Execute DEVINIT. */ if (post) { nvkm_wr32(device, 0x10a040, 0x00005000); pmu_exec(init, exec); @@ -157,7 +156,9 @@ gm200_devinit_post(struct nvkm_devinit *base, bool post) return -ETIMEDOUT; } - /* load and execute some other ucode image (bios therm?) */ + /* Optional: Execute PRE_OS application on PMU, which should at + * least take care of fans until a full PMU has been loaded. + */ pmu_load(init, 0x01, post, NULL, NULL); return 0; }