blob: a920f5697f295bba3809c54620f233cb86d7c60c [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
Shalabh Jainf7228dc2012-05-23 17:32:05 -0700303#ifdef CONFIG_DIAG_BRIDGE_CODE
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700304 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)
Shalabh Jainf7228dc2012-05-23 17:32:05 -0700308 queue_work(driver->diag_bridge_wq,
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700309 &(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
Shalabh Jainf7228dc2012-05-23 17:32:05 -0700355#ifdef CONFIG_DIAG_BRIDGE_CODE
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800356 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");
Shalabh Jainf7228dc2012-05-23 17:32:05 -0700363 } else if (proc_num == SMUX_DATA) {
364 write_ptr->buf = buf;
365 pr_debug("diag: writing SMUX data\n");
366 err = usb_diag_write(driver->mdm_ch, write_ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700367 }
368#endif
369 APPEND_DEBUG('d');
370 }
371#endif /* DIAG OVER USB */
372 return err;
373}
374
375void __diag_smd_wcnss_send_req(void)
376{
Ashay Jaiswal29620122012-03-21 12:02:36 +0530377 void *buf = NULL;
378 int *in_busy_wcnss_ptr = NULL;
379 struct diag_request *write_ptr_wcnss = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700380
Ashay Jaiswal29620122012-03-21 12:02:36 +0530381 if (!driver->in_busy_wcnss_1) {
382 buf = driver->buf_in_wcnss_1;
383 write_ptr_wcnss = driver->write_ptr_wcnss_1;
384 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_1);
385 } else if (!driver->in_busy_wcnss_2) {
386 buf = driver->buf_in_wcnss_2;
387 write_ptr_wcnss = driver->write_ptr_wcnss_2;
388 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_2);
389 }
390
391 if (driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700392 int r = smd_read_avail(driver->ch_wcnss);
393 if (r > IN_BUF_SIZE) {
394 if (r < MAX_IN_BUF_SIZE) {
395 pr_err("diag: wcnss packets > %d bytes", r);
396 buf = krealloc(buf, r, GFP_KERNEL);
397 } else {
398 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
399 return;
400 }
401 }
402 if (r > 0) {
403 if (!buf) {
404 pr_err("Out of diagmem for wcnss\n");
405 } else {
406 APPEND_DEBUG('i');
407 smd_read(driver->ch_wcnss, buf, r);
408 APPEND_DEBUG('j');
409 write_ptr_wcnss->length = r;
410 *in_busy_wcnss_ptr = 1;
411 diag_device_write(buf, WCNSS_DATA,
412 write_ptr_wcnss);
413 }
414 }
415 }
416}
417
418void __diag_smd_qdsp_send_req(void)
419{
420 void *buf = NULL;
421 int *in_busy_qdsp_ptr = NULL;
422 struct diag_request *write_ptr_qdsp = NULL;
423
424 if (!driver->in_busy_qdsp_1) {
425 buf = driver->buf_in_qdsp_1;
426 write_ptr_qdsp = driver->write_ptr_qdsp_1;
427 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1);
428 } else if (!driver->in_busy_qdsp_2) {
429 buf = driver->buf_in_qdsp_2;
430 write_ptr_qdsp = driver->write_ptr_qdsp_2;
431 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2);
432 }
433
434 if (driver->chqdsp && buf) {
435 int r = smd_read_avail(driver->chqdsp);
436
437 if (r > IN_BUF_SIZE) {
438 if (r < MAX_IN_BUF_SIZE) {
439 pr_err("diag: SMD sending in "
440 "packets upto %d bytes", r);
441 buf = krealloc(buf, r, GFP_KERNEL);
442 } else {
443 pr_err("diag: SMD sending in "
444 "packets more than %d bytes", MAX_IN_BUF_SIZE);
445 return;
446 }
447 }
448 if (r > 0) {
449 if (!buf)
450 printk(KERN_INFO "Out of diagmem for QDSP\n");
451 else {
452 APPEND_DEBUG('i');
453 smd_read(driver->chqdsp, buf, r);
454 APPEND_DEBUG('j');
455 write_ptr_qdsp->length = r;
456 *in_busy_qdsp_ptr = 1;
457 diag_device_write(buf, QDSP_DATA,
458 write_ptr_qdsp);
459 }
460 }
461 }
462}
463
464static void diag_print_mask_table(void)
465{
466/* Enable this to print mask table when updated */
467#ifdef MASK_DEBUG
468 int first;
469 int last;
470 uint8_t *ptr = driver->msg_masks;
471 int i = 0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700472 pr_info("diag: F3 message mask table\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700473 while (*(uint32_t *)(ptr + 4)) {
474 first = *(uint32_t *)ptr;
475 ptr += 4;
476 last = *(uint32_t *)ptr;
477 ptr += 4;
478 printk(KERN_INFO "SSID %d - %d\n", first, last);
479 for (i = 0 ; i <= last - first ; i++)
480 printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700481 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700482
483 }
484#endif
485}
486
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700487void diag_create_msg_mask_table(void)
488{
489 uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
490
491 CREATE_MSG_MASK_TBL_ROW(0);
492 CREATE_MSG_MASK_TBL_ROW(1);
493 CREATE_MSG_MASK_TBL_ROW(2);
494 CREATE_MSG_MASK_TBL_ROW(3);
495 CREATE_MSG_MASK_TBL_ROW(4);
496 CREATE_MSG_MASK_TBL_ROW(5);
497 CREATE_MSG_MASK_TBL_ROW(6);
498 CREATE_MSG_MASK_TBL_ROW(7);
499 CREATE_MSG_MASK_TBL_ROW(8);
500 CREATE_MSG_MASK_TBL_ROW(9);
501 CREATE_MSG_MASK_TBL_ROW(10);
502 CREATE_MSG_MASK_TBL_ROW(11);
503 CREATE_MSG_MASK_TBL_ROW(12);
504 CREATE_MSG_MASK_TBL_ROW(13);
505 CREATE_MSG_MASK_TBL_ROW(14);
506 CREATE_MSG_MASK_TBL_ROW(15);
507 CREATE_MSG_MASK_TBL_ROW(16);
508 CREATE_MSG_MASK_TBL_ROW(17);
509 CREATE_MSG_MASK_TBL_ROW(18);
510 CREATE_MSG_MASK_TBL_ROW(19);
511 CREATE_MSG_MASK_TBL_ROW(20);
512 CREATE_MSG_MASK_TBL_ROW(21);
513 CREATE_MSG_MASK_TBL_ROW(22);
514}
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700515
516static void diag_set_msg_mask(int rt_mask)
517{
518 int first_ssid, last_ssid, i;
519 uint8_t *parse_ptr, *ptr = driver->msg_masks;
520
521 mutex_lock(&driver->diagchar_mutex);
522 while (*(uint32_t *)(ptr + 4)) {
523 first_ssid = *(uint32_t *)ptr;
524 ptr += 4;
525 last_ssid = *(uint32_t *)ptr;
526 ptr += 4;
527 parse_ptr = ptr;
528 pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
529 for (i = 0; i < last_ssid - first_ssid + 1; i++) {
530 *(int *)parse_ptr = rt_mask;
531 parse_ptr += 4;
532 }
533 ptr += MAX_SSID_PER_RANGE * 4;
534 }
535 mutex_unlock(&driver->diagchar_mutex);
536}
537
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700538static void diag_update_msg_mask(int start, int end , uint8_t *buf)
539{
540 int found = 0;
541 int first;
542 int last;
543 uint8_t *ptr = driver->msg_masks;
544 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
545 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
546
547 mutex_lock(&driver->diagchar_mutex);
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530548
Shalabh Jain321c8b52012-02-22 12:37:06 -0800549 /* First SSID can be zero : So check that last is non-zero */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550 while (*(uint32_t *)(ptr + 4)) {
551 first = *(uint32_t *)ptr;
552 ptr += 4;
553 last = *(uint32_t *)ptr;
554 ptr += 4;
555 if (start >= first && start <= last) {
556 ptr += (start - first)*4;
557 if (end <= last)
558 if (CHK_OVERFLOW(ptr_buffer_start, ptr,
559 ptr_buffer_end,
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700560 (((end - start)+1)*4))) {
561 pr_debug("diag: update ssid start %d,"
562 " end %d\n", start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700563 memcpy(ptr, buf , ((end - start)+1)*4);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700564 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700565 printk(KERN_CRIT "Not enough"
566 " buffer space for"
567 " MSG_MASK\n");
568 else
569 printk(KERN_INFO "Unable to copy"
570 " mask change\n");
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530571
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700572 found = 1;
573 break;
574 } else {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700575 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700576 }
577 }
578 /* Entry was not found - add new table */
579 if (!found) {
580 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
581 8 + ((end - start) + 1)*4)) {
582 memcpy(ptr, &(start) , 4);
583 ptr += 4;
584 memcpy(ptr, &(end), 4);
585 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700586 pr_debug("diag: adding NEW ssid start %d, end %d\n",
587 start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700588 memcpy(ptr, buf , ((end - start) + 1)*4);
589 } else
590 printk(KERN_CRIT " Not enough buffer"
591 " space for MSG_MASK\n");
592 }
593 mutex_unlock(&driver->diagchar_mutex);
594 diag_print_mask_table();
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530595
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700596}
597
Shalabh Jaina51f2592012-03-08 14:36:35 -0800598void diag_toggle_event_mask(int toggle)
599{
600 uint8_t *ptr = driver->event_masks;
601
602 mutex_lock(&driver->diagchar_mutex);
603 if (toggle)
604 memset(ptr, 0xFF, EVENT_MASK_SIZE);
605 else
606 memset(ptr, 0, EVENT_MASK_SIZE);
607 mutex_unlock(&driver->diagchar_mutex);
608}
609
Shalabh Jain321c8b52012-02-22 12:37:06 -0800610static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700611{
612 uint8_t *ptr = driver->event_masks;
613 uint8_t *temp = buf + 2;
614
615 mutex_lock(&driver->diagchar_mutex);
616 if (!toggle)
617 memset(ptr, 0 , EVENT_MASK_SIZE);
618 else
619 if (CHK_OVERFLOW(ptr, ptr,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800620 ptr+EVENT_MASK_SIZE, num_bytes))
621 memcpy(ptr, temp , num_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700622 else
623 printk(KERN_CRIT "Not enough buffer space "
624 "for EVENT_MASK\n");
625 mutex_unlock(&driver->diagchar_mutex);
626}
627
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700628static void diag_disable_log_mask(void)
629{
630 int i = 0;
631 struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
632
633 pr_debug("diag: disable log masks\n");
634 mutex_lock(&driver->diagchar_mutex);
635 for (i = 0; i < MAX_EQUIP_ID; i++) {
636 pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
637 if (!(parse_ptr->equip_id)) /* Reached a null entry */
638 break;
639 memset(driver->log_masks + parse_ptr->index, 0,
640 (parse_ptr->num_items + 7)/8);
641 parse_ptr++;
642 }
643 mutex_unlock(&driver->diagchar_mutex);
644}
645
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700646static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
647{
648 uint8_t *temp = buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700649 int i = 0;
650 unsigned char *ptr_data;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700651 int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700652 struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700653
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700654 pr_debug("diag: received equip id = %d\n", equip_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700655 mutex_lock(&driver->diagchar_mutex);
656 /* Check if we already know index of this equipment ID */
657 for (i = 0; i < MAX_EQUIP_ID; i++) {
658 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
659 offset = ptr->index;
660 break;
661 }
662 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
Shalabh Jain321c8b52012-02-22 12:37:06 -0800663 /* Reached a null entry */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700664 ptr->equip_id = equip_id;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800665 ptr->num_items = num_items;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700666 ptr->index = driver->log_masks_length;
667 offset = driver->log_masks_length;
668 driver->log_masks_length += ((num_items+7)/8);
669 break;
670 }
671 ptr++;
672 }
673 ptr_data = driver->log_masks + offset;
674 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
675 + LOG_MASK_SIZE, (num_items+7)/8))
676 memcpy(ptr_data, temp , (num_items+7)/8);
677 else
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700678 pr_err("diag: Not enough buffer space for LOG_MASK\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700679 mutex_unlock(&driver->diagchar_mutex);
680}
681
682static void diag_update_pkt_buffer(unsigned char *buf)
683{
684 unsigned char *ptr = driver->pkt_buf;
685 unsigned char *temp = buf;
686
687 mutex_lock(&driver->diagchar_mutex);
688 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
689 memcpy(ptr, temp , driver->pkt_length);
690 else
691 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
692 mutex_unlock(&driver->diagchar_mutex);
693}
694
695void diag_update_userspace_clients(unsigned int type)
696{
697 int i;
698
699 mutex_lock(&driver->diagchar_mutex);
700 for (i = 0; i < driver->num_clients; i++)
701 if (driver->client_map[i].pid != 0)
702 driver->data_ready[i] |= type;
703 wake_up_interruptible(&driver->wait_q);
704 mutex_unlock(&driver->diagchar_mutex);
705}
706
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700707void diag_update_sleeping_process(int process_id, int data_type)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700708{
709 int i;
710
711 mutex_lock(&driver->diagchar_mutex);
712 for (i = 0; i < driver->num_clients; i++)
713 if (driver->client_map[i].pid == process_id) {
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700714 driver->data_ready[i] |= data_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700715 break;
716 }
717 wake_up_interruptible(&driver->wait_q);
718 mutex_unlock(&driver->diagchar_mutex);
719}
720
721void diag_send_data(struct diag_master_table entry, unsigned char *buf,
722 int len, int type)
723{
724 driver->pkt_length = len;
725 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
726 diag_update_pkt_buffer(buf);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700727 diag_update_sleeping_process(entry.process_id, PKT_TYPE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700728 } else {
729 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700730 if (entry.client_id == MODEM_PROC && driver->ch) {
Shalabh Jain10f5f432012-01-11 11:45:44 +0530731 if (chk_apps_master() &&
Shalabh Jainc9f35092011-07-28 18:36:17 -0700732 (int)(*(char *)buf) == MODE_CMD)
Dixon Petersonff425d12011-12-06 18:12:35 -0800733 if ((int)(*(char *)(buf+1)) ==
734 RESET_ID)
Shalabh Jainc9f35092011-07-28 18:36:17 -0700735 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700736 smd_write(driver->ch, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700737 } else if (entry.client_id == QDSP_PROC &&
738 driver->chqdsp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700739 smd_write(driver->chqdsp, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700740 } else if (entry.client_id == WCNSS_PROC &&
741 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700742 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700743 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700744 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700745 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700746 }
747 }
748}
749
Shalabh Jain321c8b52012-02-22 12:37:06 -0800750void diag_modem_mask_update_fn(struct work_struct *work)
751{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700752 diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
753 ALL_SSID, MODEM_PROC);
754 diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800755 diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
756}
757
758void diag_qdsp_mask_update_fn(struct work_struct *work)
759{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700760 diag_send_msg_mask_update(driver->chqdsp_cntl, ALL_SSID,
761 ALL_SSID, QDSP_PROC);
762 diag_send_log_mask_update(driver->chqdsp_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800763 diag_send_event_mask_update(driver->chqdsp_cntl, diag_event_num_bytes);
764}
765
766void diag_wcnss_mask_update_fn(struct work_struct *work)
767{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700768 diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
769 ALL_SSID, WCNSS_PROC);
770 diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800771 diag_send_event_mask_update(driver->ch_wcnss_cntl,
772 diag_event_num_bytes);
773}
774
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700775void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800776{
777 void *buf = driver->buf_log_mask_update;
778 int header_size = sizeof(struct diag_ctrl_log_mask);
779 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700780 int i, size, wr_size = -ENOMEM, retry_count = 0, timer;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800781
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700782 mutex_lock(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800783 for (i = 0; i < MAX_EQUIP_ID; i++) {
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700784 size = (ptr->num_items+7)/8;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800785 /* reached null entry */
786 if ((ptr->equip_id == 0) && (ptr->index == 0))
787 break;
788 driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
789 driver->log_mask->num_items = ptr->num_items;
790 driver->log_mask->data_len = 11 + size;
791 driver->log_mask->stream_id = 1; /* 2, if dual stream */
792 driver->log_mask->status = 3; /* status for valid mask */
793 driver->log_mask->equip_id = ptr->equip_id;
794 driver->log_mask->log_mask_size = size;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700795 /* send only desired update, NOT ALL */
796 if (equip_id == ALL_EQUIP_ID || equip_id ==
797 driver->log_mask->equip_id) {
798 memcpy(buf, driver->log_mask, header_size);
799 memcpy(buf+header_size, driver->log_masks+ptr->index,
800 size);
801 if (ch) {
802 while (retry_count < 3) {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700803 wr_size = smd_write(ch, buf,
804 header_size + size);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700805 if (wr_size == -ENOMEM) {
806 retry_count++;
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700807 for (timer = 0; timer < 5;
808 timer++)
809 udelay(2000);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700810 } 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 }
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700825 mutex_unlock(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800826}
827
828void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
829{
830 void *buf = driver->buf_event_mask_update;
831 int header_size = sizeof(struct diag_ctrl_event_mask);
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700832 int wr_size = -ENOMEM, retry_count = 0, timer;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800833
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700834 mutex_lock(&driver->diag_cntl_mutex);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700835 if (num_bytes == 0) {
836 pr_debug("diag: event mask not set yet, so no update\n");
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700837 mutex_unlock(&driver->diag_cntl_mutex);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700838 return;
839 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800840 /* send event mask update */
841 driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
842 driver->event_mask->data_len = 7 + num_bytes;
843 driver->event_mask->stream_id = 1; /* 2, if dual stream */
844 driver->event_mask->status = 3; /* status for valid mask */
845 driver->event_mask->event_config = diag_event_config; /* event config */
846 driver->event_mask->event_mask_size = num_bytes;
847 memcpy(buf, driver->event_mask, header_size);
848 memcpy(buf+header_size, driver->event_masks, num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700849 if (ch) {
850 while (retry_count < 3) {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700851 wr_size = smd_write(ch, buf, header_size + num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700852 if (wr_size == -ENOMEM) {
853 retry_count++;
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700854 for (timer = 0; timer < 5; timer++)
855 udelay(2000);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700856 } else
857 break;
858 }
859 if (wr_size != header_size + num_bytes)
860 pr_err("diag: error writing event mask %d, tried %d\n",
861 wr_size, header_size + num_bytes);
862 } else
863 pr_err("diag: ch not valid for event update\n");
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700864 mutex_unlock(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800865}
866
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700867void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
868 int updated_ssid_last, int proc)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800869{
870 void *buf = driver->buf_msg_mask_update;
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700871 int first, last, size = -ENOMEM, retry_count = 0, timer;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800872 int header_size = sizeof(struct diag_ctrl_msg_mask);
873 uint8_t *ptr = driver->msg_masks;
874
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700875 mutex_lock(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800876 while (*(uint32_t *)(ptr + 4)) {
877 first = *(uint32_t *)ptr;
878 ptr += 4;
879 last = *(uint32_t *)ptr;
880 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700881 if ((updated_ssid_first >= first && updated_ssid_last <= last)
882 || (updated_ssid_first == ALL_SSID)) {
883 /* send f3 mask update */
884 driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
885 driver->msg_mask->msg_mask_size = last - first + 1;
886 driver->msg_mask->data_len = 11 +
887 4 * (driver->msg_mask->msg_mask_size);
888 driver->msg_mask->stream_id = 1; /* 2, if dual stream */
889 driver->msg_mask->status = 3; /* status valid mask */
890 driver->msg_mask->msg_mode = 0; /* Legcay mode */
891 driver->msg_mask->ssid_first = first;
892 driver->msg_mask->ssid_last = last;
893 memcpy(buf, driver->msg_mask, header_size);
894 memcpy(buf+header_size, ptr,
895 4 * (driver->msg_mask->msg_mask_size));
896 if (ch) {
897 while (retry_count < 3) {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700898 size = smd_write(ch, buf, header_size +
899 4*(driver->msg_mask->msg_mask_size));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700900 if (size == -ENOMEM) {
901 retry_count++;
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700902 for (timer = 0; timer < 5;
903 timer++)
904 udelay(2000);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700905 } else
906 break;
907 }
908 if (size != header_size +
909 4*(driver->msg_mask->msg_mask_size))
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700910 pr_err("diag: proc %d, msg mask update "
911 "fail %d, tried %d\n", proc, size,
912 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"
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700915 "ssid first %d, last %d on PROC %d\n", first, last, proc);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700916 } else
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700917 pr_err("diag: proc %d, ch invalid msg mask"
918 "update\n", proc);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700919 }
920 ptr += MAX_SSID_PER_RANGE*4;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800921 }
Shalabh Jaina06c6d72012-04-30 13:40:35 -0700922 mutex_unlock(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800923}
924
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700925static int diag_process_apps_pkt(unsigned char *buf, int len)
926{
927 uint16_t subsys_cmd_code;
928 int subsys_id, ssid_first, ssid_last, ssid_range;
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700929 int packet_type = 1, i, cmd_code, rt_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700930 unsigned char *temp = buf;
931 int data_type;
932#if defined(CONFIG_DIAG_OVER_USB)
933 int payload_length;
934 unsigned char *ptr;
935#endif
936
Shalabh Jain321c8b52012-02-22 12:37:06 -0800937 /* Set log masks */
938 if (*buf == 0x73 && *(int *)(buf+4) == 3) {
939 buf += 8;
940 /* Read Equip ID and pass as first param below*/
941 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
942 diag_update_userspace_clients(LOG_MASKS_TYPE);
943#if defined(CONFIG_DIAG_OVER_USB)
944 if (chk_apps_only()) {
945 driver->apps_rsp_buf[0] = 0x73;
946 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
947 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
948 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
949 for (i = 0; i < payload_length; i++)
950 *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700951 if (driver->ch_cntl)
952 diag_send_log_mask_update(driver->ch_cntl,
953 *(int *)buf);
954 if (driver->chqdsp_cntl)
955 diag_send_log_mask_update(driver->chqdsp_cntl,
956 *(int *)buf);
957 if (driver->ch_wcnss_cntl)
958 diag_send_log_mask_update(driver->ch_wcnss_cntl,
959 *(int *)buf);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800960 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
961 return 0;
962 } else
963 buf = temp;
964#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700965 } /* Disable log masks */
966 else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700967 /* Disable mask for each log code */
968 diag_disable_log_mask();
969 diag_update_userspace_clients(LOG_MASKS_TYPE);
970#if defined(CONFIG_DIAG_OVER_USB)
971 if (chk_apps_only()) {
972 driver->apps_rsp_buf[0] = 0x73;
973 driver->apps_rsp_buf[1] = 0x0;
974 driver->apps_rsp_buf[2] = 0x0;
975 driver->apps_rsp_buf[3] = 0x0;
976 *(int *)(driver->apps_rsp_buf + 4) = 0x0;
977 if (driver->ch_cntl)
978 diag_send_log_mask_update(driver->ch_cntl,
Dixon Petersona73bb992012-05-05 18:00:40 -0700979 ALL_EQUIP_ID);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700980 if (driver->chqdsp_cntl)
981 diag_send_log_mask_update(driver->chqdsp_cntl,
Dixon Petersona73bb992012-05-05 18:00:40 -0700982 ALL_EQUIP_ID);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700983 if (driver->ch_wcnss_cntl)
984 diag_send_log_mask_update(driver->ch_wcnss_cntl,
Dixon Petersona73bb992012-05-05 18:00:40 -0700985 ALL_EQUIP_ID);
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700986 ENCODE_RSP_AND_SEND(7);
987 return 0;
Dixon Petersona73bb992012-05-05 18:00:40 -0700988 }
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700989#endif
990 } /* Set runtime message mask */
Shalabh Jain321c8b52012-02-22 12:37:06 -0800991 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
992 ssid_first = *(uint16_t *)(buf + 2);
993 ssid_last = *(uint16_t *)(buf + 4);
994 ssid_range = 4 * (ssid_last - ssid_first + 1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700995 pr_debug("diag: received mask update for ssid_first = %d,"
996 " ssid_last = %d", ssid_first, ssid_last);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800997 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
998 diag_update_userspace_clients(MSG_MASKS_TYPE);
999#if defined(CONFIG_DIAG_OVER_USB)
1000 if (chk_apps_only()) {
1001 for (i = 0; i < 8 + ssid_range; i++)
1002 *(driver->apps_rsp_buf + i) = *(buf+i);
1003 *(driver->apps_rsp_buf + 6) = 0x1;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001004 if (driver->ch_cntl)
1005 diag_send_msg_mask_update(driver->ch_cntl,
1006 ssid_first, ssid_last, MODEM_PROC);
1007 if (driver->chqdsp_cntl)
1008 diag_send_msg_mask_update(driver->chqdsp_cntl,
1009 ssid_first, ssid_last, QDSP_PROC);
1010 if (driver->ch_wcnss_cntl)
1011 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1012 ssid_first, ssid_last, WCNSS_PROC);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001013 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1014 return 0;
1015 } else
1016 buf = temp;
1017#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001018 } /* Set ALL runtime message mask */
1019 else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
1020 rt_mask = *(int *)(buf + 4);
1021 diag_set_msg_mask(rt_mask);
1022 diag_update_userspace_clients(MSG_MASKS_TYPE);
1023#if defined(CONFIG_DIAG_OVER_USB)
1024 if (chk_apps_only()) {
1025 driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
1026 driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
1027 driver->apps_rsp_buf[2] = 1; /* success */
1028 driver->apps_rsp_buf[3] = 0; /* rsvd */
1029 *(int *)(driver->apps_rsp_buf + 4) = rt_mask;
1030 /* send msg mask update to peripheral */
1031 if (driver->ch_cntl)
1032 diag_send_msg_mask_update(driver->ch_cntl,
1033 ALL_SSID, ALL_SSID, MODEM_PROC);
1034 if (driver->chqdsp_cntl)
1035 diag_send_msg_mask_update(driver->chqdsp_cntl,
1036 ALL_SSID, ALL_SSID, QDSP_PROC);
1037 if (driver->ch_wcnss_cntl)
1038 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1039 ALL_SSID, ALL_SSID, WCNSS_PROC);
1040 ENCODE_RSP_AND_SEND(7);
1041 return 0;
1042 } else
1043 buf = temp;
1044#endif
Shalabh Jain321c8b52012-02-22 12:37:06 -08001045 } else if (*buf == 0x82) { /* event mask change */
1046 buf += 4;
1047 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
1048 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
1049 diag_update_userspace_clients(EVENT_MASKS_TYPE);
1050#if defined(CONFIG_DIAG_OVER_USB)
1051 if (chk_apps_only()) {
1052 driver->apps_rsp_buf[0] = 0x82;
1053 driver->apps_rsp_buf[1] = 0x0;
1054 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1055 *(uint16_t *)(driver->apps_rsp_buf + 4) =
1056 EVENT_LAST_ID + 1;
Shalabh Jaina51f2592012-03-08 14:36:35 -08001057 memcpy(driver->apps_rsp_buf+6, driver->event_masks,
1058 EVENT_LAST_ID/8+1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001059 if (driver->ch_cntl)
1060 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001061 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001062 if (driver->chqdsp_cntl)
1063 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001064 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001065 if (driver->ch_wcnss_cntl)
1066 diag_send_event_mask_update(
1067 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001068 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1069 return 0;
1070 } else
1071 buf = temp;
1072#endif
1073 } else if (*buf == 0x60) {
1074 diag_event_config = *(buf+1);
Shalabh Jaina51f2592012-03-08 14:36:35 -08001075 diag_toggle_event_mask(*(buf+1));
1076 diag_update_userspace_clients(EVENT_MASKS_TYPE);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001077#if defined(CONFIG_DIAG_OVER_USB)
1078 if (chk_apps_only()) {
1079 driver->apps_rsp_buf[0] = 0x60;
1080 driver->apps_rsp_buf[1] = 0x0;
1081 driver->apps_rsp_buf[2] = 0x0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001082 if (driver->ch_cntl)
1083 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001084 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001085 if (driver->chqdsp_cntl)
1086 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001087 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001088 if (driver->ch_wcnss_cntl)
1089 diag_send_event_mask_update(
1090 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001091 ENCODE_RSP_AND_SEND(2);
1092 return 0;
1093 }
1094#endif
1095 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001096 /* Check for registered clients and forward packet to apropriate proc */
1097 cmd_code = (int)(*(char *)buf);
1098 temp++;
1099 subsys_id = (int)(*(char *)temp);
1100 temp++;
1101 subsys_cmd_code = *(uint16_t *)temp;
1102 temp += 2;
1103 data_type = APPS_DATA;
1104 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301105 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001106 if (subsys_id != RESET_ID)
1107 data_type = MODEM_DATA;
1108 }
1109
1110 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001111 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001112 entry = driver->table[i];
1113 if (entry.process_id != NO_PROCESS) {
1114 if (entry.cmd_code == cmd_code && entry.subsys_id ==
1115 subsys_id && entry.cmd_code_lo <=
1116 subsys_cmd_code &&
1117 entry.cmd_code_hi >= subsys_cmd_code) {
1118 diag_send_data(entry, buf, len, data_type);
1119 packet_type = 0;
1120 } else if (entry.cmd_code == 255
1121 && cmd_code == 75) {
1122 if (entry.subsys_id ==
1123 subsys_id &&
1124 entry.cmd_code_lo <=
1125 subsys_cmd_code &&
1126 entry.cmd_code_hi >=
1127 subsys_cmd_code) {
1128 diag_send_data(entry, buf, len,
1129 data_type);
1130 packet_type = 0;
1131 }
1132 } else if (entry.cmd_code == 255 &&
1133 entry.subsys_id == 255) {
1134 if (entry.cmd_code_lo <=
1135 cmd_code &&
1136 entry.
1137 cmd_code_hi >= cmd_code) {
1138 diag_send_data(entry, buf, len,
1139 data_type);
1140 packet_type = 0;
1141 }
1142 }
1143 }
1144 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001145#if defined(CONFIG_DIAG_OVER_USB)
Dixon Petersona2dd7352012-05-21 17:37:10 -07001146 /* Check for the command/respond msg for the maximum packet length */
1147 if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
1148 (*(uint16_t *)(buf+2) == 0x0055)) {
1149 for (i = 0; i < 4; i++)
1150 *(driver->apps_rsp_buf+i) = *(buf+i);
1151 *(uint32_t *)(driver->apps_rsp_buf+4) = PKT_SIZE;
1152 ENCODE_RSP_AND_SEND(7);
1153 return 0;
1154 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001155 /* Check for Apps Only & get event mask request */
Dixon Petersona2dd7352012-05-21 17:37:10 -07001156 else if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001157 driver->apps_rsp_buf[0] = 0x81;
1158 driver->apps_rsp_buf[1] = 0x0;
1159 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1160 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
1161 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
1162 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
1163 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1164 return 0;
1165 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001166 /* Get log ID range & Check for Apps Only */
1167 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001168 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
1169 driver->apps_rsp_buf[0] = 0x73;
1170 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
1171 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
1172 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
1173 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
1174 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
1175 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
1176 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
1177 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
1178 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
1179 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
1180 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
1181 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
1182 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
1183 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
1184 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
1185 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
1186 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
1187 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
1188 ENCODE_RSP_AND_SEND(75);
1189 return 0;
1190 }
1191 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001192 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001193 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
1194 driver->apps_rsp_buf[0] = 0x7d;
1195 driver->apps_rsp_buf[1] = 0x1;
1196 driver->apps_rsp_buf[2] = 0x1;
1197 driver->apps_rsp_buf[3] = 0x0;
1198 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
1199 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
1200 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
1201 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
1202 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
1203 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
1204 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
1205 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
1206 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
1207 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
1208 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
1209 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
1210 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
1211 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
1212 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
1213 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
1214 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
1215 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
1216 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
1217 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
1218 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
1219 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
1220 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
1221 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
1222 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
1223 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
1224 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
1225 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
1226 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
1227 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
1228 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
1229 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
1230 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
1231 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
1232 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
1233 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
1234 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
1235 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
1236 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001237 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
1238 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
1239 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
1240 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
1241 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
1242 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
1243 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
1244 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
1245 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001246 return 0;
1247 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001248 /* Check for Apps Only Respond to Get Subsys Build mask */
1249 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001250 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
1251 ssid_first = *(uint16_t *)(buf + 2);
1252 ssid_last = *(uint16_t *)(buf + 4);
1253 ssid_range = 4 * (ssid_last - ssid_first + 1);
1254 /* frame response */
1255 driver->apps_rsp_buf[0] = 0x7d;
1256 driver->apps_rsp_buf[1] = 0x2;
1257 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
1258 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
1259 driver->apps_rsp_buf[6] = 0x1;
1260 driver->apps_rsp_buf[7] = 0x0;
1261 ptr = driver->apps_rsp_buf + 8;
1262 /* bld time masks */
1263 switch (ssid_first) {
1264 case MSG_SSID_0:
1265 for (i = 0; i < ssid_range; i += 4)
1266 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
1267 break;
1268 case MSG_SSID_1:
1269 for (i = 0; i < ssid_range; i += 4)
1270 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
1271 break;
1272 case MSG_SSID_2:
1273 for (i = 0; i < ssid_range; i += 4)
1274 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
1275 break;
1276 case MSG_SSID_3:
1277 for (i = 0; i < ssid_range; i += 4)
1278 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
1279 break;
1280 case MSG_SSID_4:
1281 for (i = 0; i < ssid_range; i += 4)
1282 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
1283 break;
1284 case MSG_SSID_5:
1285 for (i = 0; i < ssid_range; i += 4)
1286 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
1287 break;
1288 case MSG_SSID_6:
1289 for (i = 0; i < ssid_range; i += 4)
1290 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
1291 break;
1292 case MSG_SSID_7:
1293 for (i = 0; i < ssid_range; i += 4)
1294 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
1295 break;
1296 case MSG_SSID_8:
1297 for (i = 0; i < ssid_range; i += 4)
1298 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
1299 break;
1300 case MSG_SSID_9:
1301 for (i = 0; i < ssid_range; i += 4)
1302 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
1303 break;
1304 case MSG_SSID_10:
1305 for (i = 0; i < ssid_range; i += 4)
1306 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
1307 break;
1308 case MSG_SSID_11:
1309 for (i = 0; i < ssid_range; i += 4)
1310 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
1311 break;
1312 case MSG_SSID_12:
1313 for (i = 0; i < ssid_range; i += 4)
1314 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1315 break;
1316 case MSG_SSID_13:
1317 for (i = 0; i < ssid_range; i += 4)
1318 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1319 break;
1320 case MSG_SSID_14:
1321 for (i = 0; i < ssid_range; i += 4)
1322 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1323 break;
1324 case MSG_SSID_15:
1325 for (i = 0; i < ssid_range; i += 4)
1326 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1327 break;
1328 case MSG_SSID_16:
1329 for (i = 0; i < ssid_range; i += 4)
1330 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1331 break;
1332 case MSG_SSID_17:
1333 for (i = 0; i < ssid_range; i += 4)
1334 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1335 break;
1336 case MSG_SSID_18:
1337 for (i = 0; i < ssid_range; i += 4)
1338 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1339 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001340 case MSG_SSID_19:
1341 for (i = 0; i < ssid_range; i += 4)
1342 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1343 break;
1344 case MSG_SSID_20:
1345 for (i = 0; i < ssid_range; i += 4)
1346 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1347 break;
1348 case MSG_SSID_21:
1349 for (i = 0; i < ssid_range; i += 4)
1350 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1351 break;
1352 case MSG_SSID_22:
1353 for (i = 0; i < ssid_range; i += 4)
1354 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1355 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001356 }
1357 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1358 return 0;
1359 }
1360 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301361 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001362 /* send response back */
1363 driver->apps_rsp_buf[0] = *buf;
1364 ENCODE_RSP_AND_SEND(0);
1365 msleep(5000);
1366 /* call download API */
1367 msm_set_restart_mode(RESTART_DLOAD);
1368 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1369 kernel_restart(NULL);
1370 /* Not required, represents that command isnt sent to modem */
1371 return 0;
1372 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001373 /* Check for polling for Apps only DIAG */
1374 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1375 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001376 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001377 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001378 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001379 for (i = 0; i < 3; i++)
1380 driver->apps_rsp_buf[i] = *(buf+i);
1381 for (i = 0; i < 13; i++)
1382 driver->apps_rsp_buf[i+3] = 0;
1383
1384 ENCODE_RSP_AND_SEND(15);
1385 return 0;
1386 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001387 }
1388 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001389 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001390 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001391 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001392 for (i = 0; i < 55; i++)
1393 driver->apps_rsp_buf[i] = 0;
1394
1395 ENCODE_RSP_AND_SEND(54);
1396 return 0;
1397 }
1398 /* respond to 0x7c command */
1399 else if (*buf == 0x7c) {
1400 driver->apps_rsp_buf[0] = 0x7c;
1401 for (i = 1; i < 8; i++)
1402 driver->apps_rsp_buf[i] = 0;
1403 /* Tools ID for APQ 8060 */
1404 *(int *)(driver->apps_rsp_buf + 8) =
1405 chk_config_get_id();
1406 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1407 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1408 ENCODE_RSP_AND_SEND(13);
1409 return 0;
1410 }
1411 }
1412#endif
1413 return packet_type;
1414}
1415
1416#ifdef CONFIG_DIAG_OVER_USB
1417void diag_send_error_rsp(int index)
1418{
1419 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301420
1421 if (index > 490) {
1422 pr_err("diag: error response too huge, aborting\n");
1423 return;
1424 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001425 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1426 for (i = 0; i < index; i++)
1427 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1428 ENCODE_RSP_AND_SEND(index - 3);
1429}
1430#else
1431static inline void diag_send_error_rsp(int index) {}
1432#endif
1433
1434void diag_process_hdlc(void *data, unsigned len)
1435{
1436 struct diag_hdlc_decode_type hdlc;
1437 int ret, type = 0;
1438 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1439 hdlc.dest_ptr = driver->hdlc_buf;
1440 hdlc.dest_size = USB_MAX_OUT_BUF;
1441 hdlc.src_ptr = data;
1442 hdlc.src_size = len;
1443 hdlc.src_idx = 0;
1444 hdlc.dest_idx = 0;
1445 hdlc.escaping = 0;
1446
1447 ret = diag_hdlc_decode(&hdlc);
1448
1449 if (ret)
1450 type = diag_process_apps_pkt(driver->hdlc_buf,
1451 hdlc.dest_idx - 3);
1452 else if (driver->debug_flag) {
1453 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1454 " errors or partial packet received, packet"
1455 " length = %d\n", len);
1456 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1457 DUMP_PREFIX_ADDRESS, data, len, 1);
1458 driver->debug_flag = 0;
1459 }
1460 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001461 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001462 diag_send_error_rsp(hdlc.dest_idx);
1463 type = 0;
1464 }
1465 /* implies this packet is NOT meant for apps */
1466 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001467 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001468 diag_send_error_rsp(hdlc.dest_idx);
1469 } else { /* APQ 8060, Let Q6 respond */
1470 if (driver->chqdsp)
1471 smd_write(driver->chqdsp, driver->hdlc_buf,
1472 hdlc.dest_idx - 3);
1473 }
1474 type = 0;
1475 }
1476
1477#ifdef DIAG_DEBUG
1478 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1479 for (i = 0; i < hdlc.dest_idx; i++)
1480 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1481 driver->hdlc_buf)+i));
1482#endif /* DIAG DEBUG */
1483 /* ignore 2 bytes for CRC, one for 7E and send */
1484 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1485 APPEND_DEBUG('g');
1486 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1487 APPEND_DEBUG('h');
1488#ifdef DIAG_DEBUG
1489 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1490 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1491 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1492#endif /* DIAG DEBUG */
1493 }
1494}
1495
1496#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001497/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1498#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001499#define N_LEGACY_READ 1
1500
1501int diagfwd_connect(void)
1502{
1503 int err;
1504
1505 printk(KERN_DEBUG "diag: USB connected\n");
1506 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1507 N_LEGACY_READ);
1508 if (err)
1509 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1510
1511 driver->usb_connected = 1;
1512 driver->in_busy_1 = 0;
1513 driver->in_busy_2 = 0;
1514 driver->in_busy_qdsp_1 = 0;
1515 driver->in_busy_qdsp_2 = 0;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301516 driver->in_busy_wcnss_1 = 0;
1517 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001518
1519 /* Poll SMD channels to check for data*/
1520 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1521 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1522 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001523 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001524 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1525 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1526 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001527 /* Poll USB channel to check for data*/
1528 queue_work(driver->diag_wq, &(driver->diag_read_work));
1529#ifdef CONFIG_DIAG_SDIO_PIPE
1530 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1531 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1532 diagfwd_connect_sdio();
1533 else
1534 printk(KERN_INFO "diag: No USB MDM ch");
1535 }
1536#endif
1537 return 0;
1538}
1539
1540int diagfwd_disconnect(void)
1541{
1542 printk(KERN_DEBUG "diag: USB disconnected\n");
1543 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001544 driver->debug_flag = 1;
1545 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001546 if (driver->logging_mode == USB_MODE) {
1547 driver->in_busy_1 = 1;
1548 driver->in_busy_2 = 1;
1549 driver->in_busy_qdsp_1 = 1;
1550 driver->in_busy_qdsp_2 = 1;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301551 driver->in_busy_wcnss_1 = 1;
1552 driver->in_busy_wcnss_2 = 1;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001553 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001554#ifdef CONFIG_DIAG_SDIO_PIPE
1555 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1556 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1557 diagfwd_disconnect_sdio();
1558#endif
1559 /* TBD - notify and flow control SMD */
1560 return 0;
1561}
1562
1563int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1564{
1565 unsigned char *buf = diag_write_ptr->buf;
1566 /*Determine if the write complete is for data from modem/apps/q6 */
1567 /* Need a context variable here instead */
1568 if (buf == (void *)driver->buf_in_1) {
1569 driver->in_busy_1 = 0;
1570 APPEND_DEBUG('o');
1571 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1572 } else if (buf == (void *)driver->buf_in_2) {
1573 driver->in_busy_2 = 0;
1574 APPEND_DEBUG('O');
1575 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1576 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1577 driver->in_busy_qdsp_1 = 0;
1578 APPEND_DEBUG('p');
1579 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1580 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1581 driver->in_busy_qdsp_2 = 0;
1582 APPEND_DEBUG('P');
1583 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
Ashay Jaiswal29620122012-03-21 12:02:36 +05301584 } else if (buf == driver->buf_in_wcnss_1) {
1585 driver->in_busy_wcnss_1 = 0;
1586 APPEND_DEBUG('r');
1587 queue_work(driver->diag_wq,
1588 &(driver->diag_read_smd_wcnss_work));
1589 } else if (buf == driver->buf_in_wcnss_2) {
1590 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001591 APPEND_DEBUG('R');
1592 queue_work(driver->diag_wq,
1593 &(driver->diag_read_smd_wcnss_work));
1594 }
1595#ifdef CONFIG_DIAG_SDIO_PIPE
1596 else if (buf == (void *)driver->buf_in_sdio)
1597 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001598 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001599 diagfwd_write_complete_sdio();
1600 else
1601 pr_err("diag: Incorrect buffer pointer while WRITE");
1602#endif
1603 else {
1604 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1605 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1606 POOL_TYPE_WRITE_STRUCT);
1607 APPEND_DEBUG('q');
1608 }
1609 return 0;
1610}
1611
1612int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1613{
1614 int status = diag_read_ptr->status;
1615 unsigned char *buf = diag_read_ptr->buf;
1616
1617 /* Determine if the read complete is for data on legacy/mdm ch */
1618 if (buf == (void *)driver->usb_buf_out) {
1619 driver->read_len_legacy = diag_read_ptr->actual;
1620 APPEND_DEBUG('s');
1621#ifdef DIAG_DEBUG
1622 printk(KERN_INFO "read data from USB, pkt length %d",
1623 diag_read_ptr->actual);
1624 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1625 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1626 diag_read_ptr->actual, 1);
1627#endif /* DIAG DEBUG */
1628 if (driver->logging_mode == USB_MODE) {
1629 if (status != -ECONNRESET && status != -ESHUTDOWN)
1630 queue_work(driver->diag_wq,
1631 &(driver->diag_proc_hdlc_work));
1632 else
1633 queue_work(driver->diag_wq,
1634 &(driver->diag_read_work));
1635 }
1636 }
1637#ifdef CONFIG_DIAG_SDIO_PIPE
1638 else if (buf == (void *)driver->usb_buf_mdm_out) {
1639 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001640 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001641 driver->read_len_mdm = diag_read_ptr->actual;
1642 diagfwd_read_complete_sdio();
1643 } else
1644 pr_err("diag: Incorrect buffer pointer while READ");
1645 }
1646#endif
1647 else
1648 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1649
1650 return 0;
1651}
1652
1653void diag_read_work_fn(struct work_struct *work)
1654{
1655 APPEND_DEBUG('d');
1656 driver->usb_read_ptr->buf = driver->usb_buf_out;
1657 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1658 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1659 APPEND_DEBUG('e');
1660}
1661
1662void diag_process_hdlc_fn(struct work_struct *work)
1663{
1664 APPEND_DEBUG('D');
1665 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1666 diag_read_work_fn(work);
1667 APPEND_DEBUG('E');
1668}
1669
1670void diag_usb_legacy_notifier(void *priv, unsigned event,
1671 struct diag_request *d_req)
1672{
1673 switch (event) {
1674 case USB_DIAG_CONNECT:
1675 diagfwd_connect();
1676 break;
1677 case USB_DIAG_DISCONNECT:
1678 diagfwd_disconnect();
1679 break;
1680 case USB_DIAG_READ_DONE:
1681 diagfwd_read_complete(d_req);
1682 break;
1683 case USB_DIAG_WRITE_DONE:
1684 diagfwd_write_complete(d_req);
1685 break;
1686 default:
1687 printk(KERN_ERR "Unknown event from USB diag\n");
1688 break;
1689 }
1690}
1691
1692#endif /* DIAG OVER USB */
1693
1694static void diag_smd_notify(void *ctxt, unsigned event)
1695{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001696 if (event == SMD_EVENT_CLOSE) {
1697 pr_info("diag: clean modem registration\n");
1698 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001699 driver->ch = 0;
1700 return;
1701 } else if (event == SMD_EVENT_OPEN) {
1702 driver->ch = ch_temp;
1703 }
1704 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001705}
1706
1707#if defined(CONFIG_MSM_N_WAY_SMD)
1708static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1709{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001710 if (event == SMD_EVENT_CLOSE) {
1711 pr_info("diag: clean lpass registration\n");
1712 diag_clear_reg(QDSP_PROC);
1713 driver->chqdsp = 0;
1714 return;
1715 } else if (event == SMD_EVENT_OPEN) {
1716 driver->chqdsp = chqdsp_temp;
1717 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001718 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1719}
1720#endif
1721
1722static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1723{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001724 if (event == SMD_EVENT_CLOSE) {
1725 pr_info("diag: clean wcnss registration\n");
1726 diag_clear_reg(WCNSS_PROC);
1727 driver->ch_wcnss = 0;
1728 return;
1729 } else if (event == SMD_EVENT_OPEN) {
1730 driver->ch_wcnss = ch_wcnss_temp;
1731 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001732 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1733}
1734
1735static int diag_smd_probe(struct platform_device *pdev)
1736{
1737 int r = 0;
1738
Shalabh Jaineefee052011-11-08 23:46:03 -08001739 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001740 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001741 ch_temp = driver->ch;
1742 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001743#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001744 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001745 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1746 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001747 chqdsp_temp = driver->chqdsp;
1748 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001749#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001750 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001751 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1752 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001753 ch_wcnss_temp = driver->ch_wcnss;
1754 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001755 pm_runtime_set_active(&pdev->dev);
1756 pm_runtime_enable(&pdev->dev);
1757 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1758
1759 return 0;
1760}
1761
1762static int diagfwd_runtime_suspend(struct device *dev)
1763{
1764 dev_dbg(dev, "pm_runtime: suspending...\n");
1765 return 0;
1766}
1767
1768static int diagfwd_runtime_resume(struct device *dev)
1769{
1770 dev_dbg(dev, "pm_runtime: resuming...\n");
1771 return 0;
1772}
1773
1774static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1775 .runtime_suspend = diagfwd_runtime_suspend,
1776 .runtime_resume = diagfwd_runtime_resume,
1777};
1778
1779static struct platform_driver msm_smd_ch1_driver = {
1780
1781 .probe = diag_smd_probe,
1782 .driver = {
1783 .name = "DIAG",
1784 .owner = THIS_MODULE,
1785 .pm = &diagfwd_dev_pm_ops,
1786 },
1787};
1788
1789static struct platform_driver diag_smd_lite_driver = {
1790
1791 .probe = diag_smd_probe,
1792 .driver = {
1793 .name = "APPS_RIVA_DATA",
1794 .owner = THIS_MODULE,
1795 .pm = &diagfwd_dev_pm_ops,
1796 },
1797};
1798
1799void diagfwd_init(void)
1800{
1801 diag_debug_buf_idx = 0;
1802 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001803 driver->use_device_tree = has_device_tree();
Shalabh Jaina06c6d72012-04-30 13:40:35 -07001804 mutex_init(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001805
1806 if (driver->event_mask == NULL) {
1807 driver->event_mask = kzalloc(sizeof(
1808 struct diag_ctrl_event_mask), GFP_KERNEL);
1809 if (driver->event_mask == NULL)
1810 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001811 kmemleak_not_leak(driver->event_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001812 }
1813 if (driver->msg_mask == NULL) {
1814 driver->msg_mask = kzalloc(sizeof(
1815 struct diag_ctrl_msg_mask), GFP_KERNEL);
1816 if (driver->msg_mask == NULL)
1817 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001818 kmemleak_not_leak(driver->msg_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001819 }
1820 if (driver->log_mask == NULL) {
1821 driver->log_mask = kzalloc(sizeof(
1822 struct diag_ctrl_log_mask), GFP_KERNEL);
1823 if (driver->log_mask == NULL)
1824 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001825 kmemleak_not_leak(driver->log_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001826 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001827 if (driver->buf_in_1 == NULL) {
1828 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1829 if (driver->buf_in_1 == NULL)
1830 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001831 kmemleak_not_leak(driver->buf_in_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001832 }
1833 if (driver->buf_in_2 == NULL) {
1834 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1835 if (driver->buf_in_2 == NULL)
1836 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001837 kmemleak_not_leak(driver->buf_in_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001838 }
1839 if (driver->buf_in_qdsp_1 == NULL) {
1840 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1841 if (driver->buf_in_qdsp_1 == NULL)
1842 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001843 kmemleak_not_leak(driver->buf_in_qdsp_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001844 }
1845 if (driver->buf_in_qdsp_2 == NULL) {
1846 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1847 if (driver->buf_in_qdsp_2 == NULL)
1848 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001849 kmemleak_not_leak(driver->buf_in_qdsp_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001850 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301851 if (driver->buf_in_wcnss_1 == NULL) {
1852 driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1853 if (driver->buf_in_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001854 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001855 kmemleak_not_leak(driver->buf_in_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001856 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301857 if (driver->buf_in_wcnss_2 == NULL) {
1858 driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1859 if (driver->buf_in_wcnss_2 == NULL)
1860 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001861 kmemleak_not_leak(driver->buf_in_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301862 }
1863
Shalabh Jain321c8b52012-02-22 12:37:06 -08001864 if (driver->buf_msg_mask_update == NULL) {
1865 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1866 GFP_KERNEL);
1867 if (driver->buf_msg_mask_update == NULL)
1868 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001869 kmemleak_not_leak(driver->buf_msg_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001870 }
1871 if (driver->buf_log_mask_update == NULL) {
1872 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1873 GFP_KERNEL);
1874 if (driver->buf_log_mask_update == NULL)
1875 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001876 kmemleak_not_leak(driver->buf_log_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001877 }
1878 if (driver->buf_event_mask_update == NULL) {
1879 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1880 GFP_KERNEL);
1881 if (driver->buf_event_mask_update == NULL)
1882 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001883 kmemleak_not_leak(driver->buf_event_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001884 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001885 if (driver->usb_buf_out == NULL &&
1886 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1887 GFP_KERNEL)) == NULL)
1888 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001889 kmemleak_not_leak(driver->usb_buf_out);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001890 if (driver->hdlc_buf == NULL
1891 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1892 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001893 kmemleak_not_leak(driver->hdlc_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001894 if (driver->user_space_data == NULL)
1895 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1896 if (driver->user_space_data == NULL)
1897 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001898 kmemleak_not_leak(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001899 if (driver->msg_masks == NULL
1900 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1901 GFP_KERNEL)) == NULL)
1902 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001903 kmemleak_not_leak(driver->msg_masks);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001904 diag_create_msg_mask_table();
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001905 diag_event_num_bytes = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001906 if (driver->log_masks == NULL &&
1907 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1908 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001909 kmemleak_not_leak(driver->log_masks);
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -07001910 driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001911 if (driver->event_masks == NULL &&
1912 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1913 GFP_KERNEL)) == NULL)
1914 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001915 kmemleak_not_leak(driver->event_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001916 if (driver->client_map == NULL &&
1917 (driver->client_map = kzalloc
1918 ((driver->num_clients) * sizeof(struct diag_client_map),
1919 GFP_KERNEL)) == NULL)
1920 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001921 kmemleak_not_leak(driver->client_map);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001922 if (driver->buf_tbl == NULL)
1923 driver->buf_tbl = kzalloc(buf_tbl_size *
1924 sizeof(struct diag_write_device), GFP_KERNEL);
1925 if (driver->buf_tbl == NULL)
1926 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001927 kmemleak_not_leak(driver->buf_tbl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001928 if (driver->data_ready == NULL &&
1929 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1930 , GFP_KERNEL)) == NULL)
1931 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001932 kmemleak_not_leak(driver->data_ready);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001933 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001934 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001935 sizeof(struct diag_master_table),
1936 GFP_KERNEL)) == NULL)
1937 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001938 kmemleak_not_leak(driver->table);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001939 if (driver->write_ptr_1 == NULL) {
1940 driver->write_ptr_1 = kzalloc(
1941 sizeof(struct diag_request), GFP_KERNEL);
1942 if (driver->write_ptr_1 == NULL)
1943 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001944 kmemleak_not_leak(driver->write_ptr_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001945 }
1946 if (driver->write_ptr_2 == NULL) {
1947 driver->write_ptr_2 = kzalloc(
1948 sizeof(struct diag_request), GFP_KERNEL);
1949 if (driver->write_ptr_2 == NULL)
1950 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001951 kmemleak_not_leak(driver->write_ptr_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001952 }
1953 if (driver->write_ptr_qdsp_1 == NULL) {
1954 driver->write_ptr_qdsp_1 = kzalloc(
1955 sizeof(struct diag_request), GFP_KERNEL);
1956 if (driver->write_ptr_qdsp_1 == NULL)
1957 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001958 kmemleak_not_leak(driver->write_ptr_qdsp_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001959 }
1960 if (driver->write_ptr_qdsp_2 == NULL) {
1961 driver->write_ptr_qdsp_2 = kzalloc(
1962 sizeof(struct diag_request), GFP_KERNEL);
1963 if (driver->write_ptr_qdsp_2 == NULL)
1964 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001965 kmemleak_not_leak(driver->write_ptr_qdsp_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001966 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301967 if (driver->write_ptr_wcnss_1 == NULL) {
1968 driver->write_ptr_wcnss_1 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001969 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301970 if (driver->write_ptr_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001971 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001972 kmemleak_not_leak(driver->write_ptr_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001973 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301974 if (driver->write_ptr_wcnss_2 == NULL) {
1975 driver->write_ptr_wcnss_2 = kzalloc(
1976 sizeof(struct diag_request), GFP_KERNEL);
1977 if (driver->write_ptr_wcnss_2 == NULL)
1978 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001979 kmemleak_not_leak(driver->write_ptr_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301980 }
1981
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001982 if (driver->usb_read_ptr == NULL) {
1983 driver->usb_read_ptr = kzalloc(
1984 sizeof(struct diag_request), GFP_KERNEL);
1985 if (driver->usb_read_ptr == NULL)
1986 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001987 kmemleak_not_leak(driver->usb_read_ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001988 }
1989 if (driver->pkt_buf == NULL &&
1990 (driver->pkt_buf = kzalloc(PKT_SIZE,
1991 GFP_KERNEL)) == NULL)
1992 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001993 kmemleak_not_leak(driver->pkt_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001994 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001995 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001996 if (driver->apps_rsp_buf == NULL)
1997 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001998 kmemleak_not_leak(driver->apps_rsp_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001999 }
2000 driver->diag_wq = create_singlethread_workqueue("diag_wq");
2001#ifdef CONFIG_DIAG_OVER_USB
2002 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
2003 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002004 INIT_WORK(&(driver->diag_modem_mask_update_work),
2005 diag_modem_mask_update_fn);
2006 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
2007 diag_qdsp_mask_update_fn);
2008 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
2009 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002010 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
2011 diag_usb_legacy_notifier);
2012 if (IS_ERR(driver->legacy_ch)) {
2013 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
2014 goto err;
2015 }
2016#endif
2017 platform_driver_register(&msm_smd_ch1_driver);
2018 platform_driver_register(&diag_smd_lite_driver);
2019
2020 return;
2021err:
2022 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08002023 kfree(driver->event_mask);
2024 kfree(driver->log_mask);
2025 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002026 kfree(driver->buf_in_1);
2027 kfree(driver->buf_in_2);
2028 kfree(driver->buf_in_qdsp_1);
2029 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302030 kfree(driver->buf_in_wcnss_1);
2031 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002032 kfree(driver->buf_msg_mask_update);
2033 kfree(driver->buf_log_mask_update);
2034 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002035 kfree(driver->usb_buf_out);
2036 kfree(driver->hdlc_buf);
2037 kfree(driver->msg_masks);
2038 kfree(driver->log_masks);
2039 kfree(driver->event_masks);
2040 kfree(driver->client_map);
2041 kfree(driver->buf_tbl);
2042 kfree(driver->data_ready);
2043 kfree(driver->table);
2044 kfree(driver->pkt_buf);
2045 kfree(driver->write_ptr_1);
2046 kfree(driver->write_ptr_2);
2047 kfree(driver->write_ptr_qdsp_1);
2048 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302049 kfree(driver->write_ptr_wcnss_1);
2050 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002051 kfree(driver->usb_read_ptr);
2052 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002053 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002054 if (driver->diag_wq)
2055 destroy_workqueue(driver->diag_wq);
2056}
2057
2058void diagfwd_exit(void)
2059{
2060 smd_close(driver->ch);
2061 smd_close(driver->chqdsp);
2062 smd_close(driver->ch_wcnss);
2063 driver->ch = 0; /* SMD can make this NULL */
2064 driver->chqdsp = 0;
2065 driver->ch_wcnss = 0;
2066#ifdef CONFIG_DIAG_OVER_USB
2067 if (driver->usb_connected)
2068 usb_diag_free_req(driver->legacy_ch);
2069 usb_diag_close(driver->legacy_ch);
2070#endif
2071 platform_driver_unregister(&msm_smd_ch1_driver);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -07002072 platform_driver_unregister(&msm_diag_dci_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002073 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002074 kfree(driver->event_mask);
2075 kfree(driver->log_mask);
2076 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002077 kfree(driver->buf_in_1);
2078 kfree(driver->buf_in_2);
2079 kfree(driver->buf_in_qdsp_1);
2080 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302081 kfree(driver->buf_in_wcnss_1);
2082 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002083 kfree(driver->buf_msg_mask_update);
2084 kfree(driver->buf_log_mask_update);
2085 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002086 kfree(driver->usb_buf_out);
2087 kfree(driver->hdlc_buf);
2088 kfree(driver->msg_masks);
2089 kfree(driver->log_masks);
2090 kfree(driver->event_masks);
2091 kfree(driver->client_map);
2092 kfree(driver->buf_tbl);
2093 kfree(driver->data_ready);
2094 kfree(driver->table);
2095 kfree(driver->pkt_buf);
2096 kfree(driver->write_ptr_1);
2097 kfree(driver->write_ptr_2);
2098 kfree(driver->write_ptr_qdsp_1);
2099 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302100 kfree(driver->write_ptr_wcnss_1);
2101 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002102 kfree(driver->usb_read_ptr);
2103 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002104 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002105 destroy_workqueue(driver->diag_wq);
2106}