intel_fifo_underrun.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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. #include "i915_drv.h"
  28. #include "intel_drv.h"
  29. /**
  30. * DOC: fifo underrun handling
  31. *
  32. * The i915 driver checks for display fifo underruns using the interrupt signals
  33. * provided by the hardware. This is enabled by default and fairly useful to
  34. * debug display issues, especially watermark settings.
  35. *
  36. * If an underrun is detected this is logged into dmesg. To avoid flooding logs
  37. * and occupying the cpu underrun interrupts are disabled after the first
  38. * occurrence until the next modeset on a given pipe.
  39. *
  40. * Note that underrun detection on gmch platforms is a bit more ugly since there
  41. * is no interrupt (despite that the signalling bit is in the PIPESTAT pipe
  42. * interrupt register). Also on some other platforms underrun interrupts are
  43. * shared, which means that if we detect an underrun we need to disable underrun
  44. * reporting on all pipes.
  45. *
  46. * The code also supports underrun detection on the PCH transcoder.
  47. */
  48. static bool ivb_can_enable_err_int(struct drm_device *dev)
  49. {
  50. struct drm_i915_private *dev_priv = dev->dev_private;
  51. struct intel_crtc *crtc;
  52. enum pipe pipe;
  53. assert_spin_locked(&dev_priv->irq_lock);
  54. for_each_pipe(dev_priv, pipe) {
  55. crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
  56. if (crtc->cpu_fifo_underrun_disabled)
  57. return false;
  58. }
  59. return true;
  60. }
  61. static bool cpt_can_enable_serr_int(struct drm_device *dev)
  62. {
  63. struct drm_i915_private *dev_priv = dev->dev_private;
  64. enum pipe pipe;
  65. struct intel_crtc *crtc;
  66. assert_spin_locked(&dev_priv->irq_lock);
  67. for_each_pipe(dev_priv, pipe) {
  68. crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
  69. if (crtc->pch_fifo_underrun_disabled)
  70. return false;
  71. }
  72. return true;
  73. }
  74. /**
  75. * i9xx_check_fifo_underruns - check for fifo underruns
  76. * @dev_priv: i915 device instance
  77. *
  78. * This function checks for fifo underruns on GMCH platforms. This needs to be
  79. * done manually on modeset to make sure that we catch all underruns since they
  80. * do not generate an interrupt by themselves on these platforms.
  81. */
  82. void i9xx_check_fifo_underruns(struct drm_i915_private *dev_priv)
  83. {
  84. struct intel_crtc *crtc;
  85. spin_lock_irq(&dev_priv->irq_lock);
  86. for_each_intel_crtc(dev_priv->dev, crtc) {
  87. u32 reg = PIPESTAT(crtc->pipe);
  88. u32 pipestat;
  89. if (crtc->cpu_fifo_underrun_disabled)
  90. continue;
  91. pipestat = I915_READ(reg) & 0xffff0000;
  92. if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0)
  93. continue;
  94. I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
  95. POSTING_READ(reg);
  96. DRM_ERROR("pipe %c underrun\n", pipe_name(crtc->pipe));
  97. }
  98. spin_unlock_irq(&dev_priv->irq_lock);
  99. }
  100. static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev,
  101. enum pipe pipe,
  102. bool enable, bool old)
  103. {
  104. struct drm_i915_private *dev_priv = dev->dev_private;
  105. u32 reg = PIPESTAT(pipe);
  106. u32 pipestat = I915_READ(reg) & 0xffff0000;
  107. assert_spin_locked(&dev_priv->irq_lock);
  108. if (enable) {
  109. I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS);
  110. POSTING_READ(reg);
  111. } else {
  112. if (old && pipestat & PIPE_FIFO_UNDERRUN_STATUS)
  113. DRM_ERROR("pipe %c underrun\n", pipe_name(pipe));
  114. }
  115. }
  116. static void ironlake_set_fifo_underrun_reporting(struct drm_device *dev,
  117. enum pipe pipe, bool enable)
  118. {
  119. struct drm_i915_private *dev_priv = dev->dev_private;
  120. uint32_t bit = (pipe == PIPE_A) ? DE_PIPEA_FIFO_UNDERRUN :
  121. DE_PIPEB_FIFO_UNDERRUN;
  122. if (enable)
  123. ironlake_enable_display_irq(dev_priv, bit);
  124. else
  125. ironlake_disable_display_irq(dev_priv, bit);
  126. }
  127. static void ivybridge_set_fifo_underrun_reporting(struct drm_device *dev,
  128. enum pipe pipe,
  129. bool enable, bool old)
  130. {
  131. struct drm_i915_private *dev_priv = dev->dev_private;
  132. if (enable) {
  133. I915_WRITE(GEN7_ERR_INT, ERR_INT_FIFO_UNDERRUN(pipe));
  134. if (!ivb_can_enable_err_int(dev))
  135. return;
  136. ironlake_enable_display_irq(dev_priv, DE_ERR_INT_IVB);
  137. } else {
  138. ironlake_disable_display_irq(dev_priv, DE_ERR_INT_IVB);
  139. if (old &&
  140. I915_READ(GEN7_ERR_INT) & ERR_INT_FIFO_UNDERRUN(pipe)) {
  141. DRM_ERROR("uncleared fifo underrun on pipe %c\n",
  142. pipe_name(pipe));
  143. }
  144. }
  145. }
  146. static void broadwell_set_fifo_underrun_reporting(struct drm_device *dev,
  147. enum pipe pipe, bool enable)
  148. {
  149. struct drm_i915_private *dev_priv = dev->dev_private;
  150. assert_spin_locked(&dev_priv->irq_lock);
  151. if (enable)
  152. dev_priv->de_irq_mask[pipe] &= ~GEN8_PIPE_FIFO_UNDERRUN;
  153. else
  154. dev_priv->de_irq_mask[pipe] |= GEN8_PIPE_FIFO_UNDERRUN;
  155. I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
  156. POSTING_READ(GEN8_DE_PIPE_IMR(pipe));
  157. }
  158. static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
  159. enum transcoder pch_transcoder,
  160. bool enable)
  161. {
  162. struct drm_i915_private *dev_priv = dev->dev_private;
  163. uint32_t bit = (pch_transcoder == TRANSCODER_A) ?
  164. SDE_TRANSA_FIFO_UNDER : SDE_TRANSB_FIFO_UNDER;
  165. if (enable)
  166. ibx_enable_display_interrupt(dev_priv, bit);
  167. else
  168. ibx_disable_display_interrupt(dev_priv, bit);
  169. }
  170. static void cpt_set_fifo_underrun_reporting(struct drm_device *dev,
  171. enum transcoder pch_transcoder,
  172. bool enable, bool old)
  173. {
  174. struct drm_i915_private *dev_priv = dev->dev_private;
  175. if (enable) {
  176. I915_WRITE(SERR_INT,
  177. SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder));
  178. if (!cpt_can_enable_serr_int(dev))
  179. return;
  180. ibx_enable_display_interrupt(dev_priv, SDE_ERROR_CPT);
  181. } else {
  182. ibx_disable_display_interrupt(dev_priv, SDE_ERROR_CPT);
  183. if (old && I915_READ(SERR_INT) &
  184. SERR_INT_TRANS_FIFO_UNDERRUN(pch_transcoder)) {
  185. DRM_ERROR("uncleared pch fifo underrun on pch transcoder %c\n",
  186. transcoder_name(pch_transcoder));
  187. }
  188. }
  189. }
  190. static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev,
  191. enum pipe pipe, bool enable)
  192. {
  193. struct drm_i915_private *dev_priv = dev->dev_private;
  194. struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
  195. struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  196. bool old;
  197. assert_spin_locked(&dev_priv->irq_lock);
  198. old = !intel_crtc->cpu_fifo_underrun_disabled;
  199. intel_crtc->cpu_fifo_underrun_disabled = !enable;
  200. if (HAS_GMCH_DISPLAY(dev))
  201. i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old);
  202. else if (IS_GEN5(dev) || IS_GEN6(dev))
  203. ironlake_set_fifo_underrun_reporting(dev, pipe, enable);
  204. else if (IS_GEN7(dev))
  205. ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old);
  206. else if (IS_GEN8(dev) || IS_GEN9(dev))
  207. broadwell_set_fifo_underrun_reporting(dev, pipe, enable);
  208. return old;
  209. }
  210. /**
  211. * intel_set_cpu_fifo_underrun_reporting - set cpu fifo underrrun reporting state
  212. * @dev_priv: i915 device instance
  213. * @pipe: (CPU) pipe to set state for
  214. * @enable: whether underruns should be reported or not
  215. *
  216. * This function sets the fifo underrun state for @pipe. It is used in the
  217. * modeset code to avoid false positives since on many platforms underruns are
  218. * expected when disabling or enabling the pipe.
  219. *
  220. * Notice that on some platforms disabling underrun reports for one pipe
  221. * disables for all due to shared interrupts. Actual reporting is still per-pipe
  222. * though.
  223. *
  224. * Returns the previous state of underrun reporting.
  225. */
  226. bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
  227. enum pipe pipe, bool enable)
  228. {
  229. unsigned long flags;
  230. bool ret;
  231. spin_lock_irqsave(&dev_priv->irq_lock, flags);
  232. ret = __intel_set_cpu_fifo_underrun_reporting(dev_priv->dev, pipe,
  233. enable);
  234. spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
  235. return ret;
  236. }
  237. /**
  238. * intel_set_pch_fifo_underrun_reporting - set PCH fifo underrun reporting state
  239. * @dev_priv: i915 device instance
  240. * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
  241. * @enable: whether underruns should be reported or not
  242. *
  243. * This function makes us disable or enable PCH fifo underruns for a specific
  244. * PCH transcoder. Notice that on some PCHs (e.g. CPT/PPT), disabling FIFO
  245. * underrun reporting for one transcoder may also disable all the other PCH
  246. * error interruts for the other transcoders, due to the fact that there's just
  247. * one interrupt mask/enable bit for all the transcoders.
  248. *
  249. * Returns the previous state of underrun reporting.
  250. */
  251. bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
  252. enum transcoder pch_transcoder,
  253. bool enable)
  254. {
  255. struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pch_transcoder];
  256. struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
  257. unsigned long flags;
  258. bool old;
  259. /*
  260. * NOTE: Pre-LPT has a fixed cpu pipe -> pch transcoder mapping, but LPT
  261. * has only one pch transcoder A that all pipes can use. To avoid racy
  262. * pch transcoder -> pipe lookups from interrupt code simply store the
  263. * underrun statistics in crtc A. Since we never expose this anywhere
  264. * nor use it outside of the fifo underrun code here using the "wrong"
  265. * crtc on LPT won't cause issues.
  266. */
  267. spin_lock_irqsave(&dev_priv->irq_lock, flags);
  268. old = !intel_crtc->pch_fifo_underrun_disabled;
  269. intel_crtc->pch_fifo_underrun_disabled = !enable;
  270. if (HAS_PCH_IBX(dev_priv->dev))
  271. ibx_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
  272. enable);
  273. else
  274. cpt_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
  275. enable, old);
  276. spin_unlock_irqrestore(&dev_priv->irq_lock, flags);
  277. return old;
  278. }
  279. /**
  280. * intel_cpu_fifo_underrun_irq_handler - handle CPU fifo underrun interrupt
  281. * @dev_priv: i915 device instance
  282. * @pipe: (CPU) pipe to set state for
  283. *
  284. * This handles a CPU fifo underrun interrupt, generating an underrun warning
  285. * into dmesg if underrun reporting is enabled and then disables the underrun
  286. * interrupt to avoid an irq storm.
  287. */
  288. void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
  289. enum pipe pipe)
  290. {
  291. struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];
  292. /* We may be called too early in init, thanks BIOS! */
  293. if (crtc == NULL)
  294. return;
  295. /* GMCH can't disable fifo underruns, filter them. */
  296. if (HAS_GMCH_DISPLAY(dev_priv->dev) &&
  297. to_intel_crtc(crtc)->cpu_fifo_underrun_disabled)
  298. return;
  299. if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false))
  300. DRM_ERROR("CPU pipe %c FIFO underrun\n",
  301. pipe_name(pipe));
  302. }
  303. /**
  304. * intel_pch_fifo_underrun_irq_handler - handle PCH fifo underrun interrupt
  305. * @dev_priv: i915 device instance
  306. * @pch_transcoder: the PCH transcoder (same as pipe on IVB and older)
  307. *
  308. * This handles a PCH fifo underrun interrupt, generating an underrun warning
  309. * into dmesg if underrun reporting is enabled and then disables the underrun
  310. * interrupt to avoid an irq storm.
  311. */
  312. void intel_pch_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
  313. enum transcoder pch_transcoder)
  314. {
  315. if (intel_set_pch_fifo_underrun_reporting(dev_priv, pch_transcoder,
  316. false))
  317. DRM_ERROR("PCH transcoder %c FIFO underrun\n",
  318. transcoder_name(pch_transcoder));
  319. }