aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@nokia.com>2009-12-17 07:35:21 -0500
committerTomi Valkeinen <tomi.valkeinen@nokia.com>2010-01-08 08:32:18 -0500
commitdfc0fd8d8850ef11951ba6c251e06096d1b5a0bd (patch)
treeb80a85226218abbb562c93b7777de8bbda2c5db2
parentff90a3488d98a63bf24bff37f77a9a37b00e7a54 (diff)
OMAP: DSS2: Collect interrupt statistics
Collect interrupt statistics, printable via debugfs: debugfs/omapdss/dispc_irq debugfs/omapdss/dsi_irq The counters are reset when printed. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
-rw-r--r--drivers/video/omap2/dss/Kconfig7
-rw-r--r--drivers/video/omap2/dss/core.c8
-rw-r--r--drivers/video/omap2/dss/dispc.c67
-rw-r--r--drivers/video/omap2/dss/dsi.c125
-rw-r--r--drivers/video/omap2/dss/dss.h14
5 files changed, 221 insertions, 0 deletions
diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/omap2/dss/Kconfig
index 71d8dec30635..c63ce767b277 100644
--- a/drivers/video/omap2/dss/Kconfig
+++ b/drivers/video/omap2/dss/Kconfig
@@ -25,6 +25,13 @@ config OMAP2_DSS_DEBUG_SUPPORT
25 This enables debug messages. You need to enable printing 25 This enables debug messages. You need to enable printing
26 with 'debug' module parameter. 26 with 'debug' module parameter.
27 27
28config OMAP2_DSS_COLLECT_IRQ_STATS
29 bool "Collect DSS IRQ statistics"
30 depends on OMAP2_DSS_DEBUG_SUPPORT
31 default n
32 help
33 Collect DSS IRQ statistics, printable via debugfs
34
28config OMAP2_DSS_RFBI 35config OMAP2_DSS_RFBI
29 bool "RFBI support" 36 bool "RFBI support"
30 default n 37 default n
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
index 29497a0c9a91..dbb0ce243f0c 100644
--- a/drivers/video/omap2/dss/core.c
+++ b/drivers/video/omap2/dss/core.c
@@ -395,6 +395,14 @@ static int dss_initialize_debugfs(void)
395 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir, 395 debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
396 &dss_debug_dump_clocks, &dss_debug_fops); 396 &dss_debug_dump_clocks, &dss_debug_fops);
397 397
398 debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir,
399 &dispc_dump_irqs, &dss_debug_fops);
400
401#ifdef CONFIG_OMAP2_DSS_DSI
402 debugfs_create_file("dsi_irq", S_IRUGO, dss_debugfs_dir,
403 &dsi_dump_irqs, &dss_debug_fops);
404#endif
405
398 debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir, 406 debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
399 &dss_dump_regs, &dss_debug_fops); 407 &dss_dump_regs, &dss_debug_fops);
400 debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir, 408 debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index 6dabf4b2f005..e2e0f9ae7353 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -148,6 +148,12 @@ static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES,
148 DISPC_VID_ATTRIBUTES(0), 148 DISPC_VID_ATTRIBUTES(0),
149 DISPC_VID_ATTRIBUTES(1) }; 149 DISPC_VID_ATTRIBUTES(1) };
150 150
151struct dispc_irq_stats {
152 unsigned long last_reset;
153 unsigned irq_count;
154 unsigned irqs[32];
155};
156
151static struct { 157static struct {
152 void __iomem *base; 158 void __iomem *base;
153 159
@@ -160,6 +166,11 @@ static struct {
160 struct work_struct error_work; 166 struct work_struct error_work;
161 167
162 u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; 168 u32 ctx[DISPC_SZ_REGS / sizeof(u32)];
169
170#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
171 spinlock_t irq_stats_lock;
172 struct dispc_irq_stats irq_stats;
173#endif
163} dispc; 174} dispc;
164 175
165static void _omap_dispc_set_irqs(void); 176static void _omap_dispc_set_irqs(void);
@@ -2247,6 +2258,50 @@ void dispc_dump_clocks(struct seq_file *s)
2247 enable_clocks(0); 2258 enable_clocks(0);
2248} 2259}
2249 2260
2261#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2262void dispc_dump_irqs(struct seq_file *s)
2263{
2264 unsigned long flags;
2265 struct dispc_irq_stats stats;
2266
2267 spin_lock_irqsave(&dispc.irq_stats_lock, flags);
2268
2269 stats = dispc.irq_stats;
2270 memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats));
2271 dispc.irq_stats.last_reset = jiffies;
2272
2273 spin_unlock_irqrestore(&dispc.irq_stats_lock, flags);
2274
2275 seq_printf(s, "period %u ms\n",
2276 jiffies_to_msecs(jiffies - stats.last_reset));
2277
2278 seq_printf(s, "irqs %d\n", stats.irq_count);
2279#define PIS(x) \
2280 seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]);
2281
2282 PIS(FRAMEDONE);
2283 PIS(VSYNC);
2284 PIS(EVSYNC_EVEN);
2285 PIS(EVSYNC_ODD);
2286 PIS(ACBIAS_COUNT_STAT);
2287 PIS(PROG_LINE_NUM);
2288 PIS(GFX_FIFO_UNDERFLOW);
2289 PIS(GFX_END_WIN);
2290 PIS(PAL_GAMMA_MASK);
2291 PIS(OCP_ERR);
2292 PIS(VID1_FIFO_UNDERFLOW);
2293 PIS(VID1_END_WIN);
2294 PIS(VID2_FIFO_UNDERFLOW);
2295 PIS(VID2_END_WIN);
2296 PIS(SYNC_LOST);
2297 PIS(SYNC_LOST_DIGIT);
2298 PIS(WAKEUP);
2299#undef PIS
2300}
2301#else
2302void dispc_dump_irqs(struct seq_file *s) { }
2303#endif
2304
2250void dispc_dump_regs(struct seq_file *s) 2305void dispc_dump_regs(struct seq_file *s)
2251{ 2306{
2252#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) 2307#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r))
@@ -2665,6 +2720,13 @@ void dispc_irq_handler(void)
2665 2720
2666 irqstatus = dispc_read_reg(DISPC_IRQSTATUS); 2721 irqstatus = dispc_read_reg(DISPC_IRQSTATUS);
2667 2722
2723#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
2724 spin_lock(&dispc.irq_stats_lock);
2725 dispc.irq_stats.irq_count++;
2726 dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs);
2727 spin_unlock(&dispc.irq_stats_lock);
2728#endif
2729
2668#ifdef DEBUG 2730#ifdef DEBUG
2669 if (dss_debug) 2731 if (dss_debug)
2670 print_irq_status(irqstatus); 2732 print_irq_status(irqstatus);
@@ -3012,6 +3074,11 @@ int dispc_init(void)
3012 3074
3013 spin_lock_init(&dispc.irq_lock); 3075 spin_lock_init(&dispc.irq_lock);
3014 3076
3077#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3078 spin_lock_init(&dispc.irq_stats_lock);
3079 dispc.irq_stats.last_reset = jiffies;
3080#endif
3081
3015 INIT_WORK(&dispc.error_work, dispc_error_worker); 3082 INIT_WORK(&dispc.error_work, dispc_error_worker);
3016 3083
3017 dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); 3084 dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS);
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
index e65056317a28..03f85df70749 100644
--- a/drivers/video/omap2/dss/dsi.c
+++ b/drivers/video/omap2/dss/dsi.c
@@ -204,6 +204,14 @@ struct dsi_update_region {
204 struct omap_dss_device *device; 204 struct omap_dss_device *device;
205}; 205};
206 206
207struct dsi_irq_stats {
208 unsigned long last_reset;
209 unsigned irq_count;
210 unsigned dsi_irqs[32];
211 unsigned vc_irqs[4][32];
212 unsigned cio_irqs[32];
213};
214
207static struct 215static struct
208{ 216{
209 void __iomem *base; 217 void __iomem *base;
@@ -258,6 +266,11 @@ static struct
258#endif 266#endif
259 int debug_read; 267 int debug_read;
260 int debug_write; 268 int debug_write;
269
270#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
271 spinlock_t irq_stats_lock;
272 struct dsi_irq_stats irq_stats;
273#endif
261} dsi; 274} dsi;
262 275
263#ifdef DEBUG 276#ifdef DEBUG
@@ -528,6 +541,12 @@ void dsi_irq_handler(void)
528 541
529 irqstatus = dsi_read_reg(DSI_IRQSTATUS); 542 irqstatus = dsi_read_reg(DSI_IRQSTATUS);
530 543
544#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
545 spin_lock(&dsi.irq_stats_lock);
546 dsi.irq_stats.irq_count++;
547 dss_collect_irq_stats(irqstatus, dsi.irq_stats.dsi_irqs);
548#endif
549
531 if (irqstatus & DSI_IRQ_ERROR_MASK) { 550 if (irqstatus & DSI_IRQ_ERROR_MASK) {
532 DSSERR("DSI error, irqstatus %x\n", irqstatus); 551 DSSERR("DSI error, irqstatus %x\n", irqstatus);
533 print_irq_status(irqstatus); 552 print_irq_status(irqstatus);
@@ -549,6 +568,10 @@ void dsi_irq_handler(void)
549 568
550 vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i)); 569 vcstatus = dsi_read_reg(DSI_VC_IRQSTATUS(i));
551 570
571#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
572 dss_collect_irq_stats(vcstatus, dsi.irq_stats.vc_irqs[i]);
573#endif
574
552 if (vcstatus & DSI_VC_IRQ_BTA) 575 if (vcstatus & DSI_VC_IRQ_BTA)
553 complete(&dsi.bta_completion); 576 complete(&dsi.bta_completion);
554 577
@@ -568,6 +591,10 @@ void dsi_irq_handler(void)
568 if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) { 591 if (irqstatus & DSI_IRQ_COMPLEXIO_ERR) {
569 ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); 592 ciostatus = dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
570 593
594#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
595 dss_collect_irq_stats(ciostatus, dsi.irq_stats.cio_irqs);
596#endif
597
571 dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus); 598 dsi_write_reg(DSI_COMPLEXIO_IRQ_STATUS, ciostatus);
572 /* flush posted write */ 599 /* flush posted write */
573 dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS); 600 dsi_read_reg(DSI_COMPLEXIO_IRQ_STATUS);
@@ -579,6 +606,10 @@ void dsi_irq_handler(void)
579 dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK); 606 dsi_write_reg(DSI_IRQSTATUS, irqstatus & ~DSI_IRQ_CHANNEL_MASK);
580 /* flush posted write */ 607 /* flush posted write */
581 dsi_read_reg(DSI_IRQSTATUS); 608 dsi_read_reg(DSI_IRQSTATUS);
609
610#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
611 spin_unlock(&dsi.irq_stats_lock);
612#endif
582} 613}
583 614
584 615
@@ -1226,6 +1257,95 @@ void dsi_dump_clocks(struct seq_file *s)
1226 enable_clocks(0); 1257 enable_clocks(0);
1227} 1258}
1228 1259
1260#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
1261void dsi_dump_irqs(struct seq_file *s)
1262{
1263 unsigned long flags;
1264 struct dsi_irq_stats stats;
1265
1266 spin_lock_irqsave(&dsi.irq_stats_lock, flags);
1267
1268 stats = dsi.irq_stats;
1269 memset(&dsi.irq_stats, 0, sizeof(dsi.irq_stats));
1270 dsi.irq_stats.last_reset = jiffies;
1271
1272 spin_unlock_irqrestore(&dsi.irq_stats_lock, flags);
1273
1274 seq_printf(s, "period %u ms\n",
1275 jiffies_to_msecs(jiffies - stats.last_reset));
1276
1277 seq_printf(s, "irqs %d\n", stats.irq_count);
1278#define PIS(x) \
1279 seq_printf(s, "%-20s %10d\n", #x, stats.dsi_irqs[ffs(DSI_IRQ_##x)-1]);
1280
1281 seq_printf(s, "-- DSI interrupts --\n");
1282 PIS(VC0);
1283 PIS(VC1);
1284 PIS(VC2);
1285 PIS(VC3);
1286 PIS(WAKEUP);
1287 PIS(RESYNC);
1288 PIS(PLL_LOCK);
1289 PIS(PLL_UNLOCK);
1290 PIS(PLL_RECALL);
1291 PIS(COMPLEXIO_ERR);
1292 PIS(HS_TX_TIMEOUT);
1293 PIS(LP_RX_TIMEOUT);
1294 PIS(TE_TRIGGER);
1295 PIS(ACK_TRIGGER);
1296 PIS(SYNC_LOST);
1297 PIS(LDO_POWER_GOOD);
1298 PIS(TA_TIMEOUT);
1299#undef PIS
1300
1301#define PIS(x) \
1302 seq_printf(s, "%-20s %10d %10d %10d %10d\n", #x, \
1303 stats.vc_irqs[0][ffs(DSI_VC_IRQ_##x)-1], \
1304 stats.vc_irqs[1][ffs(DSI_VC_IRQ_##x)-1], \
1305 stats.vc_irqs[2][ffs(DSI_VC_IRQ_##x)-1], \
1306 stats.vc_irqs[3][ffs(DSI_VC_IRQ_##x)-1]);
1307
1308 seq_printf(s, "-- VC interrupts --\n");
1309 PIS(CS);
1310 PIS(ECC_CORR);
1311 PIS(PACKET_SENT);
1312 PIS(FIFO_TX_OVF);
1313 PIS(FIFO_RX_OVF);
1314 PIS(BTA);
1315 PIS(ECC_NO_CORR);
1316 PIS(FIFO_TX_UDF);
1317 PIS(PP_BUSY_CHANGE);
1318#undef PIS
1319
1320#define PIS(x) \
1321 seq_printf(s, "%-20s %10d\n", #x, \
1322 stats.cio_irqs[ffs(DSI_CIO_IRQ_##x)-1]);
1323
1324 seq_printf(s, "-- CIO interrupts --\n");
1325 PIS(ERRSYNCESC1);
1326 PIS(ERRSYNCESC2);
1327 PIS(ERRSYNCESC3);
1328 PIS(ERRESC1);
1329 PIS(ERRESC2);
1330 PIS(ERRESC3);
1331 PIS(ERRCONTROL1);
1332 PIS(ERRCONTROL2);
1333 PIS(ERRCONTROL3);
1334 PIS(STATEULPS1);
1335 PIS(STATEULPS2);
1336 PIS(STATEULPS3);
1337 PIS(ERRCONTENTIONLP0_1);
1338 PIS(ERRCONTENTIONLP1_1);
1339 PIS(ERRCONTENTIONLP0_2);
1340 PIS(ERRCONTENTIONLP1_2);
1341 PIS(ERRCONTENTIONLP0_3);
1342 PIS(ERRCONTENTIONLP1_3);
1343 PIS(ULPSACTIVENOT_ALL0);
1344 PIS(ULPSACTIVENOT_ALL1);
1345#undef PIS
1346}
1347#endif
1348
1229void dsi_dump_regs(struct seq_file *s) 1349void dsi_dump_regs(struct seq_file *s)
1230{ 1350{
1231#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r)) 1351#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dsi_read_reg(r))
@@ -3637,6 +3757,11 @@ int dsi_init(struct platform_device *pdev)
3637 spin_lock_init(&dsi.errors_lock); 3757 spin_lock_init(&dsi.errors_lock);
3638 dsi.errors = 0; 3758 dsi.errors = 0;
3639 3759
3760#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
3761 spin_lock_init(&dsi.irq_stats_lock);
3762 dsi.irq_stats.last_reset = jiffies;
3763#endif
3764
3640 init_completion(&dsi.bta_completion); 3765 init_completion(&dsi.bta_completion);
3641 init_completion(&dsi.update_completion); 3766 init_completion(&dsi.update_completion);
3642 3767
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index 8da5ac42151b..2bcb1245d6c2 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -240,6 +240,7 @@ int dsi_init(struct platform_device *pdev);
240void dsi_exit(void); 240void dsi_exit(void);
241 241
242void dsi_dump_clocks(struct seq_file *s); 242void dsi_dump_clocks(struct seq_file *s);
243void dsi_dump_irqs(struct seq_file *s);
243void dsi_dump_regs(struct seq_file *s); 244void dsi_dump_regs(struct seq_file *s);
244 245
245void dsi_save_context(void); 246void dsi_save_context(void);
@@ -268,6 +269,7 @@ int dpi_init_display(struct omap_dss_device *dssdev);
268int dispc_init(void); 269int dispc_init(void);
269void dispc_exit(void); 270void dispc_exit(void);
270void dispc_dump_clocks(struct seq_file *s); 271void dispc_dump_clocks(struct seq_file *s);
272void dispc_dump_irqs(struct seq_file *s);
271void dispc_dump_regs(struct seq_file *s); 273void dispc_dump_regs(struct seq_file *s);
272void dispc_irq_handler(void); 274void dispc_irq_handler(void);
273void dispc_fake_vsync_irq(void); 275void dispc_fake_vsync_irq(void);
@@ -367,4 +369,16 @@ void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
367unsigned long rfbi_get_max_tx_rate(void); 369unsigned long rfbi_get_max_tx_rate(void);
368int rfbi_init_display(struct omap_dss_device *display); 370int rfbi_init_display(struct omap_dss_device *display);
369 371
372
373#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
374static inline void dss_collect_irq_stats(u32 irqstatus, unsigned *irq_arr)
375{
376 int b;
377 for (b = 0; b < 32; ++b) {
378 if (irqstatus & (1 << b))
379 irq_arr[b]++;
380 }
381}
382#endif
383
370#endif 384#endif