Re: [Intel-gfx] [PATCH 4/9] drm/i915: fixup g4x pll limits

2013-06-12 Thread Ville Syrjälä
On Wed, Jun 12, 2013 at 12:07:39AM +0100, Damien Lespiau wrote:
 On Tue, May 21, 2013 at 09:54:54PM +0200, Daniel Vetter wrote:
  Again the same confusion that our code expects m1/m2 in register values.
  This time around with the added fun that many of the existing values
  have been all off by a bit in different directions. Hence extract a
  common #define.
  
  Note that n limits differ between lvds and other outputs. Strangely they've
  all been correct already.
  
  v2: Rebased on top of the DP pll rework, which makes it even more
  obvious that we can do this ...
 
 I'm a bit confused by this one:
 
   - I don't seem to find the special LVDS limits for n

Me neither.

   - Those limits are gated by a IS_G4X(). IS_G4X() is true for eaglelake
 and cantiga. The docs single out Cantiga and we seem to need a
 different set of limits for that platform (compared to the rest of
 gen4) platforms?

I've noticed that the docs often mention just CTG leaving out ELK, even
though the stuff it's describing applies to both.

   - The limits for n are 3-6 or 3-5 in this code but I read 3-8 and 5-6
 (cantiga)

I see 3-8 and 4-6.

   - m doesn't seem to match what I have, it seems like it could be the
 cantiga values (except that m is in formula space so we don't
 substract 2)

105-140 is what the spec tells me, so a bit off either way.

There's more inconsistency w/ the p/p1 limits too, and the single
channel lvds dotclock limit doesn't agree w/ the spec either.

   - m1 and m2 seem to match what I have for cantiga, are we supposed to
 have those limits for eaglelake as well?
 
 Well, the only conclusion is that I must be reading the wrong docs, or?
 
  
  Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
  ---
   drivers/gpu/drm/i915/intel_display.c | 20 
   1 file changed, 8 insertions(+), 12 deletions(-)
  
  diff --git a/drivers/gpu/drm/i915/intel_display.c 
  b/drivers/gpu/drm/i915/intel_display.c
  index ea8eb0c..cb54131 100644
  --- a/drivers/gpu/drm/i915/intel_display.c
  +++ b/drivers/gpu/drm/i915/intel_display.c
  @@ -136,14 +136,16 @@ static const intel_limit_t intel_limits_i9xx_lvds = {
  .p2_slow = 14, .p2_fast = 7 },
   };
   
  +#define G4X_DPLL_M_LIMITS \
  +   .m = { .min = 104, .max = 138 },\
  +   .m1 = { .min = 15, .max = 21 },\
  +   .m2 = { .min = 3, .max = 11 },
   
   static const intel_limit_t intel_limits_g4x_sdvo = {
  .dot = { .min = 25000, .max = 27 },
  .vco = { .min = 175, .max = 350},
  .n = { .min = 1, .max = 4 },
  -   .m = { .min = 104, .max = 138 },
  -   .m1 = { .min = 17, .max = 23 },
  -   .m2 = { .min = 5, .max = 11 },
  +   G4X_DPLL_M_LIMITS
  .p = { .min = 10, .max = 30 },
  .p1 = { .min = 1, .max = 3},
  .p2 = { .dot_limit = 27,
  @@ -156,9 +158,7 @@ static const intel_limit_t intel_limits_g4x_hdmi = {
  .dot = { .min = 22000, .max = 40 },
  .vco = { .min = 175, .max = 350},
  .n = { .min = 1, .max = 4 },
  -   .m = { .min = 104, .max = 138 },
  -   .m1 = { .min = 16, .max = 23 },
  -   .m2 = { .min = 5, .max = 11 },
  +   G4X_DPLL_M_LIMITS
  .p = { .min = 5, .max = 80 },
  .p1 = { .min = 1, .max = 8},
  .p2 = { .dot_limit = 165000,
  @@ -169,9 +169,7 @@ static const intel_limit_t 
  intel_limits_g4x_single_channel_lvds = {
  .dot = { .min = 2, .max = 115000 },
  .vco = { .min = 175, .max = 350 },
  .n = { .min = 1, .max = 3 },
  -   .m = { .min = 104, .max = 138 },
  -   .m1 = { .min = 17, .max = 23 },
  -   .m2 = { .min = 5, .max = 11 },
  +   G4X_DPLL_M_LIMITS
  .p = { .min = 28, .max = 112 },
  .p1 = { .min = 2, .max = 8 },
  .p2 = { .dot_limit = 0,
  @@ -183,9 +181,7 @@ static const intel_limit_t 
  intel_limits_g4x_dual_channel_lvds = {
  .dot = { .min = 8, .max = 224000 },
  .vco = { .min = 175, .max = 350 },
  .n = { .min = 1, .max = 3 },
  -   .m = { .min = 104, .max = 138 },
  -   .m1 = { .min = 17, .max = 23 },
  -   .m2 = { .min = 5, .max = 11 },
  +   G4X_DPLL_M_LIMITS
  .p = { .min = 14, .max = 42 },
  .p1 = { .min = 2, .max = 6 },
  .p2 = { .dot_limit = 0,
  -- 
  1.7.11.7
  
  ___
  Intel-gfx mailing list
  Intel-gfx@lists.freedesktop.org
  http://lists.freedesktop.org/mailman/listinfo/intel-gfx
 ___
 Intel-gfx mailing list
 Intel-gfx@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ville Syrjälä
Intel OTC
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 4/9] drm/i915: fixup g4x pll limits

2013-06-12 Thread Daniel Vetter
On Wed, Jun 12, 2013 at 12:07:39AM +0100, Damien Lespiau wrote:
 On Tue, May 21, 2013 at 09:54:54PM +0200, Daniel Vetter wrote:
  Again the same confusion that our code expects m1/m2 in register values.
  This time around with the added fun that many of the existing values
  have been all off by a bit in different directions. Hence extract a
  common #define.
  
  Note that n limits differ between lvds and other outputs. Strangely they've
  all been correct already.
  
  v2: Rebased on top of the DP pll rework, which makes it even more
  obvious that we can do this ...
 
 I'm a bit confused by this one:
 
   - I don't seem to find the special LVDS limits for n
   - Those limits are gated by a IS_G4X(). IS_G4X() is true for eaglelake
 and cantiga. The docs single out Cantiga and we seem to need a
 different set of limits for that platform (compared to the rest of
 gen4) platforms?
   - The limits for n are 3-6 or 3-5 in this code but I read 3-8 and 5-6
 (cantiga)

I've looked at the mess around n values and decided to run the other
direction. My understanding is that the min/max in the xml are just the
limits of the table and not the hw (i.e. with the given clock ranges and
precision all the most precise clock settings happen to only use that
range).

For the actual values they seem to agree with my docs here with the
exception of TV-out. I have no idea what's going on there really, but at
least this patch here shouldn't break stuff. Otoh native TV-out seems to
have it's own pll and also pipe timing registers, so maybe it simply
doesn't matter.

   - m doesn't seem to match what I have, it seems like it could be the
 cantiga values (except that m is in formula space so we don't
 substract 2)

Yeah, m is in formula space, since we compare that limit with what
i9xx_dpll_compute_m does.

   - m1 and m2 seem to match what I have for cantiga, are we supposed to
 have those limits for eaglelake as well?

Afaik eaglelake as the desktop version of cantiga has all the same stuff
(minus a few mobile-only power saving features). The spreadsheet I have
here is even called eaglelake_cantiga_something.xls.

 Well, the only conclusion is that I must be reading the wrong docs, or?

I guess I didn't really help :(
-Daniel

 
  
  Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
  ---
   drivers/gpu/drm/i915/intel_display.c | 20 
   1 file changed, 8 insertions(+), 12 deletions(-)
  
  diff --git a/drivers/gpu/drm/i915/intel_display.c 
  b/drivers/gpu/drm/i915/intel_display.c
  index ea8eb0c..cb54131 100644
  --- a/drivers/gpu/drm/i915/intel_display.c
  +++ b/drivers/gpu/drm/i915/intel_display.c
  @@ -136,14 +136,16 @@ static const intel_limit_t intel_limits_i9xx_lvds = {
  .p2_slow = 14, .p2_fast = 7 },
   };
   
  +#define G4X_DPLL_M_LIMITS \
  +   .m = { .min = 104, .max = 138 },\
  +   .m1 = { .min = 15, .max = 21 },\
  +   .m2 = { .min = 3, .max = 11 },
   
   static const intel_limit_t intel_limits_g4x_sdvo = {
  .dot = { .min = 25000, .max = 27 },
  .vco = { .min = 175, .max = 350},
  .n = { .min = 1, .max = 4 },
  -   .m = { .min = 104, .max = 138 },
  -   .m1 = { .min = 17, .max = 23 },
  -   .m2 = { .min = 5, .max = 11 },
  +   G4X_DPLL_M_LIMITS
  .p = { .min = 10, .max = 30 },
  .p1 = { .min = 1, .max = 3},
  .p2 = { .dot_limit = 27,
  @@ -156,9 +158,7 @@ static const intel_limit_t intel_limits_g4x_hdmi = {
  .dot = { .min = 22000, .max = 40 },
  .vco = { .min = 175, .max = 350},
  .n = { .min = 1, .max = 4 },
  -   .m = { .min = 104, .max = 138 },
  -   .m1 = { .min = 16, .max = 23 },
  -   .m2 = { .min = 5, .max = 11 },
  +   G4X_DPLL_M_LIMITS
  .p = { .min = 5, .max = 80 },
  .p1 = { .min = 1, .max = 8},
  .p2 = { .dot_limit = 165000,
  @@ -169,9 +169,7 @@ static const intel_limit_t 
  intel_limits_g4x_single_channel_lvds = {
  .dot = { .min = 2, .max = 115000 },
  .vco = { .min = 175, .max = 350 },
  .n = { .min = 1, .max = 3 },
  -   .m = { .min = 104, .max = 138 },
  -   .m1 = { .min = 17, .max = 23 },
  -   .m2 = { .min = 5, .max = 11 },
  +   G4X_DPLL_M_LIMITS
  .p = { .min = 28, .max = 112 },
  .p1 = { .min = 2, .max = 8 },
  .p2 = { .dot_limit = 0,
  @@ -183,9 +181,7 @@ static const intel_limit_t 
  intel_limits_g4x_dual_channel_lvds = {
  .dot = { .min = 8, .max = 224000 },
  .vco = { .min = 175, .max = 350 },
  .n = { .min = 1, .max = 3 },
  -   .m = { .min = 104, .max = 138 },
  -   .m1 = { .min = 17, .max = 23 },
  -   .m2 = { .min = 5, .max = 11 },
  +   G4X_DPLL_M_LIMITS
  .p = { .min = 14, .max = 42 },
  .p1 = { .min = 2, .max = 6 },
  .p2 = { .dot_limit = 0,
  -- 
  1.7.11.7
  
  ___
  Intel-gfx mailing list
  Intel-gfx@lists.freedesktop.org
  http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel 

Re: [Intel-gfx] [PATCH] drm/i915: Fix VLV analog output shivers

2013-06-12 Thread Ville Syrjälä
On Tue, Jun 11, 2013 at 04:18:46PM -0700, Jesse Barnes wrote:
 On Tue, 11 Jun 2013 23:06:59 +0200
 Daniel Vetter dan...@ffwll.ch wrote:
 
  On Tue, Jun 11, 2013 at 11:08:16PM +0300, ville.syrj...@linux.intel.com 
  wrote:
   From: Ville Syrjälä ville.syrj...@linux.intel.com
   
   The current PLL settings produce a rather unstable picture when
   I hook up a VLV to my HP ZR24w display via a VGA cable. Switching
   the PLL to hybrid mode makes the picture a lot more stable. No
   idea if this is truly wise though...
  
  Ok, you've just slipped up here and mentioned that the changed bit is for
  hybrid mode. Can I have real register defines for this magic now please?
  
  Apparently Jesse just weaseled out of real work claiming that it's not
  documented at all ;-)
  
 
 There are some bits we could use, but we'd be making up the name.  On
 top of that, the hex value is used in the docs, so if we make up bit
 field names, we'll end up double taking everytime we look at these bits.
 
 So there's no good answer here... :/

For this particular register I've not seen any documented correct
value. I have no idea where the values used in the code came from. If
you have a document that has them, I'd like to see it.

There are certainly some register values that are specified as raw hex
numbers in some docs, but I've noticed that in some cases even those
don't agree with our code :(

-- 
Ville Syrjälä
Intel OTC
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH] drm/i915: Fix VLV analog output shivers

2013-06-12 Thread Daniel Vetter
On Wed, Jun 12, 2013 at 10:14 AM, Ville Syrjälä
ville.syrj...@linux.intel.com wrote:
 On Tue, Jun 11, 2013 at 04:18:46PM -0700, Jesse Barnes wrote:
 On Tue, 11 Jun 2013 23:06:59 +0200
 Daniel Vetter dan...@ffwll.ch wrote:

  On Tue, Jun 11, 2013 at 11:08:16PM +0300, ville.syrj...@linux.intel.com 
  wrote:
   From: Ville Syrjälä ville.syrj...@linux.intel.com
  
   The current PLL settings produce a rather unstable picture when
   I hook up a VLV to my HP ZR24w display via a VGA cable. Switching
   the PLL to hybrid mode makes the picture a lot more stable. No
   idea if this is truly wise though...
 
  Ok, you've just slipped up here and mentioned that the changed bit is for
  hybrid mode. Can I have real register defines for this magic now please?
 
  Apparently Jesse just weaseled out of real work claiming that it's not
  documented at all ;-)
 

 There are some bits we could use, but we'd be making up the name.  On
 top of that, the hex value is used in the docs, so if we make up bit
 field names, we'll end up double taking everytime we look at these bits.

 So there's no good answer here... :/

 For this particular register I've not seen any documented correct
 value. I have no idea where the values used in the code came from. If
 you have a document that has them, I'd like to see it.

 There are certainly some register values that are specified as raw hex
 numbers in some docs, but I've noticed that in some cases even those
 don't agree with our code :(

Yeah, I'd prefer if we can slowly move to less magic. It's more work
to fill updates from the validation guys into patches, otoh it should
help greatly to reduce accidental breakage. And if regressions start
to hit us we might have a stab at a sensible revert.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH] drm/i915: Restore fences after resume and GPU resets

2013-06-12 Thread Chris Wilson
Stéphane Marchesin found that fences for pinned objects (i.e. the
scanout) were not being restored upon resume, leading to corruption on
the display and reference counting issues. This is due to a bug in

commit 312817a39f17dbb4de000165b5b724e3728cd91c [2.6.38]
Author: Chris Wilson ch...@chris-wilson.co.uk
Date:   Mon Nov 22 11:50:11 2010 +

drm/i915: Only save and restore fences for UMS

that zapped the pinned fences even though they were in use.
Fortuitously, whilst we forced a VT switch during suspend and resume,
no fences were ever pinned at the time. However, we now can do
switchless S3 transitions and so the old bug finally surfaces.

Reported-by: Stéphane Marchesin marc...@chromium.org
Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk
Cc: Daniel Vetter daniel.vet...@ffwll.ch
Cc: Stéphane Marchesin marc...@chromium.org
---
 drivers/gpu/drm/i915/i915_drv.h |2 ++
 drivers/gpu/drm/i915/i915_gem.c |   22 +-
 drivers/gpu/drm/i915/i915_suspend.c |1 +
 3 files changed, 8 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index bacc2fe..1a67216 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1793,6 +1793,8 @@ struct drm_gem_object *i915_gem_prime_import(struct 
drm_device *dev,
 struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
struct drm_gem_object *gem_obj, int flags);
 
+void i915_gem_restore_fences(struct drm_device *dev);
+
 /* i915_gem_context.c */
 void i915_gem_context_init(struct drm_device *dev);
 void i915_gem_context_fini(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 61956a1..773c8f4 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2142,25 +2142,15 @@ static void i915_gem_reset_ring_lists(struct 
drm_i915_private *dev_priv,
ring-sync_seqno[i] = 0;
 }
 
-static void i915_gem_reset_fences(struct drm_device *dev)
+void i915_gem_restore_fences(struct drm_device *dev)
 {
struct drm_i915_private *dev_priv = dev-dev_private;
int i;
 
for (i = 0; i  dev_priv-num_fence_regs; i++) {
struct drm_i915_fence_reg *reg = dev_priv-fence_regs[i];
-
-   if (reg-obj)
-   i915_gem_object_fence_lost(reg-obj);
-
-   i915_gem_write_fence(dev, i, NULL);
-
-   reg-pin_count = 0;
-   reg-obj = NULL;
-   INIT_LIST_HEAD(reg-lru_list);
+   i915_gem_write_fence(dev, i, reg-obj);
}
-
-   INIT_LIST_HEAD(dev_priv-mm.fence_list);
 }
 
 void i915_gem_reset(struct drm_device *dev)
@@ -2187,8 +2177,7 @@ void i915_gem_reset(struct drm_device *dev)
obj-base.read_domains = ~I915_GEM_GPU_DOMAINS;
}
 
-   /* The fence registers are invalidated so clear them out */
-   i915_gem_reset_fences(dev);
+   i915_gem_restore_fences(dev);
 }
 
 /**
@@ -3922,8 +3911,6 @@ i915_gem_idle(struct drm_device *dev)
if (!drm_core_check_feature(dev, DRIVER_MODESET))
i915_gem_evict_everything(dev);
 
-   i915_gem_reset_fences(dev);
-
/* Hack!  Don't let anybody do execbuf while we don't control the chip.
 * We need to replace this with a semaphore, or something.
 * And not confound mm.suspended!
@@ -4259,7 +4246,8 @@ i915_gem_load(struct drm_device *dev)
dev_priv-num_fence_regs = 8;
 
/* Initialize fence registers to zero */
-   i915_gem_reset_fences(dev);
+   INIT_LIST_HEAD(dev_priv-mm.fence_list);
+   i915_gem_restore_fences(dev);
 
i915_gem_detect_bit_6_swizzle(dev);
init_waitqueue_head(dev_priv-pending_flip_queue);
diff --git a/drivers/gpu/drm/i915/i915_suspend.c 
b/drivers/gpu/drm/i915/i915_suspend.c
index 88b9a66..70db618 100644
--- a/drivers/gpu/drm/i915/i915_suspend.c
+++ b/drivers/gpu/drm/i915/i915_suspend.c
@@ -394,6 +394,7 @@ int i915_restore_state(struct drm_device *dev)
 
mutex_lock(dev-struct_mutex);
 
+   i915_gem_restore_fences(dev);
i915_restore_display(dev);
 
if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 5/7] drm/i915: store ring hangcheck action

2013-06-12 Thread Mika Kuoppala
For guilty batchbuffer analysis later on when rings are reset,
store what state the ring was on when hang was declared.
This helps to weed out the waiting rings from the active ones.

Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
---
 drivers/gpu/drm/i915/i915_irq.c |8 ++--
 drivers/gpu/drm/i915/intel_ringbuffer.h |3 +++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index b26243f..208e675 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2380,7 +2380,8 @@ static void semaphore_clear_deadlocks(struct 
drm_i915_private *dev_priv)
ring-hangcheck.deadlock = false;
 }
 
-static enum { wait, active, kick, hung } ring_stuck(struct intel_ring_buffer 
*ring, u32 acthd)
+static enum intel_ring_hangcheck_action
+ring_stuck(struct intel_ring_buffer *ring, u32 acthd)
 {
struct drm_device *dev = ring-dev;
struct drm_i915_private *dev_priv = dev-dev_private;
@@ -2483,7 +2484,10 @@ void i915_hangcheck_elapsed(unsigned long data)
 * being repeatedly kicked and so responsible
 * for stalling the machine.
 */
-   switch (ring_stuck(ring, acthd)) {
+   ring-hangcheck.action = ring_stuck(ring,
+   acthd);
+
+   switch (ring-hangcheck.action) {
case wait:
score = 0;
break;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h 
b/drivers/gpu/drm/i915/intel_ringbuffer.h
index a3e9610..799f04c 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -37,11 +37,14 @@ struct  intel_hw_status_page {
 #define I915_READ_SYNC_0(ring) I915_READ(RING_SYNC_0((ring)-mmio_base))
 #define I915_READ_SYNC_1(ring) I915_READ(RING_SYNC_1((ring)-mmio_base))
 
+enum intel_ring_hangcheck_action { wait, active, kick, hung };
+
 struct intel_ring_hangcheck {
bool deadlock;
u32 seqno;
u32 acthd;
int score;
+   enum intel_ring_hangcheck_action action;
 };
 
 struct  intel_ring_buffer {
-- 
1.7.9.5

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 4/7] drm/i915: add batch bo to i915_add_request()

2013-06-12 Thread Mika Kuoppala
In order to track down a batch buffer and context which
caused the ring to hang, store reference to bo into the request struct.
Request can also cause gpu to hang after the batch in the flush section
in the ring. To detect this add start of the flush portion offset into the
request.

Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
---
 drivers/gpu/drm/i915/i915_drv.h|   11 +--
 drivers/gpu/drm/i915/i915_gem.c|6 +-
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |7 ---
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 22dcff6..8bc399c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1352,12 +1352,18 @@ struct drm_i915_gem_request {
/** GEM sequence number associated with this request. */
uint32_t seqno;
 
-   /** Postion in the ringbuffer of the end of the request */
+   /** Position in the ringbuffer of the start of the request */
+   u32 head;
+
+   /** Position in the ringbuffer of the end of the request */
u32 tail;
 
/** Context related to this request */
struct i915_hw_context *ctx;
 
+   /** Batch buffer related to this request if any */
+   struct drm_i915_gem_object *batch_obj;
+
/** Time at which this request was emitted, in jiffies. */
unsigned long emitted_jiffies;
 
@@ -1747,9 +1753,10 @@ int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_idle(struct drm_device *dev);
 int __i915_add_request(struct intel_ring_buffer *ring,
   struct drm_file *file,
+  struct drm_i915_gem_object *batch_obj,
   u32 *seqno);
 #define i915_add_request(ring, seqno) \
-   __i915_add_request(ring, NULL, seqno);
+   __i915_add_request(ring, NULL, NULL, seqno);
 int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
 uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 38e2087..5be7846 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2002,14 +2002,16 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)
 
 int __i915_add_request(struct intel_ring_buffer *ring,
   struct drm_file *file,
+  struct drm_i915_gem_object *obj,
   u32 *out_seqno)
 {
drm_i915_private_t *dev_priv = ring-dev-dev_private;
struct drm_i915_gem_request *request;
-   u32 request_ring_position;
+   u32 request_ring_position, request_start;
int was_empty;
int ret;
 
+   request_start = intel_ring_get_tail(ring);
/*
 * Emit any outstanding flushes - execbuf can fail to emit the flush
 * after having emitted the batchbuffer command. Hence we need to fix
@@ -2041,8 +2043,10 @@ int __i915_add_request(struct intel_ring_buffer *ring,
 
request-seqno = intel_ring_get_seqno(ring);
request-ring = ring;
+   request-head = request_start;
request-tail = request_ring_position;
request-ctx = ring-last_context;
+   request-batch_obj = obj;
 
if (request-ctx)
i915_gem_context_reference(request-ctx);
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index d79ac7a..87a3227 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -796,13 +796,14 @@ i915_gem_execbuffer_move_to_active(struct list_head 
*objects,
 static void
 i915_gem_execbuffer_retire_commands(struct drm_device *dev,
struct drm_file *file,
-   struct intel_ring_buffer *ring)
+   struct intel_ring_buffer *ring,
+   struct drm_i915_gem_object *obj)
 {
/* Unconditionally force add_request to emit a full flush. */
ring-gpu_caches_dirty = true;
 
/* Add a breadcrumb for the completion of the batch buffer */
-   (void)__i915_add_request(ring, file, NULL);
+   (void)__i915_add_request(ring, file, obj, NULL);
 }
 
 static int
@@ -1083,7 +1084,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
 
i915_gem_execbuffer_move_to_active(eb-objects, ring);
-   i915_gem_execbuffer_retire_commands(dev, file, ring);
+   i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj);
 
 err:
eb_destroy(eb);
-- 
1.7.9.5

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 1/7] drm/i915: add struct i915_ctx_hang_stats

2013-06-12 Thread Mika Kuoppala
To count context losses, add struct i915_ctx_hang_stats for
both i915_hw_context and drm_i915_file_private.
drm_i915_file_private is used when there is no context.

v2: renamed and cleaned up the struct (Chris Wilson, Ian Romanick)

Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
---
 drivers/gpu/drm/i915/i915_dma.c |2 +-
 drivers/gpu/drm/i915/i915_drv.h |   10 ++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index fd8898c..8e628dc 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1814,7 +1814,7 @@ int i915_driver_open(struct drm_device *dev, struct 
drm_file *file)
struct drm_i915_file_private *file_priv;
 
DRM_DEBUG_DRIVER(\n);
-   file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL);
+   file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
if (!file_priv)
return -ENOMEM;
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index eaa04a6..5f3da39 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -498,6 +498,13 @@ struct i915_hw_ppgtt {
void (*cleanup)(struct i915_hw_ppgtt *ppgtt);
 };
 
+struct i915_ctx_hang_stats {
+   /* This context had batch pending when hang was declared */
+   unsigned batch_pending;
+
+   /* This context had batch active when hang was declared */
+   unsigned batch_active;
+};
 
 /* This must match up with the value previously used for execbuf2.rsvd1. */
 #define DEFAULT_CONTEXT_ID 0
@@ -508,6 +515,7 @@ struct i915_hw_context {
struct drm_i915_file_private *file_priv;
struct intel_ring_buffer *ring;
struct drm_i915_gem_object *obj;
+   struct i915_ctx_hang_stats hang_stats;
 };
 
 enum no_fbc_reason {
@@ -1367,6 +1375,8 @@ struct drm_i915_file_private {
struct list_head request_list;
} mm;
struct idr context_idr;
+
+   struct i915_ctx_hang_stats hang_stats;
 };
 
 #define INTEL_INFO(dev)(((struct drm_i915_private *) 
(dev)-dev_private)-info)
-- 
1.7.9.5

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 7/7] drm/i915: refuse to submit more batchbuffers from guilty context

2013-06-12 Thread Mika Kuoppala
If context has recently submitted a faulty batchbuffers guilty of
gpu hang and decides to keep submitting more crap, ban it permanently.

v2: Store guilty ban status bool in gpu_error instead of pointers
that might become danling before hang is declared.

v3: Use return value for banned status instead of stashing state
into gpu_error (Chris Wilson)

Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
---
 drivers/gpu/drm/i915/i915_drv.c|6 +++--
 drivers/gpu/drm/i915/i915_drv.h|8 ++-
 drivers/gpu/drm/i915/i915_gem.c|   34 
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   13 +++
 4 files changed, 49 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index c3e4f29..70b64fd 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -867,6 +867,7 @@ int i915_reset(struct drm_device *dev)
 {
drm_i915_private_t *dev_priv = dev-dev_private;
bool simulated;
+   bool ctx_banned;
int ret;
 
if (!i915_try_reset)
@@ -874,11 +875,12 @@ int i915_reset(struct drm_device *dev)
 
mutex_lock(dev-struct_mutex);
 
-   i915_gem_reset(dev);
+   ctx_banned = i915_gem_reset(dev);
 
simulated = dev_priv-gpu_error.stop_rings != 0;
 
-   if (!simulated  get_seconds() - dev_priv-gpu_error.last_reset  5) {
+   if (!(simulated || ctx_banned) 
+   get_seconds() - dev_priv-gpu_error.last_reset  5) {
DRM_ERROR(GPU hanging too fast, declaring wedged!\n);
ret = -ENODEV;
} else {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8bc399c..364afff 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -504,6 +504,12 @@ struct i915_ctx_hang_stats {
 
/* This context had batch active when hang was declared */
unsigned batch_active;
+
+   /* Time when this context was last blamed for a GPU reset */
+   unsigned long batch_active_reset_ts;
+
+   /* This context is banned to submit more work */
+   bool banned;
 };
 
 /* This must match up with the value previously used for execbuf2.rsvd1. */
@@ -1738,7 +1744,7 @@ static inline bool i915_terminally_wedged(struct 
i915_gpu_error *error)
return atomic_read(error-reset_counter) == I915_WEDGED;
 }
 
-void i915_gem_reset(struct drm_device *dev);
+bool i915_gem_reset(struct drm_device *dev);
 void i915_gem_clflush_object(struct drm_i915_gem_object *obj);
 int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj,
uint32_t read_domains,
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 6144f0b..3ecf1fe 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2143,15 +2143,15 @@ static bool i915_request_guilty(struct 
drm_i915_gem_request *request,
return false;
 }
 
-static void i915_set_reset_status(struct intel_ring_buffer *ring,
+static bool i915_set_reset_status(struct intel_ring_buffer *ring,
  struct drm_i915_gem_request *request,
  u32 acthd)
 {
struct i915_ctx_hang_stats *hs = NULL;
-   bool inside, guilty;
+   bool inside, guilty, banned;
 
/* Innocent until proven guilty */
-   guilty = false;
+   guilty = banned = false;
 
if (ring-hangcheck.last_action != wait 
i915_request_guilty(request, acthd, inside)) {
@@ -2175,11 +2175,20 @@ static void i915_set_reset_status(struct 
intel_ring_buffer *ring,
hs = request-file_priv-hang_stats;
 
if (hs) {
-   if (guilty)
+   if (guilty) {
+   if (!hs-banned 
+   get_seconds() - hs-batch_active_reset_ts  15) {
+   hs-banned = banned = true;
+   DRM_ERROR(context hanging too fast, declaring 
banned\n);
+   }
hs-batch_active++;
-   else
+   hs-batch_active_reset_ts = get_seconds();
+   } else {
hs-batch_pending++;
+   }
}
+
+   return banned;
 }
 
 static void i915_gem_free_request(struct drm_i915_gem_request *request)
@@ -2193,11 +2202,12 @@ static void i915_gem_free_request(struct 
drm_i915_gem_request *request)
kfree(request);
 }
 
-static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
+static bool i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
  struct intel_ring_buffer *ring)
 {
u32 completed_seqno;
u32 acthd;
+   bool ctx_banned = false;
 
acthd = intel_ring_get_active_head(ring);
completed_seqno = ring-get_seqno(ring, 

[Intel-gfx] [PATCH 2/7] drm/i915: add i915_gem_context_get_hang_stats()

2013-06-12 Thread Mika Kuoppala
To get context hang statistics for specified context,
add i915_gem_context_get_hang_stats().

For arb-robustness, every context needs to have its own
hang statistics tracking. Added function will return
the user specified context statistics or in case of
default context, statistics from drm_i915_file_private.

v2: handle default context inside get_reset_state

v3: return struct pointer instead of passing it in as param
(Chris Wilson)

Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
---
 drivers/gpu/drm/i915/i915_drv.h |4 
 drivers/gpu/drm/i915/i915_gem_context.c |   28 
 2 files changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5f3da39..5c15710 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1801,6 +1801,10 @@ static inline void i915_gem_context_unreference(struct 
i915_hw_context *ctx)
kref_put(ctx-ref, i915_gem_context_free);
 }
 
+struct i915_ctx_hang_stats * __must_check
+i915_gem_context_get_hang_stats(struct intel_ring_buffer *ring,
+   struct drm_file *file,
+   u32 id);
 int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
  struct drm_file *file);
 int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c 
b/drivers/gpu/drm/i915/i915_gem_context.c
index 39bcc08..f5ea3c1 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -303,6 +303,34 @@ static int context_idr_cleanup(int id, void *p, void *data)
return 0;
 }
 
+struct i915_ctx_hang_stats *
+i915_gem_context_get_hang_stats(struct intel_ring_buffer *ring,
+   struct drm_file *file,
+   u32 id)
+{
+   struct drm_i915_private *dev_priv = ring-dev-dev_private;
+   struct drm_i915_file_private *file_priv = file-driver_priv;
+   struct i915_hw_context *to;
+
+   if (dev_priv-hw_contexts_disabled)
+   return ERR_PTR(-ENOENT);
+
+   if (ring-id != RCS)
+   return ERR_PTR(-EINVAL);
+
+   if (file == NULL)
+   return ERR_PTR(-EINVAL);
+
+   if (id == DEFAULT_CONTEXT_ID)
+   return file_priv-hang_stats;
+
+   to = i915_gem_context_get(file-driver_priv, id);
+   if (to == NULL)
+   return ERR_PTR(-ENOENT);
+
+   return to-hang_stats;
+}
+
 void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
 {
struct drm_i915_file_private *file_priv = file-driver_priv;
-- 
1.7.9.5

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 3/7] drm/i915: change i915_add_request to macro

2013-06-12 Thread Mika Kuoppala
Only execbuffer needed all the parameters on i915_add_request().
By putting __i915_add_request behind macro, all current callsites
become cleaner. Following patch will introduce a new parameter
for __i915_add_request. With this patch, only the relevant callsite
will reflect the change making commit smaller and easier to understand.

v2: _i915_add_request as function name (Chris Wilson)

v3: change name __i915_add_request and fix ordering of params (Ben Widawsky)

Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
---
 drivers/gpu/drm/i915/i915_drv.h|8 +---
 drivers/gpu/drm/i915/i915_gem.c|   11 +--
 drivers/gpu/drm/i915/i915_gem_context.c|2 +-
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |2 +-
 drivers/gpu/drm/i915/intel_overlay.c   |4 ++--
 drivers/gpu/drm/i915/intel_ringbuffer.c|2 +-
 6 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5c15710..22dcff6 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1745,9 +1745,11 @@ void i915_gem_init_swizzling(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_idle(struct drm_device *dev);
-int i915_add_request(struct intel_ring_buffer *ring,
-struct drm_file *file,
-u32 *seqno);
+int __i915_add_request(struct intel_ring_buffer *ring,
+  struct drm_file *file,
+  u32 *seqno);
+#define i915_add_request(ring, seqno) \
+   __i915_add_request(ring, NULL, seqno);
 int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
 uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 58048d4..38e2087 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -959,7 +959,7 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 
seqno)
 
ret = 0;
if (seqno == ring-outstanding_lazy_request)
-   ret = i915_add_request(ring, NULL, NULL);
+   ret = i915_add_request(ring, NULL);
 
return ret;
 }
@@ -2000,10 +2000,9 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)
return 0;
 }
 
-int
-i915_add_request(struct intel_ring_buffer *ring,
-struct drm_file *file,
-u32 *out_seqno)
+int __i915_add_request(struct intel_ring_buffer *ring,
+  struct drm_file *file,
+  u32 *out_seqno)
 {
drm_i915_private_t *dev_priv = ring-dev-dev_private;
struct drm_i915_gem_request *request;
@@ -2280,7 +2279,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
idle = true;
for_each_ring(ring, dev_priv, i) {
if (ring-gpu_caches_dirty)
-   i915_add_request(ring, NULL, NULL);
+   i915_add_request(ring, NULL);
 
idle = list_empty(ring-request_list);
}
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c 
b/drivers/gpu/drm/i915/i915_gem_context.c
index f5ea3c1..ff47145 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -455,7 +455,7 @@ static int do_switch(struct i915_hw_context *to)
from-obj-dirty = 1;
BUG_ON(from-obj-ring != ring);
 
-   ret = i915_add_request(ring, NULL, NULL);
+   ret = i915_add_request(ring, NULL);
if (ret) {
/* Too late, we've already scheduled a context switch.
 * Try to undo the change so that the hw state is
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index c98333d..d79ac7a 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -802,7 +802,7 @@ i915_gem_execbuffer_retire_commands(struct drm_device *dev,
ring-gpu_caches_dirty = true;
 
/* Add a breadcrumb for the completion of the batch buffer */
-   (void)i915_add_request(ring, file, NULL);
+   (void)__i915_add_request(ring, file, NULL);
 }
 
 static int
diff --git a/drivers/gpu/drm/i915/intel_overlay.c 
b/drivers/gpu/drm/i915/intel_overlay.c
index 836794b..a369881 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -217,7 +217,7 @@ static int intel_overlay_do_wait_request(struct 
intel_overlay *overlay,
int ret;
 
BUG_ON(overlay-last_flip_req);
-   ret = i915_add_request(ring, NULL, overlay-last_flip_req);
+   ret = i915_add_request(ring, overlay-last_flip_req);
if (ret)
return ret;
 
@@ -286,7 +286,7 @@ static int 

[Intel-gfx] [PATCH 6/7] drm/i915: find guilty batch buffer on ring resets

2013-06-12 Thread Mika Kuoppala
After hang check timer has declared gpu to be hang,
rings are reset. In ring reset, when clearing
request list, do post mortem analysis to find out
the guilty batch buffer.

Select requests for further analysis by inspecting
the completed sequence number which has been updated
into the HWS page. If request was completed, it can't
be related to the hang.

For noncompleted requests mark the batch as guilty
if the ring was not waiting and the ring head was
stuck inside the buffer object or in the flush region
right after the batch. For everything else, mark
them as innocents.

v2: Fixed a typo in commit message (Ville Syrjälä)

Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
---
 drivers/gpu/drm/i915/i915_gem.c |   88 +++
 1 file changed, 88 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 5be7846..6144f0b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2103,6 +2103,85 @@ i915_gem_request_remove_from_client(struct 
drm_i915_gem_request *request)
spin_unlock(file_priv-mm.lock);
 }
 
+static bool i915_head_inside_object(u32 acthd, struct drm_i915_gem_object *obj)
+{
+   if (acthd = obj-gtt_offset 
+   acthd  obj-gtt_offset + obj-base.size)
+   return true;
+
+   return false;
+}
+
+static bool i915_head_inside_request(u32 acthd, u32 rs, u32 re)
+{
+   if (rs  re) {
+   if (acthd = rs  acthd  re)
+   return true;
+   } else if (rs  re) {
+   if (acthd = rs || acthd  re)
+   return true;
+   }
+
+   return false;
+}
+
+static bool i915_request_guilty(struct drm_i915_gem_request *request,
+   const u32 acthd, bool *inside)
+{
+   if (request-batch_obj) {
+   if (i915_head_inside_object(acthd, request-batch_obj)) {
+   *inside = true;
+   return true;
+   }
+   }
+
+   if (i915_head_inside_request(acthd, request-head, request-tail)) {
+   *inside = false;
+   return true;
+   }
+
+   return false;
+}
+
+static void i915_set_reset_status(struct intel_ring_buffer *ring,
+ struct drm_i915_gem_request *request,
+ u32 acthd)
+{
+   struct i915_ctx_hang_stats *hs = NULL;
+   bool inside, guilty;
+
+   /* Innocent until proven guilty */
+   guilty = false;
+
+   if (ring-hangcheck.last_action != wait 
+   i915_request_guilty(request, acthd, inside)) {
+   DRM_ERROR(%s hung %s bo (0x%x ctx %d) at 0x%x\n,
+ ring-name,
+ inside ? inside : flushing,
+ request-batch_obj ?
+ request-batch_obj-gtt_offset : 0,
+ request-ctx ? request-ctx-id : 0,
+ acthd);
+
+   guilty = true;
+   }
+
+   /* If contexts are disabled or this is the default context, use
+* file_priv-reset_state
+*/
+   if (request-ctx  request-ctx-id != DEFAULT_CONTEXT_ID)
+   hs = request-ctx-hang_stats;
+   else if (request-file_priv)
+   hs = request-file_priv-hang_stats;
+
+   if (hs) {
+   if (guilty)
+   hs-batch_active++;
+   else
+   hs-batch_pending++;
+   }
+}
+
 static void i915_gem_free_request(struct drm_i915_gem_request *request)
 {
list_del(request-list);
@@ -2117,6 +2196,12 @@ static void i915_gem_free_request(struct 
drm_i915_gem_request *request)
 static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
  struct intel_ring_buffer *ring)
 {
+   u32 completed_seqno;
+   u32 acthd;
+
+   acthd = intel_ring_get_active_head(ring);
+   completed_seqno = ring-get_seqno(ring, false);
+
while (!list_empty(ring-request_list)) {
struct drm_i915_gem_request *request;
 
@@ -2124,6 +2209,9 @@ static void i915_gem_reset_ring_lists(struct 
drm_i915_private *dev_priv,
   struct drm_i915_gem_request,
   list);
 
+   if (request-seqno  completed_seqno)
+   i915_set_reset_status(ring, request, acthd);
+
i915_gem_free_request(request);
}
 
-- 
1.7.9.5

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 1/2] drm/i915: tune the RC6 threshold for stability

2013-06-12 Thread Chris Wilson
On Tue, Jun 11, 2013 at 03:49:26PM -0700, Stéphane Marchesin wrote:
 It's basically the same deal as the RC6+ issues on ivy bridge
 except this time with RC6 on sandy bridge. Like last time the
 core of the issue is that the timings don't work 100% with our
 voltage regulator. So from time to time, the kernel will print
 a warning message about the GPU not getting out of RC6. In
 particular, I found this fairly easy to reproduce during
 suspend/resume.
 
 Changing the threshold to 15 instead of 5 seems to fix
 the issue.
 
 I also measured the idle power usage before/after this patch and
 didn't see a difference on a sandy bridge laptop.
 
 Signed-off-by: Stéphane Marchesin marc...@chromium.org

One magic number for another with no idea what is blowing up - I fear we
are just changing the frequency of the hang. I've pinged a number of snb
rc6 bug reports to see if we get a bite.

FWIW,
Acked-by: Chris Wilson ch...@chris-wilson.co.uk
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH] drm/i915: disable sdvo pixel multiplier cross-check for HAS_PCH_SPLIT

2013-06-12 Thread Daniel Vetter
We don't (yet) have proper pixel multiplier readout support on pch
split platforms, so the cross check will naturally fail.

v2: Fix spelling in the comment, spotted by Ville.

v3: Since the ordering constraint is pretty tricky between the crtc
get_pipe_config callback and the encoder-get_config callback add a
few comments about it. Prompted by a discussion with Chris Wilson on
irc about why this does work anywhere else than on i915g/gm.

Reported-by: Chris Wilson ch...@chris-wilson.co.uk
Cc: Chris Wilson ch...@chris-wilson.co.uk
Cc: Ville Syrjälä ville.syrj...@linux.intel.com
Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/intel_drv.h  |  3 ++-
 drivers/gpu/drm/i915/intel_sdvo.c | 11 +++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 3363358..cf26fa8 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -140,7 +140,8 @@ struct intel_encoder {
 * it is connected to in the pipe parameter. */
bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe);
/* Reconstructs the equivalent mode flags for the current hardware
-* state. */
+* state. This must be called _after_ display-get_pipe_config has
+* pre-filled the pipe config. */
void (*get_config)(struct intel_encoder *,
   struct intel_crtc_config *pipe_config);
int crtc_mask;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c 
b/drivers/gpu/drm/i915/intel_sdvo.c
index a6c53b6..1327fa9 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1342,6 +1342,13 @@ static void intel_sdvo_get_config(struct intel_encoder 
*encoder,
 
pipe_config-adjusted_mode.flags |= flags;
 
+   /*
+* pixel multiplier readout is tricky: Only on i915g/gm it is stored in
+* the sdvo port register, on all other platforms it is part of the dpll
+* state. Since the general pipe state readout happens before the
+* encoder-get_config we so already have a valid pixel multplier on all
+* other platfroms.
+*/
if (IS_I915G(dev) || IS_I915GM(dev)) {
sdvox = I915_READ(intel_sdvo-sdvo_reg);
pipe_config-pixel_multiplier =
@@ -1362,6 +1369,10 @@ static void intel_sdvo_get_config(struct intel_encoder 
*encoder,
encoder_pixel_multiplier = 4;
break;
}
+
+   if(HAS_PCH_SPLIT(dev))
+   return; /* no pixel multiplier readout support yet */
+
WARN(encoder_pixel_multiplier != pipe_config-pixel_multiplier,
 SDVO pixel multiplier mismatch, port: %i, encoder: %i\n,
 pipe_config-pixel_multiplier, encoder_pixel_multiplier);
-- 
1.7.11.7

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH] drm/i915: Ignore EIO whilst waiting without the lock

2013-06-12 Thread Chris Wilson
As we play games in set-to-domain in order to first perform a lockless
wait on outstanding rendering, it is possible that we report a spurious
GPU hang during that wait. After reclaiming the lock we then want to do
a more thorough test as to whether the hang is indeed fatal and what the
correct error code we should return. This naturally falls out of the
locked wait we perform as the second task in set-to-domain.

References: https://bugs.freedesktop.org/show_bug.cgi?id=65495
Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk
---
 drivers/gpu/drm/i915/i915_gem.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 773c8f4..70fe8a1 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1214,7 +1214,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void 
*data,
 * to catch cases where we are gazumped.
 */
ret = i915_gem_object_wait_rendering__nonblocking(obj, !write_domain);
-   if (ret)
+   if (ret  ret != -EIO)
goto unref;
 
if (read_domains  I915_GEM_DOMAIN_GTT) {
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 4/7] drm/i915: add batch bo to i915_add_request()

2013-06-12 Thread Chris Wilson
On Wed, Jun 12, 2013 at 12:35:31PM +0300, Mika Kuoppala wrote:
 In order to track down a batch buffer and context which
 caused the ring to hang, store reference to bo into the request struct.
 Request can also cause gpu to hang after the batch in the flush section
 in the ring. To detect this add start of the flush portion offset into the
 request.
 
 Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
 ---
 @@ -2041,8 +2043,10 @@ int __i915_add_request(struct intel_ring_buffer *ring,
  
   request-seqno = intel_ring_get_seqno(ring);
   request-ring = ring;
 + request-head = request_start;
   request-tail = request_ring_position;
   request-ctx = ring-last_context;
 + request-batch_obj = obj;

This could do with a comment explaining the lifetimes of the request vs
batch_obj, and so justifying why we do not need a reference count.

/* Whilst this request exists, batch_obj will be on the
 * active_list, and so will hold the active reference. Only when this
 * request is retired will the the batch_obj be moved onto the
 * inactive_list and lose its active reference. Hence we do not need
 * to explicitly hold another reference here.
 */
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 6/7] drm/i915: find guilty batch buffer on ring resets

2013-06-12 Thread Chris Wilson
On Wed, Jun 12, 2013 at 12:35:33PM +0300, Mika Kuoppala wrote:
 After hang check timer has declared gpu to be hang,
s/hang/hung/ :-p

 rings are reset. In ring reset, when clearing
 request list, do post mortem analysis to find out
 the guilty batch buffer.
 
 Select requests for further analysis by inspecting
 the completed sequence number which has been updated
 into the HWS page. If request was completed, it can't
 be related to the hang.
 
 For noncompleted requests mark the batch as guilty
 if the ring was not waiting and the ring head was
 stuck inside the buffer object or in the flush region
 right after the batch. For everything else, mark
 them as innocents.
 
 v2: Fixed a typo in commit message (Ville Syrjälä)
 
 Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
 ---

 +static bool i915_head_inside_request(u32 acthd, u32 rs, u32 re)
 +{

Be kind to your reader and use request_start, request_end or just start,
end.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH] drm/i915: WARN if the fence pin_count is invalid

2013-06-12 Thread Chris Wilson
Stéphane Marchesin found a bug where the fences were not being restored,
and in particular the fence pin_count was incorrect. Had we had a
warning in place, this bug would have come to light much earlier. Better
late than never?

Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk
Cc: Daniel Vetter daniel.vet...@ffwll.ch
Cc: Stéphane Marchesin marc...@chromium.org
---
 drivers/gpu/drm/i915/i915_drv.h |1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1a67216..041091d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1722,6 +1722,7 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object 
*obj)
 {
if (obj-fence_reg != I915_FENCE_REG_NONE) {
struct drm_i915_private *dev_priv = obj-base.dev-dev_private;
+   WARN_ON(dev_priv-fence_regs[obj-fence_reg].pin_count = 0);
dev_priv-fence_regs[obj-fence_reg].pin_count--;
}
 }
-- 
1.7.10.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 1/7] drm/i915: add struct i915_ctx_hang_stats

2013-06-12 Thread Chris Wilson
On Wed, Jun 12, 2013 at 12:35:28PM +0300, Mika Kuoppala wrote:
 To count context losses, add struct i915_ctx_hang_stats for
 both i915_hw_context and drm_i915_file_private.
 drm_i915_file_private is used when there is no context.
 
 v2: renamed and cleaned up the struct (Chris Wilson, Ian Romanick)
 
 Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com

Only minor bikesheds on the series, so
Reviewed-by: Chris Wilson ch...@chris-wilson.co.uk
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH] drm/i915: WARN if the fence pin_count is invalid

2013-06-12 Thread Daniel Vetter
On Wed, Jun 12, 2013 at 11:29:47AM +0100, Chris Wilson wrote:
 Stéphane Marchesin found a bug where the fences were not being restored,
 and in particular the fence pin_count was incorrect. Had we had a
 warning in place, this bug would have come to light much earlier. Better
 late than never?

Indeed. Queued for -next, thanks for the patch.
-Daniel

 
 Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk
 Cc: Daniel Vetter daniel.vet...@ffwll.ch
 Cc: Stéphane Marchesin marc...@chromium.org
 ---
  drivers/gpu/drm/i915/i915_drv.h |1 +
  1 file changed, 1 insertion(+)
 
 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
 index 1a67216..041091d 100644
 --- a/drivers/gpu/drm/i915/i915_drv.h
 +++ b/drivers/gpu/drm/i915/i915_drv.h
 @@ -1722,6 +1722,7 @@ i915_gem_object_unpin_fence(struct drm_i915_gem_object 
 *obj)
  {
   if (obj-fence_reg != I915_FENCE_REG_NONE) {
   struct drm_i915_private *dev_priv = obj-base.dev-dev_private;
 + WARN_ON(dev_priv-fence_regs[obj-fence_reg].pin_count = 0);
   dev_priv-fence_regs[obj-fence_reg].pin_count--;
   }
  }
 -- 
 1.7.10.4
 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 4/9] drm/i915: fixup g4x pll limits

2013-06-12 Thread Damien Lespiau
On Wed, Jun 12, 2013 at 09:39:54AM +0200, Daniel Vetter wrote:
 Afaik eaglelake as the desktop version of cantiga has all the same stuff
 (minus a few mobile-only power saving features). The spreadsheet I have
 here is even called eaglelake_cantiga_something.xls.

Ah right, so let's believe this spreadsheet, it's more convincing that
the pure hw limits. With that:

Reviewed-by: Damien Lespiau damien.lesp...@intel.com

-- 
Damien
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 00/24] irq locking review

