blob: 154ac265f9b192803c91a11740db7a55405b34af [file] [log] [blame]
Skylar Chang4d6a8fe2017-03-16 16:55:57 -07001/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
Amir Levycdccd632016-10-30 09:36:41 +02002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#ifdef CONFIG_DEBUG_FS
13
14#include <linux/completion.h>
15#include <linux/debugfs.h>
16#include <linux/dma-mapping.h>
17#include <linux/random.h>
18#include <linux/uaccess.h>
19#include <linux/msm_gsi.h>
20#include "gsi_reg.h"
21#include "gsi.h"
22
23#define TERR(fmt, args...) \
24 pr_err("%s:%d " fmt, __func__, __LINE__, ## args)
25#define TDBG(fmt, args...) \
26 pr_debug("%s:%d " fmt, __func__, __LINE__, ## args)
27#define PRT_STAT(fmt, args...) \
28 pr_err(fmt, ## args)
29
30static struct dentry *dent;
31static char dbg_buff[4096];
Skylar Changa3298c32017-04-20 10:25:43 -070032static void *gsi_ipc_logbuf_low;
Amir Levycdccd632016-10-30 09:36:41 +020033
34static void gsi_wq_print_dp_stats(struct work_struct *work);
35static DECLARE_DELAYED_WORK(gsi_print_dp_stats_work, gsi_wq_print_dp_stats);
36static void gsi_wq_update_dp_stats(struct work_struct *work);
37static DECLARE_DELAYED_WORK(gsi_update_dp_stats_work, gsi_wq_update_dp_stats);
38
39static ssize_t gsi_dump_evt(struct file *file,
40 const char __user *buf, size_t count, loff_t *ppos)
41{
42 u32 arg1;
43 u32 arg2;
44 unsigned long missing;
45 char *sptr, *token;
46 uint32_t val;
47 struct gsi_evt_ctx *ctx;
48 uint16_t i;
49
50 if (sizeof(dbg_buff) < count + 1)
51 return -EFAULT;
52
53 missing = copy_from_user(dbg_buff, buf, count);
54 if (missing)
55 return -EFAULT;
56
57 dbg_buff[count] = '\0';
58
59 sptr = dbg_buff;
60
61 token = strsep(&sptr, " ");
62 if (!token)
63 return -EINVAL;
64 if (kstrtou32(token, 0, &arg1))
65 return -EINVAL;
66
67 token = strsep(&sptr, " ");
68 if (!token)
69 return -EINVAL;
70 if (kstrtou32(token, 0, &arg2))
71 return -EINVAL;
72
73 TDBG("arg1=%u arg2=%u\n", arg1, arg2);
74
Amir Levy41644242016-11-03 15:38:09 +020075 if (arg1 >= gsi_ctx->max_ev) {
Amir Levycdccd632016-10-30 09:36:41 +020076 TERR("invalid evt ring id %u\n", arg1);
77 return -EFAULT;
78 }
79
80 val = gsi_readl(gsi_ctx->base +
81 GSI_EE_n_EV_CH_k_CNTXT_0_OFFS(arg1, gsi_ctx->per.ee));
82 TERR("EV%2d CTX0 0x%x\n", arg1, val);
83 val = gsi_readl(gsi_ctx->base +
84 GSI_EE_n_EV_CH_k_CNTXT_1_OFFS(arg1, gsi_ctx->per.ee));
85 TERR("EV%2d CTX1 0x%x\n", arg1, val);
86 val = gsi_readl(gsi_ctx->base +
87 GSI_EE_n_EV_CH_k_CNTXT_2_OFFS(arg1, gsi_ctx->per.ee));
88 TERR("EV%2d CTX2 0x%x\n", arg1, val);
89 val = gsi_readl(gsi_ctx->base +
90 GSI_EE_n_EV_CH_k_CNTXT_3_OFFS(arg1, gsi_ctx->per.ee));
91 TERR("EV%2d CTX3 0x%x\n", arg1, val);
92 val = gsi_readl(gsi_ctx->base +
93 GSI_EE_n_EV_CH_k_CNTXT_4_OFFS(arg1, gsi_ctx->per.ee));
94 TERR("EV%2d CTX4 0x%x\n", arg1, val);
95 val = gsi_readl(gsi_ctx->base +
96 GSI_EE_n_EV_CH_k_CNTXT_5_OFFS(arg1, gsi_ctx->per.ee));
97 TERR("EV%2d CTX5 0x%x\n", arg1, val);
98 val = gsi_readl(gsi_ctx->base +
99 GSI_EE_n_EV_CH_k_CNTXT_6_OFFS(arg1, gsi_ctx->per.ee));
100 TERR("EV%2d CTX6 0x%x\n", arg1, val);
101 val = gsi_readl(gsi_ctx->base +
102 GSI_EE_n_EV_CH_k_CNTXT_7_OFFS(arg1, gsi_ctx->per.ee));
103 TERR("EV%2d CTX7 0x%x\n", arg1, val);
104 val = gsi_readl(gsi_ctx->base +
105 GSI_EE_n_EV_CH_k_CNTXT_8_OFFS(arg1, gsi_ctx->per.ee));
106 TERR("EV%2d CTX8 0x%x\n", arg1, val);
107 val = gsi_readl(gsi_ctx->base +
108 GSI_EE_n_EV_CH_k_CNTXT_9_OFFS(arg1, gsi_ctx->per.ee));
109 TERR("EV%2d CTX9 0x%x\n", arg1, val);
110 val = gsi_readl(gsi_ctx->base +
111 GSI_EE_n_EV_CH_k_CNTXT_10_OFFS(arg1, gsi_ctx->per.ee));
112 TERR("EV%2d CTX10 0x%x\n", arg1, val);
113 val = gsi_readl(gsi_ctx->base +
114 GSI_EE_n_EV_CH_k_CNTXT_11_OFFS(arg1, gsi_ctx->per.ee));
115 TERR("EV%2d CTX11 0x%x\n", arg1, val);
116 val = gsi_readl(gsi_ctx->base +
117 GSI_EE_n_EV_CH_k_CNTXT_12_OFFS(arg1, gsi_ctx->per.ee));
118 TERR("EV%2d CTX12 0x%x\n", arg1, val);
119 val = gsi_readl(gsi_ctx->base +
120 GSI_EE_n_EV_CH_k_CNTXT_13_OFFS(arg1, gsi_ctx->per.ee));
121 TERR("EV%2d CTX13 0x%x\n", arg1, val);
122 val = gsi_readl(gsi_ctx->base +
123 GSI_EE_n_EV_CH_k_SCRATCH_0_OFFS(arg1, gsi_ctx->per.ee));
124 TERR("EV%2d SCR0 0x%x\n", arg1, val);
125 val = gsi_readl(gsi_ctx->base +
126 GSI_EE_n_EV_CH_k_SCRATCH_1_OFFS(arg1, gsi_ctx->per.ee));
127 TERR("EV%2d SCR1 0x%x\n", arg1, val);
128
129 if (arg2) {
130 ctx = &gsi_ctx->evtr[arg1];
131
132 if (ctx->props.ring_base_vaddr) {
133 for (i = 0; i < ctx->props.ring_len / 16; i++)
134 TERR("EV%2d (0x%08llx) %08x %08x %08x %08x\n",
135 arg1, ctx->props.ring_base_addr + i * 16,
136 *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
137 i * 16 + 0),
138 *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
139 i * 16 + 4),
140 *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
141 i * 16 + 8),
142 *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
143 i * 16 + 12));
144 } else {
145 TERR("No VA supplied for event ring id %u\n", arg1);
146 }
147 }
148
149 return count;
150}
151
152static ssize_t gsi_dump_ch(struct file *file,
153 const char __user *buf, size_t count, loff_t *ppos)
154{
155 u32 arg1;
156 u32 arg2;
157 unsigned long missing;
158 char *sptr, *token;
159 uint32_t val;
160 struct gsi_chan_ctx *ctx;
161 uint16_t i;
162
163 if (sizeof(dbg_buff) < count + 1)
164 return -EFAULT;
165
166 missing = copy_from_user(dbg_buff, buf, count);
167 if (missing)
168 return -EFAULT;
169
170 dbg_buff[count] = '\0';
171
172 sptr = dbg_buff;
173
174 token = strsep(&sptr, " ");
175 if (!token)
176 return -EINVAL;
177 if (kstrtou32(token, 0, &arg1))
178 return -EINVAL;
179
180 token = strsep(&sptr, " ");
181 if (!token)
182 return -EINVAL;
183 if (kstrtou32(token, 0, &arg2))
184 return -EINVAL;
185
186 TDBG("arg1=%u arg2=%u\n", arg1, arg2);
187
Amir Levy41644242016-11-03 15:38:09 +0200188 if (arg1 >= gsi_ctx->max_ch) {
Amir Levycdccd632016-10-30 09:36:41 +0200189 TERR("invalid chan id %u\n", arg1);
190 return -EFAULT;
191 }
192
193 val = gsi_readl(gsi_ctx->base +
194 GSI_EE_n_GSI_CH_k_CNTXT_0_OFFS(arg1, gsi_ctx->per.ee));
195 TERR("CH%2d CTX0 0x%x\n", arg1, val);
196 val = gsi_readl(gsi_ctx->base +
197 GSI_EE_n_GSI_CH_k_CNTXT_1_OFFS(arg1, gsi_ctx->per.ee));
198 TERR("CH%2d CTX1 0x%x\n", arg1, val);
199 val = gsi_readl(gsi_ctx->base +
200 GSI_EE_n_GSI_CH_k_CNTXT_2_OFFS(arg1, gsi_ctx->per.ee));
201 TERR("CH%2d CTX2 0x%x\n", arg1, val);
202 val = gsi_readl(gsi_ctx->base +
203 GSI_EE_n_GSI_CH_k_CNTXT_3_OFFS(arg1, gsi_ctx->per.ee));
204 TERR("CH%2d CTX3 0x%x\n", arg1, val);
205 val = gsi_readl(gsi_ctx->base +
206 GSI_EE_n_GSI_CH_k_CNTXT_4_OFFS(arg1, gsi_ctx->per.ee));
207 TERR("CH%2d CTX4 0x%x\n", arg1, val);
208 val = gsi_readl(gsi_ctx->base +
209 GSI_EE_n_GSI_CH_k_CNTXT_5_OFFS(arg1, gsi_ctx->per.ee));
210 TERR("CH%2d CTX5 0x%x\n", arg1, val);
211 val = gsi_readl(gsi_ctx->base +
212 GSI_EE_n_GSI_CH_k_CNTXT_6_OFFS(arg1, gsi_ctx->per.ee));
213 TERR("CH%2d CTX6 0x%x\n", arg1, val);
214 val = gsi_readl(gsi_ctx->base +
215 GSI_EE_n_GSI_CH_k_CNTXT_7_OFFS(arg1, gsi_ctx->per.ee));
216 TERR("CH%2d CTX7 0x%x\n", arg1, val);
217 val = gsi_readl(gsi_ctx->base +
218 GSI_EE_n_GSI_CH_k_RE_FETCH_READ_PTR_OFFS(arg1,
219 gsi_ctx->per.ee));
220 TERR("CH%2d REFRP 0x%x\n", arg1, val);
221 val = gsi_readl(gsi_ctx->base +
222 GSI_EE_n_GSI_CH_k_RE_FETCH_WRITE_PTR_OFFS(arg1,
223 gsi_ctx->per.ee));
224 TERR("CH%2d REFWP 0x%x\n", arg1, val);
225 val = gsi_readl(gsi_ctx->base +
226 GSI_EE_n_GSI_CH_k_QOS_OFFS(arg1, gsi_ctx->per.ee));
227 TERR("CH%2d QOS 0x%x\n", arg1, val);
228 val = gsi_readl(gsi_ctx->base +
229 GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(arg1, gsi_ctx->per.ee));
230 TERR("CH%2d SCR0 0x%x\n", arg1, val);
231 val = gsi_readl(gsi_ctx->base +
232 GSI_EE_n_GSI_CH_k_SCRATCH_1_OFFS(arg1, gsi_ctx->per.ee));
233 TERR("CH%2d SCR1 0x%x\n", arg1, val);
234 val = gsi_readl(gsi_ctx->base +
235 GSI_EE_n_GSI_CH_k_SCRATCH_2_OFFS(arg1, gsi_ctx->per.ee));
236 TERR("CH%2d SCR2 0x%x\n", arg1, val);
237 val = gsi_readl(gsi_ctx->base +
238 GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(arg1, gsi_ctx->per.ee));
239 TERR("CH%2d SCR3 0x%x\n", arg1, val);
240
241 if (arg2) {
242 ctx = &gsi_ctx->chan[arg1];
243
244 if (ctx->props.ring_base_vaddr) {
245 for (i = 0; i < ctx->props.ring_len / 16; i++)
246 TERR("CH%2d (0x%08llx) %08x %08x %08x %08x\n",
247 arg1, ctx->props.ring_base_addr + i * 16,
248 *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
249 i * 16 + 0),
250 *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
251 i * 16 + 4),
252 *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
253 i * 16 + 8),
254 *(u32 *)((u8 *)ctx->props.ring_base_vaddr +
255 i * 16 + 12));
256 } else {
257 TERR("No VA supplied for chan id %u\n", arg1);
258 }
259 }
260
261 return count;
262}
263
264static ssize_t gsi_dump_ee(struct file *file,
265 const char __user *buf, size_t count, loff_t *ppos)
266{
267 uint32_t val;
268
269 val = gsi_readl(gsi_ctx->base +
270 GSI_GSI_MANAGER_EE_QOS_n_OFFS(gsi_ctx->per.ee));
271 TERR("EE%2d QOS 0x%x\n", gsi_ctx->per.ee, val);
272 val = gsi_readl(gsi_ctx->base +
273 GSI_EE_n_GSI_STATUS_OFFS(gsi_ctx->per.ee));
274 TERR("EE%2d STATUS 0x%x\n", gsi_ctx->per.ee, val);
Amir Levy41644242016-11-03 15:38:09 +0200275 if (gsi_ctx->per.ver == GSI_VER_1_0) {
276 val = gsi_readl(gsi_ctx->base +
277 GSI_V1_0_EE_n_GSI_HW_PARAM_OFFS(gsi_ctx->per.ee));
278 TERR("EE%2d HW_PARAM 0x%x\n", gsi_ctx->per.ee, val);
279 } else if (gsi_ctx->per.ver == GSI_VER_1_2) {
280 val = gsi_readl(gsi_ctx->base +
281 GSI_V1_2_EE_n_GSI_HW_PARAM_0_OFFS(gsi_ctx->per.ee));
282 TERR("EE%2d HW_PARAM_0 0x%x\n", gsi_ctx->per.ee, val);
283 val = gsi_readl(gsi_ctx->base +
284 GSI_V1_2_EE_n_GSI_HW_PARAM_1_OFFS(gsi_ctx->per.ee));
285 TERR("EE%2d HW_PARAM_1 0x%x\n", gsi_ctx->per.ee, val);
286 } else if (gsi_ctx->per.ver == GSI_VER_1_3) {
287 val = gsi_readl(gsi_ctx->base +
288 GSI_V1_3_EE_n_GSI_HW_PARAM_0_OFFS(gsi_ctx->per.ee));
289 TERR("EE%2d HW_PARAM_0 0x%x\n", gsi_ctx->per.ee, val);
290 val = gsi_readl(gsi_ctx->base +
291 GSI_V1_3_EE_n_GSI_HW_PARAM_1_OFFS(gsi_ctx->per.ee));
292 TERR("EE%2d HW_PARAM_1 0x%x\n", gsi_ctx->per.ee, val);
293 val = gsi_readl(gsi_ctx->base +
294 GSI_V1_3_EE_n_GSI_HW_PARAM_2_OFFS(gsi_ctx->per.ee));
295 TERR("EE%2d HW_PARAM_2 0x%x\n", gsi_ctx->per.ee, val);
Michael Adisumarta8522e212017-05-15 11:59:42 -0700296 } else if (gsi_ctx->per.ver == GSI_VER_2_0) {
297 val = gsi_readl(gsi_ctx->base +
298 GSI_V1_3_EE_n_GSI_HW_PARAM_0_OFFS(gsi_ctx->per.ee));
299 TERR("EE%2d HW_PARAM_0 0x%x\n", gsi_ctx->per.ee, val);
300 val = gsi_readl(gsi_ctx->base +
301 GSI_V1_3_EE_n_GSI_HW_PARAM_1_OFFS(gsi_ctx->per.ee));
302 TERR("EE%2d HW_PARAM_1 0x%x\n", gsi_ctx->per.ee, val);
303 val = gsi_readl(gsi_ctx->base +
304 GSI_V2_0_EE_n_GSI_HW_PARAM_2_OFFS(gsi_ctx->per.ee));
305 TERR("EE%2d HW_PARAM_2 0x%x\n", gsi_ctx->per.ee, val);
Amir Levy41644242016-11-03 15:38:09 +0200306 } else {
307 WARN_ON(1);
308 }
Amir Levycdccd632016-10-30 09:36:41 +0200309 val = gsi_readl(gsi_ctx->base +
310 GSI_EE_n_GSI_SW_VERSION_OFFS(gsi_ctx->per.ee));
311 TERR("EE%2d SW_VERSION 0x%x\n", gsi_ctx->per.ee, val);
312 val = gsi_readl(gsi_ctx->base +
313 GSI_EE_n_GSI_MCS_CODE_VER_OFFS(gsi_ctx->per.ee));
314 TERR("EE%2d MCS_CODE_VER 0x%x\n", gsi_ctx->per.ee, val);
315 val = gsi_readl(gsi_ctx->base +
316 GSI_EE_n_CNTXT_TYPE_IRQ_MSK_OFFS(gsi_ctx->per.ee));
317 TERR("EE%2d TYPE_IRQ_MSK 0x%x\n", gsi_ctx->per.ee, val);
318 val = gsi_readl(gsi_ctx->base +
319 GSI_EE_n_CNTXT_SRC_GSI_CH_IRQ_MSK_OFFS(gsi_ctx->per.ee));
320 TERR("EE%2d CH_IRQ_MSK 0x%x\n", gsi_ctx->per.ee, val);
321 val = gsi_readl(gsi_ctx->base +
322 GSI_EE_n_CNTXT_SRC_EV_CH_IRQ_MSK_OFFS(gsi_ctx->per.ee));
323 TERR("EE%2d EV_IRQ_MSK 0x%x\n", gsi_ctx->per.ee, val);
324 val = gsi_readl(gsi_ctx->base +
325 GSI_EE_n_CNTXT_SRC_IEOB_IRQ_MSK_OFFS(gsi_ctx->per.ee));
326 TERR("EE%2d IEOB_IRQ_MSK 0x%x\n", gsi_ctx->per.ee, val);
327 val = gsi_readl(gsi_ctx->base +
328 GSI_EE_n_CNTXT_GLOB_IRQ_EN_OFFS(gsi_ctx->per.ee));
329 TERR("EE%2d GLOB_IRQ_EN 0x%x\n", gsi_ctx->per.ee, val);
330 val = gsi_readl(gsi_ctx->base +
331 GSI_EE_n_CNTXT_GSI_IRQ_EN_OFFS(gsi_ctx->per.ee));
332 TERR("EE%2d GSI_IRQ_EN 0x%x\n", gsi_ctx->per.ee, val);
333 val = gsi_readl(gsi_ctx->base +
334 GSI_EE_n_CNTXT_INTSET_OFFS(gsi_ctx->per.ee));
335 TERR("EE%2d INTSET 0x%x\n", gsi_ctx->per.ee, val);
336 val = gsi_readl(gsi_ctx->base +
337 GSI_EE_n_CNTXT_MSI_BASE_LSB_OFFS(gsi_ctx->per.ee));
338 TERR("EE%2d MSI_BASE_LSB 0x%x\n", gsi_ctx->per.ee, val);
339 val = gsi_readl(gsi_ctx->base +
340 GSI_EE_n_CNTXT_MSI_BASE_MSB_OFFS(gsi_ctx->per.ee));
341 TERR("EE%2d MSI_BASE_MSB 0x%x\n", gsi_ctx->per.ee, val);
342 val = gsi_readl(gsi_ctx->base +
343 GSI_EE_n_CNTXT_INT_VEC_OFFS(gsi_ctx->per.ee));
344 TERR("EE%2d INT_VEC 0x%x\n", gsi_ctx->per.ee, val);
345 val = gsi_readl(gsi_ctx->base +
346 GSI_EE_n_CNTXT_SCRATCH_0_OFFS(gsi_ctx->per.ee));
347 TERR("EE%2d SCR0 0x%x\n", gsi_ctx->per.ee, val);
348 val = gsi_readl(gsi_ctx->base +
349 GSI_EE_n_CNTXT_SCRATCH_1_OFFS(gsi_ctx->per.ee));
350 TERR("EE%2d SCR1 0x%x\n", gsi_ctx->per.ee, val);
351
352 return count;
353}
354
355static ssize_t gsi_dump_map(struct file *file,
356 const char __user *buf, size_t count, loff_t *ppos)
357{
358 struct gsi_chan_ctx *ctx;
359 uint32_t val1;
360 uint32_t val2;
361 int i;
362
363 TERR("EVT bitmap 0x%lx\n", gsi_ctx->evt_bmap);
Amir Levy41644242016-11-03 15:38:09 +0200364 for (i = 0; i < gsi_ctx->max_ch; i++) {
Amir Levycdccd632016-10-30 09:36:41 +0200365 ctx = &gsi_ctx->chan[i];
366
367 if (ctx->allocated) {
368 TERR("VIRT CH%2d -> VIRT EV%2d\n", ctx->props.ch_id,
369 ctx->evtr ? ctx->evtr->id : GSI_NO_EVT_ERINDEX);
370 val1 = gsi_readl(gsi_ctx->base +
371 GSI_GSI_DEBUG_EE_n_CH_k_VP_TABLE_OFFS(i,
372 gsi_ctx->per.ee));
373 TERR("VIRT CH%2d -> PHYS CH%2d\n", ctx->props.ch_id,
374 val1 &
375 GSI_GSI_DEBUG_EE_n_CH_k_VP_TABLE_PHY_CH_BMSK);
376 if (ctx->evtr) {
377 val2 = gsi_readl(gsi_ctx->base +
378 GSI_GSI_DEBUG_EE_n_EV_k_VP_TABLE_OFFS(
379 ctx->evtr->id, gsi_ctx->per.ee));
380 TERR("VRT EV%2d -> PHYS EV%2d\n", ctx->evtr->id,
381 val2 &
382 GSI_GSI_DEBUG_EE_n_CH_k_VP_TABLE_PHY_CH_BMSK);
383 }
384 TERR("\n");
385 }
386 }
387
388 return count;
389}
390
391static void gsi_dump_ch_stats(struct gsi_chan_ctx *ctx)
392{
393 if (!ctx->allocated)
394 return;
395
396 PRT_STAT("CH%2d:\n", ctx->props.ch_id);
397 PRT_STAT("queued=%lu compl=%lu\n",
398 ctx->stats.queued,
399 ctx->stats.completed);
400 PRT_STAT("cb->poll=%lu poll->cb=%lu\n",
401 ctx->stats.callback_to_poll,
402 ctx->stats.poll_to_callback);
403 PRT_STAT("invalid_tre_error=%lu\n",
404 ctx->stats.invalid_tre_error);
405 PRT_STAT("poll_ok=%lu poll_empty=%lu\n",
406 ctx->stats.poll_ok, ctx->stats.poll_empty);
407 if (ctx->evtr)
408 PRT_STAT("compl_evt=%lu\n",
409 ctx->evtr->stats.completed);
410
411 PRT_STAT("ch_below_lo=%lu\n", ctx->stats.dp.ch_below_lo);
412 PRT_STAT("ch_below_hi=%lu\n", ctx->stats.dp.ch_below_hi);
413 PRT_STAT("ch_above_hi=%lu\n", ctx->stats.dp.ch_above_hi);
414 PRT_STAT("time_empty=%lums\n", ctx->stats.dp.empty_time);
415 PRT_STAT("\n");
416}
417
418static ssize_t gsi_dump_stats(struct file *file,
419 const char __user *buf, size_t count, loff_t *ppos)
420{
421 int ch_id;
422 int min, max;
423
424 if (sizeof(dbg_buff) < count + 1)
425 goto error;
426
427 if (copy_from_user(dbg_buff, buf, count))
428 goto error;
429
430 dbg_buff[count] = '\0';
431
432 if (kstrtos32(dbg_buff, 0, &ch_id))
433 goto error;
434
435 if (ch_id == -1) {
436 min = 0;
Amir Levy41644242016-11-03 15:38:09 +0200437 max = gsi_ctx->max_ch;
438 } else if (ch_id < 0 || ch_id >= gsi_ctx->max_ch ||
Amir Levycdccd632016-10-30 09:36:41 +0200439 !gsi_ctx->chan[ch_id].allocated) {
440 goto error;
441 } else {
442 min = ch_id;
443 max = ch_id + 1;
444 }
445
446 for (ch_id = min; ch_id < max; ch_id++)
447 gsi_dump_ch_stats(&gsi_ctx->chan[ch_id]);
448
449 return count;
450error:
451 TERR("Usage: echo ch_id > stats. Use -1 for all\n");
452 return -EFAULT;
453}
454
455static int gsi_dbg_create_stats_wq(void)
456{
457 gsi_ctx->dp_stat_wq =
458 create_singlethread_workqueue("gsi_stat");
459 if (!gsi_ctx->dp_stat_wq) {
460 TERR("failed create workqueue\n");
461 return -ENOMEM;
462 }
463
464 return 0;
465}
466
467static void gsi_dbg_destroy_stats_wq(void)
468{
469 cancel_delayed_work_sync(&gsi_update_dp_stats_work);
470 cancel_delayed_work_sync(&gsi_print_dp_stats_work);
471 flush_workqueue(gsi_ctx->dp_stat_wq);
472 destroy_workqueue(gsi_ctx->dp_stat_wq);
473 gsi_ctx->dp_stat_wq = NULL;
474}
475
476static ssize_t gsi_enable_dp_stats(struct file *file,
477 const char __user *buf, size_t count, loff_t *ppos)
478{
479 int ch_id;
480 bool enable;
481 int ret;
482
483 if (sizeof(dbg_buff) < count + 1)
484 goto error;
485
486 if (copy_from_user(dbg_buff, buf, count))
487 goto error;
488
489 dbg_buff[count] = '\0';
490
491 if (dbg_buff[0] != '+' && dbg_buff[0] != '-')
492 goto error;
493
494 enable = (dbg_buff[0] == '+');
495
496 if (kstrtos32(dbg_buff + 1, 0, &ch_id))
497 goto error;
498
Amir Levy41644242016-11-03 15:38:09 +0200499 if (ch_id < 0 || ch_id >= gsi_ctx->max_ch ||
Amir Levycdccd632016-10-30 09:36:41 +0200500 !gsi_ctx->chan[ch_id].allocated) {
501 goto error;
502 }
503
Amir Levycdccd632016-10-30 09:36:41 +0200504 if (gsi_ctx->chan[ch_id].enable_dp_stats == enable) {
505 TERR("ch_%d: already enabled/disabled\n", ch_id);
506 return -EFAULT;
507 }
508 gsi_ctx->chan[ch_id].enable_dp_stats = enable;
509
510 if (enable)
511 gsi_ctx->num_ch_dp_stats++;
512 else
513 gsi_ctx->num_ch_dp_stats--;
514
515 if (enable) {
516 if (gsi_ctx->num_ch_dp_stats == 1) {
517 ret = gsi_dbg_create_stats_wq();
518 if (ret)
519 return ret;
520 }
521 cancel_delayed_work_sync(&gsi_update_dp_stats_work);
522 queue_delayed_work(gsi_ctx->dp_stat_wq,
523 &gsi_update_dp_stats_work, msecs_to_jiffies(10));
524 } else if (!enable && gsi_ctx->num_ch_dp_stats == 0) {
525 gsi_dbg_destroy_stats_wq();
526 }
527
528 return count;
529error:
530 TERR("Usage: echo [+-]ch_id > enable_dp_stats\n");
531 return -EFAULT;
532}
533
534static ssize_t gsi_set_max_elem_dp_stats(struct file *file,
535 const char __user *buf, size_t count, loff_t *ppos)
536{
537 u32 ch_id;
538 u32 max_elem;
539 unsigned long missing;
540 char *sptr, *token;
541
542
543 if (sizeof(dbg_buff) < count + 1)
544 goto error;
545
546 missing = copy_from_user(dbg_buff, buf, count);
547 if (missing)
548 goto error;
549
550 dbg_buff[count] = '\0';
551
552 sptr = dbg_buff;
553
554 token = strsep(&sptr, " ");
555 if (!token) {
556 TERR("\n");
557 goto error;
558 }
559
560 if (kstrtou32(token, 0, &ch_id)) {
561 TERR("\n");
562 goto error;
563 }
564
565 token = strsep(&sptr, " ");
566 if (!token) {
567 /* get */
568 if (kstrtou32(dbg_buff, 0, &ch_id))
569 goto error;
Amir Levy41644242016-11-03 15:38:09 +0200570 if (ch_id >= gsi_ctx->max_ch)
Amir Levycdccd632016-10-30 09:36:41 +0200571 goto error;
572 PRT_STAT("ch %d: max_re_expected=%d\n", ch_id,
573 gsi_ctx->chan[ch_id].props.max_re_expected);
574 return count;
575 }
576 if (kstrtou32(token, 0, &max_elem)) {
577 TERR("\n");
578 goto error;
579 }
580
581 TDBG("ch_id=%u max_elem=%u\n", ch_id, max_elem);
582
Amir Levy41644242016-11-03 15:38:09 +0200583 if (ch_id >= gsi_ctx->max_ch) {
Amir Levycdccd632016-10-30 09:36:41 +0200584 TERR("invalid chan id %u\n", ch_id);
585 goto error;
586 }
587
588 gsi_ctx->chan[ch_id].props.max_re_expected = max_elem;
589
590 return count;
591
592error:
593 TERR("Usage: (set) echo <ch_id> <max_elem> > max_elem_dp_stats\n");
594 TERR("Usage: (get) echo <ch_id> > max_elem_dp_stats\n");
595 return -EFAULT;
596}
597
598static void gsi_wq_print_dp_stats(struct work_struct *work)
599{
600 int ch_id;
601
Amir Levy41644242016-11-03 15:38:09 +0200602 for (ch_id = 0; ch_id < gsi_ctx->max_ch; ch_id++) {
Amir Levycdccd632016-10-30 09:36:41 +0200603 if (gsi_ctx->chan[ch_id].print_dp_stats)
604 gsi_dump_ch_stats(&gsi_ctx->chan[ch_id]);
605 }
606
607 queue_delayed_work(gsi_ctx->dp_stat_wq, &gsi_print_dp_stats_work,
608 msecs_to_jiffies(1000));
609}
610
611static void gsi_dbg_update_ch_dp_stats(struct gsi_chan_ctx *ctx)
612{
613 uint16_t start_hw;
614 uint16_t end_hw;
615 uint64_t rp_hw;
616 uint64_t wp_hw;
617 int ee = gsi_ctx->per.ee;
618 uint16_t used_hw;
619
620 rp_hw = gsi_readl(gsi_ctx->base +
621 GSI_EE_n_GSI_CH_k_CNTXT_4_OFFS(ctx->props.ch_id, ee));
622 rp_hw |= ((uint64_t)gsi_readl(gsi_ctx->base +
623 GSI_EE_n_GSI_CH_k_CNTXT_5_OFFS(ctx->props.ch_id, ee)))
624 << 32;
625
626 wp_hw = gsi_readl(gsi_ctx->base +
627 GSI_EE_n_GSI_CH_k_CNTXT_6_OFFS(ctx->props.ch_id, ee));
628 wp_hw |= ((uint64_t)gsi_readl(gsi_ctx->base +
629 GSI_EE_n_GSI_CH_k_CNTXT_7_OFFS(ctx->props.ch_id, ee)))
630 << 32;
631
632 start_hw = gsi_find_idx_from_addr(&ctx->ring, rp_hw);
633 end_hw = gsi_find_idx_from_addr(&ctx->ring, wp_hw);
634
635 if (end_hw >= start_hw)
636 used_hw = end_hw - start_hw;
637 else
638 used_hw = ctx->ring.max_num_elem + 1 - (start_hw - end_hw);
639
Skylar Chang8568eb92017-03-21 17:18:51 -0700640 TDBG("ch %d used %d\n", ctx->props.ch_id, used_hw);
Amir Levycdccd632016-10-30 09:36:41 +0200641 gsi_update_ch_dp_stats(ctx, used_hw);
642}
643
644static void gsi_wq_update_dp_stats(struct work_struct *work)
645{
646 int ch_id;
647
Amir Levy41644242016-11-03 15:38:09 +0200648 for (ch_id = 0; ch_id < gsi_ctx->max_ch; ch_id++) {
Amir Levycdccd632016-10-30 09:36:41 +0200649 if (gsi_ctx->chan[ch_id].allocated &&
Amir Levycdccd632016-10-30 09:36:41 +0200650 gsi_ctx->chan[ch_id].enable_dp_stats)
651 gsi_dbg_update_ch_dp_stats(&gsi_ctx->chan[ch_id]);
652 }
653
654 queue_delayed_work(gsi_ctx->dp_stat_wq, &gsi_update_dp_stats_work,
655 msecs_to_jiffies(10));
656}
657
658
659static ssize_t gsi_rst_stats(struct file *file,
660 const char __user *buf, size_t count, loff_t *ppos)
661{
662 int ch_id;
663 int min, max;
664
665 if (sizeof(dbg_buff) < count + 1)
666 goto error;
667
668 if (copy_from_user(dbg_buff, buf, count))
669 goto error;
670
671 dbg_buff[count] = '\0';
672
673 if (kstrtos32(dbg_buff, 0, &ch_id))
674 goto error;
675
676 if (ch_id == -1) {
677 min = 0;
Amir Levy41644242016-11-03 15:38:09 +0200678 max = gsi_ctx->max_ch;
679 } else if (ch_id < 0 || ch_id >= gsi_ctx->max_ch ||
Amir Levycdccd632016-10-30 09:36:41 +0200680 !gsi_ctx->chan[ch_id].allocated) {
681 goto error;
682 } else {
683 min = ch_id;
684 max = ch_id + 1;
685 }
686
687 for (ch_id = min; ch_id < max; ch_id++)
688 memset(&gsi_ctx->chan[ch_id].stats, 0,
689 sizeof(gsi_ctx->chan[ch_id].stats));
690
691 return count;
692error:
693 TERR("Usage: echo ch_id > rst_stats. Use -1 for all\n");
694 return -EFAULT;
695}
696
697static ssize_t gsi_print_dp_stats(struct file *file,
698 const char __user *buf, size_t count, loff_t *ppos)
699{
700 int ch_id;
701 bool enable;
702 int ret;
703
704 if (sizeof(dbg_buff) < count + 1)
705 goto error;
706
707 if (copy_from_user(dbg_buff, buf, count))
708 goto error;
709
710 dbg_buff[count] = '\0';
711
712 if (dbg_buff[0] != '+' && dbg_buff[0] != '-')
713 goto error;
714
715 enable = (dbg_buff[0] == '+');
716
717 if (kstrtos32(dbg_buff + 1, 0, &ch_id))
718 goto error;
719
Amir Levy41644242016-11-03 15:38:09 +0200720 if (ch_id < 0 || ch_id >= gsi_ctx->max_ch ||
Amir Levycdccd632016-10-30 09:36:41 +0200721 !gsi_ctx->chan[ch_id].allocated) {
722 goto error;
723 }
724
725 if (gsi_ctx->chan[ch_id].print_dp_stats == enable) {
726 TERR("ch_%d: already enabled/disabled\n", ch_id);
727 return -EFAULT;
728 }
729 gsi_ctx->chan[ch_id].print_dp_stats = enable;
730
731 if (enable)
732 gsi_ctx->num_ch_dp_stats++;
733 else
734 gsi_ctx->num_ch_dp_stats--;
735
736 if (enable) {
737 if (gsi_ctx->num_ch_dp_stats == 1) {
738 ret = gsi_dbg_create_stats_wq();
739 if (ret)
740 return ret;
741 }
742 cancel_delayed_work_sync(&gsi_print_dp_stats_work);
743 queue_delayed_work(gsi_ctx->dp_stat_wq,
744 &gsi_print_dp_stats_work, msecs_to_jiffies(10));
745 } else if (!enable && gsi_ctx->num_ch_dp_stats == 0) {
746 gsi_dbg_destroy_stats_wq();
747 }
748
749 return count;
750error:
751 TERR("Usage: echo [+-]ch_id > print_dp_stats\n");
752 return -EFAULT;
753}
754
Skylar Chang4d6a8fe2017-03-16 16:55:57 -0700755static ssize_t gsi_enable_ipc_low(struct file *file,
756 const char __user *ubuf, size_t count, loff_t *ppos)
757{
758 unsigned long missing;
759 s8 option = 0;
760
761 if (sizeof(dbg_buff) < count + 1)
762 return -EFAULT;
763
764 missing = copy_from_user(dbg_buff, ubuf, count);
765 if (missing)
766 return -EFAULT;
767
768 dbg_buff[count] = '\0';
769 if (kstrtos8(dbg_buff, 0, &option))
770 return -EFAULT;
771
Skylar Changa3298c32017-04-20 10:25:43 -0700772 mutex_lock(&gsi_ctx->mlock);
Skylar Chang4d6a8fe2017-03-16 16:55:57 -0700773 if (option) {
Skylar Changa3298c32017-04-20 10:25:43 -0700774 if (!gsi_ipc_logbuf_low) {
775 gsi_ipc_logbuf_low =
Skylar Chang4d6a8fe2017-03-16 16:55:57 -0700776 ipc_log_context_create(GSI_IPC_LOG_PAGES,
777 "gsi_low", 0);
Skylar Changa3298c32017-04-20 10:25:43 -0700778 if (gsi_ipc_logbuf_low == NULL)
779 TERR("failed to get ipc_logbuf_low\n");
Skylar Chang4d6a8fe2017-03-16 16:55:57 -0700780 }
Skylar Changa3298c32017-04-20 10:25:43 -0700781 gsi_ctx->ipc_logbuf_low = gsi_ipc_logbuf_low;
Skylar Chang4d6a8fe2017-03-16 16:55:57 -0700782 } else {
Skylar Chang4d6a8fe2017-03-16 16:55:57 -0700783 gsi_ctx->ipc_logbuf_low = NULL;
784 }
Skylar Changa3298c32017-04-20 10:25:43 -0700785 mutex_unlock(&gsi_ctx->mlock);
Skylar Chang4d6a8fe2017-03-16 16:55:57 -0700786
787 return count;
788}
789
790
791
Amir Levycdccd632016-10-30 09:36:41 +0200792const struct file_operations gsi_ev_dump_ops = {
793 .write = gsi_dump_evt,
794};
795
796const struct file_operations gsi_ch_dump_ops = {
797 .write = gsi_dump_ch,
798};
799
800const struct file_operations gsi_ee_dump_ops = {
801 .write = gsi_dump_ee,
802};
803
804const struct file_operations gsi_map_ops = {
805 .write = gsi_dump_map,
806};
807
808const struct file_operations gsi_stats_ops = {
809 .write = gsi_dump_stats,
810};
811
812const struct file_operations gsi_enable_dp_stats_ops = {
813 .write = gsi_enable_dp_stats,
814};
815
816const struct file_operations gsi_max_elem_dp_stats_ops = {
817 .write = gsi_set_max_elem_dp_stats,
818};
819
820const struct file_operations gsi_rst_stats_ops = {
821 .write = gsi_rst_stats,
822};
823
824const struct file_operations gsi_print_dp_stats_ops = {
825 .write = gsi_print_dp_stats,
826};
827
Skylar Chang4d6a8fe2017-03-16 16:55:57 -0700828const struct file_operations gsi_ipc_low_ops = {
829 .write = gsi_enable_ipc_low,
830};
831
Amir Levycdccd632016-10-30 09:36:41 +0200832void gsi_debugfs_init(void)
833{
834 static struct dentry *dfile;
835 const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH;
836 const mode_t write_only_mode = S_IWUSR | S_IWGRP;
837
838 dent = debugfs_create_dir("gsi", 0);
839 if (IS_ERR(dent)) {
840 TERR("fail to create dir\n");
841 return;
842 }
843
844 dfile = debugfs_create_file("ev_dump", write_only_mode,
845 dent, 0, &gsi_ev_dump_ops);
846 if (!dfile || IS_ERR(dfile)) {
847 TERR("fail to create ev_dump file\n");
848 goto fail;
849 }
850
851 dfile = debugfs_create_file("ch_dump", write_only_mode,
852 dent, 0, &gsi_ch_dump_ops);
853 if (!dfile || IS_ERR(dfile)) {
854 TERR("fail to create ch_dump file\n");
855 goto fail;
856 }
857
858 dfile = debugfs_create_file("ee_dump", read_only_mode, dent,
859 0, &gsi_ee_dump_ops);
860 if (!dfile || IS_ERR(dfile)) {
861 TERR("fail to create ee_dump file\n");
862 goto fail;
863 }
864
865 dfile = debugfs_create_file("map", read_only_mode, dent,
866 0, &gsi_map_ops);
867 if (!dfile || IS_ERR(dfile)) {
868 TERR("fail to create map file\n");
869 goto fail;
870 }
871
872 dfile = debugfs_create_file("stats", write_only_mode, dent,
873 0, &gsi_stats_ops);
874 if (!dfile || IS_ERR(dfile)) {
875 TERR("fail to create stats file\n");
876 goto fail;
877 }
878
879 dfile = debugfs_create_file("enable_dp_stats", write_only_mode, dent,
880 0, &gsi_enable_dp_stats_ops);
881 if (!dfile || IS_ERR(dfile)) {
882 TERR("fail to create stats file\n");
883 goto fail;
884 }
885
886 dfile = debugfs_create_file("max_elem_dp_stats", write_only_mode,
887 dent, 0, &gsi_max_elem_dp_stats_ops);
888 if (!dfile || IS_ERR(dfile)) {
889 TERR("fail to create stats file\n");
890 goto fail;
891 }
892
893 dfile = debugfs_create_file("rst_stats", write_only_mode,
894 dent, 0, &gsi_rst_stats_ops);
895 if (!dfile || IS_ERR(dfile)) {
896 TERR("fail to create stats file\n");
897 goto fail;
898 }
899
900 dfile = debugfs_create_file("print_dp_stats",
901 write_only_mode, dent, 0, &gsi_print_dp_stats_ops);
902 if (!dfile || IS_ERR(dfile)) {
903 TERR("fail to create stats file\n");
904 goto fail;
905 }
906
Skylar Chang4d6a8fe2017-03-16 16:55:57 -0700907 dfile = debugfs_create_file("ipc_low", write_only_mode,
908 dent, 0, &gsi_ipc_low_ops);
909 if (!dfile || IS_ERR(dfile)) {
910 TERR("could not create ipc_low\n");
911 goto fail;
912 }
913
Amir Levycdccd632016-10-30 09:36:41 +0200914 return;
915fail:
916 debugfs_remove_recursive(dent);
917}
918#else
919void gsi_debugfs_init(void)
920{
921}
922#endif