blob: 4726da14210c1799d4e98af0062c644aa125d21f [file] [log] [blame]
Dixon Peterson32e70bb2011-12-16 13:26:45 -08001/* Copyright (c) 2008-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 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070012#include <linux/slab.h>
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/err.h>
17#include <linux/platform_device.h>
18#include <linux/sched.h>
19#include <linux/workqueue.h>
20#include <linux/pm_runtime.h>
21#include <linux/diagchar.h>
22#include <linux/delay.h>
23#include <linux/reboot.h>
Dixon Petersonb4618a42012-02-29 18:56:31 -080024#include <linux/of.h>
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070025#include <linux/spinlock.h>
Dixon Petersoncc0bea772012-04-11 20:45:37 -070026#include <linux/kmemleak.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070027#ifdef CONFIG_DIAG_OVER_USB
28#include <mach/usbdiag.h>
29#endif
30#include <mach/msm_smd.h>
31#include <mach/socinfo.h>
32#include <mach/restart.h>
33#include "diagmem.h"
34#include "diagchar.h"
35#include "diagfwd.h"
36#include "diagfwd_cntl.h"
37#include "diagchar_hdlc.h"
38#ifdef CONFIG_DIAG_SDIO_PIPE
39#include "diagfwd_sdio.h"
40#endif
Shalabh Jain1c99e4c2012-03-26 18:47:59 -070041#include "diag_dci.h"
42
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070043#define MODE_CMD 41
44#define RESET_ID 2
45#define ALL_EQUIP_ID 100
46#define ALL_SSID -1
47#define MAX_SSID_PER_RANGE 100
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070048
49int diag_debug_buf_idx;
50unsigned char diag_debug_buf[1024];
51static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
52struct diag_master_table entry;
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -080053smd_channel_t *ch_temp, *chqdsp_temp, *ch_wcnss_temp;
Shalabh Jain321c8b52012-02-22 12:37:06 -080054int diag_event_num_bytes;
55int diag_event_config;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070056struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
57struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
Shalabh Jain321c8b52012-02-22 12:37:06 -080058struct mask_info {
59 int equip_id;
60 int num_items;
61 int index;
62};
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070063spinlock_t diag_cntl_lock;
64
65#define CREATE_MSG_MASK_TBL_ROW(XX) \
66do { \
67 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX; \
68 msg_mask_tbl_ptr += 4; \
69 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
70 msg_mask_tbl_ptr += 4; \
71 /* increment by MAX_SSID_PER_RANGE cells */ \
72 msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int); \
73} while (0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070074
75#define ENCODE_RSP_AND_SEND(buf_length) \
76do { \
77 send.state = DIAG_STATE_START; \
78 send.pkt = driver->apps_rsp_buf; \
79 send.last = (void *)(driver->apps_rsp_buf + buf_length); \
80 send.terminate = 1; \
81 if (!driver->in_busy_1) { \
82 enc.dest = driver->buf_in_1; \
Shalabh Jain321c8b52012-02-22 12:37:06 -080083 enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);\
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070084 diag_hdlc_encode(&send, &enc); \
85 driver->write_ptr_1->buf = driver->buf_in_1; \
86 driver->write_ptr_1->length = (int)(enc.dest - \
87 (void *)(driver->buf_in_1)); \
Shalabh Jain3893bf92011-09-18 18:37:16 -070088 driver->in_busy_1 = 1; \
Shalabh Jain69890aa2011-10-10 12:59:16 -070089 diag_device_write(driver->buf_in_1, MODEM_DATA, \
90 driver->write_ptr_1); \
Shalabh Jain321c8b52012-02-22 12:37:06 -080091 memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE); \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070092 } \
93} while (0)
94
95#define CHK_OVERFLOW(bufStart, start, end, length) \
96((bufStart <= start) && (end - start >= length)) ? 1 : 0
97
Dixon Petersonb4618a42012-02-29 18:56:31 -080098/* Determine if this device uses a device tree */
99#ifdef CONFIG_OF
100static int has_device_tree(void)
101{
102 struct device_node *node;
103
104 node = of_find_node_by_path("/");
105 if (node) {
106 of_node_put(node);
107 return 1;
108 }
109 return 0;
110}
111#else
112static int has_device_tree(void)
113{
114 return 0;
115}
116#endif
117
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700118int chk_config_get_id(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700119{
Shalabh Jain482bf122011-12-06 03:54:47 -0800120 /* For all Fusion targets, Modem will always be present */
121 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
122 return 0;
123
Dixon Petersonb4618a42012-02-29 18:56:31 -0800124 if (driver->use_device_tree) {
125 if (machine_is_copper())
126 return MSM8974_TOOLS_ID;
127 else
128 return 0;
129 } else {
130 switch (socinfo_get_msm_cpu()) {
131 case MSM_CPU_8X60:
132 return APQ8060_TOOLS_ID;
133 case MSM_CPU_8960:
134 return AO8960_TOOLS_ID;
135 case MSM_CPU_8064:
136 return APQ8064_TOOLS_ID;
137 case MSM_CPU_8930:
138 return MSM8930_TOOLS_ID;
139 case MSM_CPU_COPPER:
140 return MSM8974_TOOLS_ID;
141 case MSM_CPU_8625:
142 return MSM8625_TOOLS_ID;
143 default:
144 return 0;
145 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700146 }
147}
148
149/*
Shalabh Jain321c8b52012-02-22 12:37:06 -0800150 * This will return TRUE for targets which support apps only mode and hence SSR.
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700151 * This applies to 8960 and newer targets.
152 */
153int chk_apps_only(void)
154{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800155 if (driver->use_device_tree)
156 return 1;
157
158 switch (socinfo_get_msm_cpu()) {
159 case MSM_CPU_8960:
160 case MSM_CPU_8064:
161 case MSM_CPU_8930:
162 case MSM_CPU_8627:
163 case MSM_CPU_9615:
164 case MSM_CPU_COPPER:
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700165 return 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700166 default:
167 return 0;
168 }
169}
170
Shalabh Jain10f5f432012-01-11 11:45:44 +0530171/*
172 * This will return TRUE for targets which support apps as master.
173 * Thus, SW DLOAD and Mode Reset are supported on apps processor.
174 * This applies to 8960 and newer targets.
175 */
176int chk_apps_master(void)
177{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800178 if (driver->use_device_tree)
179 return 1;
180 else if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615() ||
181 cpu_is_apq8064() || cpu_is_msm8627())
182 return 1;
183 else
184 return 0;
185}
186
Dixon Peterson29aebee2012-04-06 12:44:08 -0700187int chk_polling_response(void)
Dixon Petersonb4618a42012-02-29 18:56:31 -0800188{
189 if (!(driver->polling_reg_flag) && chk_apps_master())
190 /*
191 * If the apps processor is master and no other processor
192 * has registered to respond for polling
193 */
194 return 1;
195 else if (!(driver->ch) && !(chk_apps_master()))
196 /*
197 * If the apps processor is not the master and the modem
198 * is not up
199 */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530200 return 1;
201 else
202 return 0;
203}
204
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700205void __diag_smd_send_req(void)
206{
207 void *buf = NULL;
208 int *in_busy_ptr = NULL;
209 struct diag_request *write_ptr_modem = NULL;
210
211 if (!driver->in_busy_1) {
212 buf = driver->buf_in_1;
213 write_ptr_modem = driver->write_ptr_1;
214 in_busy_ptr = &(driver->in_busy_1);
215 } else if (!driver->in_busy_2) {
216 buf = driver->buf_in_2;
217 write_ptr_modem = driver->write_ptr_2;
218 in_busy_ptr = &(driver->in_busy_2);
219 }
220
221 if (driver->ch && buf) {
222 int r = smd_read_avail(driver->ch);
223
224 if (r > IN_BUF_SIZE) {
225 if (r < MAX_IN_BUF_SIZE) {
226 pr_err("diag: SMD sending in "
227 "packets upto %d bytes", r);
228 buf = krealloc(buf, r, GFP_KERNEL);
229 } else {
230 pr_err("diag: SMD sending in "
231 "packets more than %d bytes", MAX_IN_BUF_SIZE);
232 return;
233 }
234 }
235 if (r > 0) {
236 if (!buf)
237 pr_info("Out of diagmem for Modem\n");
238 else {
239 APPEND_DEBUG('i');
240 smd_read(driver->ch, buf, r);
241 APPEND_DEBUG('j');
242 write_ptr_modem->length = r;
243 *in_busy_ptr = 1;
244 diag_device_write(buf, MODEM_DATA,
245 write_ptr_modem);
246 }
247 }
248 }
249}
250
251int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr)
252{
253 int i, err = 0;
254
255 if (driver->logging_mode == MEMORY_DEVICE_MODE) {
256 if (proc_num == APPS_DATA) {
257 for (i = 0; i < driver->poolsize_write_struct; i++)
258 if (driver->buf_tbl[i].length == 0) {
259 driver->buf_tbl[i].buf = buf;
260 driver->buf_tbl[i].length =
261 driver->used;
262#ifdef DIAG_DEBUG
263 pr_debug("diag: ENQUEUE buf ptr"
264 " and length is %x , %d\n",
265 (unsigned int)(driver->buf_
266 tbl[i].buf), driver->buf_tbl[i].length);
267#endif
268 break;
269 }
270 }
271 for (i = 0; i < driver->num_clients; i++)
272 if (driver->client_map[i].pid ==
273 driver->logging_process_id)
274 break;
275 if (i < driver->num_clients) {
Shalabh Jain69890aa2011-10-10 12:59:16 -0700276 driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700277 pr_debug("diag: wake up logging process\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700278 wake_up_interruptible(&driver->wait_q);
279 } else
280 return -EINVAL;
281 } else if (driver->logging_mode == NO_LOGGING_MODE) {
282 if (proc_num == MODEM_DATA) {
283 driver->in_busy_1 = 0;
284 driver->in_busy_2 = 0;
285 queue_work(driver->diag_wq, &(driver->
286 diag_read_smd_work));
287 } else if (proc_num == QDSP_DATA) {
288 driver->in_busy_qdsp_1 = 0;
289 driver->in_busy_qdsp_2 = 0;
290 queue_work(driver->diag_wq, &(driver->
291 diag_read_smd_qdsp_work));
292 } else if (proc_num == WCNSS_DATA) {
Ashay Jaiswal29620122012-03-21 12:02:36 +0530293 driver->in_busy_wcnss_1 = 0;
294 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700295 queue_work(driver->diag_wq, &(driver->
296 diag_read_smd_wcnss_work));
297 }
Shalabh Jain482bf122011-12-06 03:54:47 -0800298#ifdef CONFIG_DIAG_SDIO_PIPE
299 else if (proc_num == SDIO_DATA) {
300 driver->in_busy_sdio = 0;
301 queue_work(driver->diag_sdio_wq,
302 &(driver->diag_read_sdio_work));
303 }
304#endif
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700305#ifdef CONFIG_DIAG_HSIC_PIPE
306 else if (proc_num == HSIC_DATA) {
307 driver->in_busy_hsic_read = 0;
308 driver->in_busy_hsic_write_on_device = 0;
309 if (driver->hsic_ch)
310 queue_work(driver->diag_hsic_wq,
311 &(driver->diag_read_hsic_work));
312 }
313#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700314 err = -1;
315 }
316#ifdef CONFIG_DIAG_OVER_USB
317 else if (driver->logging_mode == USB_MODE) {
318 if (proc_num == APPS_DATA) {
319 driver->write_ptr_svc = (struct diag_request *)
320 (diagmem_alloc(driver, sizeof(struct diag_request),
321 POOL_TYPE_WRITE_STRUCT));
322 if (driver->write_ptr_svc) {
323 driver->write_ptr_svc->length = driver->used;
324 driver->write_ptr_svc->buf = buf;
325 err = usb_diag_write(driver->legacy_ch,
326 driver->write_ptr_svc);
327 } else
328 err = -1;
329 } else if (proc_num == MODEM_DATA) {
330 write_ptr->buf = buf;
331#ifdef DIAG_DEBUG
332 printk(KERN_INFO "writing data to USB,"
333 "pkt length %d\n", write_ptr->length);
334 print_hex_dump(KERN_DEBUG, "Written Packet Data to"
335 " USB: ", 16, 1, DUMP_PREFIX_ADDRESS,
336 buf, write_ptr->length, 1);
337#endif /* DIAG DEBUG */
338 err = usb_diag_write(driver->legacy_ch, write_ptr);
339 } else if (proc_num == QDSP_DATA) {
340 write_ptr->buf = buf;
341 err = usb_diag_write(driver->legacy_ch, write_ptr);
342 } else if (proc_num == WCNSS_DATA) {
343 write_ptr->buf = buf;
344 err = usb_diag_write(driver->legacy_ch, write_ptr);
345 }
346#ifdef CONFIG_DIAG_SDIO_PIPE
347 else if (proc_num == SDIO_DATA) {
348 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -0800349 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700350 write_ptr->buf = buf;
351 err = usb_diag_write(driver->mdm_ch, write_ptr);
352 } else
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800353 pr_err("diag: Incorrect sdio data "
354 "while USB write\n");
355 }
356#endif
357#ifdef CONFIG_DIAG_HSIC_PIPE
358 else if (proc_num == HSIC_DATA) {
359 if (driver->hsic_device_enabled) {
360 write_ptr->buf = buf;
361 err = usb_diag_write(driver->mdm_ch, write_ptr);
362 } else
363 pr_err("diag: Incorrect hsic data "
364 "while USB write\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700365 }
366#endif
367 APPEND_DEBUG('d');
368 }
369#endif /* DIAG OVER USB */
370 return err;
371}
372
373void __diag_smd_wcnss_send_req(void)
374{
Ashay Jaiswal29620122012-03-21 12:02:36 +0530375 void *buf = NULL;
376 int *in_busy_wcnss_ptr = NULL;
377 struct diag_request *write_ptr_wcnss = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700378
Ashay Jaiswal29620122012-03-21 12:02:36 +0530379 if (!driver->in_busy_wcnss_1) {
380 buf = driver->buf_in_wcnss_1;
381 write_ptr_wcnss = driver->write_ptr_wcnss_1;
382 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_1);
383 } else if (!driver->in_busy_wcnss_2) {
384 buf = driver->buf_in_wcnss_2;
385 write_ptr_wcnss = driver->write_ptr_wcnss_2;
386 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_2);
387 }
388
389 if (driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700390 int r = smd_read_avail(driver->ch_wcnss);
391 if (r > IN_BUF_SIZE) {
392 if (r < MAX_IN_BUF_SIZE) {
393 pr_err("diag: wcnss packets > %d bytes", r);
394 buf = krealloc(buf, r, GFP_KERNEL);
395 } else {
396 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
397 return;
398 }
399 }
400 if (r > 0) {
401 if (!buf) {
402 pr_err("Out of diagmem for wcnss\n");
403 } else {
404 APPEND_DEBUG('i');
405 smd_read(driver->ch_wcnss, buf, r);
406 APPEND_DEBUG('j');
407 write_ptr_wcnss->length = r;
408 *in_busy_wcnss_ptr = 1;
409 diag_device_write(buf, WCNSS_DATA,
410 write_ptr_wcnss);
411 }
412 }
413 }
414}
415
416void __diag_smd_qdsp_send_req(void)
417{
418 void *buf = NULL;
419 int *in_busy_qdsp_ptr = NULL;
420 struct diag_request *write_ptr_qdsp = NULL;
421
422 if (!driver->in_busy_qdsp_1) {
423 buf = driver->buf_in_qdsp_1;
424 write_ptr_qdsp = driver->write_ptr_qdsp_1;
425 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1);
426 } else if (!driver->in_busy_qdsp_2) {
427 buf = driver->buf_in_qdsp_2;
428 write_ptr_qdsp = driver->write_ptr_qdsp_2;
429 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2);
430 }
431
432 if (driver->chqdsp && buf) {
433 int r = smd_read_avail(driver->chqdsp);
434
435 if (r > IN_BUF_SIZE) {
436 if (r < MAX_IN_BUF_SIZE) {
437 pr_err("diag: SMD sending in "
438 "packets upto %d bytes", r);
439 buf = krealloc(buf, r, GFP_KERNEL);
440 } else {
441 pr_err("diag: SMD sending in "
442 "packets more than %d bytes", MAX_IN_BUF_SIZE);
443 return;
444 }
445 }
446 if (r > 0) {
447 if (!buf)
448 printk(KERN_INFO "Out of diagmem for QDSP\n");
449 else {
450 APPEND_DEBUG('i');
451 smd_read(driver->chqdsp, buf, r);
452 APPEND_DEBUG('j');
453 write_ptr_qdsp->length = r;
454 *in_busy_qdsp_ptr = 1;
455 diag_device_write(buf, QDSP_DATA,
456 write_ptr_qdsp);
457 }
458 }
459 }
460}
461
462static void diag_print_mask_table(void)
463{
464/* Enable this to print mask table when updated */
465#ifdef MASK_DEBUG
466 int first;
467 int last;
468 uint8_t *ptr = driver->msg_masks;
469 int i = 0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700470 pr_info("diag: F3 message mask table\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700471 while (*(uint32_t *)(ptr + 4)) {
472 first = *(uint32_t *)ptr;
473 ptr += 4;
474 last = *(uint32_t *)ptr;
475 ptr += 4;
476 printk(KERN_INFO "SSID %d - %d\n", first, last);
477 for (i = 0 ; i <= last - first ; i++)
478 printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700479 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700480
481 }
482#endif
483}
484
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700485void diag_create_msg_mask_table(void)
486{
487 uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
488
489 CREATE_MSG_MASK_TBL_ROW(0);
490 CREATE_MSG_MASK_TBL_ROW(1);
491 CREATE_MSG_MASK_TBL_ROW(2);
492 CREATE_MSG_MASK_TBL_ROW(3);
493 CREATE_MSG_MASK_TBL_ROW(4);
494 CREATE_MSG_MASK_TBL_ROW(5);
495 CREATE_MSG_MASK_TBL_ROW(6);
496 CREATE_MSG_MASK_TBL_ROW(7);
497 CREATE_MSG_MASK_TBL_ROW(8);
498 CREATE_MSG_MASK_TBL_ROW(9);
499 CREATE_MSG_MASK_TBL_ROW(10);
500 CREATE_MSG_MASK_TBL_ROW(11);
501 CREATE_MSG_MASK_TBL_ROW(12);
502 CREATE_MSG_MASK_TBL_ROW(13);
503 CREATE_MSG_MASK_TBL_ROW(14);
504 CREATE_MSG_MASK_TBL_ROW(15);
505 CREATE_MSG_MASK_TBL_ROW(16);
506 CREATE_MSG_MASK_TBL_ROW(17);
507 CREATE_MSG_MASK_TBL_ROW(18);
508 CREATE_MSG_MASK_TBL_ROW(19);
509 CREATE_MSG_MASK_TBL_ROW(20);
510 CREATE_MSG_MASK_TBL_ROW(21);
511 CREATE_MSG_MASK_TBL_ROW(22);
512}
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700513
514static void diag_set_msg_mask(int rt_mask)
515{
516 int first_ssid, last_ssid, i;
517 uint8_t *parse_ptr, *ptr = driver->msg_masks;
518
519 mutex_lock(&driver->diagchar_mutex);
520 while (*(uint32_t *)(ptr + 4)) {
521 first_ssid = *(uint32_t *)ptr;
522 ptr += 4;
523 last_ssid = *(uint32_t *)ptr;
524 ptr += 4;
525 parse_ptr = ptr;
526 pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
527 for (i = 0; i < last_ssid - first_ssid + 1; i++) {
528 *(int *)parse_ptr = rt_mask;
529 parse_ptr += 4;
530 }
531 ptr += MAX_SSID_PER_RANGE * 4;
532 }
533 mutex_unlock(&driver->diagchar_mutex);
534}
535
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700536static void diag_update_msg_mask(int start, int end , uint8_t *buf)
537{
538 int found = 0;
539 int first;
540 int last;
541 uint8_t *ptr = driver->msg_masks;
542 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
543 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
544
545 mutex_lock(&driver->diagchar_mutex);
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530546
Shalabh Jain321c8b52012-02-22 12:37:06 -0800547 /* First SSID can be zero : So check that last is non-zero */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700548 while (*(uint32_t *)(ptr + 4)) {
549 first = *(uint32_t *)ptr;
550 ptr += 4;
551 last = *(uint32_t *)ptr;
552 ptr += 4;
553 if (start >= first && start <= last) {
554 ptr += (start - first)*4;
555 if (end <= last)
556 if (CHK_OVERFLOW(ptr_buffer_start, ptr,
557 ptr_buffer_end,
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700558 (((end - start)+1)*4))) {
559 pr_debug("diag: update ssid start %d,"
560 " end %d\n", start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700561 memcpy(ptr, buf , ((end - start)+1)*4);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700562 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700563 printk(KERN_CRIT "Not enough"
564 " buffer space for"
565 " MSG_MASK\n");
566 else
567 printk(KERN_INFO "Unable to copy"
568 " mask change\n");
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530569
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700570 found = 1;
571 break;
572 } else {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700573 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700574 }
575 }
576 /* Entry was not found - add new table */
577 if (!found) {
578 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
579 8 + ((end - start) + 1)*4)) {
580 memcpy(ptr, &(start) , 4);
581 ptr += 4;
582 memcpy(ptr, &(end), 4);
583 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700584 pr_debug("diag: adding NEW ssid start %d, end %d\n",
585 start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700586 memcpy(ptr, buf , ((end - start) + 1)*4);
587 } else
588 printk(KERN_CRIT " Not enough buffer"
589 " space for MSG_MASK\n");
590 }
591 mutex_unlock(&driver->diagchar_mutex);
592 diag_print_mask_table();
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530593
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700594}
595
Shalabh Jaina51f2592012-03-08 14:36:35 -0800596void diag_toggle_event_mask(int toggle)
597{
598 uint8_t *ptr = driver->event_masks;
599
600 mutex_lock(&driver->diagchar_mutex);
601 if (toggle)
602 memset(ptr, 0xFF, EVENT_MASK_SIZE);
603 else
604 memset(ptr, 0, EVENT_MASK_SIZE);
605 mutex_unlock(&driver->diagchar_mutex);
606}
607
Shalabh Jain321c8b52012-02-22 12:37:06 -0800608static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700609{
610 uint8_t *ptr = driver->event_masks;
611 uint8_t *temp = buf + 2;
612
613 mutex_lock(&driver->diagchar_mutex);
614 if (!toggle)
615 memset(ptr, 0 , EVENT_MASK_SIZE);
616 else
617 if (CHK_OVERFLOW(ptr, ptr,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800618 ptr+EVENT_MASK_SIZE, num_bytes))
619 memcpy(ptr, temp , num_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700620 else
621 printk(KERN_CRIT "Not enough buffer space "
622 "for EVENT_MASK\n");
623 mutex_unlock(&driver->diagchar_mutex);
624}
625
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700626static void diag_disable_log_mask(void)
627{
628 int i = 0;
629 struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
630
631 pr_debug("diag: disable log masks\n");
632 mutex_lock(&driver->diagchar_mutex);
633 for (i = 0; i < MAX_EQUIP_ID; i++) {
634 pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
635 if (!(parse_ptr->equip_id)) /* Reached a null entry */
636 break;
637 memset(driver->log_masks + parse_ptr->index, 0,
638 (parse_ptr->num_items + 7)/8);
639 parse_ptr++;
640 }
641 mutex_unlock(&driver->diagchar_mutex);
642}
643
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700644static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
645{
646 uint8_t *temp = buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700647 int i = 0;
648 unsigned char *ptr_data;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700649 int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700650 struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700652 pr_debug("diag: received equip id = %d\n", equip_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700653 mutex_lock(&driver->diagchar_mutex);
654 /* Check if we already know index of this equipment ID */
655 for (i = 0; i < MAX_EQUIP_ID; i++) {
656 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
657 offset = ptr->index;
658 break;
659 }
660 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
Shalabh Jain321c8b52012-02-22 12:37:06 -0800661 /* Reached a null entry */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700662 ptr->equip_id = equip_id;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800663 ptr->num_items = num_items;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700664 ptr->index = driver->log_masks_length;
665 offset = driver->log_masks_length;
666 driver->log_masks_length += ((num_items+7)/8);
667 break;
668 }
669 ptr++;
670 }
671 ptr_data = driver->log_masks + offset;
672 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
673 + LOG_MASK_SIZE, (num_items+7)/8))
674 memcpy(ptr_data, temp , (num_items+7)/8);
675 else
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700676 pr_err("diag: Not enough buffer space for LOG_MASK\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700677 mutex_unlock(&driver->diagchar_mutex);
678}
679
680static void diag_update_pkt_buffer(unsigned char *buf)
681{
682 unsigned char *ptr = driver->pkt_buf;
683 unsigned char *temp = buf;
684
685 mutex_lock(&driver->diagchar_mutex);
686 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
687 memcpy(ptr, temp , driver->pkt_length);
688 else
689 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
690 mutex_unlock(&driver->diagchar_mutex);
691}
692
693void diag_update_userspace_clients(unsigned int type)
694{
695 int i;
696
697 mutex_lock(&driver->diagchar_mutex);
698 for (i = 0; i < driver->num_clients; i++)
699 if (driver->client_map[i].pid != 0)
700 driver->data_ready[i] |= type;
701 wake_up_interruptible(&driver->wait_q);
702 mutex_unlock(&driver->diagchar_mutex);
703}
704
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700705void diag_update_sleeping_process(int process_id, int data_type)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700706{
707 int i;
708
709 mutex_lock(&driver->diagchar_mutex);
710 for (i = 0; i < driver->num_clients; i++)
711 if (driver->client_map[i].pid == process_id) {
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700712 driver->data_ready[i] |= data_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700713 break;
714 }
715 wake_up_interruptible(&driver->wait_q);
716 mutex_unlock(&driver->diagchar_mutex);
717}
718
719void diag_send_data(struct diag_master_table entry, unsigned char *buf,
720 int len, int type)
721{
722 driver->pkt_length = len;
723 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
724 diag_update_pkt_buffer(buf);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700725 diag_update_sleeping_process(entry.process_id, PKT_TYPE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700726 } else {
727 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700728 if (entry.client_id == MODEM_PROC && driver->ch) {
Shalabh Jain10f5f432012-01-11 11:45:44 +0530729 if (chk_apps_master() &&
Shalabh Jainc9f35092011-07-28 18:36:17 -0700730 (int)(*(char *)buf) == MODE_CMD)
Dixon Petersonff425d12011-12-06 18:12:35 -0800731 if ((int)(*(char *)(buf+1)) ==
732 RESET_ID)
Shalabh Jainc9f35092011-07-28 18:36:17 -0700733 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700734 smd_write(driver->ch, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700735 } else if (entry.client_id == QDSP_PROC &&
736 driver->chqdsp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700737 smd_write(driver->chqdsp, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700738 } else if (entry.client_id == WCNSS_PROC &&
739 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700740 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700741 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700742 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700743 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700744 }
745 }
746}
747
Shalabh Jain321c8b52012-02-22 12:37:06 -0800748void diag_modem_mask_update_fn(struct work_struct *work)
749{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700750 diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
751 ALL_SSID, MODEM_PROC);
752 diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800753 diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
754}
755
756void diag_qdsp_mask_update_fn(struct work_struct *work)
757{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700758 diag_send_msg_mask_update(driver->chqdsp_cntl, ALL_SSID,
759 ALL_SSID, QDSP_PROC);
760 diag_send_log_mask_update(driver->chqdsp_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800761 diag_send_event_mask_update(driver->chqdsp_cntl, diag_event_num_bytes);
762}
763
764void diag_wcnss_mask_update_fn(struct work_struct *work)
765{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700766 diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
767 ALL_SSID, WCNSS_PROC);
768 diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800769 diag_send_event_mask_update(driver->ch_wcnss_cntl,
770 diag_event_num_bytes);
771}
772
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700773void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800774{
775 void *buf = driver->buf_log_mask_update;
776 int header_size = sizeof(struct diag_ctrl_log_mask);
777 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700778 int i, size, wr_size = -ENOMEM, retry_count = 0;
779 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800780
781 for (i = 0; i < MAX_EQUIP_ID; i++) {
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700782 size = (ptr->num_items+7)/8;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800783 /* reached null entry */
784 if ((ptr->equip_id == 0) && (ptr->index == 0))
785 break;
786 driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
787 driver->log_mask->num_items = ptr->num_items;
788 driver->log_mask->data_len = 11 + size;
789 driver->log_mask->stream_id = 1; /* 2, if dual stream */
790 driver->log_mask->status = 3; /* status for valid mask */
791 driver->log_mask->equip_id = ptr->equip_id;
792 driver->log_mask->log_mask_size = size;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700793 /* send only desired update, NOT ALL */
794 if (equip_id == ALL_EQUIP_ID || equip_id ==
795 driver->log_mask->equip_id) {
796 memcpy(buf, driver->log_mask, header_size);
797 memcpy(buf+header_size, driver->log_masks+ptr->index,
798 size);
799 if (ch) {
800 while (retry_count < 3) {
801 spin_lock_irqsave(&diag_cntl_lock,
802 flags);
803 wr_size = smd_write(ch, buf,
804 header_size + size);
805 spin_unlock_irqrestore(&diag_cntl_lock,
806 flags);
807 if (wr_size == -ENOMEM) {
808 retry_count++;
809 usleep(20000);
810 } else
811 break;
812 }
813 if (wr_size != header_size + size)
814 pr_err("diag: log mask update failed"
815 " %d, tried %d", wr_size, header_size + size);
816 else
817 pr_debug("diag: updated log equip ID %d"
818 ",len %d\n", driver->log_mask->equip_id,
819 driver->log_mask->log_mask_size);
820 } else
821 pr_err("diag: ch not valid for log update\n");
822 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800823 ptr++;
824 }
825}
826
827void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
828{
829 void *buf = driver->buf_event_mask_update;
830 int header_size = sizeof(struct diag_ctrl_event_mask);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700831 int wr_size = -ENOMEM, retry_count = 0;
832 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800833
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700834 if (num_bytes == 0) {
835 pr_debug("diag: event mask not set yet, so no update\n");
836 return;
837 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800838 /* send event mask update */
839 driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
840 driver->event_mask->data_len = 7 + num_bytes;
841 driver->event_mask->stream_id = 1; /* 2, if dual stream */
842 driver->event_mask->status = 3; /* status for valid mask */
843 driver->event_mask->event_config = diag_event_config; /* event config */
844 driver->event_mask->event_mask_size = num_bytes;
845 memcpy(buf, driver->event_mask, header_size);
846 memcpy(buf+header_size, driver->event_masks, num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700847 if (ch) {
848 while (retry_count < 3) {
849 spin_lock_irqsave(&diag_cntl_lock, flags);
850 wr_size = smd_write(ch, buf, header_size + num_bytes);
851 spin_unlock_irqrestore(&diag_cntl_lock, flags);
852 if (wr_size == -ENOMEM) {
853 retry_count++;
854 usleep(20000);
855 } else
856 break;
857 }
858 if (wr_size != header_size + num_bytes)
859 pr_err("diag: error writing event mask %d, tried %d\n",
860 wr_size, header_size + num_bytes);
861 } else
862 pr_err("diag: ch not valid for event update\n");
Shalabh Jain321c8b52012-02-22 12:37:06 -0800863}
864
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700865void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
866 int updated_ssid_last, int proc)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800867{
868 void *buf = driver->buf_msg_mask_update;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700869 int first, last, size = -ENOMEM, retry_count = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800870 int header_size = sizeof(struct diag_ctrl_msg_mask);
871 uint8_t *ptr = driver->msg_masks;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700872 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800873
874 while (*(uint32_t *)(ptr + 4)) {
875 first = *(uint32_t *)ptr;
876 ptr += 4;
877 last = *(uint32_t *)ptr;
878 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700879 if ((updated_ssid_first >= first && updated_ssid_last <= last)
880 || (updated_ssid_first == ALL_SSID)) {
881 /* send f3 mask update */
882 driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
883 driver->msg_mask->msg_mask_size = last - first + 1;
884 driver->msg_mask->data_len = 11 +
885 4 * (driver->msg_mask->msg_mask_size);
886 driver->msg_mask->stream_id = 1; /* 2, if dual stream */
887 driver->msg_mask->status = 3; /* status valid mask */
888 driver->msg_mask->msg_mode = 0; /* Legcay mode */
889 driver->msg_mask->ssid_first = first;
890 driver->msg_mask->ssid_last = last;
891 memcpy(buf, driver->msg_mask, header_size);
892 memcpy(buf+header_size, ptr,
893 4 * (driver->msg_mask->msg_mask_size));
894 if (ch) {
895 while (retry_count < 3) {
896 spin_lock_irqsave(&diag_cntl_lock,
897 flags);
898 size = smd_write(ch, buf, header_size +
899 4*(driver->msg_mask->msg_mask_size));
900 spin_unlock_irqrestore(&diag_cntl_lock,
901 flags);
902 if (size == -ENOMEM) {
903 retry_count++;
904 usleep(20000);
905 } else
906 break;
907 }
908 if (size != header_size +
909 4*(driver->msg_mask->msg_mask_size))
910 pr_err("diag: msg mask update fail %d,"
911 " tried %d\n", size,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800912 header_size + 4*(driver->msg_mask->msg_mask_size));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700913 else
914 pr_debug("diag: sending mask update for"
915 " ssid first %d, last %d on PROC %d\n", first, last, proc);
916 } else
917 pr_err("diag: ch invalid msg mask update\n");
918 }
919 ptr += MAX_SSID_PER_RANGE*4;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800920 }
921}
922
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700923static int diag_process_apps_pkt(unsigned char *buf, int len)
924{
925 uint16_t subsys_cmd_code;
926 int subsys_id, ssid_first, ssid_last, ssid_range;
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700927 int packet_type = 1, i, cmd_code, rt_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700928 unsigned char *temp = buf;
929 int data_type;
930#if defined(CONFIG_DIAG_OVER_USB)
931 int payload_length;
932 unsigned char *ptr;
933#endif
934
Shalabh Jain321c8b52012-02-22 12:37:06 -0800935 /* Set log masks */
936 if (*buf == 0x73 && *(int *)(buf+4) == 3) {
937 buf += 8;
938 /* Read Equip ID and pass as first param below*/
939 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
940 diag_update_userspace_clients(LOG_MASKS_TYPE);
941#if defined(CONFIG_DIAG_OVER_USB)
942 if (chk_apps_only()) {
943 driver->apps_rsp_buf[0] = 0x73;
944 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
945 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
946 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
947 for (i = 0; i < payload_length; i++)
948 *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700949 if (driver->ch_cntl)
950 diag_send_log_mask_update(driver->ch_cntl,
951 *(int *)buf);
952 if (driver->chqdsp_cntl)
953 diag_send_log_mask_update(driver->chqdsp_cntl,
954 *(int *)buf);
955 if (driver->ch_wcnss_cntl)
956 diag_send_log_mask_update(driver->ch_wcnss_cntl,
957 *(int *)buf);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800958 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
959 return 0;
960 } else
961 buf = temp;
962#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700963 } /* Disable log masks */
964 else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
965 buf += 8;
966 /* Disable mask for each log code */
967 diag_disable_log_mask();
968 diag_update_userspace_clients(LOG_MASKS_TYPE);
969#if defined(CONFIG_DIAG_OVER_USB)
970 if (chk_apps_only()) {
971 driver->apps_rsp_buf[0] = 0x73;
972 driver->apps_rsp_buf[1] = 0x0;
973 driver->apps_rsp_buf[2] = 0x0;
974 driver->apps_rsp_buf[3] = 0x0;
975 *(int *)(driver->apps_rsp_buf + 4) = 0x0;
976 if (driver->ch_cntl)
977 diag_send_log_mask_update(driver->ch_cntl,
978 *(int *)buf);
979 if (driver->chqdsp_cntl)
980 diag_send_log_mask_update(driver->chqdsp_cntl,
981 *(int *)buf);
982 if (driver->ch_wcnss_cntl)
983 diag_send_log_mask_update(driver->ch_wcnss_cntl,
984 *(int *)buf);
985 ENCODE_RSP_AND_SEND(7);
986 return 0;
987 } else
988 buf = temp;
989#endif
990 } /* Set runtime message mask */
Shalabh Jain321c8b52012-02-22 12:37:06 -0800991 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
992 ssid_first = *(uint16_t *)(buf + 2);
993 ssid_last = *(uint16_t *)(buf + 4);
994 ssid_range = 4 * (ssid_last - ssid_first + 1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700995 pr_debug("diag: received mask update for ssid_first = %d,"
996 " ssid_last = %d", ssid_first, ssid_last);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800997 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
998 diag_update_userspace_clients(MSG_MASKS_TYPE);
999#if defined(CONFIG_DIAG_OVER_USB)
1000 if (chk_apps_only()) {
1001 for (i = 0; i < 8 + ssid_range; i++)
1002 *(driver->apps_rsp_buf + i) = *(buf+i);
1003 *(driver->apps_rsp_buf + 6) = 0x1;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001004 if (driver->ch_cntl)
1005 diag_send_msg_mask_update(driver->ch_cntl,
1006 ssid_first, ssid_last, MODEM_PROC);
1007 if (driver->chqdsp_cntl)
1008 diag_send_msg_mask_update(driver->chqdsp_cntl,
1009 ssid_first, ssid_last, QDSP_PROC);
1010 if (driver->ch_wcnss_cntl)
1011 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1012 ssid_first, ssid_last, WCNSS_PROC);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001013 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1014 return 0;
1015 } else
1016 buf = temp;
1017#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001018 } /* Set ALL runtime message mask */
1019 else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
1020 rt_mask = *(int *)(buf + 4);
1021 diag_set_msg_mask(rt_mask);
1022 diag_update_userspace_clients(MSG_MASKS_TYPE);
1023#if defined(CONFIG_DIAG_OVER_USB)
1024 if (chk_apps_only()) {
1025 driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
1026 driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
1027 driver->apps_rsp_buf[2] = 1; /* success */
1028 driver->apps_rsp_buf[3] = 0; /* rsvd */
1029 *(int *)(driver->apps_rsp_buf + 4) = rt_mask;
1030 /* send msg mask update to peripheral */
1031 if (driver->ch_cntl)
1032 diag_send_msg_mask_update(driver->ch_cntl,
1033 ALL_SSID, ALL_SSID, MODEM_PROC);
1034 if (driver->chqdsp_cntl)
1035 diag_send_msg_mask_update(driver->chqdsp_cntl,
1036 ALL_SSID, ALL_SSID, QDSP_PROC);
1037 if (driver->ch_wcnss_cntl)
1038 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1039 ALL_SSID, ALL_SSID, WCNSS_PROC);
1040 ENCODE_RSP_AND_SEND(7);
1041 return 0;
1042 } else
1043 buf = temp;
1044#endif
Shalabh Jain321c8b52012-02-22 12:37:06 -08001045 } else if (*buf == 0x82) { /* event mask change */
1046 buf += 4;
1047 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
1048 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
1049 diag_update_userspace_clients(EVENT_MASKS_TYPE);
1050#if defined(CONFIG_DIAG_OVER_USB)
1051 if (chk_apps_only()) {
1052 driver->apps_rsp_buf[0] = 0x82;
1053 driver->apps_rsp_buf[1] = 0x0;
1054 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1055 *(uint16_t *)(driver->apps_rsp_buf + 4) =
1056 EVENT_LAST_ID + 1;
Shalabh Jaina51f2592012-03-08 14:36:35 -08001057 memcpy(driver->apps_rsp_buf+6, driver->event_masks,
1058 EVENT_LAST_ID/8+1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001059 if (driver->ch_cntl)
1060 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001061 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001062 if (driver->chqdsp_cntl)
1063 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001064 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001065 if (driver->ch_wcnss_cntl)
1066 diag_send_event_mask_update(
1067 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001068 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1069 return 0;
1070 } else
1071 buf = temp;
1072#endif
1073 } else if (*buf == 0x60) {
1074 diag_event_config = *(buf+1);
Shalabh Jaina51f2592012-03-08 14:36:35 -08001075 diag_toggle_event_mask(*(buf+1));
1076 diag_update_userspace_clients(EVENT_MASKS_TYPE);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001077#if defined(CONFIG_DIAG_OVER_USB)
1078 if (chk_apps_only()) {
1079 driver->apps_rsp_buf[0] = 0x60;
1080 driver->apps_rsp_buf[1] = 0x0;
1081 driver->apps_rsp_buf[2] = 0x0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001082 if (driver->ch_cntl)
1083 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001084 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001085 if (driver->chqdsp_cntl)
1086 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001087 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001088 if (driver->ch_wcnss_cntl)
1089 diag_send_event_mask_update(
1090 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001091 ENCODE_RSP_AND_SEND(2);
1092 return 0;
1093 }
1094#endif
1095 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001096 /* Check for registered clients and forward packet to apropriate proc */
1097 cmd_code = (int)(*(char *)buf);
1098 temp++;
1099 subsys_id = (int)(*(char *)temp);
1100 temp++;
1101 subsys_cmd_code = *(uint16_t *)temp;
1102 temp += 2;
1103 data_type = APPS_DATA;
1104 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301105 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001106 if (subsys_id != RESET_ID)
1107 data_type = MODEM_DATA;
1108 }
1109
1110 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001111 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001112 entry = driver->table[i];
1113 if (entry.process_id != NO_PROCESS) {
1114 if (entry.cmd_code == cmd_code && entry.subsys_id ==
1115 subsys_id && entry.cmd_code_lo <=
1116 subsys_cmd_code &&
1117 entry.cmd_code_hi >= subsys_cmd_code) {
1118 diag_send_data(entry, buf, len, data_type);
1119 packet_type = 0;
1120 } else if (entry.cmd_code == 255
1121 && cmd_code == 75) {
1122 if (entry.subsys_id ==
1123 subsys_id &&
1124 entry.cmd_code_lo <=
1125 subsys_cmd_code &&
1126 entry.cmd_code_hi >=
1127 subsys_cmd_code) {
1128 diag_send_data(entry, buf, len,
1129 data_type);
1130 packet_type = 0;
1131 }
1132 } else if (entry.cmd_code == 255 &&
1133 entry.subsys_id == 255) {
1134 if (entry.cmd_code_lo <=
1135 cmd_code &&
1136 entry.
1137 cmd_code_hi >= cmd_code) {
1138 diag_send_data(entry, buf, len,
1139 data_type);
1140 packet_type = 0;
1141 }
1142 }
1143 }
1144 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001145#if defined(CONFIG_DIAG_OVER_USB)
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001146 /* Check for Apps Only & get event mask request */
Shalabh Jain321c8b52012-02-22 12:37:06 -08001147 if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001148 driver->apps_rsp_buf[0] = 0x81;
1149 driver->apps_rsp_buf[1] = 0x0;
1150 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1151 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
1152 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
1153 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
1154 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1155 return 0;
1156 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001157 /* Get log ID range & Check for Apps Only */
1158 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001159 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
1160 driver->apps_rsp_buf[0] = 0x73;
1161 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
1162 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
1163 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
1164 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
1165 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
1166 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
1167 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
1168 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
1169 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
1170 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
1171 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
1172 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
1173 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
1174 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
1175 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
1176 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
1177 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
1178 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
1179 ENCODE_RSP_AND_SEND(75);
1180 return 0;
1181 }
1182 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001183 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001184 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
1185 driver->apps_rsp_buf[0] = 0x7d;
1186 driver->apps_rsp_buf[1] = 0x1;
1187 driver->apps_rsp_buf[2] = 0x1;
1188 driver->apps_rsp_buf[3] = 0x0;
1189 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
1190 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
1191 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
1192 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
1193 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
1194 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
1195 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
1196 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
1197 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
1198 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
1199 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
1200 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
1201 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
1202 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
1203 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
1204 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
1205 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
1206 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
1207 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
1208 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
1209 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
1210 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
1211 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
1212 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
1213 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
1214 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
1215 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
1216 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
1217 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
1218 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
1219 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
1220 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
1221 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
1222 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
1223 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
1224 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
1225 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
1226 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
1227 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001228 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
1229 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
1230 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
1231 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
1232 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
1233 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
1234 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
1235 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
1236 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001237 return 0;
1238 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001239 /* Check for Apps Only Respond to Get Subsys Build mask */
1240 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001241 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
1242 ssid_first = *(uint16_t *)(buf + 2);
1243 ssid_last = *(uint16_t *)(buf + 4);
1244 ssid_range = 4 * (ssid_last - ssid_first + 1);
1245 /* frame response */
1246 driver->apps_rsp_buf[0] = 0x7d;
1247 driver->apps_rsp_buf[1] = 0x2;
1248 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
1249 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
1250 driver->apps_rsp_buf[6] = 0x1;
1251 driver->apps_rsp_buf[7] = 0x0;
1252 ptr = driver->apps_rsp_buf + 8;
1253 /* bld time masks */
1254 switch (ssid_first) {
1255 case MSG_SSID_0:
1256 for (i = 0; i < ssid_range; i += 4)
1257 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
1258 break;
1259 case MSG_SSID_1:
1260 for (i = 0; i < ssid_range; i += 4)
1261 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
1262 break;
1263 case MSG_SSID_2:
1264 for (i = 0; i < ssid_range; i += 4)
1265 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
1266 break;
1267 case MSG_SSID_3:
1268 for (i = 0; i < ssid_range; i += 4)
1269 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
1270 break;
1271 case MSG_SSID_4:
1272 for (i = 0; i < ssid_range; i += 4)
1273 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
1274 break;
1275 case MSG_SSID_5:
1276 for (i = 0; i < ssid_range; i += 4)
1277 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
1278 break;
1279 case MSG_SSID_6:
1280 for (i = 0; i < ssid_range; i += 4)
1281 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
1282 break;
1283 case MSG_SSID_7:
1284 for (i = 0; i < ssid_range; i += 4)
1285 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
1286 break;
1287 case MSG_SSID_8:
1288 for (i = 0; i < ssid_range; i += 4)
1289 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
1290 break;
1291 case MSG_SSID_9:
1292 for (i = 0; i < ssid_range; i += 4)
1293 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
1294 break;
1295 case MSG_SSID_10:
1296 for (i = 0; i < ssid_range; i += 4)
1297 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
1298 break;
1299 case MSG_SSID_11:
1300 for (i = 0; i < ssid_range; i += 4)
1301 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
1302 break;
1303 case MSG_SSID_12:
1304 for (i = 0; i < ssid_range; i += 4)
1305 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1306 break;
1307 case MSG_SSID_13:
1308 for (i = 0; i < ssid_range; i += 4)
1309 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1310 break;
1311 case MSG_SSID_14:
1312 for (i = 0; i < ssid_range; i += 4)
1313 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1314 break;
1315 case MSG_SSID_15:
1316 for (i = 0; i < ssid_range; i += 4)
1317 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1318 break;
1319 case MSG_SSID_16:
1320 for (i = 0; i < ssid_range; i += 4)
1321 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1322 break;
1323 case MSG_SSID_17:
1324 for (i = 0; i < ssid_range; i += 4)
1325 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1326 break;
1327 case MSG_SSID_18:
1328 for (i = 0; i < ssid_range; i += 4)
1329 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1330 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001331 case MSG_SSID_19:
1332 for (i = 0; i < ssid_range; i += 4)
1333 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1334 break;
1335 case MSG_SSID_20:
1336 for (i = 0; i < ssid_range; i += 4)
1337 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1338 break;
1339 case MSG_SSID_21:
1340 for (i = 0; i < ssid_range; i += 4)
1341 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1342 break;
1343 case MSG_SSID_22:
1344 for (i = 0; i < ssid_range; i += 4)
1345 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1346 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001347 }
1348 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1349 return 0;
1350 }
1351 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301352 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001353 /* send response back */
1354 driver->apps_rsp_buf[0] = *buf;
1355 ENCODE_RSP_AND_SEND(0);
1356 msleep(5000);
1357 /* call download API */
1358 msm_set_restart_mode(RESTART_DLOAD);
1359 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1360 kernel_restart(NULL);
1361 /* Not required, represents that command isnt sent to modem */
1362 return 0;
1363 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001364 /* Check for polling for Apps only DIAG */
1365 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1366 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001367 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001368 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001369 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001370 for (i = 0; i < 3; i++)
1371 driver->apps_rsp_buf[i] = *(buf+i);
1372 for (i = 0; i < 13; i++)
1373 driver->apps_rsp_buf[i+3] = 0;
1374
1375 ENCODE_RSP_AND_SEND(15);
1376 return 0;
1377 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001378 }
1379 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001380 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001381 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001382 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001383 for (i = 0; i < 55; i++)
1384 driver->apps_rsp_buf[i] = 0;
1385
1386 ENCODE_RSP_AND_SEND(54);
1387 return 0;
1388 }
1389 /* respond to 0x7c command */
1390 else if (*buf == 0x7c) {
1391 driver->apps_rsp_buf[0] = 0x7c;
1392 for (i = 1; i < 8; i++)
1393 driver->apps_rsp_buf[i] = 0;
1394 /* Tools ID for APQ 8060 */
1395 *(int *)(driver->apps_rsp_buf + 8) =
1396 chk_config_get_id();
1397 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1398 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1399 ENCODE_RSP_AND_SEND(13);
1400 return 0;
1401 }
1402 }
1403#endif
1404 return packet_type;
1405}
1406
1407#ifdef CONFIG_DIAG_OVER_USB
1408void diag_send_error_rsp(int index)
1409{
1410 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301411
1412 if (index > 490) {
1413 pr_err("diag: error response too huge, aborting\n");
1414 return;
1415 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001416 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1417 for (i = 0; i < index; i++)
1418 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1419 ENCODE_RSP_AND_SEND(index - 3);
1420}
1421#else
1422static inline void diag_send_error_rsp(int index) {}
1423#endif
1424
1425void diag_process_hdlc(void *data, unsigned len)
1426{
1427 struct diag_hdlc_decode_type hdlc;
1428 int ret, type = 0;
1429 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1430 hdlc.dest_ptr = driver->hdlc_buf;
1431 hdlc.dest_size = USB_MAX_OUT_BUF;
1432 hdlc.src_ptr = data;
1433 hdlc.src_size = len;
1434 hdlc.src_idx = 0;
1435 hdlc.dest_idx = 0;
1436 hdlc.escaping = 0;
1437
1438 ret = diag_hdlc_decode(&hdlc);
1439
1440 if (ret)
1441 type = diag_process_apps_pkt(driver->hdlc_buf,
1442 hdlc.dest_idx - 3);
1443 else if (driver->debug_flag) {
1444 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1445 " errors or partial packet received, packet"
1446 " length = %d\n", len);
1447 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1448 DUMP_PREFIX_ADDRESS, data, len, 1);
1449 driver->debug_flag = 0;
1450 }
1451 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001452 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001453 diag_send_error_rsp(hdlc.dest_idx);
1454 type = 0;
1455 }
1456 /* implies this packet is NOT meant for apps */
1457 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001458 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001459 diag_send_error_rsp(hdlc.dest_idx);
1460 } else { /* APQ 8060, Let Q6 respond */
1461 if (driver->chqdsp)
1462 smd_write(driver->chqdsp, driver->hdlc_buf,
1463 hdlc.dest_idx - 3);
1464 }
1465 type = 0;
1466 }
1467
1468#ifdef DIAG_DEBUG
1469 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1470 for (i = 0; i < hdlc.dest_idx; i++)
1471 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1472 driver->hdlc_buf)+i));
1473#endif /* DIAG DEBUG */
1474 /* ignore 2 bytes for CRC, one for 7E and send */
1475 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1476 APPEND_DEBUG('g');
1477 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1478 APPEND_DEBUG('h');
1479#ifdef DIAG_DEBUG
1480 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1481 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1482 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1483#endif /* DIAG DEBUG */
1484 }
1485}
1486
1487#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001488/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1489#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001490#define N_LEGACY_READ 1
1491
1492int diagfwd_connect(void)
1493{
1494 int err;
1495
1496 printk(KERN_DEBUG "diag: USB connected\n");
1497 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1498 N_LEGACY_READ);
1499 if (err)
1500 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1501
1502 driver->usb_connected = 1;
1503 driver->in_busy_1 = 0;
1504 driver->in_busy_2 = 0;
1505 driver->in_busy_qdsp_1 = 0;
1506 driver->in_busy_qdsp_2 = 0;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301507 driver->in_busy_wcnss_1 = 0;
1508 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001509
1510 /* Poll SMD channels to check for data*/
1511 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1512 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1513 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001514 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001515 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1516 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1517 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001518 /* Poll USB channel to check for data*/
1519 queue_work(driver->diag_wq, &(driver->diag_read_work));
1520#ifdef CONFIG_DIAG_SDIO_PIPE
1521 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1522 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1523 diagfwd_connect_sdio();
1524 else
1525 printk(KERN_INFO "diag: No USB MDM ch");
1526 }
1527#endif
1528 return 0;
1529}
1530
1531int diagfwd_disconnect(void)
1532{
1533 printk(KERN_DEBUG "diag: USB disconnected\n");
1534 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001535 driver->debug_flag = 1;
1536 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001537 if (driver->logging_mode == USB_MODE) {
1538 driver->in_busy_1 = 1;
1539 driver->in_busy_2 = 1;
1540 driver->in_busy_qdsp_1 = 1;
1541 driver->in_busy_qdsp_2 = 1;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301542 driver->in_busy_wcnss_1 = 1;
1543 driver->in_busy_wcnss_2 = 1;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001544 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001545#ifdef CONFIG_DIAG_SDIO_PIPE
1546 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1547 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1548 diagfwd_disconnect_sdio();
1549#endif
1550 /* TBD - notify and flow control SMD */
1551 return 0;
1552}
1553
1554int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1555{
1556 unsigned char *buf = diag_write_ptr->buf;
1557 /*Determine if the write complete is for data from modem/apps/q6 */
1558 /* Need a context variable here instead */
1559 if (buf == (void *)driver->buf_in_1) {
1560 driver->in_busy_1 = 0;
1561 APPEND_DEBUG('o');
1562 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1563 } else if (buf == (void *)driver->buf_in_2) {
1564 driver->in_busy_2 = 0;
1565 APPEND_DEBUG('O');
1566 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1567 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1568 driver->in_busy_qdsp_1 = 0;
1569 APPEND_DEBUG('p');
1570 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1571 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1572 driver->in_busy_qdsp_2 = 0;
1573 APPEND_DEBUG('P');
1574 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
Ashay Jaiswal29620122012-03-21 12:02:36 +05301575 } else if (buf == driver->buf_in_wcnss_1) {
1576 driver->in_busy_wcnss_1 = 0;
1577 APPEND_DEBUG('r');
1578 queue_work(driver->diag_wq,
1579 &(driver->diag_read_smd_wcnss_work));
1580 } else if (buf == driver->buf_in_wcnss_2) {
1581 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001582 APPEND_DEBUG('R');
1583 queue_work(driver->diag_wq,
1584 &(driver->diag_read_smd_wcnss_work));
1585 }
1586#ifdef CONFIG_DIAG_SDIO_PIPE
1587 else if (buf == (void *)driver->buf_in_sdio)
1588 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001589 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001590 diagfwd_write_complete_sdio();
1591 else
1592 pr_err("diag: Incorrect buffer pointer while WRITE");
1593#endif
1594 else {
1595 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1596 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1597 POOL_TYPE_WRITE_STRUCT);
1598 APPEND_DEBUG('q');
1599 }
1600 return 0;
1601}
1602
1603int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1604{
1605 int status = diag_read_ptr->status;
1606 unsigned char *buf = diag_read_ptr->buf;
1607
1608 /* Determine if the read complete is for data on legacy/mdm ch */
1609 if (buf == (void *)driver->usb_buf_out) {
1610 driver->read_len_legacy = diag_read_ptr->actual;
1611 APPEND_DEBUG('s');
1612#ifdef DIAG_DEBUG
1613 printk(KERN_INFO "read data from USB, pkt length %d",
1614 diag_read_ptr->actual);
1615 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1616 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1617 diag_read_ptr->actual, 1);
1618#endif /* DIAG DEBUG */
1619 if (driver->logging_mode == USB_MODE) {
1620 if (status != -ECONNRESET && status != -ESHUTDOWN)
1621 queue_work(driver->diag_wq,
1622 &(driver->diag_proc_hdlc_work));
1623 else
1624 queue_work(driver->diag_wq,
1625 &(driver->diag_read_work));
1626 }
1627 }
1628#ifdef CONFIG_DIAG_SDIO_PIPE
1629 else if (buf == (void *)driver->usb_buf_mdm_out) {
1630 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001631 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001632 driver->read_len_mdm = diag_read_ptr->actual;
1633 diagfwd_read_complete_sdio();
1634 } else
1635 pr_err("diag: Incorrect buffer pointer while READ");
1636 }
1637#endif
1638 else
1639 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1640
1641 return 0;
1642}
1643
1644void diag_read_work_fn(struct work_struct *work)
1645{
1646 APPEND_DEBUG('d');
1647 driver->usb_read_ptr->buf = driver->usb_buf_out;
1648 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1649 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1650 APPEND_DEBUG('e');
1651}
1652
1653void diag_process_hdlc_fn(struct work_struct *work)
1654{
1655 APPEND_DEBUG('D');
1656 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1657 diag_read_work_fn(work);
1658 APPEND_DEBUG('E');
1659}
1660
1661void diag_usb_legacy_notifier(void *priv, unsigned event,
1662 struct diag_request *d_req)
1663{
1664 switch (event) {
1665 case USB_DIAG_CONNECT:
1666 diagfwd_connect();
1667 break;
1668 case USB_DIAG_DISCONNECT:
1669 diagfwd_disconnect();
1670 break;
1671 case USB_DIAG_READ_DONE:
1672 diagfwd_read_complete(d_req);
1673 break;
1674 case USB_DIAG_WRITE_DONE:
1675 diagfwd_write_complete(d_req);
1676 break;
1677 default:
1678 printk(KERN_ERR "Unknown event from USB diag\n");
1679 break;
1680 }
1681}
1682
1683#endif /* DIAG OVER USB */
1684
1685static void diag_smd_notify(void *ctxt, unsigned event)
1686{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001687 if (event == SMD_EVENT_CLOSE) {
1688 pr_info("diag: clean modem registration\n");
1689 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001690 driver->ch = 0;
1691 return;
1692 } else if (event == SMD_EVENT_OPEN) {
1693 driver->ch = ch_temp;
1694 }
1695 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001696}
1697
1698#if defined(CONFIG_MSM_N_WAY_SMD)
1699static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1700{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001701 if (event == SMD_EVENT_CLOSE) {
1702 pr_info("diag: clean lpass registration\n");
1703 diag_clear_reg(QDSP_PROC);
1704 driver->chqdsp = 0;
1705 return;
1706 } else if (event == SMD_EVENT_OPEN) {
1707 driver->chqdsp = chqdsp_temp;
1708 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001709 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1710}
1711#endif
1712
1713static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1714{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001715 if (event == SMD_EVENT_CLOSE) {
1716 pr_info("diag: clean wcnss registration\n");
1717 diag_clear_reg(WCNSS_PROC);
1718 driver->ch_wcnss = 0;
1719 return;
1720 } else if (event == SMD_EVENT_OPEN) {
1721 driver->ch_wcnss = ch_wcnss_temp;
1722 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001723 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1724}
1725
1726static int diag_smd_probe(struct platform_device *pdev)
1727{
1728 int r = 0;
1729
Shalabh Jaineefee052011-11-08 23:46:03 -08001730 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001731 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001732 ch_temp = driver->ch;
1733 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001734#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001735 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001736 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1737 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001738 chqdsp_temp = driver->chqdsp;
1739 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001740#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001741 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001742 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1743 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001744 ch_wcnss_temp = driver->ch_wcnss;
1745 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001746 pm_runtime_set_active(&pdev->dev);
1747 pm_runtime_enable(&pdev->dev);
1748 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1749
1750 return 0;
1751}
1752
1753static int diagfwd_runtime_suspend(struct device *dev)
1754{
1755 dev_dbg(dev, "pm_runtime: suspending...\n");
1756 return 0;
1757}
1758
1759static int diagfwd_runtime_resume(struct device *dev)
1760{
1761 dev_dbg(dev, "pm_runtime: resuming...\n");
1762 return 0;
1763}
1764
1765static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1766 .runtime_suspend = diagfwd_runtime_suspend,
1767 .runtime_resume = diagfwd_runtime_resume,
1768};
1769
1770static struct platform_driver msm_smd_ch1_driver = {
1771
1772 .probe = diag_smd_probe,
1773 .driver = {
1774 .name = "DIAG",
1775 .owner = THIS_MODULE,
1776 .pm = &diagfwd_dev_pm_ops,
1777 },
1778};
1779
1780static struct platform_driver diag_smd_lite_driver = {
1781
1782 .probe = diag_smd_probe,
1783 .driver = {
1784 .name = "APPS_RIVA_DATA",
1785 .owner = THIS_MODULE,
1786 .pm = &diagfwd_dev_pm_ops,
1787 },
1788};
1789
1790void diagfwd_init(void)
1791{
1792 diag_debug_buf_idx = 0;
1793 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001794 driver->use_device_tree = has_device_tree();
Shalabh Jainb6eda0e2012-04-18 16:39:52 -07001795 spin_lock_init(&diag_cntl_lock);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001796
1797 if (driver->event_mask == NULL) {
1798 driver->event_mask = kzalloc(sizeof(
1799 struct diag_ctrl_event_mask), GFP_KERNEL);
1800 if (driver->event_mask == NULL)
1801 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001802 kmemleak_not_leak(driver->event_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001803 }
1804 if (driver->msg_mask == NULL) {
1805 driver->msg_mask = kzalloc(sizeof(
1806 struct diag_ctrl_msg_mask), GFP_KERNEL);
1807 if (driver->msg_mask == NULL)
1808 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001809 kmemleak_not_leak(driver->msg_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001810 }
1811 if (driver->log_mask == NULL) {
1812 driver->log_mask = kzalloc(sizeof(
1813 struct diag_ctrl_log_mask), GFP_KERNEL);
1814 if (driver->log_mask == NULL)
1815 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001816 kmemleak_not_leak(driver->log_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001817 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001818 if (driver->buf_in_1 == NULL) {
1819 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1820 if (driver->buf_in_1 == NULL)
1821 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001822 kmemleak_not_leak(driver->buf_in_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001823 }
1824 if (driver->buf_in_2 == NULL) {
1825 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1826 if (driver->buf_in_2 == NULL)
1827 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001828 kmemleak_not_leak(driver->buf_in_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001829 }
1830 if (driver->buf_in_qdsp_1 == NULL) {
1831 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1832 if (driver->buf_in_qdsp_1 == NULL)
1833 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001834 kmemleak_not_leak(driver->buf_in_qdsp_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001835 }
1836 if (driver->buf_in_qdsp_2 == NULL) {
1837 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1838 if (driver->buf_in_qdsp_2 == NULL)
1839 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001840 kmemleak_not_leak(driver->buf_in_qdsp_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001841 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301842 if (driver->buf_in_wcnss_1 == NULL) {
1843 driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1844 if (driver->buf_in_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001845 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001846 kmemleak_not_leak(driver->buf_in_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001847 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301848 if (driver->buf_in_wcnss_2 == NULL) {
1849 driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1850 if (driver->buf_in_wcnss_2 == NULL)
1851 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001852 kmemleak_not_leak(driver->buf_in_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301853 }
1854
Shalabh Jain321c8b52012-02-22 12:37:06 -08001855 if (driver->buf_msg_mask_update == NULL) {
1856 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1857 GFP_KERNEL);
1858 if (driver->buf_msg_mask_update == NULL)
1859 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001860 kmemleak_not_leak(driver->buf_msg_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001861 }
1862 if (driver->buf_log_mask_update == NULL) {
1863 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1864 GFP_KERNEL);
1865 if (driver->buf_log_mask_update == NULL)
1866 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001867 kmemleak_not_leak(driver->buf_log_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001868 }
1869 if (driver->buf_event_mask_update == NULL) {
1870 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1871 GFP_KERNEL);
1872 if (driver->buf_event_mask_update == NULL)
1873 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001874 kmemleak_not_leak(driver->buf_event_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001875 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001876 if (driver->usb_buf_out == NULL &&
1877 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1878 GFP_KERNEL)) == NULL)
1879 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001880 kmemleak_not_leak(driver->usb_buf_out);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001881 if (driver->hdlc_buf == NULL
1882 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1883 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001884 kmemleak_not_leak(driver->hdlc_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001885 if (driver->user_space_data == NULL)
1886 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1887 if (driver->user_space_data == NULL)
1888 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001889 kmemleak_not_leak(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001890 if (driver->msg_masks == NULL
1891 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1892 GFP_KERNEL)) == NULL)
1893 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001894 kmemleak_not_leak(driver->msg_masks);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001895 diag_create_msg_mask_table();
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001896 diag_event_num_bytes = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001897 if (driver->log_masks == NULL &&
1898 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1899 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001900 kmemleak_not_leak(driver->log_masks);
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -07001901 driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001902 if (driver->event_masks == NULL &&
1903 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1904 GFP_KERNEL)) == NULL)
1905 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001906 kmemleak_not_leak(driver->event_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001907 if (driver->client_map == NULL &&
1908 (driver->client_map = kzalloc
1909 ((driver->num_clients) * sizeof(struct diag_client_map),
1910 GFP_KERNEL)) == NULL)
1911 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001912 kmemleak_not_leak(driver->client_map);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001913 if (driver->buf_tbl == NULL)
1914 driver->buf_tbl = kzalloc(buf_tbl_size *
1915 sizeof(struct diag_write_device), GFP_KERNEL);
1916 if (driver->buf_tbl == NULL)
1917 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001918 kmemleak_not_leak(driver->buf_tbl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001919 if (driver->data_ready == NULL &&
1920 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1921 , GFP_KERNEL)) == NULL)
1922 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001923 kmemleak_not_leak(driver->data_ready);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001924 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001925 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001926 sizeof(struct diag_master_table),
1927 GFP_KERNEL)) == NULL)
1928 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001929 kmemleak_not_leak(driver->table);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001930 if (driver->write_ptr_1 == NULL) {
1931 driver->write_ptr_1 = kzalloc(
1932 sizeof(struct diag_request), GFP_KERNEL);
1933 if (driver->write_ptr_1 == NULL)
1934 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001935 kmemleak_not_leak(driver->write_ptr_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001936 }
1937 if (driver->write_ptr_2 == NULL) {
1938 driver->write_ptr_2 = kzalloc(
1939 sizeof(struct diag_request), GFP_KERNEL);
1940 if (driver->write_ptr_2 == NULL)
1941 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001942 kmemleak_not_leak(driver->write_ptr_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001943 }
1944 if (driver->write_ptr_qdsp_1 == NULL) {
1945 driver->write_ptr_qdsp_1 = kzalloc(
1946 sizeof(struct diag_request), GFP_KERNEL);
1947 if (driver->write_ptr_qdsp_1 == NULL)
1948 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001949 kmemleak_not_leak(driver->write_ptr_qdsp_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001950 }
1951 if (driver->write_ptr_qdsp_2 == NULL) {
1952 driver->write_ptr_qdsp_2 = kzalloc(
1953 sizeof(struct diag_request), GFP_KERNEL);
1954 if (driver->write_ptr_qdsp_2 == NULL)
1955 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001956 kmemleak_not_leak(driver->write_ptr_qdsp_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001957 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301958 if (driver->write_ptr_wcnss_1 == NULL) {
1959 driver->write_ptr_wcnss_1 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001960 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301961 if (driver->write_ptr_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001962 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001963 kmemleak_not_leak(driver->write_ptr_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001964 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301965 if (driver->write_ptr_wcnss_2 == NULL) {
1966 driver->write_ptr_wcnss_2 = kzalloc(
1967 sizeof(struct diag_request), GFP_KERNEL);
1968 if (driver->write_ptr_wcnss_2 == NULL)
1969 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001970 kmemleak_not_leak(driver->write_ptr_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301971 }
1972
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001973 if (driver->usb_read_ptr == NULL) {
1974 driver->usb_read_ptr = kzalloc(
1975 sizeof(struct diag_request), GFP_KERNEL);
1976 if (driver->usb_read_ptr == NULL)
1977 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001978 kmemleak_not_leak(driver->usb_read_ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001979 }
1980 if (driver->pkt_buf == NULL &&
1981 (driver->pkt_buf = kzalloc(PKT_SIZE,
1982 GFP_KERNEL)) == NULL)
1983 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001984 kmemleak_not_leak(driver->pkt_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001985 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001986 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001987 if (driver->apps_rsp_buf == NULL)
1988 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001989 kmemleak_not_leak(driver->apps_rsp_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001990 }
1991 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1992#ifdef CONFIG_DIAG_OVER_USB
1993 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1994 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001995 INIT_WORK(&(driver->diag_modem_mask_update_work),
1996 diag_modem_mask_update_fn);
1997 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
1998 diag_qdsp_mask_update_fn);
1999 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
2000 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002001 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
2002 diag_usb_legacy_notifier);
2003 if (IS_ERR(driver->legacy_ch)) {
2004 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
2005 goto err;
2006 }
2007#endif
2008 platform_driver_register(&msm_smd_ch1_driver);
2009 platform_driver_register(&diag_smd_lite_driver);
2010
2011 return;
2012err:
2013 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08002014 kfree(driver->event_mask);
2015 kfree(driver->log_mask);
2016 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002017 kfree(driver->buf_in_1);
2018 kfree(driver->buf_in_2);
2019 kfree(driver->buf_in_qdsp_1);
2020 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302021 kfree(driver->buf_in_wcnss_1);
2022 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002023 kfree(driver->buf_msg_mask_update);
2024 kfree(driver->buf_log_mask_update);
2025 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002026 kfree(driver->usb_buf_out);
2027 kfree(driver->hdlc_buf);
2028 kfree(driver->msg_masks);
2029 kfree(driver->log_masks);
2030 kfree(driver->event_masks);
2031 kfree(driver->client_map);
2032 kfree(driver->buf_tbl);
2033 kfree(driver->data_ready);
2034 kfree(driver->table);
2035 kfree(driver->pkt_buf);
2036 kfree(driver->write_ptr_1);
2037 kfree(driver->write_ptr_2);
2038 kfree(driver->write_ptr_qdsp_1);
2039 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302040 kfree(driver->write_ptr_wcnss_1);
2041 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002042 kfree(driver->usb_read_ptr);
2043 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002044 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002045 if (driver->diag_wq)
2046 destroy_workqueue(driver->diag_wq);
2047}
2048
2049void diagfwd_exit(void)
2050{
2051 smd_close(driver->ch);
2052 smd_close(driver->chqdsp);
2053 smd_close(driver->ch_wcnss);
2054 driver->ch = 0; /* SMD can make this NULL */
2055 driver->chqdsp = 0;
2056 driver->ch_wcnss = 0;
2057#ifdef CONFIG_DIAG_OVER_USB
2058 if (driver->usb_connected)
2059 usb_diag_free_req(driver->legacy_ch);
2060 usb_diag_close(driver->legacy_ch);
2061#endif
2062 platform_driver_unregister(&msm_smd_ch1_driver);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -07002063 platform_driver_unregister(&msm_diag_dci_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002064 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002065 kfree(driver->event_mask);
2066 kfree(driver->log_mask);
2067 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002068 kfree(driver->buf_in_1);
2069 kfree(driver->buf_in_2);
2070 kfree(driver->buf_in_qdsp_1);
2071 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302072 kfree(driver->buf_in_wcnss_1);
2073 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002074 kfree(driver->buf_msg_mask_update);
2075 kfree(driver->buf_log_mask_update);
2076 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002077 kfree(driver->usb_buf_out);
2078 kfree(driver->hdlc_buf);
2079 kfree(driver->msg_masks);
2080 kfree(driver->log_masks);
2081 kfree(driver->event_masks);
2082 kfree(driver->client_map);
2083 kfree(driver->buf_tbl);
2084 kfree(driver->data_ready);
2085 kfree(driver->table);
2086 kfree(driver->pkt_buf);
2087 kfree(driver->write_ptr_1);
2088 kfree(driver->write_ptr_2);
2089 kfree(driver->write_ptr_qdsp_1);
2090 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302091 kfree(driver->write_ptr_wcnss_1);
2092 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002093 kfree(driver->usb_read_ptr);
2094 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002095 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002096 destroy_workqueue(driver->diag_wq);
2097}