2013-06-12 Thread Daniel Vetter
Hi all,

So here's my irq locking review, inspired by the VECS patches. The first part
(up to patch 14) deals mostly with display interrupts and especially
interactions between the hpd storm detection and the fifu underrun reporting.

Most of it is just unification, but there's two cases where locking wasn't
sufficient. Besides the cleanup it also reworks the fifo underrun reporting a
bit so that we also report underruns even when we can't enable the interrupt
(just in a delayed fashion). This is useful prep work for enabling fifo underrun
reporting on i9xx/vlv, since ther we don't ever have an interrupt. So only
delayed reporting is possible.

The second part streamlines the VECS-related interrupt handling. Contrary to my
claims I haven't found a real bug in there. But I still rest on my assertion
that the current code was too fragile, and the various shady comments did not
help in creating confidence, either. I've taken the oppportunity here though to
unify the interrupt enable sequence a bit, which should greatly help us in
keeping our sanity with the pc8+ patches.

I've tried to remove unecessary locking as much as possible (e.g. dropped irq
disabling wherever possible) so that the real required locking and ordering
sticks out more. One change I've considered but haven't (yet) done is to drop
the irq save/restore dance everywhere we know that spinlock nesting can't occur
(and is unlikely to ever get added). Again that would just better document that
no nasty spinlock nesting can happen (since lockdep viciously checks those
things). I'll probably do that in a follow-up series.

Comments, flames and review highly welcome.

Cheers, Daniel

Daniel Vetter (24):
  drm/i915: fix locking around ironlake_enable|disable_display_irq
  drm/i915: close tiny race in the ilk pcu even interrupt setup
  drm/i915: assert_spin_locked for pipestat interrupt enable/disable
  drm/i915: s/hotplug_irq_storm_detect/intel_hpd_irq_handler/
  drm/i915: fold the hpd_irq_setup call into intel_hpd_irq_handler
  drm/i915: fold the queue_work into intel_hpd_irq_handler
  drm/i915: fold the no-irq check into intel_hpd_irq_handler
  drm/i915: fix hpd interrupt register locking
  drm/i915: extract ibx_display_interrupt_update
  drm/i915: remove SERR_INT clearing in the postinstall hook
  drm/i915: improve SERR_INT clearing for fifo underrun reporting
  drm/i915: improve GEN7_ERR_INT clearing for fifo underrun reporting
  drm/i915: kill lpt pch transcoder-crtc mapping code for fifo
underruns
  drm/i915: irq handlers don't need interrupt-safe spinlocks
  drm/i915: streamline hsw_pm_irq_handler
  drm/i915: queue work outside spinlock in hsw_pm_irq_handler
  drm/i915: kill dev_priv-rps.lock
  drm/i915: unify ring irq refcounts (again)
  drm/i915: don't enable PM_VEBOX_CS_ERROR_INTERRUPT
  drm/i915: kill bogus GTIIR clearing in vlv_preinstall hook
  drm/i915: unify PM interrupt preinstall sequence
  drm/i915: unify GT/PM irq postinstall code
  drm/i915: extract rps interrupt enable/disable helpers
  drm/i915: simplify rps interrupt enabling/disabling sequence

 drivers/gpu/drm/i915/i915_dma.c |   1 -
 drivers/gpu/drm/i915/i915_drv.h |   8 +-
 drivers/gpu/drm/i915/i915_irq.c | 422 
 drivers/gpu/drm/i915/i915_reg.h |   2 +
 drivers/gpu/drm/i915/intel_pm.c |  65 +++--
 drivers/gpu/drm/i915/intel_ringbuffer.c |  31 ++-
 drivers/gpu/drm/i915/intel_ringbuffer.h |   5 +-
 7 files changed, 259 insertions(+), 275 deletions(-)

-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 01/24] drm/i915: fix locking around ironlake_enable|disable_display_irq

2013-06-12 Thread Daniel Vetter
The haswell unclaimed register handling code forgot to take the
spinlock. Since this is in the context of the non-rentrant interupt
handler and we only have one interrupt handler it is sufficient to
just grab the spinlock - we do not need to exclude any other
interrupts from running on the same cpu.

To prevent such gaffles in the future sprinkle assert_spin_locked over
these functions. Unfornately this requires us to hold the spinlock in
the ironlake postinstall hook where it is not strictly required:
Currently that is run in single-threaded context and with userspace
exlcuded from running concurrent ioctls. Add a comment explaining
this.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 22 --
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index c482e8a..567945f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -95,6 +95,8 @@ static void i915_hpd_irq_setup(struct drm_device *dev);
 static void
 ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
+   assert_spin_locked(dev_priv-irq_lock);
+
if ((dev_priv-irq_mask  mask) != 0) {
dev_priv-irq_mask = ~mask;
I915_WRITE(DEIMR, dev_priv-irq_mask);
@@ -105,6 +107,8 @@ ironlake_enable_display_irq(drm_i915_private_t *dev_priv, 
u32 mask)
 static void
 ironlake_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
 {
+   assert_spin_locked(dev_priv-irq_lock);
+
if ((dev_priv-irq_mask  mask) != mask) {
dev_priv-irq_mask |= mask;
I915_WRITE(DEIMR, dev_priv-irq_mask);
@@ -1218,8 +1222,11 @@ static irqreturn_t ivybridge_irq_handler(int irq, void 
*arg)
/* On Haswell, also mask ERR_INT because we don't want to risk
 * generating unclaimed register interrupts from inside the interrupt
 * handler. */
-   if (IS_HASWELL(dev))
+   if (IS_HASWELL(dev)) {
+   spin_lock(dev_priv-irq_lock);
ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
+   spin_unlock(dev_priv-irq_lock);
+   }
 
gt_iir = I915_READ(GTIIR);
if (gt_iir) {
@@ -1272,8 +1279,11 @@ static irqreturn_t ivybridge_irq_handler(int irq, void 
*arg)
ret = IRQ_HANDLED;
}
 
-   if (IS_HASWELL(dev)  ivb_can_enable_err_int(dev))
+   if (IS_HASWELL(dev)  ivb_can_enable_err_int(dev)) {
+   spin_lock(dev_priv-irq_lock);
ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
+   spin_unlock(dev_priv-irq_lock);
+   }
 
I915_WRITE(DEIER, de_ier);
POSTING_READ(DEIER);
@@ -2633,6 +2643,8 @@ static void ibx_irq_postinstall(struct drm_device *dev)
 
 static int ironlake_irq_postinstall(struct drm_device *dev)
 {
+   unsigned long irqflags;
+
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev-dev_private;
/* enable kind of interrupts always enabled */
u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT |
@@ -2671,7 +2683,13 @@ static int ironlake_irq_postinstall(struct drm_device 
*dev)
/* Clear  enable PCU event interrupts */
I915_WRITE(DEIIR, DE_PCU_EVENT);
I915_WRITE(DEIER, I915_READ(DEIER) | DE_PCU_EVENT);
+
+   /* spinlocking not required here for correctness since interrupt
+* setup is guaranteed to run in single-threaded context. But we
+* need it to make the assert_spin_locked happy. */
+   spin_lock_irqsave(dev_priv-irq_lock, irqflags);
ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT);
+   spin_unlock_irqrestore(dev_priv-irq_lock, irqflags);
}
 
return 0;
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 02/24] drm/i915: close tiny race in the ilk pcu even interrupt setup

2013-06-12 Thread Daniel Vetter
By the time we write DEIER in the postinstall hook the interrupt
handler could run any time. And it does modify DEIER to handle
interrupts.

Hence the DEIER read-modify-write cycle for enabling the PCU event
source is racy. Close this races the same way we handle vblank
interrupts: Unconditionally enable the interrupt in the IER register,
but conditionally mask it in IMR. The later poses no such race since
the interrupt handler does not touch DEIMR.

Also update the comment, the clearing has already happened
unconditionally above.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 567945f..969da20 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2658,7 +2658,8 @@ static int ironlake_irq_postinstall(struct drm_device 
*dev)
/* should always can generate irq */
I915_WRITE(DEIIR, I915_READ(DEIIR));
I915_WRITE(DEIMR, dev_priv-irq_mask);
-   I915_WRITE(DEIER, display_mask | DE_PIPEA_VBLANK | DE_PIPEB_VBLANK);
+   I915_WRITE(DEIER, display_mask |
+ DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT);
POSTING_READ(DEIER);
 
dev_priv-gt_irq_mask = ~0;
@@ -2680,11 +2681,9 @@ static int ironlake_irq_postinstall(struct drm_device 
*dev)
ibx_irq_postinstall(dev);
 
if (IS_IRONLAKE_M(dev)) {
-   /* Clear  enable PCU event interrupts */
-   I915_WRITE(DEIIR, DE_PCU_EVENT);
-   I915_WRITE(DEIER, I915_READ(DEIER) | DE_PCU_EVENT);
-
-   /* spinlocking not required here for correctness since interrupt
+   /* Clear  enable PCU event interrupts
+*
+* spinlocking not required here for correctness since interrupt
 * setup is guaranteed to run in single-threaded context. But we
 * need it to make the assert_spin_locked happy. */
spin_lock_irqsave(dev_priv-irq_lock, irqflags);
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 03/24] drm/i915: assert_spin_locked for pipestat interrupt enable/disable

2013-06-12 Thread Daniel Vetter
Just to keep the paranoia equal also sprinkle locking asserts over the
pipestat interrupt enable/disable functions.

Again this results in false positives in the interrupt setup. Add
bogo-locking for these and a big comment explaining why it's there and
that it's indeed unnecessary.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 969da20..c0b6c85 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -329,6 +329,8 @@ i915_enable_pipestat(drm_i915_private_t *dev_priv, int 
pipe, u32 mask)
u32 reg = PIPESTAT(pipe);
u32 pipestat = I915_READ(reg)  0x7fff;
 
+   assert_spin_locked(dev_priv-irq_lock);
+
if ((pipestat  mask) == mask)
return;
 
@@ -344,6 +346,8 @@ i915_disable_pipestat(drm_i915_private_t *dev_priv, int 
pipe, u32 mask)
u32 reg = PIPESTAT(pipe);
u32 pipestat = I915_READ(reg)  0x7fff;
 
+   assert_spin_locked(dev_priv-irq_lock);
+
if ((pipestat  mask) == 0)
return;
 
@@ -2681,7 +2685,7 @@ static int ironlake_irq_postinstall(struct drm_device 
*dev)
ibx_irq_postinstall(dev);
 
if (IS_IRONLAKE_M(dev)) {
-   /* Clear  enable PCU event interrupts
+   /* Enable PCU event interrupts
 *
 * spinlocking not required here for correctness since interrupt
 * setup is guaranteed to run in single-threaded context. But we
@@ -2758,6 +2762,7 @@ static int valleyview_irq_postinstall(struct drm_device 
*dev)
u32 gt_irqs;
u32 enable_mask;
u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV;
+   unsigned long irqflags;
 
enable_mask = I915_DISPLAY_PORT_INTERRUPT;
enable_mask |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
@@ -2783,9 +2788,13 @@ static int valleyview_irq_postinstall(struct drm_device 
*dev)
I915_WRITE(PIPESTAT(1), 0x);
POSTING_READ(VLV_IER);
 
+   /* Interrup setup is already guaranteed to be single-threaded, this is
+* just to make the assert_spin_locked check happy. */
+   spin_lock_irqsave(dev_priv-irq_lock, irqflags);
i915_enable_pipestat(dev_priv, 0, pipestat_enable);
i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE);
i915_enable_pipestat(dev_priv, 1, pipestat_enable);
+   spin_unlock_irqrestore(dev_priv-irq_lock, irqflags);
 
I915_WRITE(VLV_IIR, 0x);
I915_WRITE(VLV_IIR, 0x);
@@ -3267,6 +3276,7 @@ static int i965_irq_postinstall(struct drm_device *dev)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev-dev_private;
u32 enable_mask;
u32 error_mask;
+   unsigned long irqflags;
 
/* Unmask the interrupts that we always want on. */
dev_priv-irq_mask = ~(I915_ASLE_INTERRUPT |
@@ -3285,7 +3295,11 @@ static int i965_irq_postinstall(struct drm_device *dev)
if (IS_G4X(dev))
enable_mask |= I915_BSD_USER_INTERRUPT;
 
+   /* Interrup setup is already guaranteed to be single-threaded, this is
+* just to make the assert_spin_locked check happy. */
+   spin_lock_irqsave(dev_priv-irq_lock, irqflags);
i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE);
+   spin_unlock_irqrestore(dev_priv-irq_lock, irqflags);
 
/*
 * Enable some error detection, note the instruction error mask
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 05/24] drm/i915: fold the hpd_irq_setup call into intel_hpd_irq_handler

2013-06-12 Thread Daniel Vetter
We already have a vfunc for this (and other parts of the hpd storm
handling code already use it).

Cc: Egbert Eich e...@suse.de
Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 29 +++--
 1 file changed, 11 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index ab3368e..1f8d914 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -88,9 +88,6 @@ static const u32 hpd_status_i915[] = { /* i915 and valleyview 
are the same */
[HPD_PORT_D] = PORTD_HOTPLUG_INT_STATUS
 };
 
-static void ibx_hpd_irq_setup(struct drm_device *dev);
-static void i915_hpd_irq_setup(struct drm_device *dev);
-
 /* For display hotplug interrupt */
 static void
 ironlake_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
@@ -878,14 +875,14 @@ static void gen6_queue_rps_work(struct drm_i915_private 
*dev_priv,
 #define HPD_STORM_DETECT_PERIOD 1000
 #define HPD_STORM_THRESHOLD 5
 
-static inline bool intel_hpd_irq_handler(struct drm_device *dev,
+static inline void intel_hpd_irq_handler(struct drm_device *dev,
 u32 hotplug_trigger,
 const u32 *hpd)
 {
drm_i915_private_t *dev_priv = dev-dev_private;
unsigned long irqflags;
int i;
-   bool ret = false;
+   bool storm_detected = false;
 
spin_lock_irqsave(dev_priv-irq_lock, irqflags);
 
@@ -905,7 +902,7 @@ static inline bool intel_hpd_irq_handler(struct drm_device 
*dev,
dev_priv-hpd_stats[i].hpd_mark = HPD_MARK_DISABLED;
dev_priv-hpd_event_bits = ~(1  i);
DRM_DEBUG_KMS(HPD interrupt storm detected on PIN 
%d\n, i);
-   ret = true;
+   storm_detected = true;
} else {
dev_priv-hpd_stats[i].hpd_cnt++;
}
@@ -913,7 +910,8 @@ static inline bool intel_hpd_irq_handler(struct drm_device 
*dev,
 
spin_unlock_irqrestore(dev_priv-irq_lock, irqflags);
 
-   return ret;
+   if (storm_detected)
+   dev_priv-display.hpd_irq_setup(dev);
 }
 
 static void gmbus_irq_handler(struct drm_device *dev)
@@ -1021,8 +1019,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void 
*arg)
DRM_DEBUG_DRIVER(hotplug event received, stat 
0x%08x\n,
 hotplug_status);
if (hotplug_trigger) {
-   if (intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915))
-   i915_hpd_irq_setup(dev);
+   intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915);
queue_work(dev_priv-wq,
   dev_priv-hotplug_work);
}
@@ -1052,8 +1049,7 @@ static void ibx_irq_handler(struct drm_device *dev, u32 
pch_iir)
u32 hotplug_trigger = pch_iir  SDE_HOTPLUG_MASK;
 
if (hotplug_trigger) {
-   if (intel_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx))
-   ibx_hpd_irq_setup(dev);
+   intel_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx);
queue_work(dev_priv-wq, dev_priv-hotplug_work);
}
if (pch_iir  SDE_AUDIO_POWER_MASK) {
@@ -1157,8 +1153,7 @@ static void cpt_irq_handler(struct drm_device *dev, u32 
pch_iir)
u32 hotplug_trigger = pch_iir  SDE_HOTPLUG_MASK_CPT;
 
if (hotplug_trigger) {
-   if (intel_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt))
-   ibx_hpd_irq_setup(dev);
+   intel_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt);
queue_work(dev_priv-wq, dev_priv-hotplug_work);
}
if (pch_iir  SDE_AUDIO_POWER_MASK_CPT) {
@@ -3174,8 +3169,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
DRM_DEBUG_DRIVER(hotplug event received, stat 
0x%08x\n,
  hotplug_status);
if (hotplug_trigger) {
-   if (intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915))
-   i915_hpd_irq_setup(dev);
+   intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915);
queue_work(dev_priv-wq,
   dev_priv-hotplug_work);
}
@@ -3420,9 +3414,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
DRM_DEBUG_DRIVER(hotplug event received, stat 
0x%08x\n,
  hotplug_status);
if (hotplug_trigger) {
-   if (intel_hpd_irq_handler(dev, hotplug_trigger,
-   

[Intel-gfx] [PATCH 06/24] drm/i915: fold the queue_work into intel_hpd_irq_handler

2013-06-12 Thread Daniel Vetter
Everywhere the same.

Cc: Egbert Eich e...@suse.de
Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 11 +++
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 1f8d914..38bb26f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -912,6 +912,9 @@ static inline void intel_hpd_irq_handler(struct drm_device 
*dev,
 
if (storm_detected)
dev_priv-display.hpd_irq_setup(dev);
+
+   queue_work(dev_priv-wq,
+  dev_priv-hotplug_work);
 }
 
 static void gmbus_irq_handler(struct drm_device *dev)
@@ -1020,8 +1023,6 @@ static irqreturn_t valleyview_irq_handler(int irq, void 
*arg)
 hotplug_status);
if (hotplug_trigger) {
intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915);
-   queue_work(dev_priv-wq,
-  dev_priv-hotplug_work);
}
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT);
@@ -1050,7 +1051,6 @@ static void ibx_irq_handler(struct drm_device *dev, u32 
pch_iir)
 
if (hotplug_trigger) {
intel_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx);
-   queue_work(dev_priv-wq, dev_priv-hotplug_work);
}
if (pch_iir  SDE_AUDIO_POWER_MASK) {
int port = ffs((pch_iir  SDE_AUDIO_POWER_MASK) 
@@ -1154,7 +1154,6 @@ static void cpt_irq_handler(struct drm_device *dev, u32 
pch_iir)
 
if (hotplug_trigger) {
intel_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt);
-   queue_work(dev_priv-wq, dev_priv-hotplug_work);
}
if (pch_iir  SDE_AUDIO_POWER_MASK_CPT) {
int port = ffs((pch_iir  SDE_AUDIO_POWER_MASK_CPT) 
@@ -3170,8 +3169,6 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
  hotplug_status);
if (hotplug_trigger) {
intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915);
-   queue_work(dev_priv-wq,
-  dev_priv-hotplug_work);
}
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
POSTING_READ(PORT_HOTPLUG_STAT);
@@ -3416,8 +3413,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
if (hotplug_trigger) {
intel_hpd_irq_handler(dev, hotplug_trigger,
  IS_G4X(dev) ? 
hpd_status_gen4 : hpd_status_i965);
-   queue_work(dev_priv-wq,
-  dev_priv-hotplug_work);
}
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT);
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 04/24] drm/i915: s/hotplug_irq_storm_detect/intel_hpd_irq_handler/

2013-06-12 Thread Daniel Vetter
The combination of Paulo's fifo underrun detection code and Egbert's
hpd storm handling code unfortunately made the hpd storm handling code
racy.

To avoid duplicating tricky interrupt locking code over all platforms
start with a bit of refactoring. This patch is the very first step
since in the end the irq storm handling code will handle all hotplug
logic (and so also encapsulate the locking nicely).

Cc: Egbert Eich e...@suse.de
Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index c0b6c85..ab3368e 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -878,9 +878,9 @@ static void gen6_queue_rps_work(struct drm_i915_private 
*dev_priv,
 #define HPD_STORM_DETECT_PERIOD 1000
 #define HPD_STORM_THRESHOLD 5
 
-static inline bool hotplug_irq_storm_detect(struct drm_device *dev,
-   u32 hotplug_trigger,
-   const u32 *hpd)
+static inline bool intel_hpd_irq_handler(struct drm_device *dev,
+u32 hotplug_trigger,
+const u32 *hpd)
 {
drm_i915_private_t *dev_priv = dev-dev_private;
unsigned long irqflags;
@@ -1021,7 +1021,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void 
*arg)
DRM_DEBUG_DRIVER(hotplug event received, stat 
0x%08x\n,
 hotplug_status);
if (hotplug_trigger) {
-   if (hotplug_irq_storm_detect(dev, 
hotplug_trigger, hpd_status_i915))
+   if (intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915))
i915_hpd_irq_setup(dev);
queue_work(dev_priv-wq,
   dev_priv-hotplug_work);
@@ -1052,7 +1052,7 @@ static void ibx_irq_handler(struct drm_device *dev, u32 
pch_iir)
u32 hotplug_trigger = pch_iir  SDE_HOTPLUG_MASK;
 
if (hotplug_trigger) {
-   if (hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_ibx))
+   if (intel_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx))
ibx_hpd_irq_setup(dev);
queue_work(dev_priv-wq, dev_priv-hotplug_work);
}
@@ -1157,7 +1157,7 @@ static void cpt_irq_handler(struct drm_device *dev, u32 
pch_iir)
u32 hotplug_trigger = pch_iir  SDE_HOTPLUG_MASK_CPT;
 
