blob: de1a5b5415064ce962f20bcd123b98581ff317e6 [file] [log] [blame]
Shalabh Jain10f5f432012-01-11 11:45:44 +05301/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
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
13#include <linux/slab.h>
14#include <linux/diagchar.h>
15#include <linux/platform_device.h>
Dixon Petersoncc0bea772012-04-11 20:45:37 -070016#include <linux/kmemleak.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070017#include "diagchar.h"
18#include "diagfwd.h"
19#include "diagfwd_cntl.h"
Dixon Peterson29aebee2012-04-06 12:44:08 -070020#ifdef CONFIG_DEBUG_FS
21#include <linux/debugfs.h>
22#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070023
24#define HDR_SIZ 8
25
Shalabh Jain4e1bd312012-02-16 19:33:05 -080026void diag_smd_cntl_notify(void *ctxt, unsigned event)
27{
28 int r1, r2;
29
30 if (!(driver->ch_cntl))
31 return;
32
33 switch (event) {
34 case SMD_EVENT_DATA:
35 r1 = smd_read_avail(driver->ch_cntl);
36 r2 = smd_cur_packet_size(driver->ch_cntl);
37 if (r1 > 0 && r1 == r2)
38 queue_work(driver->diag_wq,
39 &(driver->diag_read_smd_cntl_work));
40 else
41 pr_debug("diag: incomplete pkt on Modem CNTL ch\n");
42 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -080043 case SMD_EVENT_OPEN:
44 queue_work(driver->diag_cntl_wq,
45 &(driver->diag_modem_mask_update_work));
46 break;
Shalabh Jain4e1bd312012-02-16 19:33:05 -080047 }
48}
49
50void diag_smd_qdsp_cntl_notify(void *ctxt, unsigned event)
51{
52 int r1, r2;
53
54 if (!(driver->chqdsp_cntl))
55 return;
56
57 switch (event) {
58 case SMD_EVENT_DATA:
59 r1 = smd_read_avail(driver->chqdsp_cntl);
60 r2 = smd_cur_packet_size(driver->chqdsp_cntl);
61 if (r1 > 0 && r1 == r2)
62 queue_work(driver->diag_wq,
63 &(driver->diag_read_smd_qdsp_cntl_work));
64 else
65 pr_debug("diag: incomplete pkt on LPASS CNTL ch\n");
66 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -080067 case SMD_EVENT_OPEN:
68 queue_work(driver->diag_cntl_wq,
69 &(driver->diag_qdsp_mask_update_work));
70 break;
Shalabh Jain4e1bd312012-02-16 19:33:05 -080071 }
72}
73
74void diag_smd_wcnss_cntl_notify(void *ctxt, unsigned event)
75{
76 int r1, r2;
77
78 if (!(driver->ch_wcnss_cntl))
79 return;
80
81 switch (event) {
82 case SMD_EVENT_DATA:
83 r1 = smd_read_avail(driver->ch_wcnss_cntl);
84 r2 = smd_cur_packet_size(driver->ch_wcnss_cntl);
85 if (r1 > 0 && r1 == r2)
86 queue_work(driver->diag_wq,
87 &(driver->diag_read_smd_wcnss_cntl_work));
88 else
89 pr_debug("diag: incomplete pkt on WCNSS CNTL ch\n");
90 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -080091 case SMD_EVENT_OPEN:
92 queue_work(driver->diag_cntl_wq,
93 &(driver->diag_wcnss_mask_update_work));
94 break;
Shalabh Jain4e1bd312012-02-16 19:33:05 -080095 }
96}
97
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070098static void diag_smd_cntl_send_req(int proc_num)
99{
Shalabh Jaincf5f20e2011-08-22 12:29:52 -0700100 int data_len = 0, type = -1, count_bytes = 0, j, r, flag = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700101 struct bindpkt_params_per_process *pkt_params =
102 kzalloc(sizeof(struct bindpkt_params_per_process), GFP_KERNEL);
103 struct diag_ctrl_msg *msg;
104 struct cmd_code_range *range;
105 struct bindpkt_params *temp;
106 void *buf = NULL;
107 smd_channel_t *smd_ch = NULL;
108
Shalabh Jain4e1bd312012-02-16 19:33:05 -0800109 if (pkt_params == NULL) {
110 pr_alert("diag: Memory allocation failure\n");
111 return;
112 }
113
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700114 if (proc_num == MODEM_PROC) {
115 buf = driver->buf_in_cntl;
116 smd_ch = driver->ch_cntl;
117 } else if (proc_num == QDSP_PROC) {
118 buf = driver->buf_in_qdsp_cntl;
119 smd_ch = driver->chqdsp_cntl;
120 } else if (proc_num == WCNSS_PROC) {
121 buf = driver->buf_in_wcnss_cntl;
122 smd_ch = driver->ch_wcnss_cntl;
123 }
124
Shalabh Jainf89c5462011-08-23 18:46:03 -0700125 if (!smd_ch || !buf) {
126 kfree(pkt_params);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700127 return;
Shalabh Jainf89c5462011-08-23 18:46:03 -0700128 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700129
130 r = smd_read_avail(smd_ch);
131 if (r > IN_BUF_SIZE) {
132 if (r < MAX_IN_BUF_SIZE) {
133 pr_err("diag: SMD CNTL sending pkt upto %d bytes", r);
134 buf = krealloc(buf, r, GFP_KERNEL);
135 } else {
136 pr_err("diag: CNTL pkt > %d bytes", MAX_IN_BUF_SIZE);
137 kfree(pkt_params);
138 return;
139 }
140 }
141 if (buf && r > 0) {
142 smd_read(smd_ch, buf, r);
143 while (count_bytes + HDR_SIZ <= r) {
144 type = *(uint32_t *)(buf);
145 data_len = *(uint32_t *)(buf + 4);
Shalabh Jainf50076b2012-02-15 19:27:01 -0800146 if (type < DIAG_CTRL_MSG_REG ||
147 type > DIAG_CTRL_MSG_F3_MASK_V2) {
Shalabh Jain4e1bd312012-02-16 19:33:05 -0800148 pr_alert("diag: Invalid Msg type %d proc %d",
149 type, proc_num);
Shalabh Jainf50076b2012-02-15 19:27:01 -0800150 break;
151 }
152 if (data_len < 0 || data_len > r) {
Shalabh Jain4e1bd312012-02-16 19:33:05 -0800153 pr_alert("diag: Invalid data len %d proc %d",
154 data_len, proc_num);
Shalabh Jainf50076b2012-02-15 19:27:01 -0800155 break;
156 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700157 count_bytes = count_bytes+HDR_SIZ+data_len;
158 if (type == DIAG_CTRL_MSG_REG && r >= count_bytes) {
159 msg = buf+HDR_SIZ;
160 range = buf+HDR_SIZ+
161 sizeof(struct diag_ctrl_msg);
162 pkt_params->count = msg->count_entries;
163 temp = kzalloc(pkt_params->count * sizeof(struct
164 bindpkt_params), GFP_KERNEL);
Shalabh Jain4e1bd312012-02-16 19:33:05 -0800165 if (temp == NULL) {
166 pr_alert("diag: Memory alloc fail\n");
Dixon Petersonee6fb2b2012-03-16 20:26:02 -0700167 kfree(pkt_params);
Shalabh Jain4e1bd312012-02-16 19:33:05 -0800168 return;
169 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700170 for (j = 0; j < pkt_params->count; j++) {
171 temp->cmd_code = msg->cmd_code;
172 temp->subsys_id = msg->subsysid;
173 temp->client_id = proc_num;
174 temp->proc_id = proc_num;
175 temp->cmd_code_lo = range->cmd_code_lo;
176 temp->cmd_code_hi = range->cmd_code_hi;
177 range++;
178 temp++;
179 }
180 temp -= pkt_params->count;
181 pkt_params->params = temp;
Shalabh Jaincf5f20e2011-08-22 12:29:52 -0700182 flag = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700183 diagchar_ioctl(NULL, DIAG_IOCTL_COMMAND_REG,
184 (unsigned long)pkt_params);
185 kfree(temp);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700186 }
Dixon Petersone8054f02012-02-06 11:46:49 -0800187 buf = buf + HDR_SIZ + data_len;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700188 }
189 }
190 kfree(pkt_params);
Shalabh Jaincf5f20e2011-08-22 12:29:52 -0700191 if (flag) {
192 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -0800193 if (proc_num == MODEM_PROC)
194 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
195 else if (proc_num == QDSP_PROC)
196 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
197 else if (proc_num == WCNSS_PROC)
198 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Shalabh Jaincf5f20e2011-08-22 12:29:52 -0700199 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700200}
201
202void diag_read_smd_cntl_work_fn(struct work_struct *work)
203{
204 diag_smd_cntl_send_req(MODEM_PROC);
205}
206
207void diag_read_smd_qdsp_cntl_work_fn(struct work_struct *work)
208{
209 diag_smd_cntl_send_req(QDSP_PROC);
210}
211
212void diag_read_smd_wcnss_cntl_work_fn(struct work_struct *work)
213{
214 diag_smd_cntl_send_req(WCNSS_PROC);
215}
216
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700217static int diag_smd_cntl_probe(struct platform_device *pdev)
218{
219 int r = 0;
220
Shalabh Jain10f5f432012-01-11 11:45:44 +0530221 /* open control ports only on 8960 & newer targets */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700222 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700223 if (pdev->id == SMD_APPS_MODEM)
224 r = smd_open("DIAG_CNTL", &driver->ch_cntl, driver,
225 diag_smd_cntl_notify);
226 if (pdev->id == SMD_APPS_QDSP)
227 r = smd_named_open_on_edge("DIAG_CNTL", SMD_APPS_QDSP
228 , &driver->chqdsp_cntl, driver,
229 diag_smd_qdsp_cntl_notify);
230 if (pdev->id == SMD_APPS_WCNSS)
231 r = smd_named_open_on_edge("APPS_RIVA_CTRL",
232 SMD_APPS_WCNSS, &driver->ch_wcnss_cntl,
233 driver, diag_smd_wcnss_cntl_notify);
234 pr_debug("diag: open CNTL port, ID = %d,r = %d\n", pdev->id, r);
235 }
236 return 0;
237}
238
239static int diagfwd_cntl_runtime_suspend(struct device *dev)
240{
241 dev_dbg(dev, "pm_runtime: suspending...\n");
242 return 0;
243}
244
245static int diagfwd_cntl_runtime_resume(struct device *dev)
246{
247 dev_dbg(dev, "pm_runtime: resuming...\n");
248 return 0;
249}
250
251static const struct dev_pm_ops diagfwd_cntl_dev_pm_ops = {
252 .runtime_suspend = diagfwd_cntl_runtime_suspend,
253 .runtime_resume = diagfwd_cntl_runtime_resume,
254};
255
256static struct platform_driver msm_smd_ch1_cntl_driver = {
257
258 .probe = diag_smd_cntl_probe,
259 .driver = {
260 .name = "DIAG_CNTL",
261 .owner = THIS_MODULE,
262 .pm = &diagfwd_cntl_dev_pm_ops,
263 },
264};
265
266static struct platform_driver diag_smd_lite_cntl_driver = {
267
268 .probe = diag_smd_cntl_probe,
269 .driver = {
270 .name = "APPS_RIVA_CTRL",
271 .owner = THIS_MODULE,
272 .pm = &diagfwd_cntl_dev_pm_ops,
273 },
274};
275
276void diagfwd_cntl_init(void)
277{
Shalabh Jain3d29fc32012-02-09 17:15:59 -0800278 driver->polling_reg_flag = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800279 driver->diag_cntl_wq = create_singlethread_workqueue("diag_cntl_wq");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700280 if (driver->buf_in_cntl == NULL) {
281 driver->buf_in_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
282 if (driver->buf_in_cntl == NULL)
283 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -0700284 kmemleak_not_leak(driver->buf_in_cntl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700285 }
286 if (driver->buf_in_qdsp_cntl == NULL) {
287 driver->buf_in_qdsp_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
288 if (driver->buf_in_qdsp_cntl == NULL)
289 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -0700290 kmemleak_not_leak(driver->buf_in_qdsp_cntl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700291 }
292 if (driver->buf_in_wcnss_cntl == NULL) {
293 driver->buf_in_wcnss_cntl = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
294 if (driver->buf_in_wcnss_cntl == NULL)
295 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -0700296 kmemleak_not_leak(driver->buf_in_wcnss_cntl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700297 }
298 platform_driver_register(&msm_smd_ch1_cntl_driver);
299 platform_driver_register(&diag_smd_lite_cntl_driver);
300
301 return;
302err:
303 pr_err("diag: Could not initialize diag buffers");
304 kfree(driver->buf_in_cntl);
305 kfree(driver->buf_in_qdsp_cntl);
306 kfree(driver->buf_in_wcnss_cntl);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800307 if (driver->diag_cntl_wq)
308 destroy_workqueue(driver->diag_cntl_wq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700309}
310
311void diagfwd_cntl_exit(void)
312{
313 smd_close(driver->ch_cntl);
314 smd_close(driver->chqdsp_cntl);
315 smd_close(driver->ch_wcnss_cntl);
316 driver->ch_cntl = 0;
317 driver->chqdsp_cntl = 0;
318 driver->ch_wcnss_cntl = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800319 destroy_workqueue(driver->diag_cntl_wq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700320 platform_driver_unregister(&msm_smd_ch1_cntl_driver);
321 platform_driver_unregister(&diag_smd_lite_cntl_driver);
322
323 kfree(driver->buf_in_cntl);
324 kfree(driver->buf_in_qdsp_cntl);
325 kfree(driver->buf_in_wcnss_cntl);
326}
Dixon Peterson29aebee2012-04-06 12:44:08 -0700327
328#ifdef CONFIG_DEBUG_FS
329#define DEBUG_BUF_SIZE 4096
330static struct dentry *diag_dbgfs_dent;
331static int diag_dbgfs_table_index;
332
333static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf,
334 size_t count, loff_t *ppos)
335{
336 char *buf;
337 int ret;
338
339 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
340 if (!buf) {
341 pr_err("diag: %s, Error allocating memory\n", __func__);
342 return -ENOMEM;
343 }
344
345 ret = scnprintf(buf, DEBUG_BUF_SIZE,
346 "modem ch: 0x%x\n"
347 "lpass ch: 0x%x\n"
348 "riva ch: 0x%x\n"
349 "dci ch: 0x%x\n"
350 "modem cntl_ch: 0x%x\n"
351 "lpass cntl_ch: 0x%x\n"
352 "riva cntl_ch: 0x%x\n"
353 "CPU Tools id: %d\n"
354 "Apps only: %d\n"
355 "Apps master: %d\n"
356 "Check Polling Response: %d\n"
357 "polling_reg_flag: %d\n"
358 "uses device tree: %d\n"
359 "in_busy_1: %d\n"
360 "in_busy_2: %d\n"
361 "in_busy_qdsp_1: %d\n"
362 "in_busy_qdsp_2: %d\n"
363 "in_busy_wcnss_1: %d\n"
364 "in_busy_wcnss_2: %d\n"
365 "in_busy_dci: %d\n",
366 (unsigned int)driver->ch,
367 (unsigned int)driver->chqdsp,
368 (unsigned int)driver->ch_wcnss,
369 (unsigned int)driver->ch_dci,
370 (unsigned int)driver->ch_cntl,
371 (unsigned int)driver->chqdsp_cntl,
372 (unsigned int)driver->ch_wcnss_cntl,
373 chk_config_get_id(),
374 chk_apps_only(),
375 chk_apps_master(),
376 chk_polling_response(),
377 driver->polling_reg_flag,
378 driver->use_device_tree,
379 driver->in_busy_1,
380 driver->in_busy_2,
381 driver->in_busy_qdsp_1,
382 driver->in_busy_qdsp_2,
383 driver->in_busy_wcnss_1,
384 driver->in_busy_wcnss_2,
385 driver->in_busy_dci);
386
387#ifdef CONFIG_DIAG_OVER_USB
388 ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
389 "usb_connected: %d\n",
390 driver->usb_connected);
391#endif
392 ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
393
394 kfree(buf);
395 return ret;
396}
397
398static ssize_t diag_dbgfs_read_workpending(struct file *file,
399 char __user *ubuf, size_t count, loff_t *ppos)
400{
401 char *buf;
402 int ret;
403
404 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
405 if (!buf) {
406 pr_err("diag: %s, Error allocating memory\n", __func__);
407 return -ENOMEM;
408 }
409
410 ret = scnprintf(buf, DEBUG_BUF_SIZE,
411 "Pending status for work_stucts:\n"
412 "diag_drain_work: %d\n"
413 "diag_read_smd_work: %d\n"
414 "diag_read_smd_cntl_work: %d\n"
415 "diag_read_smd_qdsp_work: %d\n"
416 "diag_read_smd_qdsp_cntl_work: %d\n"
417 "diag_read_smd_wcnss_work: %d\n"
418 "diag_read_smd_wcnss_cntl_work: %d\n"
419 "diag_modem_mask_update_work: %d\n"
420 "diag_qdsp_mask_update_work: %d\n"
421 "diag_wcnss_mask_update_work: %d\n"
422 "diag_read_smd_dci_work: %d\n",
423 work_pending(&(driver->diag_drain_work)),
424 work_pending(&(driver->diag_read_smd_work)),
425 work_pending(&(driver->diag_read_smd_cntl_work)),
426 work_pending(&(driver->diag_read_smd_qdsp_work)),
427 work_pending(&(driver->diag_read_smd_qdsp_cntl_work)),
428 work_pending(&(driver->diag_read_smd_wcnss_work)),
429 work_pending(&(driver->diag_read_smd_wcnss_cntl_work)),
430 work_pending(&(driver->diag_modem_mask_update_work)),
431 work_pending(&(driver->diag_qdsp_mask_update_work)),
432 work_pending(&(driver->diag_wcnss_mask_update_work)),
433 work_pending(&(driver->diag_read_smd_dci_work)));
434
435#ifdef CONFIG_DIAG_OVER_USB
436 ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
437 "diag_proc_hdlc_work: %d\n"
438 "diag_read_work: %d\n",
439 work_pending(&(driver->diag_proc_hdlc_work)),
440 work_pending(&(driver->diag_read_work)));
441#endif
442 ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
443
444 kfree(buf);
445 return ret;
446}
447
448static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf,
449 size_t count, loff_t *ppos)
450{
451 char *buf;
452 int ret = 0;
453 int i;
454 int bytes_remaining;
455 int bytes_in_buffer = 0;
456 int bytes_written;
457 int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
458
459 if (diag_dbgfs_table_index >= diag_max_reg) {
460 /* Done. Reset to prepare for future requests */
461 diag_dbgfs_table_index = 0;
462 return 0;
463 }
464
465 buf = kzalloc(sizeof(char) * buf_size, GFP_KERNEL);
466 if (!buf) {
467 pr_err("diag: %s, Error allocating memory\n", __func__);
468 return -ENOMEM;
469 }
470
471 bytes_remaining = buf_size;
472 for (i = diag_dbgfs_table_index; i < diag_max_reg; i++) {
473 /* Do not process empty entries in the table */
474 if (driver->table[i].process_id == 0)
475 continue;
476
477 bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
478 "i: %3d, cmd_code: %4x, subsys_id: %4x, "
479 "client: %2d, cmd_code_lo: %4x, "
480 "cmd_code_hi: %4x, process_id: %5d\n",
481 i,
482 driver->table[i].cmd_code,
483 driver->table[i].subsys_id,
484 driver->table[i].client_id,
485 driver->table[i].cmd_code_lo,
486 driver->table[i].cmd_code_hi,
487 driver->table[i].process_id);
488
489 bytes_in_buffer += bytes_written;
490
491 /* Check if there is room to add another table entry */
492 bytes_remaining = buf_size - bytes_in_buffer;
493 if (bytes_remaining < bytes_written)
494 break;
495 }
496 diag_dbgfs_table_index = i;
497
498 *ppos = 0;
499 ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);
500
501 kfree(buf);
502 return ret;
503}
504
505#ifdef CONFIG_DIAG_HSIC_PIPE
506static ssize_t diag_dbgfs_read_hsic(struct file *file, char __user *ubuf,
507 size_t count, loff_t *ppos)
508{
509 char *buf;
510 int ret;
511
512 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
513 if (!buf) {
514 pr_err("diag: %s, Error allocating memory\n", __func__);
515 return -ENOMEM;
516 }
517
518 ret = scnprintf(buf, DEBUG_BUF_SIZE,
519 "hsic initialized: %d\n"
520 "hsic ch: %d\n"
521 "hsic enabled: %d\n"
522 "hsic_opened: %d\n"
523 "hisc_suspend: %d\n"
524 "in_busy_hsic_read_on_mdm: %d\n"
525 "in_busy_hsic_write_on_mdm: %d\n"
526 "in_busy_hsic_write: %d\n"
527 "in_busy_hsic_read: %d\n"
528 "usb_mdm_connected: %d\n"
529 "diag_read_mdm_work: %d\n"
530 "diag_read_hsic_work: %d\n"
531 "diag_disconnect_work: %d\n"
532 "diag_usb_read_complete_work: %d\n",
533 driver->hsic_initialized,
534 driver->hsic_ch,
535 driver->hsic_device_enabled,
536 driver->hsic_device_opened,
537 driver->hsic_suspend,
538 driver->in_busy_hsic_read_on_device,
539 driver->in_busy_hsic_write_on_device,
540 driver->in_busy_hsic_write,
541 driver->in_busy_hsic_read,
542 driver->usb_mdm_connected,
543 work_pending(&(driver->diag_read_mdm_work)),
544 work_pending(&(driver->diag_read_hsic_work)),
545 work_pending(&(driver->diag_disconnect_work)),
546 work_pending(&(driver->diag_usb_read_complete_work)));
547
548 ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
549
550 kfree(buf);
551 return ret;
552}
553
554const struct file_operations diag_dbgfs_hsic_ops = {
555 .read = diag_dbgfs_read_hsic,
556};
557#endif
558
559const struct file_operations diag_dbgfs_status_ops = {
560 .read = diag_dbgfs_read_status,
561};
562
563const struct file_operations diag_dbgfs_table_ops = {
564 .read = diag_dbgfs_read_table,
565};
566
567const struct file_operations diag_dbgfs_workpending_ops = {
568 .read = diag_dbgfs_read_workpending,
569};
570
571void diag_debugfs_init(void)
572{
573 diag_dbgfs_dent = debugfs_create_dir("diag", 0);
574 if (IS_ERR(diag_dbgfs_dent))
575 return;
576
577 debugfs_create_file("status", 0444, diag_dbgfs_dent, 0,
578 &diag_dbgfs_status_ops);
579
580 debugfs_create_file("table", 0444, diag_dbgfs_dent, 0,
581 &diag_dbgfs_table_ops);
582
583 debugfs_create_file("work_pending", 0444, diag_dbgfs_dent, 0,
584 &diag_dbgfs_workpending_ops);
585
586#ifdef CONFIG_DIAG_HSIC_PIPE
587 debugfs_create_file("hsic", 0444, diag_dbgfs_dent, 0,
588 &diag_dbgfs_hsic_ops);
589#endif
590
591 diag_dbgfs_table_index = 0;
592}
593
594void diag_debugfs_cleanup(void)
595{
596 if (diag_dbgfs_dent) {
597 debugfs_remove_recursive(diag_dbgfs_dent);
598 diag_dbgfs_dent = NULL;
599 }
600}
601#else
602void diag_debugfs_init(void) { }
603void diag_debugfs_cleanup(void) { }
604#endif