@@ -1784,6 +1784,114 @@ void bdw_disable_vblank(struct drm_crtc *_crtc)
17841784 schedule_work (& display -> irq .vblank_dc_work );
17851785}
17861786
1787+ static u32 vlv_dpinvgtt_pipe_fault_mask (enum pipe pipe )
1788+ {
1789+ switch (pipe ) {
1790+ case PIPE_A :
1791+ return SPRITEB_INVALID_GTT_STATUS |
1792+ SPRITEA_INVALID_GTT_STATUS |
1793+ PLANEA_INVALID_GTT_STATUS |
1794+ CURSORA_INVALID_GTT_STATUS ;
1795+ case PIPE_B :
1796+ return SPRITED_INVALID_GTT_STATUS |
1797+ SPRITEC_INVALID_GTT_STATUS |
1798+ PLANEB_INVALID_GTT_STATUS |
1799+ CURSORB_INVALID_GTT_STATUS ;
1800+ case PIPE_C :
1801+ return SPRITEF_INVALID_GTT_STATUS |
1802+ SPRITEE_INVALID_GTT_STATUS |
1803+ PLANEC_INVALID_GTT_STATUS |
1804+ CURSORC_INVALID_GTT_STATUS ;
1805+ default :
1806+ return 0 ;
1807+ }
1808+ }
1809+
1810+ static const struct pipe_fault_handler vlv_pipe_fault_handlers [] = {
1811+ { .fault = SPRITEB_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE1 , },
1812+ { .fault = SPRITEA_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE0 , },
1813+ { .fault = PLANEA_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_PRIMARY , },
1814+ { .fault = CURSORA_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_CURSOR , },
1815+ { .fault = SPRITED_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE1 , },
1816+ { .fault = SPRITEC_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE0 , },
1817+ { .fault = PLANEB_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_PRIMARY , },
1818+ { .fault = CURSORB_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_CURSOR , },
1819+ { .fault = SPRITEF_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE1 , },
1820+ { .fault = SPRITEE_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_SPRITE0 , },
1821+ { .fault = PLANEC_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_PRIMARY , },
1822+ { .fault = CURSORC_INVALID_GTT_STATUS , .handle = handle_plane_fault , .plane_id = PLANE_CURSOR , },
1823+ {}
1824+ };
1825+
1826+ static void vlv_page_table_error_irq_ack (struct intel_display * display , u32 * dpinvgtt )
1827+ {
1828+ u32 status , enable , tmp ;
1829+
1830+ tmp = intel_de_read (display , DPINVGTT );
1831+
1832+ enable = tmp >> 16 ;
1833+ status = tmp & 0xffff ;
1834+
1835+ /*
1836+ * Despite what the docs claim, the status bits seem to get
1837+ * stuck permanently (similar the old PGTBL_ER register), so
1838+ * we have to disable and ignore them once set. They do get
1839+ * reset if the display power well goes down, so no need to
1840+ * track the enable mask explicitly.
1841+ */
1842+ * dpinvgtt = status & enable ;
1843+ enable &= ~status ;
1844+
1845+ /* customary ack+disable then re-enable to guarantee an edge */
1846+ intel_de_write (display , DPINVGTT , status );
1847+ intel_de_write (display , DPINVGTT , enable << 16 );
1848+ }
1849+
1850+ static void vlv_page_table_error_irq_handler (struct intel_display * display , u32 dpinvgtt )
1851+ {
1852+ enum pipe pipe ;
1853+
1854+ for_each_pipe (display , pipe ) {
1855+ u32 fault_errors ;
1856+
1857+ fault_errors = dpinvgtt & vlv_dpinvgtt_pipe_fault_mask (pipe );
1858+ if (fault_errors )
1859+ intel_pipe_fault_irq_handler (display , vlv_pipe_fault_handlers ,
1860+ pipe , fault_errors );
1861+ }
1862+ }
1863+
1864+ void vlv_display_error_irq_ack (struct intel_display * display ,
1865+ u32 * eir , u32 * dpinvgtt )
1866+ {
1867+ u32 emr ;
1868+
1869+ * eir = intel_de_read (display , VLV_EIR );
1870+
1871+ if (* eir & VLV_ERROR_PAGE_TABLE )
1872+ vlv_page_table_error_irq_ack (display , dpinvgtt );
1873+
1874+ intel_de_write (display , VLV_EIR , * eir );
1875+
1876+ /*
1877+ * Toggle all EMR bits to make sure we get an edge
1878+ * in the ISR master error bit if we don't clear
1879+ * all the EIR bits.
1880+ */
1881+ emr = intel_de_read (display , VLV_EMR );
1882+ intel_de_write (display , VLV_EMR , 0xffffffff );
1883+ intel_de_write (display , VLV_EMR , emr );
1884+ }
1885+
1886+ void vlv_display_error_irq_handler (struct intel_display * display ,
1887+ u32 eir , u32 dpinvgtt )
1888+ {
1889+ drm_dbg (display -> drm , "Master Error, EIR 0x%08x\n" , eir );
1890+
1891+ if (eir & VLV_ERROR_PAGE_TABLE )
1892+ vlv_page_table_error_irq_handler (display , dpinvgtt );
1893+ }
1894+
17871895static void _vlv_display_irq_reset (struct drm_i915_private * dev_priv )
17881896{
17891897 struct intel_display * display = & dev_priv -> display ;
@@ -1793,6 +1901,9 @@ static void _vlv_display_irq_reset(struct drm_i915_private *dev_priv)
17931901 else
17941902 intel_de_write (display , DPINVGTT , DPINVGTT_STATUS_MASK_VLV );
17951903
1904+ gen2_error_reset (to_intel_uncore (display -> drm ),
1905+ VLV_ERROR_REGS );
1906+
17961907 i915_hotplug_interrupt_update_locked (dev_priv , 0xffffffff , 0 );
17971908 intel_de_rmw (display , PORT_HOTPLUG_STAT (dev_priv ), 0 , 0 );
17981909
@@ -1820,6 +1931,12 @@ void i9xx_display_irq_reset(struct drm_i915_private *i915)
18201931 i9xx_pipestat_irq_reset (i915 );
18211932}
18221933
1934+ static u32 vlv_error_mask (void )
1935+ {
1936+ /* TODO enable other errors too? */
1937+ return VLV_ERROR_PAGE_TABLE ;
1938+ }
1939+
18231940void vlv_display_irq_postinstall (struct drm_i915_private * dev_priv )
18241941{
18251942 struct intel_display * display = & dev_priv -> display ;
@@ -1830,6 +1947,18 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
18301947 if (!dev_priv -> display .irq .vlv_display_irqs_enabled )
18311948 return ;
18321949
1950+ if (IS_CHERRYVIEW (dev_priv ))
1951+ intel_de_write (display , DPINVGTT ,
1952+ DPINVGTT_STATUS_MASK_CHV |
1953+ DPINVGTT_EN_MASK_CHV );
1954+ else
1955+ intel_de_write (display , DPINVGTT ,
1956+ DPINVGTT_STATUS_MASK_VLV |
1957+ DPINVGTT_EN_MASK_VLV );
1958+
1959+ gen2_error_init (to_intel_uncore (display -> drm ),
1960+ VLV_ERROR_REGS , ~vlv_error_mask ());
1961+
18331962 pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS ;
18341963
18351964 i915_enable_pipestat (dev_priv , PIPE_A , PIPE_GMBUS_INTERRUPT_STATUS );
@@ -1840,7 +1969,8 @@ void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv)
18401969 I915_DISPLAY_PIPE_A_EVENT_INTERRUPT |
18411970 I915_DISPLAY_PIPE_B_EVENT_INTERRUPT |
18421971 I915_LPE_PIPE_A_INTERRUPT |
1843- I915_LPE_PIPE_B_INTERRUPT ;
1972+ I915_LPE_PIPE_B_INTERRUPT |
1973+ I915_MASTER_ERROR_INTERRUPT ;
18441974
18451975 if (IS_CHERRYVIEW (dev_priv ))
18461976 enable_mask |= I915_DISPLAY_PIPE_C_EVENT_INTERRUPT |
0 commit comments