blob: 340524b67c95a9097e6ada32214165f65b5c0c29 [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;
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700276 pr_debug("diag: wake up logging process\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700277 wake_up_interruptible(&driver->wait_q);
278 } else
279 return -EINVAL;
280 } else if (driver->logging_mode == NO_LOGGING_MODE) {
281 if (proc_num == MODEM_DATA) {
282 driver->in_busy_1 = 0;
283 driver->in_busy_2 = 0;
284 queue_work(driver->diag_wq, &(driver->
285 diag_read_smd_work));
286 } else if (proc_num == QDSP_DATA) {
287 driver->in_busy_qdsp_1 = 0;
288 driver->in_busy_qdsp_2 = 0;
289 queue_work(driver->diag_wq, &(driver->
290 diag_read_smd_qdsp_work));
291 } else if (proc_num == WCNSS_DATA) {
Ashay Jaiswal29620122012-03-21 12:02:36 +0530292 driver->in_busy_wcnss_1 = 0;
293 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700294 queue_work(driver->diag_wq, &(driver->
295 diag_read_smd_wcnss_work));
296 }
Shalabh Jain482bf122011-12-06 03:54:47 -0800297#ifdef CONFIG_DIAG_SDIO_PIPE
298 else if (proc_num == SDIO_DATA) {
299 driver->in_busy_sdio = 0;
300 queue_work(driver->diag_sdio_wq,
301 &(driver->diag_read_sdio_work));
302 }
303#endif
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700304#ifdef CONFIG_DIAG_HSIC_PIPE
305 else if (proc_num == HSIC_DATA) {
306 driver->in_busy_hsic_read = 0;
307 driver->in_busy_hsic_write_on_device = 0;
308 if (driver->hsic_ch)
309 queue_work(driver->diag_hsic_wq,
310 &(driver->diag_read_hsic_work));
311 }
312#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700313 err = -1;
314 }
315#ifdef CONFIG_DIAG_OVER_USB
316 else if (driver->logging_mode == USB_MODE) {
317 if (proc_num == APPS_DATA) {
318 driver->write_ptr_svc = (struct diag_request *)
319 (diagmem_alloc(driver, sizeof(struct diag_request),
320 POOL_TYPE_WRITE_STRUCT));
321 if (driver->write_ptr_svc) {
322 driver->write_ptr_svc->length = driver->used;
323 driver->write_ptr_svc->buf = buf;
324 err = usb_diag_write(driver->legacy_ch,
325 driver->write_ptr_svc);
326 } else
327 err = -1;
328 } else if (proc_num == MODEM_DATA) {
329 write_ptr->buf = buf;
330#ifdef DIAG_DEBUG
331 printk(KERN_INFO "writing data to USB,"
332 "pkt length %d\n", write_ptr->length);
333 print_hex_dump(KERN_DEBUG, "Written Packet Data to"
334 " USB: ", 16, 1, DUMP_PREFIX_ADDRESS,
335 buf, write_ptr->length, 1);
336#endif /* DIAG DEBUG */
337 err = usb_diag_write(driver->legacy_ch, write_ptr);
338 } else if (proc_num == QDSP_DATA) {
339 write_ptr->buf = buf;
340 err = usb_diag_write(driver->legacy_ch, write_ptr);
341 } else if (proc_num == WCNSS_DATA) {
342 write_ptr->buf = buf;
343 err = usb_diag_write(driver->legacy_ch, write_ptr);
344 }
345#ifdef CONFIG_DIAG_SDIO_PIPE
346 else if (proc_num == SDIO_DATA) {
347 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -0800348 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700349 write_ptr->buf = buf;
350 err = usb_diag_write(driver->mdm_ch, write_ptr);
351 } else
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800352 pr_err("diag: Incorrect sdio data "
353 "while USB write\n");
354 }
355#endif
356#ifdef CONFIG_DIAG_HSIC_PIPE
357 else if (proc_num == HSIC_DATA) {
358 if (driver->hsic_device_enabled) {
359 write_ptr->buf = buf;
360 err = usb_diag_write(driver->mdm_ch, write_ptr);
361 } else
362 pr_err("diag: Incorrect hsic data "
363 "while USB write\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700364 }
365#endif
366 APPEND_DEBUG('d');
367 }
368#endif /* DIAG OVER USB */
369 return err;
370}
371
372void __diag_smd_wcnss_send_req(void)
373{
Ashay Jaiswal29620122012-03-21 12:02:36 +0530374 void *buf = NULL;
375 int *in_busy_wcnss_ptr = NULL;
376 struct diag_request *write_ptr_wcnss = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700377
Ashay Jaiswal29620122012-03-21 12:02:36 +0530378 if (!driver->in_busy_wcnss_1) {
379 buf = driver->buf_in_wcnss_1;
380 write_ptr_wcnss = driver->write_ptr_wcnss_1;
381 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_1);
382 } else if (!driver->in_busy_wcnss_2) {
383 buf = driver->buf_in_wcnss_2;
384 write_ptr_wcnss = driver->write_ptr_wcnss_2;
385 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_2);
386 }
387
388 if (driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700389 int r = smd_read_avail(driver->ch_wcnss);
390 if (r > IN_BUF_SIZE) {
391 if (r < MAX_IN_BUF_SIZE) {
392 pr_err("diag: wcnss packets > %d bytes", r);
393 buf = krealloc(buf, r, GFP_KERNEL);
394 } else {
395 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
396 return;
397 }
398 }
399 if (r > 0) {
400 if (!buf) {
401 pr_err("Out of diagmem for wcnss\n");
402 } else {
403 APPEND_DEBUG('i');
404 smd_read(driver->ch_wcnss, buf, r);
405 APPEND_DEBUG('j');
406 write_ptr_wcnss->length = r;
407 *in_busy_wcnss_ptr = 1;
408 diag_device_write(buf, WCNSS_DATA,
409 write_ptr_wcnss);
410 }
411 }
412 }
413}
414
415void __diag_smd_qdsp_send_req(void)
416{
417 void *buf = NULL;
418 int *in_busy_qdsp_ptr = NULL;
419 struct diag_request *write_ptr_qdsp = NULL;
420
421 if (!driver->in_busy_qdsp_1) {
422 buf = driver->buf_in_qdsp_1;
423 write_ptr_qdsp = driver->write_ptr_qdsp_1;
424 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1);
425 } else if (!driver->in_busy_qdsp_2) {
426 buf = driver->buf_in_qdsp_2;
427 write_ptr_qdsp = driver->write_ptr_qdsp_2;
428 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2);
429 }
430
431 if (driver->chqdsp && buf) {
432 int r = smd_read_avail(driver->chqdsp);
433
434 if (r > IN_BUF_SIZE) {
435 if (r < MAX_IN_BUF_SIZE) {
436 pr_err("diag: SMD sending in "
437 "packets upto %d bytes", r);
438 buf = krealloc(buf, r, GFP_KERNEL);
439 } else {
440 pr_err("diag: SMD sending in "
441 "packets more than %d bytes", MAX_IN_BUF_SIZE);
442 return;
443 }
444 }
445 if (r > 0) {
446 if (!buf)
447 printk(KERN_INFO "Out of diagmem for QDSP\n");
448 else {
449 APPEND_DEBUG('i');
450 smd_read(driver->chqdsp, buf, r);
451 APPEND_DEBUG('j');
452 write_ptr_qdsp->length = r;
453 *in_busy_qdsp_ptr = 1;
454 diag_device_write(buf, QDSP_DATA,
455 write_ptr_qdsp);
456 }
457 }
458 }
459}
460
461static void diag_print_mask_table(void)
462{
463/* Enable this to print mask table when updated */
464#ifdef MASK_DEBUG
465 int first;
466 int last;
467 uint8_t *ptr = driver->msg_masks;
468 int i = 0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700469 pr_info("diag: F3 message mask table\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700470 while (*(uint32_t *)(ptr + 4)) {
471 first = *(uint32_t *)ptr;
472 ptr += 4;
473 last = *(uint32_t *)ptr;
474 ptr += 4;
475 printk(KERN_INFO "SSID %d - %d\n", first, last);
476 for (i = 0 ; i <= last - first ; i++)
477 printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700478 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700479
480 }
481#endif
482}
483
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700484void diag_create_msg_mask_table(void)
485{
486 uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
487
488 CREATE_MSG_MASK_TBL_ROW(0);
489 CREATE_MSG_MASK_TBL_ROW(1);
490 CREATE_MSG_MASK_TBL_ROW(2);
491 CREATE_MSG_MASK_TBL_ROW(3);
492 CREATE_MSG_MASK_TBL_ROW(4);
493 CREATE_MSG_MASK_TBL_ROW(5);
494 CREATE_MSG_MASK_TBL_ROW(6);
495 CREATE_MSG_MASK_TBL_ROW(7);
496 CREATE_MSG_MASK_TBL_ROW(8);
497 CREATE_MSG_MASK_TBL_ROW(9);
498 CREATE_MSG_MASK_TBL_ROW(10);
499 CREATE_MSG_MASK_TBL_ROW(11);
500 CREATE_MSG_MASK_TBL_ROW(12);
501 CREATE_MSG_MASK_TBL_ROW(13);
502 CREATE_MSG_MASK_TBL_ROW(14);
503 CREATE_MSG_MASK_TBL_ROW(15);
504 CREATE_MSG_MASK_TBL_ROW(16);
505 CREATE_MSG_MASK_TBL_ROW(17);
506 CREATE_MSG_MASK_TBL_ROW(18);
507 CREATE_MSG_MASK_TBL_ROW(19);
508 CREATE_MSG_MASK_TBL_ROW(20);
509 CREATE_MSG_MASK_TBL_ROW(21);
510 CREATE_MSG_MASK_TBL_ROW(22);
511}
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700512
513static void diag_set_msg_mask(int rt_mask)
514{
515 int first_ssid, last_ssid, i;
516 uint8_t *parse_ptr, *ptr = driver->msg_masks;
517
518 mutex_lock(&driver->diagchar_mutex);
519 while (*(uint32_t *)(ptr + 4)) {
520 first_ssid = *(uint32_t *)ptr;
521 ptr += 4;
522 last_ssid = *(uint32_t *)ptr;
523 ptr += 4;
524 parse_ptr = ptr;
525 pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
526 for (i = 0; i < last_ssid - first_ssid + 1; i++) {
527 *(int *)parse_ptr = rt_mask;
528 parse_ptr += 4;
529 }
530 ptr += MAX_SSID_PER_RANGE * 4;
531 }
532 mutex_unlock(&driver->diagchar_mutex);
533}
534
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700535static void diag_update_msg_mask(int start, int end , uint8_t *buf)
536{
537 int found = 0;
538 int first;
539 int last;
540 uint8_t *ptr = driver->msg_masks;
541 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
542 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
543
544 mutex_lock(&driver->diagchar_mutex);
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530545
Shalabh Jain321c8b52012-02-22 12:37:06 -0800546 /* First SSID can be zero : So check that last is non-zero */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700547 while (*(uint32_t *)(ptr + 4)) {
548 first = *(uint32_t *)ptr;
549 ptr += 4;
550 last = *(uint32_t *)ptr;
551 ptr += 4;
552 if (start >= first && start <= last) {
553 ptr += (start - first)*4;
554 if (end <= last)
555 if (CHK_OVERFLOW(ptr_buffer_start, ptr,
556 ptr_buffer_end,
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700557 (((end - start)+1)*4))) {
558 pr_debug("diag: update ssid start %d,"
559 " end %d\n", start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700560 memcpy(ptr, buf , ((end - start)+1)*4);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700561 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700562 printk(KERN_CRIT "Not enough"
563 " buffer space for"
564 " MSG_MASK\n");
565 else
566 printk(KERN_INFO "Unable to copy"
567 " mask change\n");
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530568
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700569 found = 1;
570 break;
571 } else {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700572 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700573 }
574 }
575 /* Entry was not found - add new table */
576 if (!found) {
577 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
578 8 + ((end - start) + 1)*4)) {
579 memcpy(ptr, &(start) , 4);
580 ptr += 4;
581 memcpy(ptr, &(end), 4);
582 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700583 pr_debug("diag: adding NEW ssid start %d, end %d\n",
584 start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700585 memcpy(ptr, buf , ((end - start) + 1)*4);
586 } else
587 printk(KERN_CRIT " Not enough buffer"
588 " space for MSG_MASK\n");
589 }
590 mutex_unlock(&driver->diagchar_mutex);
591 diag_print_mask_table();
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530592
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700593}
594
Shalabh Jaina51f2592012-03-08 14:36:35 -0800595void diag_toggle_event_mask(int toggle)
596{
597 uint8_t *ptr = driver->event_masks;
598
599 mutex_lock(&driver->diagchar_mutex);
600 if (toggle)
601 memset(ptr, 0xFF, EVENT_MASK_SIZE);
602 else
603 memset(ptr, 0, EVENT_MASK_SIZE);
604 mutex_unlock(&driver->diagchar_mutex);
605}
606
Shalabh Jain321c8b52012-02-22 12:37:06 -0800607static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608{
609 uint8_t *ptr = driver->event_masks;
610 uint8_t *temp = buf + 2;
611
612 mutex_lock(&driver->diagchar_mutex);
613 if (!toggle)
614 memset(ptr, 0 , EVENT_MASK_SIZE);
615 else
616 if (CHK_OVERFLOW(ptr, ptr,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800617 ptr+EVENT_MASK_SIZE, num_bytes))
618 memcpy(ptr, temp , num_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700619 else
620 printk(KERN_CRIT "Not enough buffer space "
621 "for EVENT_MASK\n");
622 mutex_unlock(&driver->diagchar_mutex);
623}
624
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700625static void diag_disable_log_mask(void)
626{
627 int i = 0;
628 struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
629
630 pr_debug("diag: disable log masks\n");
631 mutex_lock(&driver->diagchar_mutex);
632 for (i = 0; i < MAX_EQUIP_ID; i++) {
633 pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
634 if (!(parse_ptr->equip_id)) /* Reached a null entry */
635 break;
636 memset(driver->log_masks + parse_ptr->index, 0,
637 (parse_ptr->num_items + 7)/8);
638 parse_ptr++;
639 }
640 mutex_unlock(&driver->diagchar_mutex);
641}
642
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700643static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
644{
645 uint8_t *temp = buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700646 int i = 0;
647 unsigned char *ptr_data;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700648 int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700649 struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700650
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700651 pr_debug("diag: received equip id = %d\n", equip_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700652 mutex_lock(&driver->diagchar_mutex);
653 /* Check if we already know index of this equipment ID */
654 for (i = 0; i < MAX_EQUIP_ID; i++) {
655 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
656 offset = ptr->index;
657 break;
658 }
659 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
Shalabh Jain321c8b52012-02-22 12:37:06 -0800660 /* Reached a null entry */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700661 ptr->equip_id = equip_id;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800662 ptr->num_items = num_items;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700663 ptr->index = driver->log_masks_length;
664 offset = driver->log_masks_length;
665 driver->log_masks_length += ((num_items+7)/8);
666 break;
667 }
668 ptr++;
669 }
670 ptr_data = driver->log_masks + offset;
671 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
672 + LOG_MASK_SIZE, (num_items+7)/8))
673 memcpy(ptr_data, temp , (num_items+7)/8);
674 else
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700675 pr_err("diag: Not enough buffer space for LOG_MASK\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700676 mutex_unlock(&driver->diagchar_mutex);
677}
678
679static void diag_update_pkt_buffer(unsigned char *buf)
680{
681 unsigned char *ptr = driver->pkt_buf;
682 unsigned char *temp = buf;
683
684 mutex_lock(&driver->diagchar_mutex);
685 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
686 memcpy(ptr, temp , driver->pkt_length);
687 else
688 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
689 mutex_unlock(&driver->diagchar_mutex);
690}
691
692void diag_update_userspace_clients(unsigned int type)
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 != 0)
699 driver->data_ready[i] |= type;
700 wake_up_interruptible(&driver->wait_q);
701 mutex_unlock(&driver->diagchar_mutex);
702}
703
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700704void diag_update_sleeping_process(int process_id, int data_type)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700705{
706 int i;
707
708 mutex_lock(&driver->diagchar_mutex);
709 for (i = 0; i < driver->num_clients; i++)
710 if (driver->client_map[i].pid == process_id) {
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700711 driver->data_ready[i] |= data_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700712 break;
713 }
714 wake_up_interruptible(&driver->wait_q);
715 mutex_unlock(&driver->diagchar_mutex);
716}
717
718void diag_send_data(struct diag_master_table entry, unsigned char *buf,
719 int len, int type)
720{
721 driver->pkt_length = len;
722 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
723 diag_update_pkt_buffer(buf);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700724 diag_update_sleeping_process(entry.process_id, PKT_TYPE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700725 } else {
726 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700727 if (entry.client_id == MODEM_PROC && driver->ch) {
Shalabh Jain10f5f432012-01-11 11:45:44 +0530728 if (chk_apps_master() &&
Shalabh Jainc9f35092011-07-28 18:36:17 -0700729 (int)(*(char *)buf) == MODE_CMD)
Dixon Petersonff425d12011-12-06 18:12:35 -0800730 if ((int)(*(char *)(buf+1)) ==
731 RESET_ID)
Shalabh Jainc9f35092011-07-28 18:36:17 -0700732 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700733 smd_write(driver->ch, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700734 } else if (entry.client_id == QDSP_PROC &&
735 driver->chqdsp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700736 smd_write(driver->chqdsp, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700737 } else if (entry.client_id == WCNSS_PROC &&
738 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700739 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700740 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700741 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700742 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700743 }
744 }
745}
746
Shalabh Jain321c8b52012-02-22 12:37:06 -0800747void diag_modem_mask_update_fn(struct work_struct *work)
748{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700749 diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
750 ALL_SSID, MODEM_PROC);
751 diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800752 diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
753}
754
755void diag_qdsp_mask_update_fn(struct work_struct *work)
756{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700757 diag_send_msg_mask_update(driver->chqdsp_cntl, ALL_SSID,
758 ALL_SSID, QDSP_PROC);
759 diag_send_log_mask_update(driver->chqdsp_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800760 diag_send_event_mask_update(driver->chqdsp_cntl, diag_event_num_bytes);
761}
762
763void diag_wcnss_mask_update_fn(struct work_struct *work)
764{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700765 diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
766 ALL_SSID, WCNSS_PROC);
767 diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800768 diag_send_event_mask_update(driver->ch_wcnss_cntl,
769 diag_event_num_bytes);
770}
771
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700772void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800773{
774 void *buf = driver->buf_log_mask_update;
775 int header_size = sizeof(struct diag_ctrl_log_mask);
776 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700777 int i, size, wr_size = -ENOMEM, retry_count = 0;
778 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800779
780 for (i = 0; i < MAX_EQUIP_ID; i++) {
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700781 size = (ptr->num_items+7)/8;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800782 /* reached null entry */
783 if ((ptr->equip_id == 0) && (ptr->index == 0))
784 break;
785 driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
786 driver->log_mask->num_items = ptr->num_items;
787 driver->log_mask->data_len = 11 + size;
788 driver->log_mask->stream_id = 1; /* 2, if dual stream */
789 driver->log_mask->status = 3; /* status for valid mask */
790 driver->log_mask->equip_id = ptr->equip_id;
791 driver->log_mask->log_mask_size = size;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700792 /* send only desired update, NOT ALL */
793 if (equip_id == ALL_EQUIP_ID || equip_id ==
794 driver->log_mask->equip_id) {
795 memcpy(buf, driver->log_mask, header_size);
796 memcpy(buf+header_size, driver->log_masks+ptr->index,
797 size);
798 if (ch) {
799 while (retry_count < 3) {
800 spin_lock_irqsave(&diag_cntl_lock,
801 flags);
802 wr_size = smd_write(ch, buf,
803 header_size + size);
804 spin_unlock_irqrestore(&diag_cntl_lock,
805 flags);
806 if (wr_size == -ENOMEM) {
807 retry_count++;
808 usleep(20000);
809 } else
810 break;
811 }
812 if (wr_size != header_size + size)
813 pr_err("diag: log mask update failed"
814 " %d, tried %d", wr_size, header_size + size);
815 else
816 pr_debug("diag: updated log equip ID %d"
817 ",len %d\n", driver->log_mask->equip_id,
818 driver->log_mask->log_mask_size);
819 } else
820 pr_err("diag: ch not valid for log update\n");
821 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800822 ptr++;
823 }
824}
825
826void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
827{
828 void *buf = driver->buf_event_mask_update;
829 int header_size = sizeof(struct diag_ctrl_event_mask);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700830 int wr_size = -ENOMEM, retry_count = 0;
831 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800832
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700833 if (num_bytes == 0) {
834 pr_debug("diag: event mask not set yet, so no update\n");
835 return;
836 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800837 /* send event mask update */
838 driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
839 driver->event_mask->data_len = 7 + num_bytes;
840 driver->event_mask->stream_id = 1; /* 2, if dual stream */
841 driver->event_mask->status = 3; /* status for valid mask */
842 driver->event_mask->event_config = diag_event_config; /* event config */
843 driver->event_mask->event_mask_size = num_bytes;
844 memcpy(buf, driver->event_mask, header_size);
845 memcpy(buf+header_size, driver->event_masks, num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700846 if (ch) {
847 while (retry_count < 3) {
848 spin_lock_irqsave(&diag_cntl_lock, flags);
849 wr_size = smd_write(ch, buf, header_size + num_bytes);
850 spin_unlock_irqrestore(&diag_cntl_lock, flags);
851 if (wr_size == -ENOMEM) {
852 retry_count++;
853 usleep(20000);
854 } else
855 break;
856 }
857 if (wr_size != header_size + num_bytes)
858 pr_err("diag: error writing event mask %d, tried %d\n",
859 wr_size, header_size + num_bytes);
860 } else
861 pr_err("diag: ch not valid for event update\n");
Shalabh Jain321c8b52012-02-22 12:37:06 -0800862}
863
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700864void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
865 int updated_ssid_last, int proc)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800866{
867 void *buf = driver->buf_msg_mask_update;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700868 int first, last, size = -ENOMEM, retry_count = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800869 int header_size = sizeof(struct diag_ctrl_msg_mask);
870 uint8_t *ptr = driver->msg_masks;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700871 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800872
873 while (*(uint32_t *)(ptr + 4)) {
874 first = *(uint32_t *)ptr;
875 ptr += 4;
876 last = *(uint32_t *)ptr;
877 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700878 if ((updated_ssid_first >= first && updated_ssid_last <= last)
879 || (updated_ssid_first == ALL_SSID)) {
880 /* send f3 mask update */
881 driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
882 driver->msg_mask->msg_mask_size = last - first + 1;
883 driver->msg_mask->data_len = 11 +
884 4 * (driver->msg_mask->msg_mask_size);
885 driver->msg_mask->stream_id = 1; /* 2, if dual stream */
886 driver->msg_mask->status = 3; /* status valid mask */
887 driver->msg_mask->msg_mode = 0; /* Legcay mode */
888 driver->msg_mask->ssid_first = first;
889 driver->msg_mask->ssid_last = last;
890 memcpy(buf, driver->msg_mask, header_size);
891 memcpy(buf+header_size, ptr,
892 4 * (driver->msg_mask->msg_mask_size));
893 if (ch) {
894 while (retry_count < 3) {
895 spin_lock_irqsave(&diag_cntl_lock,
896 flags);
897 size = smd_write(ch, buf, header_size +
898 4*(driver->msg_mask->msg_mask_size));
899 spin_unlock_irqrestore(&diag_cntl_lock,
900 flags);
901 if (size == -ENOMEM) {
902 retry_count++;
903 usleep(20000);
904 } else
905 break;
906 }
907 if (size != header_size +
908 4*(driver->msg_mask->msg_mask_size))
909 pr_err("diag: msg mask update fail %d,"
910 " tried %d\n", size,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800911 header_size + 4*(driver->msg_mask->msg_mask_size));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700912 else
913 pr_debug("diag: sending mask update for"
914 " ssid first %d, last %d on PROC %d\n", first, last, proc);
915 } else
916 pr_err("diag: ch invalid msg mask update\n");
917 }
918 ptr += MAX_SSID_PER_RANGE*4;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800919 }
920}
921
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700922static int diag_process_apps_pkt(unsigned char *buf, int len)
923{
924 uint16_t subsys_cmd_code;
925 int subsys_id, ssid_first, ssid_last, ssid_range;
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700926 int packet_type = 1, i, cmd_code, rt_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700927 unsigned char *temp = buf;
928 int data_type;
929#if defined(CONFIG_DIAG_OVER_USB)
930 int payload_length;
931 unsigned char *ptr;
932#endif
933
Shalabh Jain321c8b52012-02-22 12:37:06 -0800934 /* Set log masks */
935 if (*buf == 0x73 && *(int *)(buf+4) == 3) {
936 buf += 8;
937 /* Read Equip ID and pass as first param below*/
938 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
939 diag_update_userspace_clients(LOG_MASKS_TYPE);
940#if defined(CONFIG_DIAG_OVER_USB)
941 if (chk_apps_only()) {
942 driver->apps_rsp_buf[0] = 0x73;
943 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
944 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
945 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
946 for (i = 0; i < payload_length; i++)
947 *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700948 if (driver->ch_cntl)
949 diag_send_log_mask_update(driver->ch_cntl,
950 *(int *)buf);
951 if (driver->chqdsp_cntl)
952 diag_send_log_mask_update(driver->chqdsp_cntl,
953 *(int *)buf);
954 if (driver->ch_wcnss_cntl)
955 diag_send_log_mask_update(driver->ch_wcnss_cntl,
956 *(int *)buf);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800957 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
958 return 0;
959 } else
960 buf = temp;
961#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -0700962 } /* Disable log masks */
963 else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
964 buf += 8;
965 /* Disable mask for each log code */
966 diag_disable_log_mask();
967 diag_update_userspace_clients(LOG_MASKS_TYPE);
968#if defined(CONFIG_DIAG_OVER_USB)
969 if (chk_apps_only()) {
970 driver->apps_rsp_buf[0] = 0x73;
971 driver->apps_rsp_buf[1] = 0x0;
972 driver->apps_rsp_buf[2] = 0x0;
973 driver->apps_rsp_buf[3] = 0x0;
974 *(int *)(driver->apps_rsp_buf + 4) = 0x0;
975 if (driver->ch_cntl)
976 diag_send_log_mask_update(driver->ch_cntl,
977 *(int *)buf);
978 if (driver->chqdsp_cntl)
979 diag_send_log_mask_update(driver->chqdsp_cntl,
980 *(int *)buf);
981 if (driver->ch_wcnss_cntl)
982 diag_send_log_mask_update(driver->ch_wcnss_cntl,
983 *(int *)buf);
984 ENCODE_RSP_AND_SEND(7);
985 return 0;
986 } else
987 buf = temp;
988#endif
989 } /* Set runtime message mask */
Shalabh Jain321c8b52012-02-22 12:37:06 -0800990 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
991 ssid_first = *(uint16_t *)(buf + 2);
992 ssid_last = *(uint16_t *)(buf + 4);
993 ssid_range = 4 * (ssid_last - ssid_first + 1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700994 pr_debug("diag: received mask update for ssid_first = %d,"
995 " ssid_last = %d", ssid_first, ssid_last);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800996 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
997 diag_update_userspace_clients(MSG_MASKS_TYPE);
998#if defined(CONFIG_DIAG_OVER_USB)
999 if (chk_apps_only()) {
1000 for (i = 0; i < 8 + ssid_range; i++)
1001 *(driver->apps_rsp_buf + i) = *(buf+i);
1002 *(driver->apps_rsp_buf + 6) = 0x1;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001003 if (driver->ch_cntl)
1004 diag_send_msg_mask_update(driver->ch_cntl,
1005 ssid_first, ssid_last, MODEM_PROC);
1006 if (driver->chqdsp_cntl)
1007 diag_send_msg_mask_update(driver->chqdsp_cntl,
1008 ssid_first, ssid_last, QDSP_PROC);
1009 if (driver->ch_wcnss_cntl)
1010 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1011 ssid_first, ssid_last, WCNSS_PROC);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001012 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1013 return 0;
1014 } else
1015 buf = temp;
1016#endif
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001017 } /* Set ALL runtime message mask */
1018 else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
1019 rt_mask = *(int *)(buf + 4);
1020 diag_set_msg_mask(rt_mask);
1021 diag_update_userspace_clients(MSG_MASKS_TYPE);
1022#if defined(CONFIG_DIAG_OVER_USB)
1023 if (chk_apps_only()) {
1024 driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
1025 driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
1026 driver->apps_rsp_buf[2] = 1; /* success */
1027 driver->apps_rsp_buf[3] = 0; /* rsvd */
1028 *(int *)(driver->apps_rsp_buf + 4) = rt_mask;
1029 /* send msg mask update to peripheral */
1030 if (driver->ch_cntl)
1031 diag_send_msg_mask_update(driver->ch_cntl,
1032 ALL_SSID, ALL_SSID, MODEM_PROC);
1033 if (driver->chqdsp_cntl)
1034 diag_send_msg_mask_update(driver->chqdsp_cntl,
1035 ALL_SSID, ALL_SSID, QDSP_PROC);
1036 if (driver->ch_wcnss_cntl)
1037 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
1038 ALL_SSID, ALL_SSID, WCNSS_PROC);
1039 ENCODE_RSP_AND_SEND(7);
1040 return 0;
1041 } else
1042 buf = temp;
1043#endif
Shalabh Jain321c8b52012-02-22 12:37:06 -08001044 } else if (*buf == 0x82) { /* event mask change */
1045 buf += 4;
1046 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
1047 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
1048 diag_update_userspace_clients(EVENT_MASKS_TYPE);
1049#if defined(CONFIG_DIAG_OVER_USB)
1050 if (chk_apps_only()) {
1051 driver->apps_rsp_buf[0] = 0x82;
1052 driver->apps_rsp_buf[1] = 0x0;
1053 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1054 *(uint16_t *)(driver->apps_rsp_buf + 4) =
1055 EVENT_LAST_ID + 1;
Shalabh Jaina51f2592012-03-08 14:36:35 -08001056 memcpy(driver->apps_rsp_buf+6, driver->event_masks,
1057 EVENT_LAST_ID/8+1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001058 if (driver->ch_cntl)
1059 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001060 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001061 if (driver->chqdsp_cntl)
1062 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001063 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001064 if (driver->ch_wcnss_cntl)
1065 diag_send_event_mask_update(
1066 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001067 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1068 return 0;
1069 } else
1070 buf = temp;
1071#endif
1072 } else if (*buf == 0x60) {
1073 diag_event_config = *(buf+1);
Shalabh Jaina51f2592012-03-08 14:36:35 -08001074 diag_toggle_event_mask(*(buf+1));
1075 diag_update_userspace_clients(EVENT_MASKS_TYPE);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001076#if defined(CONFIG_DIAG_OVER_USB)
1077 if (chk_apps_only()) {
1078 driver->apps_rsp_buf[0] = 0x60;
1079 driver->apps_rsp_buf[1] = 0x0;
1080 driver->apps_rsp_buf[2] = 0x0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001081 if (driver->ch_cntl)
1082 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001083 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001084 if (driver->chqdsp_cntl)
1085 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -08001086 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001087 if (driver->ch_wcnss_cntl)
1088 diag_send_event_mask_update(
1089 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001090 ENCODE_RSP_AND_SEND(2);
1091 return 0;
1092 }
1093#endif
1094 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001095 /* Check for registered clients and forward packet to apropriate proc */
1096 cmd_code = (int)(*(char *)buf);
1097 temp++;
1098 subsys_id = (int)(*(char *)temp);
1099 temp++;
1100 subsys_cmd_code = *(uint16_t *)temp;
1101 temp += 2;
1102 data_type = APPS_DATA;
1103 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301104 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001105 if (subsys_id != RESET_ID)
1106 data_type = MODEM_DATA;
1107 }
1108
1109 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001110 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001111 entry = driver->table[i];
1112 if (entry.process_id != NO_PROCESS) {
1113 if (entry.cmd_code == cmd_code && entry.subsys_id ==
1114 subsys_id && entry.cmd_code_lo <=
1115 subsys_cmd_code &&
1116 entry.cmd_code_hi >= subsys_cmd_code) {
1117 diag_send_data(entry, buf, len, data_type);
1118 packet_type = 0;
1119 } else if (entry.cmd_code == 255
1120 && cmd_code == 75) {
1121 if (entry.subsys_id ==
1122 subsys_id &&
1123 entry.cmd_code_lo <=
1124 subsys_cmd_code &&
1125 entry.cmd_code_hi >=
1126 subsys_cmd_code) {
1127 diag_send_data(entry, buf, len,
1128 data_type);
1129 packet_type = 0;
1130 }
1131 } else if (entry.cmd_code == 255 &&
1132 entry.subsys_id == 255) {
1133 if (entry.cmd_code_lo <=
1134 cmd_code &&
1135 entry.
1136 cmd_code_hi >= cmd_code) {
1137 diag_send_data(entry, buf, len,
1138 data_type);
1139 packet_type = 0;
1140 }
1141 }
1142 }
1143 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001144#if defined(CONFIG_DIAG_OVER_USB)
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001145 /* Check for Apps Only & get event mask request */
Shalabh Jain321c8b52012-02-22 12:37:06 -08001146 if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001147 driver->apps_rsp_buf[0] = 0x81;
1148 driver->apps_rsp_buf[1] = 0x0;
1149 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1150 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
1151 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
1152 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
1153 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1154 return 0;
1155 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001156 /* Get log ID range & Check for Apps Only */
1157 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001158 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
1159 driver->apps_rsp_buf[0] = 0x73;
1160 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
1161 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
1162 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
1163 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
1164 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
1165 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
1166 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
1167 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
1168 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
1169 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
1170 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
1171 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
1172 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
1173 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
1174 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
1175 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
1176 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
1177 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
1178 ENCODE_RSP_AND_SEND(75);
1179 return 0;
1180 }
1181 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001182 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001183 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
1184 driver->apps_rsp_buf[0] = 0x7d;
1185 driver->apps_rsp_buf[1] = 0x1;
1186 driver->apps_rsp_buf[2] = 0x1;
1187 driver->apps_rsp_buf[3] = 0x0;
1188 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
1189 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
1190 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
1191 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
1192 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
1193 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
1194 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
1195 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
1196 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
1197 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
1198 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
1199 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
1200 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
1201 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
1202 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
1203 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
1204 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
1205 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
1206 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
1207 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
1208 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
1209 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
1210 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
1211 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
1212 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
1213 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
1214 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
1215 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
1216 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
1217 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
1218 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
1219 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
1220 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
1221 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
1222 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
1223 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
1224 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
1225 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
1226 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001227 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
1228 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
1229 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
1230 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
1231 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
1232 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
1233 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
1234 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
1235 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001236 return 0;
1237 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001238 /* Check for Apps Only Respond to Get Subsys Build mask */
1239 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001240 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
1241 ssid_first = *(uint16_t *)(buf + 2);
1242 ssid_last = *(uint16_t *)(buf + 4);
1243 ssid_range = 4 * (ssid_last - ssid_first + 1);
1244 /* frame response */
1245 driver->apps_rsp_buf[0] = 0x7d;
1246 driver->apps_rsp_buf[1] = 0x2;
1247 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
1248 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
1249 driver->apps_rsp_buf[6] = 0x1;
1250 driver->apps_rsp_buf[7] = 0x0;
1251 ptr = driver->apps_rsp_buf + 8;
1252 /* bld time masks */
1253 switch (ssid_first) {
1254 case MSG_SSID_0:
1255 for (i = 0; i < ssid_range; i += 4)
1256 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
1257 break;
1258 case MSG_SSID_1:
1259 for (i = 0; i < ssid_range; i += 4)
1260 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
1261 break;
1262 case MSG_SSID_2:
1263 for (i = 0; i < ssid_range; i += 4)
1264 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
1265 break;
1266 case MSG_SSID_3:
1267 for (i = 0; i < ssid_range; i += 4)
1268 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
1269 break;
1270 case MSG_SSID_4:
1271 for (i = 0; i < ssid_range; i += 4)
1272 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
1273 break;
1274 case MSG_SSID_5:
1275 for (i = 0; i < ssid_range; i += 4)
1276 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
1277 break;
1278 case MSG_SSID_6:
1279 for (i = 0; i < ssid_range; i += 4)
1280 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
1281 break;
1282 case MSG_SSID_7:
1283 for (i = 0; i < ssid_range; i += 4)
1284 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
1285 break;
1286 case MSG_SSID_8:
1287 for (i = 0; i < ssid_range; i += 4)
1288 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
1289 break;
1290 case MSG_SSID_9:
1291 for (i = 0; i < ssid_range; i += 4)
1292 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
1293 break;
1294 case MSG_SSID_10:
1295 for (i = 0; i < ssid_range; i += 4)
1296 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
1297 break;
1298 case MSG_SSID_11:
1299 for (i = 0; i < ssid_range; i += 4)
1300 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
1301 break;
1302 case MSG_SSID_12:
1303 for (i = 0; i < ssid_range; i += 4)
1304 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1305 break;
1306 case MSG_SSID_13:
1307 for (i = 0; i < ssid_range; i += 4)
1308 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1309 break;
1310 case MSG_SSID_14:
1311 for (i = 0; i < ssid_range; i += 4)
1312 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1313 break;
1314 case MSG_SSID_15:
1315 for (i = 0; i < ssid_range; i += 4)
1316 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1317 break;
1318 case MSG_SSID_16:
1319 for (i = 0; i < ssid_range; i += 4)
1320 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1321 break;
1322 case MSG_SSID_17:
1323 for (i = 0; i < ssid_range; i += 4)
1324 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1325 break;
1326 case MSG_SSID_18:
1327 for (i = 0; i < ssid_range; i += 4)
1328 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1329 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001330 case MSG_SSID_19:
1331 for (i = 0; i < ssid_range; i += 4)
1332 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1333 break;
1334 case MSG_SSID_20:
1335 for (i = 0; i < ssid_range; i += 4)
1336 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1337 break;
1338 case MSG_SSID_21:
1339 for (i = 0; i < ssid_range; i += 4)
1340 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1341 break;
1342 case MSG_SSID_22:
1343 for (i = 0; i < ssid_range; i += 4)
1344 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1345 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001346 }
1347 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1348 return 0;
1349 }
1350 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301351 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001352 /* send response back */
1353 driver->apps_rsp_buf[0] = *buf;
1354 ENCODE_RSP_AND_SEND(0);
1355 msleep(5000);
1356 /* call download API */
1357 msm_set_restart_mode(RESTART_DLOAD);
1358 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1359 kernel_restart(NULL);
1360 /* Not required, represents that command isnt sent to modem */
1361 return 0;
1362 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001363 /* Check for polling for Apps only DIAG */
1364 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1365 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001366 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001367 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001368 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001369 for (i = 0; i < 3; i++)
1370 driver->apps_rsp_buf[i] = *(buf+i);
1371 for (i = 0; i < 13; i++)
1372 driver->apps_rsp_buf[i+3] = 0;
1373
1374 ENCODE_RSP_AND_SEND(15);
1375 return 0;
1376 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001377 }
1378 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001379 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001380 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001381 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001382 for (i = 0; i < 55; i++)
1383 driver->apps_rsp_buf[i] = 0;
1384
1385 ENCODE_RSP_AND_SEND(54);
1386 return 0;
1387 }
1388 /* respond to 0x7c command */
1389 else if (*buf == 0x7c) {
1390 driver->apps_rsp_buf[0] = 0x7c;
1391 for (i = 1; i < 8; i++)
1392 driver->apps_rsp_buf[i] = 0;
1393 /* Tools ID for APQ 8060 */
1394 *(int *)(driver->apps_rsp_buf + 8) =
1395 chk_config_get_id();
1396 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1397 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1398 ENCODE_RSP_AND_SEND(13);
1399 return 0;
1400 }
1401 }
1402#endif
1403 return packet_type;
1404}
1405
1406#ifdef CONFIG_DIAG_OVER_USB
1407void diag_send_error_rsp(int index)
1408{
1409 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301410
1411 if (index > 490) {
1412 pr_err("diag: error response too huge, aborting\n");
1413 return;
1414 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001415 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1416 for (i = 0; i < index; i++)
1417 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1418 ENCODE_RSP_AND_SEND(index - 3);
1419}
1420#else
1421static inline void diag_send_error_rsp(int index) {}
1422#endif
1423
1424void diag_process_hdlc(void *data, unsigned len)
1425{
1426 struct diag_hdlc_decode_type hdlc;
1427 int ret, type = 0;
1428 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1429 hdlc.dest_ptr = driver->hdlc_buf;
1430 hdlc.dest_size = USB_MAX_OUT_BUF;
1431 hdlc.src_ptr = data;
1432 hdlc.src_size = len;
1433 hdlc.src_idx = 0;
1434 hdlc.dest_idx = 0;
1435 hdlc.escaping = 0;
1436
1437 ret = diag_hdlc_decode(&hdlc);
1438
1439 if (ret)
1440 type = diag_process_apps_pkt(driver->hdlc_buf,
1441 hdlc.dest_idx - 3);
1442 else if (driver->debug_flag) {
1443 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1444 " errors or partial packet received, packet"
1445 " length = %d\n", len);
1446 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1447 DUMP_PREFIX_ADDRESS, data, len, 1);
1448 driver->debug_flag = 0;
1449 }
1450 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001451 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001452 diag_send_error_rsp(hdlc.dest_idx);
1453 type = 0;
1454 }
1455 /* implies this packet is NOT meant for apps */
1456 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001457 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001458 diag_send_error_rsp(hdlc.dest_idx);
1459 } else { /* APQ 8060, Let Q6 respond */
1460 if (driver->chqdsp)
1461 smd_write(driver->chqdsp, driver->hdlc_buf,
1462 hdlc.dest_idx - 3);
1463 }
1464 type = 0;
1465 }
1466
1467#ifdef DIAG_DEBUG
1468 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1469 for (i = 0; i < hdlc.dest_idx; i++)
1470 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1471 driver->hdlc_buf)+i));
1472#endif /* DIAG DEBUG */
1473 /* ignore 2 bytes for CRC, one for 7E and send */
1474 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1475 APPEND_DEBUG('g');
1476 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1477 APPEND_DEBUG('h');
1478#ifdef DIAG_DEBUG
1479 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1480 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1481 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1482#endif /* DIAG DEBUG */
1483 }
1484}
1485
1486#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001487/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1488#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001489#define N_LEGACY_READ 1
1490
1491int diagfwd_connect(void)
1492{
1493 int err;
1494
1495 printk(KERN_DEBUG "diag: USB connected\n");
1496 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1497 N_LEGACY_READ);
1498 if (err)
1499 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1500
1501 driver->usb_connected = 1;
1502 driver->in_busy_1 = 0;
1503 driver->in_busy_2 = 0;
1504 driver->in_busy_qdsp_1 = 0;
1505 driver->in_busy_qdsp_2 = 0;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301506 driver->in_busy_wcnss_1 = 0;
1507 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001508
1509 /* Poll SMD channels to check for data*/
1510 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1511 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1512 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001513 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001514 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1515 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1516 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001517 /* Poll USB channel to check for data*/
1518 queue_work(driver->diag_wq, &(driver->diag_read_work));
1519#ifdef CONFIG_DIAG_SDIO_PIPE
1520 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1521 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1522 diagfwd_connect_sdio();
1523 else
1524 printk(KERN_INFO "diag: No USB MDM ch");
1525 }
1526#endif
1527 return 0;
1528}
1529
1530int diagfwd_disconnect(void)
1531{
1532 printk(KERN_DEBUG "diag: USB disconnected\n");
1533 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001534 driver->debug_flag = 1;
1535 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001536 if (driver->logging_mode == USB_MODE) {
1537 driver->in_busy_1 = 1;
1538 driver->in_busy_2 = 1;
1539 driver->in_busy_qdsp_1 = 1;
1540 driver->in_busy_qdsp_2 = 1;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301541 driver->in_busy_wcnss_1 = 1;
1542 driver->in_busy_wcnss_2 = 1;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001543 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001544#ifdef CONFIG_DIAG_SDIO_PIPE
1545 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1546 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1547 diagfwd_disconnect_sdio();
1548#endif
1549 /* TBD - notify and flow control SMD */
1550 return 0;
1551}
1552
1553int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1554{
1555 unsigned char *buf = diag_write_ptr->buf;
1556 /*Determine if the write complete is for data from modem/apps/q6 */
1557 /* Need a context variable here instead */
1558 if (buf == (void *)driver->buf_in_1) {
1559 driver->in_busy_1 = 0;
1560 APPEND_DEBUG('o');
1561 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1562 } else if (buf == (void *)driver->buf_in_2) {
1563 driver->in_busy_2 = 0;
1564 APPEND_DEBUG('O');
1565 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1566 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1567 driver->in_busy_qdsp_1 = 0;
1568 APPEND_DEBUG('p');
1569 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1570 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1571 driver->in_busy_qdsp_2 = 0;
1572 APPEND_DEBUG('P');
1573 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
Ashay Jaiswal29620122012-03-21 12:02:36 +05301574 } else if (buf == driver->buf_in_wcnss_1) {
1575 driver->in_busy_wcnss_1 = 0;
1576 APPEND_DEBUG('r');
1577 queue_work(driver->diag_wq,
1578 &(driver->diag_read_smd_wcnss_work));
1579 } else if (buf == driver->buf_in_wcnss_2) {
1580 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001581 APPEND_DEBUG('R');
1582 queue_work(driver->diag_wq,
1583 &(driver->diag_read_smd_wcnss_work));
1584 }
1585#ifdef CONFIG_DIAG_SDIO_PIPE
1586 else if (buf == (void *)driver->buf_in_sdio)
1587 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001588 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001589 diagfwd_write_complete_sdio();
1590 else
1591 pr_err("diag: Incorrect buffer pointer while WRITE");
1592#endif
1593 else {
1594 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1595 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1596 POOL_TYPE_WRITE_STRUCT);
1597 APPEND_DEBUG('q');
1598 }
1599 return 0;
1600}
1601
1602int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1603{
1604 int status = diag_read_ptr->status;
1605 unsigned char *buf = diag_read_ptr->buf;
1606
1607 /* Determine if the read complete is for data on legacy/mdm ch */
1608 if (buf == (void *)driver->usb_buf_out) {
1609 driver->read_len_legacy = diag_read_ptr->actual;
1610 APPEND_DEBUG('s');
1611#ifdef DIAG_DEBUG
1612 printk(KERN_INFO "read data from USB, pkt length %d",
1613 diag_read_ptr->actual);
1614 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1615 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1616 diag_read_ptr->actual, 1);
1617#endif /* DIAG DEBUG */
1618 if (driver->logging_mode == USB_MODE) {
1619 if (status != -ECONNRESET && status != -ESHUTDOWN)
1620 queue_work(driver->diag_wq,
1621 &(driver->diag_proc_hdlc_work));
1622 else
1623 queue_work(driver->diag_wq,
1624 &(driver->diag_read_work));
1625 }
1626 }
1627#ifdef CONFIG_DIAG_SDIO_PIPE
1628 else if (buf == (void *)driver->usb_buf_mdm_out) {
1629 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001630 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001631 driver->read_len_mdm = diag_read_ptr->actual;
1632 diagfwd_read_complete_sdio();
1633 } else
1634 pr_err("diag: Incorrect buffer pointer while READ");
1635 }
1636#endif
1637 else
1638 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1639
1640 return 0;
1641}
1642
1643void diag_read_work_fn(struct work_struct *work)
1644{
1645 APPEND_DEBUG('d');
1646 driver->usb_read_ptr->buf = driver->usb_buf_out;
1647 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1648 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1649 APPEND_DEBUG('e');
1650}
1651
1652void diag_process_hdlc_fn(struct work_struct *work)
1653{
1654 APPEND_DEBUG('D');
1655 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1656 diag_read_work_fn(work);
1657 APPEND_DEBUG('E');
1658}
1659
1660void diag_usb_legacy_notifier(void *priv, unsigned event,
1661 struct diag_request *d_req)
1662{
1663 switch (event) {
1664 case USB_DIAG_CONNECT:
1665 diagfwd_connect();
1666 break;
1667 case USB_DIAG_DISCONNECT:
1668 diagfwd_disconnect();
1669 break;
1670 case USB_DIAG_READ_DONE:
1671 diagfwd_read_complete(d_req);
1672 break;
1673 case USB_DIAG_WRITE_DONE:
1674 diagfwd_write_complete(d_req);
1675 break;
1676 default:
1677 printk(KERN_ERR "Unknown event from USB diag\n");
1678 break;
1679 }
1680}
1681
1682#endif /* DIAG OVER USB */
1683
1684static void diag_smd_notify(void *ctxt, unsigned event)
1685{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001686 if (event == SMD_EVENT_CLOSE) {
1687 pr_info("diag: clean modem registration\n");
1688 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001689 driver->ch = 0;
1690 return;
1691 } else if (event == SMD_EVENT_OPEN) {
1692 driver->ch = ch_temp;
1693 }
1694 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001695}
1696
1697#if defined(CONFIG_MSM_N_WAY_SMD)
1698static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1699{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001700 if (event == SMD_EVENT_CLOSE) {
1701 pr_info("diag: clean lpass registration\n");
1702 diag_clear_reg(QDSP_PROC);
1703 driver->chqdsp = 0;
1704 return;
1705 } else if (event == SMD_EVENT_OPEN) {
1706 driver->chqdsp = chqdsp_temp;
1707 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001708 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1709}
1710#endif
1711
1712static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1713{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001714 if (event == SMD_EVENT_CLOSE) {
1715 pr_info("diag: clean wcnss registration\n");
1716 diag_clear_reg(WCNSS_PROC);
1717 driver->ch_wcnss = 0;
1718 return;
1719 } else if (event == SMD_EVENT_OPEN) {
1720 driver->ch_wcnss = ch_wcnss_temp;
1721 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001722 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1723}
1724
1725static int diag_smd_probe(struct platform_device *pdev)
1726{
1727 int r = 0;
1728
Shalabh Jaineefee052011-11-08 23:46:03 -08001729 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001730 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001731 ch_temp = driver->ch;
1732 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001733#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001734 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001735 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1736 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001737 chqdsp_temp = driver->chqdsp;
1738 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001739#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001740 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001741 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1742 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001743 ch_wcnss_temp = driver->ch_wcnss;
1744 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001745 pm_runtime_set_active(&pdev->dev);
1746 pm_runtime_enable(&pdev->dev);
1747 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1748
1749 return 0;
1750}
1751
1752static int diagfwd_runtime_suspend(struct device *dev)
1753{
1754 dev_dbg(dev, "pm_runtime: suspending...\n");
1755 return 0;
1756}
1757
1758static int diagfwd_runtime_resume(struct device *dev)
1759{
1760 dev_dbg(dev, "pm_runtime: resuming...\n");
1761 return 0;
1762}
1763
1764static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1765 .runtime_suspend = diagfwd_runtime_suspend,
1766 .runtime_resume = diagfwd_runtime_resume,
1767};
1768
1769static struct platform_driver msm_smd_ch1_driver = {
1770
1771 .probe = diag_smd_probe,
1772 .driver = {
1773 .name = "DIAG",
1774 .owner = THIS_MODULE,
1775 .pm = &diagfwd_dev_pm_ops,
1776 },
1777};
1778
1779static struct platform_driver diag_smd_lite_driver = {
1780
1781 .probe = diag_smd_probe,
1782 .driver = {
1783 .name = "APPS_RIVA_DATA",
1784 .owner = THIS_MODULE,
1785 .pm = &diagfwd_dev_pm_ops,
1786 },
1787};
1788
1789void diagfwd_init(void)
1790{
1791 diag_debug_buf_idx = 0;
1792 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001793 driver->use_device_tree = has_device_tree();
Shalabh Jainb6eda0e2012-04-18 16:39:52 -07001794 spin_lock_init(&diag_cntl_lock);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001795
1796 if (driver->event_mask == NULL) {
1797 driver->event_mask = kzalloc(sizeof(
1798 struct diag_ctrl_event_mask), GFP_KERNEL);
1799 if (driver->event_mask == NULL)
1800 goto err;
1801 }
1802 if (driver->msg_mask == NULL) {
1803 driver->msg_mask = kzalloc(sizeof(
1804 struct diag_ctrl_msg_mask), GFP_KERNEL);
1805 if (driver->msg_mask == NULL)
1806 goto err;
1807 }
1808 if (driver->log_mask == NULL) {
1809 driver->log_mask = kzalloc(sizeof(
1810 struct diag_ctrl_log_mask), GFP_KERNEL);
1811 if (driver->log_mask == NULL)
1812 goto err;
1813 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001814 if (driver->buf_in_1 == NULL) {
1815 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1816 if (driver->buf_in_1 == NULL)
1817 goto err;
1818 }
1819 if (driver->buf_in_2 == NULL) {
1820 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1821 if (driver->buf_in_2 == NULL)
1822 goto err;
1823 }
1824 if (driver->buf_in_qdsp_1 == NULL) {
1825 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1826 if (driver->buf_in_qdsp_1 == NULL)
1827 goto err;
1828 }
1829 if (driver->buf_in_qdsp_2 == NULL) {
1830 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1831 if (driver->buf_in_qdsp_2 == NULL)
1832 goto err;
1833 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301834 if (driver->buf_in_wcnss_1 == NULL) {
1835 driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1836 if (driver->buf_in_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001837 goto err;
1838 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301839 if (driver->buf_in_wcnss_2 == NULL) {
1840 driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1841 if (driver->buf_in_wcnss_2 == NULL)
1842 goto err;
1843 }
1844
Shalabh Jain321c8b52012-02-22 12:37:06 -08001845 if (driver->buf_msg_mask_update == NULL) {
1846 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1847 GFP_KERNEL);
1848 if (driver->buf_msg_mask_update == NULL)
1849 goto err;
1850 }
1851 if (driver->buf_log_mask_update == NULL) {
1852 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1853 GFP_KERNEL);
1854 if (driver->buf_log_mask_update == NULL)
1855 goto err;
1856 }
1857 if (driver->buf_event_mask_update == NULL) {
1858 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1859 GFP_KERNEL);
1860 if (driver->buf_event_mask_update == NULL)
1861 goto err;
1862 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001863 if (driver->usb_buf_out == NULL &&
1864 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1865 GFP_KERNEL)) == NULL)
1866 goto err;
1867 if (driver->hdlc_buf == NULL
1868 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1869 goto err;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001870 if (driver->user_space_data == NULL)
1871 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1872 if (driver->user_space_data == NULL)
1873 goto err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001874 if (driver->msg_masks == NULL
1875 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1876 GFP_KERNEL)) == NULL)
1877 goto err;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001878 diag_create_msg_mask_table();
Shalabh Jain6e4771e2012-04-17 18:27:54 -07001879 diag_event_num_bytes = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001880 if (driver->log_masks == NULL &&
1881 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1882 goto err;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -07001883 driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001884 if (driver->event_masks == NULL &&
1885 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1886 GFP_KERNEL)) == NULL)
1887 goto err;
1888 if (driver->client_map == NULL &&
1889 (driver->client_map = kzalloc
1890 ((driver->num_clients) * sizeof(struct diag_client_map),
1891 GFP_KERNEL)) == NULL)
1892 goto err;
1893 if (driver->buf_tbl == NULL)
1894 driver->buf_tbl = kzalloc(buf_tbl_size *
1895 sizeof(struct diag_write_device), GFP_KERNEL);
1896 if (driver->buf_tbl == NULL)
1897 goto err;
1898 if (driver->data_ready == NULL &&
1899 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1900 , GFP_KERNEL)) == NULL)
1901 goto err;
1902 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001903 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001904 sizeof(struct diag_master_table),
1905 GFP_KERNEL)) == NULL)
1906 goto err;
1907 if (driver->write_ptr_1 == NULL) {
1908 driver->write_ptr_1 = kzalloc(
1909 sizeof(struct diag_request), GFP_KERNEL);
1910 if (driver->write_ptr_1 == NULL)
1911 goto err;
1912 }
1913 if (driver->write_ptr_2 == NULL) {
1914 driver->write_ptr_2 = kzalloc(
1915 sizeof(struct diag_request), GFP_KERNEL);
1916 if (driver->write_ptr_2 == NULL)
1917 goto err;
1918 }
1919 if (driver->write_ptr_qdsp_1 == NULL) {
1920 driver->write_ptr_qdsp_1 = kzalloc(
1921 sizeof(struct diag_request), GFP_KERNEL);
1922 if (driver->write_ptr_qdsp_1 == NULL)
1923 goto err;
1924 }
1925 if (driver->write_ptr_qdsp_2 == NULL) {
1926 driver->write_ptr_qdsp_2 = kzalloc(
1927 sizeof(struct diag_request), GFP_KERNEL);
1928 if (driver->write_ptr_qdsp_2 == NULL)
1929 goto err;
1930 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301931 if (driver->write_ptr_wcnss_1 == NULL) {
1932 driver->write_ptr_wcnss_1 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001933 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301934 if (driver->write_ptr_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001935 goto err;
1936 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301937 if (driver->write_ptr_wcnss_2 == NULL) {
1938 driver->write_ptr_wcnss_2 = kzalloc(
1939 sizeof(struct diag_request), GFP_KERNEL);
1940 if (driver->write_ptr_wcnss_2 == NULL)
1941 goto err;
1942 }
1943
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001944 if (driver->usb_read_ptr == NULL) {
1945 driver->usb_read_ptr = kzalloc(
1946 sizeof(struct diag_request), GFP_KERNEL);
1947 if (driver->usb_read_ptr == NULL)
1948 goto err;
1949 }
1950 if (driver->pkt_buf == NULL &&
1951 (driver->pkt_buf = kzalloc(PKT_SIZE,
1952 GFP_KERNEL)) == NULL)
1953 goto err;
1954 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001955 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001956 if (driver->apps_rsp_buf == NULL)
1957 goto err;
1958 }
1959 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1960#ifdef CONFIG_DIAG_OVER_USB
1961 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1962 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001963 INIT_WORK(&(driver->diag_modem_mask_update_work),
1964 diag_modem_mask_update_fn);
1965 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
1966 diag_qdsp_mask_update_fn);
1967 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
1968 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001969 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
1970 diag_usb_legacy_notifier);
1971 if (IS_ERR(driver->legacy_ch)) {
1972 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
1973 goto err;
1974 }
1975#endif
1976 platform_driver_register(&msm_smd_ch1_driver);
1977 platform_driver_register(&diag_smd_lite_driver);
1978
1979 return;
1980err:
1981 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08001982 kfree(driver->event_mask);
1983 kfree(driver->log_mask);
1984 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001985 kfree(driver->buf_in_1);
1986 kfree(driver->buf_in_2);
1987 kfree(driver->buf_in_qdsp_1);
1988 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301989 kfree(driver->buf_in_wcnss_1);
1990 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001991 kfree(driver->buf_msg_mask_update);
1992 kfree(driver->buf_log_mask_update);
1993 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001994 kfree(driver->usb_buf_out);
1995 kfree(driver->hdlc_buf);
1996 kfree(driver->msg_masks);
1997 kfree(driver->log_masks);
1998 kfree(driver->event_masks);
1999 kfree(driver->client_map);
2000 kfree(driver->buf_tbl);
2001 kfree(driver->data_ready);
2002 kfree(driver->table);
2003 kfree(driver->pkt_buf);
2004 kfree(driver->write_ptr_1);
2005 kfree(driver->write_ptr_2);
2006 kfree(driver->write_ptr_qdsp_1);
2007 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302008 kfree(driver->write_ptr_wcnss_1);
2009 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002010 kfree(driver->usb_read_ptr);
2011 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002012 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002013 if (driver->diag_wq)
2014 destroy_workqueue(driver->diag_wq);
2015}
2016
2017void diagfwd_exit(void)
2018{
2019 smd_close(driver->ch);
2020 smd_close(driver->chqdsp);
2021 smd_close(driver->ch_wcnss);
2022 driver->ch = 0; /* SMD can make this NULL */
2023 driver->chqdsp = 0;
2024 driver->ch_wcnss = 0;
2025#ifdef CONFIG_DIAG_OVER_USB
2026 if (driver->usb_connected)
2027 usb_diag_free_req(driver->legacy_ch);
2028 usb_diag_close(driver->legacy_ch);
2029#endif
2030 platform_driver_unregister(&msm_smd_ch1_driver);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -07002031 platform_driver_unregister(&msm_diag_dci_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002032 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002033 kfree(driver->event_mask);
2034 kfree(driver->log_mask);
2035 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002036 kfree(driver->buf_in_1);
2037 kfree(driver->buf_in_2);
2038 kfree(driver->buf_in_qdsp_1);
2039 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302040 kfree(driver->buf_in_wcnss_1);
2041 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08002042 kfree(driver->buf_msg_mask_update);
2043 kfree(driver->buf_log_mask_update);
2044 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002045 kfree(driver->usb_buf_out);
2046 kfree(driver->hdlc_buf);
2047 kfree(driver->msg_masks);
2048 kfree(driver->log_masks);
2049 kfree(driver->event_masks);
2050 kfree(driver->client_map);
2051 kfree(driver->buf_tbl);
2052 kfree(driver->data_ready);
2053 kfree(driver->table);
2054 kfree(driver->pkt_buf);
2055 kfree(driver->write_ptr_1);
2056 kfree(driver->write_ptr_2);
2057 kfree(driver->write_ptr_qdsp_1);
2058 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05302059 kfree(driver->write_ptr_wcnss_1);
2060 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002061 kfree(driver->usb_read_ptr);
2062 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07002063 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002064 destroy_workqueue(driver->diag_wq);
2065}