blob: 7066141f2c8961a76467e4080a808ac52d22fdd7 [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 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 -070062spinlock_t diag_cntl_lock;
63
64#define CREATE_MSG_MASK_TBL_ROW(XX) \
65do { \
66 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX; \
67 msg_mask_tbl_ptr += 4; \
68 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
69 msg_mask_tbl_ptr += 4; \
70 /* increment by MAX_SSID_PER_RANGE cells */ \
71 msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int); \
72} while (0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070073
74#define ENCODE_RSP_AND_SEND(buf_length) \
75do { \
76 send.state = DIAG_STATE_START; \
77 send.pkt = driver->apps_rsp_buf; \
78 send.last = (void *)(driver->apps_rsp_buf + buf_length); \
79 send.terminate = 1; \
80 if (!driver->in_busy_1) { \
81 enc.dest = driver->buf_in_1; \
Shalabh Jain321c8b52012-02-22 12:37:06 -080082 enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);\
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070083 diag_hdlc_encode(&send, &enc); \
84 driver->write_ptr_1->buf = driver->buf_in_1; \
85 driver->write_ptr_1->length = (int)(enc.dest - \
86 (void *)(driver->buf_in_1)); \
Shalabh Jain3893bf92011-09-18 18:37:16 -070087 driver->in_busy_1 = 1; \
Shalabh Jain69890aa2011-10-10 12:59:16 -070088 diag_device_write(driver->buf_in_1, MODEM_DATA, \
89 driver->write_ptr_1); \
Shalabh Jain321c8b52012-02-22 12:37:06 -080090 memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE); \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070091 } \
92} while (0)
93
94#define CHK_OVERFLOW(bufStart, start, end, length) \
95((bufStart <= start) && (end - start >= length)) ? 1 : 0
96
Dixon Petersonb4618a42012-02-29 18:56:31 -080097/* Determine if this device uses a device tree */
98#ifdef CONFIG_OF
99static int has_device_tree(void)
100{
101 struct device_node *node;
102
103 node = of_find_node_by_path("/");
104 if (node) {
105 of_node_put(node);
106 return 1;
107 }
108 return 0;
109}
110#else
111static int has_device_tree(void)
112{
113 return 0;
114}
115#endif
116
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700117int chk_config_get_id(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700118{
Shalabh Jain482bf122011-12-06 03:54:47 -0800119 /* For all Fusion targets, Modem will always be present */
120 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
121 return 0;
122
Dixon Petersonb4618a42012-02-29 18:56:31 -0800123 if (driver->use_device_tree) {
124 if (machine_is_copper())
125 return MSM8974_TOOLS_ID;
126 else
127 return 0;
128 } else {
129 switch (socinfo_get_msm_cpu()) {
130 case MSM_CPU_8X60:
131 return APQ8060_TOOLS_ID;
132 case MSM_CPU_8960:
133 return AO8960_TOOLS_ID;
134 case MSM_CPU_8064:
135 return APQ8064_TOOLS_ID;
136 case MSM_CPU_8930:
137 return MSM8930_TOOLS_ID;
138 case MSM_CPU_COPPER:
139 return MSM8974_TOOLS_ID;
140 case MSM_CPU_8625:
141 return MSM8625_TOOLS_ID;
142 default:
143 return 0;
144 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700145 }
146}
147
148/*
Shalabh Jain321c8b52012-02-22 12:37:06 -0800149 * This will return TRUE for targets which support apps only mode and hence SSR.
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700150 * This applies to 8960 and newer targets.
151 */
152int chk_apps_only(void)
153{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800154 if (driver->use_device_tree)
155 return 1;
156
157 switch (socinfo_get_msm_cpu()) {
158 case MSM_CPU_8960:
159 case MSM_CPU_8064:
160 case MSM_CPU_8930:
161 case MSM_CPU_8627:
162 case MSM_CPU_9615:
163 case MSM_CPU_COPPER:
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700164 return 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165 default:
166 return 0;
167 }
168}
169
Shalabh Jain10f5f432012-01-11 11:45:44 +0530170/*
171 * This will return TRUE for targets which support apps as master.
172 * Thus, SW DLOAD and Mode Reset are supported on apps processor.
173 * This applies to 8960 and newer targets.
174 */
175int chk_apps_master(void)
176{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800177 if (driver->use_device_tree)
178 return 1;
179 else if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615() ||
180 cpu_is_apq8064() || cpu_is_msm8627())
181 return 1;
182 else
183 return 0;
184}
185
186inline int chk_polling_response(void)
187{
188 if (!(driver->polling_reg_flag) && chk_apps_master())
189 /*
190 * If the apps processor is master and no other processor
191 * has registered to respond for polling
192 */
193 return 1;
194 else if (!(driver->ch) && !(chk_apps_master()))
195 /*
196 * If the apps processor is not the master and the modem
197 * is not up
198 */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530199 return 1;
200 else
201 return 0;
202}
203
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204void __diag_smd_send_req(void)
205{
206 void *buf = NULL;
207 int *in_busy_ptr = NULL;
208 struct diag_request *write_ptr_modem = NULL;
209
210 if (!driver->in_busy_1) {
211 buf = driver->buf_in_1;
212 write_ptr_modem = driver->write_ptr_1;
213 in_busy_ptr = &(driver->in_busy_1);
214 } else if (!driver->in_busy_2) {
215 buf = driver->buf_in_2;
216 write_ptr_modem = driver->write_ptr_2;
217 in_busy_ptr = &(driver->in_busy_2);
218 }
219
220 if (driver->ch && buf) {
221 int r = smd_read_avail(driver->ch);
222
223 if (r > IN_BUF_SIZE) {
224 if (r < MAX_IN_BUF_SIZE) {
225 pr_err("diag: SMD sending in "
226 "packets upto %d bytes", r);
227 buf = krealloc(buf, r, GFP_KERNEL);
228 } else {
229 pr_err("diag: SMD sending in "
230 "packets more than %d bytes", MAX_IN_BUF_SIZE);
231 return;
232 }
233 }
234 if (r > 0) {
235 if (!buf)
236 pr_info("Out of diagmem for Modem\n");
237 else {
238 APPEND_DEBUG('i');
239 smd_read(driver->ch, buf, r);
240 APPEND_DEBUG('j');
241 write_ptr_modem->length = r;
242 *in_busy_ptr = 1;
243 diag_device_write(buf, MODEM_DATA,
244 write_ptr_modem);
245 }
246 }
247 }
248}
249
250int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr)
251{
252 int i, err = 0;
253
254 if (driver->logging_mode == MEMORY_DEVICE_MODE) {
255 if (proc_num == APPS_DATA) {
256 for (i = 0; i < driver->poolsize_write_struct; i++)
257 if (driver->buf_tbl[i].length == 0) {
258 driver->buf_tbl[i].buf = buf;
259 driver->buf_tbl[i].length =
260 driver->used;
261#ifdef DIAG_DEBUG
262 pr_debug("diag: ENQUEUE buf ptr"
263 " and length is %x , %d\n",
264 (unsigned int)(driver->buf_
265 tbl[i].buf), driver->buf_tbl[i].length);
266#endif
267 break;
268 }
269 }
270 for (i = 0; i < driver->num_clients; i++)
271 if (driver->client_map[i].pid ==
272 driver->logging_process_id)
273 break;
274 if (i < driver->num_clients) {
Shalabh Jain69890aa2011-10-10 12:59:16 -0700275 driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
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
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700303 err = -1;
304 }
305#ifdef CONFIG_DIAG_OVER_USB
306 else if (driver->logging_mode == USB_MODE) {
307 if (proc_num == APPS_DATA) {
308 driver->write_ptr_svc = (struct diag_request *)
309 (diagmem_alloc(driver, sizeof(struct diag_request),
310 POOL_TYPE_WRITE_STRUCT));
311 if (driver->write_ptr_svc) {
312 driver->write_ptr_svc->length = driver->used;
313 driver->write_ptr_svc->buf = buf;
314 err = usb_diag_write(driver->legacy_ch,
315 driver->write_ptr_svc);
316 } else
317 err = -1;
318 } else if (proc_num == MODEM_DATA) {
319 write_ptr->buf = buf;
320#ifdef DIAG_DEBUG
321 printk(KERN_INFO "writing data to USB,"
322 "pkt length %d\n", write_ptr->length);
323 print_hex_dump(KERN_DEBUG, "Written Packet Data to"
324 " USB: ", 16, 1, DUMP_PREFIX_ADDRESS,
325 buf, write_ptr->length, 1);
326#endif /* DIAG DEBUG */
327 err = usb_diag_write(driver->legacy_ch, write_ptr);
328 } else if (proc_num == QDSP_DATA) {
329 write_ptr->buf = buf;
330 err = usb_diag_write(driver->legacy_ch, write_ptr);
331 } else if (proc_num == WCNSS_DATA) {
332 write_ptr->buf = buf;
333 err = usb_diag_write(driver->legacy_ch, write_ptr);
334 }
335#ifdef CONFIG_DIAG_SDIO_PIPE
336 else if (proc_num == SDIO_DATA) {
337 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -0800338 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700339 write_ptr->buf = buf;
340 err = usb_diag_write(driver->mdm_ch, write_ptr);
341 } else
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800342 pr_err("diag: Incorrect sdio data "
343 "while USB write\n");
344 }
345#endif
346#ifdef CONFIG_DIAG_HSIC_PIPE
347 else if (proc_num == HSIC_DATA) {
348 if (driver->hsic_device_enabled) {
349 write_ptr->buf = buf;
350 err = usb_diag_write(driver->mdm_ch, write_ptr);
351 } else
352 pr_err("diag: Incorrect hsic data "
353 "while USB write\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700354 }
355#endif
356 APPEND_DEBUG('d');
357 }
358#endif /* DIAG OVER USB */
359 return err;
360}
361
362void __diag_smd_wcnss_send_req(void)
363{
Ashay Jaiswal29620122012-03-21 12:02:36 +0530364 void *buf = NULL;
365 int *in_busy_wcnss_ptr = NULL;
366 struct diag_request *write_ptr_wcnss = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700367
Ashay Jaiswal29620122012-03-21 12:02:36 +0530368 if (!driver->in_busy_wcnss_1) {
369 buf = driver->buf_in_wcnss_1;
370 write_ptr_wcnss = driver->write_ptr_wcnss_1;
371 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_1);
372 } else if (!driver->in_busy_wcnss_2) {
373 buf = driver->buf_in_wcnss_2;
374 write_ptr_wcnss = driver->write_ptr_wcnss_2;
375 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_2);
376 }
377
378 if (driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700379 int r = smd_read_avail(driver->ch_wcnss);
380 if (r > IN_BUF_SIZE) {
381 if (r < MAX_IN_BUF_SIZE) {
382 pr_err("diag: wcnss packets > %d bytes", r);
383 buf = krealloc(buf, r, GFP_KERNEL);
384 } else {
385 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
386 return;
387 }
388 }
389 if (r > 0) {
390 if (!buf) {
391 pr_err("Out of diagmem for wcnss\n");
392 } else {
393 APPEND_DEBUG('i');
394 smd_read(driver->ch_wcnss, buf, r);
395 APPEND_DEBUG('j');
396 write_ptr_wcnss->length = r;
397 *in_busy_wcnss_ptr = 1;
398 diag_device_write(buf, WCNSS_DATA,
399 write_ptr_wcnss);
400 }
401 }
402 }
403}
404
405void __diag_smd_qdsp_send_req(void)
406{
407 void *buf = NULL;
408 int *in_busy_qdsp_ptr = NULL;
409 struct diag_request *write_ptr_qdsp = NULL;
410
411 if (!driver->in_busy_qdsp_1) {
412 buf = driver->buf_in_qdsp_1;
413 write_ptr_qdsp = driver->write_ptr_qdsp_1;
414 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1);
415 } else if (!driver->in_busy_qdsp_2) {
416 buf = driver->buf_in_qdsp_2;
417 write_ptr_qdsp = driver->write_ptr_qdsp_2;
418 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2);
419 }
420
421 if (driver->chqdsp && buf) {
422 int r = smd_read_avail(driver->chqdsp);
423
424 if (r > IN_BUF_SIZE) {
425 if (r < MAX_IN_BUF_SIZE) {
426 pr_err("diag: SMD sending in "
427 "packets upto %d bytes", r);
428 buf = krealloc(buf, r, GFP_KERNEL);
429 } else {
430 pr_err("diag: SMD sending in "
431 "packets more than %d bytes", MAX_IN_BUF_SIZE);
432 return;
433 }
434 }
435 if (r > 0) {
436 if (!buf)
437 printk(KERN_INFO "Out of diagmem for QDSP\n");
438 else {
439 APPEND_DEBUG('i');
440 smd_read(driver->chqdsp, buf, r);
441 APPEND_DEBUG('j');
442 write_ptr_qdsp->length = r;
443 *in_busy_qdsp_ptr = 1;
444 diag_device_write(buf, QDSP_DATA,
445 write_ptr_qdsp);
446 }
447 }
448 }
449}
450
451static void diag_print_mask_table(void)
452{
453/* Enable this to print mask table when updated */
454#ifdef MASK_DEBUG
455 int first;
456 int last;
457 uint8_t *ptr = driver->msg_masks;
458 int i = 0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700459 pr_info("diag: F3 message mask table\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700460 while (*(uint32_t *)(ptr + 4)) {
461 first = *(uint32_t *)ptr;
462 ptr += 4;
463 last = *(uint32_t *)ptr;
464 ptr += 4;
465 printk(KERN_INFO "SSID %d - %d\n", first, last);
466 for (i = 0 ; i <= last - first ; i++)
467 printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700468 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700469
470 }
471#endif
472}
473
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700474void diag_create_msg_mask_table(void)
475{
476 uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
477
478 CREATE_MSG_MASK_TBL_ROW(0);
479 CREATE_MSG_MASK_TBL_ROW(1);
480 CREATE_MSG_MASK_TBL_ROW(2);
481 CREATE_MSG_MASK_TBL_ROW(3);
482 CREATE_MSG_MASK_TBL_ROW(4);
483 CREATE_MSG_MASK_TBL_ROW(5);
484 CREATE_MSG_MASK_TBL_ROW(6);
485 CREATE_MSG_MASK_TBL_ROW(7);
486 CREATE_MSG_MASK_TBL_ROW(8);
487 CREATE_MSG_MASK_TBL_ROW(9);
488 CREATE_MSG_MASK_TBL_ROW(10);
489 CREATE_MSG_MASK_TBL_ROW(11);
490 CREATE_MSG_MASK_TBL_ROW(12);
491 CREATE_MSG_MASK_TBL_ROW(13);
492 CREATE_MSG_MASK_TBL_ROW(14);
493 CREATE_MSG_MASK_TBL_ROW(15);
494 CREATE_MSG_MASK_TBL_ROW(16);
495 CREATE_MSG_MASK_TBL_ROW(17);
496 CREATE_MSG_MASK_TBL_ROW(18);
497 CREATE_MSG_MASK_TBL_ROW(19);
498 CREATE_MSG_MASK_TBL_ROW(20);
499 CREATE_MSG_MASK_TBL_ROW(21);
500 CREATE_MSG_MASK_TBL_ROW(22);
501}
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700502
503static void diag_set_msg_mask(int rt_mask)
504{
505 int first_ssid, last_ssid, i;
506 uint8_t *parse_ptr, *ptr = driver->msg_masks;
507
508 mutex_lock(&driver->diagchar_mutex);
509 while (*(uint32_t *)(ptr + 4)) {
510 first_ssid = *(uint32_t *)ptr;
511 ptr += 4;
512 last_ssid = *(uint32_t *)ptr;
513 ptr += 4;
514 parse_ptr = ptr;
515 pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
516 for (i = 0; i < last_ssid - first_ssid + 1; i++) {
517 *(int *)parse_ptr = rt_mask;
518 parse_ptr += 4;
519 }
520 ptr += MAX_SSID_PER_RANGE * 4;
521 }
522 mutex_unlock(&driver->diagchar_mutex);
523}
524
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700525static void diag_update_msg_mask(int start, int end , uint8_t *buf)
526{
527 int found = 0;
528 int first;
529 int last;
530 uint8_t *ptr = driver->msg_masks;
531 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
532 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
533
534 mutex_lock(&driver->diagchar_mutex);
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530535
Shalabh Jain321c8b52012-02-22 12:37:06 -0800536 /* First SSID can be zero : So check that last is non-zero */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700537 while (*(uint32_t *)(ptr + 4)) {
538 first = *(uint32_t *)ptr;
539 ptr += 4;
540 last = *(uint32_t *)ptr;
541 ptr += 4;
542 if (start >= first && start <= last) {
543 ptr += (start - first)*4;
544 if (end <= last)
545 if (CHK_OVERFLOW(ptr_buffer_start, ptr,
546 ptr_buffer_end,
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700547 (((end - start)+1)*4))) {
548 pr_debug("diag: update ssid start %d,"
549 " end %d\n", start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550 memcpy(ptr, buf , ((end - start)+1)*4);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700551 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700552 printk(KERN_CRIT "Not enough"
553 " buffer space for"
554 " MSG_MASK\n");
555 else
556 printk(KERN_INFO "Unable to copy"
557 " mask change\n");
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530558
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700559 found = 1;
560 break;
561 } else {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700562 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700563 }
564 }
565 /* Entry was not found - add new table */
566 if (!found) {
567 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
568 8 + ((end - start) + 1)*4)) {
569 memcpy(ptr, &(start) , 4);
570 ptr += 4;
571 memcpy(ptr, &(end), 4);
572 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700573 pr_debug("diag: adding NEW ssid start %d, end %d\n",
574 start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700575 memcpy(ptr, buf , ((end - start) + 1)*4);
576 } else
577 printk(KERN_CRIT " Not enough buffer"
578 " space for MSG_MASK\n");
579 }
580 mutex_unlock(&driver->diagchar_mutex);
581 diag_print_mask_table();
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530582
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700583}
584
Shalabh Jaina51f2592012-03-08 14:36:35 -0800585void diag_toggle_event_mask(int toggle)
586{
587 uint8_t *ptr = driver->event_masks;
588
589 mutex_lock(&driver->diagchar_mutex);
590 if (toggle)
591 memset(ptr, 0xFF, EVENT_MASK_SIZE);
592 else
593 memset(ptr, 0, EVENT_MASK_SIZE);
594 mutex_unlock(&driver->diagchar_mutex);
595}
596
Shalabh Jain321c8b52012-02-22 12:37:06 -0800597static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700598{
599 uint8_t *ptr = driver->event_masks;
600 uint8_t *temp = buf + 2;
601
602 mutex_lock(&driver->diagchar_mutex);
603 if (!toggle)
604 memset(ptr, 0 , EVENT_MASK_SIZE);
605 else
606 if (CHK_OVERFLOW(ptr, ptr,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800607 ptr+EVENT_MASK_SIZE, num_bytes))
608 memcpy(ptr, temp , num_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700609 else
610 printk(KERN_CRIT "Not enough buffer space "
611 "for EVENT_MASK\n");
612 mutex_unlock(&driver->diagchar_mutex);
613}
614
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700615static void diag_disable_log_mask(void)
616{
617 int i = 0;
618 struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
619
620 pr_debug("diag: disable log masks\n");
621 mutex_lock(&driver->diagchar_mutex);
622 for (i = 0; i < MAX_EQUIP_ID; i++) {
623 pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
624 if (!(parse_ptr->equip_id)) /* Reached a null entry */
625 break;
626 memset(driver->log_masks + parse_ptr->index, 0,
627 (parse_ptr->num_items + 7)/8);
628 parse_ptr++;
629 }
630 mutex_unlock(&driver->diagchar_mutex);
631}
632
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700633static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
634{
635 uint8_t *temp = buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700636 int i = 0;
637 unsigned char *ptr_data;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700638 int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700639 struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700640
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700641 pr_debug("diag: received equip id = %d\n", equip_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700642 mutex_lock(&driver->diagchar_mutex);
643 /* Check if we already know index of this equipment ID */
644 for (i = 0; i < MAX_EQUIP_ID; i++) {
645 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
646 offset = ptr->index;
647 break;
648 }
649 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
Shalabh Jain321c8b52012-02-22 12:37:06 -0800650 /* Reached a null entry */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651 ptr->equip_id = equip_id;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800652 ptr->num_items = num_items;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700653 ptr->index = driver->log_masks_length;
654 offset = driver->log_masks_length;
655 driver->log_masks_length += ((num_items+7)/8);
656 break;
657 }
658 ptr++;
659 }
660 ptr_data = driver->log_masks + offset;
661 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
662 + LOG_MASK_SIZE, (num_items+7)/8))
663 memcpy(ptr_data, temp , (num_items+7)/8);
664 else
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700665 pr_err("diag: Not enough buffer space for LOG_MASK\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700666 mutex_unlock(&driver->diagchar_mutex);
667}
668
669static void diag_update_pkt_buffer(unsigned char *buf)
670{
671 unsigned char *ptr = driver->pkt_buf;
672 unsigned char *temp = buf;
673
674 mutex_lock(&driver->diagchar_mutex);
675 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
676 memcpy(ptr, temp , driver->pkt_length);
677 else
678 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
679 mutex_unlock(&driver->diagchar_mutex);
680}
681
682void diag_update_userspace_clients(unsigned int type)
683{
684 int i;
685
686 mutex_lock(&driver->diagchar_mutex);
687 for (i = 0; i < driver->num_clients; i++)
688 if (driver->client_map[i].pid != 0)
689 driver->data_ready[i] |= type;
690 wake_up_interruptible(&driver->wait_q);
691 mutex_unlock(&driver->diagchar_mutex);
692}
693
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700694void diag_update_sleeping_process(int process_id, int data_type)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700695{
696 int i;
697
698 mutex_lock(&driver->diagchar_mutex);
699 for (i = 0; i < driver->num_clients; i++)
700 if (driver->client_map[i].pid == process_id) {
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700701 driver->data_ready[i] |= data_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700702 break;
703 }
704 wake_up_interruptible(&driver->wait_q);
705 mutex_unlock(&driver->diagchar_mutex);
706}
707
708void diag_send_data(struct diag_master_table entry, unsigned char *buf,
709 int len, int type)
710{
711 driver->pkt_length = len;
712 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
713 diag_update_pkt_buffer(buf);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700714 diag_update_sleeping_process(entry.process_id, PKT_TYPE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700715 } else {
716 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700717 if (entry.client_id == MODEM_PROC && driver->ch) {
Shalabh Jain10f5f432012-01-11 11:45:44 +0530718 if (chk_apps_master() &&
Shalabh Jainc9f35092011-07-28 18:36:17 -0700719 (int)(*(char *)buf) == MODE_CMD)
Dixon Petersonff425d12011-12-06 18:12:35 -0800720 if ((int)(*(char *)(buf+1)) ==
721 RESET_ID)
Shalabh Jainc9f35092011-07-28 18:36:17 -0700722 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700723 smd_write(driver->ch, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700724 } else if (entry.client_id == QDSP_PROC &&
725 driver->chqdsp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700726 smd_write(driver->chqdsp, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700727 } else if (entry.client_id == WCNSS_PROC &&
728 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700729 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700730 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700731 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700732 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700733 }
734 }
735}
736
Shalabh Jain321c8b52012-02-22 12:37:06 -0800737void diag_modem_mask_update_fn(struct work_struct *work)
738{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700739 diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
740 ALL_SSID, MODEM_PROC);
741 diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800742 diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
743}
744
745void diag_qdsp_mask_update_fn(struct work_struct *work)
746{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700747 diag_send_msg_mask_update(driver->chqdsp_cntl, ALL_SSID,
748 ALL_SSID, QDSP_PROC);
749 diag_send_log_mask_update(driver->chqdsp_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800750 diag_send_event_mask_update(driver->chqdsp_cntl, diag_event_num_bytes);
751}
752
753void diag_wcnss_mask_update_fn(struct work_struct *work)
754{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700755 diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
756 ALL_SSID, WCNSS_PROC);
757 diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800758 diag_send_event_mask_update(driver->ch_wcnss_cntl,
759 diag_event_num_bytes);
760}
761
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700762void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800763{
764 void *buf = driver->buf_log_mask_update;
765 int header_size = sizeof(struct diag_ctrl_log_mask);
766 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700767 int i, size, wr_size = -ENOMEM, retry_count = 0;
768 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800769
770 for (i = 0; i < MAX_EQUIP_ID; i++) {
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700771 size = (ptr->num_items+7)/8;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800772 /* reached null entry */
773 if ((ptr->equip_id == 0) && (ptr->index == 0))
774 break;
775 driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
776 driver->log_mask->num_items = ptr->num_items;
777 driver->log_mask->data_len = 11 + size;
778 driver->log_mask->stream_id = 1; /* 2, if dual stream */
779 driver->log_mask->status = 3; /* status for valid mask */
780 driver->log_mask->equip_id = ptr->equip_id;
781 driver->log_mask->log_mask_size = size;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700782 /* send only desired update, NOT ALL */
783 if (equip_id == ALL_EQUIP_ID || equip_id ==
784 driver->log_mask->equip_id) {
785 memcpy(buf, driver->log_mask, header_size);
786 memcpy(buf+header_size, driver->log_masks+ptr->index,
787 size);
788 if (ch) {
789 while (retry_count < 3) {
790 spin_lock_irqsave(&diag_cntl_lock,
791 flags);
792 wr_size = smd_write(ch, buf,
793 header_size + size);
794 spin_unlock_irqrestore(&diag_cntl_lock,
795 flags);
796 if (wr_size == -ENOMEM) {
797 retry_count++;
798 usleep(20000);
799 } else
800 break;
801 }
802 if (wr_size != header_size + size)
803 pr_err("diag: log mask update failed"
804 " %d, tried %d", wr_size, header_size + size);
805 else
806 pr_debug("diag: updated log equip ID %d"
807 ",len %d\n", driver->log_mask->equip_id,
808 driver->log_mask->log_mask_size);
809 } else
810 pr_err("diag: ch not valid for log update\n");
811 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800812 ptr++;
813 }
814}
815
816void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
817{
818 void *buf = driver->buf_event_mask_update;
819 int header_size = sizeof(struct diag_ctrl_event_mask);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700820 int wr_size = -ENOMEM, retry_count = 0;
821 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800822
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700823 if (num_bytes == 0) {
824 pr_debug("diag: event mask not set yet, so no update\n");
825 return;
826 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800827 /* send event mask update */
828 driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
829 driver->event_mask->data_len = 7 + num_bytes;
830 driver->event_mask->stream_id = 1; /* 2, if dual stream */
831 driver->event_mask->status = 3; /* status for valid mask */
832 driver->event_mask->event_config = diag_event_config; /* event config */
833 driver->event_mask->event_mask_size = num_bytes;
834 memcpy(buf, driver->event_mask, header_size);
835 memcpy(buf+header_size, driver->event_masks, num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700836 if (ch) {
837 while (retry_count < 3) {
838 spin_lock_irqsave(&diag_cntl_lock, flags);
839 wr_size = smd_write(ch, buf, header_size + num_bytes);
840 spin_unlock_irqrestore(&diag_cntl_lock, flags);
841 if (wr_size == -ENOMEM) {
842 retry_count++;
843 usleep(20000);
844 } else
845 break;
846 }
847 if (wr_size != header_size + num_bytes)
848 pr_err("diag: error writing event mask %d, tried %d\n",
849 wr_size, header_size + num_bytes);
850 } else
851 pr_err("diag: ch not valid for event update\n");
Shalabh Jain321c8b52012-02-22 12:37:06 -0800852}
853
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700854void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
855 int updated_ssid_last, int proc)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800856{
857 void *buf = driver->buf_msg_mask_update;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700858 int first, last, size = -ENOMEM, retry_count = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800859 int header_size = sizeof(struct diag_ctrl_msg_mask);
860 uint8_t *ptr = driver->msg_masks;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700861 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800862
863 while (*(uint32_t *)(ptr + 4)) {
864 first = *(uint32_t *)ptr;
865 ptr += 4;
866 last = *(uint32_t *)ptr;
867 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700868 if ((updated_ssid_first >= first && updated_ssid_last <= last)
869 || (updated_ssid_first == ALL_SSID)) {
870 /* send f3 mask update */
871 driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
872 driver->msg_mask->msg_mask_size = last - first + 1;
873 driver->msg_mask->data_len = 11 +
874 4 * (driver->msg_mask->msg_mask_size);
875 driver->msg_mask->stream_id = 1; /* 2, if dual stream */
876 driver->msg_mask->status = 3; /* status valid mask */
877 driver->msg_mask->msg_mode = 0; /* Legcay mode */
878 driver->msg_mask->ssid_first = first;
879 driver->msg_mask->ssid_last = last;
880 memcpy(buf, driver->msg_mask, header_size);
881 memcpy(buf+header_size, ptr,
882 4 * (driver->msg_mask->msg_mask_size));
883 if (ch) {
884 while (retry_count < 3) {
885 spin_lock_irqsave(&diag_cntl_lock,
886 flags);
887 size = smd_write(ch, buf, header_size +
888 4*(driver->msg_mask->msg_mask_size));
889 spin_unlock_irqrestore(&diag_cntl_lock,
890 flags);
891 if (size == -ENOMEM) {
892 retry_count++;
893 usleep(20000);
894 } else
895 break;
896 }
897 if (size != header_size +
898 4*(driver->msg_mask->msg_mask_size))
899 pr_err("diag: msg mask update fail %d,"
900 " tried %d\n", size,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800901 header_size + 4*(driver->msg_mask->msg_mask_size));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700902 else
903 pr_debug("diag: sending mask update for"
904 " ssid first %d, last %d on PROC %d\n", first, last, proc);
905 } else
906 pr_err("diag: ch invalid msg mask update\n");
907 }
908 ptr += MAX_SSID_PER_RANGE*4;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800909 }
910}
911
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700912static int diag_process_apps_pkt(unsigned char *buf, int len)
913{
914 uint16_t subsys_cmd_code;
915 int subsys_id, ssid_first, ssid_last, ssid_range;
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700916 int packet_type = 1, i, cmd_code, rt_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700917 unsigned char *temp = buf;
918 int data_type;
919#if defined(CONFIG_DIAG_OVER_USB)
920 int payload_length;
921 unsigned char *ptr;
922#endif
923
Shalabh Jain321c8b52012-02-22 12:37:06 -0800924 /* Set log masks */
925 if (*buf == 0x73 && *(int *)(buf+4) == 3) {
926 buf += 8;
927 /* Read Equip ID and pass as first param below*/
928 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
929 diag_update_userspace_clients(LOG_MASKS_TYPE);
930#if defined(CONFIG_DIAG_OVER_USB)
931 if (chk_apps_only()) {
932 driver->apps_rsp_buf[0] = 0x73;
933 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
934 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
935 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
936 for (i = 0; i < payload_length; i++)
937 *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700938 if (driver->ch_cntl)
939 diag_send_log_mask_update(driver->ch_cntl,
940 *(int *)buf);
941 if (driver->chqdsp_cntl)
942 diag_send_log_mask_update(driver->chqdsp_cntl,
943 *(int *)buf);
944 if (driver->ch_wcnss_cntl)
945 diag_send_log_mask_update(driver->ch_wcnss_cntl,
946 *(int *)buf);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800947 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
948 return 0;
949 } else
950 buf = temp;
951#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700952 } /* Disable log masks */
953 else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
954 buf += 8;
955 /* Disable mask for each log code */
956 diag_disable_log_mask();
957 diag_update_userspace_clients(LOG_MASKS_TYPE);
958#if defined(CONFIG_DIAG_OVER_USB)
959 if (chk_apps_only()) {
960 driver->apps_rsp_buf[0] = 0x73;
961 driver->apps_rsp_buf[1] = 0x0;
962 driver->apps_rsp_buf[2] = 0x0;
963 driver->apps_rsp_buf[3] = 0x0;
964 *(int *)(driver->apps_rsp_buf + 4) = 0x0;
965 if (driver->ch_cntl)
966 diag_send_log_mask_update(driver->ch_cntl,
967 *(int *)buf);
968 if (driver->chqdsp_cntl)
969 diag_send_log_mask_update(driver->chqdsp_cntl,
970 *(int *)buf);
971 if (driver->ch_wcnss_cntl)
972 diag_send_log_mask_update(driver->ch_wcnss_cntl,
973 *(int *)buf);
974 ENCODE_RSP_AND_SEND(7);
975 return 0;
976 } else
977 buf = temp;
978#endif
979 } /* Set runtime message mask */
Shalabh Jain321c8b52012-02-22 12:37:06 -0800980 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
981 ssid_first = *(uint16_t *)(buf + 2);
982 ssid_last = *(uint16_t *)(buf + 4);
983 ssid_range = 4 * (ssid_last - ssid_first + 1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700984 pr_debug("diag: received mask update for ssid_first = %d,"
985 " ssid_last = %d", ssid_first, ssid_last);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800986 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
987 diag_update_userspace_clients(MSG_MASKS_TYPE);
988#if defined(CONFIG_DIAG_OVER_USB)
989 if (chk_apps_only()) {
990 for (i = 0; i < 8 + ssid_range; i++)
991 *(driver->apps_rsp_buf + i) = *(buf+i);
992 *(driver->apps_rsp_buf + 6) = 0x1;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700993 if (driver->ch_cntl)
994 diag_send_msg_mask_update(driver->ch_cntl,
995 ssid_first, ssid_last, MODEM_PROC);
996 if (driver->chqdsp_cntl)
997 diag_send_msg_mask_update(driver->chqdsp_cntl,
998 ssid_first, ssid_last, QDSP_PROC);
999 if (driver->ch_wcnss_cntl)
1000 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1001 ssid_first, ssid_last, WCNSS_PROC);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001002 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1003 return 0;
1004 } else
1005 buf = temp;
1006#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001007 } /* Set ALL runtime message mask */
1008 else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
1009 rt_mask = *(int *)(buf + 4);
1010 diag_set_msg_mask(rt_mask);
1011 diag_update_userspace_clients(MSG_MASKS_TYPE);
1012#if defined(CONFIG_DIAG_OVER_USB)
1013 if (chk_apps_only()) {
1014 driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
1015 driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
1016 driver->apps_rsp_buf[2] = 1; /* success */
1017 driver->apps_rsp_buf[3] = 0; /* rsvd */
1018 *(int *)(driver->apps_rsp_buf + 4) = rt_mask;
1019 /* send msg mask update to peripheral */
1020 if (driver->ch_cntl)
1021 diag_send_msg_mask_update(driver->ch_cntl,
1022 ALL_SSID, ALL_SSID, MODEM_PROC);
1023 if (driver->chqdsp_cntl)
1024 diag_send_msg_mask_update(driver->chqdsp_cntl,
1025 ALL_SSID, ALL_SSID, QDSP_PROC);
1026 if (driver->ch_wcnss_cntl)
1027 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1028 ALL_SSID, ALL_SSID, WCNSS_PROC);
1029 ENCODE_RSP_AND_SEND(7);
1030 return 0;
1031 } else
1032 buf = temp;
1033#endif
Shalabh Jain321c8b52012-02-22 12:37:06 -08001034 } else if (*buf == 0x82) { /* event mask change */
1035 buf += 4;
1036 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
1037 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
1038 diag_update_userspace_clients(EVENT_MASKS_TYPE);
1039#if defined(CONFIG_DIAG_OVER_USB)
1040 if (chk_apps_only()) {
1041 driver->apps_rsp_buf[0] = 0x82;
1042 driver->apps_rsp_buf[1] = 0x0;
1043 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1044 *(uint16_t *)(driver->apps_rsp_buf + 4) =
1045 EVENT_LAST_ID + 1;
Shalabh Jaina51f2592012-03-08 14:36:35 -08001046 memcpy(driver->apps_rsp_buf+6, driver->event_masks,
1047 EVENT_LAST_ID/8+1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001048 if (driver->ch_cntl)
1049 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001050 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001051 if (driver->chqdsp_cntl)
1052 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001053 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001054 if (driver->ch_wcnss_cntl)
1055 diag_send_event_mask_update(
1056 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001057 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1058 return 0;
1059 } else
1060 buf = temp;
1061#endif
1062 } else if (*buf == 0x60) {
1063 diag_event_config = *(buf+1);
Shalabh Jaina51f2592012-03-08 14:36:35 -08001064 diag_toggle_event_mask(*(buf+1));
1065 diag_update_userspace_clients(EVENT_MASKS_TYPE);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001066#if defined(CONFIG_DIAG_OVER_USB)
1067 if (chk_apps_only()) {
1068 driver->apps_rsp_buf[0] = 0x60;
1069 driver->apps_rsp_buf[1] = 0x0;
1070 driver->apps_rsp_buf[2] = 0x0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001071 if (driver->ch_cntl)
1072 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001073 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001074 if (driver->chqdsp_cntl)
1075 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001076 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001077 if (driver->ch_wcnss_cntl)
1078 diag_send_event_mask_update(
1079 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001080 ENCODE_RSP_AND_SEND(2);
1081 return 0;
1082 }
1083#endif
1084 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001085 /* Check for registered clients and forward packet to apropriate proc */
1086 cmd_code = (int)(*(char *)buf);
1087 temp++;
1088 subsys_id = (int)(*(char *)temp);
1089 temp++;
1090 subsys_cmd_code = *(uint16_t *)temp;
1091 temp += 2;
1092 data_type = APPS_DATA;
1093 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301094 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001095 if (subsys_id != RESET_ID)
1096 data_type = MODEM_DATA;
1097 }
1098
1099 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001100 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001101 entry = driver->table[i];
1102 if (entry.process_id != NO_PROCESS) {
1103 if (entry.cmd_code == cmd_code && entry.subsys_id ==
1104 subsys_id && entry.cmd_code_lo <=
1105 subsys_cmd_code &&
1106 entry.cmd_code_hi >= subsys_cmd_code) {
1107 diag_send_data(entry, buf, len, data_type);
1108 packet_type = 0;
1109 } else if (entry.cmd_code == 255
1110 && cmd_code == 75) {
1111 if (entry.subsys_id ==
1112 subsys_id &&
1113 entry.cmd_code_lo <=
1114 subsys_cmd_code &&
1115 entry.cmd_code_hi >=
1116 subsys_cmd_code) {
1117 diag_send_data(entry, buf, len,
1118 data_type);
1119 packet_type = 0;
1120 }
1121 } else if (entry.cmd_code == 255 &&
1122 entry.subsys_id == 255) {
1123 if (entry.cmd_code_lo <=
1124 cmd_code &&
1125 entry.
1126 cmd_code_hi >= cmd_code) {
1127 diag_send_data(entry, buf, len,
1128 data_type);
1129 packet_type = 0;
1130 }
1131 }
1132 }
1133 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001134#if defined(CONFIG_DIAG_OVER_USB)
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001135 /* Check for Apps Only & get event mask request */
Shalabh Jain321c8b52012-02-22 12:37:06 -08001136 if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001137 driver->apps_rsp_buf[0] = 0x81;
1138 driver->apps_rsp_buf[1] = 0x0;
1139 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1140 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
1141 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
1142 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
1143 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1144 return 0;
1145 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001146 /* Get log ID range & Check for Apps Only */
1147 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001148 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
1149 driver->apps_rsp_buf[0] = 0x73;
1150 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
1151 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
1152 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
1153 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
1154 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
1155 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
1156 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
1157 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
1158 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
1159 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
1160 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
1161 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
1162 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
1163 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
1164 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
1165 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
1166 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
1167 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
1168 ENCODE_RSP_AND_SEND(75);
1169 return 0;
1170 }
1171 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001172 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001173 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
1174 driver->apps_rsp_buf[0] = 0x7d;
1175 driver->apps_rsp_buf[1] = 0x1;
1176 driver->apps_rsp_buf[2] = 0x1;
1177 driver->apps_rsp_buf[3] = 0x0;
1178 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
1179 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
1180 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
1181 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
1182 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
1183 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
1184 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
1185 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
1186 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
1187 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
1188 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
1189 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
1190 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
1191 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
1192 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
1193 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
1194 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
1195 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
1196 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
1197 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
1198 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
1199 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
1200 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
1201 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
1202 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
1203 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
1204 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
1205 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
1206 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
1207 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
1208 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
1209 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
1210 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
1211 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
1212 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
1213 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
1214 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
1215 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
1216 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001217 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
1218 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
1219 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
1220 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
1221 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
1222 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
1223 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
1224 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
1225 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001226 return 0;
1227 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001228 /* Check for Apps Only Respond to Get Subsys Build mask */
1229 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001230 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
1231 ssid_first = *(uint16_t *)(buf + 2);
1232 ssid_last = *(uint16_t *)(buf + 4);
1233 ssid_range = 4 * (ssid_last - ssid_first + 1);
1234 /* frame response */
1235 driver->apps_rsp_buf[0] = 0x7d;
1236 driver->apps_rsp_buf[1] = 0x2;
1237 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
1238 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
1239 driver->apps_rsp_buf[6] = 0x1;
1240 driver->apps_rsp_buf[7] = 0x0;
1241 ptr = driver->apps_rsp_buf + 8;
1242 /* bld time masks */
1243 switch (ssid_first) {
1244 case MSG_SSID_0:
1245 for (i = 0; i < ssid_range; i += 4)
1246 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
1247 break;
1248 case MSG_SSID_1:
1249 for (i = 0; i < ssid_range; i += 4)
1250 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
1251 break;
1252 case MSG_SSID_2:
1253 for (i = 0; i < ssid_range; i += 4)
1254 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
1255 break;
1256 case MSG_SSID_3:
1257 for (i = 0; i < ssid_range; i += 4)
1258 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
1259 break;
1260 case MSG_SSID_4:
1261 for (i = 0; i < ssid_range; i += 4)
1262 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
1263 break;
1264 case MSG_SSID_5:
1265 for (i = 0; i < ssid_range; i += 4)
1266 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
1267 break;
1268 case MSG_SSID_6:
1269 for (i = 0; i < ssid_range; i += 4)
1270 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
1271 break;
1272 case MSG_SSID_7:
1273 for (i = 0; i < ssid_range; i += 4)
1274 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
1275 break;
1276 case MSG_SSID_8:
1277 for (i = 0; i < ssid_range; i += 4)
1278 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
1279 break;
1280 case MSG_SSID_9:
1281 for (i = 0; i < ssid_range; i += 4)
1282 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
1283 break;
1284 case MSG_SSID_10:
1285 for (i = 0; i < ssid_range; i += 4)
1286 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
1287 break;
1288 case MSG_SSID_11:
1289 for (i = 0; i < ssid_range; i += 4)
1290 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
1291 break;
1292 case MSG_SSID_12:
1293 for (i = 0; i < ssid_range; i += 4)
1294 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1295 break;
1296 case MSG_SSID_13:
1297 for (i = 0; i < ssid_range; i += 4)
1298 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1299 break;
1300 case MSG_SSID_14:
1301 for (i = 0; i < ssid_range; i += 4)
1302 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1303 break;
1304 case MSG_SSID_15:
1305 for (i = 0; i < ssid_range; i += 4)
1306 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1307 break;
1308 case MSG_SSID_16:
1309 for (i = 0; i < ssid_range; i += 4)
1310 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1311 break;
1312 case MSG_SSID_17:
1313 for (i = 0; i < ssid_range; i += 4)
1314 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1315 break;
1316 case MSG_SSID_18:
1317 for (i = 0; i < ssid_range; i += 4)
1318 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1319 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001320 case MSG_SSID_19:
1321 for (i = 0; i < ssid_range; i += 4)
1322 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1323 break;
1324 case MSG_SSID_20:
1325 for (i = 0; i < ssid_range; i += 4)
1326 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1327 break;
1328 case MSG_SSID_21:
1329 for (i = 0; i < ssid_range; i += 4)
1330 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1331 break;
1332 case MSG_SSID_22:
1333 for (i = 0; i < ssid_range; i += 4)
1334 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1335 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001336 }
1337 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1338 return 0;
1339 }
1340 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301341 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001342 /* send response back */
1343 driver->apps_rsp_buf[0] = *buf;
1344 ENCODE_RSP_AND_SEND(0);
1345 msleep(5000);
1346 /* call download API */
1347 msm_set_restart_mode(RESTART_DLOAD);
1348 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1349 kernel_restart(NULL);
1350 /* Not required, represents that command isnt sent to modem */
1351 return 0;
1352 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001353 /* Check for polling for Apps only DIAG */
1354 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1355 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001356 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001357 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001358 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001359 for (i = 0; i < 3; i++)
1360 driver->apps_rsp_buf[i] = *(buf+i);
1361 for (i = 0; i < 13; i++)
1362 driver->apps_rsp_buf[i+3] = 0;
1363
1364 ENCODE_RSP_AND_SEND(15);
1365 return 0;
1366 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001367 }
1368 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001369 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001370 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001371 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001372 for (i = 0; i < 55; i++)
1373 driver->apps_rsp_buf[i] = 0;
1374
1375 ENCODE_RSP_AND_SEND(54);
1376 return 0;
1377 }
1378 /* respond to 0x7c command */
1379 else if (*buf == 0x7c) {
1380 driver->apps_rsp_buf[0] = 0x7c;
1381 for (i = 1; i < 8; i++)
1382 driver->apps_rsp_buf[i] = 0;
1383 /* Tools ID for APQ 8060 */
1384 *(int *)(driver->apps_rsp_buf + 8) =
1385 chk_config_get_id();
1386 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1387 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1388 ENCODE_RSP_AND_SEND(13);
1389 return 0;
1390 }
1391 }
1392#endif
1393 return packet_type;
1394}
1395
1396#ifdef CONFIG_DIAG_OVER_USB
1397void diag_send_error_rsp(int index)
1398{
1399 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301400
1401 if (index > 490) {
1402 pr_err("diag: error response too huge, aborting\n");
1403 return;
1404 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001405 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1406 for (i = 0; i < index; i++)
1407 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1408 ENCODE_RSP_AND_SEND(index - 3);
1409}
1410#else
1411static inline void diag_send_error_rsp(int index) {}
1412#endif
1413
1414void diag_process_hdlc(void *data, unsigned len)
1415{
1416 struct diag_hdlc_decode_type hdlc;
1417 int ret, type = 0;
1418 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1419 hdlc.dest_ptr = driver->hdlc_buf;
1420 hdlc.dest_size = USB_MAX_OUT_BUF;
1421 hdlc.src_ptr = data;
1422 hdlc.src_size = len;
1423 hdlc.src_idx = 0;
1424 hdlc.dest_idx = 0;
1425 hdlc.escaping = 0;
1426
1427 ret = diag_hdlc_decode(&hdlc);
1428
1429 if (ret)
1430 type = diag_process_apps_pkt(driver->hdlc_buf,
1431 hdlc.dest_idx - 3);
1432 else if (driver->debug_flag) {
1433 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1434 " errors or partial packet received, packet"
1435 " length = %d\n", len);
1436 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1437 DUMP_PREFIX_ADDRESS, data, len, 1);
1438 driver->debug_flag = 0;
1439 }
1440 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001441 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001442 diag_send_error_rsp(hdlc.dest_idx);
1443 type = 0;
1444 }
1445 /* implies this packet is NOT meant for apps */
1446 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001447 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001448 diag_send_error_rsp(hdlc.dest_idx);
1449 } else { /* APQ 8060, Let Q6 respond */
1450 if (driver->chqdsp)
1451 smd_write(driver->chqdsp, driver->hdlc_buf,
1452 hdlc.dest_idx - 3);
1453 }
1454 type = 0;
1455 }
1456
1457#ifdef DIAG_DEBUG
1458 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1459 for (i = 0; i < hdlc.dest_idx; i++)
1460 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1461 driver->hdlc_buf)+i));
1462#endif /* DIAG DEBUG */
1463 /* ignore 2 bytes for CRC, one for 7E and send */
1464 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1465 APPEND_DEBUG('g');
1466 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1467 APPEND_DEBUG('h');
1468#ifdef DIAG_DEBUG
1469 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1470 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1471 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1472#endif /* DIAG DEBUG */
1473 }
1474}
1475
1476#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001477/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1478#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001479#define N_LEGACY_READ 1
1480
1481int diagfwd_connect(void)
1482{
1483 int err;
1484
1485 printk(KERN_DEBUG "diag: USB connected\n");
1486 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1487 N_LEGACY_READ);
1488 if (err)
1489 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1490
1491 driver->usb_connected = 1;
1492 driver->in_busy_1 = 0;
1493 driver->in_busy_2 = 0;
1494 driver->in_busy_qdsp_1 = 0;
1495 driver->in_busy_qdsp_2 = 0;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301496 driver->in_busy_wcnss_1 = 0;
1497 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001498
1499 /* Poll SMD channels to check for data*/
1500 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1501 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1502 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001503 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001504 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1505 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1506 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001507 /* Poll USB channel to check for data*/
1508 queue_work(driver->diag_wq, &(driver->diag_read_work));
1509#ifdef CONFIG_DIAG_SDIO_PIPE
1510 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1511 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1512 diagfwd_connect_sdio();
1513 else
1514 printk(KERN_INFO "diag: No USB MDM ch");
1515 }
1516#endif
1517 return 0;
1518}
1519
1520int diagfwd_disconnect(void)
1521{
1522 printk(KERN_DEBUG "diag: USB disconnected\n");
1523 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001524 driver->debug_flag = 1;
1525 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001526 if (driver->logging_mode == USB_MODE) {
1527 driver->in_busy_1 = 1;
1528 driver->in_busy_2 = 1;
1529 driver->in_busy_qdsp_1 = 1;
1530 driver->in_busy_qdsp_2 = 1;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301531 driver->in_busy_wcnss_1 = 1;
1532 driver->in_busy_wcnss_2 = 1;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001533 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001534#ifdef CONFIG_DIAG_SDIO_PIPE
1535 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1536 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1537 diagfwd_disconnect_sdio();
1538#endif
1539 /* TBD - notify and flow control SMD */
1540 return 0;
1541}
1542
1543int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1544{
1545 unsigned char *buf = diag_write_ptr->buf;
1546 /*Determine if the write complete is for data from modem/apps/q6 */
1547 /* Need a context variable here instead */
1548 if (buf == (void *)driver->buf_in_1) {
1549 driver->in_busy_1 = 0;
1550 APPEND_DEBUG('o');
1551 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1552 } else if (buf == (void *)driver->buf_in_2) {
1553 driver->in_busy_2 = 0;
1554 APPEND_DEBUG('O');
1555 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1556 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1557 driver->in_busy_qdsp_1 = 0;
1558 APPEND_DEBUG('p');
1559 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1560 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1561 driver->in_busy_qdsp_2 = 0;
1562 APPEND_DEBUG('P');
1563 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
Ashay Jaiswal29620122012-03-21 12:02:36 +05301564 } else if (buf == driver->buf_in_wcnss_1) {
1565 driver->in_busy_wcnss_1 = 0;
1566 APPEND_DEBUG('r');
1567 queue_work(driver->diag_wq,
1568 &(driver->diag_read_smd_wcnss_work));
1569 } else if (buf == driver->buf_in_wcnss_2) {
1570 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001571 APPEND_DEBUG('R');
1572 queue_work(driver->diag_wq,
1573 &(driver->diag_read_smd_wcnss_work));
1574 }
1575#ifdef CONFIG_DIAG_SDIO_PIPE
1576 else if (buf == (void *)driver->buf_in_sdio)
1577 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001578 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001579 diagfwd_write_complete_sdio();
1580 else
1581 pr_err("diag: Incorrect buffer pointer while WRITE");
1582#endif
1583 else {
1584 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1585 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1586 POOL_TYPE_WRITE_STRUCT);
1587 APPEND_DEBUG('q');
1588 }
1589 return 0;
1590}
1591
1592int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1593{
1594 int status = diag_read_ptr->status;
1595 unsigned char *buf = diag_read_ptr->buf;
1596
1597 /* Determine if the read complete is for data on legacy/mdm ch */
1598 if (buf == (void *)driver->usb_buf_out) {
1599 driver->read_len_legacy = diag_read_ptr->actual;
1600 APPEND_DEBUG('s');
1601#ifdef DIAG_DEBUG
1602 printk(KERN_INFO "read data from USB, pkt length %d",
1603 diag_read_ptr->actual);
1604 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1605 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1606 diag_read_ptr->actual, 1);
1607#endif /* DIAG DEBUG */
1608 if (driver->logging_mode == USB_MODE) {
1609 if (status != -ECONNRESET && status != -ESHUTDOWN)
1610 queue_work(driver->diag_wq,
1611 &(driver->diag_proc_hdlc_work));
1612 else
1613 queue_work(driver->diag_wq,
1614 &(driver->diag_read_work));
1615 }
1616 }
1617#ifdef CONFIG_DIAG_SDIO_PIPE
1618 else if (buf == (void *)driver->usb_buf_mdm_out) {
1619 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001620 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001621 driver->read_len_mdm = diag_read_ptr->actual;
1622 diagfwd_read_complete_sdio();
1623 } else
1624 pr_err("diag: Incorrect buffer pointer while READ");
1625 }
1626#endif
1627 else
1628 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1629
1630 return 0;
1631}
1632
1633void diag_read_work_fn(struct work_struct *work)
1634{
1635 APPEND_DEBUG('d');
1636 driver->usb_read_ptr->buf = driver->usb_buf_out;
1637 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1638 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1639 APPEND_DEBUG('e');
1640}
1641
1642void diag_process_hdlc_fn(struct work_struct *work)
1643{
1644 APPEND_DEBUG('D');
1645 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1646 diag_read_work_fn(work);
1647 APPEND_DEBUG('E');
1648}
1649
1650void diag_usb_legacy_notifier(void *priv, unsigned event,
1651 struct diag_request *d_req)
1652{
1653 switch (event) {
1654 case USB_DIAG_CONNECT:
1655 diagfwd_connect();
1656 break;
1657 case USB_DIAG_DISCONNECT:
1658 diagfwd_disconnect();
1659 break;
1660 case USB_DIAG_READ_DONE:
1661 diagfwd_read_complete(d_req);
1662 break;
1663 case USB_DIAG_WRITE_DONE:
1664 diagfwd_write_complete(d_req);
1665 break;
1666 default:
1667 printk(KERN_ERR "Unknown event from USB diag\n");
1668 break;
1669 }
1670}
1671
1672#endif /* DIAG OVER USB */
1673
1674static void diag_smd_notify(void *ctxt, unsigned event)
1675{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001676 if (event == SMD_EVENT_CLOSE) {
1677 pr_info("diag: clean modem registration\n");
1678 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001679 driver->ch = 0;
1680 return;
1681 } else if (event == SMD_EVENT_OPEN) {
1682 driver->ch = ch_temp;
1683 }
1684 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001685}
1686
1687#if defined(CONFIG_MSM_N_WAY_SMD)
1688static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1689{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001690 if (event == SMD_EVENT_CLOSE) {
1691 pr_info("diag: clean lpass registration\n");
1692 diag_clear_reg(QDSP_PROC);
1693 driver->chqdsp = 0;
1694 return;
1695 } else if (event == SMD_EVENT_OPEN) {
1696 driver->chqdsp = chqdsp_temp;
1697 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001698 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1699}
1700#endif
1701
1702static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1703{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001704 if (event == SMD_EVENT_CLOSE) {
1705 pr_info("diag: clean wcnss registration\n");
1706 diag_clear_reg(WCNSS_PROC);
1707 driver->ch_wcnss = 0;
1708 return;
1709 } else if (event == SMD_EVENT_OPEN) {
1710 driver->ch_wcnss = ch_wcnss_temp;
1711 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001712 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1713}
1714
1715static int diag_smd_probe(struct platform_device *pdev)
1716{
1717 int r = 0;
1718
Shalabh Jaineefee052011-11-08 23:46:03 -08001719 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001720 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001721 ch_temp = driver->ch;
1722 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001723#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001724 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001725 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1726 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001727 chqdsp_temp = driver->chqdsp;
1728 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001729#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001730 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001731 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1732 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001733 ch_wcnss_temp = driver->ch_wcnss;
1734 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001735 pm_runtime_set_active(&pdev->dev);
1736 pm_runtime_enable(&pdev->dev);
1737 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1738
1739 return 0;
1740}
1741
1742static int diagfwd_runtime_suspend(struct device *dev)
1743{
1744 dev_dbg(dev, "pm_runtime: suspending...\n");
1745 return 0;
1746}
1747
1748static int diagfwd_runtime_resume(struct device *dev)
1749{
1750 dev_dbg(dev, "pm_runtime: resuming...\n");
1751 return 0;
1752}
1753
1754static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1755 .runtime_suspend = diagfwd_runtime_suspend,
1756 .runtime_resume = diagfwd_runtime_resume,
1757};
1758
1759static struct platform_driver msm_smd_ch1_driver = {
1760
1761 .probe = diag_smd_probe,
1762 .driver = {
1763 .name = "DIAG",
1764 .owner = THIS_MODULE,
1765 .pm = &diagfwd_dev_pm_ops,
1766 },
1767};
1768
1769static struct platform_driver diag_smd_lite_driver = {
1770
1771 .probe = diag_smd_probe,
1772 .driver = {
1773 .name = "APPS_RIVA_DATA",
1774 .owner = THIS_MODULE,
1775 .pm = &diagfwd_dev_pm_ops,
1776 },
1777};
1778
1779void diagfwd_init(void)
1780{
1781 diag_debug_buf_idx = 0;
1782 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001783 driver->use_device_tree = has_device_tree();
Shalabh Jainb6eda0e2012-04-18 16:39:52 -07001784 spin_lock_init(&diag_cntl_lock);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001785
1786 if (driver->event_mask == NULL) {
1787 driver->event_mask = kzalloc(sizeof(
1788 struct diag_ctrl_event_mask), GFP_KERNEL);
1789 if (driver->event_mask == NULL)
1790 goto err;
1791 }
1792 if (driver->msg_mask == NULL) {
1793 driver->msg_mask = kzalloc(sizeof(
1794 struct diag_ctrl_msg_mask), GFP_KERNEL);
1795 if (driver->msg_mask == NULL)
1796 goto err;
1797 }
1798 if (driver->log_mask == NULL) {
1799 driver->log_mask = kzalloc(sizeof(
1800 struct diag_ctrl_log_mask), GFP_KERNEL);
1801 if (driver->log_mask == NULL)
1802 goto err;
1803 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001804 if (driver->buf_in_1 == NULL) {
1805 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1806 if (driver->buf_in_1 == NULL)
1807 goto err;
1808 }
1809 if (driver->buf_in_2 == NULL) {
1810 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1811 if (driver->buf_in_2 == NULL)
1812 goto err;
1813 }
1814 if (driver->buf_in_qdsp_1 == NULL) {
1815 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1816 if (driver->buf_in_qdsp_1 == NULL)
1817 goto err;
1818 }
1819 if (driver->buf_in_qdsp_2 == NULL) {
1820 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1821 if (driver->buf_in_qdsp_2 == NULL)
1822 goto err;
1823 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301824 if (driver->buf_in_wcnss_1 == NULL) {
1825 driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1826 if (driver->buf_in_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001827 goto err;
1828 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301829 if (driver->buf_in_wcnss_2 == NULL) {
1830 driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1831 if (driver->buf_in_wcnss_2 == NULL)
1832 goto err;
1833 }
1834
Shalabh Jain321c8b52012-02-22 12:37:06 -08001835 if (driver->buf_msg_mask_update == NULL) {
1836 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1837 GFP_KERNEL);
1838 if (driver->buf_msg_mask_update == NULL)
1839 goto err;
1840 }
1841 if (driver->buf_log_mask_update == NULL) {
1842 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1843 GFP_KERNEL);
1844 if (driver->buf_log_mask_update == NULL)
1845 goto err;
1846 }
1847 if (driver->buf_event_mask_update == NULL) {
1848 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1849 GFP_KERNEL);
1850 if (driver->buf_event_mask_update == NULL)
1851 goto err;
1852 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001853 if (driver->usb_buf_out == NULL &&
1854 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1855 GFP_KERNEL)) == NULL)
1856 goto err;
1857 if (driver->hdlc_buf == NULL
1858 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1859 goto err;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001860 if (driver->user_space_data == NULL)
1861 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1862 if (driver->user_space_data == NULL)
1863 goto err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001864 if (driver->msg_masks == NULL
1865 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1866 GFP_KERNEL)) == NULL)
1867 goto err;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001868 diag_create_msg_mask_table();
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001869 diag_event_num_bytes = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001870 if (driver->log_masks == NULL &&
1871 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1872 goto err;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -07001873 driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001874 if (driver->event_masks == NULL &&
1875 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1876 GFP_KERNEL)) == NULL)
1877 goto err;
1878 if (driver->client_map == NULL &&
1879 (driver->client_map = kzalloc
1880 ((driver->num_clients) * sizeof(struct diag_client_map),
1881 GFP_KERNEL)) == NULL)
1882 goto err;
1883 if (driver->buf_tbl == NULL)
1884 driver->buf_tbl = kzalloc(buf_tbl_size *
1885 sizeof(struct diag_write_device), GFP_KERNEL);
1886 if (driver->buf_tbl == NULL)
1887 goto err;
1888 if (driver->data_ready == NULL &&
1889 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1890 , GFP_KERNEL)) == NULL)
1891 goto err;
1892 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001893 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001894 sizeof(struct diag_master_table),
1895 GFP_KERNEL)) == NULL)
1896 goto err;
1897 if (driver->write_ptr_1 == NULL) {
1898 driver->write_ptr_1 = kzalloc(
1899 sizeof(struct diag_request), GFP_KERNEL);
1900 if (driver->write_ptr_1 == NULL)
1901 goto err;
1902 }
1903 if (driver->write_ptr_2 == NULL) {
1904 driver->write_ptr_2 = kzalloc(
1905 sizeof(struct diag_request), GFP_KERNEL);
1906 if (driver->write_ptr_2 == NULL)
1907 goto err;
1908 }
1909 if (driver->write_ptr_qdsp_1 == NULL) {
1910 driver->write_ptr_qdsp_1 = kzalloc(
1911 sizeof(struct diag_request), GFP_KERNEL);
1912 if (driver->write_ptr_qdsp_1 == NULL)
1913 goto err;
1914 }
1915 if (driver->write_ptr_qdsp_2 == NULL) {
1916 driver->write_ptr_qdsp_2 = kzalloc(
1917 sizeof(struct diag_request), GFP_KERNEL);
1918 if (driver->write_ptr_qdsp_2 == NULL)
1919 goto err;
1920 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301921 if (driver->write_ptr_wcnss_1 == NULL) {
1922 driver->write_ptr_wcnss_1 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001923 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301924 if (driver->write_ptr_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001925 goto err;
1926 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301927 if (driver->write_ptr_wcnss_2 == NULL) {
1928 driver->write_ptr_wcnss_2 = kzalloc(
1929 sizeof(struct diag_request), GFP_KERNEL);
1930 if (driver->write_ptr_wcnss_2 == NULL)
1931 goto err;
1932 }
1933
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001934 if (driver->usb_read_ptr == NULL) {
1935 driver->usb_read_ptr = kzalloc(
1936 sizeof(struct diag_request), GFP_KERNEL);
1937 if (driver->usb_read_ptr == NULL)
1938 goto err;
1939 }
1940 if (driver->pkt_buf == NULL &&
1941 (driver->pkt_buf = kzalloc(PKT_SIZE,
1942 GFP_KERNEL)) == NULL)
1943 goto err;
1944 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001945 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001946 if (driver->apps_rsp_buf == NULL)
1947 goto err;
1948 }
1949 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1950#ifdef CONFIG_DIAG_OVER_USB
1951 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1952 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001953 INIT_WORK(&(driver->diag_modem_mask_update_work),
1954 diag_modem_mask_update_fn);
1955 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
1956 diag_qdsp_mask_update_fn);
1957 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
1958 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001959 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
1960 diag_usb_legacy_notifier);
1961 if (IS_ERR(driver->legacy_ch)) {
1962 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
1963 goto err;
1964 }
1965#endif
1966 platform_driver_register(&msm_smd_ch1_driver);
1967 platform_driver_register(&diag_smd_lite_driver);
1968
1969 return;
1970err:
1971 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08001972 kfree(driver->event_mask);
1973 kfree(driver->log_mask);
1974 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001975 kfree(driver->buf_in_1);
1976 kfree(driver->buf_in_2);
1977 kfree(driver->buf_in_qdsp_1);
1978 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301979 kfree(driver->buf_in_wcnss_1);
1980 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001981 kfree(driver->buf_msg_mask_update);
1982 kfree(driver->buf_log_mask_update);
1983 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001984 kfree(driver->usb_buf_out);
1985 kfree(driver->hdlc_buf);
1986 kfree(driver->msg_masks);
1987 kfree(driver->log_masks);
1988 kfree(driver->event_masks);
1989 kfree(driver->client_map);
1990 kfree(driver->buf_tbl);
1991 kfree(driver->data_ready);
1992 kfree(driver->table);
1993 kfree(driver->pkt_buf);
1994 kfree(driver->write_ptr_1);
1995 kfree(driver->write_ptr_2);
1996 kfree(driver->write_ptr_qdsp_1);
1997 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301998 kfree(driver->write_ptr_wcnss_1);
1999 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002000 kfree(driver->usb_read_ptr);
2001 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002002 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002003 if (driver->diag_wq)
2004 destroy_workqueue(driver->diag_wq);
2005}
2006
2007void diagfwd_exit(void)
2008{
2009 smd_close(driver->ch);
2010 smd_close(driver->chqdsp);
2011 smd_close(driver->ch_wcnss);
2012 driver->ch = 0; /* SMD can make this NULL */
2013 driver->chqdsp = 0;
2014 driver->ch_wcnss = 0;
2015#ifdef CONFIG_DIAG_OVER_USB
2016 if (driver->usb_connected)
2017 usb_diag_free_req(driver->legacy_ch);
2018 usb_diag_close(driver->legacy_ch);
2019#endif
2020 platform_driver_unregister(&msm_smd_ch1_driver);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -07002021 platform_driver_unregister(&msm_diag_dci_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002022 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002023 kfree(driver->event_mask);
2024 kfree(driver->log_mask);
2025 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002026 kfree(driver->buf_in_1);
2027 kfree(driver->buf_in_2);
2028 kfree(driver->buf_in_qdsp_1);
2029 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302030 kfree(driver->buf_in_wcnss_1);
2031 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002032 kfree(driver->buf_msg_mask_update);
2033 kfree(driver->buf_log_mask_update);
2034 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002035 kfree(driver->usb_buf_out);
2036 kfree(driver->hdlc_buf);
2037 kfree(driver->msg_masks);
2038 kfree(driver->log_masks);
2039 kfree(driver->event_masks);
2040 kfree(driver->client_map);
2041 kfree(driver->buf_tbl);
2042 kfree(driver->data_ready);
2043 kfree(driver->table);
2044 kfree(driver->pkt_buf);
2045 kfree(driver->write_ptr_1);
2046 kfree(driver->write_ptr_2);
2047 kfree(driver->write_ptr_qdsp_1);
2048 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302049 kfree(driver->write_ptr_wcnss_1);
2050 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002051 kfree(driver->usb_read_ptr);
2052 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002053 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002054 destroy_workqueue(driver->diag_wq);
2055}