diff options
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.c | 97 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/gk20a.h | 15 |
2 files changed, 112 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c index ab417386..9255c847 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/gk20a.c | |||
@@ -94,6 +94,71 @@ u32 gk20a_dbg_ftrace; | |||
94 | 94 | ||
95 | static int gk20a_pm_prepare_poweroff(struct device *dev); | 95 | static int gk20a_pm_prepare_poweroff(struct device *dev); |
96 | 96 | ||
97 | #ifdef CONFIG_DEBUG_FS | ||
98 | static int railgate_residency_show(struct seq_file *s, void *data) | ||
99 | { | ||
100 | struct device *dev = s->private; | ||
101 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
102 | struct gk20a *g = get_gk20a(dev); | ||
103 | unsigned long time_since_last_state_transition_ms; | ||
104 | unsigned long total_rail_gate_time_ms; | ||
105 | unsigned long total_rail_ungate_time_ms; | ||
106 | |||
107 | if (platform->is_railgated(dev)) { | ||
108 | time_since_last_state_transition_ms = | ||
109 | jiffies_to_msecs(jiffies - | ||
110 | g->pstats.last_rail_gate_complete); | ||
111 | total_rail_ungate_time_ms = g->pstats.total_rail_ungate_time_ms; | ||
112 | total_rail_gate_time_ms = | ||
113 | g->pstats.total_rail_gate_time_ms + | ||
114 | time_since_last_state_transition_ms; | ||
115 | } else { | ||
116 | time_since_last_state_transition_ms = | ||
117 | jiffies_to_msecs(jiffies - | ||
118 | g->pstats.last_rail_ungate_complete); | ||
119 | total_rail_gate_time_ms = g->pstats.total_rail_gate_time_ms; | ||
120 | total_rail_ungate_time_ms = | ||
121 | g->pstats.total_rail_ungate_time_ms + | ||
122 | time_since_last_state_transition_ms; | ||
123 | } | ||
124 | |||
125 | seq_printf(s, "Time with Rails Gated: %lu ms\n" | ||
126 | "Time with Rails UnGated: %lu ms\n" | ||
127 | "Total railgating cycles: %lu\n", | ||
128 | total_rail_gate_time_ms, | ||
129 | total_rail_ungate_time_ms, | ||
130 | g->pstats.railgating_cycle_count - 1); | ||
131 | return 0; | ||
132 | |||
133 | } | ||
134 | |||
135 | static int railgate_residency_open(struct inode *inode, struct file *file) | ||
136 | { | ||
137 | return single_open(file, railgate_residency_show, inode->i_private); | ||
138 | } | ||
139 | |||
140 | static const struct file_operations railgate_residency_fops = { | ||
141 | .open = railgate_residency_open, | ||
142 | .read = seq_read, | ||
143 | .llseek = seq_lseek, | ||
144 | .release = single_release, | ||
145 | }; | ||
146 | |||
147 | int gk20a_railgating_debugfs_init(struct device *dev) | ||
148 | { | ||
149 | struct dentry *d; | ||
150 | struct gk20a_platform *platform = dev_get_drvdata(dev); | ||
151 | |||
152 | d = debugfs_create_file( | ||
153 | "railgate_residency", S_IRUGO|S_IWUSR, platform->debugfs, dev, | ||
154 | &railgate_residency_fops); | ||
155 | if (!d) | ||
156 | return -ENOMEM; | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | #endif | ||
161 | |||
97 | static inline void set_gk20a(struct platform_device *pdev, struct gk20a *gk20a) | 162 | static inline void set_gk20a(struct platform_device *pdev, struct gk20a *gk20a) |
98 | { | 163 | { |
99 | gk20a_get_platform(&pdev->dev)->g = gk20a; | 164 | gk20a_get_platform(&pdev->dev)->g = gk20a; |
@@ -1133,10 +1198,25 @@ static int gk20a_pm_railgate(struct device *dev) | |||
1133 | { | 1198 | { |
1134 | struct gk20a_platform *platform = dev_get_drvdata(dev); | 1199 | struct gk20a_platform *platform = dev_get_drvdata(dev); |
1135 | int ret = 0; | 1200 | int ret = 0; |
1201 | #ifdef CONFIG_DEBUG_FS | ||
1202 | struct gk20a *g = get_gk20a(dev); | ||
1203 | |||
1204 | g->pstats.last_rail_gate_start = jiffies; | ||
1205 | |||
1206 | if (g->pstats.railgating_cycle_count >= 1) | ||
1207 | g->pstats.total_rail_ungate_time_ms = | ||
1208 | g->pstats.total_rail_ungate_time_ms + | ||
1209 | jiffies_to_msecs(g->pstats.last_rail_gate_start - | ||
1210 | g->pstats.last_rail_ungate_complete); | ||
1211 | #endif | ||
1136 | 1212 | ||
1137 | if (platform->railgate) | 1213 | if (platform->railgate) |
1138 | ret = platform->railgate(dev); | 1214 | ret = platform->railgate(dev); |
1139 | 1215 | ||
1216 | #ifdef CONFIG_DEBUG_FS | ||
1217 | g->pstats.last_rail_gate_complete = jiffies; | ||
1218 | #endif | ||
1219 | |||
1140 | return ret; | 1220 | return ret; |
1141 | } | 1221 | } |
1142 | 1222 | ||
@@ -1144,6 +1224,18 @@ static int gk20a_pm_unrailgate(struct device *dev) | |||
1144 | { | 1224 | { |
1145 | struct gk20a_platform *platform = dev_get_drvdata(dev); | 1225 | struct gk20a_platform *platform = dev_get_drvdata(dev); |
1146 | int ret = 0; | 1226 | int ret = 0; |
1227 | #ifdef CONFIG_DEBUG_FS | ||
1228 | struct gk20a *g = get_gk20a(dev); | ||
1229 | |||
1230 | g->pstats.last_rail_ungate_start = jiffies; | ||
1231 | if (g->pstats.railgating_cycle_count >= 1) | ||
1232 | g->pstats.total_rail_gate_time_ms = | ||
1233 | g->pstats.total_rail_gate_time_ms + | ||
1234 | jiffies_to_msecs(g->pstats.last_rail_ungate_start - | ||
1235 | g->pstats.last_rail_gate_complete); | ||
1236 | |||
1237 | g->pstats.railgating_cycle_count++; | ||
1238 | #endif | ||
1147 | 1239 | ||
1148 | trace_gk20a_pm_unrailgate(dev_name(dev)); | 1240 | trace_gk20a_pm_unrailgate(dev_name(dev)); |
1149 | 1241 | ||
@@ -1153,6 +1245,10 @@ static int gk20a_pm_unrailgate(struct device *dev) | |||
1153 | mutex_unlock(&platform->railgate_lock); | 1245 | mutex_unlock(&platform->railgate_lock); |
1154 | } | 1246 | } |
1155 | 1247 | ||
1248 | #ifdef CONFIG_DEBUG_FS | ||
1249 | g->pstats.last_rail_ungate_complete = jiffies; | ||
1250 | #endif | ||
1251 | |||
1156 | return ret; | 1252 | return ret; |
1157 | } | 1253 | } |
1158 | 1254 | ||
@@ -1531,6 +1627,7 @@ static int gk20a_probe(struct platform_device *dev) | |||
1531 | 1627 | ||
1532 | gr_gk20a_debugfs_init(gk20a); | 1628 | gr_gk20a_debugfs_init(gk20a); |
1533 | gk20a_pmu_debugfs_init(&dev->dev); | 1629 | gk20a_pmu_debugfs_init(&dev->dev); |
1630 | gk20a_railgating_debugfs_init(&dev->dev); | ||
1534 | gk20a_cde_debugfs_init(&dev->dev); | 1631 | gk20a_cde_debugfs_init(&dev->dev); |
1535 | gk20a_alloc_debugfs_init(dev); | 1632 | gk20a_alloc_debugfs_init(dev); |
1536 | gk20a_mm_debugfs_init(&dev->dev); | 1633 | gk20a_mm_debugfs_init(&dev->dev); |
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h index 949cd4a5..c5da68cc 100644 --- a/drivers/gpu/nvgpu/gk20a/gk20a.h +++ b/drivers/gpu/nvgpu/gk20a/gk20a.h | |||
@@ -64,6 +64,18 @@ struct cooling_device_gk20a { | |||
64 | struct gk20a *g; | 64 | struct gk20a *g; |
65 | }; | 65 | }; |
66 | 66 | ||
67 | #ifdef CONFIG_DEBUG_FS | ||
68 | struct railgate_stats { | ||
69 | unsigned long last_rail_gate_start; | ||
70 | unsigned long last_rail_gate_complete; | ||
71 | unsigned long last_rail_ungate_start; | ||
72 | unsigned long last_rail_ungate_complete; | ||
73 | unsigned long total_rail_gate_time_ms; | ||
74 | unsigned long total_rail_ungate_time_ms; | ||
75 | unsigned long railgating_cycle_count; | ||
76 | }; | ||
77 | #endif | ||
78 | |||
67 | enum gk20a_cbc_op { | 79 | enum gk20a_cbc_op { |
68 | gk20a_cbc_op_clear, | 80 | gk20a_cbc_op_clear, |
69 | gk20a_cbc_op_clean, | 81 | gk20a_cbc_op_clean, |
@@ -687,6 +699,9 @@ struct gk20a { | |||
687 | struct acr_desc acr; | 699 | struct acr_desc acr; |
688 | struct cooling_device_gk20a gk20a_cdev; | 700 | struct cooling_device_gk20a gk20a_cdev; |
689 | 701 | ||
702 | #ifdef CONFIG_DEBUG_FS | ||
703 | struct railgate_stats pstats; | ||
704 | #endif | ||
690 | /* Save pmu fw here so that it lives cross suspend/resume. | 705 | /* Save pmu fw here so that it lives cross suspend/resume. |
691 | pmu suspend destroys all pmu sw/hw states. Loading pmu | 706 | pmu suspend destroys all pmu sw/hw states. Loading pmu |
692 | fw in resume crashes when the resume is from sys_exit. */ | 707 | fw in resume crashes when the resume is from sys_exit. */ |