gfx: drv: Add trace events for powermanagement
authorPauli Nieminen <pauli.nieminen@linux.intel.com>
Wed, 11 Jan 2012 15:06:54 +0000 (17:06 +0200)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Tue, 3 Jul 2012 09:29:34 +0000 (12:29 +0300)
SGX may lockup because of incorrectly timed or missing power state
trasition for SGX or display controller.

To make future debugging simpler for these cases add command trace
entries for realeted power management changes.

Signed-off-by: Pauli Nieminen <pauli.nieminen@linux.intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
drivers/staging/mrst/drv/psb_irq.c
drivers/staging/mrst/drv/psb_powermgmt.c
drivers/staging/mrst/pvr/pvr_trace_cmd.c
drivers/staging/mrst/pvr/pvr_trace_cmd.h

index 082cd9d..8234eb7 100644 (file)
@@ -30,6 +30,7 @@
 #include "pnw_topaz.h"
 #include "psb_intel_reg.h"
 #include "psb_powermgmt.h"
+#include "pvr_trace_cmd.h"
 
 #include "mdfld_dsi_dbi_dpu.h"
 
@@ -89,11 +90,25 @@ mid_pipeconf(int pipe)
        BUG();
 }
 
+static void trcmd_vblank_power(unsigned type, int pipe)
+{
+       struct pvr_trcmd_power *p;
+       if (in_interrupt())
+               p = pvr_trcmd_reserve(type, 0, "irq", sizeof *p);
+       else
+               p = pvr_trcmd_reserve(type, task_tgid_nr(current),
+                               current->comm, sizeof *p);
+       p->dev = PVR_TRCMD_DEVICE_PIPE_A_VSYNC + pipe;
+       pvr_trcmd_commit(p);
+}
+
 void
 psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
 {
        if ((dev_priv->pipestat[pipe] & mask) != mask) {
                u32 reg = psb_pipestat(pipe);
+               if (mask & PIPE_VBLANK_INTERRUPT_ENABLE)
+                       trcmd_vblank_power(PVR_TRCMD_RESUME, pipe);
                dev_priv->pipestat[pipe] |= mask;
                /* Enable the interrupt, clear any pending status */
                if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
@@ -111,6 +126,8 @@ psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask)
 {
        if ((dev_priv->pipestat[pipe] & mask) != 0) {
                u32 reg = psb_pipestat(pipe);
+               if (mask & PIPE_VBLANK_INTERRUPT_ENABLE)
+                       trcmd_vblank_power(PVR_TRCMD_SUSPEND, pipe);
                dev_priv->pipestat[pipe] &= ~mask;
                if (ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_ONLY_IF_ON)) {
                        u32 writeVal = PSB_RVDC32(reg);
index 9975779..7923d50 100644 (file)
 #include "psb_msvdx.h"
 #include "pnw_topaz.h"
 #include "mdfld_gl3.h"
+#include "pvr_trace_cmd.h"
 
 #include <linux/mutex.h>
 #include "mdfld_dsi_dbi.h"
 #include "mdfld_dsi_dbi_dpu.h"
 #include <asm/intel_scu_ipc.h>
 
+
 #undef OSPM_GFX_DPK
 
 extern IMG_UINT32 gui32SGXDeviceID;
@@ -1177,6 +1179,18 @@ static void ospm_resume_display(struct drm_device *drm_dev)
        mdfld_restore_cursor_overlay_registers(drm_dev);
 }
 
+static void pvrcmd_device_power(unsigned type, enum pvr_trcmd_device dev)
+{
+       struct pvr_trcmd_power *p;
+       if (in_interrupt())
+               p = pvr_trcmd_reserve(type, 0, "irq", sizeof *p);
+       else
+               p = pvr_trcmd_reserve(type, task_tgid_nr(current),
+                               current->comm, sizeof *p);
+       p->dev = dev;
+       pvr_trcmd_commit(p);
+}
+
 /*
  * ospm_suspend_pci
  *
@@ -1198,6 +1212,7 @@ static void ospm_suspend_pci(struct pci_dev *pdev)
 #ifdef CONFIG_MDFD_GL3
        gl3_invalidate();
 #endif
+       pvrcmd_device_power(PVR_TRCMD_SUSPEND, PVR_TRCMD_DEVICE_PCI);
        /* Power off GL3 after all GFX sub-systems are powered off. */
        ospm_power_island_down(OSPM_GL3_CACHE_ISLAND);
 
@@ -1226,6 +1241,7 @@ static bool ospm_resume_pci(struct pci_dev *pdev)
 #ifdef OSPM_GFX_DPK
        printk(KERN_ALERT "ospm_resume_pci\n");
 #endif
+       pvrcmd_device_power(PVR_TRCMD_RESUME, PVR_TRCMD_DEVICE_PCI);
 
        pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM);
        pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT);