if (hotplug_trigger) {
-   if (hotplug_irq_storm_detect(dev, hotplug_trigger, hpd_cpt))
+   if (intel_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt))
ibx_hpd_irq_setup(dev);
queue_work(dev_priv-wq, dev_priv-hotplug_work);
}
@@ -3174,7 +3174,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
DRM_DEBUG_DRIVER(hotplug event received, stat 
0x%08x\n,
  hotplug_status);
if (hotplug_trigger) {
-   if (hotplug_irq_storm_detect(dev, 
hotplug_trigger, hpd_status_i915))
+   if (intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915))
i915_hpd_irq_setup(dev);
queue_work(dev_priv-wq,
   dev_priv-hotplug_work);
@@ -3420,7 +3420,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
DRM_DEBUG_DRIVER(hotplug event received, stat 
0x%08x\n,
  hotplug_status);
if (hotplug_trigger) {
-   if (hotplug_irq_storm_detect(dev, 
hotplug_trigger,
+   if (intel_hpd_irq_handler(dev, hotplug_trigger,
IS_G4X(dev) ? 
hpd_status_gen4 : hpd_status_i965))
i915_hpd_irq_setup(dev);
queue_work(dev_priv-wq,
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 07/24] drm/i915: fold the no-irq check into intel_hpd_irq_handler

2013-06-12 Thread Daniel Vetter
The usual pattern for our sub-function irq_handlers is that they check
for the no-irq case themselves. This results in more streamlined code
in the upper irq handlers.

Cc: Egbert Eich e...@suse.de
Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 33 +
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 38bb26f..1815891 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -884,6 +884,9 @@ static inline void intel_hpd_irq_handler(struct drm_device 
*dev,
int i;
bool storm_detected = false;
 
+   if (!hotplug_trigger)
+   return;
+
spin_lock_irqsave(dev_priv-irq_lock, irqflags);
 
for (i = 1; i  HPD_NUM_PINS; i++) {
@@ -1021,9 +1024,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void 
*arg)
 
DRM_DEBUG_DRIVER(hotplug event received, stat 
0x%08x\n,
 hotplug_status);
-   if (hotplug_trigger) {
-   intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915);
-   }
+
+   intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915);
+
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT);
}
@@ -1049,9 +1052,8 @@ static void ibx_irq_handler(struct drm_device *dev, u32 
pch_iir)
int pipe;
u32 hotplug_trigger = pch_iir  SDE_HOTPLUG_MASK;
 
-   if (hotplug_trigger) {
-   intel_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx);
-   }
+   intel_hpd_irq_handler(dev, hotplug_trigger, hpd_ibx);
+
if (pch_iir  SDE_AUDIO_POWER_MASK) {
int port = ffs((pch_iir  SDE_AUDIO_POWER_MASK) 
   SDE_AUDIO_POWER_SHIFT);
@@ -1152,9 +1154,8 @@ static void cpt_irq_handler(struct drm_device *dev, u32 
pch_iir)
int pipe;
u32 hotplug_trigger = pch_iir  SDE_HOTPLUG_MASK_CPT;
 
-   if (hotplug_trigger) {
-   intel_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt);
-   }
+   intel_hpd_irq_handler(dev, hotplug_trigger, hpd_cpt);
+
if (pch_iir  SDE_AUDIO_POWER_MASK_CPT) {
int port = ffs((pch_iir  SDE_AUDIO_POWER_MASK_CPT) 
   SDE_AUDIO_POWER_SHIFT_CPT);
@@ -3167,9 +3168,9 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
 
DRM_DEBUG_DRIVER(hotplug event received, stat 
0x%08x\n,
  hotplug_status);
-   if (hotplug_trigger) {
-   intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915);
-   }
+
+   intel_hpd_irq_handler(dev, hotplug_trigger, 
hpd_status_i915);
+
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
POSTING_READ(PORT_HOTPLUG_STAT);
}
@@ -3410,10 +3411,10 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
 
DRM_DEBUG_DRIVER(hotplug event received, stat 
0x%08x\n,
  hotplug_status);
-   if (hotplug_trigger) {
-   intel_hpd_irq_handler(dev, hotplug_trigger,
- IS_G4X(dev) ? 
hpd_status_gen4 : hpd_status_i965);
-   }
+
+   intel_hpd_irq_handler(dev, hotplug_trigger,
+ IS_G4X(dev) ? hpd_status_gen4 : 
hpd_status_i965);
+
I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status);
I915_READ(PORT_HOTPLUG_STAT);
}
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 08/24] drm/i915: fix hpd interrupt register locking

2013-06-12 Thread Daniel Vetter
Our interrupt handler (in hardird context) could race with the timer
(in softirq context), hence we need to hold the spinlock around the
call to -hdp_irq_setup in intel_hpd_irq_handler, too.

But as an optimization (and more so to clarify things) we don't need
to do the irqsave/restore dance in the hardirq context.

Note also that on ilk+ the race isn't just against the hotplug
reenable timer, but also against the fifo underrun reporting. That one
also modifies the SDEIMR register (again protected by the same
dev_priv-irq_lock).

To lock things down again sprinkle a assert_spin_locked. But exclude
the functions touching SDEIMR for now, I want to extract them all into
a new helper function (like we do already for pipestate, display
interrupts and all the various gt interrupts).

Cc: Egbert Eich e...@suse.de
Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 1815891..95e15cd 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -880,15 +880,13 @@ static inline void intel_hpd_irq_handler(struct 
drm_device *dev,
 const u32 *hpd)
 {
drm_i915_private_t *dev_priv = dev-dev_private;
-   unsigned long irqflags;
int i;
bool storm_detected = false;
 
if (!hotplug_trigger)
return;
 
-   spin_lock_irqsave(dev_priv-irq_lock, irqflags);
-
+   spin_lock(dev_priv-irq_lock);
for (i = 1; i  HPD_NUM_PINS; i++) {
 
if (!(hpd[i]  hotplug_trigger) ||
@@ -911,10 +909,9 @@ static inline void intel_hpd_irq_handler(struct drm_device 
*dev,
}
}
 
-   spin_unlock_irqrestore(dev_priv-irq_lock, irqflags);
-
if (storm_detected)
dev_priv-display.hpd_irq_setup(dev);
+   spin_unlock(dev_priv-irq_lock);
 
queue_work(dev_priv-wq,
   dev_priv-hotplug_work);
@@ -3327,6 +3324,8 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
struct intel_encoder *intel_encoder;
u32 hotplug_en;
 
+   assert_spin_locked(dev_priv-irq_lock);
+
if (I915_HAS_HOTPLUG(dev)) {
hotplug_en = I915_READ(PORT_HOTPLUG_EN);
hotplug_en = ~HOTPLUG_INT_EN_MASK;
@@ -3610,6 +3609,7 @@ void intel_hpd_init(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev-dev_private;
struct drm_mode_config *mode_config = dev-mode_config;
struct drm_connector *connector;
+   unsigned long irqflags;
int i;
 
for (i = 1; i  HPD_NUM_PINS; i++) {
@@ -3622,6 +3622,11 @@ void intel_hpd_init(struct drm_device *dev)
if (!connector-polled  I915_HAS_HOTPLUG(dev)  
intel_connector-encoder-hpd_pin  HPD_NONE)
connector-polled = DRM_CONNECTOR_POLL_HPD;
}
+
+   /* Interrup setup is already guaranteed to be single-threaded, this is
+* just to make the assert_spin_locked checks happy. */
+   spin_lock_irqsave(dev_priv-irq_lock, irqflags);
if (dev_priv-display.hpd_irq_setup)
dev_priv-display.hpd_irq_setup(dev);
+   spin_unlock_irqrestore(dev_priv-irq_lock, irqflags);
 }
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 10/24] drm/i915: remove SERR_INT clearing in the postinstall hook

2013-06-12 Thread Daniel Vetter
The preinstallhook is supposed to clear all interrupts. Doing it
again in the postinstall hook has the risk that we're eating
an interrupt source from the handler. If that happens too often,
the kernel will disable our interrupt handler.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index c2b4b09..685ad84 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2635,8 +2635,6 @@ static void ibx_irq_postinstall(struct drm_device *dev)
   SDE_TRANSA_FIFO_UNDER | SDE_POISON;
} else {
mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT | SDE_ERROR_CPT;
-
-   I915_WRITE(SERR_INT, I915_READ(SERR_INT));
}
 
I915_WRITE(SDEIIR, I915_READ(SDEIIR));
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 09/24] drm/i915: extract ibx_display_interrupt_update

2013-06-12 Thread Daniel Vetter
This way all changes to SDEIMR all go through the same function, with
the exception of the (single-threaded) setup/teardown code.

For paranoia again add an assert_spin_locked.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 42 +++--
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 95e15cd..c2b4b09 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -177,6 +177,20 @@ static void ivybridge_set_fifo_underrun_reporting(struct 
drm_device *dev,
}
 }
 
+static void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
+uint32_t interrupt_mask,
+uint32_t enabled_irq_mask)
+{
+   uint32_t sdeimr = I915_READ(SDEIMR);
+   sdeimr = ~interrupt_mask;
+   sdeimr |= ~enabled_irq_mask;
+
+   assert_spin_locked(dev_priv-irq_lock);
+
+   I915_WRITE(SDEIMR, sdeimr);
+   POSTING_READ(SDEIMR);
+}
+
 static void ibx_set_fifo_underrun_reporting(struct intel_crtc *crtc,
bool enable)
 {
@@ -185,12 +199,8 @@ static void ibx_set_fifo_underrun_reporting(struct 
intel_crtc *crtc,
uint32_t bit = (crtc-pipe == PIPE_A) ? SDE_TRANSA_FIFO_UNDER :
SDE_TRANSB_FIFO_UNDER;
 
-   if (enable)
-   I915_WRITE(SDEIMR, I915_READ(SDEIMR)  ~bit);
-   else
-   I915_WRITE(SDEIMR, I915_READ(SDEIMR) | bit);
-
-   POSTING_READ(SDEIMR);
+   ibx_display_interrupt_update(dev_priv, bit,
+enable ? bit : 0);
 }
 
 static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
@@ -206,13 +216,10 @@ static void cpt_set_fifo_underrun_reporting(struct 
drm_device *dev,
I915_WRITE(SERR_INT, SERR_INT_TRANS_A_FIFO_UNDERRUN |
 SERR_INT_TRANS_B_FIFO_UNDERRUN |
 SERR_INT_TRANS_C_FIFO_UNDERRUN);
-
-   I915_WRITE(SDEIMR, I915_READ(SDEIMR)  ~SDE_ERROR_CPT);
-   } else {
-   I915_WRITE(SDEIMR, I915_READ(SDEIMR) | SDE_ERROR_CPT);
}
 
-   POSTING_READ(SDEIMR);
+   ibx_display_interrupt_update(dev_priv, SDE_ERROR_CPT,
+enable ? SDE_ERROR_CPT : 0);
 }
 
 /**
@@ -2585,22 +2592,21 @@ static void ibx_hpd_irq_setup(struct drm_device *dev)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev-dev_private;
struct drm_mode_config *mode_config = dev-mode_config;
struct intel_encoder *intel_encoder;
-   u32 mask = ~I915_READ(SDEIMR);
-   u32 hotplug;
+   u32 hotplug_irqs, hotplug, enabled_irqs = 0;
 
if (HAS_PCH_IBX(dev)) {
-   mask = ~SDE_HOTPLUG_MASK;
+   hotplug_irqs = SDE_HOTPLUG_MASK;
list_for_each_entry(intel_encoder, mode_config-encoder_list, 
base.head)
if 
(dev_priv-hpd_stats[intel_encoder-hpd_pin].hpd_mark == HPD_ENABLED)
-   mask |= hpd_ibx[intel_encoder-hpd_pin];
+   enabled_irqs |= hpd_ibx[intel_encoder-hpd_pin];
} else {
-   mask = ~SDE_HOTPLUG_MASK_CPT;
+   hotplug_irqs = SDE_HOTPLUG_MASK_CPT;
list_for_each_entry(intel_encoder, mode_config-encoder_list, 
base.head)
if 
(dev_priv-hpd_stats[intel_encoder-hpd_pin].hpd_mark == HPD_ENABLED)
-   mask |= hpd_cpt[intel_encoder-hpd_pin];
+   enabled_irqs |= hpd_cpt[intel_encoder-hpd_pin];
}
 
-   I915_WRITE(SDEIMR, ~mask);
+   ibx_display_interrupt_update(dev_priv, hotplug_irqs, enabled_irqs);
 
/*
 * Enable digital hotplug on the PCH, and configure the DP short pulse
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 12/24] drm/i915: improve GEN7_ERR_INT clearing for fifo underrun reporting

2013-06-12 Thread Daniel Vetter
Same treatment as for SERR_INT: If we clear only the bit for the pipe
we're enabling (but unconditionally) then we can always check for
possible underruns after having disabled the interrupt. That way pipe
underruns won't be lost, but at worst only get reported in a delayed
fashion.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 14 --
 drivers/gpu/drm/i915/i915_reg.h |  1 +
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 8627043..bb26555 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -159,21 +159,23 @@ static void ironlake_set_fifo_underrun_reporting(struct 
drm_device *dev,
 }
 
 static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
- bool enable)
+ enum pipe pipe, bool enable)
 {
struct drm_i915_private *dev_priv = dev-dev_private;
 
if (enable) {
+   I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
+
if (!ivb_can_enable_err_int(dev))
return;
 
-   I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN_A |
-ERR_INT_FIFO_UNDERRUN_B |
-ERR_INT_FIFO_UNDERRUN_C);
-
ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
} else {
ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
+
+   if (I915_READ(GEN7_ERR_INT)  ERR_INT_FIFO_UNDERRUN(pipe))
+   DRM_DEBUG_KMS(uncleared fifo underrun on pipe %i\n,
+ pipe);
}
 }
 
@@ -264,7 +266,7 @@ bool intel_set_cpu_fifo_underrun_reporting(struct 
drm_device *dev,
if (IS_GEN5(dev) || IS_GEN6(dev))
ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
else if (IS_GEN7(dev))
-   ivybridge_set_fifo_underrun_reporting(dev, enable);
+   ivybridge_set_fifo_underrun_reporting(dev, pipe, enable);
 
 done:
spin_unlock_irqrestore(dev_priv-irq_lock, flags);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 86e3987..ec71b35 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -680,6 +680,7 @@
 #define   ERR_INT_FIFO_UNDERRUN_C  (16)
 #define   ERR_INT_FIFO_UNDERRUN_B  (13)
 #define   ERR_INT_FIFO_UNDERRUN_A  (10)
+#define   ERR_INT_FIFO_UNDERRUN(pipe)  (1 (pipe*3))
 
 #define FPGA_DBG   0x42300
 #define   FPGA_DBG_RM_NOCLAIM  (131)
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 11/24] drm/i915: improve SERR_INT clearing for fifo underrun reporting

2013-06-12 Thread Daniel Vetter
The current code won't report any fifo underruns on cpt if just one
pipe has fifo underrun reporting disabled. We can't enable the
interrupts, but we can still check the per-transcoder bits and so
report the underrun delayed if:
- We always clear the transcoder's bit (and none of the other bits)
  when enabling.
- We check the transcoder's bit after disabling (to avoid racing with
  the interrupt handler).

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 15 +++
 drivers/gpu/drm/i915/i915_reg.h |  1 +
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 685ad84..8627043 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -210,16 +210,23 @@ static void cpt_set_fifo_underrun_reporting(struct 
drm_device *dev,
struct drm_i915_private *dev_priv = dev-dev_private;
 
if (enable) {
+   I915_WRITE(SERR_INT,
+  SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
+
if (!cpt_can_enable_serr_int(dev))
return;
-
-   I915_WRITE(SERR_INT, SERR_INT_TRANS_A_FIFO_UNDERRUN |
-SERR_INT_TRANS_B_FIFO_UNDERRUN |
-SERR_INT_TRANS_C_FIFO_UNDERRUN);
}
 
ibx_display_interrupt_update(dev_priv, SDE_ERROR_CPT,
 enable ? SDE_ERROR_CPT : 0);
+
+   if (!enable) {
+   uint32_t tmp = I915_READ(SERR_INT);
+
+   if (tmp  SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder))
+   DRM_DEBUG_KMS(uncleared pch fifo underrun on pipe 
%i\n,
+ pch_transcoder);
+   }
 }
 
 /**
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index b1fdca9..86e3987 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -3880,6 +3880,7 @@
 #define  SERR_INT_TRANS_C_FIFO_UNDERRUN(16)
 #define  SERR_INT_TRANS_B_FIFO_UNDERRUN(13)
 #define  SERR_INT_TRANS_A_FIFO_UNDERRUN(10)
+#define  SERR_INT_TRANS_FIFO_UNDERRUN(pipe)(1 (pipe*3))
 
 /* digital port hotplug */
 #define PCH_PORT_HOTPLUG0xc4030/* SHOTPLUG_CTL */
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 13/24] drm/i915: kill lpt pch transcoder-crtc mapping code for fifo underruns

2013-06-12 Thread Daniel Vetter
It's racy: There's no guarantee that we won't walk this code (due to a
pch fifo underrun interrupt) while someone is changing the pointers
around.

The only reason we do this is to use the righ crtc for the pch fifo
underrun accounting. But we never expose this to userspace, so
essentially no one really cares if we use the wrong crtc.

So let's just rip it out.

With this patch fifo underrun code will always use crtc A for tracking
underruns on the (only) pch transcoder on LPT.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 33 +++--
 1 file changed, 7 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index bb26555..b98ea4e 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -193,13 +193,13 @@ static void ibx_display_interrupt_update(struct 
drm_i915_private *dev_priv,
POSTING_READ(SDEIMR);
 }
 
-static void ibx_set_fifo_underrun_reporting(struct intel_crtc *crtc,
+static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
+   enum transcoder pch_transcoder,
bool enable)
 {
-   struct drm_device *dev = crtc-base.dev;
struct drm_i915_private *dev_priv = dev-dev_private;
-   uint32_t bit = (crtc-pipe == PIPE_A) ? SDE_TRANSA_FIFO_UNDER :
-   SDE_TRANSB_FIFO_UNDER;
+   uint32_t bit = (pch_transcoder == TRANSCODER_A) ?
+  SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
 
ibx_display_interrupt_update(dev_priv, bit,
 enable ? bit : 0);
@@ -292,30 +292,11 @@ bool intel_set_pch_fifo_underrun_reporting(struct 
drm_device *dev,
   bool enable)
 {
struct drm_i915_private *dev_priv = dev-dev_private;
-   enum pipe p;
-   struct drm_crtc *crtc;
-   struct intel_crtc *intel_crtc;
+   struct drm_crtc *crtc = dev_priv-pipe_to_crtc_mapping[pch_transcoder];
+   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
unsigned long flags;
bool ret;
 
-   if (HAS_PCH_LPT(dev)) {
-   crtc = NULL;
-   for_each_pipe(p) {
-   struct drm_crtc *c = dev_priv-pipe_to_crtc_mapping[p];
-   if (intel_pipe_has_type(c, INTEL_OUTPUT_ANALOG)) {
-   crtc = c;
-   break;
-   }
-   }
-   if (!crtc) {
-   DRM_ERROR(PCH FIFO underrun, but no CRTC using the PCH 
found\n);
-   return false;
-   }
-   } else {
-   crtc = dev_priv-pipe_to_crtc_mapping[pch_transcoder];
-   }
-   intel_crtc = to_intel_crtc(crtc);
-
spin_lock_irqsave(dev_priv-irq_lock, flags);
 
ret = !intel_crtc-pch_fifo_underrun_disabled;
@@ -326,7 +307,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct 
drm_device *dev,
intel_crtc-pch_fifo_underrun_disabled = !enable;
 
if (HAS_PCH_IBX(dev))
-   ibx_set_fifo_underrun_reporting(intel_crtc, enable);
+   ibx_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
else
cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
 
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 14/24] drm/i915: irq handlers don't need interrupt-safe spinlocks

2013-06-12 Thread Daniel Vetter
Since we only have one interrupt handler and interrupt handlers are
non-reentrant.

To drive the point really home give them all an _irq_handler suffix.

This is a tiny micro-optimization but even more important it makes it
clearer what locking we actually need. And in case someone screws this
up: lockdep will catch hardirq vs. other context deadlocks.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 40 +---
 1 file changed, 17 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index b98ea4e..8bba0c5 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -633,14 +633,13 @@ static void i915_hotplug_work_func(struct work_struct 
*work)
drm_kms_helper_hotplug_event(dev);
 }
 
-static void ironlake_handle_rps_change(struct drm_device *dev)
+static void ironlake_rps_change_irq_handler(struct drm_device *dev)
 {
drm_i915_private_t *dev_priv = dev-dev_private;
u32 busy_up, busy_down, max_avg, min_avg;
u8 new_delay;
-   unsigned long flags;
 
-   spin_lock_irqsave(mchdev_lock, flags);
+   spin_lock(mchdev_lock);
 
I915_WRITE16(MEMINTRSTS, I915_READ(MEMINTRSTS));
 
@@ -668,7 +667,7 @@ static void ironlake_handle_rps_change(struct drm_device 
*dev)
if (ironlake_set_drps(dev, new_delay))
dev_priv-ips.cur_delay = new_delay;
 
-   spin_unlock_irqrestore(mchdev_lock, flags);
+   spin_unlock(mchdev_lock);
 
return;
 }
@@ -804,18 +803,17 @@ static void ivybridge_parity_work(struct work_struct 
*work)
kfree(parity_event[1]);
 }
 
-static void ivybridge_handle_parity_error(struct drm_device *dev)
+static void ivybridge_parity_error_irq_handler(struct drm_device *dev)
 {
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev-dev_private;
-   unsigned long flags;
 
if (!HAS_L3_GPU_CACHE(dev))
return;
 
-   spin_lock_irqsave(dev_priv-irq_lock, flags);
+   spin_lock(dev_priv-irq_lock);
dev_priv-gt_irq_mask |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
I915_WRITE(GTIMR, dev_priv-gt_irq_mask);
-   spin_unlock_irqrestore(dev_priv-irq_lock, flags);
+   spin_unlock(dev_priv-irq_lock);
 
queue_work(dev_priv-wq, dev_priv-l3_parity.error_work);
 }
@@ -845,11 +843,9 @@ static void snb_gt_irq_handler(struct drm_device *dev,
 }
 
 /* Legacy way of handling PM interrupts */
-static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,
-   u32 pm_iir)
+static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv,
+u32 pm_iir)
 {
-   unsigned long flags;
-
/*
 * IIR bits should never already be set because IMR should
 * prevent an interrupt from being shown in IIR. The warning
@@ -860,11 +856,11 @@ static void gen6_queue_rps_work(struct drm_i915_private 
*dev_priv,
 * The mask bit in IMR is cleared by dev_priv-rps.work.
 */
 
-   spin_lock_irqsave(dev_priv-rps.lock, flags);
+   spin_lock(dev_priv-rps.lock);
dev_priv-rps.pm_iir |= pm_iir;
I915_WRITE(GEN6_PMIMR, dev_priv-rps.pm_iir);
POSTING_READ(GEN6_PMIMR);
-   spin_unlock_irqrestore(dev_priv-rps.lock, flags);
+   spin_unlock(dev_priv-rps.lock);
 
queue_work(dev_priv-wq, dev_priv-rps.work);
 }
@@ -928,7 +924,7 @@ static void dp_aux_irq_handler(struct drm_device *dev)
wake_up_all(dev_priv-gmbus_wait_queue);
 }
 
-/* Unlike gen6_queue_rps_work() from which this function is originally derived,
+/* Unlike gen6_rps_irq_handler() from which this function is originally 
derived,
  * we must be able to deal with other PM interrupts. This is complicated 
because
  * of the way in which we use the masks to defer the RPS work (which for
  * posterity is necessary because of forcewake).
@@ -936,9 +932,7 @@ static void dp_aux_irq_handler(struct drm_device *dev)
 static void hsw_pm_irq_handler(struct drm_i915_private *dev_priv,
   u32 pm_iir)
 {
-   unsigned long flags;
-
-   spin_lock_irqsave(dev_priv-rps.lock, flags);
+   spin_lock(dev_priv-rps.lock);
dev_priv-rps.pm_iir |= pm_iir  GEN6_PM_RPS_EVENTS;
if (dev_priv-rps.pm_iir) {
I915_WRITE(GEN6_PMIMR, dev_priv-rps.pm_iir);
@@ -947,7 +941,7 @@ static void hsw_pm_irq_handler(struct drm_i915_private 
*dev_priv,
/* TODO: if queue_work is slow, move it out of the spinlock */
queue_work(dev_priv-wq, dev_priv-rps.work);
}
-   spin_unlock_irqrestore(dev_priv-rps.lock, flags);
+   spin_unlock(dev_priv-rps.lock);
 
if (pm_iir  ~GEN6_PM_RPS_EVENTS) {
if (pm_iir  PM_VEBOX_USER_INTERRUPT)
@@ -1029,7 +1023,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void 
*arg)

[Intel-gfx] [PATCH 15/24] drm/i915: streamline hsw_pm_irq_handler

2013-06-12 Thread Daniel Vetter
The if (pm_iir  ~GEN6_PM_RPS_EVENTS) check was redunandant. Otoh
adding a check for rps events allows us to avoid the spinlock grabbing
for VECS interrupts.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 22 ++
 1 file changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 8bba0c5..29d4c9f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -839,7 +839,7 @@ static void snb_gt_irq_handler(struct drm_device *dev,
}
 
if (gt_iir  GT_RENDER_L3_PARITY_ERROR_INTERRUPT)
-   ivybridge_handle_parity_error(dev);
+   ivybridge_parity_error_irq_handler(dev);
 }
 
 /* Legacy way of handling PM interrupts */
@@ -932,25 +932,23 @@ static void dp_aux_irq_handler(struct drm_device *dev)
 static void hsw_pm_irq_handler(struct drm_i915_private *dev_priv,
   u32 pm_iir)
 {
-   spin_lock(dev_priv-rps.lock);
-   dev_priv-rps.pm_iir |= pm_iir  GEN6_PM_RPS_EVENTS;
-   if (dev_priv-rps.pm_iir) {
+   if (pm_iir  GEN6_PM_RPS_EVENTS) {
+   spin_lock(dev_priv-rps.lock);
+   dev_priv-rps.pm_iir |= pm_iir  GEN6_PM_RPS_EVENTS;
I915_WRITE(GEN6_PMIMR, dev_priv-rps.pm_iir);
/* never want to mask useful interrupts. (also posting read) */
WARN_ON(I915_READ_NOTRACE(GEN6_PMIMR)  ~GEN6_PM_RPS_EVENTS);
/* TODO: if queue_work is slow, move it out of the spinlock */
queue_work(dev_priv-wq, dev_priv-rps.work);
+   spin_unlock(dev_priv-rps.lock);
}
-   spin_unlock(dev_priv-rps.lock);
 
-   if (pm_iir  ~GEN6_PM_RPS_EVENTS) {
-   if (pm_iir  PM_VEBOX_USER_INTERRUPT)
-   notify_ring(dev_priv-dev, dev_priv-ring[VECS]);
+   if (pm_iir  PM_VEBOX_USER_INTERRUPT)
+   notify_ring(dev_priv-dev, dev_priv-ring[VECS]);
 
-   if (pm_iir  PM_VEBOX_CS_ERROR_INTERRUPT) {
-   DRM_ERROR(VEBOX CS error interrupt 0x%08x\n, pm_iir);
-   i915_handle_error(dev_priv-dev, false);
-   }
+   if (pm_iir  PM_VEBOX_CS_ERROR_INTERRUPT) {
+   DRM_ERROR(VEBOX CS error interrupt 0x%08x\n, pm_iir);
+   i915_handle_error(dev_priv-dev, false);
}
 }
 
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 16/24] drm/i915: queue work outside spinlock in hsw_pm_irq_handler

2013-06-12 Thread Daniel Vetter
And kill the comment about it. Queueing work is a barrier type event,
no amount of locking will help in ordering things (as long as we queue
the work after having updated all relevant data structures). Also, the
queue_work works itself as a sufficient memory barrier.

Again on the surface this is just a tiny micro-optimization to reduce
the hold-time of dev_priv-irq_lock. But the better reason is that it
reduces superficial locking and so makes it clearer what we actually
need for correctness.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 29d4c9f..752b98d 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -938,9 +938,9 @@ static void hsw_pm_irq_handler(struct drm_i915_private 
*dev_priv,
I915_WRITE(GEN6_PMIMR, dev_priv-rps.pm_iir);
/* never want to mask useful interrupts. (also posting read) */
WARN_ON(I915_READ_NOTRACE(GEN6_PMIMR)  ~GEN6_PM_RPS_EVENTS);
-   /* TODO: if queue_work is slow, move it out of the spinlock */
-   queue_work(dev_priv-wq, dev_priv-rps.work);
spin_unlock(dev_priv-rps.lock);
+
+   queue_work(dev_priv-wq, dev_priv-rps.work);
}
 
if (pm_iir  PM_VEBOX_USER_INTERRUPT)
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 17/24] drm/i915: kill dev_priv-rps.lock

2013-06-12 Thread Daniel Vetter
Now that the rps interrupt locking isn't clearly separated (at elast
conceptually) from all the other interrupt locking having a different
lock stopped making sense. With this we can (again) unifiy the
ringbuffer irq refcounts without causing a massive confusion, but
that's for the next patch.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_dma.c |  1 -
 drivers/gpu/drm/i915/i915_drv.h |  8 
 drivers/gpu/drm/i915/i915_irq.c | 12 ++--
 drivers/gpu/drm/i915/intel_pm.c | 16 
 drivers/gpu/drm/i915/intel_ringbuffer.c |  8 
 drivers/gpu/drm/i915/intel_ringbuffer.h |  2 +-
 6 files changed, 23 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index b913b3d..14c3e9c 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1612,7 +1612,6 @@ int i915_driver_load(struct drm_device *dev, unsigned 
long flags)
 
