From 5dd8c4c3f18b2ebf3f5303c7c273396441db6c6c Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Fri, 8 Nov 2013 10:20:06 -0800 Subject: 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(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8600c315b4c..51951ef7e71 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) -- cgit v1.2.3-70-g09d2 From f8e100621b072384ec1180563d933e86e2f7e2d5 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 11 Nov 2013 11:12:57 +0200 Subject: 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(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index f161ac02c4f..e6f782d1c66 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; -- cgit v1.2.3-70-g09d2 From 935e8de97564a1ea22c3bb30ca2b20b12af7cbfb Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:47 -0800 Subject: 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(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index f9883ceff94..6a4f9b615de 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); -- cgit v1.2.3-70-g09d2 From 230f955f73074ec5b1b4389f3f26152eebf54404 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:48 -0800 Subject: 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(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 3620a1b0a73..5a3cc3189f1 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)); } /** -- cgit v1.2.3-70-g09d2 From eb0d4b75d506050cb369df467b93b92360f5acaf Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:50 -0800 Subject: 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(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index b620337e6d6..c2f09d45630 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); } -- cgit v1.2.3-70-g09d2 From 3a2ffb65eec6dbda2fd8151894f51c18b42c8d41 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 7 Nov 2013 21:40:51 -0800 Subject: 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(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 5a3cc3189f1..f69bdc741b8 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; } -- cgit v1.2.3-70-g09d2 From 596cc11e7a4a89bf6c45f955402d0bd0c7d51f13 Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Mon, 11 Nov 2013 14:46:28 -0800 Subject: 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(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0a07d7c9caf..33a8dbe6403 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); -- cgit v1.2.3-70-g09d2 From 027476642811f8559cbe00ef6cc54db230e48a20 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 2 Dec 2013 11:08:06 +0200 Subject: drm/i915: Take modeset locks around intel_modeset_setup_hw_state() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some lower level things get angry if we don't have modeset locks during intel_modeset_setup_hw_state(). Actually the resume and lid_notify codepaths alreday hold the locks, but the init codepath doesn't, so fix that. Note: This slipped through since we only disable pipes if the plane/pipe linking doesn't match. Which is only relevant on older gen3 mobile machines, if the BIOS fails to set up our preferred linking. Signed-off-by: Ville Syrjälä Cc: stable@vger.kernel.org Tested-and-reported-by: Paul Bolle [danvet: Add note now that I could confirm my theory with the log files Paul Bolle provided.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 080f6fd4e83..114db51996b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11046,7 +11046,9 @@ void intel_modeset_gem_init(struct drm_device *dev) intel_setup_overlay(dev); + drm_modeset_lock_all(dev); intel_modeset_setup_hw_state(dev, false); + drm_modeset_unlock_all(dev); } void intel_modeset_cleanup(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From edd5b13313551d6b04acfb90d3db58ed3cf3c814 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 2 Dec 2013 17:39:09 +0000 Subject: drm/i915: Do not clobber config status after a forced restore of hw state We call intel_modeset_setup_hw_state() along two paths, driver load/resume and after a lid event notification. During initialisation of the driver, it is imperative that we reset the config state. This correctly sets up the initial connector statuses and prepares the hardware for a thorough probing. However, during a lid event, we only want to undo the damage caused by the bios by resetting our last known mode. In this cirumstance, we do not want to clobber our desired state. In order to try and keep sanity between the config state and our own tracking, do the drm_mode_config_reset() first along the load/resume paths before reading out the hw state and apply any definite known corrections. v2: "As discussed on irc I don't think we should force the connector state to anything here: Imo connector->status should reflect what we believe to be the true output connection state, whereas connector->encoder reflects whether this connector is wired up to a pipe. And since we no longer reject modeset on disconnected connectors and never nuked the pipe if the connector gets disconnected there's no reason for that - such policy is userspace's job. This regression has been introduced in commit 2e9388923e83bc4e2726f170a984621f1d582e77 Author: Daniel Vetter Date: Thu Oct 11 20:08:24 2012 +0200 drm/i915/crt: explicitly set up HOTPLUG_BITS on resume" so sayeth Daniel. Signed-off-by: Chris Wilson Cc: Daniel Vetter Cc: stable@vger.kernel.org (v3.8 and later) Cc: Paulo Zanoni Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 1 + drivers/gpu/drm/i915/intel_display.c | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2e367a1c6a6..5b7b7e06cb3 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -651,6 +651,7 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) intel_modeset_init_hw(dev); drm_modeset_lock_all(dev); + drm_mode_config_reset(dev); intel_modeset_setup_hw_state(dev, true); drm_modeset_unlock_all(dev); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 114db51996b..8e44b16950c 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11036,8 +11036,6 @@ void intel_modeset_setup_hw_state(struct drm_device *dev, } intel_modeset_check_state(dev); - - drm_mode_config_reset(dev); } void intel_modeset_gem_init(struct drm_device *dev) @@ -11047,6 +11045,7 @@ void intel_modeset_gem_init(struct drm_device *dev) intel_setup_overlay(dev); drm_modeset_lock_all(dev); + drm_mode_config_reset(dev); intel_modeset_setup_hw_state(dev, false); drm_modeset_unlock_all(dev); } -- cgit v1.2.3-70-g09d2 From 5ae68b413214e847a2b5c6d3c65778482542bc1a Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 2 Dec 2013 11:23:39 +0200 Subject: drm/i915: Skip clock checks on BDW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't have clock state readout support for DDI, so skip the pipe config clock checks on all DDI platforms. Signed-off-by: Ville Syrjälä Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8e44b16950c..8b8bde7dce5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9135,7 +9135,7 @@ intel_pipe_config_compare(struct drm_device *dev, if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) PIPE_CONF_CHECK_I(pipe_bpp); - if (!IS_HASWELL(dev)) { + if (!HAS_DDI(dev)) { PIPE_CONF_CHECK_CLOCK_FUZZY(adjusted_mode.crtc_clock); PIPE_CONF_CHECK_CLOCK_FUZZY(port_clock); } -- cgit v1.2.3-70-g09d2 From 0d1430a3f4b7cfd8779b78740a4182321f3ca7f3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 4 Dec 2013 14:52:06 +0000 Subject: drm/i915: Hold mutex across i915_gem_release Inorder to serialise the closing of the file descriptor and its subsequent release of client requests with i915_gem_free_request(), we need to hold the struct_mutex in i915_gem_release(). Failing to do so has the potential to trigger an OOPS, later with a use-after-free. Testcase: igt/gem_close_race Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70874 Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71029 Reported-by: Eric Anholt Signed-off-by: Chris Wilson Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 2 ++ drivers/gpu/drm/i915/i915_gem_context.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0cab2d04513..ac9dac99b58 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1848,8 +1848,10 @@ void i915_driver_lastclose(struct drm_device * dev) void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { + mutex_lock(&dev->struct_mutex); i915_gem_context_close(dev, file_priv); i915_gem_release(dev, file_priv); + mutex_unlock(&dev->struct_mutex); } void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 72a3df32292..4a05956162c 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -347,10 +347,8 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - mutex_lock(&dev->struct_mutex); idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); idr_destroy(&file_priv->context_idr); - mutex_unlock(&dev->struct_mutex); } static struct i915_hw_context * -- cgit v1.2.3-70-g09d2 From f742a55231b950ed71ac8cc8beec0944ddda312c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 6 Dec 2013 10:17:53 +0100 Subject: drm/i915: fix pm init ordering Shovel a bit more of the the code into the setup function, and call it earlier. Otherwise lockdep is unhappy since we cancel the delayed resume work before it's initialized. While at it also shovel the pc8 setup code into the same functions. I wanted to also ditch the header declaration of the hws pc8 functions, but for unfathomable reasons that stuff is in intel_display.c instead of intel_pm.c. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=71980 Tested-by: Guo Jinxian Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 10 +--------- drivers/gpu/drm/i915/i915_drv.h | 2 -- drivers/gpu/drm/i915/intel_drv.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 11 ++++++++++- 4 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index ac9dac99b58..197db0993a2 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1490,16 +1490,9 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) spin_lock_init(&dev_priv->uncore.lock); spin_lock_init(&dev_priv->mm.object_stat_lock); mutex_init(&dev_priv->dpio_lock); - mutex_init(&dev_priv->rps.hw_lock); mutex_init(&dev_priv->modeset_restore_lock); - mutex_init(&dev_priv->pc8.lock); - dev_priv->pc8.requirements_met = false; - dev_priv->pc8.gpu_idle = false; - dev_priv->pc8.irqs_disabled = false; - dev_priv->pc8.enabled = false; - dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */ - INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work); + intel_pm_setup(dev); intel_display_crc_init(dev); @@ -1603,7 +1596,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) } intel_irq_init(dev); - intel_pm_init(dev); intel_uncore_sanitize(dev); /* Try to make sure MCHBAR is enabled before poking at it */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ccdbecca070..6f04fa4b31f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1901,9 +1901,7 @@ void i915_queue_hangcheck(struct drm_device *dev); void i915_handle_error(struct drm_device *dev, bool wedged); extern void intel_irq_init(struct drm_device *dev); -extern void intel_pm_init(struct drm_device *dev); extern void intel_hpd_init(struct drm_device *dev); -extern void intel_pm_init(struct drm_device *dev); extern void intel_uncore_sanitize(struct drm_device *dev); extern void intel_uncore_early_sanitize(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index a18e88b3e42..79f91f26e28 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -821,6 +821,7 @@ void intel_update_sprite_watermarks(struct drm_plane *plane, uint32_t sprite_width, int pixel_size, bool enabled, bool scaled); void intel_init_pm(struct drm_device *dev); +void intel_pm_setup(struct drm_device *dev); bool intel_fbc_enabled(struct drm_device *dev); void intel_update_fbc(struct drm_device *dev); void intel_gpu_ips_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 6e0d5e075b1..e0dec95c764 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6130,10 +6130,19 @@ int vlv_freq_opcode(int ddr_freq, int val) return val; } -void intel_pm_init(struct drm_device *dev) +void intel_pm_setup(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; + mutex_init(&dev_priv->rps.hw_lock); + + mutex_init(&dev_priv->pc8.lock); + dev_priv->pc8.requirements_met = false; + dev_priv->pc8.gpu_idle = false; + dev_priv->pc8.irqs_disabled = false; + dev_priv->pc8.enabled = false; + dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */ + INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work); INIT_DELAYED_WORK(&dev_priv->rps.delayed_resume_work, intel_gen6_powersave_work); } -- cgit v1.2.3-70-g09d2 From acc240d41ea1ab9c488a79219fb313b5b46265ae Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 5 Dec 2013 15:42:34 +0100 Subject: drm/i915: Fix use-after-free in do_switch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So apparently under ridiculous amounts of memory pressure we can get into trouble in do_switch when we try to move the old hw context backing storage object onto the active lists. With list debugging enabled that usually results in us chasing a poisoned pointer - which means we've hit upon a vma that has been removed from all lrus with list_del (and then deallocated, so it's a real use-after free). Ian Lister has done some great callchain chasing and noticed that we can reenter do_switch: i915_gem_do_execbuffer() i915_switch_context() do_switch() from = ring->last_context; i915_gem_object_pin() i915_gem_object_bind_to_gtt() ret = drm_mm_insert_node_in_range_generic(); // If the above call fails then it will try i915_gem_evict_something() // If that fails it will call i915_gem_evict_everything() ... i915_gem_evict_everything() i915_gpu_idle() i915_switch_context(DEFAULT_CONTEXT) Like with everything else where the shrinker or eviction code can invalidate pointers we need to reload relevant state. Note that there's no need to recheck whether a context switch is still required because: - Doing a switch to the same context is harmless (besides wasting a bit of energy). - This can only happen with the default context. But since that one's pinned we'll never call down into evict_everything under normal circumstances. Note that there's a little driver bringup fun involved namely that we could recourse into do_switch for the initial switch. Atm we're fine since we assign the context pointer only after the call to do_switch at driver load or resume time. And in the gpu reset case we skip the entire setup sequence (which might be a bug on its own, but definitely not this one here). Cc'ing stable since apparently ChromeOS guys are seeing this in the wild (and not just on artificial stress tests), see the reference. Note that in upstream code doesn't calle evict_everything directly from evict_something, that's an extension in this product branch. But we can still hit upon this bug (and apparently we do, see the linked backtraces). I've noticed this while trying to construct a testcase for this bug and utterly failed to provoke it. It looks like we need to driver the system squarly into the lowmem wall and provoke the shrinker to evict the context object by doing the last-ditch evict_everything call. Aside: There's currently no means to get a badly-fragmenting hw context object away from a bad spot in the upstream code. We should fix this by at least adding some code to evict_something to handle hw contexts. References: https://code.google.com/p/chromium/issues/detail?id=248191 Reported-by: Ian Lister Cc: Ian Lister Cc: stable@vger.kernel.org Cc: Ben Widawsky Cc: Stéphane Marchesin Cc: Bloomfield, Jon Tested-by: Rafael Barbalho Reviewed-by: Ian Lister Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_context.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 4a05956162c..b0f42b9ca03 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -421,11 +421,21 @@ static int do_switch(struct i915_hw_context *to) if (ret) return ret; - /* Clear this page out of any CPU caches for coherent swap-in/out. Note + /* + * Pin can switch back to the default context if we end up calling into + * evict_everything - as a last ditch gtt defrag effort that also + * switches to the default context. Hence we need to reload from here. + */ + from = ring->last_context; + + /* + * Clear this page out of any CPU caches for coherent swap-in/out. Note * that thanks to write = false in this call and us not setting any gpu * write domains when putting a context object onto the active list * (when switching away from it), this won't block. - * XXX: We need a real interface to do this instead of trickery. */ + * + * XXX: We need a real interface to do this instead of trickery. + */ ret = i915_gem_object_set_to_gtt_domain(to->obj, false); if (ret) { i915_gem_object_unpin(to->obj); -- cgit v1.2.3-70-g09d2 From 11e6a09fba446ce799a9de51d2d99586024bbdaa Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Sun, 8 Dec 2013 23:39:04 -0800 Subject: drm/vmwgfx: Add max surface memory param Userspace uses this to workaround overcommit issues by flushing the command stream early. Signed-off-by: Jakob Bornecrantz Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 3 +++ include/uapi/drm/vmwgfx_drm.h | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index a51f48e3e91..45d5b5ab6ca 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -68,6 +68,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, SVGA_FIFO_3D_HWVERSION)); break; } + case DRM_VMW_PARAM_MAX_SURF_MEMORY: + param->value = dev_priv->memory_size; + break; default: DRM_ERROR("Illegal vmwgfx get param request: %d\n", param->param); diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h index bcb0912afe7..f854ca4a137 100644 --- a/include/uapi/drm/vmwgfx_drm.h +++ b/include/uapi/drm/vmwgfx_drm.h @@ -75,6 +75,7 @@ #define DRM_VMW_PARAM_FIFO_CAPS 4 #define DRM_VMW_PARAM_MAX_FB_SIZE 5 #define DRM_VMW_PARAM_FIFO_HW_VERSION 6 +#define DRM_VMW_PARAM_MAX_SURF_MEMORY 7 /** * struct drm_vmw_getparam_arg -- cgit v1.2.3-70-g09d2 From ad071acb53110c8efd26ff1e5b5d57449b43833b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 9 Dec 2013 10:37:24 +0000 Subject: drm/i915: Repeat eviction search after idling the GPU With the advent of hw context support, we gained some objects that are pinned for the duration of their request. That is we can make aperture space available by idling the GPU and in the process performing a context switch back to the always-pinned default context. As such, we should not conclude that there is no space in the aperture for the current object until we have unpinned any such context objects. Note that we also have the problem of outstanding pageflips preventing eviction of their framebuffer objects to resolve. Testcase: igt/gem_ctx_exec/eviction Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=72507 Signed-off-by: Chris Wilson Tested-by: lu hua Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_gem_evict.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index b7376533633..8f3adc7d0dc 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -88,6 +88,7 @@ i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm, } else drm_mm_init_scan(&vm->mm, min_size, alignment, cache_level); +search_again: /* First see if there is a large enough contiguous idle region... */ list_for_each_entry(vma, &vm->inactive_list, mm_list) { if (mark_free(vma, &unwind_list)) @@ -115,10 +116,17 @@ none: list_del_init(&vma->exec_list); } - /* We expect the caller to unpin, evict all and try again, or give up. - * So calling i915_gem_evict_vm() is unnecessary. + /* Can we unpin some objects such as idle hw contents, + * or pending flips? */ - return -ENOSPC; + ret = nonblocking ? -ENOSPC : i915_gpu_idle(dev); + if (ret) + return ret; + + /* Only idle the GPU and repeat the search once */ + i915_gem_retire_requests(dev); + nonblocking = true; + goto search_again; found: /* drm_mm doesn't allow any other other operations while -- cgit v1.2.3-70-g09d2 From 2f5ae4901acc6fdee939718658fa9f59c4f2217b Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 27 Oct 2013 15:26:33 +0000 Subject: DRM: Armada: implement lastclose() for fbhelper Call drm_fb_helper_restore_fbdev_mode() upon last close so that in the event of the X server crashing, we have some kind of mode restored. Reviewed-by: Rob Clark Reviewed-by: Thierry Reding Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_drm.h | 1 + drivers/gpu/drm/armada/armada_drv.c | 7 ++++++- drivers/gpu/drm/armada/armada_fbdev.c | 10 ++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/armada/armada_drm.h b/drivers/gpu/drm/armada/armada_drm.h index eef09ec9a5f..a72cae03b99 100644 --- a/drivers/gpu/drm/armada/armada_drm.h +++ b/drivers/gpu/drm/armada/armada_drm.h @@ -103,6 +103,7 @@ void armada_drm_queue_unref_work(struct drm_device *, extern const struct drm_mode_config_funcs armada_drm_mode_config_funcs; int armada_fbdev_init(struct drm_device *); +void armada_fbdev_lastclose(struct drm_device *); void armada_fbdev_fini(struct drm_device *); int armada_overlay_plane_create(struct drm_device *, unsigned long); diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 7aede900a22..15425d23c9c 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -321,6 +321,11 @@ static struct drm_ioctl_desc armada_ioctls[] = { DRM_UNLOCKED), }; +static void armada_drm_lastclose(struct drm_device *dev) +{ + armada_fbdev_lastclose(dev); +} + static const struct file_operations armada_drm_fops = { .owner = THIS_MODULE, .llseek = no_llseek, @@ -337,7 +342,7 @@ static struct drm_driver armada_drm_driver = { .open = NULL, .preclose = NULL, .postclose = NULL, - .lastclose = NULL, + .lastclose = armada_drm_lastclose, .unload = armada_drm_unload, .get_vblank_counter = drm_vblank_count, .enable_vblank = armada_drm_enable_vblank, diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index dd5ea77dac9..743570e99f9 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -177,6 +177,16 @@ int armada_fbdev_init(struct drm_device *dev) return ret; } +void armada_fbdev_lastclose(struct drm_device *dev) +{ + struct armada_private *priv = dev->dev_private; + + drm_modeset_lock_all(dev); + if (priv->fbdev) + drm_fb_helper_restore_fbdev_mode(priv->fbdev); + drm_modeset_unlock_all(dev); +} + void armada_fbdev_fini(struct drm_device *dev) { struct armada_private *priv = dev->dev_private; -- cgit v1.2.3-70-g09d2 From 077acbab67a785b5f5ae60e8932fcf6028072359 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 27 Oct 2013 15:35:27 +0000 Subject: DRM: Armada: destroy framebuffer after helper Destroy the framebuffer only after the helper, since the helper may still be referencing the framebufer at this point. Reviewed-by: Rob Clark Reviewed-by: Thierry Reding Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_fbdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index 743570e99f9..b348b16f81e 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -202,11 +202,11 @@ void armada_fbdev_fini(struct drm_device *dev) framebuffer_release(info); } + drm_fb_helper_fini(fbh); + if (fbh->fb) fbh->fb->funcs->destroy(fbh->fb); - drm_fb_helper_fini(fbh); - priv->fbdev = NULL; } } -- cgit v1.2.3-70-g09d2 From 7513e09596374bb7fbbecfee945fecb5b357c0e9 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 27 Nov 2013 15:46:55 +0000 Subject: DRM: Armada: fix printing of phys_addr_t/dma_addr_t These can be 64-bit quantities, so fix them up appropriately. Reviewed-by: Rob Clark Reviewed-by: Thierry Reding Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_fbdev.c | 6 +++--- drivers/gpu/drm/armada/armada_gem.c | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c index b348b16f81e..948cb14c561 100644 --- a/drivers/gpu/drm/armada/armada_fbdev.c +++ b/drivers/gpu/drm/armada/armada_fbdev.c @@ -105,9 +105,9 @@ static int armada_fb_create(struct drm_fb_helper *fbh, drm_fb_helper_fill_fix(info, dfb->fb.pitches[0], dfb->fb.depth); drm_fb_helper_fill_var(info, fbh, sizes->fb_width, sizes->fb_height); - DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08x\n", - dfb->fb.width, dfb->fb.height, - dfb->fb.bits_per_pixel, obj->phys_addr); + DRM_DEBUG_KMS("allocated %dx%d %dbpp fb: 0x%08llx\n", + dfb->fb.width, dfb->fb.height, dfb->fb.bits_per_pixel, + (unsigned long long)obj->phys_addr); return 0; diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 9f2356bae7f..adc7c2da75b 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -172,8 +172,9 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj) obj->dev_addr = obj->linear->start; } - DRM_DEBUG_DRIVER("obj %p phys %#x dev %#x\n", - obj, obj->phys_addr, obj->dev_addr); + DRM_DEBUG_DRIVER("obj %p phys %#llx dev %#llx\n", obj, + (unsigned long long)obj->phys_addr, + (unsigned long long)obj->dev_addr); return 0; } -- cgit v1.2.3-70-g09d2 From 5cd5268806435b6476184430b2806db988c903f0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 7 Dec 2013 16:28:39 +0000 Subject: DRM: Armada: prime refcounting bug fix Commit 011c2282c74d changed the way refcounting on imported dma_bufs works, and this hadn't been spotted while forward-porting Armada. Reflect the changes in that commit into the Armada driver. Reviewed-by: Rob Clark Reviewed-by: Thierry Reding Signed-off-by: Russell King --- drivers/gpu/drm/armada/armada_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index adc7c2da75b..887816f4347 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -558,7 +558,6 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf) * refcount on the gem object itself. */ drm_gem_object_reference(obj); - dma_buf_put(buf); return obj; } } @@ -574,6 +573,7 @@ armada_gem_prime_import(struct drm_device *dev, struct dma_buf *buf) } dobj->obj.import_attach = attach; + get_dma_buf(buf); /* * Don't call dma_buf_map_attachment() here - it maps the -- cgit v1.2.3-70-g09d2 From 6c719faca2aceca72f1bf5b1645c1734ed3e9447 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 10 Dec 2013 13:20:59 +0100 Subject: drm/i915: don't update the dri1 breadcrumb with modesetting The update is horribly racy since it doesn't protect at all against concurrent closing of the master fd. And it can't really since that requires us to grab a mutex. Instead of jumping through hoops and offloading this to a worker thread just block this bit of code for the modesetting driver. Note that the race is fairly easy to hit since we call the breadcrumb function for any interrupt. So the vblank interrupt (which usually keeps going for a bit) is enough. But even if we'd block this and only update the breadcrumb for user interrupts from the CS we could hit this race with kms/gem userspace: If a non-master is waiting somewhere (and hence has interrupts enabled) and the master closes its fd (probably due to crashing). v2: Add a code comment to explain why fixing this for real isn't really worth it. Also improve the commit message a bit. v3: Fix the spelling in the comment. Reported-by: Eugene Shatokhin Cc: Eugene Shatokhin Cc: stable@vger.kernel.org Acked-by: Chris Wilson Tested-by: Eugene Shatokhin Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_dma.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 197db0993a2..5c648425c1e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -83,6 +83,14 @@ void i915_update_dri1_breadcrumb(struct drm_device *dev) drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_master_private *master_priv; + /* + * The dri breadcrumb update races against the drm master disappearing. + * Instead of trying to fix this (this is by far not the only ums issue) + * just don't do the update in kms mode. + */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + if (dev->primary->master) { master_priv = dev->primary->master->driver_priv; if (master_priv->sarea_priv) -- cgit v1.2.3-70-g09d2 From 8333f0fe133be420ce3fcddfd568c3a559ab274e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 2 Dec 2013 18:15:51 -0500 Subject: drm/radeon: Fix sideport problems on certain RS690 boards Some RS690 boards with 64MB of sideport memory show up as having 128MB sideport + 256MB of UMA. In this case, just skip the sideport memory and use UMA. This fixes rendering corruption and should improve performance. bug: https://bugs.freedesktop.org/show_bug.cgi?id=35457 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/rs690.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index 1c560629575..e7dab069ccc 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -162,6 +162,16 @@ static void rs690_mc_init(struct radeon_device *rdev) base = RREG32_MC(R_000100_MCCFG_FB_LOCATION); base = G_000100_MC_FB_START(base) << 16; rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); + /* Some boards seem to be configured for 128MB of sideport memory, + * but really only have 64MB. Just skip the sideport and use + * UMA memory. + */ + if (rdev->mc.igp_sideport_enabled && + (rdev->mc.real_vram_size == (384 * 1024 * 1024))) { + base += 128 * 1024 * 1024; + rdev->mc.real_vram_size -= 128 * 1024 * 1024; + rdev->mc.mc_vram_size = rdev->mc.real_vram_size; + } /* Use K8 direct mapping for fast fb access. */ rdev->fastfb_working = false; -- cgit v1.2.3-70-g09d2 From 1522f9c79cd29c8f55120777ddc8ba63b9216509 Mon Sep 17 00:00:00 2001 From: Martin Andersson Date: Sat, 7 Dec 2013 23:22:10 +0100 Subject: drm/radeon/dpm: Fix hwmon crash Commit ec39f64bba3421c2060fcbd1aeb6eec81fe0a42d (drm/radeon/dpm: Convert to use devm_hwmon_register_with_groups) converted one usage of dev_get_drvdata, but there were two more. bug: https://bugs.freedesktop.org/show_bug.cgi?id=72457 Signed-off-by: Martin Andersson Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_pm.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index dc75bb603ea..984097b907e 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -552,8 +552,7 @@ static ssize_t radeon_hwmon_show_temp_thresh(struct device *dev, struct device_attribute *attr, char *buf) { - struct drm_device *ddev = dev_get_drvdata(dev); - struct radeon_device *rdev = ddev->dev_private; + struct radeon_device *rdev = dev_get_drvdata(dev); int hyst = to_sensor_dev_attr(attr)->index; int temp; @@ -580,8 +579,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct attribute *attr, int index) { struct device *dev = container_of(kobj, struct device, kobj); - struct drm_device *ddev = dev_get_drvdata(dev); - struct radeon_device *rdev = ddev->dev_private; + struct radeon_device *rdev = dev_get_drvdata(dev); /* Skip limit attributes if DPM is not enabled */ if (rdev->pm.pm_method != PM_METHOD_DPM && -- cgit v1.2.3-70-g09d2 From 7819678faec569f90c243d877c6f948dfb03f3a9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 9 Dec 2013 17:38:51 -0500 Subject: drm/radeon/cik: plug in missing blit callback I implemented support for this, but forget to hook up the callback so the driver can actually use it. On asics with a dedicated DMA engine, we use the DMA engine for buffer migration so this is just for testing purposes. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_asic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index e354ce94cdd..c0425bb6223 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -2021,7 +2021,7 @@ static struct radeon_asic ci_asic = { .hdmi_setmode = &evergreen_hdmi_setmode, }, .copy = { - .blit = NULL, + .blit = &cik_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &cik_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, @@ -2122,7 +2122,7 @@ static struct radeon_asic kv_asic = { .hdmi_setmode = &evergreen_hdmi_setmode, }, .copy = { - .blit = NULL, + .blit = &cik_copy_cpdma, .blit_ring_index = RADEON_RING_TYPE_GFX_INDEX, .dma = &cik_copy_dma, .dma_ring_index = R600_RING_TYPE_DMA_INDEX, -- cgit v1.2.3-70-g09d2 From 1b3abef830db98c11d7f916a483abaf2501f3323 Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 10 Dec 2013 17:57:37 +0100 Subject: drm/radeon: fix typo in cik_copy_dma MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we end up with a rather strange looking result. Signed-off-by: Christian König Tested-by: Tom Stellard Cc: stable@vger.kernel.org Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/cik_sdma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index 0300727a4f7..d08b83c6267 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -458,7 +458,7 @@ int cik_copy_dma(struct radeon_device *rdev, radeon_ring_write(ring, 0); /* src/dst endian swap */ radeon_ring_write(ring, src_offset & 0xffffffff); radeon_ring_write(ring, upper_32_bits(src_offset) & 0xffffffff); - radeon_ring_write(ring, dst_offset & 0xfffffffc); + radeon_ring_write(ring, dst_offset & 0xffffffff); radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xffffffff); src_offset += cur_size_in_bytes; dst_offset += cur_size_in_bytes; -- cgit v1.2.3-70-g09d2 From 227ae10f17a5f2fd1307b7e582b603ef7bbb7e97 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 11 Dec 2013 11:43:58 -0500 Subject: drm/radeon: add missing display tiling setup for oland Fixes improperly set up display params for 2D tiling on oland. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/atombios_crtc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 80a20120e62..b1970596a78 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1196,7 +1196,9 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, } else if ((rdev->family == CHIP_TAHITI) || (rdev->family == CHIP_PITCAIRN)) fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P8_32x32_8x16); - else if (rdev->family == CHIP_VERDE) + else if ((rdev->family == CHIP_VERDE) || + (rdev->family == CHIP_OLAND) || + (rdev->family == CHIP_HAINAN)) /* for completeness. HAINAN has no display hw */ fb_format |= SI_GRPH_PIPE_CONFIG(SI_ADDR_SURF_P4_8x16); switch (radeon_crtc->crtc_id) { -- cgit v1.2.3-70-g09d2 From 59aebe2b32466f7ed5b79f18646be6dddc926a6d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 12 Dec 2013 09:05:06 -0500 Subject: Revert "drm/radeon: Implement radeon_pci_shutdown" This causes a race condition between drm_dev_unregister() and pci_driver.shutdown at shutdown or driver unload time. We need to revisit how to properly support kexec within the drm. This reverts commit 846ae41ae99d314bf2a02784152208a6ddf7eddc. --- drivers/gpu/drm/radeon/radeon_drv.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 9f5ff28864f..1958b36ad0e 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -508,15 +508,6 @@ static const struct file_operations radeon_driver_kms_fops = { #endif }; - -static void -radeon_pci_shutdown(struct pci_dev *pdev) -{ - struct drm_device *dev = pci_get_drvdata(pdev); - - radeon_driver_unload_kms(dev); -} - static struct drm_driver kms_driver = { .driver_features = DRIVER_USE_AGP | @@ -586,7 +577,6 @@ static struct pci_driver radeon_kms_pci_driver = { .probe = radeon_pci_probe, .remove = radeon_pci_remove, .driver.pm = &radeon_pm_ops, - .shutdown = radeon_pci_shutdown, }; static int __init radeon_init(void) -- cgit v1.2.3-70-g09d2 From 0f58411d4fd704d8958879fb08751eae3573271b Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Thu, 5 Dec 2013 09:42:49 -0500 Subject: drm: don't double-free on driver load error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All instances of drm_dev_register are followed by drm_dev_free on failure. Don't free dev->control/render/primary on failure, as they will be freed by drm_dev_free since commit 8f6599da8e (drm: delay minor destruction to drm_dev_free()). Instead unplug them. Signed-off-by: Ilia Mirkin Reported-and-tested-by: Bruno Prémont Reviewed-by: David Herrmann Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_stub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_stub.c b/drivers/gpu/drm/drm_stub.c index f53d5246979..66dd3a001cf 100644 --- a/drivers/gpu/drm/drm_stub.c +++ b/drivers/gpu/drm/drm_stub.c @@ -566,11 +566,11 @@ err_unload: if (dev->driver->unload) dev->driver->unload(dev); err_primary_node: - drm_put_minor(dev->primary); + drm_unplug_minor(dev->primary); err_render_node: - drm_put_minor(dev->render); + drm_unplug_minor(dev->render); err_control_node: - drm_put_minor(dev->control); + drm_unplug_minor(dev->control); err_agp: if (dev->driver->bus->agp_destroy) dev->driver->bus->agp_destroy(dev); -- cgit v1.2.3-70-g09d2 From b25b4427e9dfba073cf9bc86603956ed395eb6e3 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Wed, 11 Dec 2013 22:19:01 -0500 Subject: drm/nouveau: only runtime suspend by default in optimus configuration The intent was to only enable it by default for optimus, e.g. see the runtime_idle callback. The suspend callback may be called directly, e.g. as a result of nouveau_crtc_set_config. Reported-by: Stefan Lippers-Hollmann Signed-off-by: Ilia Mirkin Tested-by: Stefan Lippers-Hollmann Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_drm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 7a3759f1c41..98a22e6e27a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -858,6 +858,12 @@ static int nouveau_pmops_runtime_suspend(struct device *dev) if (nouveau_runtime_pm == 0) return -EINVAL; + /* are we optimus enabled? */ + if (nouveau_runtime_pm == -1 && !nouveau_is_optimus() && !nouveau_is_v1_dsm()) { + DRM_DEBUG_DRIVER("failing to power off - not optimus\n"); + return -EINVAL; + } + nv_debug_level(SILENT); drm_kms_helper_poll_disable(drm_dev); vga_switcheroo_set_dynamic_switch(pdev, VGA_SWITCHEROO_OFF); -- cgit v1.2.3-70-g09d2 From d386735588c3e22129c2bc6eb64fc1d37a8f805c Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sun, 8 Dec 2013 23:23:57 -0800 Subject: drm/ttm: Fix accesses through vmas with only partial coverage VMAs covering a bo but that didn't start at the same address space offset as the bo they were mapping were incorrectly generating SEGFAULT errors in the fault handler. Reported-by: Joseph Dolinak Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Cc: stable@vger.kernel.org --- drivers/gpu/drm/ttm/ttm_bo_vm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index b249ab9b1eb..6440eeac22d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -169,9 +169,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + - drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff; - page_last = vma_pages(vma) + - drm_vma_node_start(&bo->vma_node) - vma->vm_pgoff; + vma->vm_pgoff - drm_vma_node_start(&bo->vma_node); + page_last = vma_pages(vma) + vma->vm_pgoff - + drm_vma_node_start(&bo->vma_node); if (unlikely(page_offset >= bo->num_pages)) { retval = VM_FAULT_SIGBUS; -- cgit v1.2.3-70-g09d2 From 49d45a31b71d7d9da74485922bdb63faf3dc9684 Mon Sep 17 00:00:00 2001 From: Rafał Miłecki Date: Sat, 7 Dec 2013 13:22:42 +0100 Subject: drm/edid: add quirk for BPC in Samsung NP700G7A-S01PL notebook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This bug in EDID was exposed by: commit eccea7920cfb009c2fa40e9ecdce8c36f61cab66 Author: Alex Deucher Date: Mon Mar 26 15:12:54 2012 -0400 drm/radeon/kms: improve bpc handling (v2) Which resulted in kind of regression in 3.5. This fixes https://bugs.freedesktop.org/show_bug.cgi?id=70934 Signed-off-by: Rafał Miłecki Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 0a1e4a5f423..8835dcddfac 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -68,6 +68,8 @@ #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) /* Force reduced-blanking timings for detailed modes */ #define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) +/* Force 8bpc */ +#define EDID_QUIRK_FORCE_8BPC (1 << 8) struct detailed_mode_closure { struct drm_connector *connector; @@ -128,6 +130,9 @@ static struct edid_quirk { /* Medion MD 30217 PG */ { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 }, + + /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */ + { "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC }, }; /* @@ -3435,6 +3440,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) drm_add_display_info(edid, &connector->display_info); + if (quirks & EDID_QUIRK_FORCE_8BPC) + connector->display_info.bpc = 8; + return num_modes; } EXPORT_SYMBOL(drm_add_edid_modes); -- cgit v1.2.3-70-g09d2