@@ -1338,6 +1354,9 @@ void ospm_power_island_up(int hw_islands)
 
 
                if (hw_islands & OSPM_GRAPHICS_ISLAND) {
+                       pvrcmd_device_power(PVR_TRCMD_RESUME,
+                                       PVR_TRCMD_DEVICE_SGX);
+
                        pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
                        pwr_mask |= PSB_PWRGT_GFX_MASK;
 #ifdef OSPM_STAT
@@ -1388,6 +1407,8 @@ void ospm_power_island_up(int hw_islands)
 
                spin_lock_irqsave(&dev_priv->ospm_lock, flags);
                pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
+               pvrcmd_device_power(PVR_TRCMD_RESUME,
+                               PVR_TRCMD_DEVICE_DISPC);
                pwr_cnt &= ~pwr_mask;
                outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
                spin_unlock_irqrestore(&dev_priv->ospm_lock, flags);
@@ -1467,6 +1488,7 @@ void ospm_power_island_down(int islands)
        g_hw_power_status_mask &= ~islands;
 
        if (islands & OSPM_GRAPHICS_ISLAND) {
+               pvrcmd_device_power(PVR_TRCMD_SUSPEND, PVR_TRCMD_DEVICE_SGX);
                pwr_cnt |= PSB_PWRGT_GFX_MASK;
                pwr_mask |= PSB_PWRGT_GFX_MASK;
 #ifdef OSPM_STAT
@@ -1519,6 +1541,7 @@ void ospm_power_island_down(int islands)
 
                outl(pwr_mask, (dev_priv->ospm_base + PSB_PM_SSC));
 
+               pvrcmd_device_power(PVR_TRCMD_SUSPEND, PVR_TRCMD_DEVICE_DISPC);
                pwr_mask = MDFLD_PWRGT_DISPLAY_STS_B0;
 
                cnt = 0;
index 7c2eba2..78c572f 100644 (file)
@@ -158,6 +158,23 @@ static size_t trcmd_prn_flpreq(char *dst, size_t dst_size, const void *tbuf)
        return len;
 }
 
+static const char * const trcmd_devices[] = {
+       [PVR_TRCMD_DEVICE_PCI]          = "PCI device",
+       [PVR_TRCMD_DEVICE_SGX]          = "SGX",
+       [PVR_TRCMD_DEVICE_DISPC]        = "Display controller",
+       [PVR_TRCMD_DEVICE_PIPE_A_VSYNC] = "Pipe A VSync",
+       [PVR_TRCMD_DEVICE_PIPE_B_VSYNC] = "Pipe B VSync",
+       [PVR_TRCMD_DEVICE_PIPE_C_VSYNC] = "Pipe C VSync",
+};
+
+static size_t trcmd_prn_power(char *dst, size_t dst_size, const void *tbuf)
+{
+       const struct pvr_trcmd_power *s = tbuf;
+
+       return scnprintf(dst, dst_size, "%*sdev %s\n", PVR_TRCMD_INDENT,
+                       "", trcmd_devices[s->dev]);
+}
+
 static struct trcmd_desc trcmd_desc_table[] = {
        [PVR_TRCMD_SGX_FIRSTKICK]    = { "sgx_first_kick", trcmd_prn_sgxkick },
        [PVR_TRCMD_SGX_KICK]         = { "sgx_kick", trcmd_prn_sgxkick },
@@ -167,6 +184,8 @@ static struct trcmd_desc trcmd_desc_table[] = {
        [PVR_TRCMD_FLPREQ]           = { "sgx_flip_req", trcmd_prn_flpreq },
        [PVR_TRCMD_FLPCOMP]          = { "sgx_flip_comp", trcmd_prn_syn },
        [PVR_TRCMD_SYN_REMOVE]       = { "sgx_syn_remove", trcmd_prn_syn },
+       [PVR_TRCMD_SUSPEND]          = { "pvr_suspend", trcmd_prn_power },
+       [PVR_TRCMD_RESUME]           = { "pvr_resume", trcmd_prn_power },
 };
 
 /* Modular add */
index 9b7cc6a..5a92255 100644 (file)
@@ -36,6 +36,8 @@ enum pvr_trcmd_type {
        PVR_TRCMD_SGX_QBLT_SYNCHK,
        PVR_TRCMD_FLPREQ,
        PVR_TRCMD_FLPCOMP,
+       PVR_TRCMD_SUSPEND,
+       PVR_TRCMD_RESUME,
 };
 
 struct pvr_trcmd_buf;
@@ -69,6 +71,19 @@ struct pvr_trcmd_flpreq {
        struct pvr_trcmd_syn    src_syn[2];
 };
 
+enum pvr_trcmd_device {
+       PVR_TRCMD_DEVICE_PCI,
+       PVR_TRCMD_DEVICE_SGX,
+       PVR_TRCMD_DEVICE_DISPC,
+       PVR_TRCMD_DEVICE_PIPE_A_VSYNC,
+       PVR_TRCMD_DEVICE_PIPE_B_VSYNC,
+       PVR_TRCMD_DEVICE_PIPE_C_VSYNC,
+};
+
+struct pvr_trcmd_power {
+       enum pvr_trcmd_device dev;
+};
+
 #ifdef CONFIG_PVR_TRACE_CMD
 
 void *pvr_trcmd_reserve(unsigned type, int pid, const char *pname,