spin_lock_init(dev_priv-irq_lock);
spin_lock_init(dev_priv-gpu_error.lock);
-   spin_lock_init(dev_priv-rps.lock);
spin_lock_init(dev_priv-backlight.lock);
mutex_init(dev_priv-dpio_lock);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 07954b2..42d1363 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -691,12 +691,12 @@ struct i915_suspend_saved_registers {
 };
 
 struct intel_gen6_power_mgmt {
+   /* work and pm_iir are protected by dev_priv-irq_lock */
struct work_struct work;
-   struct delayed_work vlv_work;
u32 pm_iir;
-   /* lock - irqsave spinlock that protectects the work_struct and
-* pm_iir. */
-   spinlock_t lock;
+
+   /* On vlv we need to manually drop to Vmin with a delayed work. */
+   struct delayed_work vlv_work;
 
/* The below variables an all the rps hw state are protected by
 * dev-struct mutext. */
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 752b98d..cd7135d 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -696,13 +696,13 @@ static void gen6_pm_rps_work(struct work_struct *work)
u32 pm_iir, pm_imr;
u8 new_delay;
 
-   spin_lock_irq(dev_priv-rps.lock);
+   spin_lock_irq(dev_priv-irq_lock);
pm_iir = dev_priv-rps.pm_iir;
dev_priv-rps.pm_iir = 0;
pm_imr = I915_READ(GEN6_PMIMR);
/* Make sure not to corrupt PMIMR state used by ringbuffer code */
I915_WRITE(GEN6_PMIMR, pm_imr  ~GEN6_PM_RPS_EVENTS);
-   spin_unlock_irq(dev_priv-rps.lock);
+   spin_unlock_irq(dev_priv-irq_lock);
 
if ((pm_iir  GEN6_PM_RPS_EVENTS) == 0)
return;
@@ -856,11 +856,11 @@ static void gen6_rps_irq_handler(struct drm_i915_private 
*dev_priv,
 * The mask bit in IMR is cleared by dev_priv-rps.work.
 */
 
-   spin_lock(dev_priv-rps.lock);
+   spin_lock(dev_priv-irq_lock);
dev_priv-rps.pm_iir |= pm_iir;
I915_WRITE(GEN6_PMIMR, dev_priv-rps.pm_iir);
POSTING_READ(GEN6_PMIMR);
-   spin_unlock(dev_priv-rps.lock);
+   spin_unlock(dev_priv-irq_lock);
 
queue_work(dev_priv-wq, dev_priv-rps.work);
 }
@@ -933,12 +933,12 @@ static void hsw_pm_irq_handler(struct drm_i915_private 
*dev_priv,
   u32 pm_iir)
 {
if (pm_iir  GEN6_PM_RPS_EVENTS) {
-   spin_lock(dev_priv-rps.lock);
+   spin_lock(dev_priv-irq_lock);
dev_priv-rps.pm_iir |= pm_iir  GEN6_PM_RPS_EVENTS;
I915_WRITE(GEN6_PMIMR, dev_priv-rps.pm_iir);
/* never want to mask useful interrupts. (also posting read) */
WARN_ON(I915_READ_NOTRACE(GEN6_PMIMR)  ~GEN6_PM_RPS_EVENTS);
-   spin_unlock(dev_priv-rps.lock);
+   spin_unlock(dev_priv-irq_lock);
 
queue_work(dev_priv-wq, dev_priv-rps.work);
}
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index adc44e4..6a5cfb5 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3128,9 +3128,9 @@ static void gen6_disable_rps(struct drm_device *dev)
 * register (PMIMR) to mask PM interrupts. The only risk is in leaving
 * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
 
-   spin_lock_irq(dev_priv-rps.lock);
+   spin_lock_irq(dev_priv-irq_lock);
dev_priv-rps.pm_iir = 0;
-   spin_unlock_irq(dev_priv-rps.lock);
+   spin_unlock_irq(dev_priv-irq_lock);
 
I915_WRITE(GEN6_PMIIR, GEN6_PM_RPS_EVENTS);
 }
@@ -3147,9 +3147,9 @@ static void valleyview_disable_rps(struct drm_device *dev)
 * register (PMIMR) to mask PM interrupts. The only risk is in leaving
 * stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
 
-   

[Intel-gfx] [PATCH 18/24] drm/i915: unify ring irq refcounts (again)

2013-06-12 Thread Daniel Vetter
With the simplified locking there's no reason any more to keep the
refcounts seperate.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/intel_ringbuffer.c | 20 ++--
 drivers/gpu/drm/i915/intel_ringbuffer.h |  5 +
 2 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c 
b/drivers/gpu/drm/i915/intel_ringbuffer.c
index a7c9934..b75e9d0 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -819,7 +819,7 @@ gen5_ring_get_irq(struct intel_ring_buffer *ring)
return false;
 
spin_lock_irqsave(dev_priv-irq_lock, flags);
-   if (ring-irq_refcount.gt++ == 0) {
+   if (ring-irq_refcount++ == 0) {
dev_priv-gt_irq_mask = ~ring-irq_enable_mask;
I915_WRITE(GTIMR, dev_priv-gt_irq_mask);
POSTING_READ(GTIMR);
@@ -837,7 +837,7 @@ gen5_ring_put_irq(struct intel_ring_buffer *ring)
unsigned long flags;
 
spin_lock_irqsave(dev_priv-irq_lock, flags);
-   if (--ring-irq_refcount.gt == 0) {
+   if (--ring-irq_refcount == 0) {
dev_priv-gt_irq_mask |= ring-irq_enable_mask;
I915_WRITE(GTIMR, dev_priv-gt_irq_mask);
POSTING_READ(GTIMR);
@@ -856,7 +856,7 @@ i9xx_ring_get_irq(struct intel_ring_buffer *ring)
return false;
 
spin_lock_irqsave(dev_priv-irq_lock, flags);
-   if (ring-irq_refcount.gt++ == 0) {
+   if (ring-irq_refcount++ == 0) {
dev_priv-irq_mask = ~ring-irq_enable_mask;
I915_WRITE(IMR, dev_priv-irq_mask);
POSTING_READ(IMR);
@@ -874,7 +874,7 @@ i9xx_ring_put_irq(struct intel_ring_buffer *ring)
unsigned long flags;
 
spin_lock_irqsave(dev_priv-irq_lock, flags);
-   if (--ring-irq_refcount.gt == 0) {
+   if (--ring-irq_refcount == 0) {
dev_priv-irq_mask |= ring-irq_enable_mask;
I915_WRITE(IMR, dev_priv-irq_mask);
POSTING_READ(IMR);
@@ -893,7 +893,7 @@ i8xx_ring_get_irq(struct intel_ring_buffer *ring)
return false;
 
spin_lock_irqsave(dev_priv-irq_lock, flags);
-   if (ring-irq_refcount.gt++ == 0) {
+   if (ring-irq_refcount++ == 0) {
dev_priv-irq_mask = ~ring-irq_enable_mask;
I915_WRITE16(IMR, dev_priv-irq_mask);
POSTING_READ16(IMR);
@@ -911,7 +911,7 @@ i8xx_ring_put_irq(struct intel_ring_buffer *ring)
unsigned long flags;
 
spin_lock_irqsave(dev_priv-irq_lock, flags);
-   if (--ring-irq_refcount.gt == 0) {
+   if (--ring-irq_refcount == 0) {
dev_priv-irq_mask |= ring-irq_enable_mask;
I915_WRITE16(IMR, dev_priv-irq_mask);
POSTING_READ16(IMR);
@@ -1004,7 +1004,7 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring)
gen6_gt_force_wake_get(dev_priv);
 
spin_lock_irqsave(dev_priv-irq_lock, flags);
-   if (ring-irq_refcount.gt++ == 0) {
+   if (ring-irq_refcount++ == 0) {
if (HAS_L3_GPU_CACHE(dev)  ring-id == RCS)
I915_WRITE_IMR(ring,
   ~(ring-irq_enable_mask |
@@ -1028,7 +1028,7 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring)
unsigned long flags;
 
spin_lock_irqsave(dev_priv-irq_lock, flags);
-   if (--ring-irq_refcount.gt == 0) {
+   if (--ring-irq_refcount == 0) {
if (HAS_L3_GPU_CACHE(dev)  ring-id == RCS)
I915_WRITE_IMR(ring,
   ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT);
@@ -1054,7 +1054,7 @@ hsw_vebox_get_irq(struct intel_ring_buffer *ring)
return false;
 
spin_lock_irqsave(dev_priv-irq_lock, flags);
-   if (ring-irq_refcount.pm++ == 0) {
+   if (ring-irq_refcount++ == 0) {
u32 pm_imr = I915_READ(GEN6_PMIMR);
I915_WRITE_IMR(ring, ~ring-irq_enable_mask);
I915_WRITE(GEN6_PMIMR, pm_imr  ~ring-irq_enable_mask);
@@ -1076,7 +1076,7 @@ hsw_vebox_put_irq(struct intel_ring_buffer *ring)
return;
 
spin_lock_irqsave(dev_priv-irq_lock, flags);
-   if (--ring-irq_refcount.pm == 0) {
+   if (--ring-irq_refcount == 0) {
u32 pm_imr = I915_READ(GEN6_PMIMR);
I915_WRITE_IMR(ring, ~0);
I915_WRITE(GEN6_PMIMR, pm_imr | ring-irq_enable_mask);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h 
b/drivers/gpu/drm/i915/intel_ringbuffer.h
index f960805..26e304c 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -74,10 +74,7 @@ struct  intel_ring_buffer {
 */
u32 last_retired_head;
 
-   struct {
-   u32 gt; /*  protected by dev_priv-irq_lock */
-   u32 pm; /*  protected by dev_priv-irq_lock */

[Intel-gfx] [PATCH 19/24] drm/i915: don't enable PM_VEBOX_CS_ERROR_INTERRUPT

2013-06-12 Thread Daniel Vetter
The code to handle it is broken - there's simply no code to clear CS
parser errors on gen5+. And behold, for all the other rings we also
don't enable it!

Leave the handling code itself in place just to be consistent with the
existing mess though. And in case someone feels like fixing it all up.

This has been errornously enabled in

commit 12638c57f31952127c734c26315e1348fa1334c2
Author: Ben Widawsky b...@bwidawsk.net
Date:   Tue May 28 19:22:31 2013 -0700

drm/i915: Enable vebox interrupts

Cc: Damien Lespiau damien.lesp...@intel.com
Cc: Ben Widawsky b...@bwidawsk.net
Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 3 +--
 drivers/gpu/drm/i915/intel_ringbuffer.c | 3 +--
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index cd7135d..293ee68 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2715,8 +2715,7 @@ static int ivybridge_irq_postinstall(struct drm_device 
*dev)
 
I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
if (HAS_VEBOX(dev))
-   pm_irqs |= PM_VEBOX_USER_INTERRUPT |
-   PM_VEBOX_CS_ERROR_INTERRUPT;
+   pm_irqs |= PM_VEBOX_USER_INTERRUPT;
 
/* Our enable/disable rps functions may touch these registers so
 * make sure to set a known state for only the non-RPS bits.
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c 
b/drivers/gpu/drm/i915/intel_ringbuffer.c
index b75e9d0..a86d5d6 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1998,8 +1998,7 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
ring-add_request = gen6_add_request;
ring-get_seqno = gen6_ring_get_seqno;
ring-set_seqno = ring_set_seqno;
-   ring-irq_enable_mask = PM_VEBOX_USER_INTERRUPT |
-   PM_VEBOX_CS_ERROR_INTERRUPT;
+   ring-irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
ring-irq_get = hsw_vebox_get_irq;
ring-irq_put = hsw_vebox_put_irq;
ring-dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 20/24] drm/i915: kill bogus GTIIR clearing in vlv_preinstall hook

2013-06-12 Thread Daniel Vetter
Preinstall disables interrupts, we clear the status register in the
postinstall hook before we actually enable interrupt sources.

Also add a comment for the curios ring IMR masking, it doesn't
seem to be required on any other platform.

We seem to have some room for common gt_preinstall/postinstall hooks.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 293ee68..b680e1c 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2546,13 +2546,12 @@ static void valleyview_irq_preinstall(struct drm_device 
*dev)
 
/* VLV magic */
I915_WRITE(VLV_IMR, 0);
+   /* Do we really need to clear ring masks for vlv? */
I915_WRITE(RING_IMR(RENDER_RING_BASE), 0);
I915_WRITE(RING_IMR(GEN6_BSD_RING_BASE), 0);
I915_WRITE(RING_IMR(BLT_RING_BASE), 0);
 
/* and GT */
-   I915_WRITE(GTIIR, I915_READ(GTIIR));
-   I915_WRITE(GTIIR, I915_READ(GTIIR));
I915_WRITE(GTIMR, 0x);
I915_WRITE(GTIER, 0x0);
POSTING_READ(GTIER);
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 23/24] drm/i915: extract rps interrupt enable/disable helpers

2013-06-12 Thread Daniel Vetter
This just unifies the vlv code with the snb-hsw code which matched
exactly before the VECS enabling.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/intel_pm.c | 59 -
 1 file changed, 29 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 1f3dcdc..2fd67ec 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3114,13 +3114,10 @@ void valleyview_set_rps(struct drm_device *dev, u8 val)
trace_intel_gpu_freq_change(vlv_gpu_freq(dev_priv-mem_freq, val));
 }
 
-
-static void gen6_disable_rps(struct drm_device *dev)
+static void gen6_disable_rps_interrupts(struct drm_device *dev)
 {
struct drm_i915_private *dev_priv = dev-dev_private;
 
-   I915_WRITE(GEN6_RC_CONTROL, 0);
-   I915_WRITE(GEN6_RPNSWREQ, 1  31);
I915_WRITE(GEN6_PMINTRMSK, 0x);
I915_WRITE(GEN6_PMIER, I915_READ(GEN6_PMIER)  ~GEN6_PM_RPS_EVENTS);
/* Complete PM interrupt masking here doesn't race with the rps work
@@ -3135,23 +3132,23 @@ static void gen6_disable_rps(struct drm_device *dev)
I915_WRITE(GEN6_PMIIR, GEN6_PM_RPS_EVENTS);
 }
 
-static void valleyview_disable_rps(struct drm_device *dev)
+static void gen6_disable_rps(struct drm_device *dev)
 {
struct drm_i915_private *dev_priv = dev-dev_private;
 
I915_WRITE(GEN6_RC_CONTROL, 0);
-   I915_WRITE(GEN6_PMINTRMSK, 0x);
-   I915_WRITE(GEN6_PMIER, 0);
-   /* Complete PM interrupt masking here doesn't race with the rps work
-* item again unmasking PM interrupts because that is using a different
-* register (PMIMR) to mask PM interrupts. The only risk is in leaving
-* stale bits in PMIIR and PMIMR which gen6_enable_rps will clean up. */
+   I915_WRITE(GEN6_RPNSWREQ, 1  31);
 
-   spin_lock_irq(dev_priv-irq_lock);
-   dev_priv-rps.pm_iir = 0;
-   spin_unlock_irq(dev_priv-irq_lock);
+   gen6_disable_rps_interrupts(dev);
+}
+
+static void valleyview_disable_rps(struct drm_device *dev)
+{
+   struct drm_i915_private *dev_priv = dev-dev_private;
+
+   I915_WRITE(GEN6_RC_CONTROL, 0);
 
-   I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
+   gen6_disable_rps_interrupts(dev);
 
if (dev_priv-vlv_pctx) {
drm_gem_object_unreference(dev_priv-vlv_pctx-base);
@@ -3184,6 +3181,21 @@ int intel_enable_rc6(const struct drm_device *dev)
return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);
 }
 
+static void gen6_enable_rps_interrupts(struct drm_device *dev)
+{
+   struct drm_i915_private *dev_priv = dev-dev_private;
+
+   spin_lock_irq(dev_priv-irq_lock);
+   /* FIXME: Our interrupt enabling sequence is bonghits.
+* dev_priv-rps.pm_iir really should be 0 here. */
+   dev_priv-rps.pm_iir = 0;
+   I915_WRITE(GEN6_PMIMR, I915_READ(GEN6_PMIMR)  ~GEN6_PM_RPS_EVENTS);
+   I915_WRITE(GEN6_PMIIR, GEN6_PM_RPS_EVENTS);
+   spin_unlock_irq(dev_priv-irq_lock);
+   /* unmask all PM interrupts */
+   I915_WRITE(GEN6_PMINTRMSK, 0);
+}
+
 static void gen6_enable_rps(struct drm_device *dev)
 {
struct drm_i915_private *dev_priv = dev-dev_private;
@@ -3312,15 +3324,7 @@ static void gen6_enable_rps(struct drm_device *dev)
 
gen6_set_rps(dev_priv-dev, (gt_perf_status  0xff00)  8);
 
-   spin_lock_irq(dev_priv-irq_lock);
-   /* FIXME: Our interrupt enabling sequence is bonghits.
-* dev_priv-rps.pm_iir really should be 0 here. */
-   dev_priv-rps.pm_iir = 0;
-   I915_WRITE(GEN6_PMIMR, I915_READ(GEN6_PMIMR)  ~GEN6_PM_RPS_EVENTS);
-   I915_WRITE(GEN6_PMIIR, GEN6_PM_RPS_EVENTS);
-   spin_unlock_irq(dev_priv-irq_lock);
-   /* unmask all PM interrupts */
-   I915_WRITE(GEN6_PMINTRMSK, 0);
+   gen6_enable_rps_interrupts(dev);
 
rc6vids = 0;
ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, 
rc6vids);
@@ -3581,12 +3585,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
 
valleyview_set_rps(dev_priv-dev, rpe);
 
-   spin_lock_irq(dev_priv-irq_lock);
-   WARN_ON(dev_priv-rps.pm_iir != 0);
-   I915_WRITE(GEN6_PMIMR, 0);
-   spin_unlock_irq(dev_priv-irq_lock);
-   /* enable all PM interrupts */
-   I915_WRITE(GEN6_PMINTRMSK, 0);
+   gen6_enable_rps_interrupts(dev);
 
gen6_gt_force_wake_put(dev_priv);
 }
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 22/24] drm/i915: unify GT/PM irq postinstall code

2013-06-12 Thread Daniel Vetter
Again extract a common helper. For the postinstall hook things are a
bit more complicated since we have more cases on ilk-hsw/vlv here.

But since vlv was clearly broken by failing to initialize
dev_priv-gt_irq_mask correclty (mayb that explains the strange
RING_IMR clearing in the preinstall hook?) clearly justified the
shared code.

Also kill the PMIER setting in the async rps enable work. I should
have been save, but also clearly looked rather fragile.

With this we now have the usual interrupt register sequence for GT/PM
irq registers:

- IER is setup once with all the interrupts we ever need in the
  postinstall hook and never touched again. Exceptions are SDEIER,
  which is touched in the preinstall hook (when the irq handler isn't
  enabled) and then only from the irq handler. And DEIER/VLV_IER with
  is used in the irq handler but also written to once in the
  postinstall hook. But since that write is essentially what enables
  the interrupt and we should always have MSI interrupts we should be
  save. In case we ever have non-MSI interrupts we'd be screwed.

- IIR is cleared in the postinstall hook before we enable/unmask the
  respective interrupt sources. Hence we can't steal an interrupt
  event an accidentally trigger the spurious interrupt logic in the
  core kernel.

- IMR regs are (usually) all masked off. Those are the only regs
  changed at runtime, which is all protected by dev_priv-irq_lock.

This unification also kills the cargo-culted read-modify-write PM
register setup for VECS. Interrupt setup is done without userspace
being able to interfere, so we better know what values we want to put
into those registers. RMW cycles otoh are really good at papering over
races, until stuff magically blows up and no one has a clue why.

Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 91 +++--
 drivers/gpu/drm/i915/intel_pm.c |  4 --
 2 files changed, 41 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 954d8f8..1fb49f7 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2616,6 +2616,44 @@ static void ibx_irq_postinstall(struct drm_device *dev)
I915_WRITE(SDEIMR, ~mask);
 }
 
+static void gen5_gt_irq_postinstall(struct drm_device *dev)
+{
+   struct drm_i915_private *dev_priv = dev-dev_private;
+   u32 pm_irqs, gt_irqs;
+
+   pm_irqs = gt_irqs = 0;
+
+   dev_priv-gt_irq_mask = ~0;
+   if (HAS_L3_GPU_CACHE(dev)) {
+   dev_priv-gt_irq_mask = ~GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
+   gt_irqs |= GT_RENDER_L3_PARITY_ERROR_INTERRUPT;
+   }
+
+   gt_irqs |= GT_RENDER_USER_INTERRUPT;
+   if (IS_GEN5(dev)) {
+   gt_irqs |= GT_RENDER_PIPECTL_NOTIFY_INTERRUPT |
+  ILK_BSD_USER_INTERRUPT;
+   } else {
+   gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
+   }
+
+   I915_WRITE(GTIIR, I915_READ(GTIIR));
+   I915_WRITE(GTIMR, dev_priv-gt_irq_mask);
+   I915_WRITE(GTIER, gt_irqs);
+   POSTING_READ(GTIER);
+
+   if (HAS_VEBOX(dev))
+   pm_irqs |= PM_VEBOX_USER_INTERRUPT;
+   if (INTEL_INFO(dev)-gen = 6)
+   pm_irqs |= GEN6_PM_RPS_EVENTS;
+
+   I915_WRITE(GEN6_PMIIR, I915_READ(GEN6_PMIIR));
+   I915_WRITE(GEN6_PMIMR, 0x);
+   I915_WRITE(GEN6_PMIER, pm_irqs);
+   POSTING_READ(GEN6_PMIER);
+
+}
+
 static int ironlake_irq_postinstall(struct drm_device *dev)
 {
unsigned long irqflags;
@@ -2626,7 +2664,6 @@ static int ironlake_irq_postinstall(struct drm_device 
*dev)
   DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE |
   DE_AUX_CHANNEL_A | DE_PIPEB_FIFO_UNDERRUN |
   DE_PIPEA_FIFO_UNDERRUN | DE_POISON;
-   u32 gt_irqs;
 
dev_priv-irq_mask = ~display_mask;
 
@@ -2637,21 +2674,7 @@ static int ironlake_irq_postinstall(struct drm_device 
*dev)
  DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT);
POSTING_READ(DEIER);
 
-   dev_priv-gt_irq_mask = ~0;
-
-   I915_WRITE(GTIIR, I915_READ(GTIIR));
-   I915_WRITE(GTIMR, dev_priv-gt_irq_mask);
-
-   gt_irqs = GT_RENDER_USER_INTERRUPT;
-
-   if (IS_GEN6(dev))
-   gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT;
-   else
-   gt_irqs |= GT_RENDER_PIPECTL_NOTIFY_INTERRUPT |
-  ILK_BSD_USER_INTERRUPT;
-
-   I915_WRITE(GTIER, gt_irqs);
-   POSTING_READ(GTIER);
+   gen5_gt_irq_postinstall(dev);
 
ibx_irq_postinstall(dev);
 
@@ -2680,8 +2703,6 @@ static int ivybridge_irq_postinstall(struct drm_device 
*dev)
DE_PLANEA_FLIP_DONE_IVB |
DE_AUX_CHANNEL_A_IVB |
DE_ERR_INT_IVB;
-   u32 pm_irqs = GEN6_PM_RPS_EVENTS;
-   u32 gt_irqs;
 

[Intel-gfx] [PATCH 24/24] drm/i915: simplify rps interrupt enabling/disabling sequence

2013-06-12 Thread Daniel Vetter
At the moment we have the following interrupt enabling sequence:
1. irq preinstall hook
2. enabling the interrupt handler and calling irq postinstall hook
3. enable rps interrupts from the async work

And the folliwing disable sequence:
1. disabling the interrupt handler and calling the uninstall hook
2. disabling the rps interrupt

Since the postinstall hook now always sets up PMIIR, PMIER and PMIMR
to known-good states there no way for an interrupt to sneak in in the
enable sequence, so we can reinstate the WARN lost in

commit eda63ffb906c2fb3b609a0e87aeb63c0f25b9e6b
Author: Ben Widawsky b...@bwidawsk.net
Date:   Tue May 28 19:22:26 2013 -0700

drm/i915: Add PM regs to pre/post install

Note that there's some room for future cleanups since most of the
interrupt register clearing in the disable function is rather
redundant. But that's better done in follow-up patches, if at all.

Cc: Ben Widawsky b...@bwidawsk.net
Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/intel_pm.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 2fd67ec..6d13265 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3186,9 +3186,7 @@ static void gen6_enable_rps_interrupts(struct drm_device 
*dev)
struct drm_i915_private *dev_priv = dev-dev_private;
 
spin_lock_irq(dev_priv-irq_lock);
-   /* FIXME: Our interrupt enabling sequence is bonghits.
-* dev_priv-rps.pm_iir really should be 0 here. */
-   dev_priv-rps.pm_iir = 0;
+   WARN_ON(dev_priv-rps.pm_iir);
I915_WRITE(GEN6_PMIMR, I915_READ(GEN6_PMIMR)  ~GEN6_PM_RPS_EVENTS);
I915_WRITE(GEN6_PMIIR, GEN6_PM_RPS_EVENTS);
spin_unlock_irq(dev_priv-irq_lock);
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 4/7] drm/i915: add batch bo to i915_add_request()

2013-06-12 Thread Mika Kuoppala
In order to track down a batch buffer and context which
caused the ring to hang, store reference to bo into the request struct.
Request can also cause gpu to hang after the batch in the flush section
in the ring. To detect this add start of the flush portion offset into the
request.

v2: Included comment about request vs batch_obj lifetimes (Chris Wilson)

Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
---
 drivers/gpu/drm/i915/i915_drv.h|   11 +--
 drivers/gpu/drm/i915/i915_gem.c|   13 -
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |7 ---
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 22dcff6..8bc399c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1352,12 +1352,18 @@ struct drm_i915_gem_request {
/** GEM sequence number associated with this request. */
uint32_t seqno;
 
-   /** Postion in the ringbuffer of the end of the request */
+   /** Position in the ringbuffer of the start of the request */
+   u32 head;
+
+   /** Position in the ringbuffer of the end of the request */
u32 tail;
 
/** Context related to this request */
struct i915_hw_context *ctx;
 
+   /** Batch buffer related to this request if any */
+   struct drm_i915_gem_object *batch_obj;
+
/** Time at which this request was emitted, in jiffies. */
unsigned long emitted_jiffies;
 
@@ -1747,9 +1753,10 @@ int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_idle(struct drm_device *dev);
 int __i915_add_request(struct intel_ring_buffer *ring,
   struct drm_file *file,
+  struct drm_i915_gem_object *batch_obj,
   u32 *seqno);
 #define i915_add_request(ring, seqno) \
-   __i915_add_request(ring, NULL, seqno);
+   __i915_add_request(ring, NULL, NULL, seqno);
 int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
 uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 38e2087..dc32fae 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2002,14 +2002,16 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)
 
 int __i915_add_request(struct intel_ring_buffer *ring,
   struct drm_file *file,
+  struct drm_i915_gem_object *obj,
   u32 *out_seqno)
 {
drm_i915_private_t *dev_priv = ring-dev-dev_private;
struct drm_i915_gem_request *request;
-   u32 request_ring_position;
+   u32 request_ring_position, request_start;
int was_empty;
int ret;
 
+   request_start = intel_ring_get_tail(ring);
/*
 * Emit any outstanding flushes - execbuf can fail to emit the flush
 * after having emitted the batchbuffer command. Hence we need to fix
@@ -2041,8 +2043,17 @@ int __i915_add_request(struct intel_ring_buffer *ring,
 
request-seqno = intel_ring_get_seqno(ring);
request-ring = ring;
+   request-head = request_start;
request-tail = request_ring_position;
request-ctx = ring-last_context;
+   request-batch_obj = obj;
+
+   /* Whilst this request exists, batch_obj will be on the
+* active_list, and so will hold the active reference. Only when this
+* request is retired will the the batch_obj be moved onto the
+* inactive_list and lose its active reference. Hence we do not need
+* to explicitly hold another reference here.
+*/
 
if (request-ctx)
i915_gem_context_reference(request-ctx);
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index d79ac7a..87a3227 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -796,13 +796,14 @@ i915_gem_execbuffer_move_to_active(struct list_head 
*objects,
 static void
 i915_gem_execbuffer_retire_commands(struct drm_device *dev,
struct drm_file *file,
-   struct intel_ring_buffer *ring)
+   struct intel_ring_buffer *ring,
+   struct drm_i915_gem_object *obj)
 {
/* Unconditionally force add_request to emit a full flush. */
ring-gpu_caches_dirty = true;
 
/* Add a breadcrumb for the completion of the batch buffer */
-   (void)__i915_add_request(ring, file, NULL);
+   (void)__i915_add_request(ring, file, obj, NULL);
 }
 
 static int
@@ -1083,7 +1084,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
trace_i915_gem_ring_dispatch(ring, intel_ring_get_seqno(ring), flags);
 
 

[Intel-gfx] [PATCH 6/7] drm/i915: find guilty batch buffer on ring resets

2013-06-12 Thread Mika Kuoppala
After hang check timer has declared gpu to be hang,
rings are reset. In ring reset, when clearing
request list, do post mortem analysis to find out
the guilty batch buffer.

Select requests for further analysis by inspecting
the completed sequence number which has been updated
into the HWS page. If request was completed, it can't
be related to the hang.

For noncompleted requests mark the batch as guilty
if the ring was not waiting and the ring head was
stuck inside the buffer object or in the flush region
right after the batch. For everything else, mark
them as innocents.

v2: Fixed a typo in commit message (Ville Syrjälä)

v3: - more descriptive function parameters (Chris Wilson)
- use masked head address when inspecting if request is in ring
- s/hangcheck.last_action/hangcheck.action
- added comment about unmasked head hitting batch_obj range

Reviewed-by: Chris Wilson ch...@chris-wilson.co.uk
Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
---
 drivers/gpu/drm/i915/i915_gem.c |   97 +++
 1 file changed, 97 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index dc32fae..9b20fbb 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2110,6 +2110,94 @@ i915_gem_request_remove_from_client(struct 
drm_i915_gem_request *request)
spin_unlock(file_priv-mm.lock);
 }
 
+static bool i915_head_inside_object(u32 acthd, struct drm_i915_gem_object *obj)
+{
+   if (acthd = obj-gtt_offset 
+   acthd  obj-gtt_offset + obj-base.size)
+   return true;
+
+   return false;
+}
+
+static bool i915_head_inside_request(const u32 acthd_unmasked,
+const u32 request_start,
+const u32 request_end)
+{
+   const u32 acthd = acthd_unmasked  HEAD_ADDR;
+
+   if (request_start  request_end) {
+   if (acthd = request_start  acthd  request_end)
+   return true;
+   } else if (request_start  request_end) {
+   if (acthd = request_start || acthd  request_end)
+   return true;
+   }
+
+   return false;
+}
+
+static bool i915_request_guilty(struct drm_i915_gem_request *request,
+   const u32 acthd, bool *inside)
+{
+   /* There is a possibility that unmasked head address
+* pointing inside the ring, matches the batch_obj address range.
+* However this is extremely unlikely.
+*/
+
+   if (request-batch_obj) {
+   if (i915_head_inside_object(acthd, request-batch_obj)) {
+   *inside = true;
+   return true;
+   }
+   }
+
+   if (i915_head_inside_request(acthd, request-head, request-tail)) {
+   *inside = false;
+   return true;
+   }
+
+   return false;
+}
+
+static void i915_set_reset_status(struct intel_ring_buffer *ring,
+ struct drm_i915_gem_request *request,
+ u32 acthd)
+{
+   struct i915_ctx_hang_stats *hs = NULL;
+   bool inside, guilty;
+
+   /* Innocent until proven guilty */
+   guilty = false;
+
+   if (ring-hangcheck.action != wait 
+   i915_request_guilty(request, acthd, inside)) {
+   DRM_ERROR(%s hung %s bo (0x%x ctx %d) at 0x%x\n,
+ ring-name,
+ inside ? inside : flushing,
+ request-batch_obj ?
+ request-batch_obj-gtt_offset : 0,
+ request-ctx ? request-ctx-id : 0,
+ acthd);
+
+   guilty = true;
+   }
+
+   /* If contexts are disabled or this is the default context, use
+* file_priv-reset_state
+*/
+   if (request-ctx  request-ctx-id != DEFAULT_CONTEXT_ID)
+   hs = request-ctx-hang_stats;
+   else if (request-file_priv)
+   hs = request-file_priv-hang_stats;
+
+   if (hs) {
+   if (guilty)
+   hs-batch_active++;
+   else
+   hs-batch_pending++;
+   }
+}
+
 static void i915_gem_free_request(struct drm_i915_gem_request *request)
 {
list_del(request-list);
@@ -2124,6 +2212,12 @@ static void i915_gem_free_request(struct 
drm_i915_gem_request *request)
 static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
  struct intel_ring_buffer *ring)
 {
+   u32 completed_seqno;
+   u32 acthd;
+
+   acthd = intel_ring_get_active_head(ring);
+   completed_seqno = ring-get_seqno(ring, false);
+
while (!list_empty(ring-request_list)) {
struct drm_i915_gem_request *request;
 
@@ -2131,6 +2225,9 @@ static void i915_gem_reset_ring_lists(struct 
drm_i915_private *dev_priv,
 

[Intel-gfx] [PATCH 6/7] drm/i915: find guilty batch buffer on ring resets

2013-06-12 Thread Mika Kuoppala
After hang check timer has declared gpu to be hung,
rings are reset. In ring reset, when clearing
request list, do post mortem analysis to find out
the guilty batch buffer.

Select requests for further analysis by inspecting
the completed sequence number which has been updated
into the HWS page. If request was completed, it can't
be related to the hang.

For noncompleted requests mark the batch as guilty
if the ring was not waiting and the ring head was
stuck inside the buffer object or in the flush region
right after the batch. For everything else, mark
them as innocents.

v2: Fixed a typo in commit message (Ville Syrjälä)

v3: - more descriptive function parameters (Chris Wilson)
- use masked head address when inspecting if request is in ring
- s/hangcheck.last_action/hangcheck.action
- added comment about unmasked head hitting batch_obj range

Reviewed-by: Chris Wilson ch...@chris-wilson.co.uk
Signed-off-by: Mika Kuoppala mika.kuopp...@intel.com
---
 drivers/gpu/drm/i915/i915_gem.c |   97 +++
 1 file changed, 97 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index dc32fae..9b20fbb 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2110,6 +2110,94 @@ i915_gem_request_remove_from_client(struct 
drm_i915_gem_request *request)
spin_unlock(file_priv-mm.lock);
 }
 
+static bool i915_head_inside_object(u32 acthd, struct drm_i915_gem_object *obj)
+{
+   if (acthd = obj-gtt_offset 
+   acthd  obj-gtt_offset + obj-base.size)
+   return true;
+
+   return false;
+}
+
+static bool i915_head_inside_request(const u32 acthd_unmasked,
+const u32 request_start,
+const u32 request_end)
+{
+   const u32 acthd = acthd_unmasked  HEAD_ADDR;
+
+   if (request_start  request_end) {
+   if (acthd = request_start  acthd  request_end)
+   return true;
+   } else if (request_start  request_end) {
+   if (acthd = request_start || acthd  request_end)
+   return true;
+   }
+
+   return false;
+}
+
+static bool i915_request_guilty(struct drm_i915_gem_request *request,
+   const u32 acthd, bool *inside)
+{
+   /* There is a possibility that unmasked head address
+* pointing inside the ring, matches the batch_obj address range.
+* However this is extremely unlikely.
+*/
+
+   if (request-batch_obj) {
+   if (i915_head_inside_object(acthd, request-batch_obj)) {
+   *inside = true;
+   return true;
+   }
+   }
+
+   if (i915_head_inside_request(acthd, request-head, request-tail)) {
+   *inside = false;
+   return true;
+   }
+
+   return false;
+}
+
+static void i915_set_reset_status(struct intel_ring_buffer *ring,
+ struct drm_i915_gem_request *request,
+ u32 acthd)
+{
+   struct i915_ctx_hang_stats *hs = NULL;
+   bool inside, guilty;
+
+   /* Innocent until proven guilty */
+   guilty = false;
+
+   if (ring-hangcheck.action != wait 
+   i915_request_guilty(request, acthd, inside)) {
+   DRM_ERROR(%s hung %s bo (0x%x ctx %d) at 0x%x\n,
+ ring-name,
+ inside ? inside : flushing,
+ request-batch_obj ?
+ request-batch_obj-gtt_offset : 0,
+ request-ctx ? request-ctx-id : 0,
+ acthd);
+
+   guilty = true;
+   }
+
+   /* If contexts are disabled or this is the default context, use
+* file_priv-reset_state
+*/
+   if (request-ctx  request-ctx-id != DEFAULT_CONTEXT_ID)
+   hs = request-ctx-hang_stats;
+   else if (request-file_priv)
+   hs = request-file_priv-hang_stats;
+
+   if (hs) {
+   if (guilty)
+   hs-batch_active++;
+   else
+   hs-batch_pending++;
+   }
+}
+
 static void i915_gem_free_request(struct drm_i915_gem_request *request)
 {
list_del(request-list);
@@ -2124,6 +2212,12 @@ static void i915_gem_free_request(struct 
drm_i915_gem_request *request)
 static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv,
  struct intel_ring_buffer *ring)
 {
+   u32 completed_seqno;
+   u32 acthd;
+
+   acthd = intel_ring_get_active_head(ring);
+   completed_seqno = ring-get_seqno(ring, false);
+
while (!list_empty(ring-request_list)) {
struct drm_i915_gem_request *request;
 
@@ -2131,6 +2225,9 @@ static void i915_gem_reset_ring_lists(struct 
drm_i915_private *dev_priv,
 

Re: [Intel-gfx] [PATCH 6/9] drm/i915: fix ibx/cpt/ppt dpll limits

2013-06-12 Thread Damien Lespiau
On Tue, May 21, 2013 at 09:54:56PM +0200, Daniel Vetter wrote:
 Now this was broken in pretty fundamental ways:
 - M1/M2 have been consistently off by 2 and used doc values instead of
   the two less registers values our code expects.
 - M/N limits often were too small by seemingly arbitrary amounts. I
   suspect this started to work around issues due to the wrong M1/M2
   limits.
 
 Rectify this all and consolidate the limits a bit with a #define where
 the docs say that they should be equal.

So this time I'm reading ibexpeak_xxx.xls

 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
 ---
  drivers/gpu/drm/i915/intel_display.c | 36 
 +++-
  1 file changed, 11 insertions(+), 25 deletions(-)
 
 diff --git a/drivers/gpu/drm/i915/intel_display.c 
 b/drivers/gpu/drm/i915/intel_display.c
 index 520e340..80698ac 100644
 --- a/drivers/gpu/drm/i915/intel_display.c
 +++ b/drivers/gpu/drm/i915/intel_display.c
 @@ -217,18 +217,16 @@ static const intel_limit_t intel_limits_pineview_lvds = 
 {
   .p2_slow = 14, .p2_fast = 14 },
  };
  
 -/* Ironlake / Sandybridge
 - *
 - * We calculate clock using (register_value + 2) for N/M1/M2, so here
 - * the range value for them is (actual_value - 2).
 - */
 +#define ILK_DPLL_M_N_LIMITS \
 + .n = { .min = 1, .max = 6 }, \
 + .m = { .min = 79, .max = 127 }, \
 + .m1 = { .min = 10, .max = 20 }, \
 + .m2 = { .min = 3, .max = 7 }, \
 +
  static const intel_limit_t intel_limits_ironlake_dac = {
   .dot = { .min = 25000, .max = 35 },
   .vco = { .min = 176, .max = 351 },
 - .n = { .min = 1, .max = 5 },
 - .m = { .min = 79, .max = 127 },
 - .m1 = { .min = 12, .max = 22 },
 - .m2 = { .min = 5, .max = 9 },
 + ILK_DPLL_M_N_LIMITS
   .p = { .min = 5, .max = 80 },
   .p1 = { .min = 1, .max = 8 },
   .p2 = { .dot_limit = 225000,

In ibexpeak_.xsl I have n between 3 and 7 (so 1,5 seemed correct)
for DAC. It also restrics M between 79 and 118.

 @@ -238,10 +236,7 @@ static const intel_limit_t intel_limits_ironlake_dac = {
  static const intel_limit_t intel_limits_ironlake_single_lvds = {
   .dot = { .min = 25000, .max = 35 },
   .vco = { .min = 176, .max = 351 },
 - .n = { .min = 1, .max = 3 },
 - .m = { .min = 79, .max = 118 },
 - .m1 = { .min = 12, .max = 22 },
 - .m2 = { .min = 5, .max = 9 },
 + ILK_DPLL_M_N_LIMITS
   .p = { .min = 28, .max = 112 },
   .p1 = { .min = 2, .max = 8 },
   .p2 = { .dot_limit = 225000,
 @@ -251,10 +246,7 @@ static const intel_limit_t 
 intel_limits_ironlake_single_lvds = {
  static const intel_limit_t intel_limits_ironlake_dual_lvds = {
   .dot = { .min = 25000, .max = 35 },
   .vco = { .min = 176, .max = 351 },
 - .n = { .min = 1, .max = 3 },
 - .m = { .min = 79, .max = 127 },
 - .m1 = { .min = 12, .max = 22 },
 - .m2 = { .min = 5, .max = 9 },
 + ILK_DPLL_M_N_LIMITS
   .p = { .min = 14, .max = 56 },
   .p1 = { .min = 2, .max = 8 },
   .p2 = { .dot_limit = 225000,

For single channel LVDS with ref clock at 120MHz I have n between 3 and
5 (so 1,3 seemed correct). M is restricted to 79,118 here as well

 @@ -265,10 +257,7 @@ static const intel_limit_t 
 intel_limits_ironlake_dual_lvds = {
  static const intel_limit_t intel_limits_ironlake_single_lvds_100m = {
   .dot = { .min = 25000, .max = 35 },
   .vco = { .min = 176, .max = 351 },
 - .n = { .min = 1, .max = 2 },
 - .m = { .min = 79, .max = 126 },
 - .m1 = { .min = 12, .max = 22 },
 - .m2 = { .min = 5, .max = 9 },
 + ILK_DPLL_M_N_LIMITS
   .p = { .min = 28, .max = 112 },
   .p1 = { .min = 2, .max = 8 },
   .p2 = { .dot_limit = 225000,

For dual channel LVDS, I have n between 3 and 5, so 1,3? M between
79,127

 @@ -278,10 +267,7 @@ static const intel_limit_t 
 intel_limits_ironlake_single_lvds_100m = {
  static const intel_limit_t intel_limits_ironlake_dual_lvds_100m = {
   .dot = { .min = 25000, .max = 35 },
   .vco = { .min = 176, .max = 351 },
 - .n = { .min = 1, .max = 3 },
 - .m = { .min = 79, .max = 126 },
 - .m1 = { .min = 12, .max = 22 },
 - .m2 = { .min = 5, .max = 9 },
 + ILK_DPLL_M_N_LIMITS
   .p = { .min = 14, .max = 42 },
   .p1 = { .min = 2, .max = 6 },
   .p2 = { .dot_limit = 225000,

And there n between 3,4 so (1,2), M was indeed between 79 and 126

-- 
Damien
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 9/9] drm/i915: check for strange pfit pipe assignemnt on ivb/hsw

2013-06-12 Thread Damien Lespiau
On Tue, May 21, 2013 at 09:54:59PM +0200, Daniel Vetter wrote:
 Panel fitters on ivb/hsw are not created equal since not all of them
 support the new high-quality upscaling mode. To offset this the hw
 allows us to freely assign the pfits to pipes.
 
 Since our code currently doesn't support this we might fall over when
 taking over firmware state. So check for this case and WARN about it.
 We can then improve the code once we've hit this in the wild. Or once
 we decide to support the improved upscale modes, though that requires
 global arbitrage of modeset resources across crtcs.
 
 Suggested-by: Mika Kuoppala mika.kuopp...@intel.com
 Cc: Mika Kuoppala mika.kuopp...@intel.com
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch

This is already in with a IS_GEN7()

-- 
Damien
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 13/24] drm/i915: kill lpt pch transcoder-crtc mapping code for fifo underruns

2013-06-12 Thread Paulo Zanoni
2013/6/12 Daniel Vetter daniel.vet...@ffwll.ch:
 It's racy: There's no guarantee that we won't walk this code (due to a
 pch fifo underrun interrupt) while someone is changing the pointers
 around.

 The only reason we do this is to use the righ crtc for the pch fifo
 underrun accounting. But we never expose this to userspace, so
 essentially no one really cares if we use the wrong crtc.

 So let's just rip it out.

 With this patch fifo underrun code will always use crtc A for tracking
 underruns on the (only) pch transcoder on LPT.

Please add a big comment in the source code explaining the hack and its reason.


 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
 ---
  drivers/gpu/drm/i915/i915_irq.c | 33 +++--
  1 file changed, 7 insertions(+), 26 deletions(-)

 diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
 index bb26555..b98ea4e 100644
 --- a/drivers/gpu/drm/i915/i915_irq.c
 +++ b/drivers/gpu/drm/i915/i915_irq.c
 @@ -193,13 +193,13 @@ static void ibx_display_interrupt_update(struct 
 drm_i915_private *dev_priv,
 POSTING_READ(SDEIMR);
  }

 -static void ibx_set_fifo_underrun_reporting(struct intel_crtc *crtc,
 +static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
 +   enum transcoder pch_transcoder,
 bool enable)
  {
 -   struct drm_device *dev = crtc-base.dev;
 struct drm_i915_private *dev_priv = dev-dev_private;
 -   uint32_t bit = (crtc-pipe == PIPE_A) ? SDE_TRANSA_FIFO_UNDER :
 -   SDE_TRANSB_FIFO_UNDER;
 +   uint32_t bit = (pch_transcoder == TRANSCODER_A) ?
 +  SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;

 ibx_display_interrupt_update(dev_priv, bit,
  enable ? bit : 0);
 @@ -292,30 +292,11 @@ bool intel_set_pch_fifo_underrun_reporting(struct 
 drm_device *dev,
bool enable)
  {
 struct drm_i915_private *dev_priv = dev-dev_private;
 -   enum pipe p;
 -   struct drm_crtc *crtc;
 -   struct intel_crtc *intel_crtc;
 +   struct drm_crtc *crtc = 
 dev_priv-pipe_to_crtc_mapping[pch_transcoder];
 +   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 unsigned long flags;
 bool ret;

 -   if (HAS_PCH_LPT(dev)) {
 -   crtc = NULL;
 -   for_each_pipe(p) {
 -   struct drm_crtc *c = 
 dev_priv-pipe_to_crtc_mapping[p];
 -   if (intel_pipe_has_type(c, INTEL_OUTPUT_ANALOG)) {
 -   crtc = c;
 -   break;
 -   }
 -   }
 -   if (!crtc) {
 -   DRM_ERROR(PCH FIFO underrun, but no CRTC using the 
 PCH found\n);
 -   return false;
 -   }
 -   } else {
 -   crtc = dev_priv-pipe_to_crtc_mapping[pch_transcoder];
 -   }
 -   intel_crtc = to_intel_crtc(crtc);
 -
 spin_lock_irqsave(dev_priv-irq_lock, flags);

 ret = !intel_crtc-pch_fifo_underrun_disabled;
 @@ -326,7 +307,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct 
 drm_device *dev,
 intel_crtc-pch_fifo_underrun_disabled = !enable;

 if (HAS_PCH_IBX(dev))
 -   ibx_set_fifo_underrun_reporting(intel_crtc, enable);
 +   ibx_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
 else
 cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable);

 --
 1.8.1.4

 ___
 Intel-gfx mailing list
 Intel-gfx@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Paulo Zanoni
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 14/31] drm/i915: display pll hw state readout and checking

2013-06-12 Thread Damien Lespiau
On Wed, Jun 05, 2013 at 01:34:16PM +0200, Daniel Vetter wrote:
 Currently still with an empty register state, this will follow in a
 next step. This one here just creates the new vfunc and uses it for
 cross-checking, initial state takeover and the dpll assert function.
 
 And add a FIXME for the ddi pll readout code, which still needs to be
 converted over.
 
 v2:
 - Add some hw state readout debug output.
 - Also cross check the enabled crtc counting.
 
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
 ---
  drivers/gpu/drm/i915/i915_drv.h  |  7 
  drivers/gpu/drm/i915/intel_display.c | 77 
 +---
  2 files changed, 79 insertions(+), 5 deletions(-)
 
 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
 index 8e61128..f23b033 100644
 --- a/drivers/gpu/drm/i915/i915_drv.h
 +++ b/drivers/gpu/drm/i915/i915_drv.h
 @@ -143,6 +143,9 @@ enum intel_dpll_id {
  };
  #define I915_NUM_PLLS 2
  
 +struct intel_dpll_hw_state {
 +};
 +
  struct intel_shared_dpll {
   int refcount; /* count of number of CRTCs sharing this PLL */
   int active; /* count of number of active CRTCs (i.e. DPMS on) */
 @@ -150,10 +153,14 @@ struct intel_shared_dpll {
   const char *name;
   /* should match the index in the dev_priv-shared_dplls array */
   enum intel_dpll_id id;
 + struct intel_dpll_hw_state hw_state;
   void (*enable)(struct drm_i915_private *dev_priv,
  struct intel_shared_dpll *pll);
   void (*disable)(struct drm_i915_private *dev_priv,
   struct intel_shared_dpll *pll);
 + bool (*get_hw_state)(struct drm_i915_private *dev_priv,
 +  struct intel_shared_dpll *pll,
 +  struct intel_dpll_hw_state *hw_state);
  };
  
  /* Used by dp and fdi links */
 diff --git a/drivers/gpu/drm/i915/intel_display.c 
 b/drivers/gpu/drm/i915/intel_display.c
 index ea4b7a6..998ba5c 100644
 --- a/drivers/gpu/drm/i915/intel_display.c
 +++ b/drivers/gpu/drm/i915/intel_display.c
 @@ -907,8 +907,8 @@ static void assert_shared_dpll(struct drm_i915_private 
 *dev_priv,
  struct intel_shared_dpll *pll,
  bool state)
  {
 - u32 val;
   bool cur_state;
 + struct intel_dpll_hw_state hw_state;
  
   if (HAS_PCH_LPT(dev_priv-dev)) {
   DRM_DEBUG_DRIVER(LPT detected: skipping PCH PLL test\n);
 @@ -919,11 +919,10 @@ static void assert_shared_dpll(struct drm_i915_private 
 *dev_priv,
 asserting DPLL %s with no DPLL\n, state_string(state)))
   return;
  
 - val = I915_READ(PCH_DPLL(pll-id));
 - cur_state = !!(val  DPLL_VCO_ENABLE);
 + cur_state = pll-get_hw_state(dev_priv, pll, hw_state);
   WARN(cur_state != state,
 -  %s assertion failure (expected %s, current %s), val=%08x\n,
 -  pll-name, state_string(state), state_string(cur_state), val);
 +  %s assertion failure (expected %s, current %s)\n,
 +  pll-name, state_string(state), state_string(cur_state));
  }
  #define assert_shared_dpll_enabled(d, p) assert_shared_dpll(d, p, true)
  #define assert_shared_dpll_disabled(d, p) assert_shared_dpll(d, p, false)
 @@ -8071,6 +8070,8 @@ intel_modeset_check_state(struct drm_device *dev)
   struct intel_encoder *encoder;
   struct intel_connector *connector;
   struct intel_crtc_config pipe_config;
 + struct intel_dpll_hw_state dpll_hw_state;
 + int i;
  
   list_for_each_entry(connector, dev-mode_config.connector_list,
   base.head) {
 @@ -8183,6 +8184,41 @@ intel_modeset_check_state(struct drm_device *dev)
  [sw state]);
   }
   }
 +
 + for (i = 0; i  dev_priv-num_shared_dpll; i++) {
 + struct intel_shared_dpll *pll = dev_priv-shared_dplls[i];
 + int enabled_crtcs = 0, active_crtcs = 0;
 + bool active;
 +
 + memset(dpll_hw_state, 0, sizeof(dpll_hw_state));
 +
 + DRM_DEBUG_KMS(%s\n, pll-name);
 +
 + active = pll-get_hw_state(dev_priv, pll, dpll_hw_state);
 +
 + WARN(pll-active  pll-refcount,
 +  more active pll users than references: %i vs %i\n,
 +  pll-active, pll-refcount);
 + WARN(pll-active  !pll-on,
 +  pll in active use but not on in sw tracking\n);
 + WARN(pll-on != active,
 +  pll on state mismatch (expected %i, found %i)\n,
 +  pll-on, active);
 +
 + list_for_each_entry(crtc, dev-mode_config.crtc_list,
 + base.head) {
 + if (crtc-base.enabled  
 intel_crtc_to_shared_dpll(crtc) == pll)
 + enabled_crtcs++;
 + if (crtc-active  intel_crtc_to_shared_dpll(crtc) == 
 pll)
 + 

Re: [Intel-gfx] [PATCH 15/31] drm/i915: extract readout_hw_state from setup_hw_state

2013-06-12 Thread Damien Lespiau
On Wed, Jun 05, 2013 at 01:34:17PM +0200, Daniel Vetter wrote:
 Simply grew too big. This also makes the fixup and restore logic in
 setup_hw_state stand out a bit more clearly.
 
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch

Reviewed-by: Damien Lespiau damien.lesp...@intel.com

-- 
Damien

 ---
  drivers/gpu/drm/i915/intel_display.c | 20 +++-
  1 file changed, 15 insertions(+), 5 deletions(-)
 
 diff --git a/drivers/gpu/drm/i915/intel_display.c 
 b/drivers/gpu/drm/i915/intel_display.c
 index 998ba5c..95ed27b 100644
 --- a/drivers/gpu/drm/i915/intel_display.c
 +++ b/drivers/gpu/drm/i915/intel_display.c
 @@ -9630,14 +9630,10 @@ void i915_redisable_vga(struct drm_device *dev)
   }
  }
  
 -/* Scan out the current hw modeset state, sanitizes it and maps it into the 
 drm
 - * and i915 state tracking structures. */
 -void intel_modeset_setup_hw_state(struct drm_device *dev,
 -   bool force_restore)
 +static void intel_modeset_readout_hw_state(struct drm_device *dev)
  {
   struct drm_i915_private *dev_priv = dev-dev_private;
   enum pipe pipe;
 - struct drm_plane *plane;
   struct intel_crtc *crtc;
   struct intel_encoder *encoder;
   struct intel_connector *connector;
 @@ -9713,6 +9709,20 @@ void intel_modeset_setup_hw_state(struct drm_device 
 *dev,
 drm_get_connector_name(connector-base),
 connector-base.encoder ? enabled : disabled);
   }
 +}
 +
 +/* Scan out the current hw modeset state, sanitizes it and maps it into the 
 drm
 + * and i915 state tracking structures. */
 +void intel_modeset_setup_hw_state(struct drm_device *dev,
 +   bool force_restore)
 +{
 + struct drm_i915_private *dev_priv = dev-dev_private;
 + enum pipe pipe;
 + struct drm_plane *plane;
 + struct intel_crtc *crtc;
 + struct intel_encoder *encoder;
 +
 + intel_modeset_readout_hw_state(dev);
  
   /* HW state is read out, now we need to sanitize this mess. */
   list_for_each_entry(encoder, dev-mode_config.encoder_list,
 -- 
 1.7.11.7
 
 ___
 Intel-gfx mailing list
 Intel-gfx@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/intel-gfx
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 16/31] drm/i915: split up intel_modeset_check_state

2013-06-12 Thread Damien Lespiau
On Wed, Jun 05, 2013 at 01:34:18PM +0200, Daniel Vetter wrote:
 Simply grew too large and neede to be split up into parts.
 
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch

Reviewed-by: Damien Lespiau damien.lesp...@intel.com

-- 
Damien

 ---
  drivers/gpu/drm/i915/intel_display.c | 44 
 +---
  1 file changed, 36 insertions(+), 8 deletions(-)
 
 diff --git a/drivers/gpu/drm/i915/intel_display.c 
 b/drivers/gpu/drm/i915/intel_display.c
 index 95ed27b..c42b87b 100644
 --- a/drivers/gpu/drm/i915/intel_display.c
 +++ b/drivers/gpu/drm/i915/intel_display.c
 @@ -8062,16 +8062,10 @@ intel_pipe_config_compare(struct drm_device *dev,
   return true;
  }
  
 -void
 -intel_modeset_check_state(struct drm_device *dev)
 +static void
 +check_connector_state(struct drm_device *dev)
  {
 - drm_i915_private_t *dev_priv = dev-dev_private;
 - struct intel_crtc *crtc;
 - struct intel_encoder *encoder;
   struct intel_connector *connector;
 - struct intel_crtc_config pipe_config;
 - struct intel_dpll_hw_state dpll_hw_state;
 - int i;
  
   list_for_each_entry(connector, dev-mode_config.connector_list,
   base.head) {
 @@ -8082,6 +8076,13 @@ intel_modeset_check_state(struct drm_device *dev)
   WARN(connector-new_encoder-base != connector-base.encoder,
connector's staged encoder doesn't match current 
 encoder\n);
   }
 +}
 +
 +static void
 +check_encoder_state(struct drm_device *dev)
 +{
 + struct intel_encoder *encoder;
 + struct intel_connector *connector;
  
   list_for_each_entry(encoder, dev-mode_config.encoder_list,
   base.head) {
 @@ -8133,6 +8134,15 @@ intel_modeset_check_state(struct drm_device *dev)
tracked_pipe, pipe);
  
   }
 +}
 +
 +static void
 +check_crtc_state(struct drm_device *dev)
 +{
 + drm_i915_private_t *dev_priv = dev-dev_private;
 + struct intel_crtc *crtc;
 + struct intel_encoder *encoder;
 + struct intel_crtc_config pipe_config;
  
   list_for_each_entry(crtc, dev-mode_config.crtc_list,
   base.head) {
 @@ -8184,6 +8194,15 @@ intel_modeset_check_state(struct drm_device *dev)
  [sw state]);
   }
   }
 +}
 +
 +static void
 +check_shared_dpll_state(struct drm_device *dev)
 +{
 + drm_i915_private_t *dev_priv = dev-dev_private;
 + struct intel_crtc *crtc;
 + struct intel_dpll_hw_state dpll_hw_state;
 + int i;
  
   for (i = 0; i  dev_priv-num_shared_dpll; i++) {
   struct intel_shared_dpll *pll = dev_priv-shared_dplls[i];
 @@ -8221,6 +8240,15 @@ intel_modeset_check_state(struct drm_device *dev)
   }
  }
  
 +void
 +intel_modeset_check_state(struct drm_device *dev)
 +{
 + check_connector_state(dev);
 + check_encoder_state(dev);
 + check_crtc_state(dev);
 + check_shared_dpll_state(dev);
 +}
 +
  static int __intel_set_mode(struct drm_crtc *crtc,
   struct drm_display_mode *mode,
   int x, int y, struct drm_framebuffer *fb)
 -- 
 1.7.11.7
 
 ___
 Intel-gfx mailing list
 Intel-gfx@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/intel-gfx
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 17/31] drm/i915: WARN on lack of shared dpll

2013-06-12 Thread Damien Lespiau
On Wed, Jun 05, 2013 at 01:34:19PM +0200, Daniel Vetter wrote:
 Now that we have proper hw state reconstruction we should never have a
 case where we don't have the software dpll state properly set up. So
 add WARNs to the respective !pll cases in enable/disabel_shared_dpll.
 
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch

Reviewed-by: Damien Lespiau damien.lesp...@intel.com

-- 
Damien

 ---
  drivers/gpu/drm/i915/intel_display.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/gpu/drm/i915/intel_display.c 
 b/drivers/gpu/drm/i915/intel_display.c
 index c42b87b..388ac54 100644
 --- a/drivers/gpu/drm/i915/intel_display.c
 +++ b/drivers/gpu/drm/i915/intel_display.c
 @@ -1371,7 +1371,7 @@ static void ironlake_enable_shared_dpll(struct 
 intel_crtc *crtc)
  
   /* PCH PLLs only available on ILK, SNB and IVB */
   BUG_ON(dev_priv-info-gen  5);
 - if (pll == NULL)
 + if (WARN_ON(pll == NULL))
   return;
  
   if (WARN_ON(pll-refcount == 0))
 @@ -1399,7 +1399,7 @@ static void intel_disable_shared_dpll(struct intel_crtc 
 *crtc)
  
   /* PCH only available on ILK+ */
   BUG_ON(dev_priv-info-gen  5);
 - if (pll == NULL)
 + if (WARN_ON(pll == NULL))
  return;
  
   if (WARN_ON(pll-refcount == 0))
 -- 
 1.7.11.7
 
 ___
 Intel-gfx mailing list
 Intel-gfx@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/intel-gfx
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 14/31] drm/i915: display pll hw state readout and checking

2013-06-12 Thread Ville Syrjälä
On Wed, Jun 12, 2013 at 02:31:23PM +0100, Damien Lespiau wrote:
 On Wed, Jun 05, 2013 at 01:34:16PM +0200, Daniel Vetter wrote:
  @@ -8621,6 +8657,17 @@ static void intel_cpu_pll_init(struct drm_device 
  *dev)
  intel_ddi_pll_init(dev);
   }
   
  +static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
  + struct intel_shared_dpll *pll,
  + struct intel_dpll_hw_state *hw_state)
  +{
  +   uint32_t val;
  +
  +   val = I915_READ(PCH_DPLL(pll-id));
  +
  +   return val  DPLL_VCO_ENABLE;
  +}
  +
 
 Don't we want !!(val  DPLL_VCO_ENABLE) here? we're comparing this to 0
 and 1.

bool is always 0 or 1.

-- 
Ville Syrjälä
Intel OTC
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 14/31] drm/i915: display pll hw state readout and checking

2013-06-12 Thread Damien Lespiau
On Wed, Jun 12, 2013 at 04:39:14PM +0300, Ville Syrjälä wrote:
 On Wed, Jun 12, 2013 at 02:31:23PM +0100, Damien Lespiau wrote:
  On Wed, Jun 05, 2013 at 01:34:16PM +0200, Daniel Vetter wrote:
   @@ -8621,6 +8657,17 @@ static void intel_cpu_pll_init(struct drm_device 
   *dev)
 intel_ddi_pll_init(dev);
}

   +static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
   +   struct intel_shared_dpll *pll,
   +   struct intel_dpll_hw_state *hw_state)
   +{
   + uint32_t val;
   +
   + val = I915_READ(PCH_DPLL(pll-id));
   +
   + return val  DPLL_VCO_ENABLE;
   +}
   +
  
  Don't we want !!(val  DPLL_VCO_ENABLE) here? we're comparing this to 0
  and 1.
 
 bool is always 0 or 1.

Oh, of course!

Reviewed-by: Damien Lespiau damien.lesp...@intel.com

then.

-- 
Damien
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 04/24] drm/i915: s/hotplug_irq_storm_detect/intel_hpd_irq_handler/

2013-06-12 Thread Egbert Eich
Daniel Vetter writes:
  The combination of Paulo's fifo underrun detection code and Egbert's
  hpd storm handling code unfortunately made the hpd storm handling code
  racy.
  
  To avoid duplicating tricky interrupt locking code over all platforms
  start with a bit of refactoring. This patch is the very first step
  since in the end the irq storm handling code will handle all hotplug
  logic (and so also encapsulate the locking nicely).
  
  Cc: Egbert Eich e...@suse.de
  Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
  ---
   drivers/gpu/drm/i915/i915_irq.c | 16 
   1 file changed, 8 insertions(+), 8 deletions(-)
  

[reviewed code deleted]

Reviewed-by: Egbert Eich e...@suse.de
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 15/31] drm/i915: extract readout_hw_state from setup_hw_state

2013-06-12 Thread Daniel Vetter
On Wed, Jun 05, 2013 at 01:34:17PM +0200, Daniel Vetter wrote:
 Simply grew too big. This also makes the fixup and restore logic in
 setup_hw_state stand out a bit more clearly.
 
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch

So I've managed to massively botch up patch ordering here, due to the lack
of refcount rescostruction but the fact that we already have hw state
readout for the pll selection we hit a bunch of WARNs in the crtc disable
path.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=65673

Damien, can you please take a good hard look at just this patch so that we
can shut up the WARNs?

Thanks, Daniel

 ---
  drivers/gpu/drm/i915/intel_display.c | 20 +++-
  1 file changed, 15 insertions(+), 5 deletions(-)
 
 diff --git a/drivers/gpu/drm/i915/intel_display.c 
 b/drivers/gpu/drm/i915/intel_display.c
 index 998ba5c..95ed27b 100644
 --- a/drivers/gpu/drm/i915/intel_display.c
 +++ b/drivers/gpu/drm/i915/intel_display.c
 @@ -9630,14 +9630,10 @@ void i915_redisable_vga(struct drm_device *dev)
   }
  }
  
 -/* Scan out the current hw modeset state, sanitizes it and maps it into the 
 drm
 - * and i915 state tracking structures. */
 -void intel_modeset_setup_hw_state(struct drm_device *dev,
 -   bool force_restore)
 +static void intel_modeset_readout_hw_state(struct drm_device *dev)
  {
   struct drm_i915_private *dev_priv = dev-dev_private;
   enum pipe pipe;
 - struct drm_plane *plane;
   struct intel_crtc *crtc;
   struct intel_encoder *encoder;
   struct intel_connector *connector;
 @@ -9713,6 +9709,20 @@ void intel_modeset_setup_hw_state(struct drm_device 
 *dev,
 drm_get_connector_name(connector-base),
 connector-base.encoder ? enabled : disabled);
   }
 +}
 +
 +/* Scan out the current hw modeset state, sanitizes it and maps it into the 
 drm
 + * and i915 state tracking structures. */
 +void intel_modeset_setup_hw_state(struct drm_device *dev,
 +   bool force_restore)
 +{
 + struct drm_i915_private *dev_priv = dev-dev_private;
 + enum pipe pipe;
 + struct drm_plane *plane;
 + struct intel_crtc *crtc;
 + struct intel_encoder *encoder;
 +
 + intel_modeset_readout_hw_state(dev);
  
   /* HW state is read out, now we need to sanitize this mess. */
   list_for_each_entry(encoder, dev-mode_config.encoder_list,
 -- 
 1.7.11.7
 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 06/24] drm/i915: fold the queue_work into intel_hpd_irq_handler

2013-06-12 Thread Egbert Eich
Daniel Vetter writes:
  Everywhere the same.
  
  Cc: Egbert Eich e...@suse.de
  Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
  ---
   drivers/gpu/drm/i915/i915_irq.c | 11 +++
   1 file changed, 3 insertions(+), 8 deletions(-)

[reviewed code deleted]

Reviewed-by: Egbert Eich e...@suse.de
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH] drm/i915: kill lpt pch transcoder-crtc mapping code for fifo underruns

2013-06-12 Thread Daniel Vetter
It's racy: There's no guarantee that we won't walk this code (due to a
pch fifo underrun interrupt) while someone is changing the pointers
around.

The only reason we do this is to use the righ crtc for the pch fifo
underrun accounting. But we never expose this to userspace, so
essentially no one really cares if we use the wrong crtc.

So let's just rip it out.

With this patch fifo underrun code will always use crtc A for tracking
underruns on the (only) pch transcoder on LPT.

v2: Add a big comment explaining what's going on. Requested by Paulo.

Cc: Paulo Zanoni przan...@gmail.com
Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
---
 drivers/gpu/drm/i915/i915_irq.c | 40 +++-
 1 file changed, 15 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index bb26555..e80c610 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -193,13 +193,13 @@ static void ibx_display_interrupt_update(struct 
drm_i915_private *dev_priv,
POSTING_READ(SDEIMR);
 }
 
-static void ibx_set_fifo_underrun_reporting(struct intel_crtc *crtc,
+static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
+   enum transcoder pch_transcoder,
bool enable)
 {
-   struct drm_device *dev = crtc-base.dev;
struct drm_i915_private *dev_priv = dev-dev_private;
-   uint32_t bit = (crtc-pipe == PIPE_A) ? SDE_TRANSA_FIFO_UNDER :
-   SDE_TRANSB_FIFO_UNDER;
+   uint32_t bit = (pch_transcoder == TRANSCODER_A) ?
+  SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
 
ibx_display_interrupt_update(dev_priv, bit,
 enable ? bit : 0);
@@ -292,29 +292,19 @@ bool intel_set_pch_fifo_underrun_reporting(struct 
drm_device *dev,
   bool enable)
 {
struct drm_i915_private *dev_priv = dev-dev_private;
-   enum pipe p;
-   struct drm_crtc *crtc;
-   struct intel_crtc *intel_crtc;
+   struct drm_crtc *crtc = dev_priv-pipe_to_crtc_mapping[pch_transcoder];
+   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
unsigned long flags;
bool ret;
 
-   if (HAS_PCH_LPT(dev)) {
-   crtc = NULL;
-   for_each_pipe(p) {
-   struct drm_crtc *c = dev_priv-pipe_to_crtc_mapping[p];
-   if (intel_pipe_has_type(c, INTEL_OUTPUT_ANALOG)) {
-   crtc = c;
-   break;
-   }
-   }
-   if (!crtc) {
-   DRM_ERROR(PCH FIFO underrun, but no CRTC using the PCH 
found\n);
-   return false;
-   }
-   } else {
-   crtc = dev_priv-pipe_to_crtc_mapping[pch_transcoder];
-   }
-   intel_crtc = to_intel_crtc(crtc);
+   /*
+* NOTE: Pre-LPT has a fixed cpu pipe - pch transcoder mapping, but LPT
+* has has only one pch transcoder A that all pipes can use. To avoid
+* racy pch transcoder - pipe lookups from interrupt code simply store
+* the underrun statistics in crtc A. Since we never expose this
+* anywhere nor use it outside of the fifo underrun code here using the
+* wrong crtc on LPT won't cause issues.
+*/
 
spin_lock_irqsave(dev_priv-irq_lock, flags);
 
@@ -326,7 +316,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct 
drm_device *dev,
intel_crtc-pch_fifo_underrun_disabled = !enable;
 
if (HAS_PCH_IBX(dev))
-   ibx_set_fifo_underrun_reporting(intel_crtc, enable);
+   ibx_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
else
cpt_set_fifo_underrun_reporting(dev, pch_transcoder, enable);
 
-- 
1.8.1.4

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH] drm/i915: disable sdvo pixel multiplier cross-check for HAS_PCH_SPLIT

2013-06-12 Thread Daniel Vetter
On Wed, Jun 12, 2013 at 11:47:24AM +0200, Daniel Vetter wrote:
 We don't (yet) have proper pixel multiplier readout support on pch
 split platforms, so the cross check will naturally fail.
 
 v2: Fix spelling in the comment, spotted by Ville.
 
 v3: Since the ordering constraint is pretty tricky between the crtc
 get_pipe_config callback and the encoder-get_config callback add a
 few comments about it. Prompted by a discussion with Chris Wilson on
 irc about why this does work anywhere else than on i915g/gm.
 
 Reported-by: Chris Wilson ch...@chris-wilson.co.uk
 Cc: Chris Wilson ch...@chris-wilson.co.uk
 Cc: Ville Syrjälä ville.syrj...@linux.intel.com
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch

Merged with Chris' irc-ack to dinq.
-Daniel

 ---
  drivers/gpu/drm/i915/intel_drv.h  |  3 ++-
  drivers/gpu/drm/i915/intel_sdvo.c | 11 +++
  2 files changed, 13 insertions(+), 1 deletion(-)
 
 diff --git a/drivers/gpu/drm/i915/intel_drv.h 
 b/drivers/gpu/drm/i915/intel_drv.h
 index 3363358..cf26fa8 100644
 --- a/drivers/gpu/drm/i915/intel_drv.h
 +++ b/drivers/gpu/drm/i915/intel_drv.h
 @@ -140,7 +140,8 @@ struct intel_encoder {
* it is connected to in the pipe parameter. */
   bool (*get_hw_state)(struct intel_encoder *, enum pipe *pipe);
   /* Reconstructs the equivalent mode flags for the current hardware
 -  * state. */
 +  * state. This must be called _after_ display-get_pipe_config has
 +  * pre-filled the pipe config. */
   void (*get_config)(struct intel_encoder *,
  struct intel_crtc_config *pipe_config);
   int crtc_mask;
 diff --git a/drivers/gpu/drm/i915/intel_sdvo.c 
 b/drivers/gpu/drm/i915/intel_sdvo.c
 index a6c53b6..1327fa9 100644
 --- a/drivers/gpu/drm/i915/intel_sdvo.c
 +++ b/drivers/gpu/drm/i915/intel_sdvo.c
 @@ -1342,6 +1342,13 @@ static void intel_sdvo_get_config(struct intel_encoder 
 *encoder,
  
   pipe_config-adjusted_mode.flags |= flags;
  
 + /*
 +  * pixel multiplier readout is tricky: Only on i915g/gm it is stored in
 +  * the sdvo port register, on all other platforms it is part of the dpll
 +  * state. Since the general pipe state readout happens before the
 +  * encoder-get_config we so already have a valid pixel multplier on all
 +  * other platfroms.
 +  */
   if (IS_I915G(dev) || IS_I915GM(dev)) {
   sdvox = I915_READ(intel_sdvo-sdvo_reg);
   pipe_config-pixel_multiplier =
 @@ -1362,6 +1369,10 @@ static void intel_sdvo_get_config(struct intel_encoder 
 *encoder,
   encoder_pixel_multiplier = 4;
   break;
   }
 +
 + if(HAS_PCH_SPLIT(dev))
 + return; /* no pixel multiplier readout support yet */
 +
   WARN(encoder_pixel_multiplier != pipe_config-pixel_multiplier,
SDVO pixel multiplier mismatch, port: %i, encoder: %i\n,
pipe_config-pixel_multiplier, encoder_pixel_multiplier);
 -- 
 1.7.11.7
 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 08/24] drm/i915: fix hpd interrupt register locking

2013-06-12 Thread Egbert Eich
Daniel Vetter writes:
  Our interrupt handler (in hardird context) could race with the timer
  Nitpick: s/d/q/

  (in softirq context), hence we need to hold the spinlock around the
  call to -hdp_irq_setup in intel_hpd_irq_handler, too.
  
  But as an optimization (and more so to clarify things) we don't need
  to do the irqsave/restore dance in the hardirq context.
  
  Note also that on ilk+ the race isn't just against the hotplug
  reenable timer, but also against the fifo underrun reporting. That one
  also modifies the SDEIMR register (again protected by the same
  dev_priv-irq_lock).
  
  To lock things down again sprinkle a assert_spin_locked. But exclude
  the functions touching SDEIMR for now, I want to extract them all into
  a new helper function (like we do already for pipestate, display
  interrupts and all the various gt interrupts).
  
  Cc: Egbert Eich e...@suse.de
  Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
  ---
   drivers/gpu/drm/i915/i915_irq.c | 15 ++-
   1 file changed, 10 insertions(+), 5 deletions(-)
  
  diff --git a/drivers/gpu/drm/i915/i915_irq.c 
  b/drivers/gpu/drm/i915/i915_irq.c
  index 1815891..95e15cd 100644
  --- a/drivers/gpu/drm/i915/i915_irq.c
  +++ b/drivers/gpu/drm/i915/i915_irq.c
  @@ -880,15 +880,13 @@ static inline void intel_hpd_irq_handler(struct 
  drm_device *dev,
const u32 *hpd)
   {
   drm_i915_private_t *dev_priv = dev-dev_private;
  -unsigned long irqflags;
   int i;
   bool storm_detected = false;
   
   if (!hotplug_trigger)
   return;
   
  -spin_lock_irqsave(dev_priv-irq_lock, irqflags);
  -
  +spin_lock(dev_priv-irq_lock);
   for (i = 1; i  HPD_NUM_PINS; i++) {
   
   if (!(hpd[i]  hotplug_trigger) ||
  @@ -911,10 +909,9 @@ static inline void intel_hpd_irq_handler(struct 
  drm_device *dev,
   }
   }
   
  -spin_unlock_irqrestore(dev_priv-irq_lock, irqflags);
  -
   if (storm_detected)
   dev_priv-display.hpd_irq_setup(dev);
  +spin_unlock(dev_priv-irq_lock);
   
   queue_work(dev_priv-wq,
  dev_priv-hotplug_work);
  @@ -3327,6 +3324,8 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
   struct intel_encoder *intel_encoder;
   u32 hotplug_en;
   
  +assert_spin_locked(dev_priv-irq_lock);
  +
   if (I915_HAS_HOTPLUG(dev)) {
   hotplug_en = I915_READ(PORT_HOTPLUG_EN);
   hotplug_en = ~HOTPLUG_INT_EN_MASK;


Didn't you want to do the same for ibx_hpd_irq_setup() ?

  @@ -3610,6 +3609,7 @@ void intel_hpd_init(struct drm_device *dev)
   struct drm_i915_private *dev_priv = dev-dev_private;
   struct drm_mode_config *mode_config = dev-mode_config;
   struct drm_connector *connector;
  +unsigned long irqflags;
   int i;
   
   for (i = 1; i  HPD_NUM_PINS; i++) {
  @@ -3622,6 +3622,11 @@ void intel_hpd_init(struct drm_device *dev)
   if (!connector-polled  I915_HAS_HOTPLUG(dev)  
  intel_connector-encoder-hpd_pin  HPD_NONE)
   connector-polled = DRM_CONNECTOR_POLL_HPD;
   }
  +
  +/* Interrup setup is already guaranteed to be single-threaded, this is

Nitpick -  missed a 't'.

  + * just to make the assert_spin_locked checks happy. */
  +spin_lock_irqsave(dev_priv-irq_lock, irqflags);
   if (dev_priv-display.hpd_irq_setup)
   dev_priv-display.hpd_irq_setup(dev);
  +spin_unlock_irqrestore(dev_priv-irq_lock, irqflags);
   }
  -- 
  1.8.1.4
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 18/31] drm/i915: hw state readout and cross-checking for shared dplls

2013-06-12 Thread Damien Lespiau
On Wed, Jun 05, 2013 at 01:34:20PM +0200, Daniel Vetter wrote:
 Just the plumbing, all the modeset and enable code has not yet been
 switched over to use the new state. It seems to be decently broken
 anyway, at least wrt to handling of the special pixel mutliplier
 enabling sequence. Follow-up patches will clean up that mess.
 
 Another missing piece is more careful handling (and fixup) of the fp1
 alternate divisor state. The BIOS most likely doesn't bother to
 program that one to what we expect. So we need to be more careful with
 comparing that state, both for cross checking but also when checking
 for dpll sharing when acquiring shared dpll. Otherwise fastboot will
 deny a few shared dpll configurations which would otherwise work.
 
 v2: We need to memcpy the pipe config dpll hw state into the pll, for
 otherwise the cross-check code will get angry.
 
 v3: Don't forget to read the pch pll state in the crtc get_pipe_config
 function for ibx/ilk platforms.
 
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch

Reviewed-by: Damien Lespiau damien.lesp...@intel.com

-- 
Damien

 ---
  drivers/gpu/drm/i915/i915_drv.h  |  3 +++
  drivers/gpu/drm/i915/intel_display.c | 38 
 
  drivers/gpu/drm/i915/intel_drv.h |  3 +++
  3 files changed, 44 insertions(+)
 
 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
 index f23b033..4dc94ed 100644
 --- a/drivers/gpu/drm/i915/i915_drv.h
 +++ b/drivers/gpu/drm/i915/i915_drv.h
 @@ -144,6 +144,9 @@ enum intel_dpll_id {
  #define I915_NUM_PLLS 2
  
  struct intel_dpll_hw_state {
 + uint32_t dpll;
 + uint32_t fp0;
 + uint32_t fp1;
  };
  
  struct intel_shared_dpll {
 diff --git a/drivers/gpu/drm/i915/intel_display.c 
 b/drivers/gpu/drm/i915/intel_display.c
 index 388ac54..a30e27a 100644
 --- a/drivers/gpu/drm/i915/intel_display.c
 +++ b/drivers/gpu/drm/i915/intel_display.c
 @@ -3055,7 +3055,11 @@ found:
   crtc-config.shared_dpll = i;
   DRM_DEBUG_DRIVER(using %s for pipe %c\n, pll-name,
pipe_name(crtc-pipe));
 +
   if (pll-active == 0) {
 + memcpy(pll-hw_state, crtc-config.dpll_hw_state,
 +sizeof(pll-hw_state));
 +
   DRM_DEBUG_DRIVER(setting up %s\n, pll-name);
   WARN_ON(pll-on);
   assert_shared_dpll_disabled(dev_priv, pll);
 @@ -5659,6 +5663,13 @@ static int ironlake_crtc_mode_set(struct drm_crtc 
 *crtc,
fp, reduced_clock,
has_reduced_clock ? fp2 : NULL);
  
 + intel_crtc-config.dpll_hw_state.dpll = dpll | DPLL_VCO_ENABLE;
 + intel_crtc-config.dpll_hw_state.fp0 = fp;
 + if (has_reduced_clock)
 + intel_crtc-config.dpll_hw_state.fp1 = fp2;
 + else
 + intel_crtc-config.dpll_hw_state.fp1 = fp;
 +
   pll = intel_get_shared_dpll(intel_crtc, dpll, fp);
   if (pll == NULL) {
   DRM_DEBUG_DRIVER(failed to find PLL for pipe %c\n,
 @@ -5778,6 +5789,8 @@ static bool ironlake_get_pipe_config(struct intel_crtc 
 *crtc,
   return false;
  
   if (I915_READ(PCH_TRANSCONF(crtc-pipe))  TRANS_ENABLE) {
 + struct intel_shared_dpll *pll;
 +
   pipe_config-has_pch_encoder = true;
  
   tmp = I915_READ(FDI_RX_CTL(crtc-pipe));
 @@ -5799,6 +5812,11 @@ static bool ironlake_get_pipe_config(struct intel_crtc 
 *crtc,
   else
   pipe_config-shared_dpll = DPLL_ID_PCH_PLL_A;
   }
 +
 + pll = dev_priv-shared_dplls[pipe_config-shared_dpll];
 +
 + WARN_ON(!pll-get_hw_state(dev_priv, pll,
 +pipe_config-dpll_hw_state));
   } else {
   pipe_config-pixel_multiplier = 1;
   }
 @@ -7987,6 +8005,15 @@ intel_pipe_config_compare(struct drm_device *dev,
 struct intel_crtc_config *current_config,
 struct intel_crtc_config *pipe_config)
  {
 +#define PIPE_CONF_CHECK_X(name)  \
 + if (current_config-name != pipe_config-name) { \
 + DRM_ERROR(mismatch in  #name   \
 +   (expected 0x%08x, found 0x%08x)\n, \
 +   current_config-name, \
 +   pipe_config-name); \
 + return false; \
 + }
 +
  #define PIPE_CONF_CHECK_I(name)  \
   if (current_config-name != pipe_config-name) { \
   DRM_ERROR(mismatch in  #name   \
 @@ -8055,7 +8082,11 @@ intel_pipe_config_compare(struct drm_device *dev,
   PIPE_CONF_CHECK_I(ips_enabled);
  
   PIPE_CONF_CHECK_I(shared_dpll);
 + PIPE_CONF_CHECK_X(dpll_hw_state.dpll);
 + PIPE_CONF_CHECK_X(dpll_hw_state.fp0);
 + PIPE_CONF_CHECK_X(dpll_hw_state.fp1);
  
 +#undef PIPE_CONF_CHECK_X
  #undef PIPE_CONF_CHECK_I
  #undef 

Re: [Intel-gfx] [PATCH 05/24] drm/i915: fold the hpd_irq_setup call into intel_hpd_irq_handler

2013-06-12 Thread Daniel Vetter
On Wed, Jun 12, 2013 at 4:26 PM, Egbert Eich e...@suse.com wrote:
 Daniel Vetter writes:
   We already have a vfunc for this (and other parts of the hpd storm
   handling code already use it).
  
   Cc: Egbert Eich e...@suse.de
   Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
   ---
drivers/gpu/drm/i915/i915_irq.c | 29 +++--
1 file changed, 11 insertions(+), 18 deletions(-)
  

 [ reviewed code deleted ]

 Reviewed-by: Egbert Eich e...@suse.de

Readd intel-gfx so I don't miss the r-b tag.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 08/24] drm/i915: fix hpd interrupt register locking

2013-06-12 Thread Daniel Vetter
On Wed, Jun 12, 2013 at 4:59 PM, Egbert Eich e...@suse.com wrote:
   +assert_spin_locked(dev_priv-irq_lock);
   +
if (I915_HAS_HOTPLUG(dev)) {
hotplug_en = I915_READ(PORT_HOTPLUG_EN);
hotplug_en = ~HOTPLUG_INT_EN_MASK;


 Didn't you want to do the same for ibx_hpd_irq_setup() ?

Will happen in a follow-up patch, since I first consolidate all access
to SDEIMR into one single helper function. I've tried to explain that
a bit in the commit message but failed to make the connection to
ibx_hpd_irq_setup - once we have the helper function the
assert_spin_locked is in there and so ibx_hpd_irq_setup doesn't need
its own check (since it won't touch SDEIMR directly any more).
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 19/31] drm/i915: fix up pch pll enabling for pixel multipliers

2013-06-12 Thread Damien Lespiau
On Wed, Jun 05, 2013 at 01:34:21PM +0200, Daniel Vetter wrote:
 We have a nice comment saying that the pixel multiplier only sticks
 once the vco is on and stable. The only problem is that the enable bit
 wasn't set at all. This patch fixes this and so brings the ilk+ pch
 pll code in line with the i8xx/i9xx pll code. Or at least improves
 matters a lot.
 
 This should fix sdvo on ilk-ivb for low-res modes.
 
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch

Reviewed-by: Damien Lespiau damien.lesp...@intel.com

-- 
Damien

 ---
  drivers/gpu/drm/i915/intel_display.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/drivers/gpu/drm/i915/intel_display.c 
 b/drivers/gpu/drm/i915/intel_display.c
 index a30e27a..ecf0b1e 100644
 --- a/drivers/gpu/drm/i915/intel_display.c
 +++ b/drivers/gpu/drm/i915/intel_display.c
 @@ -5601,7 +5601,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc 
 *intel_crtc,
   else
   dpll |= PLL_REF_INPUT_DREFCLK;
  
 - return dpll;
 + return dpll | DPLL_VCO_ENABLE;
  }
  
  static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 @@ -5663,7 +5663,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
fp, reduced_clock,
has_reduced_clock ? fp2 : NULL);
  
 - intel_crtc-config.dpll_hw_state.dpll = dpll | DPLL_VCO_ENABLE;
 + intel_crtc-config.dpll_hw_state.dpll = dpll;
   intel_crtc-config.dpll_hw_state.fp0 = fp;
   if (has_reduced_clock)
   intel_crtc-config.dpll_hw_state.fp1 = fp2;
 -- 
 1.7.11.7
 
 ___
 Intel-gfx mailing list
 Intel-gfx@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/intel-gfx
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 22/31] drm/i915: use sw tracked state to select shared dplls

2013-06-12 Thread Damien Lespiau
On Wed, Jun 05, 2013 at 01:34:24PM +0200, Daniel Vetter wrote:
 Just yet another prep step to be able to do all this up-front, before
 we've set up any of the shared dplls in the new state. This will
 eventually be useful for atomic modesetting.
 
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch

Reviewed-by: Damien Lespiau damien.lesp...@intel.com

-- 
Damien

 ---
  drivers/gpu/drm/i915/intel_display.c | 8 
  1 file changed, 4 insertions(+), 4 deletions(-)
 
 diff --git a/drivers/gpu/drm/i915/intel_display.c 
 b/drivers/gpu/drm/i915/intel_display.c
 index 334f86a..4d2284e 100644
 --- a/drivers/gpu/drm/i915/intel_display.c
 +++ b/drivers/gpu/drm/i915/intel_display.c
 @@ -2999,7 +2999,7 @@ static void intel_put_shared_dpll(struct intel_crtc 
 *crtc)
   crtc-config.shared_dpll = DPLL_ID_NONE;
  }
  
 -static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc 
 *crtc, u32 dpll, u32 fp)
 +static struct intel_shared_dpll *intel_get_shared_dpll(struct intel_crtc 
 *crtc)
  {
   struct drm_i915_private *dev_priv = crtc-base.dev-dev_private;
   struct intel_shared_dpll *pll = intel_crtc_to_shared_dpll(crtc);
 @@ -3029,8 +3029,8 @@ static struct intel_shared_dpll 
 *intel_get_shared_dpll(struct intel_crtc *crtc,
   if (pll-refcount == 0)
   continue;
  
 - if (dpll == (I915_READ(PCH_DPLL(pll-id))  0x7fff) 
 - fp == I915_READ(PCH_FP0(pll-id))) {
 + if (memcmp(crtc-config.dpll_hw_state, pll-hw_state,
 +sizeof(pll-hw_state)) == 0) {
   DRM_DEBUG_KMS(CRTC:%d sharing existing %s (refcount 
 %d, ative %d)\n,
 crtc-base.base.id,
 pll-name, pll-refcount, pll-active);
 @@ -5660,7 +5660,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
   else
   intel_crtc-config.dpll_hw_state.fp1 = fp;
  
 - pll = intel_get_shared_dpll(intel_crtc, dpll, fp);
 + pll = intel_get_shared_dpll(intel_crtc);
   if (pll == NULL) {
   DRM_DEBUG_DRIVER(failed to find PLL for pipe %c\n,
pipe_name(pipe));
 -- 
 1.7.11.7
 
 ___
 Intel-gfx mailing list
 Intel-gfx@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/intel-gfx
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 05/24] drm/i915: fold the hpd_irq_setup call into intel_hpd_irq_handler

2013-06-12 Thread Egbert Eich
Daniel Vetter writes:
  We already have a vfunc for this (and other parts of the hpd storm
  handling code already use it).
  
  Cc: Egbert Eich e...@suse.de
  Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
  ---
   drivers/gpu/drm/i915/i915_irq.c | 29 +++--
   1 file changed, 11 insertions(+), 18 deletions(-)
  

[ reviewed code deleted ]

Reviewed-by: Egbert Eich e...@suse.de


___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 0/6] Enable PC8+ states

2013-06-12 Thread Daniel Vetter
On Wed, Jun 05, 2013 at 02:21:50PM -0300, Paulo Zanoni wrote:
 From: Paulo Zanoni paulo.r.zan...@intel.com
 
 Hi
 
 So this series is a second version of the patch I sent on April 16th. Daniel
 asked to write some patches to properly initialize the interrupts we're 
 touching
 on the PC8+ patches, so the first 5 patches should do this.
 
 The 6th patch is the big one enabling PC8+ and even though I still didn't
 address all of Daniel's concerns from his first review, the patch already 
 works:
 we get into PC10 and when we get back to PC7 things are still working.

Ok, so real review now, not just function name bikeshedding ;-)

* I'd really like to see a testcase, but not per se to exercise pc8+ but
  to check that our prepare/exit code and especially the interrupt
  disabling/enabling doesn't break anything. So the overall structure of
  the test should probably be something like

  1. Put the console into raw mode (so that fbcon doesn't interfere),
  Imre's recent infrastructure patches should make this really simple.

  2. Disable all outputs with setcrtc(fb=NULL).

  3. Wait a bit until we're sure that our code has prepared for pc8+, i.e.
  all the interrupts are shut off, lcpll is disabled ...

  4. Run a subtest.

  5. Repeat.

  For subtests we need quite a pile of them I think:
  - Test getconnectors ioctl to make sure both our -detec and -get_modes
callbacks have the proper aux_display runtime pm get/put calls. On a
quick read through your patch the get/put (currently still call
forbid/allow) in the -get_modes hooks seem to be missing.
  - Direct i2c access from userspace. This happens both from random tools
probing the i2c bus, but also for real uses-cases, like the ddccontrol
tool or e.g. the Chromebook Pixie which uses gmbus as the hw i2c
engine for the touchpad.
  - Submit a patch (this might just work when waking the gt automatically
wakes up everything) _and_ do a blocking wait for it (this will break
if interrupts are dead).

  It's probably good to have some correctness checks for these, e.g.
  compare the edid property while outputs are still on (so pc8+ is
  impossible) with what happens when they're off. Execbuf could be tested
  with a simple fill blt. Imo it's also important that we have a wait
  before each new subtest, to make sure we really teste everything. E.g. a
  subtest only checks EDID for one output, then waits again. Otherwise it
  could be that the working refcounting in e.g. HDMI could shadow broken
  runtime pm refcounting for dp aux if it's done right afterwards.

* spin_lock_irqsave isn't that irq-save ;-) It only blocks interrupt on
  the local cpu. See Rusty's unreliable guide to kernel locking in
  Documentation/DocBook/kernel-locking. If you don't understand what
  spin_lock_irqsave is useful for, how our current locking works or why
  the one in your patch is broken I think we should discuss this
  afterwards. Reading my irq locking review patches and comparing it to
  the locking guid could also be interesting.

  I haven't yet done the full review, but probably the safest route is to
  fully disable our interrupt handler with disable_irq while we do the
  pc8+ prepare sequence. On the exit sequence we probably don't need it.
  In any case we can reenable interrupts again with enable_irq. Maybe
  there's a possible race there (I need to review the core irq code
  first), but now I think having a tiny race there where we could miss hpd
  events is less evil than adding complex locking just for pc8+ entry.
  Even more so with the next point, which aims to unify pc8+ entry/exit
  with our existing suspend/resume code. And s/r runs in a non-reentrant
  enviroment, so if we can keep those basic assumptions that's imo
  worthwile.

* Unifying irq setup/teardown code. I'm not really happy with the
  setup/teardown code, and I think we should take a good look at trying to
  unify it with the existing driver load/unload/suspend/resume code.
  Massive register save/restore code tends to get out of sync with other
  code changes way too easily.

  Currently our irq enable sequence is:
  1. call -irq_preinstall hook
  2. enable irq handler
  3. call -irq_postinstall hook
  and somewhen later
  4. enable hotplug interrupt handling with our own -hpd_irq_setup hook.

  The disabling sequence is:
  1. disable irq handler
  2. call -irq_uninstall hook

  Now for pc8+ we want to disable/enable almost everything _but_ the hpd
  interrupts. I think with some code wrestling we should be able to do
  that with the existing functions:
  - Split the irq_unistall into two parts, irq_unistall which disables all
interrupt sources _but_ hotplug, and a hpd_irq_teardown which disables
hotplug, too. For that we'd need an i915_irq_unistall functions which
first calls drm_irq_uninstall and the new -hpd_irq_teardown hook.
That would also allow us to unify the hotplug reenable timer teardown
a bit.
  - Rework -irq_postinstall and -irq_uninstall 

Re: [Intel-gfx] [PATCH 19/24] drm/i915: don't enable PM_VEBOX_CS_ERROR_INTERRUPT

2013-06-12 Thread Ben Widawsky
On Wed, Jun 12, 2013 at 01:37:21PM +0200, Daniel Vetter wrote:
 The code to handle it is broken - there's simply no code to clear CS
 parser errors on gen5+. And behold, for all the other rings we also
 don't enable it!
 
 Leave the handling code itself in place just to be consistent with the
 existing mess though. And in case someone feels like fixing it all up.
 
 This has been errornously enabled in
 
 commit 12638c57f31952127c734c26315e1348fa1334c2
 Author: Ben Widawsky b...@bwidawsk.net
 Date:   Tue May 28 19:22:31 2013 -0700
 
 drm/i915: Enable vebox interrupts
 
 Cc: Damien Lespiau damien.lesp...@intel.com
 Cc: Ben Widawsky b...@bwidawsk.net
 Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch

Why not fix the problem instead of just disabling the interrupt? Then
the existing mess is justified. It really shouldn't be terribly
difficult to fix it.

[snip]
-- 
Ben Widawsky, Intel Open Source Technology Center
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 19/24] drm/i915: don't enable PM_VEBOX_CS_ERROR_INTERRUPT

2013-06-12 Thread Daniel Vetter
On Wed, Jun 12, 2013 at 10:13:41AM -0700, Ben Widawsky wrote:
 On Wed, Jun 12, 2013 at 01:37:21PM +0200, Daniel Vetter wrote:
  The code to handle it is broken - there's simply no code to clear CS
  parser errors on gen5+. And behold, for all the other rings we also
  don't enable it!
  
  Leave the handling code itself in place just to be consistent with the
  existing mess though. And in case someone feels like fixing it all up.
  
  This has been errornously enabled in
  
  commit 12638c57f31952127c734c26315e1348fa1334c2
  Author: Ben Widawsky b...@bwidawsk.net
  Date:   Tue May 28 19:22:31 2013 -0700
  
  drm/i915: Enable vebox interrupts
  
  Cc: Damien Lespiau damien.lesp...@intel.com
  Cc: Ben Widawsky b...@bwidawsk.net
  Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
 
 Why not fix the problem instead of just disabling the interrupt? Then
 the existing mess is justified. It really shouldn't be terribly
 difficult to fix it.

Haven't seen it proven useful, and I don't want to blow through time just
for fun on it. Hangcheck seems to be able to deal with it just fine.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 19/24] drm/i915: don't enable PM_VEBOX_CS_ERROR_INTERRUPT

2013-06-12 Thread Ben Widawsky
On Wed, Jun 12, 2013 at 07:18:38PM +0200, Daniel Vetter wrote:
 On Wed, Jun 12, 2013 at 10:13:41AM -0700, Ben Widawsky wrote:
  On Wed, Jun 12, 2013 at 01:37:21PM +0200, Daniel Vetter wrote:
   The code to handle it is broken - there's simply no code to clear CS
   parser errors on gen5+. And behold, for all the other rings we also
   don't enable it!
   
   Leave the handling code itself in place just to be consistent with the
   existing mess though. And in case someone feels like fixing it all up.
   
   This has been errornously enabled in
   
   commit 12638c57f31952127c734c26315e1348fa1334c2
   Author: Ben Widawsky b...@bwidawsk.net
   Date:   Tue May 28 19:22:31 2013 -0700
   
   drm/i915: Enable vebox interrupts
   
   Cc: Damien Lespiau damien.lesp...@intel.com
   Cc: Ben Widawsky b...@bwidawsk.net
   Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
  
  Why not fix the problem instead of just disabling the interrupt? Then
  the existing mess is justified. It really shouldn't be terribly
  difficult to fix it.
 
 Haven't seen it proven useful, and I don't want to blow through time just
 for fun on it. Hangcheck seems to be able to deal with it just fine.
 -Daniel
I don't get it. Isn't it just clearing a bit in the handler, vs.
clearing the flag here?

 -- 
 Daniel Vetter
 Software Engineer, Intel Corporation
 +41 (0) 79 365 57 48 - http://blog.ffwll.ch
 ___
 Intel-gfx mailing list
 Intel-gfx@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Ben Widawsky, Intel Open Source Technology Center
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 19/24] drm/i915: don't enable PM_VEBOX_CS_ERROR_INTERRUPT

2013-06-12 Thread Daniel Vetter
On Wed, Jun 12, 2013 at 8:19 PM, Ben Widawsky b...@bwidawsk.net wrote:
 On Wed, Jun 12, 2013 at 07:18:38PM +0200, Daniel Vetter wrote:
 On Wed, Jun 12, 2013 at 10:13:41AM -0700, Ben Widawsky wrote:
  On Wed, Jun 12, 2013 at 01:37:21PM +0200, Daniel Vetter wrote:
   The code to handle it is broken - there's simply no code to clear CS
   parser errors on gen5+. And behold, for all the other rings we also
   don't enable it!
  
   Leave the handling code itself in place just to be consistent with the
   existing mess though. And in case someone feels like fixing it all up.
  
   This has been errornously enabled in
  
   commit 12638c57f31952127c734c26315e1348fa1334c2
   Author: Ben Widawsky b...@bwidawsk.net
   Date:   Tue May 28 19:22:31 2013 -0700
  
   drm/i915: Enable vebox interrupts
  
   Cc: Damien Lespiau damien.lesp...@intel.com
   Cc: Ben Widawsky b...@bwidawsk.net
   Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
  
  Why not fix the problem instead of just disabling the interrupt? Then
  the existing mess is justified. It really shouldn't be terribly
  difficult to fix it.

 Haven't seen it proven useful, and I don't want to blow through time just
 for fun on it. Hangcheck seems to be able to deal with it just fine.
 -Daniel
 I don't get it. Isn't it just clearing a bit in the handler, vs.
 clearing the flag here?

On a quick Bspec read we'd need to set up per-ring error interrupt
registers, put them to sensible value in them, wire up the interrupt
handling for each ring since ilk+ and then also test it. I really
don't see the point in doing that. The only upshot of all that work is
that if there's an instruction error we'd get an interrupt instead of
waiting for the hangcheck to kick in.

If you insist I can follow-up with a patch to just rip out the
bare-bones handler we have now. Everything else really feels like
wasted effort to me.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 19/24] drm/i915: don't enable PM_VEBOX_CS_ERROR_INTERRUPT

2013-06-12 Thread Ben Widawsky
On Wed, Jun 12, 2013 at 08:32:44PM +0200, Daniel Vetter wrote:
 On Wed, Jun 12, 2013 at 8:19 PM, Ben Widawsky b...@bwidawsk.net wrote:
  On Wed, Jun 12, 2013 at 07:18:38PM +0200, Daniel Vetter wrote:
  On Wed, Jun 12, 2013 at 10:13:41AM -0700, Ben Widawsky wrote:
   On Wed, Jun 12, 2013 at 01:37:21PM +0200, Daniel Vetter wrote:
The code to handle it is broken - there's simply no code to clear CS
parser errors on gen5+. And behold, for all the other rings we also
don't enable it!
   
Leave the handling code itself in place just to be consistent with the
existing mess though. And in case someone feels like fixing it all up.
   
This has been errornously enabled in
   
commit 12638c57f31952127c734c26315e1348fa1334c2
Author: Ben Widawsky b...@bwidawsk.net
Date:   Tue May 28 19:22:31 2013 -0700
   
drm/i915: Enable vebox interrupts
   
Cc: Damien Lespiau damien.lesp...@intel.com
Cc: Ben Widawsky b...@bwidawsk.net
Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
   
   Why not fix the problem instead of just disabling the interrupt? Then
   the existing mess is justified. It really shouldn't be terribly
   difficult to fix it.
 
  Haven't seen it proven useful, and I don't want to blow through time just
  for fun on it. Hangcheck seems to be able to deal with it just fine.
  -Daniel
  I don't get it. Isn't it just clearing a bit in the handler, vs.
  clearing the flag here?
 
 On a quick Bspec read we'd need to set up per-ring error interrupt
 registers, put them to sensible value in them, wire up the interrupt
 handling for each ring since ilk+ and then also test it. I really
 don't see the point in doing that. The only upshot of all that work is
 that if there's an instruction error we'd get an interrupt instead of
 waiting for the hangcheck to kick in.
 
 If you insist I can follow-up with a patch to just rip out the
 bare-bones handler we have now. Everything else really feels like
 wasted effort to me.
 -Daniel

No. I don't insist. I was just thinking these kind of error interrupts
should be always on, like L3 parity. But that is indeed more than just
clearing a bit (though not THAT much).

-- 
Ben Widawsky, Intel Open Source Technology Center
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH v2] drm/i915: Try harder to disable trickle feed on VLV

2013-06-12 Thread ville . syrjala
From: Ville Syrjälä ville.syrj...@linux.intel.com

The specs are a bit unclear whether the per-plane trickle feed disable
control exists on VLV. There is another trickle feed disable control
in the MI_ARB register.

After some experimentation it turns out both the DSPCNTR trickle feed
bits and the MI_ARB bit can be toggled. However the DSPCNTR bits don't
seem to have any effect.

The MI_ARB bit, on the other hand, has a noticable effect. I performed
an experiment where I reduced the FIFO size via DSPARB and observed the
effect of the MI_ARB trickle feed bit on the display.

Using a 1920x1080-60 mode, with MI_ARB=0x4 the display started to have
problems with DSPARB=0x42424242, whereas with MI_ARB=0x0 the problems
didn't start until DSPARB=0x09090909. This seems to confirm that the
MI_ARB trickle feed bit actually does work.

So replace the use of the DSPCNTR trickle feed bits with MI_ARB
on VLV.

v2: Amend commit message with results from experimentation

Signed-off-by: Ville Syrjälä ville.syrj...@linux.intel.com
---
 drivers/gpu/drm/i915/i915_reg.h | 2 ++
 drivers/gpu/drm/i915/intel_pm.c | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index cd37ca4..9cb6236 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1372,6 +1372,8 @@
 #define FW_BLC_SELF_VLV(VLV_DISPLAY_BASE + 0x6500)
 #define  FW_CSPWRDWNEN (115)
 
+#define MI_ARB_VLV (VLV_DISPLAY_BASE + 0x6504)
+
 /*
  * Palette regs
  */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index adc44e4..b27bda0 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -4873,7 +4873,7 @@ static void valleyview_init_clock_gating(struct 
drm_device *dev)
 
I915_WRITE(GEN7_UCGCTL4, GEN7_L3BANK2X_CLOCK_GATE_DISABLE);
 
-   g4x_disable_trickle_feed(dev);
+   I915_WRITE(MI_ARB_VLV, MI_ARB_DISPLAY_TRICKLE_FEED_DISABLE);
 
I915_WRITE(CACHE_MODE_1,
   _MASKED_BIT_ENABLE(PIXEL_SUBSPAN_COLLECT_OPT_DISABLE));
-- 
1.8.1.5

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 5/9] drm/i915: pnv dpll doesn't use m1!

2013-06-12 Thread Daniel Vetter
On Wed, Jun 12, 2013 at 12:38:40AM +0100, Damien Lespiau wrote:
 On Tue, May 21, 2013 at 09:54:55PM +0200, Daniel Vetter wrote:
  So don't try to store it in the DPLL_FP register.
  
  Otherwise it looks like the limits for pineview are correct: It has
  it's own clock computation code, which doesn't use an offset for n
  divisors, and the register value based m limits look sane enough.
 
   - n can vary between 2 and 6, but we declare the 3-6 as limits.
   - p1 seems to be able to go up to 9
   - the m upper limit seems a bit big, but the docs are a bit shy on
 that values for pnv.
 
 Otherwise, the change itself seems good:

Quoted in the commit message and merged the patch.

 Reviewed-by: Damien Lespiau damien.lesp...@intel.com

Thanks for the review, Daniel

 
  
  v2: Rebase on top of the pineview clock refactor and fixup up the
  commit message: It's m1 pnv doens't care about, not m2!
  
  Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
  ---
   drivers/gpu/drm/i915/intel_display.c | 2 +-
   1 file changed, 1 insertion(+), 1 deletion(-)
  
  diff --git a/drivers/gpu/drm/i915/intel_display.c 
  b/drivers/gpu/drm/i915/intel_display.c
  index cb54131..520e340 100644
  --- a/drivers/gpu/drm/i915/intel_display.c
  +++ b/drivers/gpu/drm/i915/intel_display.c
  @@ -4300,7 +4300,7 @@ static int i9xx_get_refclk(struct drm_crtc *crtc, int 
  num_connectors)
   
   static uint32_t pnv_dpll_compute_fp(struct dpll *dpll)
   {
  -   return (1  dpll-n)  16 | dpll-m1  8 | dpll-m2;
  +   return (1  dpll-n)  16 | dpll-m2;
   }
   
   static uint32_t i9xx_dpll_compute_fp(struct dpll *dpll)
  -- 
  1.7.11.7
  
  ___
  Intel-gfx mailing list
  Intel-gfx@lists.freedesktop.org
  http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 19/31] drm/i915: fix up pch pll enabling for pixel multipliers

2013-06-12 Thread Daniel Vetter
On Wed, Jun 12, 2013 at 04:12:48PM +0100, Damien Lespiau wrote:
 On Wed, Jun 05, 2013 at 01:34:21PM +0200, Daniel Vetter wrote:
  We have a nice comment saying that the pixel multiplier only sticks
  once the vco is on and stable. The only problem is that the enable bit
  wasn't set at all. This patch fixes this and so brings the ilk+ pch
  pll code in line with the i8xx/i9xx pll code. Or at least improves
  matters a lot.
  
  This should fix sdvo on ilk-ivb for low-res modes.
  
  Signed-off-by: Daniel Vetter daniel.vet...@ffwll.ch
 
 Reviewed-by: Damien Lespiau damien.lesp...@intel.com

Merged thus far, thanks a lot for the review.
-Daniel

 
 -- 
 Damien
 
  ---
   drivers/gpu/drm/i915/intel_display.c | 4 ++--
   1 file changed, 2 insertions(+), 2 deletions(-)
  
  diff --git a/drivers/gpu/drm/i915/intel_display.c 
  b/drivers/gpu/drm/i915/intel_display.c
  index a30e27a..ecf0b1e 100644
  --- a/drivers/gpu/drm/i915/intel_display.c
  +++ b/drivers/gpu/drm/i915/intel_display.c
  @@ -5601,7 +5601,7 @@ static uint32_t ironlake_compute_dpll(struct 
  intel_crtc *intel_crtc,
  else
  dpll |= PLL_REF_INPUT_DREFCLK;
   
  -   return dpll;
  +   return dpll | DPLL_VCO_ENABLE;
   }
   
   static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
  @@ -5663,7 +5663,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc 
  *crtc,
   fp, reduced_clock,
   has_reduced_clock ? fp2 : NULL);
   
  -   intel_crtc-config.dpll_hw_state.dpll = dpll | DPLL_VCO_ENABLE;
  +   intel_crtc-config.dpll_hw_state.dpll = dpll;
  intel_crtc-config.dpll_hw_state.fp0 = fp;
  if (has_reduced_clock)
  intel_crtc-config.dpll_hw_state.fp1 = fp2;
  -- 
  1.7.11.7
  
  ___
  Intel-gfx mailing list
  Intel-gfx@lists.freedesktop.org
  http://lists.freedesktop.org/mailman/listinfo/intel-gfx

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 0/8] Don't let the ghost eDP haunt us

2013-06-12 Thread Paulo Zanoni
From: Paulo Zanoni paulo.r.zan...@intel.com

Hi

This week I sent a patch called drm/i915: propagate errors from
intel_dp_init_connector to fix a Haswell bug that was preventing my machine
from booting. Chris provided a nice suggestion for it, so this series should
implement his suggestion, but split in a few patches. While writing this code I
also spotted a few other things, so there are some patches for them here. Patch
3 is the real bug fix and patches 4  5 implement Chris's suggestions. Patch 1
is another bug fix and patches 2, 6, 7  8 are my bikesheds for the current
code.

Thanks,
Paulo

Paulo Zanoni (8):
  drm/i915: don't check encoder at DP connector destroy()
  drm/i915: extract intel_edp_init_connector
  drm/i915: propagate errors from intel_dp_init_connector
  drm/i915: fix the ghost eDP connector unwind path
  drm/i915: fix the ghost eDP encoder unwind path
  drm/i915: check the return value of intel_dp_i2c_init
  drm/i915: invert the verbosity of intel_enable_fbc
  drm/i915: rename intel_dp_destroy to intel_dp_connector_destroy

 drivers/gpu/drm/i915/intel_ddi.c |   7 +-
 drivers/gpu/drm/i915/intel_dp.c  | 180 +++
 drivers/gpu/drm/i915/intel_drv.h |   2 +-
 drivers/gpu/drm/i915/intel_pm.c  |   3 +-
 4 files changed, 113 insertions(+), 79 deletions(-)

-- 
1.8.1.2

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 1/8] drm/i915: don't check encoder at DP connector destroy()

2013-06-12 Thread Paulo Zanoni
From: Paulo Zanoni paulo.r.zan...@intel.com

By the time we call intel_dp_destroy (which destroys the connector)
the encoder may have been destroyed already, so if we use it we may be
reading some free memory. That happens in drm_mode_config_cleanup()
and also inside intel_dp_init_connector() when we detect a ghost eDP.

I also hope this may solve some random memory bugs.

Reported-by kmemcheck.
Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com
---
 drivers/gpu/drm/i915/intel_dp.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 6d56075..dbfb32d 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2683,13 +2683,14 @@ done:
 static void
 intel_dp_destroy(struct drm_connector *connector)
 {
-   struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_connector *intel_connector = to_intel_connector(connector);
 
if (!IS_ERR_OR_NULL(intel_connector-edid))
kfree(intel_connector-edid);
 
-   if (is_edp(intel_dp))
+   /* Can't call is_edp() since the encoder may have been destroyed
+* already. */
+   if (connector-connector_type == DRM_MODE_CONNECTOR_eDP)
intel_panel_fini(intel_connector-panel);
 
drm_sysfs_connector_remove(connector);
-- 
1.8.1.2

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 3/8] drm/i915: propagate errors from intel_dp_init_connector

2013-06-12 Thread Paulo Zanoni
From: Paulo Zanoni paulo.r.zan...@intel.com

In case we detect a ghost eDP, intel_edp_init_connector frees both
the connector and encoder and then returns. On Haswell, intel_ddi_init
then tries to use the freed encoder on the HDMI initialization path
since the following commit:

commit 21a8e6a4853b2ed39fa4c5188a710f2cf1b92026
Author: Daniel Vetter daniel.vet...@ffwll.ch
Date:   Wed Apr 10 23:28:35 2013 +0200
drm/i915: don't setup hdmi for port D edp in ddi_init

So now on intel_ddi_init we check for the ghost eDP case and return
without trying to initialize HDMI. This way we won't try to read the
freed intel_encoder struct in the next if statement.

Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com
---
 drivers/gpu/drm/i915/intel_ddi.c | 3 ++-
 drivers/gpu/drm/i915/intel_dp.c  | 6 --
 drivers/gpu/drm/i915/intel_drv.h | 2 +-
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 224ce25..0f835d1 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1356,7 +1356,8 @@ void intel_ddi_init(struct drm_device *dev, enum port 
port)
intel_encoder-cloneable = false;
intel_encoder-hot_plug = intel_ddi_hot_plug;
 
-   intel_dp_init_connector(intel_dig_port, dp_connector);
+   if (!intel_dp_init_connector(intel_dig_port, dp_connector))
+   return;
 
if (intel_encoder-type != INTEL_OUTPUT_EDP) {
hdmi_connector = kzalloc(sizeof(struct intel_connector),
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 90b01f5..46b3e3b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3035,7 +3035,7 @@ static bool intel_edp_init_connector(struct intel_dp 
*intel_dp,
return true;
 }
 
-void
+bool
 intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector)
 {
@@ -3147,7 +3147,7 @@ intel_dp_init_connector(struct intel_digital_port 
*intel_dig_port,
intel_dp_i2c_init(intel_dp, intel_connector, name);
 
if (!intel_edp_init_connector(intel_dp, intel_connector))
-   return;
+   return false;
 
intel_dp_add_properties(intel_dp, connector);
 
@@ -3159,6 +3159,8 @@ intel_dp_init_connector(struct intel_digital_port 
*intel_dig_port,
u32 temp = I915_READ(PEG_BAND_GAP_DATA);
I915_WRITE(PEG_BAND_GAP_DATA, (temp  ~0xf) | 0xd);
}
+
+   return true;
 }
 
 void
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 02e5d65..d100bee 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -586,7 +586,7 @@ extern bool intel_lvds_init(struct drm_device *dev);
 extern bool intel_is_dual_link_lvds(struct drm_device *dev);
 extern void intel_dp_init(struct drm_device *dev, int output_reg,
  enum port port);
-extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
+extern bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector);
 extern void intel_dp_init_link_config(struct intel_dp *intel_dp);
 extern void intel_dp_start_link_train(struct intel_dp *intel_dp);
-- 
1.8.1.2

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 2/8] drm/i915: extract intel_edp_init_connector

2013-06-12 Thread Paulo Zanoni
From: Paulo Zanoni paulo.r.zan...@intel.com

Because intel_dp_init_connector is too big for my poor little brain.
No functional changes.

Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com
---
 drivers/gpu/drm/i915/intel_dp.c | 151 ++--
 1 file changed, 82 insertions(+), 69 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index dbfb32d..90b01f5 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2955,6 +2955,86 @@ intel_dp_init_panel_power_sequencer_registers(struct 
drm_device *dev,
  I915_READ(pp_div_reg));
 }
 
+static bool intel_edp_init_connector(struct intel_dp *intel_dp,
+struct intel_connector *intel_connector)
+{
+   struct drm_connector *connector = intel_connector-base;
+   struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
+   struct drm_device *dev = intel_dig_port-base.base.dev;
+   struct drm_i915_private *dev_priv = dev-dev_private;
+   struct drm_display_mode *fixed_mode = NULL;
+   struct edp_power_seq power_seq = { 0 };
+   bool has_dpcd;
+   struct drm_display_mode *scan;
+   struct edid *edid;
+
+   if (!is_edp(intel_dp))
+   return true;
+
+   intel_dp_init_panel_power_sequencer(dev, intel_dp, power_seq);
+
+   /* Cache DPCD and EDID for edp. */
+   ironlake_edp_panel_vdd_on(intel_dp);
+   has_dpcd = intel_dp_get_dpcd(intel_dp);
+   ironlake_edp_panel_vdd_off(intel_dp, false);
+
+   if (has_dpcd) {
+   if (intel_dp-dpcd[DP_DPCD_REV] = 0x11)
+   dev_priv-no_aux_handshake =
+   intel_dp-dpcd[DP_MAX_DOWNSPREAD] 
+   DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
+   } else {
+   /* if this fails, presume the device is a ghost */
+   DRM_INFO(failed to retrieve link info, disabling eDP\n);
+   intel_dp_encoder_destroy(intel_dig_port-base.base);
+   intel_dp_destroy(connector);
+   return false;
+   }
+
+   /* We now know it's not a ghost, init power sequence regs. */
+   intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+ power_seq);
+
+   ironlake_edp_panel_vdd_on(intel_dp);
+   edid = drm_get_edid(connector, intel_dp-adapter);
+   if (edid) {
+   if (drm_add_edid_modes(connector, edid)) {
+   drm_mode_connector_update_edid_property(connector,
+   edid);
+   drm_edid_to_eld(connector, edid);
+   } else {
+   kfree(edid);
+   edid = ERR_PTR(-EINVAL);
+   }
+   } else {
+   edid = ERR_PTR(-ENOENT);
+   }
+   intel_connector-edid = edid;
+
+   /* prefer fixed mode from EDID if available */
+   list_for_each_entry(scan, connector-probed_modes, head) {
+   if ((scan-type  DRM_MODE_TYPE_PREFERRED)) {
+   fixed_mode = drm_mode_duplicate(dev, scan);
+   break;
+   }
+   }
+
+   /* fallback to VBT if available for eDP */
+   if (!fixed_mode  dev_priv-vbt.lfp_lvds_vbt_mode) {
+   fixed_mode = drm_mode_duplicate(dev,
+   dev_priv-vbt.lfp_lvds_vbt_mode);
+   if (fixed_mode)
+   fixed_mode-type |= DRM_MODE_TYPE_PREFERRED;
+   }
+
+   ironlake_edp_panel_vdd_off(intel_dp, false);
+
+   intel_panel_init(intel_connector-panel, fixed_mode);
+   intel_panel_setup_backlight(connector);
+
+   return true;
+}
+
 void
 intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector)
@@ -2964,8 +3044,6 @@ intel_dp_init_connector(struct intel_digital_port 
*intel_dig_port,
struct intel_encoder *intel_encoder = intel_dig_port-base;
struct drm_device *dev = intel_encoder-base.dev;
struct drm_i915_private *dev_priv = dev-dev_private;
-   struct drm_display_mode *fixed_mode = NULL;
-   struct edp_power_seq power_seq = { 0 };
enum port port = intel_dig_port-port;
const char *name = NULL;
int type;
@@ -3066,75 +3144,10 @@ intel_dp_init_connector(struct intel_digital_port 
*intel_dig_port,
BUG();
}
 
-   if (is_edp(intel_dp))
-   intel_dp_init_panel_power_sequencer(dev, intel_dp, power_seq);
-
intel_dp_i2c_init(intel_dp, intel_connector, name);
 
-   /* Cache DPCD and EDID for edp. */
-   if (is_edp(intel_dp)) {
-   bool ret;
-   struct drm_display_mode *scan;
-   struct edid *edid;
-
-   ironlake_edp_panel_vdd_on(intel_dp);
-

[Intel-gfx] [PATCH 5/8] drm/i915: fix the ghost eDP encoder unwind path

2013-06-12 Thread Paulo Zanoni
From: Paulo Zanoni paulo.r.zan...@intel.com

Because calling intel_dp_encoder_destroy inside
intel_edp_init_connector is just wrong. This is the initialization
path, so we should properly unwind all the initialization through the
whole caller stack.

On the intel_dp_encoder_destroy function we do the following:
1 - Call i2c_del_adapter
2 - Call drm_encoder_cleanup
3 - If edp:
3.1 - Cancel panel_vdd_work
3.2 - Call ironlake_panel_vdd_of_sync
4 - Free the encoder

And here is how we unwind each specific step:
1 - We have intel_dp_init_connector - intel_dp_i2c_init -
i2c_dp_aux_add_bus - i2c_add_adapter, so we call
i2c_del_dapter at intel_dp_init_connector
2 - Call it in the same function that called drm_encoder_init
3 - Call it in the same function that called INIT_DELAYED_WORK
4 - Free it in the same function that allocated it

Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com
---
 drivers/gpu/drm/i915/intel_ddi.c |  2 ++
 drivers/gpu/drm/i915/intel_dp.c  | 13 +++--
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index aed363c..324211a 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1357,6 +1357,8 @@ void intel_ddi_init(struct drm_device *dev, enum port 
port)
intel_encoder-hot_plug = intel_ddi_hot_plug;
 
if (!intel_dp_init_connector(intel_dig_port, dp_connector)) {
+   drm_encoder_cleanup(encoder);
+   kfree(intel_dig_port);
kfree(dp_connector);
return;
}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index da7460c..b311eaf 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2986,7 +2986,6 @@ static bool intel_edp_init_connector(struct intel_dp 
*intel_dp,
} else {
/* if this fails, presume the device is a ghost */
DRM_INFO(failed to retrieve link info, disabling eDP\n);
-   intel_dp_encoder_destroy(intel_dig_port-base.base);
return false;
}
 
@@ -3146,6 +3145,13 @@ intel_dp_init_connector(struct intel_digital_port 
*intel_dig_port,
intel_dp_i2c_init(intel_dp, intel_connector, name);
 
if (!intel_edp_init_connector(intel_dp, intel_connector)) {
+   i2c_del_adapter(intel_dp-adapter);
+   if (is_edp(intel_dp)) {
+   cancel_delayed_work_sync(intel_dp-panel_vdd_work);
+   mutex_lock(dev-mode_config.mutex);
+   ironlake_panel_vdd_off_sync(intel_dp);
+   mutex_unlock(dev-mode_config.mutex);
+   }
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
return false;
@@ -3208,6 +3214,9 @@ intel_dp_init(struct drm_device *dev, int output_reg, 
enum port port)
intel_encoder-cloneable = false;
intel_encoder-hot_plug = intel_dp_hot_plug;
 
-   if (!intel_dp_init_connector(intel_dig_port, intel_connector))
+   if (!intel_dp_init_connector(intel_dig_port, intel_connector)) {
+   drm_encoder_cleanup(encoder);
+   kfree(intel_dig_port);
kfree(intel_connector);
+   }
 }
-- 
1.8.1.2

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 4/8] drm/i915: fix the ghost eDP connector unwind path

2013-06-12 Thread Paulo Zanoni
From: Paulo Zanoni paulo.r.zan...@intel.com

Because calling intel_dp_destroy inside intel_edp_init_connector is
just wrong. This is the initialization path, so we should properly
unwind all the initialization through the whole caller stack.

On the intel_dp_destroy function we do the following:
1 - Free edid if it exists
2 - Call intel_panel_fini in case it's eDP
3 - Call drm_sysfs_connector_remove
4 - Call drm_connector_cleanup
5 - Free the connector

And here is how we unwind each specific step:
1 - No need as we still didn't assign anything
2 - No need as we still didn't call intel_panel_init
3 - Call it in the same function that called drm_sysfs_connector_add
4 - Call it in the same function that called drm_connector_init
5 - Free it in the same function that allocated it

Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com
---
 drivers/gpu/drm/i915/intel_ddi.c | 4 +++-
 drivers/gpu/drm/i915/intel_dp.c  | 9 ++---
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 0f835d1..aed363c 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1356,8 +1356,10 @@ void intel_ddi_init(struct drm_device *dev, enum port 
port)
intel_encoder-cloneable = false;
intel_encoder-hot_plug = intel_ddi_hot_plug;
 
-   if (!intel_dp_init_connector(intel_dig_port, dp_connector))
+   if (!intel_dp_init_connector(intel_dig_port, dp_connector)) {
+   kfree(dp_connector);
return;
+   }
 
if (intel_encoder-type != INTEL_OUTPUT_EDP) {
hdmi_connector = kzalloc(sizeof(struct intel_connector),
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 46b3e3b..da7460c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2987,7 +2987,6 @@ static bool intel_edp_init_connector(struct intel_dp 
*intel_dp,
/* if this fails, presume the device is a ghost */
DRM_INFO(failed to retrieve link info, disabling eDP\n);
intel_dp_encoder_destroy(intel_dig_port-base.base);
-   intel_dp_destroy(connector);
return false;
}
 
@@ -3146,8 +3145,11 @@ intel_dp_init_connector(struct intel_digital_port 
*intel_dig_port,
 
intel_dp_i2c_init(intel_dp, intel_connector, name);
 
-   if (!intel_edp_init_connector(intel_dp, intel_connector))
+   if (!intel_edp_init_connector(intel_dp, intel_connector)) {
+   drm_sysfs_connector_remove(connector);
+   drm_connector_cleanup(connector);
return false;
+   }
 
intel_dp_add_properties(intel_dp, connector);
 
@@ -3206,5 +3208,6 @@ intel_dp_init(struct drm_device *dev, int output_reg, 
enum port port)
intel_encoder-cloneable = false;
intel_encoder-hot_plug = intel_dp_hot_plug;
 
-   intel_dp_init_connector(intel_dig_port, intel_connector);
+   if (!intel_dp_init_connector(intel_dig_port, intel_connector))
+   kfree(intel_connector);
 }
-- 
1.8.1.2

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 6/8] drm/i915: check the return value of intel_dp_i2c_init

2013-06-12 Thread Paulo Zanoni
From: Paulo Zanoni paulo.r.zan...@intel.com

We've been ignoring this return value, so print a nice backtrace in
case it's not what we expected.

Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com
---
 drivers/gpu/drm/i915/intel_dp.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index b311eaf..89e30ec 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3044,7 +3044,7 @@ intel_dp_init_connector(struct intel_digital_port 
*intel_dig_port,
struct drm_i915_private *dev_priv = dev-dev_private;
enum port port = intel_dig_port-port;
const char *name = NULL;
-   int type;
+   int type, error;
 
/* Preserve the current hw state. */
intel_dp-DP = I915_READ(intel_dp-output_reg);
@@ -3142,7 +3142,9 @@ intel_dp_init_connector(struct intel_digital_port 
*intel_dig_port,
BUG();
}
 
-   intel_dp_i2c_init(intel_dp, intel_connector, name);
+   error = intel_dp_i2c_init(intel_dp, intel_connector, name);
+   WARN(error, intel_dp_i2c_init failed with error %d for port %c\n,
+error, port_name(port));
 
if (!intel_edp_init_connector(intel_dp, intel_connector)) {
i2c_del_adapter(intel_dp-adapter);
-- 
1.8.1.2

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 7/8] drm/i915: invert the verbosity of intel_enable_fbc

2013-06-12 Thread Paulo Zanoni
From: Paulo Zanoni paulo.r.zan...@intel.com

We currently print a DRM_DEBUG_KMS message on the happy path and don't
print anything on the failed to allocate path. On some desktop
environments (e.g., Unity) I see the scheduling delayed FBC enable
thousands and thousands of times on my dmesg.

So kill the useless message for the happy case, saving a lot of dmesg
space, and properly signal the kzalloc fail case.

Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com
---
 drivers/gpu/drm/i915/intel_pm.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index adc44e4..7093402 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -381,6 +381,7 @@ void intel_enable_fbc(struct drm_crtc *crtc, unsigned long 
interval)
 
work = kzalloc(sizeof *work, GFP_KERNEL);
if (work == NULL) {
+   DRM_ERROR(Failed to allocate FBC work structure\n);
dev_priv-display.enable_fbc(crtc, interval);
return;
}
@@ -392,8 +393,6 @@ void intel_enable_fbc(struct drm_crtc *crtc, unsigned long 
interval)
 
dev_priv-fbc_work = work;
 
-   DRM_DEBUG_KMS(scheduling delayed FBC enable\n);
-
/* Delay the actual enabling to let pageflipping cease and the
 * display to settle before starting the compression. Note that
 * this delay also serves a second purpose: it allows for a
-- 
1.8.1.2

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 8/8] drm/i915: rename intel_dp_destroy to intel_dp_connector_destroy

2013-06-12 Thread Paulo Zanoni
From: Paulo Zanoni paulo.r.zan...@intel.com

Because it's the function that destroys the connector, not the
encoder. And we already have intel_dp_encoder_destroy.

This has annoyed me for a long time.

Signed-off-by: Paulo Zanoni paulo.r.zan...@intel.com
---
 drivers/gpu/drm/i915/intel_dp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 89e30ec..8708a0c 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2681,7 +2681,7 @@ done:
 }
 
 static void
-intel_dp_destroy(struct drm_connector *connector)
+intel_dp_connector_destroy(struct drm_connector *connector)
 {
struct intel_connector *intel_connector = to_intel_connector(connector);
 
@@ -2724,7 +2724,7 @@ static const struct drm_connector_funcs 
intel_dp_connector_funcs = {
.detect = intel_dp_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
.set_property = intel_dp_set_property,
-   .destroy = intel_dp_destroy,
+   .destroy = intel_dp_connector_destroy,
 };
 
 static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs 
= {
-- 
1.8.1.2

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH] drm/i915: Restore fences after resume and GPU resets

2013-06-12 Thread Daniel Vetter
On Wed, Jun 12, 2013 at 10:15:12AM +0100, Chris Wilson wrote:
 Stéphane Marchesin found that fences for pinned objects (i.e. the
 scanout) were not being restored upon resume, leading to corruption on
 the display and reference counting issues. This is due to a bug in
 
 commit 312817a39f17dbb4de000165b5b724e3728cd91c [2.6.38]
 Author: Chris Wilson ch...@chris-wilson.co.uk
 Date:   Mon Nov 22 11:50:11 2010 +
 
 drm/i915: Only save and restore fences for UMS
 
 that zapped the pinned fences even though they were in use.
 Fortuitously, whilst we forced a VT switch during suspend and resume,
 no fences were ever pinned at the time. However, we now can do
 switchless S3 transitions and so the old bug finally surfaces.
 
 Reported-by: Stéphane Marchesin marc...@chromium.org
 Signed-off-by: Chris Wilson ch...@chris-wilson.co.uk
 Cc: Daniel Vetter daniel.vet...@ffwll.ch
 Cc: Stéphane Marchesin marc...@chromium.org

Now that people have hit the WARN, picked up for -fixes, thanks for the
patch.
-Daniel
 ---
  drivers/gpu/drm/i915/i915_drv.h |2 ++
  drivers/gpu/drm/i915/i915_gem.c |   22 +-
  drivers/gpu/drm/i915/i915_suspend.c |1 +
  3 files changed, 8 insertions(+), 17 deletions(-)
 
 diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
 index bacc2fe..1a67216 100644
 --- a/drivers/gpu/drm/i915/i915_drv.h
 +++ b/drivers/gpu/drm/i915/i915_drv.h
 @@ -1793,6 +1793,8 @@ struct drm_gem_object *i915_gem_prime_import(struct 
 drm_device *dev,
  struct dma_buf *i915_gem_prime_export(struct drm_device *dev,
   struct drm_gem_object *gem_obj, int flags);
  
 +void i915_gem_restore_fences(struct drm_device *dev);
 +
  /* i915_gem_context.c */
  void i915_gem_context_init(struct drm_device *dev);
  void i915_gem_context_fini(struct drm_device *dev);
 diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
 index 61956a1..773c8f4 100644
 --- a/drivers/gpu/drm/i915/i915_gem.c
 +++ b/drivers/gpu/drm/i915/i915_gem.c
 @@ -2142,25 +2142,15 @@ static void i915_gem_reset_ring_lists(struct 
 drm_i915_private *dev_priv,
   ring-sync_seqno[i] = 0;
  }
  
 -static void i915_gem_reset_fences(struct drm_device *dev)
 +void i915_gem_restore_fences(struct drm_device *dev)
  {
   struct drm_i915_private *dev_priv = dev-dev_private;
   int i;
  
   for (i = 0; i  dev_priv-num_fence_regs; i++) {
   struct drm_i915_fence_reg *reg = dev_priv-fence_regs[i];
 -
 - if (reg-obj)
 - i915_gem_object_fence_lost(reg-obj);
 -
 - i915_gem_write_fence(dev, i, NULL);
 -
 - reg-pin_count = 0;
 - reg-obj = NULL;
 - INIT_LIST_HEAD(reg-lru_list);
 + i915_gem_write_fence(dev, i, reg-obj);
   }
 -
 - INIT_LIST_HEAD(dev_priv-mm.fence_list);
  }
  
  void i915_gem_reset(struct drm_device *dev)
 @@ -2187,8 +2177,7 @@ void i915_gem_reset(struct drm_device *dev)
   obj-base.read_domains = ~I915_GEM_GPU_DOMAINS;
   }
  
 - /* The fence registers are invalidated so clear them out */
 - i915_gem_reset_fences(dev);
 + i915_gem_restore_fences(dev);
  }
  
  /**
 @@ -3922,8 +3911,6 @@ i915_gem_idle(struct drm_device *dev)
   if (!drm_core_check_feature(dev, DRIVER_MODESET))
   i915_gem_evict_everything(dev);
  
 - i915_gem_reset_fences(dev);
 -
   /* Hack!  Don't let anybody do execbuf while we don't control the chip.
* We need to replace this with a semaphore, or something.
* And not confound mm.suspended!
 @@ -4259,7 +4246,8 @@ i915_gem_load(struct drm_device *dev)
   dev_priv-num_fence_regs = 8;
  
   /* Initialize fence registers to zero */
 - i915_gem_reset_fences(dev);
 + INIT_LIST_HEAD(dev_priv-mm.fence_list);
 + i915_gem_restore_fences(dev);
  
   i915_gem_detect_bit_6_swizzle(dev);
   init_waitqueue_head(dev_priv-pending_flip_queue);
 diff --git a/drivers/gpu/drm/i915/i915_suspend.c 
 b/drivers/gpu/drm/i915/i915_suspend.c
 index 88b9a66..70db618 100644
 --- a/drivers/gpu/drm/i915/i915_suspend.c
 +++ b/drivers/gpu/drm/i915/i915_suspend.c
 @@ -394,6 +394,7 @@ int i915_restore_state(struct drm_device *dev)
  
   mutex_lock(dev-struct_mutex);
  
 + i915_gem_restore_fences(dev);
   i915_restore_display(dev);
  
   if (!drm_core_check_feature(dev, DRIVER_MODESET)) {
 -- 
 1.7.10.4
 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 01/13] drm: Added SDP and VSC structures for handling PSR for eDP

2013-06-12 Thread Rodrigo Vivi
From: Shobhit Kumar shobhit.ku...@intel.com

v2: Modified and corrected the structures to be more in line for
kernel coding guidelines and rebased the code on Paulo's DP patchset
v3: removing unecessary identation at DP_RECEIVER_CAP_SIZE
v4: moving them to include/drm/drm_dp_helper.h and also already
icluding EDP_PSR_RECEIVER_CAP_SIZE to add everything needed
for PSR at once at drm_dp_helper.h
v5: Fix SDP VSC header and identation by (Paulo Zanoni) and
remove i915 from title (Daniel Vetter)

CC: Paulo Zanoni paulo.r.zan...@intel.com
Signed-off-by: Sateesh Kavuri sateesh.kav...@intel.com
Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com
Signed-off-by: Rodrigo Vivi rodrigo.v...@gmail.com
---
 include/drm/drm_dp_helper.h | 33 -
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index e8e1417..4062c9e 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -342,13 +342,44 @@ u8 drm_dp_get_adjust_request_voltage(u8 
link_status[DP_LINK_STATUS_SIZE],
 u8 drm_dp_get_adjust_request_pre_emphasis(u8 link_status[DP_LINK_STATUS_SIZE],
  int lane);
 
-#define DP_RECEIVER_CAP_SIZE   0xf
+#define DP_RECEIVER_CAP_SIZE   0xf
+#define EDP_PSR_RECEIVER_CAP_SIZE  2
+
 void drm_dp_link_train_clock_recovery_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]);
 void drm_dp_link_train_channel_eq_delay(u8 dpcd[DP_RECEIVER_CAP_SIZE]);
 
 u8 drm_dp_link_rate_to_bw_code(int link_rate);
 int drm_dp_bw_code_to_link_rate(u8 link_bw);
 
+/* SDP header as per eDP 1.3 spec, section 3.6 */
+struct edp_sdp_header {
+   u8 HB0; /* Secondary Data Packet ID */
+   u8 HB1; /* Secondary Data Packet Type */
+   u8 HB2; /* 7:5 reserved, 4:0 revision number */
+   u8 HB3; /* 7:5 reserved, 4:0 number of valid data bytes */
+} __packed;
+
+#define EDP_SDP_HEADER_REVISION_MASK   0x1F
+#define EDP_SDP_HEADER_VALID_PAYLOAD_BYTES 0x1F
+
+/* SDP VSC header as per eDP 1.3 spec, section 3.6 */
+struct edp_vsc_psr {
+   struct edp_sdp_header sdp_header;
+   u8 DB0; /* Stereo Interface */
+   u8 DB1; /* 0 - PSR State; 1 - Update RFB; 2 - CRC Valid */
+   u8 DB2; /* CRC value bits 7:0 of the R or Cr component */
+   u8 DB3; /* CRC value bits 15:8 of the R or Cr component */
+   u8 DB4; /* CRC value bits 7:0 of the G or Y component */
+   u8 DB5; /* CRC value bits 15:8 of the G or Y component */
+   u8 DB6; /* CRC value bits 7:0 of the B or Cb component */
+   u8 DB7; /* CRC value bits 15:8 of the B or Cb component */
+   u8 DB8_31[24]; /* Reserved */
+} __packed;
+
+#define EDP_VSC_PSR_STATE_ACTIVE   (10)
+#define EDP_VSC_PSR_UPDATE_RFB (11)
+#define EDP_VSC_PSR_CRC_VALUES_VALID   (12)
+
 static inline int
 drm_dp_max_link_rate(u8 dpcd[DP_RECEIVER_CAP_SIZE])
 {
-- 
1.7.11.7

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 02/13] drm/i915: Read the EDP DPCD and PSR Capability

2013-06-12 Thread Rodrigo Vivi
From: Shobhit Kumar shobhit.ku...@intel.com

v2: reuse of just created is_edp_psr and put it at right place.
v3: move is_edp_psr above intel_edp_disable

Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com
Signed-off-by: Rodrigo Vivi rodrigo.v...@gmail.com
Reviewed-by: Jani Nikula jani.nik...@intel.com
---
 drivers/gpu/drm/i915/intel_dp.c  | 13 +
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 759a1c5..5332186 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1342,6 +1342,12 @@ static void intel_dp_get_config(struct intel_encoder 
*encoder,
pipe_config-adjusted_mode.flags |= flags;
 }
 
+static bool is_edp_psr(struct intel_dp *intel_dp)
+{
+   return (is_edp(intel_dp) 
+   (intel_dp-psr_dpcd[0]  DP_PSR_IS_SUPPORTED));
+}
+
 static void intel_disable_dp(struct intel_encoder *encoder)
 {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder-base);
@@ -2255,6 +2261,13 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
if (intel_dp-dpcd[DP_DPCD_REV] == 0)
return false; /* DPCD not present */
 
+   /* Check if the panel supports PSR */
+   memset(intel_dp-psr_dpcd, 0, sizeof(intel_dp-psr_dpcd));
+   intel_dp_aux_native_read_retry(intel_dp, DP_PSR_SUPPORT,
+  intel_dp-psr_dpcd,
+  sizeof(intel_dp-psr_dpcd));
+   if (is_edp_psr(intel_dp))
+   DRM_DEBUG_KMS(Detected EDP PSR Panel.\n);
if (!(intel_dp-dpcd[DP_DOWNSTREAMPORT_PRESENT] 
  DP_DWN_STRM_PORT_PRESENT))
return true; /* native DP sink */
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 0445d8c..18d9dea 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -470,6 +470,7 @@ struct intel_dp {
uint8_t link_bw;
uint8_t lane_count;
uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
+   uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
struct i2c_adapter adapter;
struct i2c_algo_dp_aux_data algo;
-- 
1.7.11.7

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 03/13] drm/i915: VBT Parsing for the PSR Feature Block for HSW

2013-06-12 Thread Rodrigo Vivi
From: Shobhit Kumar shobhit.ku...@intel.com

Parse and store useful information in i915_dev_private

v2: Add to new vbt struct and call them psr_*
v3: Fix comment and variable name

Signed-off-by: Shobhit Kumar shobhit.ku...@intel.com
Signed-off-by: Rodrigo Vivi rodrigo.v...@gmail.com
---
 drivers/gpu/drm/i915/i915_drv.h   |  7 +++
 drivers/gpu/drm/i915/intel_bios.c | 30 ++
 drivers/gpu/drm/i915/intel_bios.h | 20 +++-
 3 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 87f7f88..dd459a5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -951,6 +951,13 @@ struct intel_vbt_data {
int edp_bpp;
struct edp_power_seq edp_pps;
 
+   /* eDP PSR*/
+   u8 psr_full_link_state;
+   u8 psr_wait_lines;
+   u8 psr_idle_frames;
+   u16 psr_wakeup_tp1;
+   u16 psr_wakeup_tp2_tp3;
+
int crt_ddc_pin;
 
int child_dev_num;
diff --git a/drivers/gpu/drm/i915/intel_bios.c 
b/drivers/gpu/drm/i915/intel_bios.c
index 53f2bed..99c6788 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -383,6 +383,35 @@ parse_general_definitions(struct drm_i915_private 
*dev_priv,
}
 }
 
+
+static void
+parse_edp_psr(struct drm_i915_private *dev_priv, struct bdb_header *bdb)
+{
+   struct bdb_psr_features *psr;
+   struct bdb_lvds_options *lvds_opts;
+   int index = 0;
+   lvds_opts = find_section(bdb, BDB_LVDS_OPTIONS);
+   if (!lvds_opts) {
+   DRM_DEBUG_KMS(No LVDS Options block found.\n);
+   return;
+   }
+
+   index = lvds_opts-panel_type;
+
+   psr = find_section(bdb, BDB_PSR_FEATURES);
+   if (!psr) {
+   DRM_DEBUG_KMS(No PSR feature block found.\n);
+   return;
+   }
+
+   dev_priv-vbt.psr_full_link_state = psr[index].link_disable;
+   dev_priv-vbt.psr_wait_lines = psr[index].wait_lines;
+   dev_priv-vbt.psr_idle_frames = psr[index].idle_frames;
+   dev_priv-vbt.psr_wakeup_tp1 = psr[index].wakeup_tp1;
+   dev_priv-vbt.psr_wakeup_tp2_tp3 = psr[index].wakeup_tp2_tp3;
+}
+
+
 static void
 parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
  struct bdb_header *bdb)
@@ -745,6 +774,7 @@ intel_parse_bios(struct drm_device *dev)
parse_device_mapping(dev_priv, bdb);
parse_driver_features(dev_priv, bdb);
parse_edp(dev_priv, bdb);
+   parse_edp_psr(dev_priv, bdb);
 
if (bios)
pci_unmap_rom(pdev, bios);
diff --git a/drivers/gpu/drm/i915/intel_bios.h 
b/drivers/gpu/drm/i915/intel_bios.h
index e088d6f..c883b87 100644
--- a/drivers/gpu/drm/i915/intel_bios.h
+++ b/drivers/gpu/drm/i915/intel_bios.h
@@ -80,7 +80,7 @@ struct vbios_data {
 #define BDB_EXT_MMIO_REGS6
 #define BDB_SWF_IO   7
 #define BDB_SWF_MMIO 8
-#define BDB_DOT_CLOCK_TABLE  9
+#define BDB_PSR_FEATURES 9
 #define BDB_MODE_REMOVAL_TABLE  10
 #define BDB_CHILD_DEVICE_TABLE  11
 #define BDB_DRIVER_FEATURES 12
@@ -265,6 +265,24 @@ struct bdb_lvds_options {
u8 rsvd4;
 } __attribute__((packed));
 
+struct bdb_psr_features {
+   /* Feature bits */
+   u8 link_disable:1;
+   u8 require_aux:1;
+   u8 rsvd1:6;
+
+   /* Wait times */
+   u8 idle_frames:4;
+   u8 wait_lines:3;
+   u8 rsvd2:1;
+
+   /* TP1 wakeup time */
+   u16 wakeup_tp1;
+
+   /* TP2 TP3 wakeup time */
+   u16 wakeup_tp2_tp3;
+} __attribute__((packed));
+
 /* LFP pointer table contains entries to the struct below */
 struct bdb_lvds_lfp_data_ptr {
u16 fp_timing_offset; /* offsets are from start of bdb */
-- 
1.7.11.7

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 05/13] drm/i915: Enable/Disable PSR

2013-06-12 Thread Rodrigo Vivi
Adding Enable and Disable PSR functionalities. This includes setting the
PSR configuration over AUX, sending SDP VSC DIP over the eDP PIPE config,
enabling PSR in the sink via DPCD register and finally enabling PSR on
the host.

This patch is heavily based on initial PSR code by Sateesh Kavuri and
Kumar Shobhit but in a different implementation.

v2: * moved functions around and changed its names.
* removed VSC DIP unset from disable.
* remove FBC wa.
* don't mask LSPS anymore.
* incorporate new crtc usage after a rebase.

Credits-by: Sateesh Kavuri sateesh.kav...@intel.com
Credits-by: Shobhit Kumar shobhit.ku...@intel.com
Signed-off-by: Rodrigo Vivi rodrigo.v...@gmail.com
---
 drivers/gpu/drm/i915/i915_reg.h  |  42 ++
 drivers/gpu/drm/i915/intel_dp.c  | 172 +++
 drivers/gpu/drm/i915/intel_drv.h |   3 +
 3 files changed, 217 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index b1fdca9..4df97b4 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1775,6 +1775,47 @@
 #define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
 #define VSYNCSHIFT(trans) _TRANSCODER(trans, _VSYNCSHIFT_A, _VSYNCSHIFT_B)
 
+/* HSW eDP PSR registers */
+#define EDP_PSR_CTL0x64800
+#define   EDP_PSR_ENABLE   (131)
+#define   EDP_PSR_LINK_DISABLE (027)
+#define   EDP_PSR_LINK_STANDBY (127)
+#define   EDP_PSR_MIN_LINK_ENTRY_TIME_MASK (325)
+#define   EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES  (025)
+#define   EDP_PSR_MIN_LINK_ENTRY_TIME_4_LINES  (125)
+#define   EDP_PSR_MIN_LINK_ENTRY_TIME_2_LINES  (225)
+#define   EDP_PSR_MIN_LINK_ENTRY_TIME_0_LINES  (325)
+#define   EDP_PSR_MAX_SLEEP_TIME_SHIFT 20
+#define   EDP_PSR_SKIP_AUX_EXIT(112)
+#define   EDP_PSR_TP1_TP2_SEL  (011)
+#define   EDP_PSR_TP1_TP3_SEL  (111)
+#define   EDP_PSR_TP2_TP3_TIME_500us   (08)
+#define   EDP_PSR_TP2_TP3_TIME_100us   (18)
+#define   EDP_PSR_TP2_TP3_TIME_2500us  (28)
+#define   EDP_PSR_TP2_TP3_TIME_0us (38)
+#define   EDP_PSR_TP1_TIME_500us   (04)
+#define   EDP_PSR_TP1_TIME_100us   (14)
+#define   EDP_PSR_TP1_TIME_2500us  (24)
+#define   EDP_PSR_TP1_TIME_0us (34)
+#define   EDP_PSR_IDLE_FRAME_SHIFT 0
+
+#define EDP_PSR_AUX_CTL0x64810
+#define EDP_PSR_AUX_DATA1  0x64814
+#define   EDP_PSR_DPCD_COMMAND 0x8006
+#define EDP_PSR_AUX_DATA2  0x64818
+#define   EDP_PSR_DPCD_NORMAL_OPERATION(124)
+#define EDP_PSR_AUX_DATA3  0x6481c
+#define EDP_PSR_AUX_DATA4  0x64820
+#define EDP_PSR_AUX_DATA5  0x64824
+
+#define EDP_PSR_STATUS_CTL 0x64840
+#define   EDP_PSR_STATUS_STATE_MASK(729)
+
+#define EDP_PSR_DEBUG_CTL  0x64860
+#define   EDP_PSR_DEBUG_MASK_LPSP  (127)
+#define   EDP_PSR_DEBUG_MASK_MEMUP (126)
+#define   EDP_PSR_DEBUG_MASK_HPD   (125)
+
 /* VGA port control */
 #define ADPA   0x61100
 #define PCH_ADPA0xe1100
@@ -2045,6 +2086,7 @@
  * (Haswell and newer) to see which VIDEO_DIP_DATA byte corresponds to each 
byte
  * of the infoframe structure specified by CEA-861. */
 #define   VIDEO_DIP_DATA_SIZE  32
+#define   VIDEO_DIP_VSC_DATA_SIZE  36
 #define VIDEO_DIP_CTL  0x61170
 /* Pre HSW: */
 #define   VIDEO_DIP_ENABLE (1  31)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 02b2865..e9c18bd 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1356,6 +1356,178 @@ static bool is_edp_psr(struct intel_dp *intel_dp)
(intel_dp-psr_dpcd[0]  DP_PSR_IS_SUPPORTED));
 }
 
+static bool intel_edp_is_psr_enabled(struct drm_device *dev)
+{
+   struct drm_i915_private *dev_priv = dev-dev_private;
+   return I915_READ(EDP_PSR_CTL)  EDP_PSR_ENABLE;
+}
+
+static void intel_edp_psr_enable_src(struct intel_dp *intel_dp)
+{
+   struct drm_device *dev = intel_dp_to_dev(intel_dp);
+   struct drm_i915_private *dev_priv = dev-dev_private;
+   uint32_t max_sleep_time = 0x1f;
+   uint32_t val = 0x0;
+
+   if (dev_priv-vbt.psr_idle_frames)
+   val |= dev_priv-vbt.psr_idle_frames  EDP_PSR_IDLE_FRAME_SHIFT;
+   else
+   val |= 1  EDP_PSR_IDLE_FRAME_SHIFT;
+
+   if (intel_dp-psr_dpcd[1]  DP_PSR_NO_TRAIN_ON_EXIT) {
+   val |= EDP_PSR_LINK_STANDBY;
+   val |= EDP_PSR_TP2_TP3_TIME_0us;
+   val |= EDP_PSR_TP1_TIME_0us;
+   val |= EDP_PSR_SKIP_AUX_EXIT;
+   } else {
+   val |= EDP_PSR_LINK_DISABLE;
+   /* Use these Values from VBT
+* Case values are timings for HSW as of now
+   

[Intel-gfx] [PATCH 06/13] drm/i915: Added debugfs support for PSR Status

2013-06-12 Thread Rodrigo Vivi
Adding support for PSR Status, PSR entry counter and performance counters.
Heavily based on initial work from Shobhit.

v2: Fix PSR Status Link bits by Paulo Zanoni.

CC: Paulo Zanoni paulo.r.zan...@intel.com
Credits-by: Shobhit Kumar shobhit.ku...@intel.com
Signed-off-by: Rodrigo Vivi rodrigo.v...@gmail.com
---
 drivers/gpu/drm/i915/i915_debugfs.c | 90 +
 drivers/gpu/drm/i915/i915_reg.h | 24 ++
 2 files changed, 114 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index d4e78b6..19192af 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1875,6 +1875,95 @@ static int i915_dpio_info(struct seq_file *m, void *data)
return 0;
 }
 
+static int i915_edp_psr_status(struct seq_file *m, void *data)
+{
+   struct drm_info_node *node = m-private;
+   struct drm_device *dev = node-minor-dev;
+   struct drm_i915_private *dev_priv = dev-dev_private;
+   u32 psrctl, psrstat, psrperf;
+
+   psrctl = I915_READ(EDP_PSR_CTL);
+   seq_printf(m, PSR Enabled: %s\n,
+  yesno(psrctl  EDP_PSR_ENABLE));
+
+   psrstat = I915_READ(EDP_PSR_STATUS_CTL);
+
+   seq_printf(m, PSR Current State: );
+   switch (psrstat  EDP_PSR_STATUS_STATE_MASK) {
+   case EDP_PSR_STATUS_STATE_IDLE:
+   seq_printf(m, Reset state\n);
+   break;
+   case EDP_PSR_STATUS_STATE_SRDONACK:
+   seq_printf(m, Wait for TG/Stream to send on frame of data 
after SRD conditions are met\n);
+   break;
+   case EDP_PSR_STATUS_STATE_SRDENT:
+   seq_printf(m, SRD entry\n);
+   break;
+   case EDP_PSR_STATUS_STATE_BUFOFF:
+   seq_printf(m, Wait for buffer turn off\n);
+   break;
+   case EDP_PSR_STATUS_STATE_BUFON:
+   seq_printf(m, Wait for buffer turn on\n);
+   break;
+   case EDP_PSR_STATUS_STATE_AUXACK:
+   seq_printf(m, Wait for AUX to acknowledge on SRD 
exit\n);
+   break;
+   case EDP_PSR_STATUS_STATE_SRDOFFACK:
+   seq_printf(m, Wait for TG/Stream to acknowledge the 
SRD VDM exit\n);
+   break;
+   default:
+   seq_printf(m, Unknown\n);
+   break;
+   }
+
+   seq_printf(m, Link Status: );
+   switch (psrstat  EDP_PSR_STATUS_LINK_MASK) {
+   case EDP_PSR_STATUS_LINK_FULL_OFF:
+   seq_printf(m, Link is fully off\n);
+   break;
+   case EDP_PSR_STATUS_LINK_FULL_ON:
+   seq_printf(m, Link is fully on\n);
+   break;
+   case EDP_PSR_STATUS_LINK_STANDBY:
+   seq_printf(m, Link is in standby\n);
+   break;
+   default:
+   seq_printf(m, Unknown\n);
+   break;
+   }
+
+   seq_printf(m, PSR Entry Count: %u\n,
+  psrstat  EDP_PSR_STATUS_COUNT_SHIFT 
+  EDP_PSR_STATUS_COUNT_MASK);
+
+   seq_printf(m, Max Sleep Timer Counter: %u\n,
+  psrstat  EDP_PSR_STATUS_MAX_SLEEP_TIMER_SHIFT 
+  EDP_PSR_STATUS_MAX_SLEEP_TIMER_MASK);
+
+   seq_printf(m, Had AUX error: %s\n,
+  yesno(psrstat  EDP_PSR_STATUS_AUX_ERROR));
+
+   seq_printf(m, Sending AUX: %s\n,
+  yesno(psrstat  EDP_PSR_STATUS_AUX_SENDING));
+
+   seq_printf(m, Sending Idle: %s\n,
+  yesno(psrstat  EDP_PSR_STATUS_SENDING_IDLE));
+
+   seq_printf(m, Sending TP2 TP3: %s\n,
+  yesno(psrstat  EDP_PSR_STATUS_SENDING_TP2_TP3));
+
+   seq_printf(m, Sending TP1: %s\n,
+  yesno(psrstat  EDP_PSR_STATUS_SENDING_TP1));
+
+   seq_printf(m, Idle Count: %u\n,
+  psrstat  EDP_PSR_STATUS_IDLE_MASK);
+
+   psrperf = (I915_READ(EDP_PSR_PERF_CNT))  EDP_PSR_PERF_CNT_MASK;
+   seq_printf(m, Performance Counter: %u\n, psrperf);
+
+   return 0;
+}
+
 static int
 i915_wedged_get(void *data, u64 *val)
 {
@@ -2304,6 +2393,7 @@ static struct drm_info_list i915_debugfs_list[] = {
{i915_swizzle_info, i915_swizzle_info, 0},
{i915_ppgtt_info, i915_ppgtt_info, 0},
{i915_dpio, i915_dpio_info, 0},
+   {i915_edp_psr_status, i915_edp_psr_status, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 4df97b4..16ab839 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1810,6 +1810,30 @@
 
 #define EDP_PSR_STATUS_CTL 0x64840
 #define   EDP_PSR_STATUS_STATE_MASK(729)
+#define   EDP_PSR_STATUS_STATE_IDLE(029)
+#define   EDP_PSR_STATUS_STATE_SRDONACK(129)
+#define   EDP_PSR_STATUS_STATE_SRDENT  (229)
+#define   EDP_PSR_STATUS_STATE_BUFOFF  (329)
+#define   

[Intel-gfx] [PATCH 07/13] drm/i915: Match all PSR mode entry conditions before enabling it.

2013-06-12 Thread Rodrigo Vivi
Signed-off-by: Rodrigo Vivi rodrigo.v...@gmail.com
---
 drivers/gpu/drm/i915/i915_debugfs.c | 39 ++---
 drivers/gpu/drm/i915/i915_drv.h | 12 +++
 drivers/gpu/drm/i915/intel_dp.c | 68 -
 3 files changed, 114 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index 19192af..f4e9147 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1880,11 +1880,42 @@ static int i915_edp_psr_status(struct seq_file *m, void 
*data)
struct drm_info_node *node = m-private;
struct drm_device *dev = node-minor-dev;
struct drm_i915_private *dev_priv = dev-dev_private;
-   u32 psrctl, psrstat, psrperf;
+   u32 psrstat, psrperf;
 
-   psrctl = I915_READ(EDP_PSR_CTL);
-   seq_printf(m, PSR Enabled: %s\n,
-  yesno(psrctl  EDP_PSR_ENABLE));
+   if (I915_READ(EDP_PSR_CTL)  EDP_PSR_ENABLE) {
+   seq_printf(m, PSR enabled\n);
+   } else {
+   seq_printf(m, PSR disabled: );
+   switch (dev_priv-no_psr_reason) {
+   case PSR_NO_SOURCE:
+   seq_printf(m, not supported on this platform);
+   break;
+   case PSR_NO_SINK:
+   seq_printf(m, not supported by panel);
+   break;
+   case PSR_CRTC_NOT_ACTIVE:
+   seq_printf(m, crtc not active);
+   break;
+   case PSR_PWR_WELL_ENABLED:
+   seq_printf(m, power well enabled);
+   break;
+   case PSR_NOT_TILED:
+   seq_printf(m, not tiled);
+   break;
+   case PSR_SPRITE_ENABLED:
+   seq_printf(m, sprite enabled);
+   break;
+   case PSR_INTERLACED_ENABLED:
+   seq_printf(m, interlaced enabled);
+   break;
+   case PSR_HSW_NOT_DDIA:
+   seq_printf(m, HSW ties PSR to DDI A (eDP));
+   break;
+   default:
+   seq_printf(m, unknown reason);
+   }
+   seq_printf(m, \n);
+   }
 
psrstat = I915_READ(EDP_PSR_STATUS_CTL);
 
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index dd459a5..cbe842b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -509,6 +509,17 @@ enum no_fbc_reason {
FBC_MODULE_PARAM,
 };
 
+enum no_psr_reason {
+   PSR_NO_SOURCE, /* Not supported on platform */
+   PSR_NO_SINK, /* Not supported by panel */
+   PSR_CRTC_NOT_ACTIVE,
+   PSR_PWR_WELL_ENABLED,
+   PSR_NOT_TILED,
+   PSR_SPRITE_ENABLED,
+   PSR_INTERLACED_ENABLED,
+   PSR_HSW_NOT_DDIA,
+};
+
 enum intel_pch {
PCH_NONE = 0,   /* No PCH present */
PCH_IBX,/* Ibexpeak PCH */
@@ -1119,6 +1130,7 @@ typedef struct drm_i915_private {
struct i915_power_well power_well;
 
enum no_fbc_reason no_fbc_reason;
+   enum no_psr_reason no_psr_reason;
 
struct drm_mm_node *compressed_fb;
struct drm_mm_node *compressed_llb;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e9c18bd..c105236 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1455,6 +1455,71 @@ void intel_edp_psr_write_vsc(struct intel_dp* intel_dp,
POSTING_READ(ctl_reg);
 }
 
+static bool intel_edp_psr_match_conditions(struct intel_dp *intel_dp)
+{
+   struct drm_device *dev = intel_dp_to_dev(intel_dp);
+   struct drm_i915_private *dev_priv = dev-dev_private;
+   struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+   struct drm_crtc *crtc = dig_port-base.base.crtc;
+   struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+   struct drm_i915_gem_object *obj = to_intel_framebuffer(crtc-fb)-obj;
+   struct intel_encoder *intel_encoder = dp_to_dig_port(intel_dp)-base;
+
+   if (!IS_HASWELL(dev)) {
+   DRM_DEBUG_KMS(PSR not supported on this platform\n);
+   dev_priv-no_psr_reason = PSR_NO_SOURCE;
+   return false;
+   }
+
+   if ((intel_encoder-type != INTEL_OUTPUT_EDP) ||
+   (enc_to_dig_port(intel_encoder-base)-port != PORT_A)) {
+   DRM_DEBUG_KMS(HSW ties PSR to DDI A (eDP)\n);
+   dev_priv-no_psr_reason = PSR_HSW_NOT_DDIA;
+   return false;
+   }
+
+   if (!is_edp_psr(intel_dp)) {
+   DRM_DEBUG_KMS(PSR not supported by this panel\n);
+   dev_priv-no_psr_reason = PSR_NO_SINK;
+   return false;
+   }
+
+   if (!intel_crtc-active || !crtc-fb || !crtc-mode.clock) {
+   DRM_DEBUG_KMS(crtc not active for PSR\n);

[Intel-gfx] [PATCH 08/13] drm/i915: Hook PSR functionality

2013-06-12 Thread Rodrigo Vivi
PSR must be enabled after transcoder and port are running.
And it is only available for HSW.

v2: move enable/disable to intel_ddi
v3: The spec suggests PSR should be disabled even before backlight (by pzanoni)
v4: also disabling and enabling whenever panel is disabled/enabled.

CC: Paulo Zanoni paulo.r.zan...@intel.com
Signed-off-by: Rodrigo Vivi rodrigo.v...@gmail.com
---
 drivers/gpu/drm/i915/intel_ddi.c | 2 ++
 drivers/gpu/drm/i915/intel_dp.c  | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 224ce25..45042c0 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1117,6 +1117,7 @@ static void intel_enable_ddi(struct intel_encoder 
*intel_encoder)
intel_dp_stop_link_train(intel_dp);
 
ironlake_edp_backlight_on(intel_dp);
+   intel_edp_psr_enable(intel_dp);
}
 
if (intel_crtc-eld_vld  type != INTEL_OUTPUT_EDP) {
@@ -1147,6 +1148,7 @@ static void intel_disable_ddi(struct intel_encoder 
*intel_encoder)
if (type == INTEL_OUTPUT_EDP) {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
+   intel_edp_psr_disable(intel_dp);
ironlake_edp_backlight_off(intel_dp);
}
 }
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index c105236..e7cd6e0 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1603,6 +1603,7 @@ static void intel_disable_dp(struct intel_encoder 
*encoder)
/* Make sure the panel is off before trying to change the mode. But also
 * ensure that we have vdd while we switch off the panel. */
ironlake_edp_panel_vdd_on(intel_dp);
+   intel_edp_psr_disable(intel_dp);
ironlake_edp_backlight_off(intel_dp);
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
ironlake_edp_panel_off(intel_dp);
@@ -1643,6 +1644,7 @@ static void intel_enable_dp(struct intel_encoder *encoder)
intel_dp_complete_link_train(intel_dp);
intel_dp_stop_link_train(intel_dp);
ironlake_edp_backlight_on(intel_dp);
+   intel_edp_psr_enable(intel_dp);
 
if (IS_VALLEYVIEW(dev)) {
struct intel_digital_port *dport =
-- 
1.7.11.7

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 09/13] drm/i915: add update function to disable/enable-back PSR

2013-06-12 Thread Rodrigo Vivi
Required function to disable PSR when going to console mode.
But also can be used whenever PSR mode entry conditions changed.
---
 drivers/gpu/drm/i915/intel_display.c |  1 +
 drivers/gpu/drm/i915/intel_dp.c  | 32 +++-
 drivers/gpu/drm/i915/intel_drv.h |  1 +
 3 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index ccd28f4..c62fe39 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2233,6 +2233,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
}
 
intel_update_fbc(dev);
+   intel_edp_psr_update(dev);
mutex_unlock(dev-struct_mutex);
 
intel_crtc_update_sarea_pos(crtc, x, y);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e7cd6e0..ea88207 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1520,7 +1520,7 @@ static bool intel_edp_psr_match_conditions(struct 
intel_dp *intel_dp)
return true;
 }
 
-void intel_edp_psr_enable(struct intel_dp* intel_dp)
+void intel_edp_psr_do_enable(struct intel_dp* intel_dp)
 {
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev-dev_private;
@@ -1572,6 +1572,15 @@ void intel_edp_psr_enable(struct intel_dp* intel_dp)
intel_edp_psr_enable_src(intel_dp);
 }
 
+void intel_edp_psr_enable(struct intel_dp* intel_dp)
+{
+   struct drm_device *dev = intel_dp_to_dev(intel_dp);
+
+   if (intel_edp_psr_match_conditions(intel_dp) 
+   !intel_edp_is_psr_enabled(dev))
+   intel_edp_psr_do_enable(intel_dp);
+}
+
 void intel_edp_psr_disable(struct intel_dp* intel_dp)
 {
struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -1594,6 +1603,26 @@ void intel_edp_psr_disable(struct intel_dp* intel_dp)
intel_wait_for_vblank(dev, intel_crtc-pipe);
 }
 
+void intel_edp_psr_update(struct drm_device *dev)
+{
+   struct intel_encoder *encoder;
+   struct intel_dp *intel_dp = NULL;
+
+   list_for_each_entry(encoder, dev-mode_config.encoder_list, base.head)
+   if (encoder-type == INTEL_OUTPUT_EDP) {
+   intel_dp = enc_to_intel_dp(encoder-base);
+
+   if (!is_edp_psr(intel_dp))
+   return;
+
+   if (!intel_edp_psr_match_conditions(intel_dp))
+   intel_edp_psr_disable(intel_dp);
+   else
+   if (!intel_edp_is_psr_enabled(dev))
+   intel_edp_psr_do_enable(intel_dp);
+   }
+}
+
 static void intel_disable_dp(struct intel_encoder *encoder)
 {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder-base);
@@ -1626,6 +1655,7 @@ static void intel_post_disable_dp(struct intel_encoder 
*encoder)
}
 }
 
+
 static void intel_enable_dp(struct intel_encoder *encoder)
 {
struct intel_dp *intel_dp = enc_to_intel_dp(encoder-base);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5113572..c6c8076 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -811,5 +811,6 @@ extern bool intel_set_pch_fifo_underrun_reporting(struct 
drm_device *dev,
 
 extern void intel_edp_psr_enable(struct intel_dp* intel_dp);
 extern void intel_edp_psr_disable(struct intel_dp* intel_dp);
+extern void intel_edp_psr_update(struct drm_device *dev);
 
 #endif /* __INTEL_DRV_H__ */
-- 
1.7.11.7

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 11/13] drm/i915: PSR: Make a clear separation between Sink (Panel) and Source (HW) enabling.

2013-06-12 Thread Rodrigo Vivi
Signed-off-by: Rodrigo Vivi rodrigo.v...@gmail.com
---
 drivers/gpu/drm/i915/intel_dp.c | 169 +---
 1 file changed, 87 insertions(+), 82 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index a7f3bd1..c5ea419 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1362,7 +1362,79 @@ static bool intel_edp_is_psr_enabled(struct drm_device 
*dev)
return I915_READ(EDP_PSR_CTL)  EDP_PSR_ENABLE;
 }
 
-static void intel_edp_psr_enable_src(struct intel_dp *intel_dp)
+
+void intel_edp_psr_write_vsc(struct intel_dp* intel_dp,
+struct edp_vsc_psr *vsc_psr)
+{
+   struct drm_device *dev = intel_dp_to_dev(intel_dp);
+   struct drm_i915_private *dev_priv = dev-dev_private;
+   struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+   struct intel_crtc *crtc = to_intel_crtc(dig_port-base.base.crtc);
+
+   u32 ctl_reg = HSW_TVIDEO_DIP_CTL(crtc-config.cpu_transcoder);
+   u32 data_reg = HSW_TVIDEO_DIP_VSC_DATA(crtc-config.cpu_transcoder);
+   uint32_t *data = (uint32_t *) vsc_psr;
+   unsigned int i;
+   u32 val = I915_READ(ctl_reg);
+
+   /* As per eDP spec, wait for vblank to send SDP VSC packet */
+   intel_wait_for_vblank(dev, crtc-pipe);
+
+   /* As per BSPec (Pipe Video Data Island Packet), besides wait for
+  vsync we need to disable the video DIP being updated before program
+  video DIP data buffer registers for DIP being updated.*/
+   I915_WRITE(ctl_reg, val  ~VIDEO_DIP_ENABLE_VSC_HSW);
+   POSTING_READ(ctl_reg);
+
+   for (i = 0; i  VIDEO_DIP_VSC_DATA_SIZE; i += 4) {
+if (i  sizeof(struct edp_vsc_psr))
+I915_WRITE(data_reg + i, *data++);
+else
+I915_WRITE(data_reg + i, 0);
+}
+
+   I915_WRITE(ctl_reg, val | VIDEO_DIP_ENABLE_VSC_HSW);
+   POSTING_READ(ctl_reg);
+}
+
+static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
+{
+   struct drm_device *dev = intel_dp_to_dev(intel_dp);
+   struct drm_i915_private *dev_priv = dev-dev_private;
+   struct edp_vsc_psr psr_vsc;
+   uint32_t aux_clock_divider = get_aux_clock_divider(intel_dp);
+   int precharge = 0x3;
+   int msg_size = 5;   /* Header(4) + Message(1) */
+
+   /* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */
+   memset(psr_vsc, 0, sizeof(psr_vsc));
+   psr_vsc.sdp_header.HB0 = 0;
+   psr_vsc.sdp_header.HB1 = 0x7;
+   psr_vsc.sdp_header.HB2 = 0x2;
+   psr_vsc.sdp_header.HB3 = 0x8;
+   intel_edp_psr_write_vsc(intel_dp, psr_vsc);
+
+   /* Enable PSR in sink */
+   if (intel_dp-psr_dpcd[1]  DP_PSR_NO_TRAIN_ON_EXIT)
+   intel_dp_aux_native_write_1(intel_dp, DP_PSR_EN_CFG,
+   DP_PSR_ENABLE 
+   ~DP_PSR_MAIN_LINK_ACTIVE);
+   else
+   intel_dp_aux_native_write_1(intel_dp, DP_PSR_EN_CFG,
+   DP_PSR_ENABLE |
+   DP_PSR_MAIN_LINK_ACTIVE);
+
+   /* Setup AUX registers */
+   I915_WRITE(EDP_PSR_AUX_DATA1, EDP_PSR_DPCD_COMMAND);
+   I915_WRITE(EDP_PSR_AUX_DATA2, EDP_PSR_DPCD_NORMAL_OPERATION);
+   I915_WRITE(EDP_PSR_AUX_CTL,
+  DP_AUX_CH_CTL_TIME_OUT_400us |
+  (msg_size  DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+  (precharge  DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+  (aux_clock_divider  DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT));
+}
+
+static void intel_edp_psr_enable_source(struct intel_dp *intel_dp)
 {
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev-dev_private;
@@ -1415,44 +1487,29 @@ static void intel_edp_psr_enable_src(struct intel_dp 
*intel_dp)
};
}
 
+   /* Avoid continuous PSR exit by masking memup and hpd */
+   I915_WRITE(EDP_PSR_DEBUG_CTL, EDP_PSR_DEBUG_MASK_MEMUP |
+  EDP_PSR_DEBUG_MASK_HPD);
+
+   /* Disable unused interrupts */
+   I915_WRITE(GEN6_PMINTRMSK, GEN6_PM_RP_UP_EI_EXPIRED |
+  GEN6_PM_RP_DOWN_EI_EXPIRED);
+
+
I915_WRITE(EDP_PSR_CTL, val |
   EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES |
   max_sleep_time  EDP_PSR_MAX_SLEEP_TIME_SHIFT |
   EDP_PSR_ENABLE);
 }
 
-void intel_edp_psr_write_vsc(struct intel_dp* intel_dp,
-struct edp_vsc_psr *vsc_psr)
+static void intel_edp_psr_do_enable(struct intel_dp* intel_dp)
 {
-   struct drm_device *dev = intel_dp_to_dev(intel_dp);
-   struct drm_i915_private *dev_priv = dev-dev_private;
-   struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-   struct intel_crtc *crtc = to_intel_crtc(dig_port-base.base.crtc);
-
-   u32 

[Intel-gfx] [PATCH 10/13] drm/intel: add enable_psr module option

2013-06-12 Thread Rodrigo Vivi
PSR is enabled by default but can be disabled.

Signed-off-by: Rodrigo Vivi rodrigo.v...@gmail.com
---
 drivers/gpu/drm/i915/i915_debugfs.c | 3 +++
 drivers/gpu/drm/i915/i915_drv.c | 4 
 drivers/gpu/drm/i915/i915_drv.h | 2 ++
 drivers/gpu/drm/i915/intel_dp.c | 6 ++
 4 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index f4e9147..f3e83a6 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1893,6 +1893,9 @@ static int i915_edp_psr_status(struct seq_file *m, void 
*data)
case PSR_NO_SINK:
seq_printf(m, not supported by panel);
break;
+   case PSR_MODULE_PARAM:
+   seq_printf(m, disabled by flag);
+   break;
case PSR_CRTC_NOT_ACTIVE:
seq_printf(m, crtc not active);
break;
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b23cd63..020f416 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -118,6 +118,10 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, 
int, 0600);
 MODULE_PARM_DESC(i915_enable_ppgtt,
Enable PPGTT (default: true));
 
+int i915_enable_psr __read_mostly = 1;
+module_param_named(enable_psr, i915_enable_psr, int, 0600);
+MODULE_PARM_DESC(enable_psr, Enable PSR (default: true));
+
 unsigned int i915_preliminary_hw_support __read_mostly = 0;
 module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 
0600);
 MODULE_PARM_DESC(preliminary_hw_support,
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index cbe842b..cbf85aa 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -512,6 +512,7 @@ enum no_fbc_reason {
 enum no_psr_reason {
PSR_NO_SOURCE, /* Not supported on platform */
PSR_NO_SINK, /* Not supported by panel */
+   PSR_MODULE_PARAM,
PSR_CRTC_NOT_ACTIVE,
PSR_PWR_WELL_ENABLED,
PSR_NOT_TILED,
@@ -1518,6 +1519,7 @@ extern int i915_enable_rc6 __read_mostly;
 extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
+extern int i915_enable_psr __read_mostly;
 extern unsigned int i915_preliminary_hw_support __read_mostly;
 extern int i915_disable_power_well __read_mostly;
 extern int i915_enable_ips __read_mostly;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index ea88207..a7f3bd1 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1484,6 +1484,12 @@ static bool intel_edp_psr_match_conditions(struct 
intel_dp *intel_dp)
return false;
}
 
+   if (!i915_enable_psr) {
+   DRM_DEBUG_KMS(PSR disable by flag\n);
+   dev_priv-no_psr_reason = PSR_MODULE_PARAM;
+   return false;
+   }
+
if (!intel_crtc-active || !crtc-fb || !crtc-mode.clock) {
DRM_DEBUG_KMS(crtc not active for PSR\n);
dev_priv-no_psr_reason = PSR_CRTC_NOT_ACTIVE;
-- 
1.7.11.7

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 12/13] drm/i915: Adding global I915_PARAM for PSR ACTIVE.

2013-06-12 Thread Rodrigo Vivi
This global value allows userspace know when PSR is enabled and active,
i.e. in SRD entry state.
This will allow userspace emit more busy_ioctl when doing directly copy_area
operations through scanout allowing forced psr exit.

Signed-off-by: Rodrigo Vivi rodrigo.v...@gmail.com
---
 drivers/gpu/drm/i915/i915_dma.c | 3 +++
 include/uapi/drm/i915_drm.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index fd8898c..d21b9a0 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1001,6 +1001,9 @@ static int i915_getparam(struct drm_device *dev, void 
*data,
case I915_PARAM_HAS_EXEC_HANDLE_LUT:
value = 1;
break;
+   case I915_PARAM_PSR_ACTIVE:
+   value = I915_READ(EDP_PSR_STATUS_CTL)  
EDP_PSR_STATUS_STATE_SRDENT;
+   break;
default:
DRM_DEBUG(Unknown parameter %d\n, param-param);
return -EINVAL;
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 923ed7f..191a7fc 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -310,6 +310,7 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_PINNED_BATCHES   24
 #define I915_PARAM_HAS_EXEC_NO_RELOC25
 #define I915_PARAM_HAS_EXEC_HANDLE_LUT   26
+#define I915_PARAM_PSR_ACTIVE   27
 
 typedef struct drm_i915_getparam {
int param;
-- 
1.7.11.7

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH 13/13] drm/i915: force psr exit when busy

2013-06-12 Thread Rodrigo Vivi
PSR tracking engine in HSW doesn't detect automagically some directly copy area
operations through scanout so we have to kick it manually and reschedule it to
come back to normal operation as soon as possible.

Signed-off-by: Rodrigo Vivi rodrigo.v...@gmail.com
---
 drivers/gpu/drm/i915/i915_gem.c  |  2 ++
 drivers/gpu/drm/i915/i915_reg.h  |  1 +
 drivers/gpu/drm/i915/intel_dp.c  | 61 
 drivers/gpu/drm/i915/intel_drv.h |  4 +++
 4 files changed, 68 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 58048d4..fc640fc 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3684,6 +3684,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
goto unlock;
}
 
+   intel_edp_psr_force_exit(dev);
+
/* Count all active objects as busy, even if they are currently not used
 * by the gpu. Users of this interface expect objects to eventually
 * become non-busy without any further actions, therefore emit any
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 16ab839..9ad699e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -1836,6 +1836,7 @@
 #define   EDP_PSR_PERF_CNT_MASK0xff
 
 #define EDP_PSR_DEBUG_CTL  0x64860
+#define   EDP_PSR_DEBUG_FORCE_EXIT (330)
 #define   EDP_PSR_DEBUG_MASK_LPSP  (127)
 #define   EDP_PSR_DEBUG_MASK_MEMUP (126)
 #define   EDP_PSR_DEBUG_MASK_HPD   (125)
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index c5ea419..4ab9aa9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1359,9 +1359,54 @@ static bool is_edp_psr(struct intel_dp *intel_dp)
 static bool intel_edp_is_psr_enabled(struct drm_device *dev)
 {
struct drm_i915_private *dev_priv = dev-dev_private;
+
+   if (!IS_HASWELL(dev))
+   return false;
+
return I915_READ(EDP_PSR_CTL)  EDP_PSR_ENABLE;
 }
 
+static void intel_edp_psr_delayed_normal_work(struct work_struct *__work)
+{
+   struct intel_dp *intel_dp = container_of(to_delayed_work(__work),
+struct intel_dp,
+edp_psr_delayed_normal_work);
+   struct drm_device *dev = intel_dp_to_dev(intel_dp);
+   struct drm_i915_private *dev_priv = dev-dev_private;
+
+   mutex_lock(intel_dp-psr_exit_mutex);
+   I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) 
+  ~EDP_PSR_DEBUG_FORCE_EXIT);
+   mutex_unlock(intel_dp-psr_exit_mutex);
+}
+
+void intel_edp_psr_force_exit(struct drm_device *dev)
+{
+   struct drm_i915_private *dev_priv = dev-dev_private;
+   struct intel_encoder *encoder;
+   struct intel_dp *intel_dp = NULL;
+
+   if (!intel_edp_is_psr_enabled(dev))
+   return;
+
+   list_for_each_entry(encoder, dev-mode_config.encoder_list, base.head)
+   if (encoder-type == INTEL_OUTPUT_EDP)
+   intel_dp = enc_to_intel_dp(encoder-base);
+
+   if (!intel_dp)
+   return;
+
+   if (WARN_ON(!intel_dp-psr_setup_done))
+   return;
+
+   mutex_lock(intel_dp-psr_exit_mutex);
+   I915_WRITE(EDP_PSR_DEBUG_CTL, I915_READ(EDP_PSR_DEBUG_CTL) |
+  EDP_PSR_DEBUG_FORCE_EXIT);
+   mutex_unlock(intel_dp-psr_exit_mutex);
+
+   schedule_delayed_work(intel_dp-edp_psr_delayed_normal_work,
+ msecs_to_jiffies(100));
+}
 
 void intel_edp_psr_write_vsc(struct intel_dp* intel_dp,
 struct edp_vsc_psr *vsc_psr)
@@ -1397,6 +1442,18 @@ void intel_edp_psr_write_vsc(struct intel_dp* intel_dp,
POSTING_READ(ctl_reg);
 }
 
+static void intel_edp_psr_setup(struct intel_dp *intel_dp)
+{
+   if (intel_dp-psr_setup_done)
+   return;
+
+   INIT_DELAYED_WORK(intel_dp-edp_psr_delayed_normal_work,
+ intel_edp_psr_delayed_normal_work);
+   mutex_init(intel_dp-psr_exit_mutex);
+
+   intel_dp-psr_setup_done = true;
+}
+
 static void intel_edp_psr_enable_sink(struct intel_dp *intel_dp)
 {
struct drm_device *dev = intel_dp_to_dev(intel_dp);
@@ -1504,6 +1561,8 @@ static void intel_edp_psr_enable_source(struct intel_dp 
*intel_dp)
 
 static void intel_edp_psr_do_enable(struct intel_dp* intel_dp)
 {
+   /* Setup PSR once */
+   intel_edp_psr_setup(intel_dp);
 
/* Enable PSR on the panel */
intel_edp_psr_enable_sink(intel_dp);
@@ -3370,6 +3429,8 @@ intel_dp_init_connector(struct intel_digital_port 
*intel_dig_port,
if (is_edp(intel_dp))
intel_dp_init_panel_power_sequencer(dev, intel_dp, power_seq);
 
+   intel_dp-psr_setup_done = false;
+
intel_dp_i2c_init(intel_dp, intel_connector, name);
 
/* Cache DPCD 

  1   2   >