From 1dca220b2b6ba605bff07c4d019dd2cd2d70036c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 8 Nov 2013 10:10:31 +0200 Subject: [PATCH 01/12] drm/i915/opregion: fix build error on CONFIG_ACPI=n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix CONFIG_ACPI=n build fail CC drivers/gpu/drm/i915/intel_opregion.o drivers/gpu/drm/i915/intel_opregion.c: In function ‘intel_opregion_setup’: drivers/gpu/drm/i915/intel_opregion.c:879:2: error: ‘asle_work’ undeclared (first use in this function) drivers/gpu/drm/i915/intel_opregion.c:879:2: note: each undeclared identifier is reported only once for each function it appears in make[4]: *** [drivers/gpu/drm/i915/intel_opregion.o] Error 1 introduced in commit 91a60f20712179e56b7a6c3d332a5f6f9a54aa11 Author: Jani Nikula Date: Thu Oct 31 18:55:48 2013 +0200 drm/i915: move opregion asle request handling to a work queue Reported-by: Jim Davis Reference: http://lkml.kernel.org/r/CA+r1ZhjcFpr5KKVX0pLCOP8cAyZoiYO=UyqYMJtNSV-Kt_p7xQ@mail.gmail.com Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_opregion.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 91b68dca0641..1b2f41c3f191 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -876,7 +876,9 @@ int intel_opregion_setup(struct drm_device *dev) return -ENOTSUPP; } +#ifdef CONFIG_ACPI INIT_WORK(&opregion->asle_work, asle_work); +#endif base = acpi_os_ioremap(asls, OPREGION_SIZE); if (!base) From 339d202cde8e63113124d8931203f5bdb3343f27 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 15 Aug 2013 11:42:14 -0400 Subject: [PATCH 02/12] drm/edid: compare actual vrefresh for all modes for quirks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vrefresh field of the mode is 0 for most modes fetched from the EDID (e.g., established timings). When dealing with monitors that have a bogus preferred mode, we may not always select the mode we want because we compare the target refresh to the mode's vrefresh which is 0 in a lot of cases. Signed-off-by: Alex Deucher Reviewed-by: Ville Syrjälä --- drivers/gpu/drm/drm_edid.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 2f325bcd0708..fb7cf0e796f6 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1329,7 +1329,7 @@ static u32 edid_get_quirks(struct edid *edid) } #define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) -#define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) +#define MODE_REFRESH_DIFF(c,t) (abs((c) - (t))) /** * edid_fixup_preferred - set preferred modes based on quirk list @@ -1344,6 +1344,7 @@ static void edid_fixup_preferred(struct drm_connector *connector, { struct drm_display_mode *t, *cur_mode, *preferred_mode; int target_refresh = 0; + int cur_vrefresh, preferred_vrefresh; if (list_empty(&connector->probed_modes)) return; @@ -1366,10 +1367,14 @@ static void edid_fixup_preferred(struct drm_connector *connector, if (MODE_SIZE(cur_mode) > MODE_SIZE(preferred_mode)) preferred_mode = cur_mode; + cur_vrefresh = cur_mode->vrefresh ? + cur_mode->vrefresh : drm_mode_vrefresh(cur_mode); + preferred_vrefresh = preferred_mode->vrefresh ? + preferred_mode->vrefresh : drm_mode_vrefresh(preferred_mode); /* At a given size, try to get closest to target refresh */ if ((MODE_SIZE(cur_mode) == MODE_SIZE(preferred_mode)) && - MODE_REFRESH_DIFF(cur_mode, target_refresh) < - MODE_REFRESH_DIFF(preferred_mode, target_refresh)) { + MODE_REFRESH_DIFF(cur_vrefresh, target_refresh) < + MODE_REFRESH_DIFF(preferred_vrefresh, target_refresh)) { preferred_mode = cur_mode; } } From ea029c28deadc33d2af4baf26810dd5fc44d4926 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 12 Nov 2013 00:09:54 -0800 Subject: [PATCH 03/12] drm/vmwgfx: Resource evict fixes Fix an error message that was incorrectly blaming device resource id shortage. Also make sure we correctly catch resource eviction errors, that could otherwise lead to evictable resources temporarily not being on the LRU list. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Cc: stable@vger.kernel.org --- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 42 ++++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 0e67cf41065d..941e5ffd1c72 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -32,6 +32,8 @@ #include #include "vmwgfx_resource_priv.h" +#define VMW_RES_EVICT_ERR_COUNT 10 + struct vmw_user_dma_buffer { struct ttm_base_object base; struct vmw_dma_buffer dma; @@ -1091,8 +1093,9 @@ vmw_resource_backoff_reservation(struct ww_acquire_ctx *ticket, * to a backup buffer. * * @res: The resource to evict. + * @interruptible: Whether to wait interruptible. */ -int vmw_resource_do_evict(struct vmw_resource *res) +int vmw_resource_do_evict(struct vmw_resource *res, bool interruptible) { struct ttm_validate_buffer val_buf; const struct vmw_res_func *func = res->func; @@ -1102,7 +1105,8 @@ int vmw_resource_do_evict(struct vmw_resource *res) BUG_ON(!func->may_evict); val_buf.bo = NULL; - ret = vmw_resource_check_buffer(res, &ticket, true, &val_buf); + ret = vmw_resource_check_buffer(res, &ticket, interruptible, + &val_buf); if (unlikely(ret != 0)) return ret; @@ -1141,6 +1145,7 @@ int vmw_resource_validate(struct vmw_resource *res) struct vmw_private *dev_priv = res->dev_priv; struct list_head *lru_list = &dev_priv->res_lru[res->func->res_type]; struct ttm_validate_buffer val_buf; + unsigned err_count = 0; if (likely(!res->func->may_evict)) return 0; @@ -1155,7 +1160,7 @@ int vmw_resource_validate(struct vmw_resource *res) write_lock(&dev_priv->resource_lock); if (list_empty(lru_list) || !res->func->may_evict) { - DRM_ERROR("Out of device device id entries " + DRM_ERROR("Out of device device resources " "for %s.\n", res->func->type_name); ret = -EBUSY; write_unlock(&dev_priv->resource_lock); @@ -1168,7 +1173,19 @@ int vmw_resource_validate(struct vmw_resource *res) list_del_init(&evict_res->lru_head); write_unlock(&dev_priv->resource_lock); - vmw_resource_do_evict(evict_res); + + ret = vmw_resource_do_evict(evict_res, true); + if (unlikely(ret != 0)) { + write_lock(&dev_priv->resource_lock); + list_add_tail(&evict_res->lru_head, lru_list); + write_unlock(&dev_priv->resource_lock); + if (ret == -ERESTARTSYS || + ++err_count > VMW_RES_EVICT_ERR_COUNT) { + vmw_resource_unreference(&evict_res); + goto out_no_validate; + } + } + vmw_resource_unreference(&evict_res); } while (1); @@ -1253,13 +1270,15 @@ bool vmw_resource_needs_backup(const struct vmw_resource *res) * @type: The resource type to evict * * To avoid thrashing starvation or as part of the hibernation sequence, - * evict all evictable resources of a specific type. + * try to evict all evictable resources of a specific type. */ static void vmw_resource_evict_type(struct vmw_private *dev_priv, enum vmw_res_type type) { struct list_head *lru_list = &dev_priv->res_lru[type]; struct vmw_resource *evict_res; + unsigned err_count = 0; + int ret; do { write_lock(&dev_priv->resource_lock); @@ -1272,7 +1291,18 @@ static void vmw_resource_evict_type(struct vmw_private *dev_priv, lru_head)); list_del_init(&evict_res->lru_head); write_unlock(&dev_priv->resource_lock); - vmw_resource_do_evict(evict_res); + + ret = vmw_resource_do_evict(evict_res, false); + if (unlikely(ret != 0)) { + write_lock(&dev_priv->resource_lock); + list_add_tail(&evict_res->lru_head, lru_list); + write_unlock(&dev_priv->resource_lock); + if (++err_count > VMW_RES_EVICT_ERR_COUNT) { + vmw_resource_unreference(&evict_res); + return; + } + } + vmw_resource_unreference(&evict_res); } while (1); From e14cd9536bd11b174a849da91c7a26bbc980330d Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 11 Nov 2013 23:49:26 -0800 Subject: [PATCH 04/12] drm/vmwgfx: Fix a couple of compile / sparse warnings and errors Fixes *) an implicit function declaration on mips, *) a defined but not used label on !CONFIG_INTEL_IOMMU *) Hopefully a couple of sparse warnings where we implicitly typecast integer to __le32 and vice versa. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 9 ++++++++- drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c | 7 +++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 0b5c7818ebfb..a278581ca276 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -453,12 +453,13 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv) */ static int vmw_dma_select_mode(struct vmw_private *dev_priv) { - const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev); static const char *names[vmw_dma_map_max] = { [vmw_dma_phys] = "Using physical TTM page addresses.", [vmw_dma_alloc_coherent] = "Using coherent TTM pages.", [vmw_dma_map_populate] = "Keeping DMA mappings.", [vmw_dma_map_bind] = "Giving up DMA mappings early."}; +#ifdef CONFIG_X86 + const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev); #ifdef CONFIG_INTEL_IOMMU if (intel_iommu_enabled) { @@ -482,7 +483,9 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv) dev_priv->map_mode = vmw_dma_map_populate; #endif +#ifdef CONFIG_INTEL_IOMMU out_fixup: +#endif if (dev_priv->map_mode == vmw_dma_map_populate && vmw_restrict_iommu) dev_priv->map_mode = vmw_dma_map_bind; @@ -498,6 +501,10 @@ out_fixup: return -EINVAL; #endif +#else /* CONFIG_X86 */ + dev_priv->map_mode = vmw_dma_map_populate; +#endif /* CONFIG_X86 */ + DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]); return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c index 6d0952366f91..6ef0b035becb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c @@ -145,7 +145,9 @@ static void vmw_gmr_free_descriptors(struct device *dev, dma_addr_t desc_dma, } page_virtual = kmap_atomic(page); - desc_dma = page_virtual[desc_per_page].ppn << PAGE_SHIFT; + desc_dma = (dma_addr_t) + le32_to_cpu(page_virtual[desc_per_page].ppn) << + PAGE_SHIFT; kunmap_atomic(page_virtual); __free_page(page); @@ -217,7 +219,8 @@ static int vmw_gmr_build_descriptors(struct device *dev, desc_dma = 0; list_for_each_entry_reverse(page, desc_pages, lru) { page_virtual = kmap_atomic(page); - page_virtual[desc_per_page].ppn = desc_dma >> PAGE_SHIFT; + page_virtual[desc_per_page].ppn = cpu_to_le32 + (desc_dma >> PAGE_SHIFT); kunmap_atomic(page_virtual); desc_dma = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_TO_DEVICE); From 3943875e7b73fdd94dd9e911d69f0cee9ab66a89 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Wed, 6 Nov 2013 09:32:59 -0800 Subject: [PATCH 05/12] drm/ttm: Fix vma page_prot bit manipulation Fix a long-standing TTM issue where we manipulated the vma page_prot bits while mmap_sem was taken in read mode only. We now make a local copy of the vma structure which we pass when we set the ptes. Signed-off-by: Thomas Hellstrom Reviewed-by: Jerome Glisse --- drivers/gpu/drm/ttm/ttm_bo_vm.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index c03514b93f9c..ac617f3ecd0c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -102,6 +102,7 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) int retval = VM_FAULT_NOPAGE; struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type]; + struct vm_area_struct cvma; /* * Work around locking order reversal in fault / nopfn @@ -164,26 +165,21 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } /* - * Strictly, we're not allowed to modify vma->vm_page_prot here, - * since the mmap_sem is only held in read mode. However, we - * modify only the caching bits of vma->vm_page_prot and - * consider those bits protected by - * the bo->mutex, as we should be the only writers. - * There shouldn't really be any readers of these bits except - * within vm_insert_mixed()? fork? - * - * TODO: Add a list of vmas to the bo, and change the - * vma->vm_page_prot when the object changes caching policy, with - * the correct locks held. + * Make a local vma copy to modify the page_prot member + * and vm_flags if necessary. The vma parameter is protected + * by mmap_sem in write mode. */ + cvma = *vma; + cvma.vm_page_prot = vm_get_page_prot(cvma.vm_flags); + if (bo->mem.bus.is_iomem) { - vma->vm_page_prot = ttm_io_prot(bo->mem.placement, - vma->vm_page_prot); + cvma.vm_page_prot = ttm_io_prot(bo->mem.placement, + cvma.vm_page_prot); } else { ttm = bo->ttm; - vma->vm_page_prot = (bo->mem.placement & TTM_PL_FLAG_CACHED) ? - vm_get_page_prot(vma->vm_flags) : - ttm_io_prot(bo->mem.placement, vma->vm_page_prot); + if (!(bo->mem.placement & TTM_PL_FLAG_CACHED)) + cvma.vm_page_prot = ttm_io_prot(bo->mem.placement, + cvma.vm_page_prot); /* Allocate all page at once, most common usage */ if (ttm->bdev->driver->ttm_tt_populate(ttm)) { @@ -210,7 +206,7 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) pfn = page_to_pfn(page); } - ret = vm_insert_mixed(vma, address, pfn); + ret = vm_insert_mixed(&cvma, address, pfn); /* * Somebody beat us to this PTE or prefaulting to * an already populated PTE, or prefaulting error. From 5dd8c4c3f18b2ebf3f5303c7c273396441db6c6c Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 8 Nov 2013 10:20:06 -0800 Subject: [PATCH 06/12] drm/i915/bdw: Add BDW to ULT macro For what we care about ULT and ULX are interchangeable. We know of 3 types of pciids for these cases. I am not sure if at some point we will need to distinguish ULT and ULX. Cc: Paulo Zanoni Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8600c315b4c4..51951ef7e71d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1755,8 +1755,13 @@ struct drm_i915_file_private { #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0xFF00) == 0x0C00) -#define IS_ULT(dev) (IS_HASWELL(dev) && \ +#define IS_BDW_ULT(dev) (IS_BROADWELL(dev) && \ + (((dev)->pdev->device & 0xf) == 0x2 || \ + ((dev)->pdev->device & 0xf) == 0x6 || \ + ((dev)->pdev->device & 0xf) == 0xe)) +#define IS_HSW_ULT(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0xFF00) == 0x0A00) +#define IS_ULT(dev) (IS_HSW_ULT(dev) || IS_BDW_ULT(dev)) #define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \ ((dev)->pdev->device & 0x00F0) == 0x0020) #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) From f8e100621b072384ec1180563d933e86e2f7e2d5 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 11 Nov 2013 11:12:57 +0200 Subject: [PATCH 07/12] drm/i915/bdw: GEN8 backlight support Prior to Haswell the CPU control register for backlight (BLC_PWM_CPU_CTL) toggled the PCH baclight pin for us. This made some sense as there was no pin on the CPU. With Haswell came the introduction of a CPU backlight pin, but the interface was still controlled by software with the same mechnism. Behind the scenes, hardware did all the dirty work for us. Broadwell no longer provides this for free. If we want to use the PCH backlight pin [1] then we have to set the override bit BLC_PWM_PCH_CTL1 and program BLC_PWM_PCH_CTL2 for the PWM values. This patch implements that. This patch is compile tested only, and given that I rarely if ever touch this code, careful review is welcome. [1] According to Art, we know of no devices that exist which use the CPU pin (and remember it has existed already on HSW). If such a device does exist, we'll have to handle it properly - this is left as TODO until then. v2: Drop the abstraction prep patch, as a bigger backlight overhaul is in the works, and do just the mimimal bdw enabling now. (by Jani) CC: Art Runyan Signed-off-by: Ben Widawsky Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index f161ac02c4f6..e6f782d1c669 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -451,7 +451,9 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, spin_lock_irqsave(&dev_priv->backlight.lock, flags); - if (HAS_PCH_SPLIT(dev)) { + if (IS_BROADWELL(dev)) { + val = I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK; + } else if (HAS_PCH_SPLIT(dev)) { val = I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK; } else { if (IS_VALLEYVIEW(dev)) @@ -479,6 +481,13 @@ static u32 intel_panel_get_backlight(struct drm_device *dev, return val; } +static void intel_bdw_panel_set_backlight(struct drm_device *dev, u32 level) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK; + I915_WRITE(BLC_PWM_PCH_CTL2, val | level); +} + static void intel_pch_panel_set_backlight(struct drm_device *dev, u32 level) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -496,7 +505,9 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); level = intel_panel_compute_brightness(dev, pipe, level); - if (HAS_PCH_SPLIT(dev)) + if (IS_BROADWELL(dev)) + return intel_bdw_panel_set_backlight(dev, level); + else if (HAS_PCH_SPLIT(dev)) return intel_pch_panel_set_backlight(dev, level); if (is_backlight_combination_mode(dev)) { @@ -666,7 +677,16 @@ void intel_panel_enable_backlight(struct intel_connector *connector) POSTING_READ(reg); I915_WRITE(reg, tmp | BLM_PWM_ENABLE); - if (HAS_PCH_SPLIT(dev) && + if (IS_BROADWELL(dev)) { + /* + * Broadwell requires PCH override to drive the PCH + * backlight pin. The above will configure the CPU + * backlight pin, which we don't plan to use. + */ + tmp = I915_READ(BLC_PWM_PCH_CTL1); + tmp |= BLM_PCH_OVERRIDE_ENABLE | BLM_PCH_PWM_ENABLE; + I915_WRITE(BLC_PWM_PCH_CTL1, tmp); + } else if (HAS_PCH_SPLIT(dev) && !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { tmp = I915_READ(BLC_PWM_PCH_CTL1); tmp |= BLM_PCH_PWM_ENABLE; From 935e8de97564a1ea22c3bb30ca2b20b12af7cbfb Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:47 -0800 Subject: [PATCH 08/12] drm/i915/bdw: Do gen6 style reset for gen8 This patch existed before, but was lost over time. Note that reset is still somewhat problematic in my limited testing (ie. module_reload will not pass) but it can be disabled with a module parameter, and support should be considered preliminary anyway. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_uncore.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index f9883ceff946..6a4f9b615de1 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -782,6 +782,7 @@ static int gen6_do_reset(struct drm_device *dev) int intel_gpu_reset(struct drm_device *dev) { switch (INTEL_INFO(dev)->gen) { + case 8: case 7: case 6: return gen6_do_reset(dev); case 5: return ironlake_do_reset(dev); From 230f955f73074ec5b1b4389f3f26152eebf54404 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:48 -0800 Subject: [PATCH 09/12] drm/i915/bdw: Free correct number of ppgtt pages I am unclear how this got messed up in the shuffle, but it did. Cc: Imre Deak Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 3620a1b0a73c..5a3cc3189f1f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -335,8 +335,8 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm) kfree(ppgtt->gen8_pt_dma_addr[i]); } - __free_pages(ppgtt->gen8_pt_pages, ppgtt->num_pt_pages << PAGE_SHIFT); - __free_pages(ppgtt->pd_pages, ppgtt->num_pd_pages << PAGE_SHIFT); + __free_pages(ppgtt->gen8_pt_pages, get_order(ppgtt->num_pt_pages << PAGE_SHIFT)); + __free_pages(ppgtt->pd_pages, get_order(ppgtt->num_pd_pages << PAGE_SHIFT)); } /** From eb0d4b75d506050cb369df467b93b92360f5acaf Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:50 -0800 Subject: [PATCH 10/12] drm/i915/bdw: Add comment about gen8 HWS PGA This confused me some many times that I think it is appropriate to add a small comment to instruct the reader of the code that it is indeed doing what it is supposed to do. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_ringbuffer.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b620337e6d67..c2f09d456300 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -965,6 +965,7 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring) } else if (IS_GEN6(ring->dev)) { mmio = RING_HWS_PGA_GEN6(ring->mmio_base); } else { + /* XXX: gen8 returns to sanity */ mmio = RING_HWS_PGA(ring->mmio_base); } From 3a2ffb65eec6dbda2fd8151894f51c18b42c8d41 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:51 -0800 Subject: [PATCH 11/12] drm/i915/bdw: Limit GTT to 2GB Because of the way in which we're allocating the pages for the Aliasing PPGTT, we cannot actually successfully alloc enough space for anything greater than 2GB. Instead of a quick hack to fix this, we should defer until we have the real solution in place (allocating much less contiguous space). This wasn't found sooner because we didn't not have any systems supporting more than a 2GB GTT. Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 5a3cc3189f1f..f69bdc741b80 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1239,6 +1239,11 @@ static inline unsigned int gen8_get_total_gtt_size(u16 bdw_gmch_ctl) bdw_gmch_ctl &= BDW_GMCH_GGMS_MASK; if (bdw_gmch_ctl) bdw_gmch_ctl = 1 << bdw_gmch_ctl; + if (bdw_gmch_ctl > 4) { + WARN_ON(!i915_preliminary_hw_support); + return 4<<20; + } + return bdw_gmch_ctl << 20; } From 596cc11e7a4a89bf6c45f955402d0bd0c7d51f13 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 11 Nov 2013 14:46:28 -0800 Subject: [PATCH 12/12] drm/i915/bdw: PIPE_[BC] I[ME]R moved to powerwell The pipe B and pipe C interrupt mask and enable registers are now part of the pipe, so disabling the pipe power wells will lost the contests of the registers. Art totally debugged this one! v2: Use the irq_lock to clarify code, and prevent future bugs (Daniel) Cc: Art Runyan Cc: Paulo Zanoni Signed-off-by: Ben Widawsky [danvet: Make sparse happy.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_pm.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0a07d7c9cafc..33a8dbe64039 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5684,6 +5684,7 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) { struct drm_i915_private *dev_priv = dev->dev_private; bool is_enabled, enable_requested; + unsigned long irqflags; uint32_t tmp; tmp = I915_READ(HSW_PWR_WELL_DRIVER); @@ -5701,9 +5702,24 @@ static void __intel_set_power_well(struct drm_device *dev, bool enable) HSW_PWR_WELL_STATE_ENABLED), 20)) DRM_ERROR("Timeout enabling power well\n"); } + + if (IS_BROADWELL(dev)) { + spin_lock_irqsave(&dev_priv->irq_lock, irqflags); + I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_B), + dev_priv->de_irq_mask[PIPE_B]); + I915_WRITE(GEN8_DE_PIPE_IER(PIPE_B), + ~dev_priv->de_irq_mask[PIPE_B] | + GEN8_PIPE_VBLANK); + I915_WRITE(GEN8_DE_PIPE_IMR(PIPE_C), + dev_priv->de_irq_mask[PIPE_C]); + I915_WRITE(GEN8_DE_PIPE_IER(PIPE_C), + ~dev_priv->de_irq_mask[PIPE_C] | + GEN8_PIPE_VBLANK); + POSTING_READ(GEN8_DE_PIPE_IER(PIPE_C)); + spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + } } else { if (enable_requested) { - unsigned long irqflags; enum pipe p; I915_WRITE(HSW_PWR_WELL_DRIVER, 0);