blob: 4ac2643e0d8fff9110f7a93f6ed8eba396d64053 [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)
Dixon Petersona2dd7352012-05-21 17:37:10 -07001142 /* Check for the command/respond msg for the maximum packet length */
1143 if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
1144 (*(uint16_t *)(buf+2) == 0x0055)) {
1145 for (i = 0; i < 4; i++)
1146 *(driver->apps_rsp_buf+i) = *(buf+i);
1147 *(uint32_t *)(driver->apps_rsp_buf+4) = PKT_SIZE;
1148 ENCODE_RSP_AND_SEND(7);
1149 return 0;
1150 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001151 /* Check for Apps Only & get event mask request */
Dixon Petersona2dd7352012-05-21 17:37:10 -07001152 else if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001153 driver->apps_rsp_buf[0] = 0x81;
1154 driver->apps_rsp_buf[1] = 0x0;
1155 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1156 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
1157 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
1158 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
1159 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1160 return 0;
1161 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001162 /* Get log ID range & Check for Apps Only */
1163 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001164 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
1165 driver->apps_rsp_buf[0] = 0x73;
1166 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
1167 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
1168 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
1169 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
1170 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
1171 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
1172 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
1173 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
1174 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
1175 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
1176 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
1177 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
1178 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
1179 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
1180 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
1181 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
1182 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
1183 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
1184 ENCODE_RSP_AND_SEND(75);
1185 return 0;
1186 }
1187 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001188 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001189 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
1190 driver->apps_rsp_buf[0] = 0x7d;
1191 driver->apps_rsp_buf[1] = 0x1;
1192 driver->apps_rsp_buf[2] = 0x1;
1193 driver->apps_rsp_buf[3] = 0x0;
1194 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
1195 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
1196 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
1197 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
1198 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
1199 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
1200 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
1201 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
1202 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
1203 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
1204 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
1205 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
1206 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
1207 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
1208 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
1209 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
1210 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
1211 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
1212 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
1213 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
1214 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
1215 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
1216 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
1217 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
1218 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
1219 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
1220 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
1221 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
1222 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
1223 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
1224 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
1225 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
1226 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
1227 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
1228 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
1229 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
1230 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
1231 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
1232 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001233 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
1234 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
1235 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
1236 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
1237 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
1238 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
1239 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
1240 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
1241 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001242 return 0;
1243 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001244 /* Check for Apps Only Respond to Get Subsys Build mask */
1245 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001246 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
1247 ssid_first = *(uint16_t *)(buf + 2);
1248 ssid_last = *(uint16_t *)(buf + 4);
1249 ssid_range = 4 * (ssid_last - ssid_first + 1);
1250 /* frame response */
1251 driver->apps_rsp_buf[0] = 0x7d;
1252 driver->apps_rsp_buf[1] = 0x2;
1253 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
1254 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
1255 driver->apps_rsp_buf[6] = 0x1;
1256 driver->apps_rsp_buf[7] = 0x0;
1257 ptr = driver->apps_rsp_buf + 8;
1258 /* bld time masks */
1259 switch (ssid_first) {
1260 case MSG_SSID_0:
1261 for (i = 0; i < ssid_range; i += 4)
1262 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
1263 break;
1264 case MSG_SSID_1:
1265 for (i = 0; i < ssid_range; i += 4)
1266 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
1267 break;
1268 case MSG_SSID_2:
1269 for (i = 0; i < ssid_range; i += 4)
1270 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
1271 break;
1272 case MSG_SSID_3:
1273 for (i = 0; i < ssid_range; i += 4)
1274 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
1275 break;
1276 case MSG_SSID_4:
1277 for (i = 0; i < ssid_range; i += 4)
1278 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
1279 break;
1280 case MSG_SSID_5:
1281 for (i = 0; i < ssid_range; i += 4)
1282 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
1283 break;
1284 case MSG_SSID_6:
1285 for (i = 0; i < ssid_range; i += 4)
1286 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
1287 break;
1288 case MSG_SSID_7:
1289 for (i = 0; i < ssid_range; i += 4)
1290 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
1291 break;
1292 case MSG_SSID_8:
1293 for (i = 0; i < ssid_range; i += 4)
1294 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
1295 break;
1296 case MSG_SSID_9:
1297 for (i = 0; i < ssid_range; i += 4)
1298 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
1299 break;
1300 case MSG_SSID_10:
1301 for (i = 0; i < ssid_range; i += 4)
1302 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
1303 break;
1304 case MSG_SSID_11:
1305 for (i = 0; i < ssid_range; i += 4)
1306 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
1307 break;
1308 case MSG_SSID_12:
1309 for (i = 0; i < ssid_range; i += 4)
1310 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1311 break;
1312 case MSG_SSID_13:
1313 for (i = 0; i < ssid_range; i += 4)
1314 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1315 break;
1316 case MSG_SSID_14:
1317 for (i = 0; i < ssid_range; i += 4)
1318 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1319 break;
1320 case MSG_SSID_15:
1321 for (i = 0; i < ssid_range; i += 4)
1322 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1323 break;
1324 case MSG_SSID_16:
1325 for (i = 0; i < ssid_range; i += 4)
1326 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1327 break;
1328 case MSG_SSID_17:
1329 for (i = 0; i < ssid_range; i += 4)
1330 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1331 break;
1332 case MSG_SSID_18:
1333 for (i = 0; i < ssid_range; i += 4)
1334 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1335 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001336 case MSG_SSID_19:
1337 for (i = 0; i < ssid_range; i += 4)
1338 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1339 break;
1340 case MSG_SSID_20:
1341 for (i = 0; i < ssid_range; i += 4)
1342 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1343 break;
1344 case MSG_SSID_21:
1345 for (i = 0; i < ssid_range; i += 4)
1346 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1347 break;
1348 case MSG_SSID_22:
1349 for (i = 0; i < ssid_range; i += 4)
1350 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1351 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001352 }
1353 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1354 return 0;
1355 }
1356 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301357 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001358 /* send response back */
1359 driver->apps_rsp_buf[0] = *buf;
1360 ENCODE_RSP_AND_SEND(0);
1361 msleep(5000);
1362 /* call download API */
1363 msm_set_restart_mode(RESTART_DLOAD);
1364 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1365 kernel_restart(NULL);
1366 /* Not required, represents that command isnt sent to modem */
1367 return 0;
1368 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001369 /* Check for polling for Apps only DIAG */
1370 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1371 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001372 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001373 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001374 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001375 for (i = 0; i < 3; i++)
1376 driver->apps_rsp_buf[i] = *(buf+i);
1377 for (i = 0; i < 13; i++)
1378 driver->apps_rsp_buf[i+3] = 0;
1379
1380 ENCODE_RSP_AND_SEND(15);
1381 return 0;
1382 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001383 }
1384 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001385 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001386 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001387 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001388 for (i = 0; i < 55; i++)
1389 driver->apps_rsp_buf[i] = 0;
1390
1391 ENCODE_RSP_AND_SEND(54);
1392 return 0;
1393 }
1394 /* respond to 0x7c command */
1395 else if (*buf == 0x7c) {
1396 driver->apps_rsp_buf[0] = 0x7c;
1397 for (i = 1; i < 8; i++)
1398 driver->apps_rsp_buf[i] = 0;
1399 /* Tools ID for APQ 8060 */
1400 *(int *)(driver->apps_rsp_buf + 8) =
1401 chk_config_get_id();
1402 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1403 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1404 ENCODE_RSP_AND_SEND(13);
1405 return 0;
1406 }
1407 }
1408#endif
1409 return packet_type;
1410}
1411
1412#ifdef CONFIG_DIAG_OVER_USB
1413void diag_send_error_rsp(int index)
1414{
1415 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301416
1417 if (index > 490) {
1418 pr_err("diag: error response too huge, aborting\n");
1419 return;
1420 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001421 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1422 for (i = 0; i < index; i++)
1423 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1424 ENCODE_RSP_AND_SEND(index - 3);
1425}
1426#else
1427static inline void diag_send_error_rsp(int index) {}
1428#endif
1429
1430void diag_process_hdlc(void *data, unsigned len)
1431{
1432 struct diag_hdlc_decode_type hdlc;
1433 int ret, type = 0;
1434 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1435 hdlc.dest_ptr = driver->hdlc_buf;
1436 hdlc.dest_size = USB_MAX_OUT_BUF;
1437 hdlc.src_ptr = data;
1438 hdlc.src_size = len;
1439 hdlc.src_idx = 0;
1440 hdlc.dest_idx = 0;
1441 hdlc.escaping = 0;
1442
1443 ret = diag_hdlc_decode(&hdlc);
1444
1445 if (ret)
1446 type = diag_process_apps_pkt(driver->hdlc_buf,
1447 hdlc.dest_idx - 3);
1448 else if (driver->debug_flag) {
1449 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1450 " errors or partial packet received, packet"
1451 " length = %d\n", len);
1452 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1453 DUMP_PREFIX_ADDRESS, data, len, 1);
1454 driver->debug_flag = 0;
1455 }
1456 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001457 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001458 diag_send_error_rsp(hdlc.dest_idx);
1459 type = 0;
1460 }
1461 /* implies this packet is NOT meant for apps */
1462 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001463 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001464 diag_send_error_rsp(hdlc.dest_idx);
1465 } else { /* APQ 8060, Let Q6 respond */
1466 if (driver->chqdsp)
1467 smd_write(driver->chqdsp, driver->hdlc_buf,
1468 hdlc.dest_idx - 3);
1469 }
1470 type = 0;
1471 }
1472
1473#ifdef DIAG_DEBUG
1474 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1475 for (i = 0; i < hdlc.dest_idx; i++)
1476 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1477 driver->hdlc_buf)+i));
1478#endif /* DIAG DEBUG */
1479 /* ignore 2 bytes for CRC, one for 7E and send */
1480 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1481 APPEND_DEBUG('g');
1482 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1483 APPEND_DEBUG('h');
1484#ifdef DIAG_DEBUG
1485 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1486 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1487 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1488#endif /* DIAG DEBUG */
1489 }
1490}
1491
1492#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001493/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1494#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001495#define N_LEGACY_READ 1
1496
1497int diagfwd_connect(void)
1498{
1499 int err;
1500
1501 printk(KERN_DEBUG "diag: USB connected\n");
1502 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1503 N_LEGACY_READ);
1504 if (err)
1505 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1506
1507 driver->usb_connected = 1;
1508 driver->in_busy_1 = 0;
1509 driver->in_busy_2 = 0;
1510 driver->in_busy_qdsp_1 = 0;
1511 driver->in_busy_qdsp_2 = 0;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301512 driver->in_busy_wcnss_1 = 0;
1513 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001514
1515 /* Poll SMD channels to check for data*/
1516 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1517 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1518 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001519 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001520 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1521 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1522 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001523 /* Poll USB channel to check for data*/
1524 queue_work(driver->diag_wq, &(driver->diag_read_work));
1525#ifdef CONFIG_DIAG_SDIO_PIPE
1526 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1527 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1528 diagfwd_connect_sdio();
1529 else
1530 printk(KERN_INFO "diag: No USB MDM ch");
1531 }
1532#endif
1533 return 0;
1534}
1535
1536int diagfwd_disconnect(void)
1537{
1538 printk(KERN_DEBUG "diag: USB disconnected\n");
1539 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001540 driver->debug_flag = 1;
1541 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001542 if (driver->logging_mode == USB_MODE) {
1543 driver->in_busy_1 = 1;
1544 driver->in_busy_2 = 1;
1545 driver->in_busy_qdsp_1 = 1;
1546 driver->in_busy_qdsp_2 = 1;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301547 driver->in_busy_wcnss_1 = 1;
1548 driver->in_busy_wcnss_2 = 1;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001549 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001550#ifdef CONFIG_DIAG_SDIO_PIPE
1551 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1552 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1553 diagfwd_disconnect_sdio();
1554#endif
1555 /* TBD - notify and flow control SMD */
1556 return 0;
1557}
1558
1559int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1560{
1561 unsigned char *buf = diag_write_ptr->buf;
1562 /*Determine if the write complete is for data from modem/apps/q6 */
1563 /* Need a context variable here instead */
1564 if (buf == (void *)driver->buf_in_1) {
1565 driver->in_busy_1 = 0;
1566 APPEND_DEBUG('o');
1567 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1568 } else if (buf == (void *)driver->buf_in_2) {
1569 driver->in_busy_2 = 0;
1570 APPEND_DEBUG('O');
1571 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1572 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1573 driver->in_busy_qdsp_1 = 0;
1574 APPEND_DEBUG('p');
1575 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1576 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1577 driver->in_busy_qdsp_2 = 0;
1578 APPEND_DEBUG('P');
1579 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
Ashay Jaiswal29620122012-03-21 12:02:36 +05301580 } else if (buf == driver->buf_in_wcnss_1) {
1581 driver->in_busy_wcnss_1 = 0;
1582 APPEND_DEBUG('r');
1583 queue_work(driver->diag_wq,
1584 &(driver->diag_read_smd_wcnss_work));
1585 } else if (buf == driver->buf_in_wcnss_2) {
1586 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001587 APPEND_DEBUG('R');
1588 queue_work(driver->diag_wq,
1589 &(driver->diag_read_smd_wcnss_work));
1590 }
1591#ifdef CONFIG_DIAG_SDIO_PIPE
1592 else if (buf == (void *)driver->buf_in_sdio)
1593 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001594 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001595 diagfwd_write_complete_sdio();
1596 else
1597 pr_err("diag: Incorrect buffer pointer while WRITE");
1598#endif
1599 else {
1600 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1601 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1602 POOL_TYPE_WRITE_STRUCT);
1603 APPEND_DEBUG('q');
1604 }
1605 return 0;
1606}
1607
1608int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1609{
1610 int status = diag_read_ptr->status;
1611 unsigned char *buf = diag_read_ptr->buf;
1612
1613 /* Determine if the read complete is for data on legacy/mdm ch */
1614 if (buf == (void *)driver->usb_buf_out) {
1615 driver->read_len_legacy = diag_read_ptr->actual;
1616 APPEND_DEBUG('s');
1617#ifdef DIAG_DEBUG
1618 printk(KERN_INFO "read data from USB, pkt length %d",
1619 diag_read_ptr->actual);
1620 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1621 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1622 diag_read_ptr->actual, 1);
1623#endif /* DIAG DEBUG */
1624 if (driver->logging_mode == USB_MODE) {
1625 if (status != -ECONNRESET && status != -ESHUTDOWN)
1626 queue_work(driver->diag_wq,
1627 &(driver->diag_proc_hdlc_work));
1628 else
1629 queue_work(driver->diag_wq,
1630 &(driver->diag_read_work));
1631 }
1632 }
1633#ifdef CONFIG_DIAG_SDIO_PIPE
1634 else if (buf == (void *)driver->usb_buf_mdm_out) {
1635 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001636 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001637 driver->read_len_mdm = diag_read_ptr->actual;
1638 diagfwd_read_complete_sdio();
1639 } else
1640 pr_err("diag: Incorrect buffer pointer while READ");
1641 }
1642#endif
1643 else
1644 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1645
1646 return 0;
1647}
1648
1649void diag_read_work_fn(struct work_struct *work)
1650{
1651 APPEND_DEBUG('d');
1652 driver->usb_read_ptr->buf = driver->usb_buf_out;
1653 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1654 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1655 APPEND_DEBUG('e');
1656}
1657
1658void diag_process_hdlc_fn(struct work_struct *work)
1659{
1660 APPEND_DEBUG('D');
1661 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1662 diag_read_work_fn(work);
1663 APPEND_DEBUG('E');
1664}
1665
1666void diag_usb_legacy_notifier(void *priv, unsigned event,
1667 struct diag_request *d_req)
1668{
1669 switch (event) {
1670 case USB_DIAG_CONNECT:
1671 diagfwd_connect();
1672 break;
1673 case USB_DIAG_DISCONNECT:
1674 diagfwd_disconnect();
1675 break;
1676 case USB_DIAG_READ_DONE:
1677 diagfwd_read_complete(d_req);
1678 break;
1679 case USB_DIAG_WRITE_DONE:
1680 diagfwd_write_complete(d_req);
1681 break;
1682 default:
1683 printk(KERN_ERR "Unknown event from USB diag\n");
1684 break;
1685 }
1686}
1687
1688#endif /* DIAG OVER USB */
1689
1690static void diag_smd_notify(void *ctxt, unsigned event)
1691{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001692 if (event == SMD_EVENT_CLOSE) {
1693 pr_info("diag: clean modem registration\n");
1694 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001695 driver->ch = 0;
1696 return;
1697 } else if (event == SMD_EVENT_OPEN) {
1698 driver->ch = ch_temp;
1699 }
1700 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001701}
1702
1703#if defined(CONFIG_MSM_N_WAY_SMD)
1704static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1705{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001706 if (event == SMD_EVENT_CLOSE) {
1707 pr_info("diag: clean lpass registration\n");
1708 diag_clear_reg(QDSP_PROC);
1709 driver->chqdsp = 0;
1710 return;
1711 } else if (event == SMD_EVENT_OPEN) {
1712 driver->chqdsp = chqdsp_temp;
1713 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001714 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1715}
1716#endif
1717
1718static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1719{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001720 if (event == SMD_EVENT_CLOSE) {
1721 pr_info("diag: clean wcnss registration\n");
1722 diag_clear_reg(WCNSS_PROC);
1723 driver->ch_wcnss = 0;
1724 return;
1725 } else if (event == SMD_EVENT_OPEN) {
1726 driver->ch_wcnss = ch_wcnss_temp;
1727 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001728 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1729}
1730
1731static int diag_smd_probe(struct platform_device *pdev)
1732{
1733 int r = 0;
1734
Shalabh Jaineefee052011-11-08 23:46:03 -08001735 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001736 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001737 ch_temp = driver->ch;
1738 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001739#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001740 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001741 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1742 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001743 chqdsp_temp = driver->chqdsp;
1744 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001745#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001746 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001747 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1748 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001749 ch_wcnss_temp = driver->ch_wcnss;
1750 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001751 pm_runtime_set_active(&pdev->dev);
1752 pm_runtime_enable(&pdev->dev);
1753 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1754
1755 return 0;
1756}
1757
1758static int diagfwd_runtime_suspend(struct device *dev)
1759{
1760 dev_dbg(dev, "pm_runtime: suspending...\n");
1761 return 0;
1762}
1763
1764static int diagfwd_runtime_resume(struct device *dev)
1765{
1766 dev_dbg(dev, "pm_runtime: resuming...\n");
1767 return 0;
1768}
1769
1770static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1771 .runtime_suspend = diagfwd_runtime_suspend,
1772 .runtime_resume = diagfwd_runtime_resume,
1773};
1774
1775static struct platform_driver msm_smd_ch1_driver = {
1776
1777 .probe = diag_smd_probe,
1778 .driver = {
1779 .name = "DIAG",
1780 .owner = THIS_MODULE,
1781 .pm = &diagfwd_dev_pm_ops,
1782 },
1783};
1784
1785static struct platform_driver diag_smd_lite_driver = {
1786
1787 .probe = diag_smd_probe,
1788 .driver = {
1789 .name = "APPS_RIVA_DATA",
1790 .owner = THIS_MODULE,
1791 .pm = &diagfwd_dev_pm_ops,
1792 },
1793};
1794
1795void diagfwd_init(void)
1796{
1797 diag_debug_buf_idx = 0;
1798 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001799 driver->use_device_tree = has_device_tree();
Shalabh Jaina06c6d72012-04-30 13:40:35 -07001800 mutex_init(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001801
1802 if (driver->event_mask == NULL) {
1803 driver->event_mask = kzalloc(sizeof(
1804 struct diag_ctrl_event_mask), GFP_KERNEL);
1805 if (driver->event_mask == NULL)
1806 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001807 kmemleak_not_leak(driver->event_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001808 }
1809 if (driver->msg_mask == NULL) {
1810 driver->msg_mask = kzalloc(sizeof(
1811 struct diag_ctrl_msg_mask), GFP_KERNEL);
1812 if (driver->msg_mask == NULL)
1813 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001814 kmemleak_not_leak(driver->msg_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001815 }
1816 if (driver->log_mask == NULL) {
1817 driver->log_mask = kzalloc(sizeof(
1818 struct diag_ctrl_log_mask), GFP_KERNEL);
1819 if (driver->log_mask == NULL)
1820 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001821 kmemleak_not_leak(driver->log_mask);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001822 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001823 if (driver->buf_in_1 == NULL) {
1824 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1825 if (driver->buf_in_1 == NULL)
1826 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001827 kmemleak_not_leak(driver->buf_in_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001828 }
1829 if (driver->buf_in_2 == NULL) {
1830 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1831 if (driver->buf_in_2 == NULL)
1832 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001833 kmemleak_not_leak(driver->buf_in_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001834 }
1835 if (driver->buf_in_qdsp_1 == NULL) {
1836 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1837 if (driver->buf_in_qdsp_1 == NULL)
1838 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001839 kmemleak_not_leak(driver->buf_in_qdsp_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001840 }
1841 if (driver->buf_in_qdsp_2 == NULL) {
1842 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1843 if (driver->buf_in_qdsp_2 == NULL)
1844 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001845 kmemleak_not_leak(driver->buf_in_qdsp_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001846 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301847 if (driver->buf_in_wcnss_1 == NULL) {
1848 driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1849 if (driver->buf_in_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001850 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001851 kmemleak_not_leak(driver->buf_in_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001852 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301853 if (driver->buf_in_wcnss_2 == NULL) {
1854 driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1855 if (driver->buf_in_wcnss_2 == NULL)
1856 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001857 kmemleak_not_leak(driver->buf_in_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301858 }
1859
Shalabh Jain321c8b52012-02-22 12:37:06 -08001860 if (driver->buf_msg_mask_update == NULL) {
1861 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1862 GFP_KERNEL);
1863 if (driver->buf_msg_mask_update == NULL)
1864 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001865 kmemleak_not_leak(driver->buf_msg_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001866 }
1867 if (driver->buf_log_mask_update == NULL) {
1868 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1869 GFP_KERNEL);
1870 if (driver->buf_log_mask_update == NULL)
1871 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001872 kmemleak_not_leak(driver->buf_log_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001873 }
1874 if (driver->buf_event_mask_update == NULL) {
1875 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1876 GFP_KERNEL);
1877 if (driver->buf_event_mask_update == NULL)
1878 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001879 kmemleak_not_leak(driver->buf_event_mask_update);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001880 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001881 if (driver->usb_buf_out == NULL &&
1882 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1883 GFP_KERNEL)) == NULL)
1884 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001885 kmemleak_not_leak(driver->usb_buf_out);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001886 if (driver->hdlc_buf == NULL
1887 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1888 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001889 kmemleak_not_leak(driver->hdlc_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001890 if (driver->user_space_data == NULL)
1891 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1892 if (driver->user_space_data == NULL)
1893 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001894 kmemleak_not_leak(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001895 if (driver->msg_masks == NULL
1896 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1897 GFP_KERNEL)) == NULL)
1898 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001899 kmemleak_not_leak(driver->msg_masks);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001900 diag_create_msg_mask_table();
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001901 diag_event_num_bytes = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001902 if (driver->log_masks == NULL &&
1903 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1904 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001905 kmemleak_not_leak(driver->log_masks);
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -07001906 driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001907 if (driver->event_masks == NULL &&
1908 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1909 GFP_KERNEL)) == NULL)
1910 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001911 kmemleak_not_leak(driver->event_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001912 if (driver->client_map == NULL &&
1913 (driver->client_map = kzalloc
1914 ((driver->num_clients) * sizeof(struct diag_client_map),
1915 GFP_KERNEL)) == NULL)
1916 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001917 kmemleak_not_leak(driver->client_map);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001918 if (driver->buf_tbl == NULL)
1919 driver->buf_tbl = kzalloc(buf_tbl_size *
1920 sizeof(struct diag_write_device), GFP_KERNEL);
1921 if (driver->buf_tbl == NULL)
1922 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001923 kmemleak_not_leak(driver->buf_tbl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001924 if (driver->data_ready == NULL &&
1925 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1926 , GFP_KERNEL)) == NULL)
1927 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001928 kmemleak_not_leak(driver->data_ready);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001929 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001930 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001931 sizeof(struct diag_master_table),
1932 GFP_KERNEL)) == NULL)
1933 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001934 kmemleak_not_leak(driver->table);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001935 if (driver->write_ptr_1 == NULL) {
1936 driver->write_ptr_1 = kzalloc(
1937 sizeof(struct diag_request), GFP_KERNEL);
1938 if (driver->write_ptr_1 == NULL)
1939 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001940 kmemleak_not_leak(driver->write_ptr_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001941 }
1942 if (driver->write_ptr_2 == NULL) {
1943 driver->write_ptr_2 = kzalloc(
1944 sizeof(struct diag_request), GFP_KERNEL);
1945 if (driver->write_ptr_2 == NULL)
1946 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001947 kmemleak_not_leak(driver->write_ptr_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001948 }
1949 if (driver->write_ptr_qdsp_1 == NULL) {
1950 driver->write_ptr_qdsp_1 = kzalloc(
1951 sizeof(struct diag_request), GFP_KERNEL);
1952 if (driver->write_ptr_qdsp_1 == NULL)
1953 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001954 kmemleak_not_leak(driver->write_ptr_qdsp_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001955 }
1956 if (driver->write_ptr_qdsp_2 == NULL) {
1957 driver->write_ptr_qdsp_2 = kzalloc(
1958 sizeof(struct diag_request), GFP_KERNEL);
1959 if (driver->write_ptr_qdsp_2 == NULL)
1960 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001961 kmemleak_not_leak(driver->write_ptr_qdsp_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001962 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301963 if (driver->write_ptr_wcnss_1 == NULL) {
1964 driver->write_ptr_wcnss_1 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001965 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301966 if (driver->write_ptr_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001967 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001968 kmemleak_not_leak(driver->write_ptr_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001969 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301970 if (driver->write_ptr_wcnss_2 == NULL) {
1971 driver->write_ptr_wcnss_2 = kzalloc(
1972 sizeof(struct diag_request), GFP_KERNEL);
1973 if (driver->write_ptr_wcnss_2 == NULL)
1974 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001975 kmemleak_not_leak(driver->write_ptr_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301976 }
1977
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001978 if (driver->usb_read_ptr == NULL) {
1979 driver->usb_read_ptr = kzalloc(
1980 sizeof(struct diag_request), GFP_KERNEL);
1981 if (driver->usb_read_ptr == NULL)
1982 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001983 kmemleak_not_leak(driver->usb_read_ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001984 }
1985 if (driver->pkt_buf == NULL &&
1986 (driver->pkt_buf = kzalloc(PKT_SIZE,
1987 GFP_KERNEL)) == NULL)
1988 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001989 kmemleak_not_leak(driver->pkt_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001990 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001991 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001992 if (driver->apps_rsp_buf == NULL)
1993 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001994 kmemleak_not_leak(driver->apps_rsp_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001995 }
1996 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1997#ifdef CONFIG_DIAG_OVER_USB
1998 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1999 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002000 INIT_WORK(&(driver->diag_modem_mask_update_work),
2001 diag_modem_mask_update_fn);
2002 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
2003 diag_qdsp_mask_update_fn);
2004 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
2005 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002006 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
2007 diag_usb_legacy_notifier);
2008 if (IS_ERR(driver->legacy_ch)) {
2009 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
2010 goto err;
2011 }
2012#endif
2013 platform_driver_register(&msm_smd_ch1_driver);
2014 platform_driver_register(&diag_smd_lite_driver);
2015
2016 return;
2017err:
2018 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08002019 kfree(driver->event_mask);
2020 kfree(driver->log_mask);
2021 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002022 kfree(driver->buf_in_1);
2023 kfree(driver->buf_in_2);
2024 kfree(driver->buf_in_qdsp_1);
2025 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302026 kfree(driver->buf_in_wcnss_1);
2027 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002028 kfree(driver->buf_msg_mask_update);
2029 kfree(driver->buf_log_mask_update);
2030 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002031 kfree(driver->usb_buf_out);
2032 kfree(driver->hdlc_buf);
2033 kfree(driver->msg_masks);
2034 kfree(driver->log_masks);
2035 kfree(driver->event_masks);
2036 kfree(driver->client_map);
2037 kfree(driver->buf_tbl);
2038 kfree(driver->data_ready);
2039 kfree(driver->table);
2040 kfree(driver->pkt_buf);
2041 kfree(driver->write_ptr_1);
2042 kfree(driver->write_ptr_2);
2043 kfree(driver->write_ptr_qdsp_1);
2044 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302045 kfree(driver->write_ptr_wcnss_1);
2046 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002047 kfree(driver->usb_read_ptr);
2048 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002049 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002050 if (driver->diag_wq)
2051 destroy_workqueue(driver->diag_wq);
2052}
2053
2054void diagfwd_exit(void)
2055{
2056 smd_close(driver->ch);
2057 smd_close(driver->chqdsp);
2058 smd_close(driver->ch_wcnss);
2059 driver->ch = 0; /* SMD can make this NULL */
2060 driver->chqdsp = 0;
2061 driver->ch_wcnss = 0;
2062#ifdef CONFIG_DIAG_OVER_USB
2063 if (driver->usb_connected)
2064 usb_diag_free_req(driver->legacy_ch);
2065 usb_diag_close(driver->legacy_ch);
2066#endif
2067 platform_driver_unregister(&msm_smd_ch1_driver);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -07002068 platform_driver_unregister(&msm_diag_dci_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002069 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002070 kfree(driver->event_mask);
2071 kfree(driver->log_mask);
2072 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002073 kfree(driver->buf_in_1);
2074 kfree(driver->buf_in_2);
2075 kfree(driver->buf_in_qdsp_1);
2076 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302077 kfree(driver->buf_in_wcnss_1);
2078 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002079 kfree(driver->buf_msg_mask_update);
2080 kfree(driver->buf_log_mask_update);
2081 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002082 kfree(driver->usb_buf_out);
2083 kfree(driver->hdlc_buf);
2084 kfree(driver->msg_masks);
2085 kfree(driver->log_masks);
2086 kfree(driver->event_masks);
2087 kfree(driver->client_map);
2088 kfree(driver->buf_tbl);
2089 kfree(driver->data_ready);
2090 kfree(driver->table);
2091 kfree(driver->pkt_buf);
2092 kfree(driver->write_ptr_1);
2093 kfree(driver->write_ptr_2);
2094 kfree(driver->write_ptr_qdsp_1);
2095 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302096 kfree(driver->write_ptr_wcnss_1);
2097 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002098 kfree(driver->usb_read_ptr);
2099 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002100 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002101 destroy_workqueue(driver->diag_wq);
2102}