Branch data Line data Source code
1 : : /*
2 : : * Copyright © 2014 Intel Corporation
3 : : *
4 : : * Permission is hereby granted, free of charge, to any person obtaining a
5 : : * copy of this software and associated documentation files (the "Software"),
6 : : * to deal in the Software without restriction, including without limitation
7 : : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 : : * and/or sell copies of the Software, and to permit persons to whom the
9 : : * Software is furnished to do so, subject to the following conditions:
10 : : *
11 : : * The above copyright notice and this permission notice (including the next
12 : : * paragraph) shall be included in all copies or substantial portions of the
13 : : * Software.
14 : : *
15 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 : : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 : : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 : : * IN THE SOFTWARE.
22 : : *
23 : : * Authors:
24 : : * Daniel Vetter <daniel.vetter@ffwll.ch>
25 : : *
26 : : */
27 : :
28 : : #include "i915_drv.h"
29 : : #include "i915_trace.h"
30 : : #include "intel_display_types.h"
31 : : #include "intel_fbc.h"
32 : : #include "intel_fifo_underrun.h"
33 : :
34 : : /**
35 : : * DOC: fifo underrun handling
36 : : *
37 : : * The i915 driver checks for display fifo underruns using the interrupt signals
38 : : * provided by the hardware. This is enabled by default and fairly useful to
39 : : * debug display issues, especially watermark settings.
40 : : *
41 : : * If an underrun is detected this is logged into dmesg. To avoid flooding logs
42 : : * and occupying the cpu underrun interrupts are disabled after the first
43 : : * occurrence until the next modeset on a given pipe.
44 : : *
45 : : * Note that underrun detection on gmch platforms is a bit more ugly since there
46 : : * is no interrupt (despite that the signalling bit is in the PIPESTAT pipe
47 : : * interrupt register). Also on some other platforms underrun interrupts are
48 : : * shared, which means that if we detect an underrun we need to disable underrun
49 : : * reporting on all pipes.
50 : : *
51 : : * The code also supports underrun detection on the PCH transcoder.
52 : : */
53 : :
54 : 0 : static bool ivb_can_enable_err_int(struct drm_device *dev)
55 : : {
56 : 0 : struct drm_i915_private *dev_priv = to_i915(dev);
57 : 0 : struct intel_crtc *crtc;
58 : 0 : enum pipe pipe;
59 : :
60 : 0 : lockdep_assert_held(&dev_priv->irq_lock);
61 : :
62 [ # # # # ]: 0 : for_each_pipe(dev_priv, pipe) {
63 [ # # ]: 0 : crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
64 : :
65 [ # # ]: 0 : if (crtc->cpu_fifo_underrun_disabled)
66 : : return false;
67 : : }
68 : :
69 : : return true;
70 : : }
71 : :
72 : 0 : static bool cpt_can_enable_serr_int(struct drm_device *dev)
73 : : {
74 : 0 : struct drm_i915_private *dev_priv = to_i915(dev);
75 : 0 : enum pipe pipe;
76 : 0 : struct intel_crtc *crtc;
77 : :
78 : 0 : lockdep_assert_held(&dev_priv->irq_lock);
79 : :
80 [ # # # # ]: 0 : for_each_pipe(dev_priv, pipe) {
81 [ # # ]: 0 : crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
82 : :
83 [ # # ]: 0 : if (crtc->pch_fifo_underrun_disabled)
84 : : return false;
85 : : }
86 : :
87 : : return true;
88 : : }
89 : :
90 : : static void i9xx_check_fifo_underruns(struct intel_crtc *crtc)
91 : : {
92 : : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
93 : : i915_reg_t reg = PIPESTAT(crtc->pipe);
94 : : u32 enable_mask;
95 : :
96 : : lockdep_assert_held(&dev_priv->irq_lock);
97 : :
98 : : if ((I915_READ(reg) & PIPE_FIFO_UNDERRUN_STATUS) == 0)
99 : : return;
100 : :
101 : : enable_mask = i915_pipestat_enable_mask(dev_priv, crtc->pipe);
102 : : I915_WRITE(reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS);
103 : : POSTING_READ(reg);
104 : :
105 : : trace_intel_cpu_fifo_underrun(dev_priv, crtc->pipe);
106 : : DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
107 : : }
108 : :
109 : 0 : static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
110 : : enum pipe pipe,
111 : : bool enable, bool old)
112 : : {
113 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(dev);
114 : 0 : i915_reg_t reg = PIPESTAT(pipe);
115 : :
116 : 0 : lockdep_assert_held(&dev_priv->irq_lock);
117 : :
118 [ # # ]: 0 : if (enable) {
119 : 0 : u32 enable_mask = i915_pipestat_enable_mask(dev_priv, pipe);
120 : :
121 : 0 : I915_WRITE(reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS);
122 : 0 : POSTING_READ(reg);
123 : : } else {
124 [ # # # # ]: 0 : if (old && I915_READ(reg) & PIPE_FIFO_UNDERRUN_STATUS)
125 : 0 : DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
126 : : }
127 : 0 : }
128 : :
129 : 0 : static void ilk_set_fifo_underrun_reporting(struct drm_device *dev,
130 : : enum pipe pipe, bool enable)
131 : : {
132 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(dev);
133 : 0 : u32 bit = (pipe == PIPE_A) ?
134 [ # # ]: 0 : DE_PIPEA_FIFO_UNDERRUN : DE_PIPEB_FIFO_UNDERRUN;
135 : :
136 [ # # ]: 0 : if (enable)
137 : 0 : ilk_enable_display_irq(dev_priv, bit);
138 : : else
139 : 0 : ilk_disable_display_irq(dev_priv, bit);
140 : 0 : }
141 : :
142 : : static void ivb_check_fifo_underruns(struct intel_crtc *crtc)
143 : : {
144 : : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
145 : : enum pipe pipe = crtc->pipe;
146 : : u32 err_int = I915_READ(GEN7_ERR_INT);
147 : :
148 : : lockdep_assert_held(&dev_priv->irq_lock);
149 : :
150 : : if ((err_int & ERR_INT_FIFO_UNDERRUN(pipe)) == 0)
151 : : return;
152 : :
153 : : I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
154 : : POSTING_READ(GEN7_ERR_INT);
155 : :
156 : : trace_intel_cpu_fifo_underrun(dev_priv, pipe);
157 : : DRM_ERROR("fifo underrun on pipe %c\n", pipe_name(pipe));
158 : : }
159 : :
160 : 0 : static void ivb_set_fifo_underrun_reporting(struct drm_device *dev,
161 : : enum pipe pipe, bool enable,
162 : : bool old)
163 : : {
164 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(dev);
165 [ # # ]: 0 : if (enable) {
166 : 0 : I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
167 : :
168 [ # # ]: 0 : if (!ivb_can_enable_err_int(dev))
169 : : return;
170 : :
171 : 0 : ilk_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
172 : : } else {
173 : 0 : ilk_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
174 : :
175 [ # # ]: 0 : if (old &&
176 [ # # ]: 0 : I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
177 : 0 : DRM_ERROR("uncleared fifo underrun on pipe %c\n",
178 : : pipe_name(pipe));
179 : : }
180 : : }
181 : : }
182 : :
183 : 0 : static void bdw_set_fifo_underrun_reporting(struct drm_device *dev,
184 : : enum pipe pipe, bool enable)
185 : : {
186 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(dev);
187 : :
188 [ # # ]: 0 : if (enable)
189 : 0 : bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
190 : : else
191 : 0 : bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
192 : 0 : }
193 : :
194 : 0 : static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
195 : : enum pipe pch_transcoder,
196 : : bool enable)
197 : : {
198 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(dev);
199 : 0 : u32 bit = (pch_transcoder == PIPE_A) ?
200 [ # # ]: 0 : SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
201 : :
202 [ # # ]: 0 : if (enable)
203 : 0 : ibx_enable_display_interrupt(dev_priv, bit);
204 : : else
205 : 0 : ibx_disable_display_interrupt(dev_priv, bit);
206 : 0 : }
207 : :
208 : : static void cpt_check_pch_fifo_underruns(struct intel_crtc *crtc)
209 : : {
210 : : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
211 : : enum pipe pch_transcoder = crtc->pipe;
212 : : u32 serr_int = I915_READ(SERR_INT);
213 : :
214 : : lockdep_assert_held(&dev_priv->irq_lock);
215 : :
216 : : if ((serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) == 0)
217 : : return;
218 : :
219 : : I915_WRITE(SERR_INT, SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
220 : : POSTING_READ(SERR_INT);
221 : :
222 : : trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
223 : : DRM_ERROR("pch fifo underrun on pch transcoder %c\n",
224 : : pipe_name(pch_transcoder));
225 : : }
226 : :
227 : 0 : static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
228 : : enum pipe pch_transcoder,
229 : : bool enable, bool old)
230 : : {
231 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(dev);
232 : :
233 [ # # ]: 0 : if (enable) {
234 : 0 : I915_WRITE(SERR_INT,
235 : : SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
236 : :
237 [ # # ]: 0 : if (!cpt_can_enable_serr_int(dev))
238 : : return;
239 : :
240 : 0 : ibx_enable_display_interrupt(dev_priv, SDE_ERROR_CPT);
241 : : } else {
242 : 0 : ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT);
243 : :
244 [ # # ]: 0 : if (old && I915_READ(SERR_INT) &
245 [ # # ]: 0 : SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
246 : 0 : DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
247 : : pipe_name(pch_transcoder));
248 : : }
249 : : }
250 : : }
251 : :
252 : 0 : static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
253 : : enum pipe pipe, bool enable)
254 : : {
255 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(dev);
256 [ # # ]: 0 : struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
257 : 0 : bool old;
258 : :
259 : 0 : lockdep_assert_held(&dev_priv->irq_lock);
260 : :
261 : 0 : old = !crtc->cpu_fifo_underrun_disabled;
262 : 0 : crtc->cpu_fifo_underrun_disabled = !enable;
263 : :
264 [ # # ]: 0 : if (HAS_GMCH(dev_priv))
265 : 0 : i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
266 [ # # ]: 0 : else if (IS_GEN_RANGE(dev_priv, 5, 6))
267 : 0 : ilk_set_fifo_underrun_reporting(dev, pipe, enable);
268 [ # # ]: 0 : else if (IS_GEN(dev_priv, 7))
269 : 0 : ivb_set_fifo_underrun_reporting(dev, pipe, enable, old);
270 [ # # ]: 0 : else if (INTEL_GEN(dev_priv) >= 8)
271 : 0 : bdw_set_fifo_underrun_reporting(dev, pipe, enable);
272 : :
273 : 0 : return old;
274 : : }
275 : :
276 : : /**
277 : : * intel_set_cpu_fifo_underrun_reporting - set cpu fifo underrrun reporting state
278 : : * @dev_priv: i915 device instance
279 : : * @pipe: (CPU) pipe to set state for
280 : : * @enable: whether underruns should be reported or not
281 : : *
282 : : * This function sets the fifo underrun state for @pipe. It is used in the
283 : : * modeset code to avoid false positives since on many platforms underruns are
284 : : * expected when disabling or enabling the pipe.
285 : : *
286 : : * Notice that on some platforms disabling underrun reports for one pipe
287 : : * disables for all due to shared interrupts. Actual reporting is still per-pipe
288 : : * though.
289 : : *
290 : : * Returns the previous state of underrun reporting.
291 : : */
292 : 0 : bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
293 : : enum pipe pipe, bool enable)
294 : : {
295 : 0 : unsigned long flags;
296 : 0 : bool ret;
297 : :
298 : 0 : spin_lock_irqsave(&dev_priv->irq_lock, flags);
299 : 0 : ret = __intel_set_cpu_fifo_underrun_reporting(&dev_priv->drm, pipe,
300 : : enable);
301 : 0 : spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
302 : :
303 : 0 : return ret;
304 : : }
305 : :
306 : : /**
307 : : * intel_set_pch_fifo_underrun_reporting - set PCH fifo underrun reporting state
308 : : * @dev_priv: i915 device instance
309 : : * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
310 : : * @enable: whether underruns should be reported or not
311 : : *
312 : : * This function makes us disable or enable PCH fifo underruns for a specific
313 : : * PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO
314 : : * underrun reporting for one transcoder may also disable all the other PCH
315 : : * error interruts for the other transcoders, due to the fact that there's just
316 : : * one interrupt mask/enable bit for all the transcoders.
317 : : *
318 : : * Returns the previous state of underrun reporting.
319 : : */
320 : 0 : bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
321 : : enum pipe pch_transcoder,
322 : : bool enable)
323 : : {
324 : 0 : struct intel_crtc *crtc =
325 : : intel_get_crtc_for_pipe(dev_priv, pch_transcoder);
326 : 0 : unsigned long flags;
327 : 0 : bool old;
328 : :
329 : : /*
330 : : * NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT
331 : : * has only one pch transcoder A that all pipes can use. To avoid racy
332 : : * pch transcoder -> pipe lookups from interrupt code simply store the
333 : : * underrun statistics in crtc A. Since we never expose this anywhere
334 : : * nor use it outside of the fifo underrun code here using the "wrong"
335 : : * crtc on LPT won't cause issues.
336 : : */
337 : :
338 : 0 : spin_lock_irqsave(&dev_priv->irq_lock, flags);
339 : :
340 : 0 : old = !crtc->pch_fifo_underrun_disabled;
341 : 0 : crtc->pch_fifo_underrun_disabled = !enable;
342 : :
343 [ # # ]: 0 : if (HAS_PCH_IBX(dev_priv))
344 : 0 : ibx_set_fifo_underrun_reporting(&dev_priv->drm,
345 : : pch_transcoder,
346 : : enable);
347 : : else
348 : 0 : cpt_set_fifo_underrun_reporting(&dev_priv->drm,
349 : : pch_transcoder,
350 : : enable, old);
351 : :
352 : 0 : spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
353 : 0 : return old;
354 : : }
355 : :
356 : : /**
357 : : * intel_cpu_fifo_underrun_irq_handler - handle CPU fifo underrun interrupt
358 : : * @dev_priv: i915 device instance
359 : : * @pipe: (CPU) pipe to set state for
360 : : *
361 : : * This handles a CPU fifo underrun interrupt, generating an underrun warning
362 : : * into dmesg if underrun reporting is enabled and then disables the underrun
363 : : * interrupt to avoid an irq storm.
364 : : */
365 : 0 : void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
366 : : enum pipe pipe)
367 : : {
368 [ # # ]: 0 : struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
369 : :
370 : : /* We may be called too early in init, thanks BIOS! */
371 [ # # ]: 0 : if (crtc == NULL)
372 : : return;
373 : :
374 : : /* GMCH can't disable fifo underruns, filter them. */
375 [ # # ]: 0 : if (HAS_GMCH(dev_priv) &&
376 [ # # ]: 0 : crtc->cpu_fifo_underrun_disabled)
377 : : return;
378 : :
379 [ # # ]: 0 : if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) {
380 : 0 : trace_intel_cpu_fifo_underrun(dev_priv, pipe);
381 : 0 : DRM_ERROR("CPU pipe %c FIFO underrun\n",
382 : : pipe_name(pipe));
383 : : }
384 : :
385 : 0 : intel_fbc_handle_fifo_underrun_irq(dev_priv);
386 : : }
387 : :
388 : : /**
389 : : * intel_pch_fifo_underrun_irq_handler - handle PCH fifo underrun interrupt
390 : : * @dev_priv: i915 device instance
391 : : * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
392 : : *
393 : : * This handles a PCH fifo underrun interrupt, generating an underrun warning
394 : : * into dmesg if underrun reporting is enabled and then disables the underrun
395 : : * interrupt to avoid an irq storm.
396 : : */
397 : 0 : void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
398 : : enum pipe pch_transcoder)
399 : : {
400 [ # # ]: 0 : if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
401 : : false)) {
402 : 0 : trace_intel_pch_fifo_underrun(dev_priv, pch_transcoder);
403 : 0 : DRM_ERROR("PCH transcoder %c FIFO underrun\n",
404 : : pipe_name(pch_transcoder));
405 : : }
406 : 0 : }
407 : :
408 : : /**
409 : : * intel_check_cpu_fifo_underruns - check for CPU fifo underruns immediately
410 : : * @dev_priv: i915 device instance
411 : : *
412 : : * Check for CPU fifo underruns immediately. Useful on IVB/HSW where the shared
413 : : * error interrupt may have been disabled, and so CPU fifo underruns won't
414 : : * necessarily raise an interrupt, and on GMCH platforms where underruns never
415 : : * raise an interrupt.
416 : : */
417 : 0 : void intel_check_cpu_fifo_underruns(struct drm_i915_private *dev_priv)
418 : : {
419 : 0 : struct intel_crtc *crtc;
420 : :
421 : 0 : spin_lock_irq(&dev_priv->irq_lock);
422 : :
423 [ # # ]: 0 : for_each_intel_crtc(&dev_priv->drm, crtc) {
424 [ # # ]: 0 : if (crtc->cpu_fifo_underrun_disabled)
425 : 0 : continue;
426 : :
427 [ # # ]: 0 : if (HAS_GMCH(dev_priv))
428 : 0 : i9xx_check_fifo_underruns(crtc);
429 [ # # ]: 0 : else if (IS_GEN(dev_priv, 7))
430 : 0 : ivb_check_fifo_underruns(crtc);
431 : : }
432 : :
433 : 0 : spin_unlock_irq(&dev_priv->irq_lock);
434 : 0 : }
435 : :
436 : : /**
437 : : * intel_check_pch_fifo_underruns - check for PCH fifo underruns immediately
438 : : * @dev_priv: i915 device instance
439 : : *
440 : : * Check for PCH fifo underruns immediately. Useful on CPT/PPT where the shared
441 : : * error interrupt may have been disabled, and so PCH fifo underruns won't
442 : : * necessarily raise an interrupt.
443 : : */
444 : 0 : void intel_check_pch_fifo_underruns(struct drm_i915_private *dev_priv)
445 : : {
446 : 0 : struct intel_crtc *crtc;
447 : :
448 : 0 : spin_lock_irq(&dev_priv->irq_lock);
449 : :
450 [ # # ]: 0 : for_each_intel_crtc(&dev_priv->drm, crtc) {
451 [ # # ]: 0 : if (crtc->pch_fifo_underrun_disabled)
452 : 0 : continue;
453 : :
454 [ # # ]: 0 : if (HAS_PCH_CPT(dev_priv))
455 : 0 : cpt_check_pch_fifo_underruns(crtc);
456 : : }
457 : :
458 : 0 : spin_unlock_irq(&dev_priv->irq_lock);
459 : 0 : }
|