diff options
Diffstat (limited to 'drivers/gpu/nvgpu/gk20a')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/cde_gk20a.c | 45 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/cde_gk20a.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/ce2_gk20a.c | 24 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/ce2_gk20a.h | 6 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 10 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/debug_gk20a.c | 425 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/debug_gk20a.h | 41 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | 414 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/fifo_gk20a.h | 7 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 6 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.c | 22 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gr_gk20a.h | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/hal_gk20a.c | 1 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.c | 16 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/mm_gk20a.h | 3 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | 487 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | 7 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/sched_gk20a.c | 67 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/sched_gk20a.h | 1 |
19 files changed, 88 insertions, 1496 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c index a0160274..084f1793 100644 --- a/drivers/gpu/nvgpu/gk20a/cde_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/cde_gk20a.c | |||
@@ -18,9 +18,6 @@ | |||
18 | 18 | ||
19 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
21 | #ifdef CONFIG_DEBUG_FS | ||
22 | #include <linux/debugfs.h> | ||
23 | #endif | ||
24 | #include <linux/dma-buf.h> | 21 | #include <linux/dma-buf.h> |
25 | 22 | ||
26 | #include <trace/events/gk20a.h> | 23 | #include <trace/events/gk20a.h> |
@@ -40,8 +37,6 @@ | |||
40 | #include "cde_gk20a.h" | 37 | #include "cde_gk20a.h" |
41 | #include "fence_gk20a.h" | 38 | #include "fence_gk20a.h" |
42 | #include "gr_gk20a.h" | 39 | #include "gr_gk20a.h" |
43 | #include "debug_gk20a.h" | ||
44 | #include "platform_gk20a.h" | ||
45 | 40 | ||
46 | #include <nvgpu/hw/gk20a/hw_ccsr_gk20a.h> | 41 | #include <nvgpu/hw/gk20a/hw_ccsr_gk20a.h> |
47 | #include <nvgpu/hw/gk20a/hw_pbdma_gk20a.h> | 42 | #include <nvgpu/hw/gk20a/hw_pbdma_gk20a.h> |
@@ -1585,8 +1580,7 @@ int gk20a_prepare_compressible_read( | |||
1585 | if (IS_ERR(dmabuf)) | 1580 | if (IS_ERR(dmabuf)) |
1586 | return -EINVAL; | 1581 | return -EINVAL; |
1587 | 1582 | ||
1588 | err = gk20a_dmabuf_get_state(dmabuf, dev_from_gk20a(g), | 1583 | err = gk20a_dmabuf_get_state(dmabuf, g, offset, &state); |
1589 | offset, &state); | ||
1590 | if (err) { | 1584 | if (err) { |
1591 | dma_buf_put(dmabuf); | 1585 | dma_buf_put(dmabuf); |
1592 | return err; | 1586 | return err; |
@@ -1650,7 +1644,7 @@ int gk20a_mark_compressible_write(struct gk20a *g, u32 buffer_fd, | |||
1650 | return -EINVAL; | 1644 | return -EINVAL; |
1651 | } | 1645 | } |
1652 | 1646 | ||
1653 | err = gk20a_dmabuf_get_state(dmabuf, dev_from_gk20a(g), offset, &state); | 1647 | err = gk20a_dmabuf_get_state(dmabuf, g, offset, &state); |
1654 | if (err) { | 1648 | if (err) { |
1655 | nvgpu_err(g, "could not get state from dmabuf"); | 1649 | nvgpu_err(g, "could not get state from dmabuf"); |
1656 | dma_buf_put(dmabuf); | 1650 | dma_buf_put(dmabuf); |
@@ -1671,38 +1665,3 @@ int gk20a_mark_compressible_write(struct gk20a *g, u32 buffer_fd, | |||
1671 | dma_buf_put(dmabuf); | 1665 | dma_buf_put(dmabuf); |
1672 | return 0; | 1666 | return 0; |
1673 | } | 1667 | } |
1674 | |||
1675 | #ifdef CONFIG_DEBUG_FS | ||
1676 | static ssize_t gk20a_cde_reload_write(struct file *file, | ||
1677 | const char __user *userbuf, size_t count, loff_t *ppos) | ||
1678 | { | ||
1679 | struct gk20a *g = file->private_data; | ||
1680 | gk20a_cde_reload(g); | ||
1681 | return count; | ||
1682 | } | ||
1683 | |||
1684 | static const struct file_operations gk20a_cde_reload_fops = { | ||
1685 | .open = simple_open, | ||
1686 | .write = gk20a_cde_reload_write, | ||
1687 | }; | ||
1688 | |||
1689 | void gk20a_cde_debugfs_init(struct device *dev) | ||
1690 | { | ||
1691 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
1692 | struct gk20a *g = get_gk20a(dev); | ||
1693 | |||
1694 | if (!platform->has_cde) | ||
1695 | return; | ||
1696 | |||
1697 | debugfs_create_u32("cde_parameter", S_IWUSR | S_IRUGO, | ||
1698 | platform->debugfs, &g->cde_app.shader_parameter); | ||
1699 | debugfs_create_u32("cde_ctx_count", S_IWUSR | S_IRUGO, | ||
1700 | platform->debugfs, &g->cde_app.ctx_count); | ||
1701 | debugfs_create_u32("cde_ctx_usecount", S_IWUSR | S_IRUGO, | ||
1702 | platform->debugfs, &g->cde_app.ctx_usecount); | ||
1703 | debugfs_create_u32("cde_ctx_count_top", S_IWUSR | S_IRUGO, | ||
1704 | platform->debugfs, &g->cde_app.ctx_count_top); | ||
1705 | debugfs_create_file("reload_cde_firmware", S_IWUSR, platform->debugfs, | ||
1706 | g, &gk20a_cde_reload_fops); | ||
1707 | } | ||
1708 | #endif | ||
diff --git a/drivers/gpu/nvgpu/gk20a/cde_gk20a.h b/drivers/gpu/nvgpu/gk20a/cde_gk20a.h index ffd55b4d..4f400bf3 100644 --- a/drivers/gpu/nvgpu/gk20a/cde_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/cde_gk20a.h | |||
@@ -295,7 +295,6 @@ int gk20a_cde_convert(struct gk20a *g, | |||
295 | struct nvgpu_fence *fence, | 295 | struct nvgpu_fence *fence, |
296 | u32 __flags, struct gk20a_cde_param *params, | 296 | u32 __flags, struct gk20a_cde_param *params, |
297 | int num_params, struct gk20a_fence **fence_out); | 297 | int num_params, struct gk20a_fence **fence_out); |
298 | void gk20a_cde_debugfs_init(struct device *dev); | ||
299 | 298 | ||
300 | int gk20a_prepare_compressible_read( | 299 | int gk20a_prepare_compressible_read( |
301 | struct gk20a *g, u32 buffer_fd, u32 request, u64 offset, | 300 | struct gk20a *g, u32 buffer_fd, u32 request, u64 offset, |
diff --git a/drivers/gpu/nvgpu/gk20a/ce2_gk20a.c b/drivers/gpu/nvgpu/gk20a/ce2_gk20a.c index 1ed90b14..c905bedb 100644 --- a/drivers/gpu/nvgpu/gk20a/ce2_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/ce2_gk20a.c | |||
@@ -13,15 +13,10 @@ | |||
13 | * more details. | 13 | * more details. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #ifdef CONFIG_DEBUG_FS | ||
17 | #include <linux/debugfs.h> | ||
18 | #endif | ||
19 | |||
20 | #include <nvgpu/kmem.h> | 16 | #include <nvgpu/kmem.h> |
21 | #include <nvgpu/dma.h> | 17 | #include <nvgpu/dma.h> |
22 | 18 | ||
23 | #include "gk20a.h" | 19 | #include "gk20a.h" |
24 | #include "debug_gk20a.h" | ||
25 | 20 | ||
26 | #include <nvgpu/log.h> | 21 | #include <nvgpu/log.h> |
27 | 22 | ||
@@ -33,10 +28,6 @@ | |||
33 | #include <nvgpu/hw/gk20a/hw_mc_gk20a.h> | 28 | #include <nvgpu/hw/gk20a/hw_mc_gk20a.h> |
34 | #include <nvgpu/hw/gk20a/hw_gr_gk20a.h> | 29 | #include <nvgpu/hw/gk20a/hw_gr_gk20a.h> |
35 | 30 | ||
36 | #ifdef CONFIG_DEBUG_FS | ||
37 | #include "platform_gk20a.h" | ||
38 | #endif | ||
39 | |||
40 | static u32 ce2_nonblockpipe_isr(struct gk20a *g, u32 fifo_intr) | 31 | static u32 ce2_nonblockpipe_isr(struct gk20a *g, u32 fifo_intr) |
41 | { | 32 | { |
42 | gk20a_dbg(gpu_dbg_intr, "ce2 non-blocking pipe interrupt\n"); | 33 | gk20a_dbg(gpu_dbg_intr, "ce2 non-blocking pipe interrupt\n"); |
@@ -728,18 +719,3 @@ void gk20a_ce_delete_context_priv(struct gk20a *g, | |||
728 | return; | 719 | return; |
729 | } | 720 | } |
730 | EXPORT_SYMBOL(gk20a_ce_delete_context); | 721 | EXPORT_SYMBOL(gk20a_ce_delete_context); |
731 | |||
732 | #ifdef CONFIG_DEBUG_FS | ||
733 | void gk20a_ce_debugfs_init(struct device *dev) | ||
734 | { | ||
735 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
736 | struct gk20a *g = get_gk20a(dev); | ||
737 | |||
738 | debugfs_create_u32("ce_app_ctx_count", S_IWUSR | S_IRUGO, | ||
739 | platform->debugfs, &g->ce_app.ctx_count); | ||
740 | debugfs_create_u32("ce_app_state", S_IWUSR | S_IRUGO, | ||
741 | platform->debugfs, &g->ce_app.app_state); | ||
742 | debugfs_create_u32("ce_app_next_ctx_id", S_IWUSR | S_IRUGO, | ||
743 | platform->debugfs, &g->ce_app.next_ctx_id); | ||
744 | } | ||
745 | #endif | ||
diff --git a/drivers/gpu/nvgpu/gk20a/ce2_gk20a.h b/drivers/gpu/nvgpu/gk20a/ce2_gk20a.h index dfd19019..f972e175 100644 --- a/drivers/gpu/nvgpu/gk20a/ce2_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/ce2_gk20a.h | |||
@@ -156,10 +156,4 @@ void gk20a_ce_delete_context_priv(struct gk20a *g, | |||
156 | void gk20a_ce_delete_context(struct gk20a *g, | 156 | void gk20a_ce_delete_context(struct gk20a *g, |
157 | u32 ce_ctx_id); | 157 | u32 ce_ctx_id); |
158 | 158 | ||
159 | |||
160 | #ifdef CONFIG_DEBUG_FS | ||
161 | /* CE app debugfs api */ | ||
162 | void gk20a_ce_debugfs_init(struct device *dev); | ||
163 | #endif | ||
164 | |||
165 | #endif /*__CE2_GK20A_H__*/ | 159 | #endif /*__CE2_GK20A_H__*/ |
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c index 571570d8..13abed95 100644 --- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |||
@@ -30,9 +30,9 @@ | |||
30 | #include <nvgpu/circ_buf.h> | 30 | #include <nvgpu/circ_buf.h> |
31 | #include <nvgpu/cond.h> | 31 | #include <nvgpu/cond.h> |
32 | #include <nvgpu/enabled.h> | 32 | #include <nvgpu/enabled.h> |
33 | #include <nvgpu/debug.h> | ||
33 | 34 | ||
34 | #include "gk20a.h" | 35 | #include "gk20a.h" |
35 | #include "debug_gk20a.h" | ||
36 | #include "ctxsw_trace_gk20a.h" | 36 | #include "ctxsw_trace_gk20a.h" |
37 | #include "dbg_gpu_gk20a.h" | 37 | #include "dbg_gpu_gk20a.h" |
38 | #include "fence_gk20a.h" | 38 | #include "fence_gk20a.h" |
@@ -1403,6 +1403,7 @@ static u32 get_gp_free_count(struct channel_gk20a *c) | |||
1403 | return gp_free_count(c); | 1403 | return gp_free_count(c); |
1404 | } | 1404 | } |
1405 | 1405 | ||
1406 | #ifdef CONFIG_DEBUG_FS | ||
1406 | static void trace_write_pushbuffer(struct channel_gk20a *c, | 1407 | static void trace_write_pushbuffer(struct channel_gk20a *c, |
1407 | struct nvgpu_gpfifo *g) | 1408 | struct nvgpu_gpfifo *g) |
1408 | { | 1409 | { |
@@ -1439,6 +1440,7 @@ static void trace_write_pushbuffer(struct channel_gk20a *c, | |||
1439 | dma_buf_vunmap(dmabuf, mem); | 1440 | dma_buf_vunmap(dmabuf, mem); |
1440 | } | 1441 | } |
1441 | } | 1442 | } |
1443 | #endif | ||
1442 | 1444 | ||
1443 | static void trace_write_pushbuffer_range(struct channel_gk20a *c, | 1445 | static void trace_write_pushbuffer_range(struct channel_gk20a *c, |
1444 | struct nvgpu_gpfifo *g, | 1446 | struct nvgpu_gpfifo *g, |
@@ -1446,6 +1448,7 @@ static void trace_write_pushbuffer_range(struct channel_gk20a *c, | |||
1446 | int offset, | 1448 | int offset, |
1447 | int count) | 1449 | int count) |
1448 | { | 1450 | { |
1451 | #ifdef CONFIG_DEBUG_FS | ||
1449 | u32 size; | 1452 | u32 size; |
1450 | int i; | 1453 | int i; |
1451 | struct nvgpu_gpfifo *gp; | 1454 | struct nvgpu_gpfifo *gp; |
@@ -1478,6 +1481,7 @@ static void trace_write_pushbuffer_range(struct channel_gk20a *c, | |||
1478 | 1481 | ||
1479 | if (gpfifo_allocated) | 1482 | if (gpfifo_allocated) |
1480 | nvgpu_big_free(c->g, g); | 1483 | nvgpu_big_free(c->g, g); |
1484 | #endif | ||
1481 | } | 1485 | } |
1482 | 1486 | ||
1483 | static void __gk20a_channel_timeout_start(struct channel_gk20a *ch) | 1487 | static void __gk20a_channel_timeout_start(struct channel_gk20a *ch) |
@@ -1629,8 +1633,8 @@ static void gk20a_channel_timeout_handler(struct channel_gk20a *ch) | |||
1629 | nvgpu_err(g, "Job on channel %d timed out", | 1633 | nvgpu_err(g, "Job on channel %d timed out", |
1630 | ch->hw_chid); | 1634 | ch->hw_chid); |
1631 | 1635 | ||
1632 | gk20a_debug_dump(g->dev); | 1636 | gk20a_debug_dump(g); |
1633 | gk20a_gr_debug_dump(g->dev); | 1637 | gk20a_gr_debug_dump(g); |
1634 | 1638 | ||
1635 | g->ops.fifo.force_reset_ch(ch, | 1639 | g->ops.fifo.force_reset_ch(ch, |
1636 | NVGPU_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT, true); | 1640 | NVGPU_CHANNEL_FIFO_ERROR_IDLE_TIMEOUT, true); |
diff --git a/drivers/gpu/nvgpu/gk20a/debug_gk20a.c b/drivers/gpu/nvgpu/gk20a/debug_gk20a.c deleted file mode 100644 index ac435046..00000000 --- a/drivers/gpu/nvgpu/gk20a/debug_gk20a.c +++ /dev/null | |||
@@ -1,425 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011-2017 NVIDIA Corporation. All rights reserved. | ||
3 | * | ||
4 | * This software is licensed under the terms of the GNU General Public | ||
5 | * License version 2, as published by the Free Software Foundation, and | ||
6 | * may be copied, distributed, and modified under those terms. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #ifdef CONFIG_DEBUG_FS | ||
16 | #include <linux/debugfs.h> | ||
17 | #endif | ||
18 | #include <linux/seq_file.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/fs.h> | ||
21 | |||
22 | #include <nvgpu/log.h> | ||
23 | #include <nvgpu/kmem.h> | ||
24 | #include <nvgpu/semaphore.h> | ||
25 | #include <nvgpu/log.h> | ||
26 | |||
27 | #include "gk20a.h" | ||
28 | #include "gk20a/platform_gk20a.h" | ||
29 | #include "debug_gk20a.h" | ||
30 | |||
31 | #include <nvgpu/hw/gk20a/hw_ram_gk20a.h> | ||
32 | #include <nvgpu/hw/gk20a/hw_fifo_gk20a.h> | ||
33 | #include <nvgpu/hw/gk20a/hw_ccsr_gk20a.h> | ||
34 | #include <nvgpu/hw/gk20a/hw_pbdma_gk20a.h> | ||
35 | |||
36 | unsigned int gk20a_debug_trace_cmdbuf; | ||
37 | |||
38 | static inline void gk20a_debug_write_printk(void *ctx, const char *str, | ||
39 | size_t len) | ||
40 | { | ||
41 | pr_info("%s", str); | ||
42 | } | ||
43 | |||
44 | static inline void gk20a_debug_write_to_seqfile(void *ctx, const char *str, | ||
45 | size_t len) | ||
46 | { | ||
47 | seq_write((struct seq_file *)ctx, str, len); | ||
48 | } | ||
49 | |||
50 | void gk20a_debug_output(struct gk20a_debug_output *o, | ||
51 | const char *fmt, ...) | ||
52 | { | ||
53 | va_list args; | ||
54 | int len; | ||
55 | |||
56 | va_start(args, fmt); | ||
57 | len = vsnprintf(o->buf, sizeof(o->buf), fmt, args); | ||
58 | va_end(args); | ||
59 | o->fn(o->ctx, o->buf, len); | ||
60 | } | ||
61 | |||
62 | static void gk20a_debug_dump_all_channel_status_ramfc(struct gk20a *g, | ||
63 | struct gk20a_debug_output *o) | ||
64 | { | ||
65 | struct fifo_gk20a *f = &g->fifo; | ||
66 | u32 chid; | ||
67 | struct ch_state **ch_state; | ||
68 | |||
69 | ch_state = nvgpu_kzalloc(g, sizeof(*ch_state) * f->num_channels); | ||
70 | if (!ch_state) { | ||
71 | gk20a_debug_output(o, "cannot alloc memory for channels\n"); | ||
72 | return; | ||
73 | } | ||
74 | |||
75 | for (chid = 0; chid < f->num_channels; chid++) { | ||
76 | struct channel_gk20a *ch = &f->channel[chid]; | ||
77 | if (gk20a_channel_get(ch)) { | ||
78 | ch_state[chid] = | ||
79 | nvgpu_kmalloc(g, sizeof(struct ch_state) + | ||
80 | ram_in_alloc_size_v()); | ||
81 | /* ref taken stays to below loop with | ||
82 | * successful allocs */ | ||
83 | if (!ch_state[chid]) | ||
84 | gk20a_channel_put(ch); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | for (chid = 0; chid < f->num_channels; chid++) { | ||
89 | struct channel_gk20a *ch = &f->channel[chid]; | ||
90 | if (!ch_state[chid]) | ||
91 | continue; | ||
92 | |||
93 | ch_state[chid]->pid = ch->pid; | ||
94 | ch_state[chid]->refs = atomic_read(&ch->ref_count); | ||
95 | nvgpu_mem_rd_n(g, &ch->inst_block, 0, | ||
96 | &ch_state[chid]->inst_block[0], | ||
97 | ram_in_alloc_size_v()); | ||
98 | gk20a_channel_put(ch); | ||
99 | } | ||
100 | for (chid = 0; chid < f->num_channels; chid++) { | ||
101 | if (ch_state[chid]) { | ||
102 | g->ops.fifo.dump_channel_status_ramfc(g, o, chid, | ||
103 | ch_state[chid]); | ||
104 | nvgpu_kfree(g, ch_state[chid]); | ||
105 | } | ||
106 | } | ||
107 | nvgpu_kfree(g, ch_state); | ||
108 | } | ||
109 | |||
110 | void gk20a_debug_show_dump(struct gk20a *g, struct gk20a_debug_output *o) | ||
111 | { | ||
112 | g->ops.fifo.dump_pbdma_status(g, o); | ||
113 | g->ops.fifo.dump_eng_status(g, o); | ||
114 | |||
115 | gk20a_debug_dump_all_channel_status_ramfc(g, o); | ||
116 | } | ||
117 | |||
118 | static int gk20a_gr_dump_regs(struct device *dev, | ||
119 | struct gk20a_debug_output *o) | ||
120 | { | ||
121 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
122 | struct gk20a *g = platform->g; | ||
123 | |||
124 | if (g->ops.gr.dump_gr_regs) | ||
125 | gr_gk20a_elpg_protected_call(g, g->ops.gr.dump_gr_regs(g, o)); | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | int gk20a_gr_debug_dump(struct device *dev) | ||
131 | { | ||
132 | struct gk20a_debug_output o = { | ||
133 | .fn = gk20a_debug_write_printk | ||
134 | }; | ||
135 | |||
136 | gk20a_gr_dump_regs(dev, &o); | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int gk20a_gr_debug_show(struct seq_file *s, void *unused) | ||
142 | { | ||
143 | struct device *dev = s->private; | ||
144 | struct gk20a *g = gk20a_get_platform(dev)->g; | ||
145 | struct gk20a_debug_output o = { | ||
146 | .fn = gk20a_debug_write_to_seqfile, | ||
147 | .ctx = s, | ||
148 | }; | ||
149 | int err; | ||
150 | |||
151 | err = gk20a_busy(g); | ||
152 | if (err) { | ||
153 | nvgpu_err(g, "failed to power on gpu: %d", err); | ||
154 | return -EINVAL; | ||
155 | } | ||
156 | |||
157 | gk20a_gr_dump_regs(dev, &o); | ||
158 | |||
159 | gk20a_idle(g); | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | void gk20a_debug_dump(struct device *dev) | ||
165 | { | ||
166 | struct gk20a_platform *platform = gk20a_get_platform(dev); | ||
167 | struct gk20a *g = platform->g; | ||
168 | struct gk20a_debug_output o = { | ||
169 | .fn = gk20a_debug_write_printk | ||
170 | }; | ||
171 | |||
172 | if (platform->dump_platform_dependencies) | ||
173 | platform->dump_platform_dependencies(dev); | ||
174 | |||
175 | /* HAL only initialized after 1st power-on */ | ||
176 | if (g->ops.debug.show_dump) | ||
177 | g->ops.debug.show_dump(g, &o); | ||
178 | } | ||
179 | |||
180 | static int gk20a_debug_show(struct seq_file *s, void *unused) | ||
181 | { | ||
182 | struct device *dev = s->private; | ||
183 | struct gk20a_debug_output o = { | ||
184 | .fn = gk20a_debug_write_to_seqfile, | ||
185 | .ctx = s, | ||
186 | }; | ||
187 | struct gk20a *g; | ||
188 | int err; | ||
189 | |||
190 | g = gk20a_get_platform(dev)->g; | ||
191 | |||
192 | err = gk20a_busy(g); | ||
193 | if (err) { | ||
194 | nvgpu_err(g, "failed to power on gpu: %d", err); | ||
195 | return -EFAULT; | ||
196 | } | ||
197 | |||
198 | /* HAL only initialized after 1st power-on */ | ||
199 | if (g->ops.debug.show_dump) | ||
200 | g->ops.debug.show_dump(g, &o); | ||
201 | |||
202 | gk20a_idle(g); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int gk20a_gr_debug_open(struct inode *inode, struct file *file) | ||
207 | { | ||
208 | return single_open(file, gk20a_gr_debug_show, inode->i_private); | ||
209 | } | ||
210 | |||
211 | static int gk20a_debug_open(struct inode *inode, struct file *file) | ||
212 | { | ||
213 | return single_open(file, gk20a_debug_show, inode->i_private); | ||
214 | } | ||
215 | |||
216 | static const struct file_operations gk20a_gr_debug_fops = { | ||
217 | .open = gk20a_gr_debug_open, | ||
218 | .read = seq_read, | ||
219 | .llseek = seq_lseek, | ||
220 | .release = single_release, | ||
221 | }; | ||
222 | |||
223 | static const struct file_operations gk20a_debug_fops = { | ||
224 | .open = gk20a_debug_open, | ||
225 | .read = seq_read, | ||
226 | .llseek = seq_lseek, | ||
227 | .release = single_release, | ||
228 | }; | ||
229 | |||
230 | void gk20a_init_debug_ops(struct gpu_ops *gops) | ||
231 | { | ||
232 | gops->debug.show_dump = gk20a_debug_show_dump; | ||
233 | } | ||
234 | |||
235 | #ifdef CONFIG_DEBUG_FS | ||
236 | static int railgate_residency_show(struct seq_file *s, void *data) | ||
237 | { | ||
238 | struct device *dev = s->private; | ||
239 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
240 | struct gk20a *g = get_gk20a(dev); | ||
241 | unsigned long time_since_last_state_transition_ms; | ||
242 | unsigned long total_rail_gate_time_ms; | ||
243 | unsigned long total_rail_ungate_time_ms; | ||
244 | |||
245 | if (platform->is_railgated(dev)) { | ||
246 | time_since_last_state_transition_ms = | ||
247 | jiffies_to_msecs(jiffies - | ||
248 | g->pstats.last_rail_gate_complete); | ||
249 | total_rail_ungate_time_ms = g->pstats.total_rail_ungate_time_ms; | ||
250 | total_rail_gate_time_ms = | ||
251 | g->pstats.total_rail_gate_time_ms + | ||
252 | time_since_last_state_transition_ms; | ||
253 | } else { | ||
254 | time_since_last_state_transition_ms = | ||
255 | jiffies_to_msecs(jiffies - | ||
256 | g->pstats.last_rail_ungate_complete); | ||
257 | total_rail_gate_time_ms = g->pstats.total_rail_gate_time_ms; | ||
258 | total_rail_ungate_time_ms = | ||
259 | g->pstats.total_rail_ungate_time_ms + | ||
260 | time_since_last_state_transition_ms; | ||
261 | } | ||
262 | |||
263 | seq_printf(s, "Time with Rails Gated: %lu ms\n" | ||
264 | "Time with Rails UnGated: %lu ms\n" | ||
265 | "Total railgating cycles: %lu\n", | ||
266 | total_rail_gate_time_ms, | ||
267 | total_rail_ungate_time_ms, | ||
268 | g->pstats.railgating_cycle_count - 1); | ||
269 | return 0; | ||
270 | |||
271 | } | ||
272 | |||
273 | static int railgate_residency_open(struct inode *inode, struct file *file) | ||
274 | { | ||
275 | return single_open(file, railgate_residency_show, inode->i_private); | ||
276 | } | ||
277 | |||
278 | static const struct file_operations railgate_residency_fops = { | ||
279 | .open = railgate_residency_open, | ||
280 | .read = seq_read, | ||
281 | .llseek = seq_lseek, | ||
282 | .release = single_release, | ||
283 | }; | ||
284 | |||
285 | int gk20a_railgating_debugfs_init(struct device *dev) | ||
286 | { | ||
287 | struct dentry *d; | ||
288 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
289 | struct gk20a *g = get_gk20a(dev); | ||
290 | |||
291 | if (!g->can_railgate) | ||
292 | return 0; | ||
293 | |||
294 | d = debugfs_create_file( | ||
295 | "railgate_residency", S_IRUGO|S_IWUSR, platform->debugfs, dev, | ||
296 | &railgate_residency_fops); | ||
297 | if (!d) | ||
298 | return -ENOMEM; | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | #endif | ||
303 | |||
304 | void gk20a_debug_init(struct device *dev, const char *debugfs_symlink) | ||
305 | { | ||
306 | #ifdef CONFIG_DEBUG_FS | ||
307 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
308 | struct gk20a *g = platform->g; | ||
309 | |||
310 | platform->debugfs = debugfs_create_dir(dev_name(dev), NULL); | ||
311 | if (!platform->debugfs) | ||
312 | return; | ||
313 | |||
314 | if (debugfs_symlink) | ||
315 | platform->debugfs_alias = | ||
316 | debugfs_create_symlink(debugfs_symlink, | ||
317 | NULL, dev_name(dev)); | ||
318 | |||
319 | debugfs_create_file("status", S_IRUGO, platform->debugfs, | ||
320 | dev, &gk20a_debug_fops); | ||
321 | debugfs_create_file("gr_status", S_IRUGO, platform->debugfs, | ||
322 | dev, &gk20a_gr_debug_fops); | ||
323 | debugfs_create_u32("trace_cmdbuf", S_IRUGO|S_IWUSR, | ||
324 | platform->debugfs, &gk20a_debug_trace_cmdbuf); | ||
325 | |||
326 | debugfs_create_u32("ch_wdt_timeout_ms", S_IRUGO|S_IWUSR, | ||
327 | platform->debugfs, &g->ch_wdt_timeout_ms); | ||
328 | |||
329 | debugfs_create_u32("disable_syncpoints", S_IRUGO|S_IWUSR, | ||
330 | platform->debugfs, &g->disable_syncpoints); | ||
331 | |||
332 | /* Legacy debugging API. */ | ||
333 | debugfs_create_u32("dbg_mask", S_IRUGO|S_IWUSR, | ||
334 | platform->debugfs, &nvgpu_dbg_mask); | ||
335 | |||
336 | /* New debug logging API. */ | ||
337 | debugfs_create_u32("log_mask", S_IRUGO|S_IWUSR, | ||
338 | platform->debugfs, &g->log_mask); | ||
339 | debugfs_create_u32("log_trace", S_IRUGO|S_IWUSR, | ||
340 | platform->debugfs, &g->log_trace); | ||
341 | |||
342 | nvgpu_spinlock_init(&g->debugfs_lock); | ||
343 | |||
344 | g->mm.ltc_enabled = true; | ||
345 | g->mm.ltc_enabled_debug = true; | ||
346 | |||
347 | g->debugfs_ltc_enabled = | ||
348 | debugfs_create_bool("ltc_enabled", S_IRUGO|S_IWUSR, | ||
349 | platform->debugfs, | ||
350 | &g->mm.ltc_enabled_debug); | ||
351 | |||
352 | g->debugfs_gr_idle_timeout_default = | ||
353 | debugfs_create_u32("gr_idle_timeout_default_us", | ||
354 | S_IRUGO|S_IWUSR, platform->debugfs, | ||
355 | &g->gr_idle_timeout_default); | ||
356 | g->debugfs_timeouts_enabled = | ||
357 | debugfs_create_bool("timeouts_enabled", | ||
358 | S_IRUGO|S_IWUSR, | ||
359 | platform->debugfs, | ||
360 | &g->timeouts_enabled); | ||
361 | |||
362 | g->debugfs_bypass_smmu = | ||
363 | debugfs_create_bool("bypass_smmu", | ||
364 | S_IRUGO|S_IWUSR, | ||
365 | platform->debugfs, | ||
366 | &g->mm.bypass_smmu); | ||
367 | g->debugfs_disable_bigpage = | ||
368 | debugfs_create_bool("disable_bigpage", | ||
369 | S_IRUGO|S_IWUSR, | ||
370 | platform->debugfs, | ||
371 | &g->mm.disable_bigpage); | ||
372 | |||
373 | g->debugfs_timeslice_low_priority_us = | ||
374 | debugfs_create_u32("timeslice_low_priority_us", | ||
375 | S_IRUGO|S_IWUSR, | ||
376 | platform->debugfs, | ||
377 | &g->timeslice_low_priority_us); | ||
378 | g->debugfs_timeslice_medium_priority_us = | ||
379 | debugfs_create_u32("timeslice_medium_priority_us", | ||
380 | S_IRUGO|S_IWUSR, | ||
381 | platform->debugfs, | ||
382 | &g->timeslice_medium_priority_us); | ||
383 | g->debugfs_timeslice_high_priority_us = | ||
384 | debugfs_create_u32("timeslice_high_priority_us", | ||
385 | S_IRUGO|S_IWUSR, | ||
386 | platform->debugfs, | ||
387 | &g->timeslice_high_priority_us); | ||
388 | g->debugfs_runlist_interleave = | ||
389 | debugfs_create_bool("runlist_interleave", | ||
390 | S_IRUGO|S_IWUSR, | ||
391 | platform->debugfs, | ||
392 | &g->runlist_interleave); | ||
393 | #ifdef CONFIG_ARCH_TEGRA_18x_SOC | ||
394 | g->gr.t18x.ctx_vars.debugfs_force_preemption_gfxp = | ||
395 | debugfs_create_bool("force_preemption_gfxp", S_IRUGO|S_IWUSR, | ||
396 | platform->debugfs, | ||
397 | &g->gr.t18x.ctx_vars.force_preemption_gfxp); | ||
398 | |||
399 | g->gr.t18x.ctx_vars.debugfs_force_preemption_cilp = | ||
400 | debugfs_create_bool("force_preemption_cilp", S_IRUGO|S_IWUSR, | ||
401 | platform->debugfs, | ||
402 | &g->gr.t18x.ctx_vars.force_preemption_cilp); | ||
403 | |||
404 | g->gr.t18x.ctx_vars.debugfs_dump_ctxsw_stats = | ||
405 | debugfs_create_bool("dump_ctxsw_stats_on_channel_close", | ||
406 | S_IRUGO|S_IWUSR, platform->debugfs, | ||
407 | &g->gr.t18x. | ||
408 | ctx_vars.dump_ctxsw_stats_on_channel_close); | ||
409 | #endif | ||
410 | |||
411 | gr_gk20a_debugfs_init(g); | ||
412 | gk20a_pmu_debugfs_init(g->dev); | ||
413 | gk20a_railgating_debugfs_init(g->dev); | ||
414 | gk20a_cde_debugfs_init(g->dev); | ||
415 | gk20a_ce_debugfs_init(g->dev); | ||
416 | nvgpu_alloc_debugfs_init(g->dev); | ||
417 | gk20a_mm_debugfs_init(g->dev); | ||
418 | gk20a_fifo_debugfs_init(g->dev); | ||
419 | gk20a_sched_debugfs_init(g->dev); | ||
420 | #ifdef CONFIG_NVGPU_TRACK_MEM_USAGE | ||
421 | nvgpu_kmem_debugfs_init(g->dev); | ||
422 | #endif | ||
423 | #endif | ||
424 | |||
425 | } | ||
diff --git a/drivers/gpu/nvgpu/gk20a/debug_gk20a.h b/drivers/gpu/nvgpu/gk20a/debug_gk20a.h deleted file mode 100644 index 213922b3..00000000 --- a/drivers/gpu/nvgpu/gk20a/debug_gk20a.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /* | ||
2 | * GK20A Debug functionality | ||
3 | * | ||
4 | * Copyright (C) 2011-2017 NVIDIA CORPORATION. All rights reserved. | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef _DEBUG_GK20A_H_ | ||
18 | #define _DEBUG_GK20A_H_ | ||
19 | |||
20 | struct platform_device; | ||
21 | struct gk20a; | ||
22 | struct gpu_ops; | ||
23 | |||
24 | extern unsigned int gk20a_debug_trace_cmdbuf; | ||
25 | |||
26 | struct gk20a_debug_output { | ||
27 | void (*fn)(void *ctx, const char *str, size_t len); | ||
28 | void *ctx; | ||
29 | char buf[256]; | ||
30 | }; | ||
31 | |||
32 | void gk20a_debug_output(struct gk20a_debug_output *o, | ||
33 | const char *fmt, ...); | ||
34 | |||
35 | void gk20a_debug_dump(struct device *pdev); | ||
36 | void gk20a_debug_show_dump(struct gk20a *g, struct gk20a_debug_output *o); | ||
37 | int gk20a_gr_debug_dump(struct device *pdev); | ||
38 | void gk20a_debug_init(struct device *dev, const char *debugfs_symlink); | ||
39 | void gk20a_init_debug_ops(struct gpu_ops *gops); | ||
40 | void gk20a_debug_dump_device(void *dev); | ||
41 | #endif | ||
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c index ac3a3d57..46560a56 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.c | |||
@@ -29,12 +29,11 @@ | |||
29 | #include <nvgpu/log.h> | 29 | #include <nvgpu/log.h> |
30 | #include <nvgpu/soc.h> | 30 | #include <nvgpu/soc.h> |
31 | #include <nvgpu/atomic.h> | 31 | #include <nvgpu/atomic.h> |
32 | #include <nvgpu/sort.h> | ||
33 | #include <nvgpu/bug.h> | 32 | #include <nvgpu/bug.h> |
34 | #include <nvgpu/log2.h> | 33 | #include <nvgpu/log2.h> |
34 | #include <nvgpu/debug.h> | ||
35 | 35 | ||
36 | #include "gk20a.h" | 36 | #include "gk20a.h" |
37 | #include "debug_gk20a.h" | ||
38 | #include "ctxsw_trace_gk20a.h" | 37 | #include "ctxsw_trace_gk20a.h" |
39 | #include "mm_gk20a.h" | 38 | #include "mm_gk20a.h" |
40 | 39 | ||
@@ -46,10 +45,6 @@ | |||
46 | #include <nvgpu/hw/gk20a/hw_mc_gk20a.h> | 45 | #include <nvgpu/hw/gk20a/hw_mc_gk20a.h> |
47 | #include <nvgpu/hw/gk20a/hw_gr_gk20a.h> | 46 | #include <nvgpu/hw/gk20a/hw_gr_gk20a.h> |
48 | 47 | ||
49 | #ifdef CONFIG_DEBUG_FS | ||
50 | #include "platform_gk20a.h" | ||
51 | #endif | ||
52 | |||
53 | #define FECS_METHOD_WFI_RESTORE 0x80000 | 48 | #define FECS_METHOD_WFI_RESTORE 0x80000 |
54 | 49 | ||
55 | static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, | 50 | static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, |
@@ -57,10 +52,6 @@ static int gk20a_fifo_update_runlist_locked(struct gk20a *g, u32 runlist_id, | |||
57 | bool wait_for_finish); | 52 | bool wait_for_finish); |
58 | static u32 gk20a_fifo_engines_on_id(struct gk20a *g, u32 id, bool is_tsg); | 53 | static u32 gk20a_fifo_engines_on_id(struct gk20a *g, u32 id, bool is_tsg); |
59 | 54 | ||
60 | #ifdef CONFIG_DEBUG_FS | ||
61 | static void __gk20a_fifo_profile_free(struct kref *ref); | ||
62 | #endif | ||
63 | |||
64 | u32 gk20a_fifo_get_engine_ids(struct gk20a *g, | 55 | u32 gk20a_fifo_get_engine_ids(struct gk20a *g, |
65 | u32 engine_id[], u32 engine_id_sz, | 56 | u32 engine_id[], u32 engine_id_sz, |
66 | u32 engine_enum) | 57 | u32 engine_enum) |
@@ -562,14 +553,6 @@ static void gk20a_remove_fifo_support(struct fifo_gk20a *f) | |||
562 | f->engine_info = NULL; | 553 | f->engine_info = NULL; |
563 | nvgpu_kfree(g, f->active_engines_list); | 554 | nvgpu_kfree(g, f->active_engines_list); |
564 | f->active_engines_list = NULL; | 555 | f->active_engines_list = NULL; |
565 | #ifdef CONFIG_DEBUG_FS | ||
566 | nvgpu_mutex_acquire(&f->profile.lock); | ||
567 | if (f->profile.enabled) { | ||
568 | f->profile.enabled = false; | ||
569 | kref_put(&f->profile.ref, __gk20a_fifo_profile_free); | ||
570 | } | ||
571 | nvgpu_mutex_release(&f->profile.lock); | ||
572 | #endif | ||
573 | } | 556 | } |
574 | 557 | ||
575 | /* reads info from hardware and fills in pbmda exception info record */ | 558 | /* reads info from hardware and fills in pbmda exception info record */ |
@@ -1543,7 +1526,7 @@ static bool gk20a_fifo_handle_mmu_fault( | |||
1543 | } else { | 1526 | } else { |
1544 | fault_id = gk20a_readl(g, fifo_intr_mmu_fault_id_r()); | 1527 | fault_id = gk20a_readl(g, fifo_intr_mmu_fault_id_r()); |
1545 | fake_fault = false; | 1528 | fake_fault = false; |
1546 | gk20a_debug_dump(g->dev); | 1529 | gk20a_debug_dump(g); |
1547 | } | 1530 | } |
1548 | 1531 | ||
1549 | 1532 | ||
@@ -1833,7 +1816,7 @@ void gk20a_fifo_recover_ch(struct gk20a *g, u32 hw_chid, bool verbose) | |||
1833 | gk20a_channel_abort(ch, false); | 1816 | gk20a_channel_abort(ch, false); |
1834 | 1817 | ||
1835 | if (gk20a_fifo_error_ch(g, ch)) | 1818 | if (gk20a_fifo_error_ch(g, ch)) |
1836 | gk20a_debug_dump(g->dev); | 1819 | gk20a_debug_dump(g); |
1837 | 1820 | ||
1838 | gk20a_channel_put(ch); | 1821 | gk20a_channel_put(ch); |
1839 | } | 1822 | } |
@@ -1860,7 +1843,7 @@ void gk20a_fifo_recover_tsg(struct gk20a *g, u32 tsgid, bool verbose) | |||
1860 | struct tsg_gk20a *tsg = &g->fifo.tsg[tsgid]; | 1843 | struct tsg_gk20a *tsg = &g->fifo.tsg[tsgid]; |
1861 | 1844 | ||
1862 | if (gk20a_fifo_error_tsg(g, tsg)) | 1845 | if (gk20a_fifo_error_tsg(g, tsg)) |
1863 | gk20a_debug_dump(g->dev); | 1846 | gk20a_debug_dump(g); |
1864 | 1847 | ||
1865 | gk20a_fifo_abort_tsg(g, tsgid, false); | 1848 | gk20a_fifo_abort_tsg(g, tsgid, false); |
1866 | } | 1849 | } |
@@ -1957,7 +1940,7 @@ void gk20a_fifo_recover(struct gk20a *g, u32 __engine_ids, | |||
1957 | unsigned int id_type; | 1940 | unsigned int id_type; |
1958 | 1941 | ||
1959 | if (verbose) | 1942 | if (verbose) |
1960 | gk20a_debug_dump(g->dev); | 1943 | gk20a_debug_dump(g); |
1961 | 1944 | ||
1962 | if (g->ops.ltc.flush) | 1945 | if (g->ops.ltc.flush) |
1963 | g->ops.ltc.flush(g); | 1946 | g->ops.ltc.flush(g); |
@@ -3441,345 +3424,6 @@ struct channel_gk20a *gk20a_fifo_channel_from_hw_chid(struct gk20a *g, | |||
3441 | return NULL; | 3424 | return NULL; |
3442 | } | 3425 | } |
3443 | 3426 | ||
3444 | #ifdef CONFIG_DEBUG_FS | ||
3445 | |||
3446 | /* Get the next element in the ring buffer of profile entries | ||
3447 | * and grab a reference to the structure | ||
3448 | */ | ||
3449 | struct fifo_profile_gk20a *gk20a_fifo_profile_acquire(struct gk20a *g) | ||
3450 | { | ||
3451 | struct fifo_gk20a *f = &g->fifo; | ||
3452 | struct fifo_profile_gk20a *profile; | ||
3453 | unsigned int index; | ||
3454 | |||
3455 | /* If kref is zero, profiling is not enabled */ | ||
3456 | if (!kref_get_unless_zero(&f->profile.ref)) | ||
3457 | return NULL; | ||
3458 | index = atomic_inc_return(&f->profile.get); | ||
3459 | profile = &f->profile.data[index % FIFO_PROFILING_ENTRIES]; | ||
3460 | |||
3461 | return profile; | ||
3462 | } | ||
3463 | |||
3464 | /* Free the reference to the structure. This allows deferred cleanups */ | ||
3465 | void gk20a_fifo_profile_release(struct gk20a *g, | ||
3466 | struct fifo_profile_gk20a *profile) | ||
3467 | { | ||
3468 | kref_put(&g->fifo.profile.ref, __gk20a_fifo_profile_free); | ||
3469 | } | ||
3470 | |||
3471 | static void *gk20a_fifo_sched_debugfs_seq_start( | ||
3472 | struct seq_file *s, loff_t *pos) | ||
3473 | { | ||
3474 | struct gk20a *g = s->private; | ||
3475 | struct fifo_gk20a *f = &g->fifo; | ||
3476 | |||
3477 | if (*pos >= f->num_channels) | ||
3478 | return NULL; | ||
3479 | |||
3480 | return &f->channel[*pos]; | ||
3481 | } | ||
3482 | |||
3483 | static void *gk20a_fifo_sched_debugfs_seq_next( | ||
3484 | struct seq_file *s, void *v, loff_t *pos) | ||
3485 | { | ||
3486 | struct gk20a *g = s->private; | ||
3487 | struct fifo_gk20a *f = &g->fifo; | ||
3488 | |||
3489 | ++(*pos); | ||
3490 | if (*pos >= f->num_channels) | ||
3491 | return NULL; | ||
3492 | |||
3493 | return &f->channel[*pos]; | ||
3494 | } | ||
3495 | |||
3496 | static void gk20a_fifo_sched_debugfs_seq_stop( | ||
3497 | struct seq_file *s, void *v) | ||
3498 | { | ||
3499 | } | ||
3500 | |||
3501 | static int gk20a_fifo_sched_debugfs_seq_show( | ||
3502 | struct seq_file *s, void *v) | ||
3503 | { | ||
3504 | struct gk20a *g = s->private; | ||
3505 | struct fifo_gk20a *f = &g->fifo; | ||
3506 | struct channel_gk20a *ch = v; | ||
3507 | struct tsg_gk20a *tsg = NULL; | ||
3508 | |||
3509 | struct fifo_engine_info_gk20a *engine_info; | ||
3510 | struct fifo_runlist_info_gk20a *runlist; | ||
3511 | u32 runlist_id; | ||
3512 | int ret = SEQ_SKIP; | ||
3513 | u32 engine_id; | ||
3514 | |||
3515 | engine_id = gk20a_fifo_get_gr_engine_id(g); | ||
3516 | engine_info = (f->engine_info + engine_id); | ||
3517 | runlist_id = engine_info->runlist_id; | ||
3518 | runlist = &f->runlist_info[runlist_id]; | ||
3519 | |||
3520 | if (ch == f->channel) { | ||
3521 | seq_puts(s, "chid tsgid pid timeslice timeout interleave graphics_preempt compute_preempt\n"); | ||
3522 | seq_puts(s, " (usecs) (msecs)\n"); | ||
3523 | ret = 0; | ||
3524 | } | ||
3525 | |||
3526 | if (!test_bit(ch->hw_chid, runlist->active_channels)) | ||
3527 | return ret; | ||
3528 | |||
3529 | if (gk20a_channel_get(ch)) { | ||
3530 | if (gk20a_is_channel_marked_as_tsg(ch)) | ||
3531 | tsg = &f->tsg[ch->tsgid]; | ||
3532 | |||
3533 | seq_printf(s, "%-8d %-8d %-8d %-9d %-8d %-10d %-8d %-8d\n", | ||
3534 | ch->hw_chid, | ||
3535 | ch->tsgid, | ||
3536 | ch->tgid, | ||
3537 | tsg ? tsg->timeslice_us : ch->timeslice_us, | ||
3538 | ch->timeout_ms_max, | ||
3539 | tsg ? tsg->interleave_level : ch->interleave_level, | ||
3540 | ch->ch_ctx.gr_ctx ? ch->ch_ctx.gr_ctx->graphics_preempt_mode : U32_MAX, | ||
3541 | ch->ch_ctx.gr_ctx ? ch->ch_ctx.gr_ctx->compute_preempt_mode : U32_MAX); | ||
3542 | gk20a_channel_put(ch); | ||
3543 | } | ||
3544 | return 0; | ||
3545 | } | ||
3546 | |||
3547 | static const struct seq_operations gk20a_fifo_sched_debugfs_seq_ops = { | ||
3548 | .start = gk20a_fifo_sched_debugfs_seq_start, | ||
3549 | .next = gk20a_fifo_sched_debugfs_seq_next, | ||
3550 | .stop = gk20a_fifo_sched_debugfs_seq_stop, | ||
3551 | .show = gk20a_fifo_sched_debugfs_seq_show | ||
3552 | }; | ||
3553 | |||
3554 | static int gk20a_fifo_sched_debugfs_open(struct inode *inode, | ||
3555 | struct file *file) | ||
3556 | { | ||
3557 | int err; | ||
3558 | |||
3559 | if (!capable(CAP_SYS_ADMIN)) | ||
3560 | return -EPERM; | ||
3561 | |||
3562 | err = seq_open(file, &gk20a_fifo_sched_debugfs_seq_ops); | ||
3563 | if (err) | ||
3564 | return err; | ||
3565 | |||
3566 | gk20a_dbg(gpu_dbg_info, "i_private=%p", inode->i_private); | ||
3567 | |||
3568 | ((struct seq_file *)file->private_data)->private = inode->i_private; | ||
3569 | return 0; | ||
3570 | }; | ||
3571 | |||
3572 | /* | ||
3573 | * The file operations structure contains our open function along with | ||
3574 | * set of the canned seq_ ops. | ||
3575 | */ | ||
3576 | static const struct file_operations gk20a_fifo_sched_debugfs_fops = { | ||
3577 | .owner = THIS_MODULE, | ||
3578 | .open = gk20a_fifo_sched_debugfs_open, | ||
3579 | .read = seq_read, | ||
3580 | .llseek = seq_lseek, | ||
3581 | .release = seq_release | ||
3582 | }; | ||
3583 | |||
3584 | static void __gk20a_fifo_profile_free(struct kref *ref) | ||
3585 | { | ||
3586 | struct fifo_gk20a *f = container_of(ref, struct fifo_gk20a, | ||
3587 | profile.ref); | ||
3588 | nvgpu_vfree(f->g, f->profile.data); | ||
3589 | nvgpu_vfree(f->g, f->profile.sorted); | ||
3590 | } | ||
3591 | |||
3592 | static int gk20a_fifo_profile_enable(void *data, u64 val) | ||
3593 | { | ||
3594 | struct gk20a *g = (struct gk20a *) data; | ||
3595 | struct fifo_gk20a *f = &g->fifo; | ||
3596 | |||
3597 | |||
3598 | nvgpu_mutex_acquire(&f->profile.lock); | ||
3599 | if (val == 0) { | ||
3600 | if (f->profile.enabled) { | ||
3601 | f->profile.enabled = false; | ||
3602 | kref_put(&f->profile.ref, __gk20a_fifo_profile_free); | ||
3603 | } | ||
3604 | } else { | ||
3605 | if (!f->profile.enabled) { | ||
3606 | /* not kref init as it can have a running condition if | ||
3607 | * we enable/disable/enable while kickoff is happening | ||
3608 | */ | ||
3609 | if (!kref_get_unless_zero(&f->profile.ref)) { | ||
3610 | f->profile.data = vzalloc( | ||
3611 | FIFO_PROFILING_ENTRIES * | ||
3612 | sizeof(struct fifo_profile_gk20a)); | ||
3613 | f->profile.sorted = vzalloc( | ||
3614 | FIFO_PROFILING_ENTRIES * | ||
3615 | sizeof(u64)); | ||
3616 | if (!(f->profile.data && f->profile.sorted)) { | ||
3617 | nvgpu_vfree(g, f->profile.data); | ||
3618 | nvgpu_vfree(g, f->profile.sorted); | ||
3619 | nvgpu_mutex_release(&f->profile.lock); | ||
3620 | return -ENOMEM; | ||
3621 | } | ||
3622 | kref_init(&f->profile.ref); | ||
3623 | } | ||
3624 | atomic_set(&f->profile.get, 0); | ||
3625 | f->profile.enabled = true; | ||
3626 | } | ||
3627 | } | ||
3628 | nvgpu_mutex_release(&f->profile.lock); | ||
3629 | |||
3630 | return 0; | ||
3631 | } | ||
3632 | |||
3633 | DEFINE_SIMPLE_ATTRIBUTE( | ||
3634 | gk20a_fifo_profile_enable_debugfs_fops, | ||
3635 | NULL, | ||
3636 | gk20a_fifo_profile_enable, | ||
3637 | "%llu\n" | ||
3638 | ); | ||
3639 | |||
3640 | static int __profile_cmp(const void *a, const void *b) | ||
3641 | { | ||
3642 | return *((unsigned long long *) a) - *((unsigned long long *) b); | ||
3643 | } | ||
3644 | |||
3645 | /* | ||
3646 | * This uses about 800b in the stack, but the function using it is not part | ||
3647 | * of a callstack where much memory is being used, so it is fine | ||
3648 | */ | ||
3649 | #define PERCENTILE_WIDTH 5 | ||
3650 | #define PERCENTILE_RANGES (100/PERCENTILE_WIDTH) | ||
3651 | |||
3652 | static unsigned int __gk20a_fifo_create_stats(struct gk20a *g, | ||
3653 | u64 *percentiles, u32 index_end, u32 index_start) | ||
3654 | { | ||
3655 | unsigned int nelem = 0; | ||
3656 | unsigned int index; | ||
3657 | struct fifo_profile_gk20a *profile; | ||
3658 | |||
3659 | for (index = 0; index < FIFO_PROFILING_ENTRIES; index++) { | ||
3660 | profile = &g->fifo.profile.data[index]; | ||
3661 | |||
3662 | if (profile->timestamp[index_end] > | ||
3663 | profile->timestamp[index_start]) { | ||
3664 | /* This is a valid element */ | ||
3665 | g->fifo.profile.sorted[nelem] = | ||
3666 | profile->timestamp[index_end] - | ||
3667 | profile->timestamp[index_start]; | ||
3668 | nelem++; | ||
3669 | } | ||
3670 | } | ||
3671 | |||
3672 | /* sort it */ | ||
3673 | sort(g->fifo.profile.sorted, nelem, sizeof(unsigned long long), | ||
3674 | __profile_cmp, NULL); | ||
3675 | |||
3676 | /* build ranges */ | ||
3677 | for (index = 0; index < PERCENTILE_RANGES; index++) | ||
3678 | percentiles[index] = | ||
3679 | g->fifo.profile.sorted[(PERCENTILE_WIDTH * (index + 1) * | ||
3680 | nelem)/100 - 1]; | ||
3681 | return nelem; | ||
3682 | } | ||
3683 | |||
3684 | static int gk20a_fifo_profile_stats(struct seq_file *s, void *unused) | ||
3685 | { | ||
3686 | struct gk20a *g = s->private; | ||
3687 | unsigned int get, nelem, index; | ||
3688 | /* | ||
3689 | * 800B in the stack, but function is declared statically and only | ||
3690 | * called from debugfs handler | ||
3691 | */ | ||
3692 | u64 percentiles_ioctl[PERCENTILE_RANGES]; | ||
3693 | u64 percentiles_kickoff[PERCENTILE_RANGES]; | ||
3694 | u64 percentiles_jobtracking[PERCENTILE_RANGES]; | ||
3695 | u64 percentiles_append[PERCENTILE_RANGES]; | ||
3696 | u64 percentiles_userd[PERCENTILE_RANGES]; | ||
3697 | |||
3698 | if (!kref_get_unless_zero(&g->fifo.profile.ref)) { | ||
3699 | seq_printf(s, "Profiling disabled\n"); | ||
3700 | return 0; | ||
3701 | } | ||
3702 | |||
3703 | get = atomic_read(&g->fifo.profile.get); | ||
3704 | |||
3705 | __gk20a_fifo_create_stats(g, percentiles_ioctl, | ||
3706 | PROFILE_IOCTL_EXIT, PROFILE_IOCTL_ENTRY); | ||
3707 | __gk20a_fifo_create_stats(g, percentiles_kickoff, | ||
3708 | PROFILE_END, PROFILE_ENTRY); | ||
3709 | __gk20a_fifo_create_stats(g, percentiles_jobtracking, | ||
3710 | PROFILE_JOB_TRACKING, PROFILE_IOCTL_ENTRY); | ||
3711 | __gk20a_fifo_create_stats(g, percentiles_append, | ||
3712 | PROFILE_APPEND, PROFILE_JOB_TRACKING); | ||
3713 | nelem = __gk20a_fifo_create_stats(g, percentiles_userd, | ||
3714 | PROFILE_END, PROFILE_APPEND); | ||
3715 | |||
3716 | seq_printf(s, "Number of kickoffs: %d\n", nelem); | ||
3717 | seq_printf(s, "Perc \t ioctl(ns) \t kickoff(ns) \t pbcopy(ns) \t jobtrack(ns) \t userd(ns)\n"); | ||
3718 | |||
3719 | for (index = 0; index < PERCENTILE_RANGES; index++) | ||
3720 | seq_printf(s, "[%2dpc]\t%8lld\t%8lld\t%8lld\t%8lld\t%8lld\n", | ||
3721 | PERCENTILE_WIDTH * (index+1), | ||
3722 | percentiles_ioctl[index], | ||
3723 | percentiles_kickoff[index], | ||
3724 | percentiles_append[index], | ||
3725 | percentiles_jobtracking[index], | ||
3726 | percentiles_userd[index]); | ||
3727 | |||
3728 | kref_put(&g->fifo.profile.ref, __gk20a_fifo_profile_free); | ||
3729 | |||
3730 | return 0; | ||
3731 | } | ||
3732 | |||
3733 | static int gk20a_fifo_profile_stats_open(struct inode *inode, struct file *file) | ||
3734 | { | ||
3735 | return single_open(file, gk20a_fifo_profile_stats, inode->i_private); | ||
3736 | } | ||
3737 | |||
3738 | static const struct file_operations gk20a_fifo_profile_stats_debugfs_fops = { | ||
3739 | .open = gk20a_fifo_profile_stats_open, | ||
3740 | .read = seq_read, | ||
3741 | .llseek = seq_lseek, | ||
3742 | .release = single_release, | ||
3743 | }; | ||
3744 | |||
3745 | |||
3746 | void gk20a_fifo_debugfs_init(struct device *dev) | ||
3747 | { | ||
3748 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
3749 | struct gk20a *g = get_gk20a(dev); | ||
3750 | |||
3751 | struct dentry *gpu_root = platform->debugfs; | ||
3752 | struct dentry *fifo_root; | ||
3753 | struct dentry *profile_root; | ||
3754 | |||
3755 | |||
3756 | fifo_root = debugfs_create_dir("fifo", gpu_root); | ||
3757 | if (IS_ERR_OR_NULL(fifo_root)) | ||
3758 | return; | ||
3759 | |||
3760 | gk20a_dbg(gpu_dbg_info, "g=%p", g); | ||
3761 | |||
3762 | debugfs_create_file("sched", 0600, fifo_root, g, | ||
3763 | &gk20a_fifo_sched_debugfs_fops); | ||
3764 | |||
3765 | profile_root = debugfs_create_dir("profile", fifo_root); | ||
3766 | if (IS_ERR_OR_NULL(profile_root)) | ||
3767 | return; | ||
3768 | |||
3769 | nvgpu_mutex_init(&g->fifo.profile.lock); | ||
3770 | g->fifo.profile.enabled = false; | ||
3771 | atomic_set(&g->fifo.profile.get, 0); | ||
3772 | atomic_set(&g->fifo.profile.ref.refcount, 0); | ||
3773 | |||
3774 | debugfs_create_file("enable", 0600, profile_root, g, | ||
3775 | &gk20a_fifo_profile_enable_debugfs_fops); | ||
3776 | |||
3777 | debugfs_create_file("stats", 0600, profile_root, g, | ||
3778 | &gk20a_fifo_profile_stats_debugfs_fops); | ||
3779 | |||
3780 | } | ||
3781 | #endif /* CONFIG_DEBUG_FS */ | ||
3782 | |||
3783 | static const char * const ccsr_chan_status_str[] = { | 3427 | static const char * const ccsr_chan_status_str[] = { |
3784 | "idle", | 3428 | "idle", |
3785 | "pending", | 3429 | "pending", |
@@ -3901,6 +3545,54 @@ void gk20a_dump_channel_status_ramfc(struct gk20a *g, | |||
3901 | gk20a_debug_output(o, "\n"); | 3545 | gk20a_debug_output(o, "\n"); |
3902 | } | 3546 | } |
3903 | 3547 | ||
3548 | void gk20a_debug_dump_all_channel_status_ramfc(struct gk20a *g, | ||
3549 | struct gk20a_debug_output *o) | ||
3550 | { | ||
3551 | struct fifo_gk20a *f = &g->fifo; | ||
3552 | u32 chid; | ||
3553 | struct ch_state **ch_state; | ||
3554 | |||
3555 | ch_state = nvgpu_kzalloc(g, sizeof(*ch_state) * f->num_channels); | ||
3556 | if (!ch_state) { | ||
3557 | gk20a_debug_output(o, "cannot alloc memory for channels\n"); | ||
3558 | return; | ||
3559 | } | ||
3560 | |||
3561 | for (chid = 0; chid < f->num_channels; chid++) { | ||
3562 | struct channel_gk20a *ch = &f->channel[chid]; | ||
3563 | if (gk20a_channel_get(ch)) { | ||
3564 | ch_state[chid] = | ||
3565 | nvgpu_kmalloc(g, sizeof(struct ch_state) + | ||
3566 | ram_in_alloc_size_v()); | ||
3567 | /* ref taken stays to below loop with | ||
3568 | * successful allocs */ | ||
3569 | if (!ch_state[chid]) | ||
3570 | gk20a_channel_put(ch); | ||
3571 | } | ||
3572 | } | ||
3573 | |||
3574 | for (chid = 0; chid < f->num_channels; chid++) { | ||
3575 | struct channel_gk20a *ch = &f->channel[chid]; | ||
3576 | if (!ch_state[chid]) | ||
3577 | continue; | ||
3578 | |||
3579 | ch_state[chid]->pid = ch->pid; | ||
3580 | ch_state[chid]->refs = atomic_read(&ch->ref_count); | ||
3581 | nvgpu_mem_rd_n(g, &ch->inst_block, 0, | ||
3582 | &ch_state[chid]->inst_block[0], | ||
3583 | ram_in_alloc_size_v()); | ||
3584 | gk20a_channel_put(ch); | ||
3585 | } | ||
3586 | for (chid = 0; chid < f->num_channels; chid++) { | ||
3587 | if (ch_state[chid]) { | ||
3588 | g->ops.fifo.dump_channel_status_ramfc(g, o, chid, | ||
3589 | ch_state[chid]); | ||
3590 | nvgpu_kfree(g, ch_state[chid]); | ||
3591 | } | ||
3592 | } | ||
3593 | nvgpu_kfree(g, ch_state); | ||
3594 | } | ||
3595 | |||
3904 | void gk20a_dump_pbdma_status(struct gk20a *g, | 3596 | void gk20a_dump_pbdma_status(struct gk20a *g, |
3905 | struct gk20a_debug_output *o) | 3597 | struct gk20a_debug_output *o) |
3906 | { | 3598 | { |
diff --git a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h index 6c8868a2..228e5130 100644 --- a/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/fifo_gk20a.h | |||
@@ -23,10 +23,11 @@ | |||
23 | 23 | ||
24 | #include "channel_gk20a.h" | 24 | #include "channel_gk20a.h" |
25 | #include "tsg_gk20a.h" | 25 | #include "tsg_gk20a.h" |
26 | #include "debug_gk20a.h" | ||
27 | 26 | ||
28 | #include <nvgpu/kref.h> | 27 | #include <nvgpu/kref.h> |
29 | 28 | ||
29 | struct gk20a_debug_output; | ||
30 | |||
30 | #define MAX_RUNLIST_BUFFERS 2 | 31 | #define MAX_RUNLIST_BUFFERS 2 |
31 | 32 | ||
32 | #define FIFO_INVAL_ENGINE_ID ((u32)~0) | 33 | #define FIFO_INVAL_ENGINE_ID ((u32)~0) |
@@ -287,8 +288,6 @@ int gk20a_fifo_set_runlist_interleave(struct gk20a *g, | |||
287 | int gk20a_fifo_tsg_set_timeslice(struct tsg_gk20a *tsg, u32 timeslice); | 288 | int gk20a_fifo_tsg_set_timeslice(struct tsg_gk20a *tsg, u32 timeslice); |
288 | 289 | ||
289 | 290 | ||
290 | void gk20a_fifo_debugfs_init(struct device *dev); | ||
291 | |||
292 | const char *gk20a_fifo_interleave_level_name(u32 interleave_level); | 291 | const char *gk20a_fifo_interleave_level_name(u32 interleave_level); |
293 | 292 | ||
294 | int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type, | 293 | int gk20a_fifo_engine_enum_from_type(struct gk20a *g, u32 engine_type, |
@@ -341,6 +340,8 @@ void gk20a_dump_channel_status_ramfc(struct gk20a *g, | |||
341 | struct gk20a_debug_output *o, | 340 | struct gk20a_debug_output *o, |
342 | u32 hw_chid, | 341 | u32 hw_chid, |
343 | struct ch_state *ch_state); | 342 | struct ch_state *ch_state); |
343 | void gk20a_debug_dump_all_channel_status_ramfc(struct gk20a *g, | ||
344 | struct gk20a_debug_output *o); | ||
344 | void gk20a_dump_pbdma_status(struct gk20a *g, | 345 | void gk20a_dump_pbdma_status(struct gk20a *g, |
345 | struct gk20a_debug_output *o); | 346 | struct gk20a_debug_output *o); |
346 | void gk20a_dump_eng_status(struct gk20a *g, | 347 | void gk20a_dump_eng_status(struct gk20a *g, |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 689fafb1..899c1d6a 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -30,6 +30,7 @@ struct acr_desc; | |||
30 | struct nvgpu_mem_alloc_tracker; | 30 | struct nvgpu_mem_alloc_tracker; |
31 | struct dbg_profiler_object_data; | 31 | struct dbg_profiler_object_data; |
32 | struct ecc_gk20a; | 32 | struct ecc_gk20a; |
33 | struct gk20a_debug_output; | ||
33 | 34 | ||
34 | #include <linux/sched.h> | 35 | #include <linux/sched.h> |
35 | #include <nvgpu/lock.h> | 36 | #include <nvgpu/lock.h> |
@@ -61,7 +62,6 @@ struct ecc_gk20a; | |||
61 | #include "therm_gk20a.h" | 62 | #include "therm_gk20a.h" |
62 | #include "gm20b/acr_gm20b.h" | 63 | #include "gm20b/acr_gm20b.h" |
63 | #include "cde_gk20a.h" | 64 | #include "cde_gk20a.h" |
64 | #include "debug_gk20a.h" | ||
65 | #include "sched_gk20a.h" | 65 | #include "sched_gk20a.h" |
66 | #ifdef CONFIG_ARCH_TEGRA_18x_SOC | 66 | #ifdef CONFIG_ARCH_TEGRA_18x_SOC |
67 | #include "clk/clk.h" | 67 | #include "clk/clk.h" |
@@ -1544,10 +1544,6 @@ void nvgpu_wait_for_deferred_interrupts(struct gk20a *g); | |||
1544 | struct gk20a * __must_check gk20a_get(struct gk20a *g); | 1544 | struct gk20a * __must_check gk20a_get(struct gk20a *g); |
1545 | void gk20a_put(struct gk20a *g); | 1545 | void gk20a_put(struct gk20a *g); |
1546 | 1546 | ||
1547 | #ifdef CONFIG_DEBUG_FS | ||
1548 | int gk20a_railgating_debugfs_init(struct device *dev); | ||
1549 | #endif | ||
1550 | |||
1551 | static inline bool gk20a_platform_has_syncpoints(struct gk20a *g) | 1547 | static inline bool gk20a_platform_has_syncpoints(struct gk20a *g) |
1552 | { | 1548 | { |
1553 | #ifdef CONFIG_TEGRA_GK20A_NVHOST | 1549 | #ifdef CONFIG_TEGRA_GK20A_NVHOST |
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c index 2188618c..982cfac8 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <nvgpu/bug.h> | 30 | #include <nvgpu/bug.h> |
31 | #include <nvgpu/firmware.h> | 31 | #include <nvgpu/firmware.h> |
32 | #include <nvgpu/enabled.h> | 32 | #include <nvgpu/enabled.h> |
33 | #include <nvgpu/debug.h> | ||
33 | 34 | ||
34 | #include "gk20a.h" | 35 | #include "gk20a.h" |
35 | #include "kind_gk20a.h" | 36 | #include "kind_gk20a.h" |
@@ -37,13 +38,8 @@ | |||
37 | #include "gr_pri_gk20a.h" | 38 | #include "gr_pri_gk20a.h" |
38 | #include "regops_gk20a.h" | 39 | #include "regops_gk20a.h" |
39 | #include "dbg_gpu_gk20a.h" | 40 | #include "dbg_gpu_gk20a.h" |
40 | #include "debug_gk20a.h" | ||
41 | #include "ctxsw_trace_gk20a.h" | 41 | #include "ctxsw_trace_gk20a.h" |
42 | 42 | ||
43 | #ifdef CONFIG_DEBUG_FS | ||
44 | #include "platform_gk20a.h" | ||
45 | #endif | ||
46 | |||
47 | #include <nvgpu/hw/gk20a/hw_ccsr_gk20a.h> | 43 | #include <nvgpu/hw/gk20a/hw_ccsr_gk20a.h> |
48 | #include <nvgpu/hw/gk20a/hw_ctxsw_prog_gk20a.h> | 44 | #include <nvgpu/hw/gk20a/hw_ctxsw_prog_gk20a.h> |
49 | #include <nvgpu/hw/gk20a/hw_fifo_gk20a.h> | 45 | #include <nvgpu/hw/gk20a/hw_fifo_gk20a.h> |
@@ -514,7 +510,7 @@ int gr_gk20a_ctx_wait_ucode(struct gk20a *g, u32 mailbox_id, | |||
514 | nvgpu_err(g, | 510 | nvgpu_err(g, |
515 | "timeout waiting on ucode response"); | 511 | "timeout waiting on ucode response"); |
516 | gk20a_fecs_dump_falcon_stats(g); | 512 | gk20a_fecs_dump_falcon_stats(g); |
517 | gk20a_gr_debug_dump(g->dev); | 513 | gk20a_gr_debug_dump(g); |
518 | return -1; | 514 | return -1; |
519 | } else if (check == WAIT_UCODE_ERROR) { | 515 | } else if (check == WAIT_UCODE_ERROR) { |
520 | nvgpu_err(g, | 516 | nvgpu_err(g, |
@@ -9032,20 +9028,6 @@ static int gr_gk20a_dump_gr_status_regs(struct gk20a *g, | |||
9032 | return 0; | 9028 | return 0; |
9033 | } | 9029 | } |
9034 | 9030 | ||
9035 | #ifdef CONFIG_DEBUG_FS | ||
9036 | int gr_gk20a_debugfs_init(struct gk20a *g) | ||
9037 | { | ||
9038 | struct gk20a_platform *platform = dev_get_drvdata(g->dev); | ||
9039 | |||
9040 | g->debugfs_gr_default_attrib_cb_size = | ||
9041 | debugfs_create_u32("gr_default_attrib_cb_size", | ||
9042 | S_IRUGO|S_IWUSR, platform->debugfs, | ||
9043 | &g->gr.attrib_cb_default_size); | ||
9044 | |||
9045 | return 0; | ||
9046 | } | ||
9047 | #endif | ||
9048 | |||
9049 | static void gr_gk20a_init_cyclestats(struct gk20a *g) | 9031 | static void gr_gk20a_init_cyclestats(struct gk20a *g) |
9050 | { | 9032 | { |
9051 | #if defined(CONFIG_GK20A_CYCLE_STATS) | 9033 | #if defined(CONFIG_GK20A_CYCLE_STATS) |
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h index 79aeb42f..deb8ea9c 100644 --- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.h | |||
@@ -653,7 +653,6 @@ int gr_gk20a_alloc_gr_ctx(struct gk20a *g, | |||
653 | void gr_gk20a_free_gr_ctx(struct gk20a *g, | 653 | void gr_gk20a_free_gr_ctx(struct gk20a *g, |
654 | struct vm_gk20a *vm, struct gr_ctx_desc *gr_ctx); | 654 | struct vm_gk20a *vm, struct gr_ctx_desc *gr_ctx); |
655 | int gr_gk20a_halt_pipe(struct gk20a *g); | 655 | int gr_gk20a_halt_pipe(struct gk20a *g); |
656 | int gr_gk20a_debugfs_init(struct gk20a *g); | ||
657 | 656 | ||
658 | #if defined(CONFIG_GK20A_CYCLE_STATS) | 657 | #if defined(CONFIG_GK20A_CYCLE_STATS) |
659 | int gr_gk20a_css_attach(struct channel_gk20a *ch, /* in - main hw structure */ | 658 | int gr_gk20a_css_attach(struct channel_gk20a *ch, /* in - main hw structure */ |
diff --git a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c index 8a3beb39..b19398a6 100644 --- a/drivers/gpu/nvgpu/gk20a/hal_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/hal_gk20a.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "pramin_gk20a.h" | 37 | #include "pramin_gk20a.h" |
38 | #include "priv_ring_gk20a.h" | 38 | #include "priv_ring_gk20a.h" |
39 | 39 | ||
40 | #include <nvgpu/debug.h> | ||
40 | #include <nvgpu/log.h> | 41 | #include <nvgpu/log.h> |
41 | #include <nvgpu/bug.h> | 42 | #include <nvgpu/bug.h> |
42 | 43 | ||
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c index 53d22a7d..08e2e9cc 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.c | |||
@@ -2563,13 +2563,13 @@ priv_exist_or_err: | |||
2563 | return 0; | 2563 | return 0; |
2564 | } | 2564 | } |
2565 | 2565 | ||
2566 | int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct device *dev, | 2566 | int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct gk20a *g, |
2567 | u64 offset, struct gk20a_buffer_state **state) | 2567 | u64 offset, struct gk20a_buffer_state **state) |
2568 | { | 2568 | { |
2569 | int err = 0; | 2569 | int err = 0; |
2570 | struct gk20a_dmabuf_priv *priv; | 2570 | struct gk20a_dmabuf_priv *priv; |
2571 | struct gk20a_buffer_state *s; | 2571 | struct gk20a_buffer_state *s; |
2572 | struct gk20a *g = get_gk20a(dev); | 2572 | struct device *dev = g->dev; |
2573 | 2573 | ||
2574 | if (WARN_ON(offset >= (u64)dmabuf->size)) | 2574 | if (WARN_ON(offset >= (u64)dmabuf->size)) |
2575 | return -EINVAL; | 2575 | return -EINVAL; |
@@ -3123,18 +3123,6 @@ static bool gk20a_mm_is_bar1_supported(struct gk20a *g) | |||
3123 | return true; | 3123 | return true; |
3124 | } | 3124 | } |
3125 | 3125 | ||
3126 | #ifdef CONFIG_DEBUG_FS | ||
3127 | void gk20a_mm_debugfs_init(struct device *dev) | ||
3128 | { | ||
3129 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
3130 | struct dentry *gpu_root = platform->debugfs; | ||
3131 | struct gk20a *g = gk20a_get_platform(dev)->g; | ||
3132 | |||
3133 | debugfs_create_bool("force_pramin", 0664, gpu_root, | ||
3134 | &g->mm.force_pramin); | ||
3135 | } | ||
3136 | #endif | ||
3137 | |||
3138 | void gk20a_init_mm(struct gpu_ops *gops) | 3126 | void gk20a_init_mm(struct gpu_ops *gops) |
3139 | { | 3127 | { |
3140 | gops->mm.gmmu_map = gk20a_locked_gmmu_map; | 3128 | gops->mm.gmmu_map = gk20a_locked_gmmu_map; |
diff --git a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h index 79b55371..5d90cbf6 100644 --- a/drivers/gpu/nvgpu/gk20a/mm_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/mm_gk20a.h | |||
@@ -146,7 +146,6 @@ struct channel_gk20a; | |||
146 | int gk20a_init_mm_support(struct gk20a *g); | 146 | int gk20a_init_mm_support(struct gk20a *g); |
147 | int gk20a_init_mm_setup_sw(struct gk20a *g); | 147 | int gk20a_init_mm_setup_sw(struct gk20a *g); |
148 | int gk20a_init_mm_setup_hw(struct gk20a *g); | 148 | int gk20a_init_mm_setup_hw(struct gk20a *g); |
149 | void gk20a_mm_debugfs_init(struct device *dev); | ||
150 | void gk20a_init_mm_ce_context(struct gk20a *g); | 149 | void gk20a_init_mm_ce_context(struct gk20a *g); |
151 | 150 | ||
152 | int gk20a_mm_fb_flush(struct gk20a *g); | 151 | int gk20a_mm_fb_flush(struct gk20a *g); |
@@ -437,7 +436,7 @@ dma_addr_t gk20a_mm_gpuva_to_iova_base(struct vm_gk20a *vm, u64 gpu_vaddr); | |||
437 | 436 | ||
438 | int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev); | 437 | int gk20a_dmabuf_alloc_drvdata(struct dma_buf *dmabuf, struct device *dev); |
439 | 438 | ||
440 | int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct device *dev, | 439 | int gk20a_dmabuf_get_state(struct dma_buf *dmabuf, struct gk20a *g, |
441 | u64 offset, struct gk20a_buffer_state **state); | 440 | u64 offset, struct gk20a_buffer_state **state); |
442 | 441 | ||
443 | int map_gmmu_pages(struct gk20a *g, struct gk20a_mm_entry *entry); | 442 | int map_gmmu_pages(struct gk20a *g, struct gk20a_mm_entry *entry); |
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c index a9e03943..552d5d73 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c | |||
@@ -35,12 +35,6 @@ | |||
35 | #include "nvgpu_gpuid_t19x.h" | 35 | #include "nvgpu_gpuid_t19x.h" |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #ifdef CONFIG_DEBUG_FS | ||
39 | #include <linux/debugfs.h> | ||
40 | #include <linux/uaccess.h> | ||
41 | #include "platform_gk20a.h" | ||
42 | #endif | ||
43 | |||
44 | #define GK20A_PMU_UCODE_IMAGE "gpmu_ucode.bin" | 38 | #define GK20A_PMU_UCODE_IMAGE "gpmu_ucode.bin" |
45 | 39 | ||
46 | #define PMU_MEM_SCRUBBING_TIMEOUT_MAX 1000 | 40 | #define PMU_MEM_SCRUBBING_TIMEOUT_MAX 1000 |
@@ -49,7 +43,7 @@ | |||
49 | #define gk20a_dbg_pmu(fmt, arg...) \ | 43 | #define gk20a_dbg_pmu(fmt, arg...) \ |
50 | gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) | 44 | gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) |
51 | 45 | ||
52 | static int gk20a_pmu_get_pg_stats(struct gk20a *g, | 46 | int gk20a_pmu_get_pg_stats(struct gk20a *g, |
53 | u32 pg_engine_id, | 47 | u32 pg_engine_id, |
54 | struct pmu_pg_stats_data *pg_stat_data); | 48 | struct pmu_pg_stats_data *pg_stat_data); |
55 | static void ap_callback_init_and_enable_ctrl( | 49 | static void ap_callback_init_and_enable_ctrl( |
@@ -281,7 +275,7 @@ static void set_pmu_cmdline_args_falctracesize_v1( | |||
281 | pmu->args_v1.falc_trace_size = size; | 275 | pmu->args_v1.falc_trace_size = size; |
282 | } | 276 | } |
283 | 277 | ||
284 | static bool find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos) | 278 | bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos) |
285 | { | 279 | { |
286 | u32 i = 0, j = strlen(strings); | 280 | u32 i = 0, j = strlen(strings); |
287 | for (; i < j; i++) { | 281 | for (; i < j; i++) { |
@@ -326,7 +320,7 @@ static void printtrace(struct pmu_gk20a *pmu) | |||
326 | count = scnprintf(buf, 0x40, "Index %x: ", trace1[(i / 4)]); | 320 | count = scnprintf(buf, 0x40, "Index %x: ", trace1[(i / 4)]); |
327 | l = 0; | 321 | l = 0; |
328 | m = 0; | 322 | m = 0; |
329 | while (find_hex_in_string((trace+i+20+m), g, &k)) { | 323 | while (nvgpu_find_hex_in_string((trace+i+20+m), g, &k)) { |
330 | if (k >= 40) | 324 | if (k >= 40) |
331 | break; | 325 | break; |
332 | strncpy(part_str, (trace+i+20+m), k); | 326 | strncpy(part_str, (trace+i+20+m), k); |
@@ -4141,7 +4135,7 @@ void gk20a_pmu_save_zbc(struct gk20a *g, u32 entries) | |||
4141 | nvgpu_err(g, "ZBC save timeout"); | 4135 | nvgpu_err(g, "ZBC save timeout"); |
4142 | } | 4136 | } |
4143 | 4137 | ||
4144 | static int pmu_perfmon_start_sampling(struct pmu_gk20a *pmu) | 4138 | int nvgpu_pmu_perfmon_start_sampling(struct pmu_gk20a *pmu) |
4145 | { | 4139 | { |
4146 | struct gk20a *g = gk20a_from_pmu(pmu); | 4140 | struct gk20a *g = gk20a_from_pmu(pmu); |
4147 | struct pmu_v *pv = &g->ops.pmu_ver; | 4141 | struct pmu_v *pv = &g->ops.pmu_ver; |
@@ -4185,7 +4179,7 @@ static int pmu_perfmon_start_sampling(struct pmu_gk20a *pmu) | |||
4185 | return 0; | 4179 | return 0; |
4186 | } | 4180 | } |
4187 | 4181 | ||
4188 | static int pmu_perfmon_stop_sampling(struct pmu_gk20a *pmu) | 4182 | int nvgpu_pmu_perfmon_stop_sampling(struct pmu_gk20a *pmu) |
4189 | { | 4183 | { |
4190 | struct gk20a *g = gk20a_from_pmu(pmu); | 4184 | struct gk20a *g = gk20a_from_pmu(pmu); |
4191 | struct pmu_cmd cmd; | 4185 | struct pmu_cmd cmd; |
@@ -4231,7 +4225,7 @@ static int pmu_handle_perfmon_event(struct pmu_gk20a *pmu, | |||
4231 | 4225 | ||
4232 | /* restart sampling */ | 4226 | /* restart sampling */ |
4233 | if (pmu->perfmon_sampling_enabled) | 4227 | if (pmu->perfmon_sampling_enabled) |
4234 | return pmu_perfmon_start_sampling(pmu); | 4228 | return nvgpu_pmu_perfmon_start_sampling(pmu); |
4235 | return 0; | 4229 | return 0; |
4236 | } | 4230 | } |
4237 | 4231 | ||
@@ -5173,9 +5167,9 @@ int gk20a_pmu_perfmon_enable(struct gk20a *g, bool enable) | |||
5173 | gk20a_dbg_fn(""); | 5167 | gk20a_dbg_fn(""); |
5174 | 5168 | ||
5175 | if (enable) | 5169 | if (enable) |
5176 | err = pmu_perfmon_start_sampling(pmu); | 5170 | err = nvgpu_pmu_perfmon_start_sampling(pmu); |
5177 | else | 5171 | else |
5178 | err = pmu_perfmon_stop_sampling(pmu); | 5172 | err = nvgpu_pmu_perfmon_stop_sampling(pmu); |
5179 | 5173 | ||
5180 | return err; | 5174 | return err; |
5181 | } | 5175 | } |
@@ -5293,7 +5287,7 @@ void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id, | |||
5293 | pg_stat_data->avg_exit_latency_us = stats.pg_avg_exit_time_us; | 5287 | pg_stat_data->avg_exit_latency_us = stats.pg_avg_exit_time_us; |
5294 | } | 5288 | } |
5295 | 5289 | ||
5296 | static int gk20a_pmu_get_pg_stats(struct gk20a *g, | 5290 | int gk20a_pmu_get_pg_stats(struct gk20a *g, |
5297 | u32 pg_engine_id, | 5291 | u32 pg_engine_id, |
5298 | struct pmu_pg_stats_data *pg_stat_data) | 5292 | struct pmu_pg_stats_data *pg_stat_data) |
5299 | { | 5293 | { |
@@ -5463,466 +5457,3 @@ int gk20a_aelpg_init_and_enable(struct gk20a *g, u8 ctrl_id) | |||
5463 | status = gk20a_pmu_ap_send_command(g, &ap_cmd, true); | 5457 | status = gk20a_pmu_ap_send_command(g, &ap_cmd, true); |
5464 | return status; | 5458 | return status; |
5465 | } | 5459 | } |
5466 | |||
5467 | #ifdef CONFIG_DEBUG_FS | ||
5468 | static int lpwr_debug_show(struct seq_file *s, void *data) | ||
5469 | { | ||
5470 | struct gk20a *g = s->private; | ||
5471 | |||
5472 | if (g->ops.pmu.pmu_pg_engines_feature_list && | ||
5473 | g->ops.pmu.pmu_pg_engines_feature_list(g, | ||
5474 | PMU_PG_ELPG_ENGINE_ID_GRAPHICS) != | ||
5475 | PMU_PG_FEATURE_GR_POWER_GATING_ENABLED) { | ||
5476 | seq_printf(s, "PSTATE: %u\n" | ||
5477 | "RPPG Enabled: %u\n" | ||
5478 | "RPPG ref count: %u\n" | ||
5479 | "RPPG state: %u\n" | ||
5480 | "MSCG Enabled: %u\n" | ||
5481 | "MSCG pstate state: %u\n" | ||
5482 | "MSCG transition state: %u\n", | ||
5483 | g->ops.clk_arb.get_current_pstate(g), | ||
5484 | g->elpg_enabled, g->pmu.elpg_refcnt, | ||
5485 | g->pmu.elpg_stat, g->mscg_enabled, | ||
5486 | g->pmu.mscg_stat, g->pmu.mscg_transition_state); | ||
5487 | |||
5488 | } else | ||
5489 | seq_printf(s, "ELPG Enabled: %u\n" | ||
5490 | "ELPG ref count: %u\n" | ||
5491 | "ELPG state: %u\n", | ||
5492 | g->elpg_enabled, g->pmu.elpg_refcnt, | ||
5493 | g->pmu.elpg_stat); | ||
5494 | |||
5495 | return 0; | ||
5496 | |||
5497 | } | ||
5498 | |||
5499 | static int lpwr_debug_open(struct inode *inode, struct file *file) | ||
5500 | { | ||
5501 | return single_open(file, lpwr_debug_show, inode->i_private); | ||
5502 | } | ||
5503 | |||
5504 | static const struct file_operations lpwr_debug_fops = { | ||
5505 | .open = lpwr_debug_open, | ||
5506 | .read = seq_read, | ||
5507 | .llseek = seq_lseek, | ||
5508 | .release = single_release, | ||
5509 | }; | ||
5510 | |||
5511 | static int mscg_stat_show(struct seq_file *s, void *data) | ||
5512 | { | ||
5513 | struct gk20a *g = s->private; | ||
5514 | u64 total_ingating, total_ungating, residency, divisor, dividend; | ||
5515 | struct pmu_pg_stats_data pg_stat_data = { 0 }; | ||
5516 | int err; | ||
5517 | |||
5518 | /* Don't unnecessarily power on the device */ | ||
5519 | if (g->power_on) { | ||
5520 | err = gk20a_busy(g); | ||
5521 | if (err) | ||
5522 | return err; | ||
5523 | |||
5524 | gk20a_pmu_get_pg_stats(g, | ||
5525 | PMU_PG_ELPG_ENGINE_ID_MS, &pg_stat_data); | ||
5526 | gk20a_idle(g); | ||
5527 | } | ||
5528 | total_ingating = g->pg_ingating_time_us + | ||
5529 | (u64)pg_stat_data.ingating_time; | ||
5530 | total_ungating = g->pg_ungating_time_us + | ||
5531 | (u64)pg_stat_data.ungating_time; | ||
5532 | |||
5533 | divisor = total_ingating + total_ungating; | ||
5534 | |||
5535 | /* We compute the residency on a scale of 1000 */ | ||
5536 | dividend = total_ingating * 1000; | ||
5537 | |||
5538 | if (divisor) | ||
5539 | residency = div64_u64(dividend, divisor); | ||
5540 | else | ||
5541 | residency = 0; | ||
5542 | |||
5543 | seq_printf(s, | ||
5544 | "Time in MSCG: %llu us\n" | ||
5545 | "Time out of MSCG: %llu us\n" | ||
5546 | "MSCG residency ratio: %llu\n" | ||
5547 | "MSCG Entry Count: %u\n" | ||
5548 | "MSCG Avg Entry latency %u\n" | ||
5549 | "MSCG Avg Exit latency %u\n", | ||
5550 | total_ingating, total_ungating, | ||
5551 | residency, pg_stat_data.gating_cnt, | ||
5552 | pg_stat_data.avg_entry_latency_us, | ||
5553 | pg_stat_data.avg_exit_latency_us); | ||
5554 | return 0; | ||
5555 | |||
5556 | } | ||
5557 | |||
5558 | static int mscg_stat_open(struct inode *inode, struct file *file) | ||
5559 | { | ||
5560 | return single_open(file, mscg_stat_show, inode->i_private); | ||
5561 | } | ||
5562 | |||
5563 | static const struct file_operations mscg_stat_fops = { | ||
5564 | .open = mscg_stat_open, | ||
5565 | .read = seq_read, | ||
5566 | .llseek = seq_lseek, | ||
5567 | .release = single_release, | ||
5568 | }; | ||
5569 | |||
5570 | static int mscg_transitions_show(struct seq_file *s, void *data) | ||
5571 | { | ||
5572 | struct gk20a *g = s->private; | ||
5573 | struct pmu_pg_stats_data pg_stat_data = { 0 }; | ||
5574 | u32 total_gating_cnt; | ||
5575 | int err; | ||
5576 | |||
5577 | if (g->power_on) { | ||
5578 | err = gk20a_busy(g); | ||
5579 | if (err) | ||
5580 | return err; | ||
5581 | |||
5582 | gk20a_pmu_get_pg_stats(g, | ||
5583 | PMU_PG_ELPG_ENGINE_ID_MS, &pg_stat_data); | ||
5584 | gk20a_idle(g); | ||
5585 | } | ||
5586 | total_gating_cnt = g->pg_gating_cnt + pg_stat_data.gating_cnt; | ||
5587 | |||
5588 | seq_printf(s, "%u\n", total_gating_cnt); | ||
5589 | return 0; | ||
5590 | |||
5591 | } | ||
5592 | |||
5593 | static int mscg_transitions_open(struct inode *inode, struct file *file) | ||
5594 | { | ||
5595 | return single_open(file, mscg_transitions_show, inode->i_private); | ||
5596 | } | ||
5597 | |||
5598 | static const struct file_operations mscg_transitions_fops = { | ||
5599 | .open = mscg_transitions_open, | ||
5600 | .read = seq_read, | ||
5601 | .llseek = seq_lseek, | ||
5602 | .release = single_release, | ||
5603 | }; | ||
5604 | |||
5605 | static int elpg_stat_show(struct seq_file *s, void *data) | ||
5606 | { | ||
5607 | struct gk20a *g = s->private; | ||
5608 | struct pmu_pg_stats_data pg_stat_data = { 0 }; | ||
5609 | u64 total_ingating, total_ungating, residency, divisor, dividend; | ||
5610 | int err; | ||
5611 | |||
5612 | /* Don't unnecessarily power on the device */ | ||
5613 | if (g->power_on) { | ||
5614 | err = gk20a_busy(g); | ||
5615 | if (err) | ||
5616 | return err; | ||
5617 | |||
5618 | gk20a_pmu_get_pg_stats(g, | ||
5619 | PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data); | ||
5620 | gk20a_idle(g); | ||
5621 | } | ||
5622 | total_ingating = g->pg_ingating_time_us + | ||
5623 | (u64)pg_stat_data.ingating_time; | ||
5624 | total_ungating = g->pg_ungating_time_us + | ||
5625 | (u64)pg_stat_data.ungating_time; | ||
5626 | divisor = total_ingating + total_ungating; | ||
5627 | |||
5628 | /* We compute the residency on a scale of 1000 */ | ||
5629 | dividend = total_ingating * 1000; | ||
5630 | |||
5631 | if (divisor) | ||
5632 | residency = div64_u64(dividend, divisor); | ||
5633 | else | ||
5634 | residency = 0; | ||
5635 | |||
5636 | seq_printf(s, | ||
5637 | "Time in ELPG: %llu us\n" | ||
5638 | "Time out of ELPG: %llu us\n" | ||
5639 | "ELPG residency ratio: %llu\n" | ||
5640 | "ELPG Entry Count: %u\n" | ||
5641 | "ELPG Avg Entry latency %u us\n" | ||
5642 | "ELPG Avg Exit latency %u us\n", | ||
5643 | total_ingating, total_ungating, | ||
5644 | residency, pg_stat_data.gating_cnt, | ||
5645 | pg_stat_data.avg_entry_latency_us, | ||
5646 | pg_stat_data.avg_exit_latency_us); | ||
5647 | return 0; | ||
5648 | |||
5649 | } | ||
5650 | |||
5651 | static int elpg_stat_open(struct inode *inode, struct file *file) | ||
5652 | { | ||
5653 | return single_open(file, elpg_stat_show, inode->i_private); | ||
5654 | } | ||
5655 | |||
5656 | static const struct file_operations elpg_stat_fops = { | ||
5657 | .open = elpg_stat_open, | ||
5658 | .read = seq_read, | ||
5659 | .llseek = seq_lseek, | ||
5660 | .release = single_release, | ||
5661 | }; | ||
5662 | |||
5663 | static int elpg_transitions_show(struct seq_file *s, void *data) | ||
5664 | { | ||
5665 | struct gk20a *g = s->private; | ||
5666 | struct pmu_pg_stats_data pg_stat_data = { 0 }; | ||
5667 | u32 total_gating_cnt; | ||
5668 | int err; | ||
5669 | |||
5670 | if (g->power_on) { | ||
5671 | err = gk20a_busy(g); | ||
5672 | if (err) | ||
5673 | return err; | ||
5674 | |||
5675 | gk20a_pmu_get_pg_stats(g, | ||
5676 | PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data); | ||
5677 | gk20a_idle(g); | ||
5678 | } | ||
5679 | total_gating_cnt = g->pg_gating_cnt + pg_stat_data.gating_cnt; | ||
5680 | |||
5681 | seq_printf(s, "%u\n", total_gating_cnt); | ||
5682 | return 0; | ||
5683 | |||
5684 | } | ||
5685 | |||
5686 | static int elpg_transitions_open(struct inode *inode, struct file *file) | ||
5687 | { | ||
5688 | return single_open(file, elpg_transitions_show, inode->i_private); | ||
5689 | } | ||
5690 | |||
5691 | static const struct file_operations elpg_transitions_fops = { | ||
5692 | .open = elpg_transitions_open, | ||
5693 | .read = seq_read, | ||
5694 | .llseek = seq_lseek, | ||
5695 | .release = single_release, | ||
5696 | }; | ||
5697 | |||
5698 | static int falc_trace_show(struct seq_file *s, void *data) | ||
5699 | { | ||
5700 | struct gk20a *g = s->private; | ||
5701 | struct pmu_gk20a *pmu = &g->pmu; | ||
5702 | u32 i = 0, j = 0, k, l, m; | ||
5703 | char part_str[40]; | ||
5704 | void *tracebuffer; | ||
5705 | char *trace; | ||
5706 | u32 *trace1; | ||
5707 | |||
5708 | /* allocate system memory to copy pmu trace buffer */ | ||
5709 | tracebuffer = nvgpu_kzalloc(g, GK20A_PMU_TRACE_BUFSIZE); | ||
5710 | if (tracebuffer == NULL) | ||
5711 | return -ENOMEM; | ||
5712 | |||
5713 | /* read pmu traces into system memory buffer */ | ||
5714 | nvgpu_mem_rd_n(g, &pmu->trace_buf, | ||
5715 | 0, tracebuffer, GK20A_PMU_TRACE_BUFSIZE); | ||
5716 | |||
5717 | trace = (char *)tracebuffer; | ||
5718 | trace1 = (u32 *)tracebuffer; | ||
5719 | |||
5720 | for (i = 0; i < GK20A_PMU_TRACE_BUFSIZE; i += 0x40) { | ||
5721 | for (j = 0; j < 0x40; j++) | ||
5722 | if (trace1[(i / 4) + j]) | ||
5723 | break; | ||
5724 | if (j == 0x40) | ||
5725 | break; | ||
5726 | seq_printf(s, "Index %x: ", trace1[(i / 4)]); | ||
5727 | l = 0; | ||
5728 | m = 0; | ||
5729 | while (find_hex_in_string((trace+i+20+m), g, &k)) { | ||
5730 | if (k >= 40) | ||
5731 | break; | ||
5732 | strncpy(part_str, (trace+i+20+m), k); | ||
5733 | part_str[k] = 0; | ||
5734 | seq_printf(s, "%s0x%x", part_str, | ||
5735 | trace1[(i / 4) + 1 + l]); | ||
5736 | l++; | ||
5737 | m += k + 2; | ||
5738 | } | ||
5739 | seq_printf(s, "%s", (trace+i+20+m)); | ||
5740 | } | ||
5741 | |||
5742 | nvgpu_kfree(g, tracebuffer); | ||
5743 | return 0; | ||
5744 | } | ||
5745 | |||
5746 | static int falc_trace_open(struct inode *inode, struct file *file) | ||
5747 | { | ||
5748 | return single_open(file, falc_trace_show, inode->i_private); | ||
5749 | } | ||
5750 | |||
5751 | static const struct file_operations falc_trace_fops = { | ||
5752 | .open = falc_trace_open, | ||
5753 | .read = seq_read, | ||
5754 | .llseek = seq_lseek, | ||
5755 | .release = single_release, | ||
5756 | }; | ||
5757 | |||
5758 | static int perfmon_events_enable_show(struct seq_file *s, void *data) | ||
5759 | { | ||
5760 | struct gk20a *g = s->private; | ||
5761 | |||
5762 | seq_printf(s, "%u\n", g->pmu.perfmon_sampling_enabled ? 1 : 0); | ||
5763 | return 0; | ||
5764 | |||
5765 | } | ||
5766 | |||
5767 | static int perfmon_events_enable_open(struct inode *inode, struct file *file) | ||
5768 | { | ||
5769 | return single_open(file, perfmon_events_enable_show, inode->i_private); | ||
5770 | } | ||
5771 | |||
5772 | static ssize_t perfmon_events_enable_write(struct file *file, | ||
5773 | const char __user *userbuf, size_t count, loff_t *ppos) | ||
5774 | { | ||
5775 | struct seq_file *s = file->private_data; | ||
5776 | struct gk20a *g = s->private; | ||
5777 | unsigned long val = 0; | ||
5778 | char buf[40]; | ||
5779 | int buf_size; | ||
5780 | int err; | ||
5781 | |||
5782 | memset(buf, 0, sizeof(buf)); | ||
5783 | buf_size = min(count, (sizeof(buf)-1)); | ||
5784 | |||
5785 | if (copy_from_user(buf, userbuf, buf_size)) | ||
5786 | return -EFAULT; | ||
5787 | |||
5788 | if (kstrtoul(buf, 10, &val) < 0) | ||
5789 | return -EINVAL; | ||
5790 | |||
5791 | /* Don't turn on gk20a unnecessarily */ | ||
5792 | if (g->power_on) { | ||
5793 | err = gk20a_busy(g); | ||
5794 | if (err) | ||
5795 | return err; | ||
5796 | |||
5797 | if (val && !g->pmu.perfmon_sampling_enabled) { | ||
5798 | g->pmu.perfmon_sampling_enabled = true; | ||
5799 | pmu_perfmon_start_sampling(&(g->pmu)); | ||
5800 | } else if (!val && g->pmu.perfmon_sampling_enabled) { | ||
5801 | g->pmu.perfmon_sampling_enabled = false; | ||
5802 | pmu_perfmon_stop_sampling(&(g->pmu)); | ||
5803 | } | ||
5804 | gk20a_idle(g); | ||
5805 | } else { | ||
5806 | g->pmu.perfmon_sampling_enabled = val ? true : false; | ||
5807 | } | ||
5808 | |||
5809 | return count; | ||
5810 | } | ||
5811 | |||
5812 | static const struct file_operations perfmon_events_enable_fops = { | ||
5813 | .open = perfmon_events_enable_open, | ||
5814 | .read = seq_read, | ||
5815 | .write = perfmon_events_enable_write, | ||
5816 | .llseek = seq_lseek, | ||
5817 | .release = single_release, | ||
5818 | }; | ||
5819 | |||
5820 | static int perfmon_events_count_show(struct seq_file *s, void *data) | ||
5821 | { | ||
5822 | struct gk20a *g = s->private; | ||
5823 | |||
5824 | seq_printf(s, "%lu\n", g->pmu.perfmon_events_cnt); | ||
5825 | return 0; | ||
5826 | |||
5827 | } | ||
5828 | |||
5829 | static int perfmon_events_count_open(struct inode *inode, struct file *file) | ||
5830 | { | ||
5831 | return single_open(file, perfmon_events_count_show, inode->i_private); | ||
5832 | } | ||
5833 | |||
5834 | static const struct file_operations perfmon_events_count_fops = { | ||
5835 | .open = perfmon_events_count_open, | ||
5836 | .read = seq_read, | ||
5837 | .llseek = seq_lseek, | ||
5838 | .release = single_release, | ||
5839 | }; | ||
5840 | |||
5841 | static int security_show(struct seq_file *s, void *data) | ||
5842 | { | ||
5843 | struct gk20a *g = s->private; | ||
5844 | |||
5845 | seq_printf(s, "%d\n", g->pmu.pmu_mode); | ||
5846 | return 0; | ||
5847 | |||
5848 | } | ||
5849 | |||
5850 | static int security_open(struct inode *inode, struct file *file) | ||
5851 | { | ||
5852 | return single_open(file, security_show, inode->i_private); | ||
5853 | } | ||
5854 | |||
5855 | static const struct file_operations security_fops = { | ||
5856 | .open = security_open, | ||
5857 | .read = seq_read, | ||
5858 | .llseek = seq_lseek, | ||
5859 | .release = single_release, | ||
5860 | }; | ||
5861 | |||
5862 | int gk20a_pmu_debugfs_init(struct device *dev) | ||
5863 | { | ||
5864 | struct dentry *d; | ||
5865 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
5866 | struct gk20a *g = get_gk20a(dev); | ||
5867 | |||
5868 | d = debugfs_create_file( | ||
5869 | "lpwr_debug", S_IRUGO|S_IWUSR, platform->debugfs, g, | ||
5870 | &lpwr_debug_fops); | ||
5871 | if (!d) | ||
5872 | goto err_out; | ||
5873 | |||
5874 | d = debugfs_create_file( | ||
5875 | "mscg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g, | ||
5876 | &mscg_stat_fops); | ||
5877 | if (!d) | ||
5878 | goto err_out; | ||
5879 | |||
5880 | d = debugfs_create_file( | ||
5881 | "mscg_transitions", S_IRUGO, platform->debugfs, g, | ||
5882 | &mscg_transitions_fops); | ||
5883 | if (!d) | ||
5884 | goto err_out; | ||
5885 | |||
5886 | d = debugfs_create_file( | ||
5887 | "elpg_residency", S_IRUGO|S_IWUSR, platform->debugfs, g, | ||
5888 | &elpg_stat_fops); | ||
5889 | if (!d) | ||
5890 | goto err_out; | ||
5891 | |||
5892 | d = debugfs_create_file( | ||
5893 | "elpg_transitions", S_IRUGO, platform->debugfs, g, | ||
5894 | &elpg_transitions_fops); | ||
5895 | if (!d) | ||
5896 | goto err_out; | ||
5897 | |||
5898 | d = debugfs_create_file( | ||
5899 | "falc_trace", S_IRUGO, platform->debugfs, g, | ||
5900 | &falc_trace_fops); | ||
5901 | if (!d) | ||
5902 | goto err_out; | ||
5903 | |||
5904 | d = debugfs_create_file( | ||
5905 | "perfmon_events_enable", S_IRUGO, platform->debugfs, g, | ||
5906 | &perfmon_events_enable_fops); | ||
5907 | if (!d) | ||
5908 | goto err_out; | ||
5909 | |||
5910 | d = debugfs_create_file( | ||
5911 | "perfmon_events_count", S_IRUGO, platform->debugfs, g, | ||
5912 | &perfmon_events_count_fops); | ||
5913 | if (!d) | ||
5914 | goto err_out; | ||
5915 | |||
5916 | d = debugfs_create_file( | ||
5917 | "pmu_security", S_IRUGO, platform->debugfs, g, | ||
5918 | &security_fops); | ||
5919 | if (!d) | ||
5920 | goto err_out; | ||
5921 | return 0; | ||
5922 | err_out: | ||
5923 | pr_err("%s: Failed to make debugfs node\n", __func__); | ||
5924 | debugfs_remove_recursive(platform->debugfs); | ||
5925 | return -ENOMEM; | ||
5926 | } | ||
5927 | |||
5928 | #endif | ||
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h index e7a8b7c2..cefb6577 100644 --- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h | |||
@@ -426,7 +426,6 @@ int pmu_mutex_release(struct pmu_gk20a *pmu, u32 id, u32 *token); | |||
426 | int gk20a_pmu_destroy(struct gk20a *g); | 426 | int gk20a_pmu_destroy(struct gk20a *g); |
427 | int gk20a_pmu_load_norm(struct gk20a *g, u32 *load); | 427 | int gk20a_pmu_load_norm(struct gk20a *g, u32 *load); |
428 | int gk20a_pmu_load_update(struct gk20a *g); | 428 | int gk20a_pmu_load_update(struct gk20a *g); |
429 | int gk20a_pmu_debugfs_init(struct device *dev); | ||
430 | void gk20a_pmu_reset_load_counters(struct gk20a *g); | 429 | void gk20a_pmu_reset_load_counters(struct gk20a *g); |
431 | void gk20a_pmu_get_load_counters(struct gk20a *g, u32 *busy_cycles, | 430 | void gk20a_pmu_get_load_counters(struct gk20a *g, u32 *busy_cycles, |
432 | u32 *total_cycles); | 431 | u32 *total_cycles); |
@@ -468,5 +467,11 @@ int gk20a_pmu_vidmem_surface_alloc(struct gk20a *g, struct nvgpu_mem *mem, | |||
468 | u32 size); | 467 | u32 size); |
469 | int gk20a_pmu_sysmem_surface_alloc(struct gk20a *g, struct nvgpu_mem *mem, | 468 | int gk20a_pmu_sysmem_surface_alloc(struct gk20a *g, struct nvgpu_mem *mem, |
470 | u32 size); | 469 | u32 size); |
470 | int gk20a_pmu_get_pg_stats(struct gk20a *g, | ||
471 | u32 pg_engine_id, struct pmu_pg_stats_data *pg_stat_data); | ||
472 | bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos); | ||
473 | |||
474 | int nvgpu_pmu_perfmon_start_sampling(struct pmu_gk20a *pmu); | ||
475 | int nvgpu_pmu_perfmon_stop_sampling(struct pmu_gk20a *pmu); | ||
471 | 476 | ||
472 | #endif /*__PMU_GK20A_H__*/ | 477 | #endif /*__PMU_GK20A_H__*/ |
diff --git a/drivers/gpu/nvgpu/gk20a/sched_gk20a.c b/drivers/gpu/nvgpu/gk20a/sched_gk20a.c index b7edf3f0..3f3119af 100644 --- a/drivers/gpu/nvgpu/gk20a/sched_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/sched_gk20a.c | |||
@@ -13,10 +13,6 @@ | |||
13 | 13 | ||
14 | #include <asm/barrier.h> | 14 | #include <asm/barrier.h> |
15 | #include <linux/wait.h> | 15 | #include <linux/wait.h> |
16 | #ifdef CONFIG_DEBUG_FS | ||
17 | #include <linux/debugfs.h> | ||
18 | #include "platform_gk20a.h" | ||
19 | #endif | ||
20 | #include <linux/uaccess.h> | 16 | #include <linux/uaccess.h> |
21 | #include <linux/poll.h> | 17 | #include <linux/poll.h> |
22 | #include <uapi/linux/nvgpu.h> | 18 | #include <uapi/linux/nvgpu.h> |
@@ -523,69 +519,6 @@ int gk20a_sched_dev_release(struct inode *inode, struct file *filp) | |||
523 | return 0; | 519 | return 0; |
524 | } | 520 | } |
525 | 521 | ||
526 | #ifdef CONFIG_DEBUG_FS | ||
527 | static int gk20a_sched_debugfs_show(struct seq_file *s, void *unused) | ||
528 | { | ||
529 | struct device *dev = s->private; | ||
530 | struct gk20a *g = gk20a_get_platform(dev)->g; | ||
531 | struct gk20a_sched_ctrl *sched = &g->sched_ctrl; | ||
532 | bool sched_busy = true; | ||
533 | |||
534 | int n = sched->bitmap_size / sizeof(u64); | ||
535 | int i; | ||
536 | int err; | ||
537 | |||
538 | err = gk20a_busy(g); | ||
539 | if (err) | ||
540 | return err; | ||
541 | |||
542 | if (nvgpu_mutex_tryacquire(&sched->busy_lock)) { | ||
543 | sched_busy = false; | ||
544 | nvgpu_mutex_release(&sched->busy_lock); | ||
545 | } | ||
546 | |||
547 | seq_printf(s, "control_locked=%d\n", sched->control_locked); | ||
548 | seq_printf(s, "busy=%d\n", sched_busy); | ||
549 | seq_printf(s, "bitmap_size=%zu\n", sched->bitmap_size); | ||
550 | |||
551 | nvgpu_mutex_acquire(&sched->status_lock); | ||
552 | |||
553 | seq_puts(s, "active_tsg_bitmap\n"); | ||
554 | for (i = 0; i < n; i++) | ||
555 | seq_printf(s, "\t0x%016llx\n", sched->active_tsg_bitmap[i]); | ||
556 | |||
557 | seq_puts(s, "recent_tsg_bitmap\n"); | ||
558 | for (i = 0; i < n; i++) | ||
559 | seq_printf(s, "\t0x%016llx\n", sched->recent_tsg_bitmap[i]); | ||
560 | |||
561 | nvgpu_mutex_release(&sched->status_lock); | ||
562 | |||
563 | gk20a_idle(g); | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | static int gk20a_sched_debugfs_open(struct inode *inode, struct file *file) | ||
569 | { | ||
570 | return single_open(file, gk20a_sched_debugfs_show, inode->i_private); | ||
571 | } | ||
572 | |||
573 | static const struct file_operations gk20a_sched_debugfs_fops = { | ||
574 | .open = gk20a_sched_debugfs_open, | ||
575 | .read = seq_read, | ||
576 | .llseek = seq_lseek, | ||
577 | .release = single_release, | ||
578 | }; | ||
579 | |||
580 | void gk20a_sched_debugfs_init(struct device *dev) | ||
581 | { | ||
582 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
583 | |||
584 | debugfs_create_file("sched_ctrl", S_IRUGO, platform->debugfs, | ||
585 | dev, &gk20a_sched_debugfs_fops); | ||
586 | } | ||
587 | #endif /* CONFIG_DEBUG_FS */ | ||
588 | |||
589 | void gk20a_sched_ctrl_tsg_added(struct gk20a *g, struct tsg_gk20a *tsg) | 522 | void gk20a_sched_ctrl_tsg_added(struct gk20a *g, struct tsg_gk20a *tsg) |
590 | { | 523 | { |
591 | struct gk20a_sched_ctrl *sched = &g->sched_ctrl; | 524 | struct gk20a_sched_ctrl *sched = &g->sched_ctrl; |
diff --git a/drivers/gpu/nvgpu/gk20a/sched_gk20a.h b/drivers/gpu/nvgpu/gk20a/sched_gk20a.h index 4f6d1510..776f689d 100644 --- a/drivers/gpu/nvgpu/gk20a/sched_gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/sched_gk20a.h | |||
@@ -48,7 +48,6 @@ void gk20a_sched_ctrl_tsg_added(struct gk20a *, struct tsg_gk20a *); | |||
48 | void gk20a_sched_ctrl_tsg_removed(struct gk20a *, struct tsg_gk20a *); | 48 | void gk20a_sched_ctrl_tsg_removed(struct gk20a *, struct tsg_gk20a *); |
49 | int gk20a_sched_ctrl_init(struct gk20a *); | 49 | int gk20a_sched_ctrl_init(struct gk20a *); |
50 | 50 | ||
51 | void gk20a_sched_debugfs_init(struct device *dev); | ||
52 | void gk20a_sched_ctrl_cleanup(struct gk20a *g); | 51 | void gk20a_sched_ctrl_cleanup(struct gk20a *g); |
53 | 52 | ||
54 | #endif /* __SCHED_GK20A_H */ | 53 | #endif /* __SCHED_GK20A_H */ |