blob: efe0241279df6ae7c66dc1665487c55f99a2facc [file] [log] [blame]
Dixon Peterson32e70bb2011-12-16 13:26:45 -08001/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070012#include <linux/slab.h>
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/err.h>
17#include <linux/platform_device.h>
18#include <linux/sched.h>
19#include <linux/workqueue.h>
20#include <linux/pm_runtime.h>
21#include <linux/diagchar.h>
22#include <linux/delay.h>
23#include <linux/reboot.h>
Dixon Petersonb4618a42012-02-29 18:56:31 -080024#include <linux/of.h>
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070025#include <linux/spinlock.h>
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 Jain6a2ca7c2012-04-10 14:35:15 -070040#define MODE_CMD 41
41#define RESET_ID 2
42#define ALL_EQUIP_ID 100
43#define ALL_SSID -1
44#define MAX_SSID_PER_RANGE 100
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070045
46int diag_debug_buf_idx;
47unsigned char diag_debug_buf[1024];
48static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
49struct diag_master_table entry;
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -080050smd_channel_t *ch_temp, *chqdsp_temp, *ch_wcnss_temp;
Shalabh Jain321c8b52012-02-22 12:37:06 -080051int diag_event_num_bytes;
52int diag_event_config;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070053struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
54struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
Shalabh Jain321c8b52012-02-22 12:37:06 -080055struct mask_info {
56 int equip_id;
57 int num_items;
58 int index;
59};
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070060spinlock_t diag_cntl_lock;
61
62#define CREATE_MSG_MASK_TBL_ROW(XX) \
63do { \
64 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX; \
65 msg_mask_tbl_ptr += 4; \
66 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
67 msg_mask_tbl_ptr += 4; \
68 /* increment by MAX_SSID_PER_RANGE cells */ \
69 msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int); \
70} while (0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070071
72#define ENCODE_RSP_AND_SEND(buf_length) \
73do { \
74 send.state = DIAG_STATE_START; \
75 send.pkt = driver->apps_rsp_buf; \
76 send.last = (void *)(driver->apps_rsp_buf + buf_length); \
77 send.terminate = 1; \
78 if (!driver->in_busy_1) { \
79 enc.dest = driver->buf_in_1; \
Shalabh Jain321c8b52012-02-22 12:37:06 -080080 enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);\
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070081 diag_hdlc_encode(&send, &enc); \
82 driver->write_ptr_1->buf = driver->buf_in_1; \
83 driver->write_ptr_1->length = (int)(enc.dest - \
84 (void *)(driver->buf_in_1)); \
Shalabh Jain3893bf92011-09-18 18:37:16 -070085 driver->in_busy_1 = 1; \
Shalabh Jain69890aa2011-10-10 12:59:16 -070086 diag_device_write(driver->buf_in_1, MODEM_DATA, \
87 driver->write_ptr_1); \
Shalabh Jain321c8b52012-02-22 12:37:06 -080088 memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE); \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070089 } \
90} while (0)
91
92#define CHK_OVERFLOW(bufStart, start, end, length) \
93((bufStart <= start) && (end - start >= length)) ? 1 : 0
94
Dixon Petersonb4618a42012-02-29 18:56:31 -080095/* Determine if this device uses a device tree */
96#ifdef CONFIG_OF
97static int has_device_tree(void)
98{
99 struct device_node *node;
100
101 node = of_find_node_by_path("/");
102 if (node) {
103 of_node_put(node);
104 return 1;
105 }
106 return 0;
107}
108#else
109static int has_device_tree(void)
110{
111 return 0;
112}
113#endif
114
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700115int chk_config_get_id(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700116{
Shalabh Jain482bf122011-12-06 03:54:47 -0800117 /* For all Fusion targets, Modem will always be present */
118 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
119 return 0;
120
Dixon Petersonb4618a42012-02-29 18:56:31 -0800121 if (driver->use_device_tree) {
122 if (machine_is_copper())
123 return MSM8974_TOOLS_ID;
124 else
125 return 0;
126 } else {
127 switch (socinfo_get_msm_cpu()) {
128 case MSM_CPU_8X60:
129 return APQ8060_TOOLS_ID;
130 case MSM_CPU_8960:
131 return AO8960_TOOLS_ID;
132 case MSM_CPU_8064:
133 return APQ8064_TOOLS_ID;
134 case MSM_CPU_8930:
135 return MSM8930_TOOLS_ID;
136 case MSM_CPU_COPPER:
137 return MSM8974_TOOLS_ID;
138 case MSM_CPU_8625:
139 return MSM8625_TOOLS_ID;
140 default:
141 return 0;
142 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700143 }
144}
145
146/*
Shalabh Jain321c8b52012-02-22 12:37:06 -0800147 * This will return TRUE for targets which support apps only mode and hence SSR.
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700148 * This applies to 8960 and newer targets.
149 */
150int chk_apps_only(void)
151{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800152 if (driver->use_device_tree)
153 return 1;
154
155 switch (socinfo_get_msm_cpu()) {
156 case MSM_CPU_8960:
157 case MSM_CPU_8064:
158 case MSM_CPU_8930:
159 case MSM_CPU_8627:
160 case MSM_CPU_9615:
161 case MSM_CPU_COPPER:
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700162 return 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700163 default:
164 return 0;
165 }
166}
167
Shalabh Jain10f5f432012-01-11 11:45:44 +0530168/*
169 * This will return TRUE for targets which support apps as master.
170 * Thus, SW DLOAD and Mode Reset are supported on apps processor.
171 * This applies to 8960 and newer targets.
172 */
173int chk_apps_master(void)
174{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800175 if (driver->use_device_tree)
176 return 1;
177 else if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615() ||
178 cpu_is_apq8064() || cpu_is_msm8627())
179 return 1;
180 else
181 return 0;
182}
183
184inline int chk_polling_response(void)
185{
186 if (!(driver->polling_reg_flag) && chk_apps_master())
187 /*
188 * If the apps processor is master and no other processor
189 * has registered to respond for polling
190 */
191 return 1;
192 else if (!(driver->ch) && !(chk_apps_master()))
193 /*
194 * If the apps processor is not the master and the modem
195 * is not up
196 */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530197 return 1;
198 else
199 return 0;
200}
201
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700202void __diag_smd_send_req(void)
203{
204 void *buf = NULL;
205 int *in_busy_ptr = NULL;
206 struct diag_request *write_ptr_modem = NULL;
207
208 if (!driver->in_busy_1) {
209 buf = driver->buf_in_1;
210 write_ptr_modem = driver->write_ptr_1;
211 in_busy_ptr = &(driver->in_busy_1);
212 } else if (!driver->in_busy_2) {
213 buf = driver->buf_in_2;
214 write_ptr_modem = driver->write_ptr_2;
215 in_busy_ptr = &(driver->in_busy_2);
216 }
217
218 if (driver->ch && buf) {
219 int r = smd_read_avail(driver->ch);
220
221 if (r > IN_BUF_SIZE) {
222 if (r < MAX_IN_BUF_SIZE) {
223 pr_err("diag: SMD sending in "
224 "packets upto %d bytes", r);
225 buf = krealloc(buf, r, GFP_KERNEL);
226 } else {
227 pr_err("diag: SMD sending in "
228 "packets more than %d bytes", MAX_IN_BUF_SIZE);
229 return;
230 }
231 }
232 if (r > 0) {
233 if (!buf)
234 pr_info("Out of diagmem for Modem\n");
235 else {
236 APPEND_DEBUG('i');
237 smd_read(driver->ch, buf, r);
238 APPEND_DEBUG('j');
239 write_ptr_modem->length = r;
240 *in_busy_ptr = 1;
241 diag_device_write(buf, MODEM_DATA,
242 write_ptr_modem);
243 }
244 }
245 }
246}
247
248int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr)
249{
250 int i, err = 0;
251
252 if (driver->logging_mode == MEMORY_DEVICE_MODE) {
253 if (proc_num == APPS_DATA) {
254 for (i = 0; i < driver->poolsize_write_struct; i++)
255 if (driver->buf_tbl[i].length == 0) {
256 driver->buf_tbl[i].buf = buf;
257 driver->buf_tbl[i].length =
258 driver->used;
259#ifdef DIAG_DEBUG
260 pr_debug("diag: ENQUEUE buf ptr"
261 " and length is %x , %d\n",
262 (unsigned int)(driver->buf_
263 tbl[i].buf), driver->buf_tbl[i].length);
264#endif
265 break;
266 }
267 }
268 for (i = 0; i < driver->num_clients; i++)
269 if (driver->client_map[i].pid ==
270 driver->logging_process_id)
271 break;
272 if (i < driver->num_clients) {
Shalabh Jain69890aa2011-10-10 12:59:16 -0700273 driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700274 wake_up_interruptible(&driver->wait_q);
275 } else
276 return -EINVAL;
277 } else if (driver->logging_mode == NO_LOGGING_MODE) {
278 if (proc_num == MODEM_DATA) {
279 driver->in_busy_1 = 0;
280 driver->in_busy_2 = 0;
281 queue_work(driver->diag_wq, &(driver->
282 diag_read_smd_work));
283 } else if (proc_num == QDSP_DATA) {
284 driver->in_busy_qdsp_1 = 0;
285 driver->in_busy_qdsp_2 = 0;
286 queue_work(driver->diag_wq, &(driver->
287 diag_read_smd_qdsp_work));
288 } else if (proc_num == WCNSS_DATA) {
Ashay Jaiswal29620122012-03-21 12:02:36 +0530289 driver->in_busy_wcnss_1 = 0;
290 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700291 queue_work(driver->diag_wq, &(driver->
292 diag_read_smd_wcnss_work));
293 }
Shalabh Jain482bf122011-12-06 03:54:47 -0800294#ifdef CONFIG_DIAG_SDIO_PIPE
295 else if (proc_num == SDIO_DATA) {
296 driver->in_busy_sdio = 0;
297 queue_work(driver->diag_sdio_wq,
298 &(driver->diag_read_sdio_work));
299 }
300#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700301 err = -1;
302 }
303#ifdef CONFIG_DIAG_OVER_USB
304 else if (driver->logging_mode == USB_MODE) {
305 if (proc_num == APPS_DATA) {
306 driver->write_ptr_svc = (struct diag_request *)
307 (diagmem_alloc(driver, sizeof(struct diag_request),
308 POOL_TYPE_WRITE_STRUCT));
309 if (driver->write_ptr_svc) {
310 driver->write_ptr_svc->length = driver->used;
311 driver->write_ptr_svc->buf = buf;
312 err = usb_diag_write(driver->legacy_ch,
313 driver->write_ptr_svc);
314 } else
315 err = -1;
316 } else if (proc_num == MODEM_DATA) {
317 write_ptr->buf = buf;
318#ifdef DIAG_DEBUG
319 printk(KERN_INFO "writing data to USB,"
320 "pkt length %d\n", write_ptr->length);
321 print_hex_dump(KERN_DEBUG, "Written Packet Data to"
322 " USB: ", 16, 1, DUMP_PREFIX_ADDRESS,
323 buf, write_ptr->length, 1);
324#endif /* DIAG DEBUG */
325 err = usb_diag_write(driver->legacy_ch, write_ptr);
326 } else if (proc_num == QDSP_DATA) {
327 write_ptr->buf = buf;
328 err = usb_diag_write(driver->legacy_ch, write_ptr);
329 } else if (proc_num == WCNSS_DATA) {
330 write_ptr->buf = buf;
331 err = usb_diag_write(driver->legacy_ch, write_ptr);
332 }
333#ifdef CONFIG_DIAG_SDIO_PIPE
334 else if (proc_num == SDIO_DATA) {
335 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -0800336 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700337 write_ptr->buf = buf;
338 err = usb_diag_write(driver->mdm_ch, write_ptr);
339 } else
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800340 pr_err("diag: Incorrect sdio data "
341 "while USB write\n");
342 }
343#endif
344#ifdef CONFIG_DIAG_HSIC_PIPE
345 else if (proc_num == HSIC_DATA) {
346 if (driver->hsic_device_enabled) {
347 write_ptr->buf = buf;
348 err = usb_diag_write(driver->mdm_ch, write_ptr);
349 } else
350 pr_err("diag: Incorrect hsic data "
351 "while USB write\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700352 }
353#endif
354 APPEND_DEBUG('d');
355 }
356#endif /* DIAG OVER USB */
357 return err;
358}
359
360void __diag_smd_wcnss_send_req(void)
361{
Ashay Jaiswal29620122012-03-21 12:02:36 +0530362 void *buf = NULL;
363 int *in_busy_wcnss_ptr = NULL;
364 struct diag_request *write_ptr_wcnss = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700365
Ashay Jaiswal29620122012-03-21 12:02:36 +0530366 if (!driver->in_busy_wcnss_1) {
367 buf = driver->buf_in_wcnss_1;
368 write_ptr_wcnss = driver->write_ptr_wcnss_1;
369 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_1);
370 } else if (!driver->in_busy_wcnss_2) {
371 buf = driver->buf_in_wcnss_2;
372 write_ptr_wcnss = driver->write_ptr_wcnss_2;
373 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_2);
374 }
375
376 if (driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700377 int r = smd_read_avail(driver->ch_wcnss);
378 if (r > IN_BUF_SIZE) {
379 if (r < MAX_IN_BUF_SIZE) {
380 pr_err("diag: wcnss packets > %d bytes", r);
381 buf = krealloc(buf, r, GFP_KERNEL);
382 } else {
383 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
384 return;
385 }
386 }
387 if (r > 0) {
388 if (!buf) {
389 pr_err("Out of diagmem for wcnss\n");
390 } else {
391 APPEND_DEBUG('i');
392 smd_read(driver->ch_wcnss, buf, r);
393 APPEND_DEBUG('j');
394 write_ptr_wcnss->length = r;
395 *in_busy_wcnss_ptr = 1;
396 diag_device_write(buf, WCNSS_DATA,
397 write_ptr_wcnss);
398 }
399 }
400 }
401}
402
403void __diag_smd_qdsp_send_req(void)
404{
405 void *buf = NULL;
406 int *in_busy_qdsp_ptr = NULL;
407 struct diag_request *write_ptr_qdsp = NULL;
408
409 if (!driver->in_busy_qdsp_1) {
410 buf = driver->buf_in_qdsp_1;
411 write_ptr_qdsp = driver->write_ptr_qdsp_1;
412 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1);
413 } else if (!driver->in_busy_qdsp_2) {
414 buf = driver->buf_in_qdsp_2;
415 write_ptr_qdsp = driver->write_ptr_qdsp_2;
416 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2);
417 }
418
419 if (driver->chqdsp && buf) {
420 int r = smd_read_avail(driver->chqdsp);
421
422 if (r > IN_BUF_SIZE) {
423 if (r < MAX_IN_BUF_SIZE) {
424 pr_err("diag: SMD sending in "
425 "packets upto %d bytes", r);
426 buf = krealloc(buf, r, GFP_KERNEL);
427 } else {
428 pr_err("diag: SMD sending in "
429 "packets more than %d bytes", MAX_IN_BUF_SIZE);
430 return;
431 }
432 }
433 if (r > 0) {
434 if (!buf)
435 printk(KERN_INFO "Out of diagmem for QDSP\n");
436 else {
437 APPEND_DEBUG('i');
438 smd_read(driver->chqdsp, buf, r);
439 APPEND_DEBUG('j');
440 write_ptr_qdsp->length = r;
441 *in_busy_qdsp_ptr = 1;
442 diag_device_write(buf, QDSP_DATA,
443 write_ptr_qdsp);
444 }
445 }
446 }
447}
448
449static void diag_print_mask_table(void)
450{
451/* Enable this to print mask table when updated */
452#ifdef MASK_DEBUG
453 int first;
454 int last;
455 uint8_t *ptr = driver->msg_masks;
456 int i = 0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700457 pr_info("diag: F3 message mask table\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700458 while (*(uint32_t *)(ptr + 4)) {
459 first = *(uint32_t *)ptr;
460 ptr += 4;
461 last = *(uint32_t *)ptr;
462 ptr += 4;
463 printk(KERN_INFO "SSID %d - %d\n", first, last);
464 for (i = 0 ; i <= last - first ; i++)
465 printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700466 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700467
468 }
469#endif
470}
471
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700472void diag_create_msg_mask_table(void)
473{
474 uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
475
476 CREATE_MSG_MASK_TBL_ROW(0);
477 CREATE_MSG_MASK_TBL_ROW(1);
478 CREATE_MSG_MASK_TBL_ROW(2);
479 CREATE_MSG_MASK_TBL_ROW(3);
480 CREATE_MSG_MASK_TBL_ROW(4);
481 CREATE_MSG_MASK_TBL_ROW(5);
482 CREATE_MSG_MASK_TBL_ROW(6);
483 CREATE_MSG_MASK_TBL_ROW(7);
484 CREATE_MSG_MASK_TBL_ROW(8);
485 CREATE_MSG_MASK_TBL_ROW(9);
486 CREATE_MSG_MASK_TBL_ROW(10);
487 CREATE_MSG_MASK_TBL_ROW(11);
488 CREATE_MSG_MASK_TBL_ROW(12);
489 CREATE_MSG_MASK_TBL_ROW(13);
490 CREATE_MSG_MASK_TBL_ROW(14);
491 CREATE_MSG_MASK_TBL_ROW(15);
492 CREATE_MSG_MASK_TBL_ROW(16);
493 CREATE_MSG_MASK_TBL_ROW(17);
494 CREATE_MSG_MASK_TBL_ROW(18);
495 CREATE_MSG_MASK_TBL_ROW(19);
496 CREATE_MSG_MASK_TBL_ROW(20);
497 CREATE_MSG_MASK_TBL_ROW(21);
498 CREATE_MSG_MASK_TBL_ROW(22);
499}
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700500
501static void diag_set_msg_mask(int rt_mask)
502{
503 int first_ssid, last_ssid, i;
504 uint8_t *parse_ptr, *ptr = driver->msg_masks;
505
506 mutex_lock(&driver->diagchar_mutex);
507 while (*(uint32_t *)(ptr + 4)) {
508 first_ssid = *(uint32_t *)ptr;
509 ptr += 4;
510 last_ssid = *(uint32_t *)ptr;
511 ptr += 4;
512 parse_ptr = ptr;
513 pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
514 for (i = 0; i < last_ssid - first_ssid + 1; i++) {
515 *(int *)parse_ptr = rt_mask;
516 parse_ptr += 4;
517 }
518 ptr += MAX_SSID_PER_RANGE * 4;
519 }
520 mutex_unlock(&driver->diagchar_mutex);
521}
522
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700523static void diag_update_msg_mask(int start, int end , uint8_t *buf)
524{
525 int found = 0;
526 int first;
527 int last;
528 uint8_t *ptr = driver->msg_masks;
529 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
530 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
531
532 mutex_lock(&driver->diagchar_mutex);
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530533
Shalabh Jain321c8b52012-02-22 12:37:06 -0800534 /* First SSID can be zero : So check that last is non-zero */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700535 while (*(uint32_t *)(ptr + 4)) {
536 first = *(uint32_t *)ptr;
537 ptr += 4;
538 last = *(uint32_t *)ptr;
539 ptr += 4;
540 if (start >= first && start <= last) {
541 ptr += (start - first)*4;
542 if (end <= last)
543 if (CHK_OVERFLOW(ptr_buffer_start, ptr,
544 ptr_buffer_end,
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700545 (((end - start)+1)*4))) {
546 pr_debug("diag: update ssid start %d,"
547 " end %d\n", start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700548 memcpy(ptr, buf , ((end - start)+1)*4);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700549 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550 printk(KERN_CRIT "Not enough"
551 " buffer space for"
552 " MSG_MASK\n");
553 else
554 printk(KERN_INFO "Unable to copy"
555 " mask change\n");
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530556
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700557 found = 1;
558 break;
559 } else {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700560 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700561 }
562 }
563 /* Entry was not found - add new table */
564 if (!found) {
565 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
566 8 + ((end - start) + 1)*4)) {
567 memcpy(ptr, &(start) , 4);
568 ptr += 4;
569 memcpy(ptr, &(end), 4);
570 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700571 pr_debug("diag: adding NEW ssid start %d, end %d\n",
572 start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700573 memcpy(ptr, buf , ((end - start) + 1)*4);
574 } else
575 printk(KERN_CRIT " Not enough buffer"
576 " space for MSG_MASK\n");
577 }
578 mutex_unlock(&driver->diagchar_mutex);
579 diag_print_mask_table();
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530580
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700581}
582
Shalabh Jaina51f2592012-03-08 14:36:35 -0800583void diag_toggle_event_mask(int toggle)
584{
585 uint8_t *ptr = driver->event_masks;
586
587 mutex_lock(&driver->diagchar_mutex);
588 if (toggle)
589 memset(ptr, 0xFF, EVENT_MASK_SIZE);
590 else
591 memset(ptr, 0, EVENT_MASK_SIZE);
592 mutex_unlock(&driver->diagchar_mutex);
593}
594
Shalabh Jain321c8b52012-02-22 12:37:06 -0800595static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700596{
597 uint8_t *ptr = driver->event_masks;
598 uint8_t *temp = buf + 2;
599
600 mutex_lock(&driver->diagchar_mutex);
601 if (!toggle)
602 memset(ptr, 0 , EVENT_MASK_SIZE);
603 else
604 if (CHK_OVERFLOW(ptr, ptr,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800605 ptr+EVENT_MASK_SIZE, num_bytes))
606 memcpy(ptr, temp , num_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700607 else
608 printk(KERN_CRIT "Not enough buffer space "
609 "for EVENT_MASK\n");
610 mutex_unlock(&driver->diagchar_mutex);
611}
612
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700613static void diag_disable_log_mask(void)
614{
615 int i = 0;
616 struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
617
618 pr_debug("diag: disable log masks\n");
619 mutex_lock(&driver->diagchar_mutex);
620 for (i = 0; i < MAX_EQUIP_ID; i++) {
621 pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
622 if (!(parse_ptr->equip_id)) /* Reached a null entry */
623 break;
624 memset(driver->log_masks + parse_ptr->index, 0,
625 (parse_ptr->num_items + 7)/8);
626 parse_ptr++;
627 }
628 mutex_unlock(&driver->diagchar_mutex);
629}
630
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700631static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
632{
633 uint8_t *temp = buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700634 int i = 0;
635 unsigned char *ptr_data;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700636 int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700637 struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700638
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700639 pr_debug("diag: received equip id = %d\n", equip_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700640 mutex_lock(&driver->diagchar_mutex);
641 /* Check if we already know index of this equipment ID */
642 for (i = 0; i < MAX_EQUIP_ID; i++) {
643 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
644 offset = ptr->index;
645 break;
646 }
647 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
Shalabh Jain321c8b52012-02-22 12:37:06 -0800648 /* Reached a null entry */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700649 ptr->equip_id = equip_id;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800650 ptr->num_items = num_items;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651 ptr->index = driver->log_masks_length;
652 offset = driver->log_masks_length;
653 driver->log_masks_length += ((num_items+7)/8);
654 break;
655 }
656 ptr++;
657 }
658 ptr_data = driver->log_masks + offset;
659 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
660 + LOG_MASK_SIZE, (num_items+7)/8))
661 memcpy(ptr_data, temp , (num_items+7)/8);
662 else
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700663 pr_err("diag: Not enough buffer space for LOG_MASK\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700664 mutex_unlock(&driver->diagchar_mutex);
665}
666
667static void diag_update_pkt_buffer(unsigned char *buf)
668{
669 unsigned char *ptr = driver->pkt_buf;
670 unsigned char *temp = buf;
671
672 mutex_lock(&driver->diagchar_mutex);
673 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
674 memcpy(ptr, temp , driver->pkt_length);
675 else
676 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
677 mutex_unlock(&driver->diagchar_mutex);
678}
679
680void diag_update_userspace_clients(unsigned int type)
681{
682 int i;
683
684 mutex_lock(&driver->diagchar_mutex);
685 for (i = 0; i < driver->num_clients; i++)
686 if (driver->client_map[i].pid != 0)
687 driver->data_ready[i] |= type;
688 wake_up_interruptible(&driver->wait_q);
689 mutex_unlock(&driver->diagchar_mutex);
690}
691
692void diag_update_sleeping_process(int process_id)
693{
694 int i;
695
696 mutex_lock(&driver->diagchar_mutex);
697 for (i = 0; i < driver->num_clients; i++)
698 if (driver->client_map[i].pid == process_id) {
699 driver->data_ready[i] |= PKT_TYPE;
700 break;
701 }
702 wake_up_interruptible(&driver->wait_q);
703 mutex_unlock(&driver->diagchar_mutex);
704}
705
706void diag_send_data(struct diag_master_table entry, unsigned char *buf,
707 int len, int type)
708{
709 driver->pkt_length = len;
710 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
711 diag_update_pkt_buffer(buf);
712 diag_update_sleeping_process(entry.process_id);
713 } else {
714 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700715 if (entry.client_id == MODEM_PROC && driver->ch) {
Shalabh Jain10f5f432012-01-11 11:45:44 +0530716 if (chk_apps_master() &&
Shalabh Jainc9f35092011-07-28 18:36:17 -0700717 (int)(*(char *)buf) == MODE_CMD)
Dixon Petersonff425d12011-12-06 18:12:35 -0800718 if ((int)(*(char *)(buf+1)) ==
719 RESET_ID)
Shalabh Jainc9f35092011-07-28 18:36:17 -0700720 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700721 smd_write(driver->ch, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700722 } else if (entry.client_id == QDSP_PROC &&
723 driver->chqdsp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700724 smd_write(driver->chqdsp, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700725 } else if (entry.client_id == WCNSS_PROC &&
726 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700727 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700728 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700729 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700730 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700731 }
732 }
733}
734
Shalabh Jain321c8b52012-02-22 12:37:06 -0800735void diag_modem_mask_update_fn(struct work_struct *work)
736{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700737 diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
738 ALL_SSID, MODEM_PROC);
739 diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800740 diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
741}
742
743void diag_qdsp_mask_update_fn(struct work_struct *work)
744{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700745 diag_send_msg_mask_update(driver->chqdsp_cntl, ALL_SSID,
746 ALL_SSID, QDSP_PROC);
747 diag_send_log_mask_update(driver->chqdsp_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800748 diag_send_event_mask_update(driver->chqdsp_cntl, diag_event_num_bytes);
749}
750
751void diag_wcnss_mask_update_fn(struct work_struct *work)
752{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700753 diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
754 ALL_SSID, WCNSS_PROC);
755 diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800756 diag_send_event_mask_update(driver->ch_wcnss_cntl,
757 diag_event_num_bytes);
758}
759
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700760void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800761{
762 void *buf = driver->buf_log_mask_update;
763 int header_size = sizeof(struct diag_ctrl_log_mask);
764 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700765 int i, size, wr_size = -ENOMEM, retry_count = 0;
766 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800767
768 for (i = 0; i < MAX_EQUIP_ID; i++) {
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700769 size = (ptr->num_items+7)/8;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800770 /* reached null entry */
771 if ((ptr->equip_id == 0) && (ptr->index == 0))
772 break;
773 driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
774 driver->log_mask->num_items = ptr->num_items;
775 driver->log_mask->data_len = 11 + size;
776 driver->log_mask->stream_id = 1; /* 2, if dual stream */
777 driver->log_mask->status = 3; /* status for valid mask */
778 driver->log_mask->equip_id = ptr->equip_id;
779 driver->log_mask->log_mask_size = size;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700780 /* send only desired update, NOT ALL */
781 if (equip_id == ALL_EQUIP_ID || equip_id ==
782 driver->log_mask->equip_id) {
783 memcpy(buf, driver->log_mask, header_size);
784 memcpy(buf+header_size, driver->log_masks+ptr->index,
785 size);
786 if (ch) {
787 while (retry_count < 3) {
788 spin_lock_irqsave(&diag_cntl_lock,
789 flags);
790 wr_size = smd_write(ch, buf,
791 header_size + size);
792 spin_unlock_irqrestore(&diag_cntl_lock,
793 flags);
794 if (wr_size == -ENOMEM) {
795 retry_count++;
796 usleep(20000);
797 } else
798 break;
799 }
800 if (wr_size != header_size + size)
801 pr_err("diag: log mask update failed"
802 " %d, tried %d", wr_size, header_size + size);
803 else
804 pr_debug("diag: updated log equip ID %d"
805 ",len %d\n", driver->log_mask->equip_id,
806 driver->log_mask->log_mask_size);
807 } else
808 pr_err("diag: ch not valid for log update\n");
809 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800810 ptr++;
811 }
812}
813
814void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
815{
816 void *buf = driver->buf_event_mask_update;
817 int header_size = sizeof(struct diag_ctrl_event_mask);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700818 int wr_size = -ENOMEM, retry_count = 0;
819 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800820
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700821 if (num_bytes == 0) {
822 pr_debug("diag: event mask not set yet, so no update\n");
823 return;
824 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800825 /* send event mask update */
826 driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
827 driver->event_mask->data_len = 7 + num_bytes;
828 driver->event_mask->stream_id = 1; /* 2, if dual stream */
829 driver->event_mask->status = 3; /* status for valid mask */
830 driver->event_mask->event_config = diag_event_config; /* event config */
831 driver->event_mask->event_mask_size = num_bytes;
832 memcpy(buf, driver->event_mask, header_size);
833 memcpy(buf+header_size, driver->event_masks, num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700834 if (ch) {
835 while (retry_count < 3) {
836 spin_lock_irqsave(&diag_cntl_lock, flags);
837 wr_size = smd_write(ch, buf, header_size + num_bytes);
838 spin_unlock_irqrestore(&diag_cntl_lock, flags);
839 if (wr_size == -ENOMEM) {
840 retry_count++;
841 usleep(20000);
842 } else
843 break;
844 }
845 if (wr_size != header_size + num_bytes)
846 pr_err("diag: error writing event mask %d, tried %d\n",
847 wr_size, header_size + num_bytes);
848 } else
849 pr_err("diag: ch not valid for event update\n");
Shalabh Jain321c8b52012-02-22 12:37:06 -0800850}
851
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700852void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
853 int updated_ssid_last, int proc)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800854{
855 void *buf = driver->buf_msg_mask_update;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700856 int first, last, size = -ENOMEM, retry_count = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800857 int header_size = sizeof(struct diag_ctrl_msg_mask);
858 uint8_t *ptr = driver->msg_masks;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700859 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800860
861 while (*(uint32_t *)(ptr + 4)) {
862 first = *(uint32_t *)ptr;
863 ptr += 4;
864 last = *(uint32_t *)ptr;
865 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700866 if ((updated_ssid_first >= first && updated_ssid_last <= last)
867 || (updated_ssid_first == ALL_SSID)) {
868 /* send f3 mask update */
869 driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
870 driver->msg_mask->msg_mask_size = last - first + 1;
871 driver->msg_mask->data_len = 11 +
872 4 * (driver->msg_mask->msg_mask_size);
873 driver->msg_mask->stream_id = 1; /* 2, if dual stream */
874 driver->msg_mask->status = 3; /* status valid mask */
875 driver->msg_mask->msg_mode = 0; /* Legcay mode */
876 driver->msg_mask->ssid_first = first;
877 driver->msg_mask->ssid_last = last;
878 memcpy(buf, driver->msg_mask, header_size);
879 memcpy(buf+header_size, ptr,
880 4 * (driver->msg_mask->msg_mask_size));
881 if (ch) {
882 while (retry_count < 3) {
883 spin_lock_irqsave(&diag_cntl_lock,
884 flags);
885 size = smd_write(ch, buf, header_size +
886 4*(driver->msg_mask->msg_mask_size));
887 spin_unlock_irqrestore(&diag_cntl_lock,
888 flags);
889 if (size == -ENOMEM) {
890 retry_count++;
891 usleep(20000);
892 } else
893 break;
894 }
895 if (size != header_size +
896 4*(driver->msg_mask->msg_mask_size))
897 pr_err("diag: msg mask update fail %d,"
898 " tried %d\n", size,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800899 header_size + 4*(driver->msg_mask->msg_mask_size));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700900 else
901 pr_debug("diag: sending mask update for"
902 " ssid first %d, last %d on PROC %d\n", first, last, proc);
903 } else
904 pr_err("diag: ch invalid msg mask update\n");
905 }
906 ptr += MAX_SSID_PER_RANGE*4;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800907 }
908}
909
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700910static int diag_process_apps_pkt(unsigned char *buf, int len)
911{
912 uint16_t subsys_cmd_code;
913 int subsys_id, ssid_first, ssid_last, ssid_range;
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700914 int packet_type = 1, i, cmd_code, rt_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700915 unsigned char *temp = buf;
916 int data_type;
917#if defined(CONFIG_DIAG_OVER_USB)
918 int payload_length;
919 unsigned char *ptr;
920#endif
921
Shalabh Jain321c8b52012-02-22 12:37:06 -0800922 /* Set log masks */
923 if (*buf == 0x73 && *(int *)(buf+4) == 3) {
924 buf += 8;
925 /* Read Equip ID and pass as first param below*/
926 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
927 diag_update_userspace_clients(LOG_MASKS_TYPE);
928#if defined(CONFIG_DIAG_OVER_USB)
929 if (chk_apps_only()) {
930 driver->apps_rsp_buf[0] = 0x73;
931 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
932 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
933 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
934 for (i = 0; i < payload_length; i++)
935 *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700936 if (driver->ch_cntl)
937 diag_send_log_mask_update(driver->ch_cntl,
938 *(int *)buf);
939 if (driver->chqdsp_cntl)
940 diag_send_log_mask_update(driver->chqdsp_cntl,
941 *(int *)buf);
942 if (driver->ch_wcnss_cntl)
943 diag_send_log_mask_update(driver->ch_wcnss_cntl,
944 *(int *)buf);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800945 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
946 return 0;
947 } else
948 buf = temp;
949#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700950 } /* Disable log masks */
951 else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
952 buf += 8;
953 /* Disable mask for each log code */
954 diag_disable_log_mask();
955 diag_update_userspace_clients(LOG_MASKS_TYPE);
956#if defined(CONFIG_DIAG_OVER_USB)
957 if (chk_apps_only()) {
958 driver->apps_rsp_buf[0] = 0x73;
959 driver->apps_rsp_buf[1] = 0x0;
960 driver->apps_rsp_buf[2] = 0x0;
961 driver->apps_rsp_buf[3] = 0x0;
962 *(int *)(driver->apps_rsp_buf + 4) = 0x0;
963 if (driver->ch_cntl)
964 diag_send_log_mask_update(driver->ch_cntl,
965 *(int *)buf);
966 if (driver->chqdsp_cntl)
967 diag_send_log_mask_update(driver->chqdsp_cntl,
968 *(int *)buf);
969 if (driver->ch_wcnss_cntl)
970 diag_send_log_mask_update(driver->ch_wcnss_cntl,
971 *(int *)buf);
972 ENCODE_RSP_AND_SEND(7);
973 return 0;
974 } else
975 buf = temp;
976#endif
977 } /* Set runtime message mask */
Shalabh Jain321c8b52012-02-22 12:37:06 -0800978 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
979 ssid_first = *(uint16_t *)(buf + 2);
980 ssid_last = *(uint16_t *)(buf + 4);
981 ssid_range = 4 * (ssid_last - ssid_first + 1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700982 pr_debug("diag: received mask update for ssid_first = %d,"
983 " ssid_last = %d", ssid_first, ssid_last);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800984 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
985 diag_update_userspace_clients(MSG_MASKS_TYPE);
986#if defined(CONFIG_DIAG_OVER_USB)
987 if (chk_apps_only()) {
988 for (i = 0; i < 8 + ssid_range; i++)
989 *(driver->apps_rsp_buf + i) = *(buf+i);
990 *(driver->apps_rsp_buf + 6) = 0x1;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700991 if (driver->ch_cntl)
992 diag_send_msg_mask_update(driver->ch_cntl,
993 ssid_first, ssid_last, MODEM_PROC);
994 if (driver->chqdsp_cntl)
995 diag_send_msg_mask_update(driver->chqdsp_cntl,
996 ssid_first, ssid_last, QDSP_PROC);
997 if (driver->ch_wcnss_cntl)
998 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
999 ssid_first, ssid_last, WCNSS_PROC);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001000 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1001 return 0;
1002 } else
1003 buf = temp;
1004#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001005 } /* Set ALL runtime message mask */
1006 else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
1007 rt_mask = *(int *)(buf + 4);
1008 diag_set_msg_mask(rt_mask);
1009 diag_update_userspace_clients(MSG_MASKS_TYPE);
1010#if defined(CONFIG_DIAG_OVER_USB)
1011 if (chk_apps_only()) {
1012 driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
1013 driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
1014 driver->apps_rsp_buf[2] = 1; /* success */
1015 driver->apps_rsp_buf[3] = 0; /* rsvd */
1016 *(int *)(driver->apps_rsp_buf + 4) = rt_mask;
1017 /* send msg mask update to peripheral */
1018 if (driver->ch_cntl)
1019 diag_send_msg_mask_update(driver->ch_cntl,
1020 ALL_SSID, ALL_SSID, MODEM_PROC);
1021 if (driver->chqdsp_cntl)
1022 diag_send_msg_mask_update(driver->chqdsp_cntl,
1023 ALL_SSID, ALL_SSID, QDSP_PROC);
1024 if (driver->ch_wcnss_cntl)
1025 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1026 ALL_SSID, ALL_SSID, WCNSS_PROC);
1027 ENCODE_RSP_AND_SEND(7);
1028 return 0;
1029 } else
1030 buf = temp;
1031#endif
Shalabh Jain321c8b52012-02-22 12:37:06 -08001032 } else if (*buf == 0x82) { /* event mask change */
1033 buf += 4;
1034 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
1035 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
1036 diag_update_userspace_clients(EVENT_MASKS_TYPE);
1037#if defined(CONFIG_DIAG_OVER_USB)
1038 if (chk_apps_only()) {
1039 driver->apps_rsp_buf[0] = 0x82;
1040 driver->apps_rsp_buf[1] = 0x0;
1041 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1042 *(uint16_t *)(driver->apps_rsp_buf + 4) =
1043 EVENT_LAST_ID + 1;
Shalabh Jaina51f2592012-03-08 14:36:35 -08001044 memcpy(driver->apps_rsp_buf+6, driver->event_masks,
1045 EVENT_LAST_ID/8+1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001046 if (driver->ch_cntl)
1047 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001048 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001049 if (driver->chqdsp_cntl)
1050 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001051 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001052 if (driver->ch_wcnss_cntl)
1053 diag_send_event_mask_update(
1054 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001055 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1056 return 0;
1057 } else
1058 buf = temp;
1059#endif
1060 } else if (*buf == 0x60) {
1061 diag_event_config = *(buf+1);
Shalabh Jaina51f2592012-03-08 14:36:35 -08001062 diag_toggle_event_mask(*(buf+1));
1063 diag_update_userspace_clients(EVENT_MASKS_TYPE);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001064#if defined(CONFIG_DIAG_OVER_USB)
1065 if (chk_apps_only()) {
1066 driver->apps_rsp_buf[0] = 0x60;
1067 driver->apps_rsp_buf[1] = 0x0;
1068 driver->apps_rsp_buf[2] = 0x0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001069 if (driver->ch_cntl)
1070 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001071 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001072 if (driver->chqdsp_cntl)
1073 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001074 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001075 if (driver->ch_wcnss_cntl)
1076 diag_send_event_mask_update(
1077 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001078 ENCODE_RSP_AND_SEND(2);
1079 return 0;
1080 }
1081#endif
1082 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001083 /* Check for registered clients and forward packet to apropriate proc */
1084 cmd_code = (int)(*(char *)buf);
1085 temp++;
1086 subsys_id = (int)(*(char *)temp);
1087 temp++;
1088 subsys_cmd_code = *(uint16_t *)temp;
1089 temp += 2;
1090 data_type = APPS_DATA;
1091 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301092 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001093 if (subsys_id != RESET_ID)
1094 data_type = MODEM_DATA;
1095 }
1096
1097 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001098 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001099 entry = driver->table[i];
1100 if (entry.process_id != NO_PROCESS) {
1101 if (entry.cmd_code == cmd_code && entry.subsys_id ==
1102 subsys_id && entry.cmd_code_lo <=
1103 subsys_cmd_code &&
1104 entry.cmd_code_hi >= subsys_cmd_code) {
1105 diag_send_data(entry, buf, len, data_type);
1106 packet_type = 0;
1107 } else if (entry.cmd_code == 255
1108 && cmd_code == 75) {
1109 if (entry.subsys_id ==
1110 subsys_id &&
1111 entry.cmd_code_lo <=
1112 subsys_cmd_code &&
1113 entry.cmd_code_hi >=
1114 subsys_cmd_code) {
1115 diag_send_data(entry, buf, len,
1116 data_type);
1117 packet_type = 0;
1118 }
1119 } else if (entry.cmd_code == 255 &&
1120 entry.subsys_id == 255) {
1121 if (entry.cmd_code_lo <=
1122 cmd_code &&
1123 entry.
1124 cmd_code_hi >= cmd_code) {
1125 diag_send_data(entry, buf, len,
1126 data_type);
1127 packet_type = 0;
1128 }
1129 }
1130 }
1131 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001132#if defined(CONFIG_DIAG_OVER_USB)
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001133 /* Check for Apps Only & get event mask request */
Shalabh Jain321c8b52012-02-22 12:37:06 -08001134 if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001135 driver->apps_rsp_buf[0] = 0x81;
1136 driver->apps_rsp_buf[1] = 0x0;
1137 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1138 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
1139 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
1140 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
1141 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1142 return 0;
1143 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001144 /* Get log ID range & Check for Apps Only */
1145 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001146 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
1147 driver->apps_rsp_buf[0] = 0x73;
1148 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
1149 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
1150 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
1151 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
1152 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
1153 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
1154 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
1155 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
1156 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
1157 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
1158 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
1159 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
1160 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
1161 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
1162 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
1163 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
1164 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
1165 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
1166 ENCODE_RSP_AND_SEND(75);
1167 return 0;
1168 }
1169 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001170 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001171 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
1172 driver->apps_rsp_buf[0] = 0x7d;
1173 driver->apps_rsp_buf[1] = 0x1;
1174 driver->apps_rsp_buf[2] = 0x1;
1175 driver->apps_rsp_buf[3] = 0x0;
1176 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
1177 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
1178 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
1179 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
1180 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
1181 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
1182 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
1183 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
1184 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
1185 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
1186 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
1187 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
1188 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
1189 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
1190 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
1191 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
1192 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
1193 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
1194 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
1195 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
1196 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
1197 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
1198 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
1199 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
1200 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
1201 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
1202 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
1203 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
1204 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
1205 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
1206 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
1207 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
1208 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
1209 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
1210 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
1211 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
1212 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
1213 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
1214 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001215 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
1216 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
1217 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
1218 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
1219 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
1220 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
1221 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
1222 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
1223 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001224 return 0;
1225 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001226 /* Check for Apps Only Respond to Get Subsys Build mask */
1227 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001228 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
1229 ssid_first = *(uint16_t *)(buf + 2);
1230 ssid_last = *(uint16_t *)(buf + 4);
1231 ssid_range = 4 * (ssid_last - ssid_first + 1);
1232 /* frame response */
1233 driver->apps_rsp_buf[0] = 0x7d;
1234 driver->apps_rsp_buf[1] = 0x2;
1235 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
1236 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
1237 driver->apps_rsp_buf[6] = 0x1;
1238 driver->apps_rsp_buf[7] = 0x0;
1239 ptr = driver->apps_rsp_buf + 8;
1240 /* bld time masks */
1241 switch (ssid_first) {
1242 case MSG_SSID_0:
1243 for (i = 0; i < ssid_range; i += 4)
1244 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
1245 break;
1246 case MSG_SSID_1:
1247 for (i = 0; i < ssid_range; i += 4)
1248 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
1249 break;
1250 case MSG_SSID_2:
1251 for (i = 0; i < ssid_range; i += 4)
1252 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
1253 break;
1254 case MSG_SSID_3:
1255 for (i = 0; i < ssid_range; i += 4)
1256 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
1257 break;
1258 case MSG_SSID_4:
1259 for (i = 0; i < ssid_range; i += 4)
1260 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
1261 break;
1262 case MSG_SSID_5:
1263 for (i = 0; i < ssid_range; i += 4)
1264 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
1265 break;
1266 case MSG_SSID_6:
1267 for (i = 0; i < ssid_range; i += 4)
1268 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
1269 break;
1270 case MSG_SSID_7:
1271 for (i = 0; i < ssid_range; i += 4)
1272 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
1273 break;
1274 case MSG_SSID_8:
1275 for (i = 0; i < ssid_range; i += 4)
1276 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
1277 break;
1278 case MSG_SSID_9:
1279 for (i = 0; i < ssid_range; i += 4)
1280 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
1281 break;
1282 case MSG_SSID_10:
1283 for (i = 0; i < ssid_range; i += 4)
1284 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
1285 break;
1286 case MSG_SSID_11:
1287 for (i = 0; i < ssid_range; i += 4)
1288 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
1289 break;
1290 case MSG_SSID_12:
1291 for (i = 0; i < ssid_range; i += 4)
1292 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1293 break;
1294 case MSG_SSID_13:
1295 for (i = 0; i < ssid_range; i += 4)
1296 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1297 break;
1298 case MSG_SSID_14:
1299 for (i = 0; i < ssid_range; i += 4)
1300 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1301 break;
1302 case MSG_SSID_15:
1303 for (i = 0; i < ssid_range; i += 4)
1304 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1305 break;
1306 case MSG_SSID_16:
1307 for (i = 0; i < ssid_range; i += 4)
1308 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1309 break;
1310 case MSG_SSID_17:
1311 for (i = 0; i < ssid_range; i += 4)
1312 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1313 break;
1314 case MSG_SSID_18:
1315 for (i = 0; i < ssid_range; i += 4)
1316 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1317 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001318 case MSG_SSID_19:
1319 for (i = 0; i < ssid_range; i += 4)
1320 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1321 break;
1322 case MSG_SSID_20:
1323 for (i = 0; i < ssid_range; i += 4)
1324 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1325 break;
1326 case MSG_SSID_21:
1327 for (i = 0; i < ssid_range; i += 4)
1328 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1329 break;
1330 case MSG_SSID_22:
1331 for (i = 0; i < ssid_range; i += 4)
1332 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1333 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001334 }
1335 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1336 return 0;
1337 }
1338 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301339 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001340 /* send response back */
1341 driver->apps_rsp_buf[0] = *buf;
1342 ENCODE_RSP_AND_SEND(0);
1343 msleep(5000);
1344 /* call download API */
1345 msm_set_restart_mode(RESTART_DLOAD);
1346 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1347 kernel_restart(NULL);
1348 /* Not required, represents that command isnt sent to modem */
1349 return 0;
1350 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001351 /* Check for polling for Apps only DIAG */
1352 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1353 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001354 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001355 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001356 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001357 for (i = 0; i < 3; i++)
1358 driver->apps_rsp_buf[i] = *(buf+i);
1359 for (i = 0; i < 13; i++)
1360 driver->apps_rsp_buf[i+3] = 0;
1361
1362 ENCODE_RSP_AND_SEND(15);
1363 return 0;
1364 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001365 }
1366 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001367 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001368 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001369 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001370 for (i = 0; i < 55; i++)
1371 driver->apps_rsp_buf[i] = 0;
1372
1373 ENCODE_RSP_AND_SEND(54);
1374 return 0;
1375 }
1376 /* respond to 0x7c command */
1377 else if (*buf == 0x7c) {
1378 driver->apps_rsp_buf[0] = 0x7c;
1379 for (i = 1; i < 8; i++)
1380 driver->apps_rsp_buf[i] = 0;
1381 /* Tools ID for APQ 8060 */
1382 *(int *)(driver->apps_rsp_buf + 8) =
1383 chk_config_get_id();
1384 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1385 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1386 ENCODE_RSP_AND_SEND(13);
1387 return 0;
1388 }
1389 }
1390#endif
1391 return packet_type;
1392}
1393
1394#ifdef CONFIG_DIAG_OVER_USB
1395void diag_send_error_rsp(int index)
1396{
1397 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301398
1399 if (index > 490) {
1400 pr_err("diag: error response too huge, aborting\n");
1401 return;
1402 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001403 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1404 for (i = 0; i < index; i++)
1405 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1406 ENCODE_RSP_AND_SEND(index - 3);
1407}
1408#else
1409static inline void diag_send_error_rsp(int index) {}
1410#endif
1411
1412void diag_process_hdlc(void *data, unsigned len)
1413{
1414 struct diag_hdlc_decode_type hdlc;
1415 int ret, type = 0;
1416 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1417 hdlc.dest_ptr = driver->hdlc_buf;
1418 hdlc.dest_size = USB_MAX_OUT_BUF;
1419 hdlc.src_ptr = data;
1420 hdlc.src_size = len;
1421 hdlc.src_idx = 0;
1422 hdlc.dest_idx = 0;
1423 hdlc.escaping = 0;
1424
1425 ret = diag_hdlc_decode(&hdlc);
1426
1427 if (ret)
1428 type = diag_process_apps_pkt(driver->hdlc_buf,
1429 hdlc.dest_idx - 3);
1430 else if (driver->debug_flag) {
1431 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1432 " errors or partial packet received, packet"
1433 " length = %d\n", len);
1434 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1435 DUMP_PREFIX_ADDRESS, data, len, 1);
1436 driver->debug_flag = 0;
1437 }
1438 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001439 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001440 diag_send_error_rsp(hdlc.dest_idx);
1441 type = 0;
1442 }
1443 /* implies this packet is NOT meant for apps */
1444 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001445 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001446 diag_send_error_rsp(hdlc.dest_idx);
1447 } else { /* APQ 8060, Let Q6 respond */
1448 if (driver->chqdsp)
1449 smd_write(driver->chqdsp, driver->hdlc_buf,
1450 hdlc.dest_idx - 3);
1451 }
1452 type = 0;
1453 }
1454
1455#ifdef DIAG_DEBUG
1456 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1457 for (i = 0; i < hdlc.dest_idx; i++)
1458 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1459 driver->hdlc_buf)+i));
1460#endif /* DIAG DEBUG */
1461 /* ignore 2 bytes for CRC, one for 7E and send */
1462 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1463 APPEND_DEBUG('g');
1464 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1465 APPEND_DEBUG('h');
1466#ifdef DIAG_DEBUG
1467 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1468 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1469 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1470#endif /* DIAG DEBUG */
1471 }
1472}
1473
1474#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001475/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1476#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001477#define N_LEGACY_READ 1
1478
1479int diagfwd_connect(void)
1480{
1481 int err;
1482
1483 printk(KERN_DEBUG "diag: USB connected\n");
1484 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1485 N_LEGACY_READ);
1486 if (err)
1487 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1488
1489 driver->usb_connected = 1;
1490 driver->in_busy_1 = 0;
1491 driver->in_busy_2 = 0;
1492 driver->in_busy_qdsp_1 = 0;
1493 driver->in_busy_qdsp_2 = 0;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301494 driver->in_busy_wcnss_1 = 0;
1495 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001496
1497 /* Poll SMD channels to check for data*/
1498 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1499 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1500 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001501 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001502 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1503 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1504 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001505 /* Poll USB channel to check for data*/
1506 queue_work(driver->diag_wq, &(driver->diag_read_work));
1507#ifdef CONFIG_DIAG_SDIO_PIPE
1508 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1509 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1510 diagfwd_connect_sdio();
1511 else
1512 printk(KERN_INFO "diag: No USB MDM ch");
1513 }
1514#endif
1515 return 0;
1516}
1517
1518int diagfwd_disconnect(void)
1519{
1520 printk(KERN_DEBUG "diag: USB disconnected\n");
1521 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001522 driver->debug_flag = 1;
1523 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001524 if (driver->logging_mode == USB_MODE) {
1525 driver->in_busy_1 = 1;
1526 driver->in_busy_2 = 1;
1527 driver->in_busy_qdsp_1 = 1;
1528 driver->in_busy_qdsp_2 = 1;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301529 driver->in_busy_wcnss_1 = 1;
1530 driver->in_busy_wcnss_2 = 1;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001531 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001532#ifdef CONFIG_DIAG_SDIO_PIPE
1533 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1534 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1535 diagfwd_disconnect_sdio();
1536#endif
1537 /* TBD - notify and flow control SMD */
1538 return 0;
1539}
1540
1541int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1542{
1543 unsigned char *buf = diag_write_ptr->buf;
1544 /*Determine if the write complete is for data from modem/apps/q6 */
1545 /* Need a context variable here instead */
1546 if (buf == (void *)driver->buf_in_1) {
1547 driver->in_busy_1 = 0;
1548 APPEND_DEBUG('o');
1549 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1550 } else if (buf == (void *)driver->buf_in_2) {
1551 driver->in_busy_2 = 0;
1552 APPEND_DEBUG('O');
1553 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1554 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1555 driver->in_busy_qdsp_1 = 0;
1556 APPEND_DEBUG('p');
1557 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1558 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1559 driver->in_busy_qdsp_2 = 0;
1560 APPEND_DEBUG('P');
1561 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
Ashay Jaiswal29620122012-03-21 12:02:36 +05301562 } else if (buf == driver->buf_in_wcnss_1) {
1563 driver->in_busy_wcnss_1 = 0;
1564 APPEND_DEBUG('r');
1565 queue_work(driver->diag_wq,
1566 &(driver->diag_read_smd_wcnss_work));
1567 } else if (buf == driver->buf_in_wcnss_2) {
1568 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001569 APPEND_DEBUG('R');
1570 queue_work(driver->diag_wq,
1571 &(driver->diag_read_smd_wcnss_work));
1572 }
1573#ifdef CONFIG_DIAG_SDIO_PIPE
1574 else if (buf == (void *)driver->buf_in_sdio)
1575 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001576 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001577 diagfwd_write_complete_sdio();
1578 else
1579 pr_err("diag: Incorrect buffer pointer while WRITE");
1580#endif
1581 else {
1582 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1583 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1584 POOL_TYPE_WRITE_STRUCT);
1585 APPEND_DEBUG('q');
1586 }
1587 return 0;
1588}
1589
1590int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1591{
1592 int status = diag_read_ptr->status;
1593 unsigned char *buf = diag_read_ptr->buf;
1594
1595 /* Determine if the read complete is for data on legacy/mdm ch */
1596 if (buf == (void *)driver->usb_buf_out) {
1597 driver->read_len_legacy = diag_read_ptr->actual;
1598 APPEND_DEBUG('s');
1599#ifdef DIAG_DEBUG
1600 printk(KERN_INFO "read data from USB, pkt length %d",
1601 diag_read_ptr->actual);
1602 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1603 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1604 diag_read_ptr->actual, 1);
1605#endif /* DIAG DEBUG */
1606 if (driver->logging_mode == USB_MODE) {
1607 if (status != -ECONNRESET && status != -ESHUTDOWN)
1608 queue_work(driver->diag_wq,
1609 &(driver->diag_proc_hdlc_work));
1610 else
1611 queue_work(driver->diag_wq,
1612 &(driver->diag_read_work));
1613 }
1614 }
1615#ifdef CONFIG_DIAG_SDIO_PIPE
1616 else if (buf == (void *)driver->usb_buf_mdm_out) {
1617 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001618 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001619 driver->read_len_mdm = diag_read_ptr->actual;
1620 diagfwd_read_complete_sdio();
1621 } else
1622 pr_err("diag: Incorrect buffer pointer while READ");
1623 }
1624#endif
1625 else
1626 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1627
1628 return 0;
1629}
1630
1631void diag_read_work_fn(struct work_struct *work)
1632{
1633 APPEND_DEBUG('d');
1634 driver->usb_read_ptr->buf = driver->usb_buf_out;
1635 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1636 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1637 APPEND_DEBUG('e');
1638}
1639
1640void diag_process_hdlc_fn(struct work_struct *work)
1641{
1642 APPEND_DEBUG('D');
1643 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1644 diag_read_work_fn(work);
1645 APPEND_DEBUG('E');
1646}
1647
1648void diag_usb_legacy_notifier(void *priv, unsigned event,
1649 struct diag_request *d_req)
1650{
1651 switch (event) {
1652 case USB_DIAG_CONNECT:
1653 diagfwd_connect();
1654 break;
1655 case USB_DIAG_DISCONNECT:
1656 diagfwd_disconnect();
1657 break;
1658 case USB_DIAG_READ_DONE:
1659 diagfwd_read_complete(d_req);
1660 break;
1661 case USB_DIAG_WRITE_DONE:
1662 diagfwd_write_complete(d_req);
1663 break;
1664 default:
1665 printk(KERN_ERR "Unknown event from USB diag\n");
1666 break;
1667 }
1668}
1669
1670#endif /* DIAG OVER USB */
1671
1672static void diag_smd_notify(void *ctxt, unsigned event)
1673{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001674 if (event == SMD_EVENT_CLOSE) {
1675 pr_info("diag: clean modem registration\n");
1676 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001677 driver->ch = 0;
1678 return;
1679 } else if (event == SMD_EVENT_OPEN) {
1680 driver->ch = ch_temp;
1681 }
1682 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001683}
1684
1685#if defined(CONFIG_MSM_N_WAY_SMD)
1686static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1687{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001688 if (event == SMD_EVENT_CLOSE) {
1689 pr_info("diag: clean lpass registration\n");
1690 diag_clear_reg(QDSP_PROC);
1691 driver->chqdsp = 0;
1692 return;
1693 } else if (event == SMD_EVENT_OPEN) {
1694 driver->chqdsp = chqdsp_temp;
1695 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001696 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1697}
1698#endif
1699
1700static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1701{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001702 if (event == SMD_EVENT_CLOSE) {
1703 pr_info("diag: clean wcnss registration\n");
1704 diag_clear_reg(WCNSS_PROC);
1705 driver->ch_wcnss = 0;
1706 return;
1707 } else if (event == SMD_EVENT_OPEN) {
1708 driver->ch_wcnss = ch_wcnss_temp;
1709 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001710 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1711}
1712
1713static int diag_smd_probe(struct platform_device *pdev)
1714{
1715 int r = 0;
1716
Shalabh Jaineefee052011-11-08 23:46:03 -08001717 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001718 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001719 ch_temp = driver->ch;
1720 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001721#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001722 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001723 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1724 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001725 chqdsp_temp = driver->chqdsp;
1726 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001727#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001728 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001729 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1730 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001731 ch_wcnss_temp = driver->ch_wcnss;
1732 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001733 pm_runtime_set_active(&pdev->dev);
1734 pm_runtime_enable(&pdev->dev);
1735 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1736
1737 return 0;
1738}
1739
1740static int diagfwd_runtime_suspend(struct device *dev)
1741{
1742 dev_dbg(dev, "pm_runtime: suspending...\n");
1743 return 0;
1744}
1745
1746static int diagfwd_runtime_resume(struct device *dev)
1747{
1748 dev_dbg(dev, "pm_runtime: resuming...\n");
1749 return 0;
1750}
1751
1752static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1753 .runtime_suspend = diagfwd_runtime_suspend,
1754 .runtime_resume = diagfwd_runtime_resume,
1755};
1756
1757static struct platform_driver msm_smd_ch1_driver = {
1758
1759 .probe = diag_smd_probe,
1760 .driver = {
1761 .name = "DIAG",
1762 .owner = THIS_MODULE,
1763 .pm = &diagfwd_dev_pm_ops,
1764 },
1765};
1766
1767static struct platform_driver diag_smd_lite_driver = {
1768
1769 .probe = diag_smd_probe,
1770 .driver = {
1771 .name = "APPS_RIVA_DATA",
1772 .owner = THIS_MODULE,
1773 .pm = &diagfwd_dev_pm_ops,
1774 },
1775};
1776
1777void diagfwd_init(void)
1778{
1779 diag_debug_buf_idx = 0;
1780 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001781 driver->use_device_tree = has_device_tree();
Shalabh Jainb6eda0e2012-04-18 16:39:52 -07001782 spin_lock_init(&diag_cntl_lock);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001783
1784 if (driver->event_mask == NULL) {
1785 driver->event_mask = kzalloc(sizeof(
1786 struct diag_ctrl_event_mask), GFP_KERNEL);
1787 if (driver->event_mask == NULL)
1788 goto err;
1789 }
1790 if (driver->msg_mask == NULL) {
1791 driver->msg_mask = kzalloc(sizeof(
1792 struct diag_ctrl_msg_mask), GFP_KERNEL);
1793 if (driver->msg_mask == NULL)
1794 goto err;
1795 }
1796 if (driver->log_mask == NULL) {
1797 driver->log_mask = kzalloc(sizeof(
1798 struct diag_ctrl_log_mask), GFP_KERNEL);
1799 if (driver->log_mask == NULL)
1800 goto err;
1801 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001802 if (driver->buf_in_1 == NULL) {
1803 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1804 if (driver->buf_in_1 == NULL)
1805 goto err;
1806 }
1807 if (driver->buf_in_2 == NULL) {
1808 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1809 if (driver->buf_in_2 == NULL)
1810 goto err;
1811 }
1812 if (driver->buf_in_qdsp_1 == NULL) {
1813 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1814 if (driver->buf_in_qdsp_1 == NULL)
1815 goto err;
1816 }
1817 if (driver->buf_in_qdsp_2 == NULL) {
1818 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1819 if (driver->buf_in_qdsp_2 == NULL)
1820 goto err;
1821 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301822 if (driver->buf_in_wcnss_1 == NULL) {
1823 driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1824 if (driver->buf_in_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001825 goto err;
1826 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301827 if (driver->buf_in_wcnss_2 == NULL) {
1828 driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1829 if (driver->buf_in_wcnss_2 == NULL)
1830 goto err;
1831 }
1832
Shalabh Jain321c8b52012-02-22 12:37:06 -08001833 if (driver->buf_msg_mask_update == NULL) {
1834 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1835 GFP_KERNEL);
1836 if (driver->buf_msg_mask_update == NULL)
1837 goto err;
1838 }
1839 if (driver->buf_log_mask_update == NULL) {
1840 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1841 GFP_KERNEL);
1842 if (driver->buf_log_mask_update == NULL)
1843 goto err;
1844 }
1845 if (driver->buf_event_mask_update == NULL) {
1846 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1847 GFP_KERNEL);
1848 if (driver->buf_event_mask_update == NULL)
1849 goto err;
1850 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001851 if (driver->usb_buf_out == NULL &&
1852 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1853 GFP_KERNEL)) == NULL)
1854 goto err;
1855 if (driver->hdlc_buf == NULL
1856 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1857 goto err;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001858 if (driver->user_space_data == NULL)
1859 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1860 if (driver->user_space_data == NULL)
1861 goto err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001862 if (driver->msg_masks == NULL
1863 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1864 GFP_KERNEL)) == NULL)
1865 goto err;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001866 diag_create_msg_mask_table();
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001867 diag_event_num_bytes = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001868 if (driver->log_masks == NULL &&
1869 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1870 goto err;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -07001871 driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001872 if (driver->event_masks == NULL &&
1873 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1874 GFP_KERNEL)) == NULL)
1875 goto err;
1876 if (driver->client_map == NULL &&
1877 (driver->client_map = kzalloc
1878 ((driver->num_clients) * sizeof(struct diag_client_map),
1879 GFP_KERNEL)) == NULL)
1880 goto err;
1881 if (driver->buf_tbl == NULL)
1882 driver->buf_tbl = kzalloc(buf_tbl_size *
1883 sizeof(struct diag_write_device), GFP_KERNEL);
1884 if (driver->buf_tbl == NULL)
1885 goto err;
1886 if (driver->data_ready == NULL &&
1887 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1888 , GFP_KERNEL)) == NULL)
1889 goto err;
1890 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001891 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001892 sizeof(struct diag_master_table),
1893 GFP_KERNEL)) == NULL)
1894 goto err;
1895 if (driver->write_ptr_1 == NULL) {
1896 driver->write_ptr_1 = kzalloc(
1897 sizeof(struct diag_request), GFP_KERNEL);
1898 if (driver->write_ptr_1 == NULL)
1899 goto err;
1900 }
1901 if (driver->write_ptr_2 == NULL) {
1902 driver->write_ptr_2 = kzalloc(
1903 sizeof(struct diag_request), GFP_KERNEL);
1904 if (driver->write_ptr_2 == NULL)
1905 goto err;
1906 }
1907 if (driver->write_ptr_qdsp_1 == NULL) {
1908 driver->write_ptr_qdsp_1 = kzalloc(
1909 sizeof(struct diag_request), GFP_KERNEL);
1910 if (driver->write_ptr_qdsp_1 == NULL)
1911 goto err;
1912 }
1913 if (driver->write_ptr_qdsp_2 == NULL) {
1914 driver->write_ptr_qdsp_2 = kzalloc(
1915 sizeof(struct diag_request), GFP_KERNEL);
1916 if (driver->write_ptr_qdsp_2 == NULL)
1917 goto err;
1918 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301919 if (driver->write_ptr_wcnss_1 == NULL) {
1920 driver->write_ptr_wcnss_1 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001921 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301922 if (driver->write_ptr_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001923 goto err;
1924 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301925 if (driver->write_ptr_wcnss_2 == NULL) {
1926 driver->write_ptr_wcnss_2 = kzalloc(
1927 sizeof(struct diag_request), GFP_KERNEL);
1928 if (driver->write_ptr_wcnss_2 == NULL)
1929 goto err;
1930 }
1931
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001932 if (driver->usb_read_ptr == NULL) {
1933 driver->usb_read_ptr = kzalloc(
1934 sizeof(struct diag_request), GFP_KERNEL);
1935 if (driver->usb_read_ptr == NULL)
1936 goto err;
1937 }
1938 if (driver->pkt_buf == NULL &&
1939 (driver->pkt_buf = kzalloc(PKT_SIZE,
1940 GFP_KERNEL)) == NULL)
1941 goto err;
1942 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001943 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001944 if (driver->apps_rsp_buf == NULL)
1945 goto err;
1946 }
1947 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1948#ifdef CONFIG_DIAG_OVER_USB
1949 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1950 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001951 INIT_WORK(&(driver->diag_modem_mask_update_work),
1952 diag_modem_mask_update_fn);
1953 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
1954 diag_qdsp_mask_update_fn);
1955 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
1956 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001957 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
1958 diag_usb_legacy_notifier);
1959 if (IS_ERR(driver->legacy_ch)) {
1960 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
1961 goto err;
1962 }
1963#endif
1964 platform_driver_register(&msm_smd_ch1_driver);
1965 platform_driver_register(&diag_smd_lite_driver);
1966
1967 return;
1968err:
1969 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08001970 kfree(driver->event_mask);
1971 kfree(driver->log_mask);
1972 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001973 kfree(driver->buf_in_1);
1974 kfree(driver->buf_in_2);
1975 kfree(driver->buf_in_qdsp_1);
1976 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301977 kfree(driver->buf_in_wcnss_1);
1978 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001979 kfree(driver->buf_msg_mask_update);
1980 kfree(driver->buf_log_mask_update);
1981 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001982 kfree(driver->usb_buf_out);
1983 kfree(driver->hdlc_buf);
1984 kfree(driver->msg_masks);
1985 kfree(driver->log_masks);
1986 kfree(driver->event_masks);
1987 kfree(driver->client_map);
1988 kfree(driver->buf_tbl);
1989 kfree(driver->data_ready);
1990 kfree(driver->table);
1991 kfree(driver->pkt_buf);
1992 kfree(driver->write_ptr_1);
1993 kfree(driver->write_ptr_2);
1994 kfree(driver->write_ptr_qdsp_1);
1995 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301996 kfree(driver->write_ptr_wcnss_1);
1997 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001998 kfree(driver->usb_read_ptr);
1999 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002000 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002001 if (driver->diag_wq)
2002 destroy_workqueue(driver->diag_wq);
2003}
2004
2005void diagfwd_exit(void)
2006{
2007 smd_close(driver->ch);
2008 smd_close(driver->chqdsp);
2009 smd_close(driver->ch_wcnss);
2010 driver->ch = 0; /* SMD can make this NULL */
2011 driver->chqdsp = 0;
2012 driver->ch_wcnss = 0;
2013#ifdef CONFIG_DIAG_OVER_USB
2014 if (driver->usb_connected)
2015 usb_diag_free_req(driver->legacy_ch);
2016 usb_diag_close(driver->legacy_ch);
2017#endif
2018 platform_driver_unregister(&msm_smd_ch1_driver);
2019 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002020 kfree(driver->event_mask);
2021 kfree(driver->log_mask);
2022 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002023 kfree(driver->buf_in_1);
2024 kfree(driver->buf_in_2);
2025 kfree(driver->buf_in_qdsp_1);
2026 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302027 kfree(driver->buf_in_wcnss_1);
2028 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002029 kfree(driver->buf_msg_mask_update);
2030 kfree(driver->buf_log_mask_update);
2031 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002032 kfree(driver->usb_buf_out);
2033 kfree(driver->hdlc_buf);
2034 kfree(driver->msg_masks);
2035 kfree(driver->log_masks);
2036 kfree(driver->event_masks);
2037 kfree(driver->client_map);
2038 kfree(driver->buf_tbl);
2039 kfree(driver->data_ready);
2040 kfree(driver->table);
2041 kfree(driver->pkt_buf);
2042 kfree(driver->write_ptr_1);
2043 kfree(driver->write_ptr_2);
2044 kfree(driver->write_ptr_qdsp_1);
2045 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302046 kfree(driver->write_ptr_wcnss_1);
2047 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002048 kfree(driver->usb_read_ptr);
2049 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002050 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002051 destroy_workqueue(driver->diag_wq);
2052}