blob: 4d3fc293285137f190918483adf8ace08f4a44f7 [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) {
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700965 /* Disable mask for each log code */
966 diag_disable_log_mask();
967 diag_update_userspace_clients(LOG_MASKS_TYPE);
968#if defined(CONFIG_DIAG_OVER_USB)
969 if (chk_apps_only()) {
970 driver->apps_rsp_buf[0] = 0x73;
971 driver->apps_rsp_buf[1] = 0x0;
972 driver->apps_rsp_buf[2] = 0x0;
973 driver->apps_rsp_buf[3] = 0x0;
974 *(int *)(driver->apps_rsp_buf + 4) = 0x0;
975 if (driver->ch_cntl)
976 diag_send_log_mask_update(driver->ch_cntl,
Dixon Petersona73bb992012-05-05 18:00:40 -0700977 ALL_EQUIP_ID);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700978 if (driver->chqdsp_cntl)
979 diag_send_log_mask_update(driver->chqdsp_cntl,
Dixon Petersona73bb992012-05-05 18:00:40 -0700980 ALL_EQUIP_ID);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700981 if (driver->ch_wcnss_cntl)
982 diag_send_log_mask_update(driver->ch_wcnss_cntl,
Dixon Petersona73bb992012-05-05 18:00:40 -0700983 ALL_EQUIP_ID);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700984 ENCODE_RSP_AND_SEND(7);
985 return 0;
Dixon Petersona73bb992012-05-05 18:00:40 -0700986 }
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700987#endif
988 } /* Set runtime message mask */
Shalabh Jain321c8b52012-02-22 12:37:06 -0800989 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
990 ssid_first = *(uint16_t *)(buf + 2);
991 ssid_last = *(uint16_t *)(buf + 4);
992 ssid_range = 4 * (ssid_last - ssid_first + 1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700993 pr_debug("diag: received mask update for ssid_first = %d,"
994 " ssid_last = %d", ssid_first, ssid_last);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800995 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
996 diag_update_userspace_clients(MSG_MASKS_TYPE);
997#if defined(CONFIG_DIAG_OVER_USB)
998 if (chk_apps_only()) {
999 for (i = 0; i < 8 + ssid_range; i++)
1000 *(driver->apps_rsp_buf + i) = *(buf+i);
1001 *(driver->apps_rsp_buf + 6) = 0x1;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001002 if (driver->ch_cntl)
1003 diag_send_msg_mask_update(driver->ch_cntl,
1004 ssid_first, ssid_last, MODEM_PROC);
1005 if (driver->chqdsp_cntl)
1006 diag_send_msg_mask_update(driver->chqdsp_cntl,
1007 ssid_first, ssid_last, QDSP_PROC);
1008 if (driver->ch_wcnss_cntl)
1009 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1010 ssid_first, ssid_last, WCNSS_PROC);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001011 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1012 return 0;
1013 } else
1014 buf = temp;
1015#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001016 } /* Set ALL runtime message mask */
1017 else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
1018 rt_mask = *(int *)(buf + 4);
1019 diag_set_msg_mask(rt_mask);
1020 diag_update_userspace_clients(MSG_MASKS_TYPE);
1021#if defined(CONFIG_DIAG_OVER_USB)
1022 if (chk_apps_only()) {
1023 driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
1024 driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
1025 driver->apps_rsp_buf[2] = 1; /* success */
1026 driver->apps_rsp_buf[3] = 0; /* rsvd */
1027 *(int *)(driver->apps_rsp_buf + 4) = rt_mask;
1028 /* send msg mask update to peripheral */
1029 if (driver->ch_cntl)
1030 diag_send_msg_mask_update(driver->ch_cntl,
1031 ALL_SSID, ALL_SSID, MODEM_PROC);
1032 if (driver->chqdsp_cntl)
1033 diag_send_msg_mask_update(driver->chqdsp_cntl,
1034 ALL_SSID, ALL_SSID, QDSP_PROC);
1035 if (driver->ch_wcnss_cntl)
1036 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1037 ALL_SSID, ALL_SSID, WCNSS_PROC);
1038 ENCODE_RSP_AND_SEND(7);
1039 return 0;
1040 } else
1041 buf = temp;
1042#endif
Shalabh Jain321c8b52012-02-22 12:37:06 -08001043 } else if (*buf == 0x82) { /* event mask change */
1044 buf += 4;
1045 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
1046 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
1047 diag_update_userspace_clients(EVENT_MASKS_TYPE);
1048#if defined(CONFIG_DIAG_OVER_USB)
1049 if (chk_apps_only()) {
1050 driver->apps_rsp_buf[0] = 0x82;
1051 driver->apps_rsp_buf[1] = 0x0;
1052 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1053 *(uint16_t *)(driver->apps_rsp_buf + 4) =
1054 EVENT_LAST_ID + 1;
Shalabh Jaina51f2592012-03-08 14:36:35 -08001055 memcpy(driver->apps_rsp_buf+6, driver->event_masks,
1056 EVENT_LAST_ID/8+1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001057 if (driver->ch_cntl)
1058 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001059 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001060 if (driver->chqdsp_cntl)
1061 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001062 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001063 if (driver->ch_wcnss_cntl)
1064 diag_send_event_mask_update(
1065 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001066 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1067 return 0;
1068 } else
1069 buf = temp;
1070#endif
1071 } else if (*buf == 0x60) {
1072 diag_event_config = *(buf+1);
Shalabh Jaina51f2592012-03-08 14:36:35 -08001073 diag_toggle_event_mask(*(buf+1));
1074 diag_update_userspace_clients(EVENT_MASKS_TYPE);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001075#if defined(CONFIG_DIAG_OVER_USB)
1076 if (chk_apps_only()) {
1077 driver->apps_rsp_buf[0] = 0x60;
1078 driver->apps_rsp_buf[1] = 0x0;
1079 driver->apps_rsp_buf[2] = 0x0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001080 if (driver->ch_cntl)
1081 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001082 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001083 if (driver->chqdsp_cntl)
1084 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001085 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001086 if (driver->ch_wcnss_cntl)
1087 diag_send_event_mask_update(
1088 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001089 ENCODE_RSP_AND_SEND(2);
1090 return 0;
1091 }
1092#endif
1093 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001094 /* Check for registered clients and forward packet to apropriate proc */
1095 cmd_code = (int)(*(char *)buf);
1096 temp++;
1097 subsys_id = (int)(*(char *)temp);
1098 temp++;
1099 subsys_cmd_code = *(uint16_t *)temp;
1100 temp += 2;
1101 data_type = APPS_DATA;
1102 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301103 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001104 if (subsys_id != RESET_ID)
1105 data_type = MODEM_DATA;
1106 }
1107
1108 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001109 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001110 entry = driver->table[i];
1111 if (entry.process_id != NO_PROCESS) {
1112 if (entry.cmd_code == cmd_code && entry.subsys_id ==
1113 subsys_id && entry.cmd_code_lo <=
1114 subsys_cmd_code &&
1115 entry.cmd_code_hi >= subsys_cmd_code) {
1116 diag_send_data(entry, buf, len, data_type);
1117 packet_type = 0;
1118 } else if (entry.cmd_code == 255
1119 && cmd_code == 75) {
1120 if (entry.subsys_id ==
1121 subsys_id &&
1122 entry.cmd_code_lo <=
1123 subsys_cmd_code &&
1124 entry.cmd_code_hi >=
1125 subsys_cmd_code) {
1126 diag_send_data(entry, buf, len,
1127 data_type);
1128 packet_type = 0;
1129 }
1130 } else if (entry.cmd_code == 255 &&
1131 entry.subsys_id == 255) {
1132 if (entry.cmd_code_lo <=
1133 cmd_code &&
1134 entry.
1135 cmd_code_hi >= cmd_code) {
1136 diag_send_data(entry, buf, len,
1137 data_type);
1138 packet_type = 0;
1139 }
1140 }
1141 }
1142 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001143#if defined(CONFIG_DIAG_OVER_USB)
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001144 /* Check for Apps Only & get event mask request */
Shalabh Jain321c8b52012-02-22 12:37:06 -08001145 if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001146 driver->apps_rsp_buf[0] = 0x81;
1147 driver->apps_rsp_buf[1] = 0x0;
1148 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1149 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
1150 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
1151 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
1152 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1153 return 0;
1154 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001155 /* Get log ID range & Check for Apps Only */
1156 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001157 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
1158 driver->apps_rsp_buf[0] = 0x73;
1159 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
1160 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
1161 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
1162 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
1163 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
1164 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
1165 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
1166 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
1167 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
1168 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
1169 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
1170 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
1171 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
1172 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
1173 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
1174 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
1175 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
1176 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
1177 ENCODE_RSP_AND_SEND(75);
1178 return 0;
1179 }
1180 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001181 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001182 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
1183 driver->apps_rsp_buf[0] = 0x7d;
1184 driver->apps_rsp_buf[1] = 0x1;
1185 driver->apps_rsp_buf[2] = 0x1;
1186 driver->apps_rsp_buf[3] = 0x0;
1187 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
1188 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
1189 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
1190 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
1191 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
1192 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
1193 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
1194 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
1195 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
1196 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
1197 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
1198 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
1199 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
1200 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
1201 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
1202 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
1203 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
1204 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
1205 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
1206 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
1207 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
1208 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
1209 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
1210 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
1211 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
1212 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
1213 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
1214 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
1215 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
1216 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
1217 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
1218 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
1219 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
1220 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
1221 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
1222 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
1223 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
1224 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
1225 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001226 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
1227 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
1228 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
1229 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
1230 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
1231 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
1232 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
1233 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
1234 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001235 return 0;
1236 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001237 /* Check for Apps Only Respond to Get Subsys Build mask */
1238 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001239 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
1240 ssid_first = *(uint16_t *)(buf + 2);
1241 ssid_last = *(uint16_t *)(buf + 4);
1242 ssid_range = 4 * (ssid_last - ssid_first + 1);
1243 /* frame response */
1244 driver->apps_rsp_buf[0] = 0x7d;
1245 driver->apps_rsp_buf[1] = 0x2;
1246 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
1247 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
1248 driver->apps_rsp_buf[6] = 0x1;
1249 driver->apps_rsp_buf[7] = 0x0;
1250 ptr = driver->apps_rsp_buf + 8;
1251 /* bld time masks */
1252 switch (ssid_first) {
1253 case MSG_SSID_0:
1254 for (i = 0; i < ssid_range; i += 4)
1255 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
1256 break;
1257 case MSG_SSID_1:
1258 for (i = 0; i < ssid_range; i += 4)
1259 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
1260 break;
1261 case MSG_SSID_2:
1262 for (i = 0; i < ssid_range; i += 4)
1263 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
1264 break;
1265 case MSG_SSID_3:
1266 for (i = 0; i < ssid_range; i += 4)
1267 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
1268 break;
1269 case MSG_SSID_4:
1270 for (i = 0; i < ssid_range; i += 4)
1271 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
1272 break;
1273 case MSG_SSID_5:
1274 for (i = 0; i < ssid_range; i += 4)
1275 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
1276 break;
1277 case MSG_SSID_6:
1278 for (i = 0; i < ssid_range; i += 4)
1279 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
1280 break;
1281 case MSG_SSID_7:
1282 for (i = 0; i < ssid_range; i += 4)
1283 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
1284 break;
1285 case MSG_SSID_8:
1286 for (i = 0; i < ssid_range; i += 4)
1287 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
1288 break;
1289 case MSG_SSID_9:
1290 for (i = 0; i < ssid_range; i += 4)
1291 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
1292 break;
1293 case MSG_SSID_10:
1294 for (i = 0; i < ssid_range; i += 4)
1295 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
1296 break;
1297 case MSG_SSID_11:
1298 for (i = 0; i < ssid_range; i += 4)
1299 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
1300 break;
1301 case MSG_SSID_12:
1302 for (i = 0; i < ssid_range; i += 4)
1303 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1304 break;
1305 case MSG_SSID_13:
1306 for (i = 0; i < ssid_range; i += 4)
1307 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1308 break;
1309 case MSG_SSID_14:
1310 for (i = 0; i < ssid_range; i += 4)
1311 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1312 break;
1313 case MSG_SSID_15:
1314 for (i = 0; i < ssid_range; i += 4)
1315 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1316 break;
1317 case MSG_SSID_16:
1318 for (i = 0; i < ssid_range; i += 4)
1319 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1320 break;
1321 case MSG_SSID_17:
1322 for (i = 0; i < ssid_range; i += 4)
1323 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1324 break;
1325 case MSG_SSID_18:
1326 for (i = 0; i < ssid_range; i += 4)
1327 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1328 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001329 case MSG_SSID_19:
1330 for (i = 0; i < ssid_range; i += 4)
1331 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1332 break;
1333 case MSG_SSID_20:
1334 for (i = 0; i < ssid_range; i += 4)
1335 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1336 break;
1337 case MSG_SSID_21:
1338 for (i = 0; i < ssid_range; i += 4)
1339 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1340 break;
1341 case MSG_SSID_22:
1342 for (i = 0; i < ssid_range; i += 4)
1343 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1344 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001345 }
1346 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1347 return 0;
1348 }
1349 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301350 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001351 /* send response back */
1352 driver->apps_rsp_buf[0] = *buf;
1353 ENCODE_RSP_AND_SEND(0);
1354 msleep(5000);
1355 /* call download API */
1356 msm_set_restart_mode(RESTART_DLOAD);
1357 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1358 kernel_restart(NULL);
1359 /* Not required, represents that command isnt sent to modem */
1360 return 0;
1361 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001362 /* Check for polling for Apps only DIAG */
1363 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1364 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001365 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001366 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001367 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001368 for (i = 0; i < 3; i++)
1369 driver->apps_rsp_buf[i] = *(buf+i);
1370 for (i = 0; i < 13; i++)
1371 driver->apps_rsp_buf[i+3] = 0;
1372
1373 ENCODE_RSP_AND_SEND(15);
1374 return 0;
1375 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001376 }
1377 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001378 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001379 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001380 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001381 for (i = 0; i < 55; i++)
1382 driver->apps_rsp_buf[i] = 0;
1383
1384 ENCODE_RSP_AND_SEND(54);
1385 return 0;
1386 }
1387 /* respond to 0x7c command */
1388 else if (*buf == 0x7c) {
1389 driver->apps_rsp_buf[0] = 0x7c;
1390 for (i = 1; i < 8; i++)
1391 driver->apps_rsp_buf[i] = 0;
1392 /* Tools ID for APQ 8060 */
1393 *(int *)(driver->apps_rsp_buf + 8) =
1394 chk_config_get_id();
1395 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1396 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1397 ENCODE_RSP_AND_SEND(13);
1398 return 0;
1399 }
1400 }
1401#endif
1402 return packet_type;
1403}
1404
1405#ifdef CONFIG_DIAG_OVER_USB
1406void diag_send_error_rsp(int index)
1407{
1408 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301409
1410 if (index > 490) {
1411 pr_err("diag: error response too huge, aborting\n");
1412 return;
1413 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001414 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1415 for (i = 0; i < index; i++)
1416 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1417 ENCODE_RSP_AND_SEND(index - 3);
1418}
1419#else
1420static inline void diag_send_error_rsp(int index) {}
1421#endif
1422
1423void diag_process_hdlc(void *data, unsigned len)
1424{
1425 struct diag_hdlc_decode_type hdlc;
1426 int ret, type = 0;
1427 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1428 hdlc.dest_ptr = driver->hdlc_buf;
1429 hdlc.dest_size = USB_MAX_OUT_BUF;
1430 hdlc.src_ptr = data;
1431 hdlc.src_size = len;
1432 hdlc.src_idx = 0;
1433 hdlc.dest_idx = 0;
1434 hdlc.escaping = 0;
1435
1436 ret = diag_hdlc_decode(&hdlc);
1437
1438 if (ret)
1439 type = diag_process_apps_pkt(driver->hdlc_buf,
1440 hdlc.dest_idx - 3);
1441 else if (driver->debug_flag) {
1442 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1443 " errors or partial packet received, packet"
1444 " length = %d\n", len);
1445 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1446 DUMP_PREFIX_ADDRESS, data, len, 1);
1447 driver->debug_flag = 0;
1448 }
1449 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001450 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001451 diag_send_error_rsp(hdlc.dest_idx);
1452 type = 0;
1453 }
1454 /* implies this packet is NOT meant for apps */
1455 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001456 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001457 diag_send_error_rsp(hdlc.dest_idx);
1458 } else { /* APQ 8060, Let Q6 respond */
1459 if (driver->chqdsp)
1460 smd_write(driver->chqdsp, driver->hdlc_buf,
1461 hdlc.dest_idx - 3);
1462 }
1463 type = 0;
1464 }
1465
1466#ifdef DIAG_DEBUG
1467 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1468 for (i = 0; i < hdlc.dest_idx; i++)
1469 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1470 driver->hdlc_buf)+i));
1471#endif /* DIAG DEBUG */
1472 /* ignore 2 bytes for CRC, one for 7E and send */
1473 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1474 APPEND_DEBUG('g');
1475 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1476 APPEND_DEBUG('h');
1477#ifdef DIAG_DEBUG
1478 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1479 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1480 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1481#endif /* DIAG DEBUG */
1482 }
1483}
1484
1485#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001486/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1487#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001488#define N_LEGACY_READ 1
1489
1490int diagfwd_connect(void)
1491{
1492 int err;
1493
1494 printk(KERN_DEBUG "diag: USB connected\n");
1495 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1496 N_LEGACY_READ);
1497 if (err)
1498 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1499
1500 driver->usb_connected = 1;
1501 driver->in_busy_1 = 0;
1502 driver->in_busy_2 = 0;
1503 driver->in_busy_qdsp_1 = 0;
1504 driver->in_busy_qdsp_2 = 0;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301505 driver->in_busy_wcnss_1 = 0;
1506 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001507
1508 /* Poll SMD channels to check for data*/
1509 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1510 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1511 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001512 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001513 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1514 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1515 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001516 /* Poll USB channel to check for data*/
1517 queue_work(driver->diag_wq, &(driver->diag_read_work));
1518#ifdef CONFIG_DIAG_SDIO_PIPE
1519 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1520 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1521 diagfwd_connect_sdio();
1522 else
1523 printk(KERN_INFO "diag: No USB MDM ch");
1524 }
1525#endif
1526 return 0;
1527}
1528
1529int diagfwd_disconnect(void)
1530{
1531 printk(KERN_DEBUG "diag: USB disconnected\n");
1532 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001533 driver->debug_flag = 1;
1534 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001535 if (driver->logging_mode == USB_MODE) {
1536 driver->in_busy_1 = 1;
1537 driver->in_busy_2 = 1;
1538 driver->in_busy_qdsp_1 = 1;
1539 driver->in_busy_qdsp_2 = 1;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301540 driver->in_busy_wcnss_1 = 1;
1541 driver->in_busy_wcnss_2 = 1;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001542 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001543#ifdef CONFIG_DIAG_SDIO_PIPE
1544 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1545 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1546 diagfwd_disconnect_sdio();
1547#endif
1548 /* TBD - notify and flow control SMD */
1549 return 0;
1550}
1551
1552int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1553{
1554 unsigned char *buf = diag_write_ptr->buf;
1555 /*Determine if the write complete is for data from modem/apps/q6 */
1556 /* Need a context variable here instead */
1557 if (buf == (void *)driver->buf_in_1) {
1558 driver->in_busy_1 = 0;
1559 APPEND_DEBUG('o');
1560 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1561 } else if (buf == (void *)driver->buf_in_2) {
1562 driver->in_busy_2 = 0;
1563 APPEND_DEBUG('O');
1564 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1565 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1566 driver->in_busy_qdsp_1 = 0;
1567 APPEND_DEBUG('p');
1568 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1569 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1570 driver->in_busy_qdsp_2 = 0;
1571 APPEND_DEBUG('P');
1572 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
Ashay Jaiswal29620122012-03-21 12:02:36 +05301573 } else if (buf == driver->buf_in_wcnss_1) {
1574 driver->in_busy_wcnss_1 = 0;
1575 APPEND_DEBUG('r');
1576 queue_work(driver->diag_wq,
1577 &(driver->diag_read_smd_wcnss_work));
1578 } else if (buf == driver->buf_in_wcnss_2) {
1579 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001580 APPEND_DEBUG('R');
1581 queue_work(driver->diag_wq,
1582 &(driver->diag_read_smd_wcnss_work));
1583 }
1584#ifdef CONFIG_DIAG_SDIO_PIPE
1585 else if (buf == (void *)driver->buf_in_sdio)
1586 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001587 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001588 diagfwd_write_complete_sdio();
1589 else
1590 pr_err("diag: Incorrect buffer pointer while WRITE");
1591#endif
1592 else {
1593 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1594 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1595 POOL_TYPE_WRITE_STRUCT);
1596 APPEND_DEBUG('q');
1597 }
1598 return 0;
1599}
1600
1601int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1602{
1603 int status = diag_read_ptr->status;
1604 unsigned char *buf = diag_read_ptr->buf;
1605
1606 /* Determine if the read complete is for data on legacy/mdm ch */
1607 if (buf == (void *)driver->usb_buf_out) {
1608 driver->read_len_legacy = diag_read_ptr->actual;
1609 APPEND_DEBUG('s');
1610#ifdef DIAG_DEBUG
1611 printk(KERN_INFO "read data from USB, pkt length %d",
1612 diag_read_ptr->actual);
1613 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1614 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1615 diag_read_ptr->actual, 1);
1616#endif /* DIAG DEBUG */
1617 if (driver->logging_mode == USB_MODE) {
1618 if (status != -ECONNRESET && status != -ESHUTDOWN)
1619 queue_work(driver->diag_wq,
1620 &(driver->diag_proc_hdlc_work));
1621 else
1622 queue_work(driver->diag_wq,
1623 &(driver->diag_read_work));
1624 }
1625 }
1626#ifdef CONFIG_DIAG_SDIO_PIPE
1627 else if (buf == (void *)driver->usb_buf_mdm_out) {
1628 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001629 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001630 driver->read_len_mdm = diag_read_ptr->actual;
1631 diagfwd_read_complete_sdio();
1632 } else
1633 pr_err("diag: Incorrect buffer pointer while READ");
1634 }
1635#endif
1636 else
1637 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1638
1639 return 0;
1640}
1641
1642void diag_read_work_fn(struct work_struct *work)
1643{
1644 APPEND_DEBUG('d');
1645 driver->usb_read_ptr->buf = driver->usb_buf_out;
1646 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1647 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1648 APPEND_DEBUG('e');
1649}
1650
1651void diag_process_hdlc_fn(struct work_struct *work)
1652{
1653 APPEND_DEBUG('D');
1654 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1655 diag_read_work_fn(work);
1656 APPEND_DEBUG('E');
1657}
1658
1659void diag_usb_legacy_notifier(void *priv, unsigned event,
1660 struct diag_request *d_req)
1661{
1662 switch (event) {
1663 case USB_DIAG_CONNECT:
1664 diagfwd_connect();
1665 break;
1666 case USB_DIAG_DISCONNECT:
1667 diagfwd_disconnect();
1668 break;
1669 case USB_DIAG_READ_DONE:
1670 diagfwd_read_complete(d_req);
1671 break;
1672 case USB_DIAG_WRITE_DONE:
1673 diagfwd_write_complete(d_req);
1674 break;
1675 default:
1676 printk(KERN_ERR "Unknown event from USB diag\n");
1677 break;
1678 }
1679}
1680
1681#endif /* DIAG OVER USB */
1682
1683static void diag_smd_notify(void *ctxt, unsigned event)
1684{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001685 if (event == SMD_EVENT_CLOSE) {
1686 pr_info("diag: clean modem registration\n");
1687 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001688 driver->ch = 0;
1689 return;
1690 } else if (event == SMD_EVENT_OPEN) {
1691 driver->ch = ch_temp;
1692 }
1693 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001694}
1695
1696#if defined(CONFIG_MSM_N_WAY_SMD)
1697static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1698{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001699 if (event == SMD_EVENT_CLOSE) {
1700 pr_info("diag: clean lpass registration\n");
1701 diag_clear_reg(QDSP_PROC);
1702 driver->chqdsp = 0;
1703 return;
1704 } else if (event == SMD_EVENT_OPEN) {
1705 driver->chqdsp = chqdsp_temp;
1706 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001707 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1708}
1709#endif
1710
1711static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1712{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001713 if (event == SMD_EVENT_CLOSE) {
1714 pr_info("diag: clean wcnss registration\n");
1715 diag_clear_reg(WCNSS_PROC);
1716 driver->ch_wcnss = 0;
1717 return;
1718 } else if (event == SMD_EVENT_OPEN) {
1719 driver->ch_wcnss = ch_wcnss_temp;
1720 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001721 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1722}
1723
1724static int diag_smd_probe(struct platform_device *pdev)
1725{
1726 int r = 0;
1727
Shalabh Jaineefee052011-11-08 23:46:03 -08001728 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001729 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001730 ch_temp = driver->ch;
1731 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001732#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001733 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001734 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1735 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001736 chqdsp_temp = driver->chqdsp;
1737 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001738#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001739 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001740 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1741 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001742 ch_wcnss_temp = driver->ch_wcnss;
1743 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001744 pm_runtime_set_active(&pdev->dev);
1745 pm_runtime_enable(&pdev->dev);
1746 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1747
1748 return 0;
1749}
1750
1751static int diagfwd_runtime_suspend(struct device *dev)
1752{
1753 dev_dbg(dev, "pm_runtime: suspending...\n");
1754 return 0;
1755}
1756
1757static int diagfwd_runtime_resume(struct device *dev)
1758{
1759 dev_dbg(dev, "pm_runtime: resuming...\n");
1760 return 0;
1761}
1762
1763static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1764 .runtime_suspend = diagfwd_runtime_suspend,
1765 .runtime_resume = diagfwd_runtime_resume,
1766};
1767
1768static struct platform_driver msm_smd_ch1_driver = {
1769
1770 .probe = diag_smd_probe,
1771 .driver = {
1772 .name = "DIAG",
1773 .owner = THIS_MODULE,
1774 .pm = &diagfwd_dev_pm_ops,
1775 },
1776};
1777
1778static struct platform_driver diag_smd_lite_driver = {
1779
1780 .probe = diag_smd_probe,
1781 .driver = {
1782 .name = "APPS_RIVA_DATA",
1783 .owner = THIS_MODULE,
1784 .pm = &diagfwd_dev_pm_ops,
1785 },
1786};
1787
1788void diagfwd_init(void)
1789{
1790 diag_debug_buf_idx = 0;
1791 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001792 driver->use_device_tree = has_device_tree();
Shalabh Jainb6eda0e2012-04-18 16:39:52 -07001793 spin_lock_init(&diag_cntl_lock);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001794
1795 if (driver->event_mask == NULL) {
1796 driver->event_mask = kzalloc(sizeof(
1797 struct diag_ctrl_event_mask), GFP_KERNEL);
1798 if (driver->event_mask == NULL)
1799 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001800 kmemleak_not_leak(driver->event_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001801 }
1802 if (driver->msg_mask == NULL) {
1803 driver->msg_mask = kzalloc(sizeof(
1804 struct diag_ctrl_msg_mask), GFP_KERNEL);
1805 if (driver->msg_mask == NULL)
1806 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001807 kmemleak_not_leak(driver->msg_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001808 }
1809 if (driver->log_mask == NULL) {
1810 driver->log_mask = kzalloc(sizeof(
1811 struct diag_ctrl_log_mask), GFP_KERNEL);
1812 if (driver->log_mask == NULL)
1813 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001814 kmemleak_not_leak(driver->log_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001815 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001816 if (driver->buf_in_1 == NULL) {
1817 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1818 if (driver->buf_in_1 == NULL)
1819 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001820 kmemleak_not_leak(driver->buf_in_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001821 }
1822 if (driver->buf_in_2 == NULL) {
1823 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1824 if (driver->buf_in_2 == NULL)
1825 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001826 kmemleak_not_leak(driver->buf_in_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001827 }
1828 if (driver->buf_in_qdsp_1 == NULL) {
1829 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1830 if (driver->buf_in_qdsp_1 == NULL)
1831 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001832 kmemleak_not_leak(driver->buf_in_qdsp_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001833 }
1834 if (driver->buf_in_qdsp_2 == NULL) {
1835 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1836 if (driver->buf_in_qdsp_2 == NULL)
1837 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001838 kmemleak_not_leak(driver->buf_in_qdsp_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001839 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301840 if (driver->buf_in_wcnss_1 == NULL) {
1841 driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1842 if (driver->buf_in_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001843 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001844 kmemleak_not_leak(driver->buf_in_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001845 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301846 if (driver->buf_in_wcnss_2 == NULL) {
1847 driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1848 if (driver->buf_in_wcnss_2 == NULL)
1849 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001850 kmemleak_not_leak(driver->buf_in_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301851 }
1852
Shalabh Jain321c8b52012-02-22 12:37:06 -08001853 if (driver->buf_msg_mask_update == NULL) {
1854 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1855 GFP_KERNEL);
1856 if (driver->buf_msg_mask_update == NULL)
1857 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001858 kmemleak_not_leak(driver->buf_msg_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001859 }
1860 if (driver->buf_log_mask_update == NULL) {
1861 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1862 GFP_KERNEL);
1863 if (driver->buf_log_mask_update == NULL)
1864 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001865 kmemleak_not_leak(driver->buf_log_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001866 }
1867 if (driver->buf_event_mask_update == NULL) {
1868 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1869 GFP_KERNEL);
1870 if (driver->buf_event_mask_update == NULL)
1871 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001872 kmemleak_not_leak(driver->buf_event_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001873 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001874 if (driver->usb_buf_out == NULL &&
1875 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1876 GFP_KERNEL)) == NULL)
1877 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001878 kmemleak_not_leak(driver->usb_buf_out);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001879 if (driver->hdlc_buf == NULL
1880 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1881 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001882 kmemleak_not_leak(driver->hdlc_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001883 if (driver->user_space_data == NULL)
1884 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1885 if (driver->user_space_data == NULL)
1886 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001887 kmemleak_not_leak(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001888 if (driver->msg_masks == NULL
1889 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1890 GFP_KERNEL)) == NULL)
1891 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001892 kmemleak_not_leak(driver->msg_masks);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001893 diag_create_msg_mask_table();
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001894 diag_event_num_bytes = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001895 if (driver->log_masks == NULL &&
1896 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1897 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001898 kmemleak_not_leak(driver->log_masks);
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -07001899 driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001900 if (driver->event_masks == NULL &&
1901 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1902 GFP_KERNEL)) == NULL)
1903 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001904 kmemleak_not_leak(driver->event_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001905 if (driver->client_map == NULL &&
1906 (driver->client_map = kzalloc
1907 ((driver->num_clients) * sizeof(struct diag_client_map),
1908 GFP_KERNEL)) == NULL)
1909 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001910 kmemleak_not_leak(driver->client_map);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001911 if (driver->buf_tbl == NULL)
1912 driver->buf_tbl = kzalloc(buf_tbl_size *
1913 sizeof(struct diag_write_device), GFP_KERNEL);
1914 if (driver->buf_tbl == NULL)
1915 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001916 kmemleak_not_leak(driver->buf_tbl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001917 if (driver->data_ready == NULL &&
1918 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1919 , GFP_KERNEL)) == NULL)
1920 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001921 kmemleak_not_leak(driver->data_ready);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001922 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001923 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001924 sizeof(struct diag_master_table),
1925 GFP_KERNEL)) == NULL)
1926 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001927 kmemleak_not_leak(driver->table);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001928 if (driver->write_ptr_1 == NULL) {
1929 driver->write_ptr_1 = kzalloc(
1930 sizeof(struct diag_request), GFP_KERNEL);
1931 if (driver->write_ptr_1 == NULL)
1932 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001933 kmemleak_not_leak(driver->write_ptr_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001934 }
1935 if (driver->write_ptr_2 == NULL) {
1936 driver->write_ptr_2 = kzalloc(
1937 sizeof(struct diag_request), GFP_KERNEL);
1938 if (driver->write_ptr_2 == NULL)
1939 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001940 kmemleak_not_leak(driver->write_ptr_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001941 }
1942 if (driver->write_ptr_qdsp_1 == NULL) {
1943 driver->write_ptr_qdsp_1 = kzalloc(
1944 sizeof(struct diag_request), GFP_KERNEL);
1945 if (driver->write_ptr_qdsp_1 == NULL)
1946 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001947 kmemleak_not_leak(driver->write_ptr_qdsp_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001948 }
1949 if (driver->write_ptr_qdsp_2 == NULL) {
1950 driver->write_ptr_qdsp_2 = kzalloc(
1951 sizeof(struct diag_request), GFP_KERNEL);
1952 if (driver->write_ptr_qdsp_2 == NULL)
1953 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001954 kmemleak_not_leak(driver->write_ptr_qdsp_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001955 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301956 if (driver->write_ptr_wcnss_1 == NULL) {
1957 driver->write_ptr_wcnss_1 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001958 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301959 if (driver->write_ptr_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001960 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001961 kmemleak_not_leak(driver->write_ptr_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001962 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301963 if (driver->write_ptr_wcnss_2 == NULL) {
1964 driver->write_ptr_wcnss_2 = kzalloc(
1965 sizeof(struct diag_request), GFP_KERNEL);
1966 if (driver->write_ptr_wcnss_2 == NULL)
1967 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001968 kmemleak_not_leak(driver->write_ptr_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301969 }
1970
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001971 if (driver->usb_read_ptr == NULL) {
1972 driver->usb_read_ptr = kzalloc(
1973 sizeof(struct diag_request), GFP_KERNEL);
1974 if (driver->usb_read_ptr == NULL)
1975 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001976 kmemleak_not_leak(driver->usb_read_ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001977 }
1978 if (driver->pkt_buf == NULL &&
1979 (driver->pkt_buf = kzalloc(PKT_SIZE,
1980 GFP_KERNEL)) == NULL)
1981 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001982 kmemleak_not_leak(driver->pkt_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001983 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001984 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001985 if (driver->apps_rsp_buf == NULL)
1986 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001987 kmemleak_not_leak(driver->apps_rsp_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001988 }
1989 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1990#ifdef CONFIG_DIAG_OVER_USB
1991 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1992 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001993 INIT_WORK(&(driver->diag_modem_mask_update_work),
1994 diag_modem_mask_update_fn);
1995 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
1996 diag_qdsp_mask_update_fn);
1997 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
1998 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001999 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
2000 diag_usb_legacy_notifier);
2001 if (IS_ERR(driver->legacy_ch)) {
2002 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
2003 goto err;
2004 }
2005#endif
2006 platform_driver_register(&msm_smd_ch1_driver);
2007 platform_driver_register(&diag_smd_lite_driver);
2008
2009 return;
2010err:
2011 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08002012 kfree(driver->event_mask);
2013 kfree(driver->log_mask);
2014 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002015 kfree(driver->buf_in_1);
2016 kfree(driver->buf_in_2);
2017 kfree(driver->buf_in_qdsp_1);
2018 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302019 kfree(driver->buf_in_wcnss_1);
2020 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002021 kfree(driver->buf_msg_mask_update);
2022 kfree(driver->buf_log_mask_update);
2023 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002024 kfree(driver->usb_buf_out);
2025 kfree(driver->hdlc_buf);
2026 kfree(driver->msg_masks);
2027 kfree(driver->log_masks);
2028 kfree(driver->event_masks);
2029 kfree(driver->client_map);
2030 kfree(driver->buf_tbl);
2031 kfree(driver->data_ready);
2032 kfree(driver->table);
2033 kfree(driver->pkt_buf);
2034 kfree(driver->write_ptr_1);
2035 kfree(driver->write_ptr_2);
2036 kfree(driver->write_ptr_qdsp_1);
2037 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302038 kfree(driver->write_ptr_wcnss_1);
2039 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002040 kfree(driver->usb_read_ptr);
2041 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002042 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002043 if (driver->diag_wq)
2044 destroy_workqueue(driver->diag_wq);
2045}
2046
2047void diagfwd_exit(void)
2048{
2049 smd_close(driver->ch);
2050 smd_close(driver->chqdsp);
2051 smd_close(driver->ch_wcnss);
2052 driver->ch = 0; /* SMD can make this NULL */
2053 driver->chqdsp = 0;
2054 driver->ch_wcnss = 0;
2055#ifdef CONFIG_DIAG_OVER_USB
2056 if (driver->usb_connected)
2057 usb_diag_free_req(driver->legacy_ch);
2058 usb_diag_close(driver->legacy_ch);
2059#endif
2060 platform_driver_unregister(&msm_smd_ch1_driver);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -07002061 platform_driver_unregister(&msm_diag_dci_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002062 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002063 kfree(driver->event_mask);
2064 kfree(driver->log_mask);
2065 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002066 kfree(driver->buf_in_1);
2067 kfree(driver->buf_in_2);
2068 kfree(driver->buf_in_qdsp_1);
2069 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302070 kfree(driver->buf_in_wcnss_1);
2071 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002072 kfree(driver->buf_msg_mask_update);
2073 kfree(driver->buf_log_mask_update);
2074 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002075 kfree(driver->usb_buf_out);
2076 kfree(driver->hdlc_buf);
2077 kfree(driver->msg_masks);
2078 kfree(driver->log_masks);
2079 kfree(driver->event_masks);
2080 kfree(driver->client_map);
2081 kfree(driver->buf_tbl);
2082 kfree(driver->data_ready);
2083 kfree(driver->table);
2084 kfree(driver->pkt_buf);
2085 kfree(driver->write_ptr_1);
2086 kfree(driver->write_ptr_2);
2087 kfree(driver->write_ptr_qdsp_1);
2088 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302089 kfree(driver->write_ptr_wcnss_1);
2090 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002091 kfree(driver->usb_read_ptr);
2092 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002093 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002094 destroy_workqueue(driver->diag_wq);
2095}