blob: a7a4a2a009832f8c1b06cae0e6f93b6c895b1ed6 [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>
Dixon Petersoncc0bea772012-04-11 20:45:37 -070025#include <linux/kmemleak.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070026#ifdef CONFIG_DIAG_OVER_USB
27#include <mach/usbdiag.h>
28#endif
29#include <mach/msm_smd.h>
30#include <mach/socinfo.h>
31#include <mach/restart.h>
32#include "diagmem.h"
33#include "diagchar.h"
34#include "diagfwd.h"
35#include "diagfwd_cntl.h"
36#include "diagchar_hdlc.h"
37#ifdef CONFIG_DIAG_SDIO_PIPE
38#include "diagfwd_sdio.h"
39#endif
Shalabh Jain1c99e4c2012-03-26 18:47:59 -070040#include "diag_dci.h"
41
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070042#define MODE_CMD 41
43#define RESET_ID 2
44#define ALL_EQUIP_ID 100
45#define ALL_SSID -1
46#define MAX_SSID_PER_RANGE 100
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070047
48int diag_debug_buf_idx;
49unsigned char diag_debug_buf[1024];
50static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
51struct diag_master_table entry;
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -080052smd_channel_t *ch_temp, *chqdsp_temp, *ch_wcnss_temp;
Shalabh Jain321c8b52012-02-22 12:37:06 -080053int diag_event_num_bytes;
54int diag_event_config;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070055struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
56struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
Shalabh Jain321c8b52012-02-22 12:37:06 -080057struct mask_info {
58 int equip_id;
59 int num_items;
60 int index;
61};
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070062
63#define CREATE_MSG_MASK_TBL_ROW(XX) \
64do { \
65 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX; \
66 msg_mask_tbl_ptr += 4; \
67 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
68 msg_mask_tbl_ptr += 4; \
69 /* increment by MAX_SSID_PER_RANGE cells */ \
70 msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int); \
71} while (0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070072
73#define ENCODE_RSP_AND_SEND(buf_length) \
74do { \
75 send.state = DIAG_STATE_START; \
76 send.pkt = driver->apps_rsp_buf; \
77 send.last = (void *)(driver->apps_rsp_buf + buf_length); \
78 send.terminate = 1; \
79 if (!driver->in_busy_1) { \
80 enc.dest = driver->buf_in_1; \
Shalabh Jain321c8b52012-02-22 12:37:06 -080081 enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);\
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070082 diag_hdlc_encode(&send, &enc); \
83 driver->write_ptr_1->buf = driver->buf_in_1; \
84 driver->write_ptr_1->length = (int)(enc.dest - \
85 (void *)(driver->buf_in_1)); \
Shalabh Jain3893bf92011-09-18 18:37:16 -070086 driver->in_busy_1 = 1; \
Shalabh Jain69890aa2011-10-10 12:59:16 -070087 diag_device_write(driver->buf_in_1, MODEM_DATA, \
88 driver->write_ptr_1); \
Shalabh Jain321c8b52012-02-22 12:37:06 -080089 memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE); \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070090 } \
91} while (0)
92
93#define CHK_OVERFLOW(bufStart, start, end, length) \
94((bufStart <= start) && (end - start >= length)) ? 1 : 0
95
Dixon Petersonb4618a42012-02-29 18:56:31 -080096/* Determine if this device uses a device tree */
97#ifdef CONFIG_OF
98static int has_device_tree(void)
99{
100 struct device_node *node;
101
102 node = of_find_node_by_path("/");
103 if (node) {
104 of_node_put(node);
105 return 1;
106 }
107 return 0;
108}
109#else
110static int has_device_tree(void)
111{
112 return 0;
113}
114#endif
115
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700116int chk_config_get_id(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117{
Shalabh Jain482bf122011-12-06 03:54:47 -0800118 /* For all Fusion targets, Modem will always be present */
119 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
120 return 0;
121
Dixon Petersonb4618a42012-02-29 18:56:31 -0800122 if (driver->use_device_tree) {
123 if (machine_is_copper())
124 return MSM8974_TOOLS_ID;
125 else
126 return 0;
127 } else {
128 switch (socinfo_get_msm_cpu()) {
129 case MSM_CPU_8X60:
130 return APQ8060_TOOLS_ID;
131 case MSM_CPU_8960:
132 return AO8960_TOOLS_ID;
133 case MSM_CPU_8064:
134 return APQ8064_TOOLS_ID;
135 case MSM_CPU_8930:
136 return MSM8930_TOOLS_ID;
137 case MSM_CPU_COPPER:
138 return MSM8974_TOOLS_ID;
139 case MSM_CPU_8625:
140 return MSM8625_TOOLS_ID;
141 default:
142 return 0;
143 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700144 }
145}
146
147/*
Shalabh Jain321c8b52012-02-22 12:37:06 -0800148 * This will return TRUE for targets which support apps only mode and hence SSR.
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700149 * This applies to 8960 and newer targets.
150 */
151int chk_apps_only(void)
152{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800153 if (driver->use_device_tree)
154 return 1;
155
156 switch (socinfo_get_msm_cpu()) {
157 case MSM_CPU_8960:
158 case MSM_CPU_8064:
159 case MSM_CPU_8930:
160 case MSM_CPU_8627:
161 case MSM_CPU_9615:
162 case MSM_CPU_COPPER:
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700163 return 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700164 default:
165 return 0;
166 }
167}
168
Shalabh Jain10f5f432012-01-11 11:45:44 +0530169/*
170 * This will return TRUE for targets which support apps as master.
171 * Thus, SW DLOAD and Mode Reset are supported on apps processor.
172 * This applies to 8960 and newer targets.
173 */
174int chk_apps_master(void)
175{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800176 if (driver->use_device_tree)
177 return 1;
178 else if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615() ||
179 cpu_is_apq8064() || cpu_is_msm8627())
180 return 1;
181 else
182 return 0;
183}
184
Dixon Peterson29aebee2012-04-06 12:44:08 -0700185int chk_polling_response(void)
Dixon Petersonb4618a42012-02-29 18:56:31 -0800186{
187 if (!(driver->polling_reg_flag) && chk_apps_master())
188 /*
189 * If the apps processor is master and no other processor
190 * has registered to respond for polling
191 */
192 return 1;
193 else if (!(driver->ch) && !(chk_apps_master()))
194 /*
195 * If the apps processor is not the master and the modem
196 * is not up
197 */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530198 return 1;
199 else
200 return 0;
201}
202
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700203void __diag_smd_send_req(void)
204{
205 void *buf = NULL;
206 int *in_busy_ptr = NULL;
207 struct diag_request *write_ptr_modem = NULL;
208
209 if (!driver->in_busy_1) {
210 buf = driver->buf_in_1;
211 write_ptr_modem = driver->write_ptr_1;
212 in_busy_ptr = &(driver->in_busy_1);
213 } else if (!driver->in_busy_2) {
214 buf = driver->buf_in_2;
215 write_ptr_modem = driver->write_ptr_2;
216 in_busy_ptr = &(driver->in_busy_2);
217 }
218
219 if (driver->ch && buf) {
220 int r = smd_read_avail(driver->ch);
221
222 if (r > IN_BUF_SIZE) {
223 if (r < MAX_IN_BUF_SIZE) {
224 pr_err("diag: SMD sending in "
225 "packets upto %d bytes", r);
226 buf = krealloc(buf, r, GFP_KERNEL);
227 } else {
228 pr_err("diag: SMD sending in "
229 "packets more than %d bytes", MAX_IN_BUF_SIZE);
230 return;
231 }
232 }
233 if (r > 0) {
234 if (!buf)
235 pr_info("Out of diagmem for Modem\n");
236 else {
237 APPEND_DEBUG('i');
238 smd_read(driver->ch, buf, r);
239 APPEND_DEBUG('j');
240 write_ptr_modem->length = r;
241 *in_busy_ptr = 1;
242 diag_device_write(buf, MODEM_DATA,
243 write_ptr_modem);
244 }
245 }
246 }
247}
248
249int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr)
250{
251 int i, err = 0;
252
253 if (driver->logging_mode == MEMORY_DEVICE_MODE) {
254 if (proc_num == APPS_DATA) {
255 for (i = 0; i < driver->poolsize_write_struct; i++)
256 if (driver->buf_tbl[i].length == 0) {
257 driver->buf_tbl[i].buf = buf;
258 driver->buf_tbl[i].length =
259 driver->used;
260#ifdef DIAG_DEBUG
261 pr_debug("diag: ENQUEUE buf ptr"
262 " and length is %x , %d\n",
263 (unsigned int)(driver->buf_
264 tbl[i].buf), driver->buf_tbl[i].length);
265#endif
266 break;
267 }
268 }
269 for (i = 0; i < driver->num_clients; i++)
270 if (driver->client_map[i].pid ==
271 driver->logging_process_id)
272 break;
273 if (i < driver->num_clients) {
Shalabh Jain69890aa2011-10-10 12:59:16 -0700274 driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700275 pr_debug("diag: wake up logging process\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700276 wake_up_interruptible(&driver->wait_q);
277 } else
278 return -EINVAL;
279 } else if (driver->logging_mode == NO_LOGGING_MODE) {
280 if (proc_num == MODEM_DATA) {
281 driver->in_busy_1 = 0;
282 driver->in_busy_2 = 0;
283 queue_work(driver->diag_wq, &(driver->
284 diag_read_smd_work));
285 } else if (proc_num == QDSP_DATA) {
286 driver->in_busy_qdsp_1 = 0;
287 driver->in_busy_qdsp_2 = 0;
288 queue_work(driver->diag_wq, &(driver->
289 diag_read_smd_qdsp_work));
290 } else if (proc_num == WCNSS_DATA) {
Ashay Jaiswal29620122012-03-21 12:02:36 +0530291 driver->in_busy_wcnss_1 = 0;
292 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700293 queue_work(driver->diag_wq, &(driver->
294 diag_read_smd_wcnss_work));
295 }
Shalabh Jain482bf122011-12-06 03:54:47 -0800296#ifdef CONFIG_DIAG_SDIO_PIPE
297 else if (proc_num == SDIO_DATA) {
298 driver->in_busy_sdio = 0;
299 queue_work(driver->diag_sdio_wq,
300 &(driver->diag_read_sdio_work));
301 }
302#endif
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700303#ifdef CONFIG_DIAG_HSIC_PIPE
304 else if (proc_num == HSIC_DATA) {
305 driver->in_busy_hsic_read = 0;
306 driver->in_busy_hsic_write_on_device = 0;
307 if (driver->hsic_ch)
308 queue_work(driver->diag_hsic_wq,
309 &(driver->diag_read_hsic_work));
310 }
311#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700312 err = -1;
313 }
314#ifdef CONFIG_DIAG_OVER_USB
315 else if (driver->logging_mode == USB_MODE) {
316 if (proc_num == APPS_DATA) {
317 driver->write_ptr_svc = (struct diag_request *)
318 (diagmem_alloc(driver, sizeof(struct diag_request),
319 POOL_TYPE_WRITE_STRUCT));
320 if (driver->write_ptr_svc) {
321 driver->write_ptr_svc->length = driver->used;
322 driver->write_ptr_svc->buf = buf;
323 err = usb_diag_write(driver->legacy_ch,
324 driver->write_ptr_svc);
325 } else
326 err = -1;
327 } else if (proc_num == MODEM_DATA) {
328 write_ptr->buf = buf;
329#ifdef DIAG_DEBUG
330 printk(KERN_INFO "writing data to USB,"
331 "pkt length %d\n", write_ptr->length);
332 print_hex_dump(KERN_DEBUG, "Written Packet Data to"
333 " USB: ", 16, 1, DUMP_PREFIX_ADDRESS,
334 buf, write_ptr->length, 1);
335#endif /* DIAG DEBUG */
336 err = usb_diag_write(driver->legacy_ch, write_ptr);
337 } else if (proc_num == QDSP_DATA) {
338 write_ptr->buf = buf;
339 err = usb_diag_write(driver->legacy_ch, write_ptr);
340 } else if (proc_num == WCNSS_DATA) {
341 write_ptr->buf = buf;
342 err = usb_diag_write(driver->legacy_ch, write_ptr);
343 }
344#ifdef CONFIG_DIAG_SDIO_PIPE
345 else if (proc_num == SDIO_DATA) {
346 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -0800347 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700348 write_ptr->buf = buf;
349 err = usb_diag_write(driver->mdm_ch, write_ptr);
350 } else
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800351 pr_err("diag: Incorrect sdio data "
352 "while USB write\n");
353 }
354#endif
355#ifdef CONFIG_DIAG_HSIC_PIPE
356 else if (proc_num == HSIC_DATA) {
357 if (driver->hsic_device_enabled) {
358 write_ptr->buf = buf;
359 err = usb_diag_write(driver->mdm_ch, write_ptr);
360 } else
361 pr_err("diag: Incorrect hsic data "
362 "while USB write\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700363 }
364#endif
365 APPEND_DEBUG('d');
366 }
367#endif /* DIAG OVER USB */
368 return err;
369}
370
371void __diag_smd_wcnss_send_req(void)
372{
Ashay Jaiswal29620122012-03-21 12:02:36 +0530373 void *buf = NULL;
374 int *in_busy_wcnss_ptr = NULL;
375 struct diag_request *write_ptr_wcnss = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700376
Ashay Jaiswal29620122012-03-21 12:02:36 +0530377 if (!driver->in_busy_wcnss_1) {
378 buf = driver->buf_in_wcnss_1;
379 write_ptr_wcnss = driver->write_ptr_wcnss_1;
380 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_1);
381 } else if (!driver->in_busy_wcnss_2) {
382 buf = driver->buf_in_wcnss_2;
383 write_ptr_wcnss = driver->write_ptr_wcnss_2;
384 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_2);
385 }
386
387 if (driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700388 int r = smd_read_avail(driver->ch_wcnss);
389 if (r > IN_BUF_SIZE) {
390 if (r < MAX_IN_BUF_SIZE) {
391 pr_err("diag: wcnss packets > %d bytes", r);
392 buf = krealloc(buf, r, GFP_KERNEL);
393 } else {
394 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
395 return;
396 }
397 }
398 if (r > 0) {
399 if (!buf) {
400 pr_err("Out of diagmem for wcnss\n");
401 } else {
402 APPEND_DEBUG('i');
403 smd_read(driver->ch_wcnss, buf, r);
404 APPEND_DEBUG('j');
405 write_ptr_wcnss->length = r;
406 *in_busy_wcnss_ptr = 1;
407 diag_device_write(buf, WCNSS_DATA,
408 write_ptr_wcnss);
409 }
410 }
411 }
412}
413
414void __diag_smd_qdsp_send_req(void)
415{
416 void *buf = NULL;
417 int *in_busy_qdsp_ptr = NULL;
418 struct diag_request *write_ptr_qdsp = NULL;
419
420 if (!driver->in_busy_qdsp_1) {
421 buf = driver->buf_in_qdsp_1;
422 write_ptr_qdsp = driver->write_ptr_qdsp_1;
423 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1);
424 } else if (!driver->in_busy_qdsp_2) {
425 buf = driver->buf_in_qdsp_2;
426 write_ptr_qdsp = driver->write_ptr_qdsp_2;
427 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2);
428 }
429
430 if (driver->chqdsp && buf) {
431 int r = smd_read_avail(driver->chqdsp);
432
433 if (r > IN_BUF_SIZE) {
434 if (r < MAX_IN_BUF_SIZE) {
435 pr_err("diag: SMD sending in "
436 "packets upto %d bytes", r);
437 buf = krealloc(buf, r, GFP_KERNEL);
438 } else {
439 pr_err("diag: SMD sending in "
440 "packets more than %d bytes", MAX_IN_BUF_SIZE);
441 return;
442 }
443 }
444 if (r > 0) {
445 if (!buf)
446 printk(KERN_INFO "Out of diagmem for QDSP\n");
447 else {
448 APPEND_DEBUG('i');
449 smd_read(driver->chqdsp, buf, r);
450 APPEND_DEBUG('j');
451 write_ptr_qdsp->length = r;
452 *in_busy_qdsp_ptr = 1;
453 diag_device_write(buf, QDSP_DATA,
454 write_ptr_qdsp);
455 }
456 }
457 }
458}
459
460static void diag_print_mask_table(void)
461{
462/* Enable this to print mask table when updated */
463#ifdef MASK_DEBUG
464 int first;
465 int last;
466 uint8_t *ptr = driver->msg_masks;
467 int i = 0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700468 pr_info("diag: F3 message mask table\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700469 while (*(uint32_t *)(ptr + 4)) {
470 first = *(uint32_t *)ptr;
471 ptr += 4;
472 last = *(uint32_t *)ptr;
473 ptr += 4;
474 printk(KERN_INFO "SSID %d - %d\n", first, last);
475 for (i = 0 ; i <= last - first ; i++)
476 printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700477 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700478
479 }
480#endif
481}
482
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700483void diag_create_msg_mask_table(void)
484{
485 uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
486
487 CREATE_MSG_MASK_TBL_ROW(0);
488 CREATE_MSG_MASK_TBL_ROW(1);
489 CREATE_MSG_MASK_TBL_ROW(2);
490 CREATE_MSG_MASK_TBL_ROW(3);
491 CREATE_MSG_MASK_TBL_ROW(4);
492 CREATE_MSG_MASK_TBL_ROW(5);
493 CREATE_MSG_MASK_TBL_ROW(6);
494 CREATE_MSG_MASK_TBL_ROW(7);
495 CREATE_MSG_MASK_TBL_ROW(8);
496 CREATE_MSG_MASK_TBL_ROW(9);
497 CREATE_MSG_MASK_TBL_ROW(10);
498 CREATE_MSG_MASK_TBL_ROW(11);
499 CREATE_MSG_MASK_TBL_ROW(12);
500 CREATE_MSG_MASK_TBL_ROW(13);
501 CREATE_MSG_MASK_TBL_ROW(14);
502 CREATE_MSG_MASK_TBL_ROW(15);
503 CREATE_MSG_MASK_TBL_ROW(16);
504 CREATE_MSG_MASK_TBL_ROW(17);
505 CREATE_MSG_MASK_TBL_ROW(18);
506 CREATE_MSG_MASK_TBL_ROW(19);
507 CREATE_MSG_MASK_TBL_ROW(20);
508 CREATE_MSG_MASK_TBL_ROW(21);
509 CREATE_MSG_MASK_TBL_ROW(22);
510}
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700511
512static void diag_set_msg_mask(int rt_mask)
513{
514 int first_ssid, last_ssid, i;
515 uint8_t *parse_ptr, *ptr = driver->msg_masks;
516
517 mutex_lock(&driver->diagchar_mutex);
518 while (*(uint32_t *)(ptr + 4)) {
519 first_ssid = *(uint32_t *)ptr;
520 ptr += 4;
521 last_ssid = *(uint32_t *)ptr;
522 ptr += 4;
523 parse_ptr = ptr;
524 pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
525 for (i = 0; i < last_ssid - first_ssid + 1; i++) {
526 *(int *)parse_ptr = rt_mask;
527 parse_ptr += 4;
528 }
529 ptr += MAX_SSID_PER_RANGE * 4;
530 }
531 mutex_unlock(&driver->diagchar_mutex);
532}
533
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700534static void diag_update_msg_mask(int start, int end , uint8_t *buf)
535{
536 int found = 0;
537 int first;
538 int last;
539 uint8_t *ptr = driver->msg_masks;
540 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
541 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
542
543 mutex_lock(&driver->diagchar_mutex);
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530544
Shalabh Jain321c8b52012-02-22 12:37:06 -0800545 /* First SSID can be zero : So check that last is non-zero */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700546 while (*(uint32_t *)(ptr + 4)) {
547 first = *(uint32_t *)ptr;
548 ptr += 4;
549 last = *(uint32_t *)ptr;
550 ptr += 4;
551 if (start >= first && start <= last) {
552 ptr += (start - first)*4;
553 if (end <= last)
554 if (CHK_OVERFLOW(ptr_buffer_start, ptr,
555 ptr_buffer_end,
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700556 (((end - start)+1)*4))) {
557 pr_debug("diag: update ssid start %d,"
558 " end %d\n", start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700559 memcpy(ptr, buf , ((end - start)+1)*4);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700560 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700561 printk(KERN_CRIT "Not enough"
562 " buffer space for"
563 " MSG_MASK\n");
564 else
565 printk(KERN_INFO "Unable to copy"
566 " mask change\n");
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530567
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700568 found = 1;
569 break;
570 } else {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700571 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700572 }
573 }
574 /* Entry was not found - add new table */
575 if (!found) {
576 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
577 8 + ((end - start) + 1)*4)) {
578 memcpy(ptr, &(start) , 4);
579 ptr += 4;
580 memcpy(ptr, &(end), 4);
581 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700582 pr_debug("diag: adding NEW ssid start %d, end %d\n",
583 start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700584 memcpy(ptr, buf , ((end - start) + 1)*4);
585 } else
586 printk(KERN_CRIT " Not enough buffer"
587 " space for MSG_MASK\n");
588 }
589 mutex_unlock(&driver->diagchar_mutex);
590 diag_print_mask_table();
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530591
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700592}
593
Shalabh Jaina51f2592012-03-08 14:36:35 -0800594void diag_toggle_event_mask(int toggle)
595{
596 uint8_t *ptr = driver->event_masks;
597
598 mutex_lock(&driver->diagchar_mutex);
599 if (toggle)
600 memset(ptr, 0xFF, EVENT_MASK_SIZE);
601 else
602 memset(ptr, 0, EVENT_MASK_SIZE);
603 mutex_unlock(&driver->diagchar_mutex);
604}
605
Shalabh Jain321c8b52012-02-22 12:37:06 -0800606static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700607{
608 uint8_t *ptr = driver->event_masks;
609 uint8_t *temp = buf + 2;
610
611 mutex_lock(&driver->diagchar_mutex);
612 if (!toggle)
613 memset(ptr, 0 , EVENT_MASK_SIZE);
614 else
615 if (CHK_OVERFLOW(ptr, ptr,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800616 ptr+EVENT_MASK_SIZE, num_bytes))
617 memcpy(ptr, temp , num_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700618 else
619 printk(KERN_CRIT "Not enough buffer space "
620 "for EVENT_MASK\n");
621 mutex_unlock(&driver->diagchar_mutex);
622}
623
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700624static void diag_disable_log_mask(void)
625{
626 int i = 0;
627 struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
628
629 pr_debug("diag: disable log masks\n");
630 mutex_lock(&driver->diagchar_mutex);
631 for (i = 0; i < MAX_EQUIP_ID; i++) {
632 pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
633 if (!(parse_ptr->equip_id)) /* Reached a null entry */
634 break;
635 memset(driver->log_masks + parse_ptr->index, 0,
636 (parse_ptr->num_items + 7)/8);
637 parse_ptr++;
638 }
639 mutex_unlock(&driver->diagchar_mutex);
640}
641
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700642static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
643{
644 uint8_t *temp = buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700645 int i = 0;
646 unsigned char *ptr_data;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700647 int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700648 struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700649
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700650 pr_debug("diag: received equip id = %d\n", equip_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651 mutex_lock(&driver->diagchar_mutex);
652 /* Check if we already know index of this equipment ID */
653 for (i = 0; i < MAX_EQUIP_ID; i++) {
654 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
655 offset = ptr->index;
656 break;
657 }
658 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
Shalabh Jain321c8b52012-02-22 12:37:06 -0800659 /* Reached a null entry */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700660 ptr->equip_id = equip_id;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800661 ptr->num_items = num_items;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700662 ptr->index = driver->log_masks_length;
663 offset = driver->log_masks_length;
664 driver->log_masks_length += ((num_items+7)/8);
665 break;
666 }
667 ptr++;
668 }
669 ptr_data = driver->log_masks + offset;
670 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
671 + LOG_MASK_SIZE, (num_items+7)/8))
672 memcpy(ptr_data, temp , (num_items+7)/8);
673 else
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700674 pr_err("diag: Not enough buffer space for LOG_MASK\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700675 mutex_unlock(&driver->diagchar_mutex);
676}
677
678static void diag_update_pkt_buffer(unsigned char *buf)
679{
680 unsigned char *ptr = driver->pkt_buf;
681 unsigned char *temp = buf;
682
683 mutex_lock(&driver->diagchar_mutex);
684 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
685 memcpy(ptr, temp , driver->pkt_length);
686 else
687 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
688 mutex_unlock(&driver->diagchar_mutex);
689}
690
691void diag_update_userspace_clients(unsigned int type)
692{
693 int i;
694
695 mutex_lock(&driver->diagchar_mutex);
696 for (i = 0; i < driver->num_clients; i++)
697 if (driver->client_map[i].pid != 0)
698 driver->data_ready[i] |= type;
699 wake_up_interruptible(&driver->wait_q);
700 mutex_unlock(&driver->diagchar_mutex);
701}
702
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700703void diag_update_sleeping_process(int process_id, int data_type)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700704{
705 int i;
706
707 mutex_lock(&driver->diagchar_mutex);
708 for (i = 0; i < driver->num_clients; i++)
709 if (driver->client_map[i].pid == process_id) {
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700710 driver->data_ready[i] |= data_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700711 break;
712 }
713 wake_up_interruptible(&driver->wait_q);
714 mutex_unlock(&driver->diagchar_mutex);
715}
716
717void diag_send_data(struct diag_master_table entry, unsigned char *buf,
718 int len, int type)
719{
720 driver->pkt_length = len;
721 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
722 diag_update_pkt_buffer(buf);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700723 diag_update_sleeping_process(entry.process_id, PKT_TYPE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700724 } else {
725 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700726 if (entry.client_id == MODEM_PROC && driver->ch) {
Shalabh Jain10f5f432012-01-11 11:45:44 +0530727 if (chk_apps_master() &&
Shalabh Jainc9f35092011-07-28 18:36:17 -0700728 (int)(*(char *)buf) == MODE_CMD)
Dixon Petersonff425d12011-12-06 18:12:35 -0800729 if ((int)(*(char *)(buf+1)) ==
730 RESET_ID)
Shalabh Jainc9f35092011-07-28 18:36:17 -0700731 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700732 smd_write(driver->ch, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700733 } else if (entry.client_id == QDSP_PROC &&
734 driver->chqdsp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700735 smd_write(driver->chqdsp, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700736 } else if (entry.client_id == WCNSS_PROC &&
737 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700738 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700739 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700740 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700741 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700742 }
743 }
744}
745
Shalabh Jain321c8b52012-02-22 12:37:06 -0800746void diag_modem_mask_update_fn(struct work_struct *work)
747{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700748 diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
749 ALL_SSID, MODEM_PROC);
750 diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800751 diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
752}
753
754void diag_qdsp_mask_update_fn(struct work_struct *work)
755{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700756 diag_send_msg_mask_update(driver->chqdsp_cntl, ALL_SSID,
757 ALL_SSID, QDSP_PROC);
758 diag_send_log_mask_update(driver->chqdsp_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800759 diag_send_event_mask_update(driver->chqdsp_cntl, diag_event_num_bytes);
760}
761
762void diag_wcnss_mask_update_fn(struct work_struct *work)
763{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700764 diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
765 ALL_SSID, WCNSS_PROC);
766 diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800767 diag_send_event_mask_update(driver->ch_wcnss_cntl,
768 diag_event_num_bytes);
769}
770
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700771void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800772{
773 void *buf = driver->buf_log_mask_update;
774 int header_size = sizeof(struct diag_ctrl_log_mask);
775 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700776 int i, size, wr_size = -ENOMEM, retry_count = 0, timer;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800777
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700778 mutex_lock(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800779 for (i = 0; i < MAX_EQUIP_ID; i++) {
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700780 size = (ptr->num_items+7)/8;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800781 /* reached null entry */
782 if ((ptr->equip_id == 0) && (ptr->index == 0))
783 break;
784 driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
785 driver->log_mask->num_items = ptr->num_items;
786 driver->log_mask->data_len = 11 + size;
787 driver->log_mask->stream_id = 1; /* 2, if dual stream */
788 driver->log_mask->status = 3; /* status for valid mask */
789 driver->log_mask->equip_id = ptr->equip_id;
790 driver->log_mask->log_mask_size = size;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700791 /* send only desired update, NOT ALL */
792 if (equip_id == ALL_EQUIP_ID || equip_id ==
793 driver->log_mask->equip_id) {
794 memcpy(buf, driver->log_mask, header_size);
795 memcpy(buf+header_size, driver->log_masks+ptr->index,
796 size);
797 if (ch) {
798 while (retry_count < 3) {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700799 wr_size = smd_write(ch, buf,
800 header_size + size);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700801 if (wr_size == -ENOMEM) {
802 retry_count++;
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700803 for (timer = 0; timer < 5;
804 timer++)
805 udelay(2000);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700806 } else
807 break;
808 }
809 if (wr_size != header_size + size)
810 pr_err("diag: log mask update failed"
811 " %d, tried %d", wr_size, header_size + size);
812 else
813 pr_debug("diag: updated log equip ID %d"
814 ",len %d\n", driver->log_mask->equip_id,
815 driver->log_mask->log_mask_size);
816 } else
817 pr_err("diag: ch not valid for log update\n");
818 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800819 ptr++;
820 }
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700821 mutex_unlock(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800822}
823
824void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
825{
826 void *buf = driver->buf_event_mask_update;
827 int header_size = sizeof(struct diag_ctrl_event_mask);
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700828 int wr_size = -ENOMEM, retry_count = 0, timer;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800829
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700830 mutex_lock(&driver->diag_cntl_mutex);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700831 if (num_bytes == 0) {
832 pr_debug("diag: event mask not set yet, so no update\n");
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700833 mutex_unlock(&driver->diag_cntl_mutex);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700834 return;
835 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800836 /* send event mask update */
837 driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
838 driver->event_mask->data_len = 7 + num_bytes;
839 driver->event_mask->stream_id = 1; /* 2, if dual stream */
840 driver->event_mask->status = 3; /* status for valid mask */
841 driver->event_mask->event_config = diag_event_config; /* event config */
842 driver->event_mask->event_mask_size = num_bytes;
843 memcpy(buf, driver->event_mask, header_size);
844 memcpy(buf+header_size, driver->event_masks, num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700845 if (ch) {
846 while (retry_count < 3) {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700847 wr_size = smd_write(ch, buf, header_size + num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700848 if (wr_size == -ENOMEM) {
849 retry_count++;
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700850 for (timer = 0; timer < 5; timer++)
851 udelay(2000);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700852 } else
853 break;
854 }
855 if (wr_size != header_size + num_bytes)
856 pr_err("diag: error writing event mask %d, tried %d\n",
857 wr_size, header_size + num_bytes);
858 } else
859 pr_err("diag: ch not valid for event update\n");
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700860 mutex_unlock(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800861}
862
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700863void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
864 int updated_ssid_last, int proc)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800865{
866 void *buf = driver->buf_msg_mask_update;
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700867 int first, last, size = -ENOMEM, retry_count = 0, timer;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800868 int header_size = sizeof(struct diag_ctrl_msg_mask);
869 uint8_t *ptr = driver->msg_masks;
870
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700871 mutex_lock(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800872 while (*(uint32_t *)(ptr + 4)) {
873 first = *(uint32_t *)ptr;
874 ptr += 4;
875 last = *(uint32_t *)ptr;
876 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700877 if ((updated_ssid_first >= first && updated_ssid_last <= last)
878 || (updated_ssid_first == ALL_SSID)) {
879 /* send f3 mask update */
880 driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
881 driver->msg_mask->msg_mask_size = last - first + 1;
882 driver->msg_mask->data_len = 11 +
883 4 * (driver->msg_mask->msg_mask_size);
884 driver->msg_mask->stream_id = 1; /* 2, if dual stream */
885 driver->msg_mask->status = 3; /* status valid mask */
886 driver->msg_mask->msg_mode = 0; /* Legcay mode */
887 driver->msg_mask->ssid_first = first;
888 driver->msg_mask->ssid_last = last;
889 memcpy(buf, driver->msg_mask, header_size);
890 memcpy(buf+header_size, ptr,
891 4 * (driver->msg_mask->msg_mask_size));
892 if (ch) {
893 while (retry_count < 3) {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700894 size = smd_write(ch, buf, header_size +
895 4*(driver->msg_mask->msg_mask_size));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700896 if (size == -ENOMEM) {
897 retry_count++;
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700898 for (timer = 0; timer < 5;
899 timer++)
900 udelay(2000);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700901 } else
902 break;
903 }
904 if (size != header_size +
905 4*(driver->msg_mask->msg_mask_size))
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700906 pr_err("diag: proc %d, msg mask update "
907 "fail %d, tried %d\n", proc, size,
908 header_size + 4*(driver->msg_mask->msg_mask_size));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700909 else
910 pr_debug("diag: sending mask update for"
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700911 "ssid first %d, last %d on PROC %d\n", first, last, proc);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700912 } else
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700913 pr_err("diag: proc %d, ch invalid msg mask"
914 "update\n", proc);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700915 }
916 ptr += MAX_SSID_PER_RANGE*4;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800917 }
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700918 mutex_unlock(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800919}
920
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700921static int diag_process_apps_pkt(unsigned char *buf, int len)
922{
923 uint16_t subsys_cmd_code;
924 int subsys_id, ssid_first, ssid_last, ssid_range;
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700925 int packet_type = 1, i, cmd_code, rt_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700926 unsigned char *temp = buf;
927 int data_type;
928#if defined(CONFIG_DIAG_OVER_USB)
929 int payload_length;
930 unsigned char *ptr;
931#endif
932
Shalabh Jain321c8b52012-02-22 12:37:06 -0800933 /* Set log masks */
934 if (*buf == 0x73 && *(int *)(buf+4) == 3) {
935 buf += 8;
936 /* Read Equip ID and pass as first param below*/
937 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
938 diag_update_userspace_clients(LOG_MASKS_TYPE);
939#if defined(CONFIG_DIAG_OVER_USB)
940 if (chk_apps_only()) {
941 driver->apps_rsp_buf[0] = 0x73;
942 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
943 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
944 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
945 for (i = 0; i < payload_length; i++)
946 *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700947 if (driver->ch_cntl)
948 diag_send_log_mask_update(driver->ch_cntl,
949 *(int *)buf);
950 if (driver->chqdsp_cntl)
951 diag_send_log_mask_update(driver->chqdsp_cntl,
952 *(int *)buf);
953 if (driver->ch_wcnss_cntl)
954 diag_send_log_mask_update(driver->ch_wcnss_cntl,
955 *(int *)buf);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800956 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
957 return 0;
958 } else
959 buf = temp;
960#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700961 } /* Disable log masks */
962 else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700963 /* Disable mask for each log code */
964 diag_disable_log_mask();
965 diag_update_userspace_clients(LOG_MASKS_TYPE);
966#if defined(CONFIG_DIAG_OVER_USB)
967 if (chk_apps_only()) {
968 driver->apps_rsp_buf[0] = 0x73;
969 driver->apps_rsp_buf[1] = 0x0;
970 driver->apps_rsp_buf[2] = 0x0;
971 driver->apps_rsp_buf[3] = 0x0;
972 *(int *)(driver->apps_rsp_buf + 4) = 0x0;
973 if (driver->ch_cntl)
974 diag_send_log_mask_update(driver->ch_cntl,
Dixon Petersona73bb992012-05-05 18:00:40 -0700975 ALL_EQUIP_ID);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700976 if (driver->chqdsp_cntl)
977 diag_send_log_mask_update(driver->chqdsp_cntl,
Dixon Petersona73bb992012-05-05 18:00:40 -0700978 ALL_EQUIP_ID);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700979 if (driver->ch_wcnss_cntl)
980 diag_send_log_mask_update(driver->ch_wcnss_cntl,
Dixon Petersona73bb992012-05-05 18:00:40 -0700981 ALL_EQUIP_ID);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700982 ENCODE_RSP_AND_SEND(7);
983 return 0;
Dixon Petersona73bb992012-05-05 18:00:40 -0700984 }
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700985#endif
986 } /* Set runtime message mask */
Shalabh Jain321c8b52012-02-22 12:37:06 -0800987 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
988 ssid_first = *(uint16_t *)(buf + 2);
989 ssid_last = *(uint16_t *)(buf + 4);
990 ssid_range = 4 * (ssid_last - ssid_first + 1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700991 pr_debug("diag: received mask update for ssid_first = %d,"
992 " ssid_last = %d", ssid_first, ssid_last);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800993 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
994 diag_update_userspace_clients(MSG_MASKS_TYPE);
995#if defined(CONFIG_DIAG_OVER_USB)
996 if (chk_apps_only()) {
997 for (i = 0; i < 8 + ssid_range; i++)
998 *(driver->apps_rsp_buf + i) = *(buf+i);
999 *(driver->apps_rsp_buf + 6) = 0x1;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001000 if (driver->ch_cntl)
1001 diag_send_msg_mask_update(driver->ch_cntl,
1002 ssid_first, ssid_last, MODEM_PROC);
1003 if (driver->chqdsp_cntl)
1004 diag_send_msg_mask_update(driver->chqdsp_cntl,
1005 ssid_first, ssid_last, QDSP_PROC);
1006 if (driver->ch_wcnss_cntl)
1007 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1008 ssid_first, ssid_last, WCNSS_PROC);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001009 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1010 return 0;
1011 } else
1012 buf = temp;
1013#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001014 } /* Set ALL runtime message mask */
1015 else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
1016 rt_mask = *(int *)(buf + 4);
1017 diag_set_msg_mask(rt_mask);
1018 diag_update_userspace_clients(MSG_MASKS_TYPE);
1019#if defined(CONFIG_DIAG_OVER_USB)
1020 if (chk_apps_only()) {
1021 driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
1022 driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
1023 driver->apps_rsp_buf[2] = 1; /* success */
1024 driver->apps_rsp_buf[3] = 0; /* rsvd */
1025 *(int *)(driver->apps_rsp_buf + 4) = rt_mask;
1026 /* send msg mask update to peripheral */
1027 if (driver->ch_cntl)
1028 diag_send_msg_mask_update(driver->ch_cntl,
1029 ALL_SSID, ALL_SSID, MODEM_PROC);
1030 if (driver->chqdsp_cntl)
1031 diag_send_msg_mask_update(driver->chqdsp_cntl,
1032 ALL_SSID, ALL_SSID, QDSP_PROC);
1033 if (driver->ch_wcnss_cntl)
1034 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1035 ALL_SSID, ALL_SSID, WCNSS_PROC);
1036 ENCODE_RSP_AND_SEND(7);
1037 return 0;
1038 } else
1039 buf = temp;
1040#endif
Shalabh Jain321c8b52012-02-22 12:37:06 -08001041 } else if (*buf == 0x82) { /* event mask change */
1042 buf += 4;
1043 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
1044 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
1045 diag_update_userspace_clients(EVENT_MASKS_TYPE);
1046#if defined(CONFIG_DIAG_OVER_USB)
1047 if (chk_apps_only()) {
1048 driver->apps_rsp_buf[0] = 0x82;
1049 driver->apps_rsp_buf[1] = 0x0;
1050 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1051 *(uint16_t *)(driver->apps_rsp_buf + 4) =
1052 EVENT_LAST_ID + 1;
Shalabh Jaina51f2592012-03-08 14:36:35 -08001053 memcpy(driver->apps_rsp_buf+6, driver->event_masks,
1054 EVENT_LAST_ID/8+1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001055 if (driver->ch_cntl)
1056 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001057 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001058 if (driver->chqdsp_cntl)
1059 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001060 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001061 if (driver->ch_wcnss_cntl)
1062 diag_send_event_mask_update(
1063 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001064 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1065 return 0;
1066 } else
1067 buf = temp;
1068#endif
1069 } else if (*buf == 0x60) {
1070 diag_event_config = *(buf+1);
Shalabh Jaina51f2592012-03-08 14:36:35 -08001071 diag_toggle_event_mask(*(buf+1));
1072 diag_update_userspace_clients(EVENT_MASKS_TYPE);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001073#if defined(CONFIG_DIAG_OVER_USB)
1074 if (chk_apps_only()) {
1075 driver->apps_rsp_buf[0] = 0x60;
1076 driver->apps_rsp_buf[1] = 0x0;
1077 driver->apps_rsp_buf[2] = 0x0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001078 if (driver->ch_cntl)
1079 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001080 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001081 if (driver->chqdsp_cntl)
1082 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001083 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001084 if (driver->ch_wcnss_cntl)
1085 diag_send_event_mask_update(
1086 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001087 ENCODE_RSP_AND_SEND(2);
1088 return 0;
1089 }
1090#endif
1091 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001092 /* Check for registered clients and forward packet to apropriate proc */
1093 cmd_code = (int)(*(char *)buf);
1094 temp++;
1095 subsys_id = (int)(*(char *)temp);
1096 temp++;
1097 subsys_cmd_code = *(uint16_t *)temp;
1098 temp += 2;
1099 data_type = APPS_DATA;
1100 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301101 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001102 if (subsys_id != RESET_ID)
1103 data_type = MODEM_DATA;
1104 }
1105
1106 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001107 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001108 entry = driver->table[i];
1109 if (entry.process_id != NO_PROCESS) {
1110 if (entry.cmd_code == cmd_code && entry.subsys_id ==
1111 subsys_id && entry.cmd_code_lo <=
1112 subsys_cmd_code &&
1113 entry.cmd_code_hi >= subsys_cmd_code) {
1114 diag_send_data(entry, buf, len, data_type);
1115 packet_type = 0;
1116 } else if (entry.cmd_code == 255
1117 && cmd_code == 75) {
1118 if (entry.subsys_id ==
1119 subsys_id &&
1120 entry.cmd_code_lo <=
1121 subsys_cmd_code &&
1122 entry.cmd_code_hi >=
1123 subsys_cmd_code) {
1124 diag_send_data(entry, buf, len,
1125 data_type);
1126 packet_type = 0;
1127 }
1128 } else if (entry.cmd_code == 255 &&
1129 entry.subsys_id == 255) {
1130 if (entry.cmd_code_lo <=
1131 cmd_code &&
1132 entry.
1133 cmd_code_hi >= cmd_code) {
1134 diag_send_data(entry, buf, len,
1135 data_type);
1136 packet_type = 0;
1137 }
1138 }
1139 }
1140 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001141#if defined(CONFIG_DIAG_OVER_USB)
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001142 /* Check for Apps Only & get event mask request */
Shalabh Jain321c8b52012-02-22 12:37:06 -08001143 if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001144 driver->apps_rsp_buf[0] = 0x81;
1145 driver->apps_rsp_buf[1] = 0x0;
1146 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1147 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
1148 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
1149 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
1150 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1151 return 0;
1152 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001153 /* Get log ID range & Check for Apps Only */
1154 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001155 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
1156 driver->apps_rsp_buf[0] = 0x73;
1157 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
1158 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
1159 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
1160 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
1161 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
1162 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
1163 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
1164 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
1165 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
1166 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
1167 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
1168 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
1169 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
1170 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
1171 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
1172 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
1173 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
1174 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
1175 ENCODE_RSP_AND_SEND(75);
1176 return 0;
1177 }
1178 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001179 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001180 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
1181 driver->apps_rsp_buf[0] = 0x7d;
1182 driver->apps_rsp_buf[1] = 0x1;
1183 driver->apps_rsp_buf[2] = 0x1;
1184 driver->apps_rsp_buf[3] = 0x0;
1185 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
1186 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
1187 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
1188 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
1189 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
1190 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
1191 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
1192 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
1193 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
1194 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
1195 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
1196 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
1197 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
1198 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
1199 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
1200 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
1201 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
1202 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
1203 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
1204 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
1205 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
1206 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
1207 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
1208 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
1209 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
1210 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
1211 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
1212 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
1213 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
1214 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
1215 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
1216 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
1217 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
1218 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
1219 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
1220 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
1221 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
1222 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
1223 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001224 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
1225 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
1226 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
1227 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
1228 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
1229 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
1230 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
1231 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
1232 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001233 return 0;
1234 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001235 /* Check for Apps Only Respond to Get Subsys Build mask */
1236 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001237 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
1238 ssid_first = *(uint16_t *)(buf + 2);
1239 ssid_last = *(uint16_t *)(buf + 4);
1240 ssid_range = 4 * (ssid_last - ssid_first + 1);
1241 /* frame response */
1242 driver->apps_rsp_buf[0] = 0x7d;
1243 driver->apps_rsp_buf[1] = 0x2;
1244 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
1245 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
1246 driver->apps_rsp_buf[6] = 0x1;
1247 driver->apps_rsp_buf[7] = 0x0;
1248 ptr = driver->apps_rsp_buf + 8;
1249 /* bld time masks */
1250 switch (ssid_first) {
1251 case MSG_SSID_0:
1252 for (i = 0; i < ssid_range; i += 4)
1253 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
1254 break;
1255 case MSG_SSID_1:
1256 for (i = 0; i < ssid_range; i += 4)
1257 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
1258 break;
1259 case MSG_SSID_2:
1260 for (i = 0; i < ssid_range; i += 4)
1261 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
1262 break;
1263 case MSG_SSID_3:
1264 for (i = 0; i < ssid_range; i += 4)
1265 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
1266 break;
1267 case MSG_SSID_4:
1268 for (i = 0; i < ssid_range; i += 4)
1269 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
1270 break;
1271 case MSG_SSID_5:
1272 for (i = 0; i < ssid_range; i += 4)
1273 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
1274 break;
1275 case MSG_SSID_6:
1276 for (i = 0; i < ssid_range; i += 4)
1277 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
1278 break;
1279 case MSG_SSID_7:
1280 for (i = 0; i < ssid_range; i += 4)
1281 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
1282 break;
1283 case MSG_SSID_8:
1284 for (i = 0; i < ssid_range; i += 4)
1285 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
1286 break;
1287 case MSG_SSID_9:
1288 for (i = 0; i < ssid_range; i += 4)
1289 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
1290 break;
1291 case MSG_SSID_10:
1292 for (i = 0; i < ssid_range; i += 4)
1293 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
1294 break;
1295 case MSG_SSID_11:
1296 for (i = 0; i < ssid_range; i += 4)
1297 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
1298 break;
1299 case MSG_SSID_12:
1300 for (i = 0; i < ssid_range; i += 4)
1301 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1302 break;
1303 case MSG_SSID_13:
1304 for (i = 0; i < ssid_range; i += 4)
1305 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1306 break;
1307 case MSG_SSID_14:
1308 for (i = 0; i < ssid_range; i += 4)
1309 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1310 break;
1311 case MSG_SSID_15:
1312 for (i = 0; i < ssid_range; i += 4)
1313 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1314 break;
1315 case MSG_SSID_16:
1316 for (i = 0; i < ssid_range; i += 4)
1317 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1318 break;
1319 case MSG_SSID_17:
1320 for (i = 0; i < ssid_range; i += 4)
1321 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1322 break;
1323 case MSG_SSID_18:
1324 for (i = 0; i < ssid_range; i += 4)
1325 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1326 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001327 case MSG_SSID_19:
1328 for (i = 0; i < ssid_range; i += 4)
1329 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1330 break;
1331 case MSG_SSID_20:
1332 for (i = 0; i < ssid_range; i += 4)
1333 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1334 break;
1335 case MSG_SSID_21:
1336 for (i = 0; i < ssid_range; i += 4)
1337 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1338 break;
1339 case MSG_SSID_22:
1340 for (i = 0; i < ssid_range; i += 4)
1341 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1342 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001343 }
1344 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1345 return 0;
1346 }
1347 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301348 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001349 /* send response back */
1350 driver->apps_rsp_buf[0] = *buf;
1351 ENCODE_RSP_AND_SEND(0);
1352 msleep(5000);
1353 /* call download API */
1354 msm_set_restart_mode(RESTART_DLOAD);
1355 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1356 kernel_restart(NULL);
1357 /* Not required, represents that command isnt sent to modem */
1358 return 0;
1359 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001360 /* Check for polling for Apps only DIAG */
1361 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1362 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001363 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001364 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001365 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001366 for (i = 0; i < 3; i++)
1367 driver->apps_rsp_buf[i] = *(buf+i);
1368 for (i = 0; i < 13; i++)
1369 driver->apps_rsp_buf[i+3] = 0;
1370
1371 ENCODE_RSP_AND_SEND(15);
1372 return 0;
1373 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001374 }
1375 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001376 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001377 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001378 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001379 for (i = 0; i < 55; i++)
1380 driver->apps_rsp_buf[i] = 0;
1381
1382 ENCODE_RSP_AND_SEND(54);
1383 return 0;
1384 }
1385 /* respond to 0x7c command */
1386 else if (*buf == 0x7c) {
1387 driver->apps_rsp_buf[0] = 0x7c;
1388 for (i = 1; i < 8; i++)
1389 driver->apps_rsp_buf[i] = 0;
1390 /* Tools ID for APQ 8060 */
1391 *(int *)(driver->apps_rsp_buf + 8) =
1392 chk_config_get_id();
1393 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1394 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1395 ENCODE_RSP_AND_SEND(13);
1396 return 0;
1397 }
1398 }
1399#endif
1400 return packet_type;
1401}
1402
1403#ifdef CONFIG_DIAG_OVER_USB
1404void diag_send_error_rsp(int index)
1405{
1406 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301407
1408 if (index > 490) {
1409 pr_err("diag: error response too huge, aborting\n");
1410 return;
1411 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001412 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1413 for (i = 0; i < index; i++)
1414 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1415 ENCODE_RSP_AND_SEND(index - 3);
1416}
1417#else
1418static inline void diag_send_error_rsp(int index) {}
1419#endif
1420
1421void diag_process_hdlc(void *data, unsigned len)
1422{
1423 struct diag_hdlc_decode_type hdlc;
1424 int ret, type = 0;
1425 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1426 hdlc.dest_ptr = driver->hdlc_buf;
1427 hdlc.dest_size = USB_MAX_OUT_BUF;
1428 hdlc.src_ptr = data;
1429 hdlc.src_size = len;
1430 hdlc.src_idx = 0;
1431 hdlc.dest_idx = 0;
1432 hdlc.escaping = 0;
1433
1434 ret = diag_hdlc_decode(&hdlc);
1435
1436 if (ret)
1437 type = diag_process_apps_pkt(driver->hdlc_buf,
1438 hdlc.dest_idx - 3);
1439 else if (driver->debug_flag) {
1440 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1441 " errors or partial packet received, packet"
1442 " length = %d\n", len);
1443 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1444 DUMP_PREFIX_ADDRESS, data, len, 1);
1445 driver->debug_flag = 0;
1446 }
1447 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001448 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001449 diag_send_error_rsp(hdlc.dest_idx);
1450 type = 0;
1451 }
1452 /* implies this packet is NOT meant for apps */
1453 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001454 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001455 diag_send_error_rsp(hdlc.dest_idx);
1456 } else { /* APQ 8060, Let Q6 respond */
1457 if (driver->chqdsp)
1458 smd_write(driver->chqdsp, driver->hdlc_buf,
1459 hdlc.dest_idx - 3);
1460 }
1461 type = 0;
1462 }
1463
1464#ifdef DIAG_DEBUG
1465 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1466 for (i = 0; i < hdlc.dest_idx; i++)
1467 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1468 driver->hdlc_buf)+i));
1469#endif /* DIAG DEBUG */
1470 /* ignore 2 bytes for CRC, one for 7E and send */
1471 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1472 APPEND_DEBUG('g');
1473 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1474 APPEND_DEBUG('h');
1475#ifdef DIAG_DEBUG
1476 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1477 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1478 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1479#endif /* DIAG DEBUG */
1480 }
1481}
1482
1483#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001484/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1485#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001486#define N_LEGACY_READ 1
1487
1488int diagfwd_connect(void)
1489{
1490 int err;
1491
1492 printk(KERN_DEBUG "diag: USB connected\n");
1493 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1494 N_LEGACY_READ);
1495 if (err)
1496 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1497
1498 driver->usb_connected = 1;
1499 driver->in_busy_1 = 0;
1500 driver->in_busy_2 = 0;
1501 driver->in_busy_qdsp_1 = 0;
1502 driver->in_busy_qdsp_2 = 0;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301503 driver->in_busy_wcnss_1 = 0;
1504 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001505
1506 /* Poll SMD channels to check for data*/
1507 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1508 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1509 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001510 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001511 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1512 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1513 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001514 /* Poll USB channel to check for data*/
1515 queue_work(driver->diag_wq, &(driver->diag_read_work));
1516#ifdef CONFIG_DIAG_SDIO_PIPE
1517 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1518 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1519 diagfwd_connect_sdio();
1520 else
1521 printk(KERN_INFO "diag: No USB MDM ch");
1522 }
1523#endif
1524 return 0;
1525}
1526
1527int diagfwd_disconnect(void)
1528{
1529 printk(KERN_DEBUG "diag: USB disconnected\n");
1530 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001531 driver->debug_flag = 1;
1532 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001533 if (driver->logging_mode == USB_MODE) {
1534 driver->in_busy_1 = 1;
1535 driver->in_busy_2 = 1;
1536 driver->in_busy_qdsp_1 = 1;
1537 driver->in_busy_qdsp_2 = 1;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301538 driver->in_busy_wcnss_1 = 1;
1539 driver->in_busy_wcnss_2 = 1;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001540 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001541#ifdef CONFIG_DIAG_SDIO_PIPE
1542 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1543 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1544 diagfwd_disconnect_sdio();
1545#endif
1546 /* TBD - notify and flow control SMD */
1547 return 0;
1548}
1549
1550int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1551{
1552 unsigned char *buf = diag_write_ptr->buf;
1553 /*Determine if the write complete is for data from modem/apps/q6 */
1554 /* Need a context variable here instead */
1555 if (buf == (void *)driver->buf_in_1) {
1556 driver->in_busy_1 = 0;
1557 APPEND_DEBUG('o');
1558 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1559 } else if (buf == (void *)driver->buf_in_2) {
1560 driver->in_busy_2 = 0;
1561 APPEND_DEBUG('O');
1562 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1563 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1564 driver->in_busy_qdsp_1 = 0;
1565 APPEND_DEBUG('p');
1566 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1567 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1568 driver->in_busy_qdsp_2 = 0;
1569 APPEND_DEBUG('P');
1570 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
Ashay Jaiswal29620122012-03-21 12:02:36 +05301571 } else if (buf == driver->buf_in_wcnss_1) {
1572 driver->in_busy_wcnss_1 = 0;
1573 APPEND_DEBUG('r');
1574 queue_work(driver->diag_wq,
1575 &(driver->diag_read_smd_wcnss_work));
1576 } else if (buf == driver->buf_in_wcnss_2) {
1577 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001578 APPEND_DEBUG('R');
1579 queue_work(driver->diag_wq,
1580 &(driver->diag_read_smd_wcnss_work));
1581 }
1582#ifdef CONFIG_DIAG_SDIO_PIPE
1583 else if (buf == (void *)driver->buf_in_sdio)
1584 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001585 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001586 diagfwd_write_complete_sdio();
1587 else
1588 pr_err("diag: Incorrect buffer pointer while WRITE");
1589#endif
1590 else {
1591 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1592 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1593 POOL_TYPE_WRITE_STRUCT);
1594 APPEND_DEBUG('q');
1595 }
1596 return 0;
1597}
1598
1599int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1600{
1601 int status = diag_read_ptr->status;
1602 unsigned char *buf = diag_read_ptr->buf;
1603
1604 /* Determine if the read complete is for data on legacy/mdm ch */
1605 if (buf == (void *)driver->usb_buf_out) {
1606 driver->read_len_legacy = diag_read_ptr->actual;
1607 APPEND_DEBUG('s');
1608#ifdef DIAG_DEBUG
1609 printk(KERN_INFO "read data from USB, pkt length %d",
1610 diag_read_ptr->actual);
1611 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1612 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1613 diag_read_ptr->actual, 1);
1614#endif /* DIAG DEBUG */
1615 if (driver->logging_mode == USB_MODE) {
1616 if (status != -ECONNRESET && status != -ESHUTDOWN)
1617 queue_work(driver->diag_wq,
1618 &(driver->diag_proc_hdlc_work));
1619 else
1620 queue_work(driver->diag_wq,
1621 &(driver->diag_read_work));
1622 }
1623 }
1624#ifdef CONFIG_DIAG_SDIO_PIPE
1625 else if (buf == (void *)driver->usb_buf_mdm_out) {
1626 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001627 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001628 driver->read_len_mdm = diag_read_ptr->actual;
1629 diagfwd_read_complete_sdio();
1630 } else
1631 pr_err("diag: Incorrect buffer pointer while READ");
1632 }
1633#endif
1634 else
1635 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1636
1637 return 0;
1638}
1639
1640void diag_read_work_fn(struct work_struct *work)
1641{
1642 APPEND_DEBUG('d');
1643 driver->usb_read_ptr->buf = driver->usb_buf_out;
1644 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1645 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1646 APPEND_DEBUG('e');
1647}
1648
1649void diag_process_hdlc_fn(struct work_struct *work)
1650{
1651 APPEND_DEBUG('D');
1652 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1653 diag_read_work_fn(work);
1654 APPEND_DEBUG('E');
1655}
1656
1657void diag_usb_legacy_notifier(void *priv, unsigned event,
1658 struct diag_request *d_req)
1659{
1660 switch (event) {
1661 case USB_DIAG_CONNECT:
1662 diagfwd_connect();
1663 break;
1664 case USB_DIAG_DISCONNECT:
1665 diagfwd_disconnect();
1666 break;
1667 case USB_DIAG_READ_DONE:
1668 diagfwd_read_complete(d_req);
1669 break;
1670 case USB_DIAG_WRITE_DONE:
1671 diagfwd_write_complete(d_req);
1672 break;
1673 default:
1674 printk(KERN_ERR "Unknown event from USB diag\n");
1675 break;
1676 }
1677}
1678
1679#endif /* DIAG OVER USB */
1680
1681static void diag_smd_notify(void *ctxt, unsigned event)
1682{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001683 if (event == SMD_EVENT_CLOSE) {
1684 pr_info("diag: clean modem registration\n");
1685 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001686 driver->ch = 0;
1687 return;
1688 } else if (event == SMD_EVENT_OPEN) {
1689 driver->ch = ch_temp;
1690 }
1691 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001692}
1693
1694#if defined(CONFIG_MSM_N_WAY_SMD)
1695static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1696{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001697 if (event == SMD_EVENT_CLOSE) {
1698 pr_info("diag: clean lpass registration\n");
1699 diag_clear_reg(QDSP_PROC);
1700 driver->chqdsp = 0;
1701 return;
1702 } else if (event == SMD_EVENT_OPEN) {
1703 driver->chqdsp = chqdsp_temp;
1704 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001705 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1706}
1707#endif
1708
1709static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1710{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001711 if (event == SMD_EVENT_CLOSE) {
1712 pr_info("diag: clean wcnss registration\n");
1713 diag_clear_reg(WCNSS_PROC);
1714 driver->ch_wcnss = 0;
1715 return;
1716 } else if (event == SMD_EVENT_OPEN) {
1717 driver->ch_wcnss = ch_wcnss_temp;
1718 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001719 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1720}
1721
1722static int diag_smd_probe(struct platform_device *pdev)
1723{
1724 int r = 0;
1725
Shalabh Jaineefee052011-11-08 23:46:03 -08001726 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001727 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001728 ch_temp = driver->ch;
1729 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001730#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001731 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001732 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1733 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001734 chqdsp_temp = driver->chqdsp;
1735 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001736#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001737 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001738 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1739 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001740 ch_wcnss_temp = driver->ch_wcnss;
1741 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001742 pm_runtime_set_active(&pdev->dev);
1743 pm_runtime_enable(&pdev->dev);
1744 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1745
1746 return 0;
1747}
1748
1749static int diagfwd_runtime_suspend(struct device *dev)
1750{
1751 dev_dbg(dev, "pm_runtime: suspending...\n");
1752 return 0;
1753}
1754
1755static int diagfwd_runtime_resume(struct device *dev)
1756{
1757 dev_dbg(dev, "pm_runtime: resuming...\n");
1758 return 0;
1759}
1760
1761static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1762 .runtime_suspend = diagfwd_runtime_suspend,
1763 .runtime_resume = diagfwd_runtime_resume,
1764};
1765
1766static struct platform_driver msm_smd_ch1_driver = {
1767
1768 .probe = diag_smd_probe,
1769 .driver = {
1770 .name = "DIAG",
1771 .owner = THIS_MODULE,
1772 .pm = &diagfwd_dev_pm_ops,
1773 },
1774};
1775
1776static struct platform_driver diag_smd_lite_driver = {
1777
1778 .probe = diag_smd_probe,
1779 .driver = {
1780 .name = "APPS_RIVA_DATA",
1781 .owner = THIS_MODULE,
1782 .pm = &diagfwd_dev_pm_ops,
1783 },
1784};
1785
1786void diagfwd_init(void)
1787{
1788 diag_debug_buf_idx = 0;
1789 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001790 driver->use_device_tree = has_device_tree();
Shalabh Jaina06c6d72012-04-30 13:40:35 -07001791 mutex_init(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001792
1793 if (driver->event_mask == NULL) {
1794 driver->event_mask = kzalloc(sizeof(
1795 struct diag_ctrl_event_mask), GFP_KERNEL);
1796 if (driver->event_mask == NULL)
1797 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001798 kmemleak_not_leak(driver->event_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001799 }
1800 if (driver->msg_mask == NULL) {
1801 driver->msg_mask = kzalloc(sizeof(
1802 struct diag_ctrl_msg_mask), GFP_KERNEL);
1803 if (driver->msg_mask == NULL)
1804 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001805 kmemleak_not_leak(driver->msg_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001806 }
1807 if (driver->log_mask == NULL) {
1808 driver->log_mask = kzalloc(sizeof(
1809 struct diag_ctrl_log_mask), GFP_KERNEL);
1810 if (driver->log_mask == NULL)
1811 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001812 kmemleak_not_leak(driver->log_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001813 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001814 if (driver->buf_in_1 == NULL) {
1815 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1816 if (driver->buf_in_1 == NULL)
1817 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001818 kmemleak_not_leak(driver->buf_in_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001819 }
1820 if (driver->buf_in_2 == NULL) {
1821 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1822 if (driver->buf_in_2 == NULL)
1823 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001824 kmemleak_not_leak(driver->buf_in_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001825 }
1826 if (driver->buf_in_qdsp_1 == NULL) {
1827 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1828 if (driver->buf_in_qdsp_1 == NULL)
1829 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001830 kmemleak_not_leak(driver->buf_in_qdsp_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001831 }
1832 if (driver->buf_in_qdsp_2 == NULL) {
1833 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1834 if (driver->buf_in_qdsp_2 == NULL)
1835 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001836 kmemleak_not_leak(driver->buf_in_qdsp_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001837 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301838 if (driver->buf_in_wcnss_1 == NULL) {
1839 driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1840 if (driver->buf_in_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001841 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001842 kmemleak_not_leak(driver->buf_in_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001843 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301844 if (driver->buf_in_wcnss_2 == NULL) {
1845 driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1846 if (driver->buf_in_wcnss_2 == NULL)
1847 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001848 kmemleak_not_leak(driver->buf_in_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301849 }
1850
Shalabh Jain321c8b52012-02-22 12:37:06 -08001851 if (driver->buf_msg_mask_update == NULL) {
1852 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1853 GFP_KERNEL);
1854 if (driver->buf_msg_mask_update == NULL)
1855 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001856 kmemleak_not_leak(driver->buf_msg_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001857 }
1858 if (driver->buf_log_mask_update == NULL) {
1859 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1860 GFP_KERNEL);
1861 if (driver->buf_log_mask_update == NULL)
1862 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001863 kmemleak_not_leak(driver->buf_log_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001864 }
1865 if (driver->buf_event_mask_update == NULL) {
1866 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1867 GFP_KERNEL);
1868 if (driver->buf_event_mask_update == NULL)
1869 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001870 kmemleak_not_leak(driver->buf_event_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001871 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001872 if (driver->usb_buf_out == NULL &&
1873 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1874 GFP_KERNEL)) == NULL)
1875 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001876 kmemleak_not_leak(driver->usb_buf_out);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001877 if (driver->hdlc_buf == NULL
1878 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1879 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001880 kmemleak_not_leak(driver->hdlc_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001881 if (driver->user_space_data == NULL)
1882 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1883 if (driver->user_space_data == NULL)
1884 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001885 kmemleak_not_leak(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001886 if (driver->msg_masks == NULL
1887 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1888 GFP_KERNEL)) == NULL)
1889 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001890 kmemleak_not_leak(driver->msg_masks);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001891 diag_create_msg_mask_table();
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001892 diag_event_num_bytes = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001893 if (driver->log_masks == NULL &&
1894 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1895 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001896 kmemleak_not_leak(driver->log_masks);
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -07001897 driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001898 if (driver->event_masks == NULL &&
1899 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1900 GFP_KERNEL)) == NULL)
1901 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001902 kmemleak_not_leak(driver->event_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001903 if (driver->client_map == NULL &&
1904 (driver->client_map = kzalloc
1905 ((driver->num_clients) * sizeof(struct diag_client_map),
1906 GFP_KERNEL)) == NULL)
1907 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001908 kmemleak_not_leak(driver->client_map);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001909 if (driver->buf_tbl == NULL)
1910 driver->buf_tbl = kzalloc(buf_tbl_size *
1911 sizeof(struct diag_write_device), GFP_KERNEL);
1912 if (driver->buf_tbl == NULL)
1913 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001914 kmemleak_not_leak(driver->buf_tbl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001915 if (driver->data_ready == NULL &&
1916 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1917 , GFP_KERNEL)) == NULL)
1918 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001919 kmemleak_not_leak(driver->data_ready);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001920 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001921 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001922 sizeof(struct diag_master_table),
1923 GFP_KERNEL)) == NULL)
1924 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001925 kmemleak_not_leak(driver->table);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001926 if (driver->write_ptr_1 == NULL) {
1927 driver->write_ptr_1 = kzalloc(
1928 sizeof(struct diag_request), GFP_KERNEL);
1929 if (driver->write_ptr_1 == NULL)
1930 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001931 kmemleak_not_leak(driver->write_ptr_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001932 }
1933 if (driver->write_ptr_2 == NULL) {
1934 driver->write_ptr_2 = kzalloc(
1935 sizeof(struct diag_request), GFP_KERNEL);
1936 if (driver->write_ptr_2 == NULL)
1937 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001938 kmemleak_not_leak(driver->write_ptr_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001939 }
1940 if (driver->write_ptr_qdsp_1 == NULL) {
1941 driver->write_ptr_qdsp_1 = kzalloc(
1942 sizeof(struct diag_request), GFP_KERNEL);
1943 if (driver->write_ptr_qdsp_1 == NULL)
1944 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001945 kmemleak_not_leak(driver->write_ptr_qdsp_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001946 }
1947 if (driver->write_ptr_qdsp_2 == NULL) {
1948 driver->write_ptr_qdsp_2 = kzalloc(
1949 sizeof(struct diag_request), GFP_KERNEL);
1950 if (driver->write_ptr_qdsp_2 == NULL)
1951 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001952 kmemleak_not_leak(driver->write_ptr_qdsp_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001953 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301954 if (driver->write_ptr_wcnss_1 == NULL) {
1955 driver->write_ptr_wcnss_1 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001956 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301957 if (driver->write_ptr_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001958 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001959 kmemleak_not_leak(driver->write_ptr_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001960 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301961 if (driver->write_ptr_wcnss_2 == NULL) {
1962 driver->write_ptr_wcnss_2 = kzalloc(
1963 sizeof(struct diag_request), GFP_KERNEL);
1964 if (driver->write_ptr_wcnss_2 == NULL)
1965 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001966 kmemleak_not_leak(driver->write_ptr_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301967 }
1968
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001969 if (driver->usb_read_ptr == NULL) {
1970 driver->usb_read_ptr = kzalloc(
1971 sizeof(struct diag_request), GFP_KERNEL);
1972 if (driver->usb_read_ptr == NULL)
1973 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001974 kmemleak_not_leak(driver->usb_read_ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001975 }
1976 if (driver->pkt_buf == NULL &&
1977 (driver->pkt_buf = kzalloc(PKT_SIZE,
1978 GFP_KERNEL)) == NULL)
1979 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001980 kmemleak_not_leak(driver->pkt_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001981 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001982 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001983 if (driver->apps_rsp_buf == NULL)
1984 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001985 kmemleak_not_leak(driver->apps_rsp_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001986 }
1987 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1988#ifdef CONFIG_DIAG_OVER_USB
1989 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1990 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001991 INIT_WORK(&(driver->diag_modem_mask_update_work),
1992 diag_modem_mask_update_fn);
1993 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
1994 diag_qdsp_mask_update_fn);
1995 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
1996 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001997 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
1998 diag_usb_legacy_notifier);
1999 if (IS_ERR(driver->legacy_ch)) {
2000 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
2001 goto err;
2002 }
2003#endif
2004 platform_driver_register(&msm_smd_ch1_driver);
2005 platform_driver_register(&diag_smd_lite_driver);
2006
2007 return;
2008err:
2009 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08002010 kfree(driver->event_mask);
2011 kfree(driver->log_mask);
2012 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002013 kfree(driver->buf_in_1);
2014 kfree(driver->buf_in_2);
2015 kfree(driver->buf_in_qdsp_1);
2016 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302017 kfree(driver->buf_in_wcnss_1);
2018 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002019 kfree(driver->buf_msg_mask_update);
2020 kfree(driver->buf_log_mask_update);
2021 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002022 kfree(driver->usb_buf_out);
2023 kfree(driver->hdlc_buf);
2024 kfree(driver->msg_masks);
2025 kfree(driver->log_masks);
2026 kfree(driver->event_masks);
2027 kfree(driver->client_map);
2028 kfree(driver->buf_tbl);
2029 kfree(driver->data_ready);
2030 kfree(driver->table);
2031 kfree(driver->pkt_buf);
2032 kfree(driver->write_ptr_1);
2033 kfree(driver->write_ptr_2);
2034 kfree(driver->write_ptr_qdsp_1);
2035 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302036 kfree(driver->write_ptr_wcnss_1);
2037 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002038 kfree(driver->usb_read_ptr);
2039 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002040 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002041 if (driver->diag_wq)
2042 destroy_workqueue(driver->diag_wq);
2043}
2044
2045void diagfwd_exit(void)
2046{
2047 smd_close(driver->ch);
2048 smd_close(driver->chqdsp);
2049 smd_close(driver->ch_wcnss);
2050 driver->ch = 0; /* SMD can make this NULL */
2051 driver->chqdsp = 0;
2052 driver->ch_wcnss = 0;
2053#ifdef CONFIG_DIAG_OVER_USB
2054 if (driver->usb_connected)
2055 usb_diag_free_req(driver->legacy_ch);
2056 usb_diag_close(driver->legacy_ch);
2057#endif
2058 platform_driver_unregister(&msm_smd_ch1_driver);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -07002059 platform_driver_unregister(&msm_diag_dci_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002060 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002061 kfree(driver->event_mask);
2062 kfree(driver->log_mask);
2063 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002064 kfree(driver->buf_in_1);
2065 kfree(driver->buf_in_2);
2066 kfree(driver->buf_in_qdsp_1);
2067 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302068 kfree(driver->buf_in_wcnss_1);
2069 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002070 kfree(driver->buf_msg_mask_update);
2071 kfree(driver->buf_log_mask_update);
2072 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002073 kfree(driver->usb_buf_out);
2074 kfree(driver->hdlc_buf);
2075 kfree(driver->msg_masks);
2076 kfree(driver->log_masks);
2077 kfree(driver->event_masks);
2078 kfree(driver->client_map);
2079 kfree(driver->buf_tbl);
2080 kfree(driver->data_ready);
2081 kfree(driver->table);
2082 kfree(driver->pkt_buf);
2083 kfree(driver->write_ptr_1);
2084 kfree(driver->write_ptr_2);
2085 kfree(driver->write_ptr_qdsp_1);
2086 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302087 kfree(driver->write_ptr_wcnss_1);
2088 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002089 kfree(driver->usb_read_ptr);
2090 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002091 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002092 destroy_workqueue(driver->diag_wq);
2093}