[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-ti33x-psp-3.2 / 3.2.3 / 0030-drm-i915-paper-over-missed-irq-issues-with-force-wak.patch
1 From 8192adb1ac4be659f5fc3010fa53c7cb3f59a409 Mon Sep 17 00:00:00 2001
2 From: Daniel Vetter <daniel.vetter@ffwll.ch>
3 Date: Fri, 14 Dec 2012 16:01:25 +0100
4 Subject: [PATCH 30/90] drm/i915: paper over missed irq issues with force wake
5 voodoo
7 commit 4cd53c0c8b01fc05c3ad5b2acdad02e37d3c2f55 upstream.
9 Two things seem to do the trick on my ivb machine here:
10 - prevent the gt from powering down while waiting for seqno
11 notification interrupts by grabbing the force_wake in get_irq (and
12 dropping it in put_irq again).
13 - ordering writes from the ring's CS by reading a CS register, ACTHD
14 seems to work.
16 Only the blt&bsd ring on ivb seem to be massively affected by this,
17 but for paranoia do this dance also on the render ring and on snb
18 (i.e. all gpus with forcewake).
20 Tested with Eric's glCopyPixels loop which without this patch scores a
21 missed irq every few seconds.
23 This patch needs my forcewake rework to use a spinlock instead of
24 dev->struct_mutex.
26 After crawling through docs a lot I've found the following nugget:
28 Internal doc "SNB GT PM Programming Guide", Section 4.3.1:
30 "GT does not generate interrupts while in RC6 (by design)"
32 So it looks like rc6 and irq generation are indeed related.
34 v2: Improve the comment per Eugeni Dodonov's suggestion.
36 v3: Add the documentation snipped. Also restrict the w/a to ivb only
37 for -fixes, as suggested by Keith Packard.
39 Cc: Eric Anholt <eric@anholt.net>
40 Cc: Kenneth Graunke <kenneth@whitecape.org>
41 Cc: Eugeni Dodonov <eugeni.dodonov@intel.com>
42 Tested-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
43 Reviewed-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
44 Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
45 Signed-off-by: Keith Packard <keithp@keithp.com>
46 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
47 ---
48 drivers/gpu/drm/i915/intel_ringbuffer.c | 27 +++++++++++++++++++++++++--
49 1 files changed, 25 insertions(+), 2 deletions(-)
51 diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
52 index ca70e2f..30a9af9 100644
53 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c
54 +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
55 @@ -631,6 +631,19 @@ render_ring_add_request(struct intel_ring_buffer *ring,
56 }
58 static u32
59 +gen6_ring_get_seqno(struct intel_ring_buffer *ring)
60 +{
61 + struct drm_device *dev = ring->dev;
62 +
63 + /* Workaround to force correct ordering between irq and seqno writes on
64 + * ivb (and maybe also on snb) by reading from a CS register (like
65 + * ACTHD) before reading the status page. */
66 + if (IS_GEN7(dev))
67 + intel_ring_get_active_head(ring);
68 + return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
69 +}
70 +
71 +static u32
72 ring_get_seqno(struct intel_ring_buffer *ring)
73 {
74 return intel_read_status_page(ring, I915_GEM_HWS_INDEX);
75 @@ -795,6 +808,12 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
76 if (!dev->irq_enabled)
77 return false;
79 + /* It looks like we need to prevent the gt from suspending while waiting
80 + * for an notifiy irq, otherwise irqs seem to get lost on at least the
81 + * blt/bsd rings on ivb. */
82 + if (IS_GEN7(dev))
83 + gen6_gt_force_wake_get(dev_priv);
84 +
85 spin_lock(&ring->irq_lock);
86 if (ring->irq_refcount++ == 0) {
87 ring->irq_mask &= ~rflag;
88 @@ -819,6 +838,9 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
89 ironlake_disable_irq(dev_priv, gflag);
90 }
91 spin_unlock(&ring->irq_lock);
92 +
93 + if (IS_GEN7(dev))
94 + gen6_gt_force_wake_put(dev_priv);
95 }
97 static bool
98 @@ -1316,7 +1338,7 @@ static const struct intel_ring_buffer gen6_bsd_ring = {
99 .write_tail = gen6_bsd_ring_write_tail,
100 .flush = gen6_ring_flush,
101 .add_request = gen6_add_request,
102 - .get_seqno = ring_get_seqno,
103 + .get_seqno = gen6_ring_get_seqno,
104 .irq_get = gen6_bsd_ring_get_irq,
105 .irq_put = gen6_bsd_ring_put_irq,
106 .dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
107 @@ -1451,7 +1473,7 @@ static const struct intel_ring_buffer gen6_blt_ring = {
108 .write_tail = ring_write_tail,
109 .flush = blt_ring_flush,
110 .add_request = gen6_add_request,
111 - .get_seqno = ring_get_seqno,
112 + .get_seqno = gen6_ring_get_seqno,
113 .irq_get = blt_ring_get_irq,
114 .irq_put = blt_ring_put_irq,
115 .dispatch_execbuffer = gen6_ring_dispatch_execbuffer,
116 @@ -1474,6 +1496,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
117 ring->flush = gen6_render_ring_flush;
118 ring->irq_get = gen6_render_ring_get_irq;
119 ring->irq_put = gen6_render_ring_put_irq;
120 + ring->get_seqno = gen6_ring_get_seqno;
121 } else if (IS_GEN5(dev)) {
122 ring->add_request = pc_render_add_request;
123 ring->get_seqno = pc_render_get_seqno;
124 --
125 1.7.7.4