blob: 77d84fd2859f084d4f8aa87743761ab9d7b42b1d [file] [log] [blame]
Dixon Peterson32e70bb2011-12-16 13:26:45 -08001/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070012#include <linux/slab.h>
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/err.h>
17#include <linux/platform_device.h>
18#include <linux/sched.h>
19#include <linux/workqueue.h>
20#include <linux/pm_runtime.h>
21#include <linux/diagchar.h>
22#include <linux/delay.h>
23#include <linux/reboot.h>
Dixon Petersonb4618a42012-02-29 18:56:31 -080024#include <linux/of.h>
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070025#include <linux/spinlock.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070026#ifdef CONFIG_DIAG_OVER_USB
27#include <mach/usbdiag.h>
28#endif
29#include <mach/msm_smd.h>
30#include <mach/socinfo.h>
31#include <mach/restart.h>
32#include "diagmem.h"
33#include "diagchar.h"
34#include "diagfwd.h"
35#include "diagfwd_cntl.h"
36#include "diagchar_hdlc.h"
37#ifdef CONFIG_DIAG_SDIO_PIPE
38#include "diagfwd_sdio.h"
39#endif
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070040#define MODE_CMD 41
41#define RESET_ID 2
42#define ALL_EQUIP_ID 100
43#define ALL_SSID -1
44#define MAX_SSID_PER_RANGE 100
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070045
46int diag_debug_buf_idx;
47unsigned char diag_debug_buf[1024];
48static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
49struct diag_master_table entry;
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -080050smd_channel_t *ch_temp, *chqdsp_temp, *ch_wcnss_temp;
Shalabh Jain321c8b52012-02-22 12:37:06 -080051int diag_event_num_bytes;
52int diag_event_config;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070053struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
54struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
Shalabh Jain321c8b52012-02-22 12:37:06 -080055struct mask_info {
56 int equip_id;
57 int num_items;
58 int index;
59};
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070060spinlock_t diag_cntl_lock;
61
62#define CREATE_MSG_MASK_TBL_ROW(XX) \
63do { \
64 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX; \
65 msg_mask_tbl_ptr += 4; \
66 *(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST; \
67 msg_mask_tbl_ptr += 4; \
68 /* increment by MAX_SSID_PER_RANGE cells */ \
69 msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int); \
70} while (0)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070071
72#define ENCODE_RSP_AND_SEND(buf_length) \
73do { \
74 send.state = DIAG_STATE_START; \
75 send.pkt = driver->apps_rsp_buf; \
76 send.last = (void *)(driver->apps_rsp_buf + buf_length); \
77 send.terminate = 1; \
78 if (!driver->in_busy_1) { \
79 enc.dest = driver->buf_in_1; \
Shalabh Jain321c8b52012-02-22 12:37:06 -080080 enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);\
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070081 diag_hdlc_encode(&send, &enc); \
82 driver->write_ptr_1->buf = driver->buf_in_1; \
83 driver->write_ptr_1->length = (int)(enc.dest - \
84 (void *)(driver->buf_in_1)); \
Shalabh Jain3893bf92011-09-18 18:37:16 -070085 driver->in_busy_1 = 1; \
Shalabh Jain69890aa2011-10-10 12:59:16 -070086 diag_device_write(driver->buf_in_1, MODEM_DATA, \
87 driver->write_ptr_1); \
Shalabh Jain321c8b52012-02-22 12:37:06 -080088 memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE); \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070089 } \
90} while (0)
91
92#define CHK_OVERFLOW(bufStart, start, end, length) \
93((bufStart <= start) && (end - start >= length)) ? 1 : 0
94
Dixon Petersonb4618a42012-02-29 18:56:31 -080095/* Determine if this device uses a device tree */
96#ifdef CONFIG_OF
97static int has_device_tree(void)
98{
99 struct device_node *node;
100
101 node = of_find_node_by_path("/");
102 if (node) {
103 of_node_put(node);
104 return 1;
105 }
106 return 0;
107}
108#else
109static int has_device_tree(void)
110{
111 return 0;
112}
113#endif
114
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700115int chk_config_get_id(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700116{
Shalabh Jain482bf122011-12-06 03:54:47 -0800117 /* For all Fusion targets, Modem will always be present */
118 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
119 return 0;
120
Dixon Petersonb4618a42012-02-29 18:56:31 -0800121 if (driver->use_device_tree) {
122 if (machine_is_copper())
123 return MSM8974_TOOLS_ID;
124 else
125 return 0;
126 } else {
127 switch (socinfo_get_msm_cpu()) {
128 case MSM_CPU_8X60:
129 return APQ8060_TOOLS_ID;
130 case MSM_CPU_8960:
131 return AO8960_TOOLS_ID;
132 case MSM_CPU_8064:
133 return APQ8064_TOOLS_ID;
134 case MSM_CPU_8930:
135 return MSM8930_TOOLS_ID;
136 case MSM_CPU_COPPER:
137 return MSM8974_TOOLS_ID;
138 case MSM_CPU_8625:
139 return MSM8625_TOOLS_ID;
140 default:
141 return 0;
142 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700143 }
144}
145
146/*
Shalabh Jain321c8b52012-02-22 12:37:06 -0800147 * This will return TRUE for targets which support apps only mode and hence SSR.
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700148 * This applies to 8960 and newer targets.
149 */
150int chk_apps_only(void)
151{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800152 if (driver->use_device_tree)
153 return 1;
154
155 switch (socinfo_get_msm_cpu()) {
156 case MSM_CPU_8960:
157 case MSM_CPU_8064:
158 case MSM_CPU_8930:
159 case MSM_CPU_8627:
160 case MSM_CPU_9615:
161 case MSM_CPU_COPPER:
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700162 return 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700163 default:
164 return 0;
165 }
166}
167
Shalabh Jain10f5f432012-01-11 11:45:44 +0530168/*
169 * This will return TRUE for targets which support apps as master.
170 * Thus, SW DLOAD and Mode Reset are supported on apps processor.
171 * This applies to 8960 and newer targets.
172 */
173int chk_apps_master(void)
174{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800175 if (driver->use_device_tree)
176 return 1;
177 else if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615() ||
178 cpu_is_apq8064() || cpu_is_msm8627())
179 return 1;
180 else
181 return 0;
182}
183
184inline int chk_polling_response(void)
185{
186 if (!(driver->polling_reg_flag) && chk_apps_master())
187 /*
188 * If the apps processor is master and no other processor
189 * has registered to respond for polling
190 */
191 return 1;
192 else if (!(driver->ch) && !(chk_apps_master()))
193 /*
194 * If the apps processor is not the master and the modem
195 * is not up
196 */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530197 return 1;
198 else
199 return 0;
200}
201
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700202void __diag_smd_send_req(void)
203{
204 void *buf = NULL;
205 int *in_busy_ptr = NULL;
206 struct diag_request *write_ptr_modem = NULL;
207
208 if (!driver->in_busy_1) {
209 buf = driver->buf_in_1;
210 write_ptr_modem = driver->write_ptr_1;
211 in_busy_ptr = &(driver->in_busy_1);
212 } else if (!driver->in_busy_2) {
213 buf = driver->buf_in_2;
214 write_ptr_modem = driver->write_ptr_2;
215 in_busy_ptr = &(driver->in_busy_2);
216 }
217
218 if (driver->ch && buf) {
219 int r = smd_read_avail(driver->ch);
220
221 if (r > IN_BUF_SIZE) {
222 if (r < MAX_IN_BUF_SIZE) {
223 pr_err("diag: SMD sending in "
224 "packets upto %d bytes", r);
225 buf = krealloc(buf, r, GFP_KERNEL);
226 } else {
227 pr_err("diag: SMD sending in "
228 "packets more than %d bytes", MAX_IN_BUF_SIZE);
229 return;
230 }
231 }
232 if (r > 0) {
233 if (!buf)
234 pr_info("Out of diagmem for Modem\n");
235 else {
236 APPEND_DEBUG('i');
237 smd_read(driver->ch, buf, r);
238 APPEND_DEBUG('j');
239 write_ptr_modem->length = r;
240 *in_busy_ptr = 1;
241 diag_device_write(buf, MODEM_DATA,
242 write_ptr_modem);
243 }
244 }
245 }
246}
247
248int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr)
249{
250 int i, err = 0;
251
252 if (driver->logging_mode == MEMORY_DEVICE_MODE) {
253 if (proc_num == APPS_DATA) {
254 for (i = 0; i < driver->poolsize_write_struct; i++)
255 if (driver->buf_tbl[i].length == 0) {
256 driver->buf_tbl[i].buf = buf;
257 driver->buf_tbl[i].length =
258 driver->used;
259#ifdef DIAG_DEBUG
260 pr_debug("diag: ENQUEUE buf ptr"
261 " and length is %x , %d\n",
262 (unsigned int)(driver->buf_
263 tbl[i].buf), driver->buf_tbl[i].length);
264#endif
265 break;
266 }
267 }
268 for (i = 0; i < driver->num_clients; i++)
269 if (driver->client_map[i].pid ==
270 driver->logging_process_id)
271 break;
272 if (i < driver->num_clients) {
Shalabh Jain69890aa2011-10-10 12:59:16 -0700273 driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700274 wake_up_interruptible(&driver->wait_q);
275 } else
276 return -EINVAL;
277 } else if (driver->logging_mode == NO_LOGGING_MODE) {
278 if (proc_num == MODEM_DATA) {
279 driver->in_busy_1 = 0;
280 driver->in_busy_2 = 0;
281 queue_work(driver->diag_wq, &(driver->
282 diag_read_smd_work));
283 } else if (proc_num == QDSP_DATA) {
284 driver->in_busy_qdsp_1 = 0;
285 driver->in_busy_qdsp_2 = 0;
286 queue_work(driver->diag_wq, &(driver->
287 diag_read_smd_qdsp_work));
288 } else if (proc_num == WCNSS_DATA) {
Ashay Jaiswal29620122012-03-21 12:02:36 +0530289 driver->in_busy_wcnss_1 = 0;
290 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700291 queue_work(driver->diag_wq, &(driver->
292 diag_read_smd_wcnss_work));
293 }
Shalabh Jain482bf122011-12-06 03:54:47 -0800294#ifdef CONFIG_DIAG_SDIO_PIPE
295 else if (proc_num == SDIO_DATA) {
296 driver->in_busy_sdio = 0;
297 queue_work(driver->diag_sdio_wq,
298 &(driver->diag_read_sdio_work));
299 }
300#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700301 err = -1;
302 }
303#ifdef CONFIG_DIAG_OVER_USB
304 else if (driver->logging_mode == USB_MODE) {
305 if (proc_num == APPS_DATA) {
306 driver->write_ptr_svc = (struct diag_request *)
307 (diagmem_alloc(driver, sizeof(struct diag_request),
308 POOL_TYPE_WRITE_STRUCT));
309 if (driver->write_ptr_svc) {
310 driver->write_ptr_svc->length = driver->used;
311 driver->write_ptr_svc->buf = buf;
312 err = usb_diag_write(driver->legacy_ch,
313 driver->write_ptr_svc);
314 } else
315 err = -1;
316 } else if (proc_num == MODEM_DATA) {
317 write_ptr->buf = buf;
318#ifdef DIAG_DEBUG
319 printk(KERN_INFO "writing data to USB,"
320 "pkt length %d\n", write_ptr->length);
321 print_hex_dump(KERN_DEBUG, "Written Packet Data to"
322 " USB: ", 16, 1, DUMP_PREFIX_ADDRESS,
323 buf, write_ptr->length, 1);
324#endif /* DIAG DEBUG */
325 err = usb_diag_write(driver->legacy_ch, write_ptr);
326 } else if (proc_num == QDSP_DATA) {
327 write_ptr->buf = buf;
328 err = usb_diag_write(driver->legacy_ch, write_ptr);
329 } else if (proc_num == WCNSS_DATA) {
330 write_ptr->buf = buf;
331 err = usb_diag_write(driver->legacy_ch, write_ptr);
332 }
333#ifdef CONFIG_DIAG_SDIO_PIPE
334 else if (proc_num == SDIO_DATA) {
335 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -0800336 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700337 write_ptr->buf = buf;
338 err = usb_diag_write(driver->mdm_ch, write_ptr);
339 } else
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800340 pr_err("diag: Incorrect sdio data "
341 "while USB write\n");
342 }
343#endif
344#ifdef CONFIG_DIAG_HSIC_PIPE
345 else if (proc_num == HSIC_DATA) {
346 if (driver->hsic_device_enabled) {
347 write_ptr->buf = buf;
348 err = usb_diag_write(driver->mdm_ch, write_ptr);
349 } else
350 pr_err("diag: Incorrect hsic data "
351 "while USB write\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700352 }
353#endif
354 APPEND_DEBUG('d');
355 }
356#endif /* DIAG OVER USB */
357 return err;
358}
359
360void __diag_smd_wcnss_send_req(void)
361{
Ashay Jaiswal29620122012-03-21 12:02:36 +0530362 void *buf = NULL;
363 int *in_busy_wcnss_ptr = NULL;
364 struct diag_request *write_ptr_wcnss = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700365
Ashay Jaiswal29620122012-03-21 12:02:36 +0530366 if (!driver->in_busy_wcnss_1) {
367 buf = driver->buf_in_wcnss_1;
368 write_ptr_wcnss = driver->write_ptr_wcnss_1;
369 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_1);
370 } else if (!driver->in_busy_wcnss_2) {
371 buf = driver->buf_in_wcnss_2;
372 write_ptr_wcnss = driver->write_ptr_wcnss_2;
373 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_2);
374 }
375
376 if (driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700377 int r = smd_read_avail(driver->ch_wcnss);
378 if (r > IN_BUF_SIZE) {
379 if (r < MAX_IN_BUF_SIZE) {
380 pr_err("diag: wcnss packets > %d bytes", r);
381 buf = krealloc(buf, r, GFP_KERNEL);
382 } else {
383 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
384 return;
385 }
386 }
387 if (r > 0) {
388 if (!buf) {
389 pr_err("Out of diagmem for wcnss\n");
390 } else {
391 APPEND_DEBUG('i');
392 smd_read(driver->ch_wcnss, buf, r);
393 APPEND_DEBUG('j');
394 write_ptr_wcnss->length = r;
395 *in_busy_wcnss_ptr = 1;
396 diag_device_write(buf, WCNSS_DATA,
397 write_ptr_wcnss);
398 }
399 }
400 }
401}
402
403void __diag_smd_qdsp_send_req(void)
404{
405 void *buf = NULL;
406 int *in_busy_qdsp_ptr = NULL;
407 struct diag_request *write_ptr_qdsp = NULL;
408
409 if (!driver->in_busy_qdsp_1) {
410 buf = driver->buf_in_qdsp_1;
411 write_ptr_qdsp = driver->write_ptr_qdsp_1;
412 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1);
413 } else if (!driver->in_busy_qdsp_2) {
414 buf = driver->buf_in_qdsp_2;
415 write_ptr_qdsp = driver->write_ptr_qdsp_2;
416 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2);
417 }
418
419 if (driver->chqdsp && buf) {
420 int r = smd_read_avail(driver->chqdsp);
421
422 if (r > IN_BUF_SIZE) {
423 if (r < MAX_IN_BUF_SIZE) {
424 pr_err("diag: SMD sending in "
425 "packets upto %d bytes", r);
426 buf = krealloc(buf, r, GFP_KERNEL);
427 } else {
428 pr_err("diag: SMD sending in "
429 "packets more than %d bytes", MAX_IN_BUF_SIZE);
430 return;
431 }
432 }
433 if (r > 0) {
434 if (!buf)
435 printk(KERN_INFO "Out of diagmem for QDSP\n");
436 else {
437 APPEND_DEBUG('i');
438 smd_read(driver->chqdsp, buf, r);
439 APPEND_DEBUG('j');
440 write_ptr_qdsp->length = r;
441 *in_busy_qdsp_ptr = 1;
442 diag_device_write(buf, QDSP_DATA,
443 write_ptr_qdsp);
444 }
445 }
446 }
447}
448
449static void diag_print_mask_table(void)
450{
451/* Enable this to print mask table when updated */
452#ifdef MASK_DEBUG
453 int first;
454 int last;
455 uint8_t *ptr = driver->msg_masks;
456 int i = 0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700457 pr_info("diag: F3 message mask table\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700458 while (*(uint32_t *)(ptr + 4)) {
459 first = *(uint32_t *)ptr;
460 ptr += 4;
461 last = *(uint32_t *)ptr;
462 ptr += 4;
463 printk(KERN_INFO "SSID %d - %d\n", first, last);
464 for (i = 0 ; i <= last - first ; i++)
465 printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700466 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700467
468 }
469#endif
470}
471
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700472void diag_create_msg_mask_table(void)
473{
474 uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
475
476 CREATE_MSG_MASK_TBL_ROW(0);
477 CREATE_MSG_MASK_TBL_ROW(1);
478 CREATE_MSG_MASK_TBL_ROW(2);
479 CREATE_MSG_MASK_TBL_ROW(3);
480 CREATE_MSG_MASK_TBL_ROW(4);
481 CREATE_MSG_MASK_TBL_ROW(5);
482 CREATE_MSG_MASK_TBL_ROW(6);
483 CREATE_MSG_MASK_TBL_ROW(7);
484 CREATE_MSG_MASK_TBL_ROW(8);
485 CREATE_MSG_MASK_TBL_ROW(9);
486 CREATE_MSG_MASK_TBL_ROW(10);
487 CREATE_MSG_MASK_TBL_ROW(11);
488 CREATE_MSG_MASK_TBL_ROW(12);
489 CREATE_MSG_MASK_TBL_ROW(13);
490 CREATE_MSG_MASK_TBL_ROW(14);
491 CREATE_MSG_MASK_TBL_ROW(15);
492 CREATE_MSG_MASK_TBL_ROW(16);
493 CREATE_MSG_MASK_TBL_ROW(17);
494 CREATE_MSG_MASK_TBL_ROW(18);
495 CREATE_MSG_MASK_TBL_ROW(19);
496 CREATE_MSG_MASK_TBL_ROW(20);
497 CREATE_MSG_MASK_TBL_ROW(21);
498 CREATE_MSG_MASK_TBL_ROW(22);
499}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700500static void diag_update_msg_mask(int start, int end , uint8_t *buf)
501{
502 int found = 0;
503 int first;
504 int last;
505 uint8_t *ptr = driver->msg_masks;
506 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
507 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
508
509 mutex_lock(&driver->diagchar_mutex);
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530510
Shalabh Jain321c8b52012-02-22 12:37:06 -0800511 /* First SSID can be zero : So check that last is non-zero */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700512 while (*(uint32_t *)(ptr + 4)) {
513 first = *(uint32_t *)ptr;
514 ptr += 4;
515 last = *(uint32_t *)ptr;
516 ptr += 4;
517 if (start >= first && start <= last) {
518 ptr += (start - first)*4;
519 if (end <= last)
520 if (CHK_OVERFLOW(ptr_buffer_start, ptr,
521 ptr_buffer_end,
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700522 (((end - start)+1)*4))) {
523 pr_debug("diag: update ssid start %d,"
524 " end %d\n", start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700525 memcpy(ptr, buf , ((end - start)+1)*4);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700526 } else
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700527 printk(KERN_CRIT "Not enough"
528 " buffer space for"
529 " MSG_MASK\n");
530 else
531 printk(KERN_INFO "Unable to copy"
532 " mask change\n");
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530533
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700534 found = 1;
535 break;
536 } else {
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700537 ptr += MAX_SSID_PER_RANGE*4;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700538 }
539 }
540 /* Entry was not found - add new table */
541 if (!found) {
542 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
543 8 + ((end - start) + 1)*4)) {
544 memcpy(ptr, &(start) , 4);
545 ptr += 4;
546 memcpy(ptr, &(end), 4);
547 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700548 pr_debug("diag: adding NEW ssid start %d, end %d\n",
549 start, end);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550 memcpy(ptr, buf , ((end - start) + 1)*4);
551 } else
552 printk(KERN_CRIT " Not enough buffer"
553 " space for MSG_MASK\n");
554 }
555 mutex_unlock(&driver->diagchar_mutex);
556 diag_print_mask_table();
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530557
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700558}
559
Shalabh Jaina51f2592012-03-08 14:36:35 -0800560void diag_toggle_event_mask(int toggle)
561{
562 uint8_t *ptr = driver->event_masks;
563
564 mutex_lock(&driver->diagchar_mutex);
565 if (toggle)
566 memset(ptr, 0xFF, EVENT_MASK_SIZE);
567 else
568 memset(ptr, 0, EVENT_MASK_SIZE);
569 mutex_unlock(&driver->diagchar_mutex);
570}
571
Shalabh Jain321c8b52012-02-22 12:37:06 -0800572static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700573{
574 uint8_t *ptr = driver->event_masks;
575 uint8_t *temp = buf + 2;
576
577 mutex_lock(&driver->diagchar_mutex);
578 if (!toggle)
579 memset(ptr, 0 , EVENT_MASK_SIZE);
580 else
581 if (CHK_OVERFLOW(ptr, ptr,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800582 ptr+EVENT_MASK_SIZE, num_bytes))
583 memcpy(ptr, temp , num_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700584 else
585 printk(KERN_CRIT "Not enough buffer space "
586 "for EVENT_MASK\n");
587 mutex_unlock(&driver->diagchar_mutex);
588}
589
590static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
591{
592 uint8_t *temp = buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700593 int i = 0;
594 unsigned char *ptr_data;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700595 int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700596 struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700597
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700598 pr_debug("diag: received equip id = %d\n", equip_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700599 mutex_lock(&driver->diagchar_mutex);
600 /* Check if we already know index of this equipment ID */
601 for (i = 0; i < MAX_EQUIP_ID; i++) {
602 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
603 offset = ptr->index;
604 break;
605 }
606 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
Shalabh Jain321c8b52012-02-22 12:37:06 -0800607 /* Reached a null entry */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608 ptr->equip_id = equip_id;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800609 ptr->num_items = num_items;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700610 ptr->index = driver->log_masks_length;
611 offset = driver->log_masks_length;
612 driver->log_masks_length += ((num_items+7)/8);
613 break;
614 }
615 ptr++;
616 }
617 ptr_data = driver->log_masks + offset;
618 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
619 + LOG_MASK_SIZE, (num_items+7)/8))
620 memcpy(ptr_data, temp , (num_items+7)/8);
621 else
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700622 pr_err("diag: Not enough buffer space for LOG_MASK\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700623 mutex_unlock(&driver->diagchar_mutex);
624}
625
626static void diag_update_pkt_buffer(unsigned char *buf)
627{
628 unsigned char *ptr = driver->pkt_buf;
629 unsigned char *temp = buf;
630
631 mutex_lock(&driver->diagchar_mutex);
632 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
633 memcpy(ptr, temp , driver->pkt_length);
634 else
635 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
636 mutex_unlock(&driver->diagchar_mutex);
637}
638
639void diag_update_userspace_clients(unsigned int type)
640{
641 int i;
642
643 mutex_lock(&driver->diagchar_mutex);
644 for (i = 0; i < driver->num_clients; i++)
645 if (driver->client_map[i].pid != 0)
646 driver->data_ready[i] |= type;
647 wake_up_interruptible(&driver->wait_q);
648 mutex_unlock(&driver->diagchar_mutex);
649}
650
651void diag_update_sleeping_process(int process_id)
652{
653 int i;
654
655 mutex_lock(&driver->diagchar_mutex);
656 for (i = 0; i < driver->num_clients; i++)
657 if (driver->client_map[i].pid == process_id) {
658 driver->data_ready[i] |= PKT_TYPE;
659 break;
660 }
661 wake_up_interruptible(&driver->wait_q);
662 mutex_unlock(&driver->diagchar_mutex);
663}
664
665void diag_send_data(struct diag_master_table entry, unsigned char *buf,
666 int len, int type)
667{
668 driver->pkt_length = len;
669 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
670 diag_update_pkt_buffer(buf);
671 diag_update_sleeping_process(entry.process_id);
672 } else {
673 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700674 if (entry.client_id == MODEM_PROC && driver->ch) {
Shalabh Jain10f5f432012-01-11 11:45:44 +0530675 if (chk_apps_master() &&
Shalabh Jainc9f35092011-07-28 18:36:17 -0700676 (int)(*(char *)buf) == MODE_CMD)
Dixon Petersonff425d12011-12-06 18:12:35 -0800677 if ((int)(*(char *)(buf+1)) ==
678 RESET_ID)
Shalabh Jainc9f35092011-07-28 18:36:17 -0700679 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700680 smd_write(driver->ch, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700681 } else if (entry.client_id == QDSP_PROC &&
682 driver->chqdsp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700683 smd_write(driver->chqdsp, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700684 } else if (entry.client_id == WCNSS_PROC &&
685 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700686 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700687 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700688 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700689 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700690 }
691 }
692}
693
Shalabh Jain321c8b52012-02-22 12:37:06 -0800694void diag_modem_mask_update_fn(struct work_struct *work)
695{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700696 diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
697 ALL_SSID, MODEM_PROC);
698 diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800699 diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
700}
701
702void diag_qdsp_mask_update_fn(struct work_struct *work)
703{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700704 diag_send_msg_mask_update(driver->chqdsp_cntl, ALL_SSID,
705 ALL_SSID, QDSP_PROC);
706 diag_send_log_mask_update(driver->chqdsp_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800707 diag_send_event_mask_update(driver->chqdsp_cntl, diag_event_num_bytes);
708}
709
710void diag_wcnss_mask_update_fn(struct work_struct *work)
711{
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700712 diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
713 ALL_SSID, WCNSS_PROC);
714 diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800715 diag_send_event_mask_update(driver->ch_wcnss_cntl,
716 diag_event_num_bytes);
717}
718
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700719void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800720{
721 void *buf = driver->buf_log_mask_update;
722 int header_size = sizeof(struct diag_ctrl_log_mask);
723 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700724 int i, size, wr_size = -ENOMEM, retry_count = 0;
725 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800726
727 for (i = 0; i < MAX_EQUIP_ID; i++) {
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700728 size = (ptr->num_items+7)/8;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800729 /* reached null entry */
730 if ((ptr->equip_id == 0) && (ptr->index == 0))
731 break;
732 driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
733 driver->log_mask->num_items = ptr->num_items;
734 driver->log_mask->data_len = 11 + size;
735 driver->log_mask->stream_id = 1; /* 2, if dual stream */
736 driver->log_mask->status = 3; /* status for valid mask */
737 driver->log_mask->equip_id = ptr->equip_id;
738 driver->log_mask->log_mask_size = size;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700739 /* send only desired update, NOT ALL */
740 if (equip_id == ALL_EQUIP_ID || equip_id ==
741 driver->log_mask->equip_id) {
742 memcpy(buf, driver->log_mask, header_size);
743 memcpy(buf+header_size, driver->log_masks+ptr->index,
744 size);
745 if (ch) {
746 while (retry_count < 3) {
747 spin_lock_irqsave(&diag_cntl_lock,
748 flags);
749 wr_size = smd_write(ch, buf,
750 header_size + size);
751 spin_unlock_irqrestore(&diag_cntl_lock,
752 flags);
753 if (wr_size == -ENOMEM) {
754 retry_count++;
755 usleep(20000);
756 } else
757 break;
758 }
759 if (wr_size != header_size + size)
760 pr_err("diag: log mask update failed"
761 " %d, tried %d", wr_size, header_size + size);
762 else
763 pr_debug("diag: updated log equip ID %d"
764 ",len %d\n", driver->log_mask->equip_id,
765 driver->log_mask->log_mask_size);
766 } else
767 pr_err("diag: ch not valid for log update\n");
768 }
Shalabh Jain321c8b52012-02-22 12:37:06 -0800769 ptr++;
770 }
771}
772
773void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
774{
775 void *buf = driver->buf_event_mask_update;
776 int header_size = sizeof(struct diag_ctrl_event_mask);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700777 int wr_size = -ENOMEM, retry_count = 0;
778 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800779
780 /* send event mask update */
781 driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
782 driver->event_mask->data_len = 7 + num_bytes;
783 driver->event_mask->stream_id = 1; /* 2, if dual stream */
784 driver->event_mask->status = 3; /* status for valid mask */
785 driver->event_mask->event_config = diag_event_config; /* event config */
786 driver->event_mask->event_mask_size = num_bytes;
787 memcpy(buf, driver->event_mask, header_size);
788 memcpy(buf+header_size, driver->event_masks, num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700789 if (ch) {
790 while (retry_count < 3) {
791 spin_lock_irqsave(&diag_cntl_lock, flags);
792 wr_size = smd_write(ch, buf, header_size + num_bytes);
793 spin_unlock_irqrestore(&diag_cntl_lock, flags);
794 if (wr_size == -ENOMEM) {
795 retry_count++;
796 usleep(20000);
797 } else
798 break;
799 }
800 if (wr_size != header_size + num_bytes)
801 pr_err("diag: error writing event mask %d, tried %d\n",
802 wr_size, header_size + num_bytes);
803 } else
804 pr_err("diag: ch not valid for event update\n");
Shalabh Jain321c8b52012-02-22 12:37:06 -0800805}
806
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700807void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
808 int updated_ssid_last, int proc)
Shalabh Jain321c8b52012-02-22 12:37:06 -0800809{
810 void *buf = driver->buf_msg_mask_update;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700811 int first, last, size = -ENOMEM, retry_count = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800812 int header_size = sizeof(struct diag_ctrl_msg_mask);
813 uint8_t *ptr = driver->msg_masks;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700814 unsigned long flags = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800815
816 while (*(uint32_t *)(ptr + 4)) {
817 first = *(uint32_t *)ptr;
818 ptr += 4;
819 last = *(uint32_t *)ptr;
820 ptr += 4;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700821 if ((updated_ssid_first >= first && updated_ssid_last <= last)
822 || (updated_ssid_first == ALL_SSID)) {
823 /* send f3 mask update */
824 driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
825 driver->msg_mask->msg_mask_size = last - first + 1;
826 driver->msg_mask->data_len = 11 +
827 4 * (driver->msg_mask->msg_mask_size);
828 driver->msg_mask->stream_id = 1; /* 2, if dual stream */
829 driver->msg_mask->status = 3; /* status valid mask */
830 driver->msg_mask->msg_mode = 0; /* Legcay mode */
831 driver->msg_mask->ssid_first = first;
832 driver->msg_mask->ssid_last = last;
833 memcpy(buf, driver->msg_mask, header_size);
834 memcpy(buf+header_size, ptr,
835 4 * (driver->msg_mask->msg_mask_size));
836 if (ch) {
837 while (retry_count < 3) {
838 spin_lock_irqsave(&diag_cntl_lock,
839 flags);
840 size = smd_write(ch, buf, header_size +
841 4*(driver->msg_mask->msg_mask_size));
842 spin_unlock_irqrestore(&diag_cntl_lock,
843 flags);
844 if (size == -ENOMEM) {
845 retry_count++;
846 usleep(20000);
847 } else
848 break;
849 }
850 if (size != header_size +
851 4*(driver->msg_mask->msg_mask_size))
852 pr_err("diag: msg mask update fail %d,"
853 " tried %d\n", size,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800854 header_size + 4*(driver->msg_mask->msg_mask_size));
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700855 else
856 pr_debug("diag: sending mask update for"
857 " ssid first %d, last %d on PROC %d\n", first, last, proc);
858 } else
859 pr_err("diag: ch invalid msg mask update\n");
860 }
861 ptr += MAX_SSID_PER_RANGE*4;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800862 }
863}
864
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700865static int diag_process_apps_pkt(unsigned char *buf, int len)
866{
867 uint16_t subsys_cmd_code;
868 int subsys_id, ssid_first, ssid_last, ssid_range;
869 int packet_type = 1, i, cmd_code;
870 unsigned char *temp = buf;
871 int data_type;
872#if defined(CONFIG_DIAG_OVER_USB)
873 int payload_length;
874 unsigned char *ptr;
875#endif
876
Shalabh Jain321c8b52012-02-22 12:37:06 -0800877 /* Set log masks */
878 if (*buf == 0x73 && *(int *)(buf+4) == 3) {
879 buf += 8;
880 /* Read Equip ID and pass as first param below*/
881 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
882 diag_update_userspace_clients(LOG_MASKS_TYPE);
883#if defined(CONFIG_DIAG_OVER_USB)
884 if (chk_apps_only()) {
885 driver->apps_rsp_buf[0] = 0x73;
886 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
887 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
888 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
889 for (i = 0; i < payload_length; i++)
890 *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700891 if (driver->ch_cntl)
892 diag_send_log_mask_update(driver->ch_cntl,
893 *(int *)buf);
894 if (driver->chqdsp_cntl)
895 diag_send_log_mask_update(driver->chqdsp_cntl,
896 *(int *)buf);
897 if (driver->ch_wcnss_cntl)
898 diag_send_log_mask_update(driver->ch_wcnss_cntl,
899 *(int *)buf);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800900 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
901 return 0;
902 } else
903 buf = temp;
904#endif
905 } /* Check for set message mask */
906 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
907 ssid_first = *(uint16_t *)(buf + 2);
908 ssid_last = *(uint16_t *)(buf + 4);
909 ssid_range = 4 * (ssid_last - ssid_first + 1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700910 pr_debug("diag: received mask update for ssid_first = %d,"
911 " ssid_last = %d", ssid_first, ssid_last);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800912 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
913 diag_update_userspace_clients(MSG_MASKS_TYPE);
914#if defined(CONFIG_DIAG_OVER_USB)
915 if (chk_apps_only()) {
916 for (i = 0; i < 8 + ssid_range; i++)
917 *(driver->apps_rsp_buf + i) = *(buf+i);
918 *(driver->apps_rsp_buf + 6) = 0x1;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700919 if (driver->ch_cntl)
920 diag_send_msg_mask_update(driver->ch_cntl,
921 ssid_first, ssid_last, MODEM_PROC);
922 if (driver->chqdsp_cntl)
923 diag_send_msg_mask_update(driver->chqdsp_cntl,
924 ssid_first, ssid_last, QDSP_PROC);
925 if (driver->ch_wcnss_cntl)
926 diag_send_msg_mask_update(driver->ch_wcnss_cntl,
927 ssid_first, ssid_last, WCNSS_PROC);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800928 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
929 return 0;
930 } else
931 buf = temp;
932#endif
933 } else if (*buf == 0x82) { /* event mask change */
934 buf += 4;
935 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
936 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
937 diag_update_userspace_clients(EVENT_MASKS_TYPE);
938#if defined(CONFIG_DIAG_OVER_USB)
939 if (chk_apps_only()) {
940 driver->apps_rsp_buf[0] = 0x82;
941 driver->apps_rsp_buf[1] = 0x0;
942 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
943 *(uint16_t *)(driver->apps_rsp_buf + 4) =
944 EVENT_LAST_ID + 1;
Shalabh Jaina51f2592012-03-08 14:36:35 -0800945 memcpy(driver->apps_rsp_buf+6, driver->event_masks,
946 EVENT_LAST_ID/8+1);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700947 if (driver->ch_cntl)
948 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800949 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700950 if (driver->chqdsp_cntl)
951 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800952 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700953 if (driver->ch_wcnss_cntl)
954 diag_send_event_mask_update(
955 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800956 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
957 return 0;
958 } else
959 buf = temp;
960#endif
961 } else if (*buf == 0x60) {
962 diag_event_config = *(buf+1);
Shalabh Jaina51f2592012-03-08 14:36:35 -0800963 diag_toggle_event_mask(*(buf+1));
964 diag_update_userspace_clients(EVENT_MASKS_TYPE);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800965#if defined(CONFIG_DIAG_OVER_USB)
966 if (chk_apps_only()) {
967 driver->apps_rsp_buf[0] = 0x60;
968 driver->apps_rsp_buf[1] = 0x0;
969 driver->apps_rsp_buf[2] = 0x0;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700970 if (driver->ch_cntl)
971 diag_send_event_mask_update(driver->ch_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800972 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700973 if (driver->chqdsp_cntl)
974 diag_send_event_mask_update(driver->chqdsp_cntl,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800975 diag_event_num_bytes);
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -0700976 if (driver->ch_wcnss_cntl)
977 diag_send_event_mask_update(
978 driver->ch_wcnss_cntl, diag_event_num_bytes);
Shalabh Jain321c8b52012-02-22 12:37:06 -0800979 ENCODE_RSP_AND_SEND(2);
980 return 0;
981 }
982#endif
983 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700984 /* Check for registered clients and forward packet to apropriate proc */
985 cmd_code = (int)(*(char *)buf);
986 temp++;
987 subsys_id = (int)(*(char *)temp);
988 temp++;
989 subsys_cmd_code = *(uint16_t *)temp;
990 temp += 2;
991 data_type = APPS_DATA;
992 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530993 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700994 if (subsys_id != RESET_ID)
995 data_type = MODEM_DATA;
996 }
997
998 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -0800999 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001000 entry = driver->table[i];
1001 if (entry.process_id != NO_PROCESS) {
1002 if (entry.cmd_code == cmd_code && entry.subsys_id ==
1003 subsys_id && entry.cmd_code_lo <=
1004 subsys_cmd_code &&
1005 entry.cmd_code_hi >= subsys_cmd_code) {
1006 diag_send_data(entry, buf, len, data_type);
1007 packet_type = 0;
1008 } else if (entry.cmd_code == 255
1009 && cmd_code == 75) {
1010 if (entry.subsys_id ==
1011 subsys_id &&
1012 entry.cmd_code_lo <=
1013 subsys_cmd_code &&
1014 entry.cmd_code_hi >=
1015 subsys_cmd_code) {
1016 diag_send_data(entry, buf, len,
1017 data_type);
1018 packet_type = 0;
1019 }
1020 } else if (entry.cmd_code == 255 &&
1021 entry.subsys_id == 255) {
1022 if (entry.cmd_code_lo <=
1023 cmd_code &&
1024 entry.
1025 cmd_code_hi >= cmd_code) {
1026 diag_send_data(entry, buf, len,
1027 data_type);
1028 packet_type = 0;
1029 }
1030 }
1031 }
1032 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001033#if defined(CONFIG_DIAG_OVER_USB)
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001034 /* Check for Apps Only & get event mask request */
Shalabh Jain321c8b52012-02-22 12:37:06 -08001035 if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001036 driver->apps_rsp_buf[0] = 0x81;
1037 driver->apps_rsp_buf[1] = 0x0;
1038 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
1039 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
1040 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
1041 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
1042 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
1043 return 0;
1044 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001045 /* Get log ID range & Check for Apps Only */
1046 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001047 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
1048 driver->apps_rsp_buf[0] = 0x73;
1049 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
1050 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
1051 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
1052 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
1053 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
1054 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
1055 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
1056 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
1057 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
1058 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
1059 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
1060 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
1061 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
1062 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
1063 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
1064 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
1065 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
1066 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
1067 ENCODE_RSP_AND_SEND(75);
1068 return 0;
1069 }
1070 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001071 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001072 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
1073 driver->apps_rsp_buf[0] = 0x7d;
1074 driver->apps_rsp_buf[1] = 0x1;
1075 driver->apps_rsp_buf[2] = 0x1;
1076 driver->apps_rsp_buf[3] = 0x0;
1077 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
1078 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
1079 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
1080 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
1081 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
1082 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
1083 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
1084 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
1085 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
1086 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
1087 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
1088 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
1089 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
1090 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
1091 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
1092 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
1093 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
1094 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
1095 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
1096 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
1097 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
1098 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
1099 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
1100 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
1101 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
1102 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
1103 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
1104 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
1105 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
1106 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
1107 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
1108 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
1109 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
1110 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
1111 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
1112 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
1113 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
1114 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
1115 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001116 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
1117 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
1118 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
1119 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
1120 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
1121 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
1122 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
1123 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
1124 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001125 return 0;
1126 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001127 /* Check for Apps Only Respond to Get Subsys Build mask */
1128 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001129 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
1130 ssid_first = *(uint16_t *)(buf + 2);
1131 ssid_last = *(uint16_t *)(buf + 4);
1132 ssid_range = 4 * (ssid_last - ssid_first + 1);
1133 /* frame response */
1134 driver->apps_rsp_buf[0] = 0x7d;
1135 driver->apps_rsp_buf[1] = 0x2;
1136 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
1137 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
1138 driver->apps_rsp_buf[6] = 0x1;
1139 driver->apps_rsp_buf[7] = 0x0;
1140 ptr = driver->apps_rsp_buf + 8;
1141 /* bld time masks */
1142 switch (ssid_first) {
1143 case MSG_SSID_0:
1144 for (i = 0; i < ssid_range; i += 4)
1145 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
1146 break;
1147 case MSG_SSID_1:
1148 for (i = 0; i < ssid_range; i += 4)
1149 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
1150 break;
1151 case MSG_SSID_2:
1152 for (i = 0; i < ssid_range; i += 4)
1153 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
1154 break;
1155 case MSG_SSID_3:
1156 for (i = 0; i < ssid_range; i += 4)
1157 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
1158 break;
1159 case MSG_SSID_4:
1160 for (i = 0; i < ssid_range; i += 4)
1161 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
1162 break;
1163 case MSG_SSID_5:
1164 for (i = 0; i < ssid_range; i += 4)
1165 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
1166 break;
1167 case MSG_SSID_6:
1168 for (i = 0; i < ssid_range; i += 4)
1169 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
1170 break;
1171 case MSG_SSID_7:
1172 for (i = 0; i < ssid_range; i += 4)
1173 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
1174 break;
1175 case MSG_SSID_8:
1176 for (i = 0; i < ssid_range; i += 4)
1177 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
1178 break;
1179 case MSG_SSID_9:
1180 for (i = 0; i < ssid_range; i += 4)
1181 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
1182 break;
1183 case MSG_SSID_10:
1184 for (i = 0; i < ssid_range; i += 4)
1185 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
1186 break;
1187 case MSG_SSID_11:
1188 for (i = 0; i < ssid_range; i += 4)
1189 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
1190 break;
1191 case MSG_SSID_12:
1192 for (i = 0; i < ssid_range; i += 4)
1193 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1194 break;
1195 case MSG_SSID_13:
1196 for (i = 0; i < ssid_range; i += 4)
1197 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1198 break;
1199 case MSG_SSID_14:
1200 for (i = 0; i < ssid_range; i += 4)
1201 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1202 break;
1203 case MSG_SSID_15:
1204 for (i = 0; i < ssid_range; i += 4)
1205 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1206 break;
1207 case MSG_SSID_16:
1208 for (i = 0; i < ssid_range; i += 4)
1209 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1210 break;
1211 case MSG_SSID_17:
1212 for (i = 0; i < ssid_range; i += 4)
1213 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1214 break;
1215 case MSG_SSID_18:
1216 for (i = 0; i < ssid_range; i += 4)
1217 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1218 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001219 case MSG_SSID_19:
1220 for (i = 0; i < ssid_range; i += 4)
1221 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1222 break;
1223 case MSG_SSID_20:
1224 for (i = 0; i < ssid_range; i += 4)
1225 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1226 break;
1227 case MSG_SSID_21:
1228 for (i = 0; i < ssid_range; i += 4)
1229 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1230 break;
1231 case MSG_SSID_22:
1232 for (i = 0; i < ssid_range; i += 4)
1233 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1234 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001235 }
1236 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1237 return 0;
1238 }
1239 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301240 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001241 /* send response back */
1242 driver->apps_rsp_buf[0] = *buf;
1243 ENCODE_RSP_AND_SEND(0);
1244 msleep(5000);
1245 /* call download API */
1246 msm_set_restart_mode(RESTART_DLOAD);
1247 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1248 kernel_restart(NULL);
1249 /* Not required, represents that command isnt sent to modem */
1250 return 0;
1251 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001252 /* Check for polling for Apps only DIAG */
1253 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1254 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001255 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001256 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001257 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001258 for (i = 0; i < 3; i++)
1259 driver->apps_rsp_buf[i] = *(buf+i);
1260 for (i = 0; i < 13; i++)
1261 driver->apps_rsp_buf[i+3] = 0;
1262
1263 ENCODE_RSP_AND_SEND(15);
1264 return 0;
1265 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001266 }
1267 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001268 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001269 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001270 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001271 for (i = 0; i < 55; i++)
1272 driver->apps_rsp_buf[i] = 0;
1273
1274 ENCODE_RSP_AND_SEND(54);
1275 return 0;
1276 }
1277 /* respond to 0x7c command */
1278 else if (*buf == 0x7c) {
1279 driver->apps_rsp_buf[0] = 0x7c;
1280 for (i = 1; i < 8; i++)
1281 driver->apps_rsp_buf[i] = 0;
1282 /* Tools ID for APQ 8060 */
1283 *(int *)(driver->apps_rsp_buf + 8) =
1284 chk_config_get_id();
1285 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1286 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1287 ENCODE_RSP_AND_SEND(13);
1288 return 0;
1289 }
1290 }
1291#endif
1292 return packet_type;
1293}
1294
1295#ifdef CONFIG_DIAG_OVER_USB
1296void diag_send_error_rsp(int index)
1297{
1298 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301299
1300 if (index > 490) {
1301 pr_err("diag: error response too huge, aborting\n");
1302 return;
1303 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001304 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1305 for (i = 0; i < index; i++)
1306 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1307 ENCODE_RSP_AND_SEND(index - 3);
1308}
1309#else
1310static inline void diag_send_error_rsp(int index) {}
1311#endif
1312
1313void diag_process_hdlc(void *data, unsigned len)
1314{
1315 struct diag_hdlc_decode_type hdlc;
1316 int ret, type = 0;
1317 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1318 hdlc.dest_ptr = driver->hdlc_buf;
1319 hdlc.dest_size = USB_MAX_OUT_BUF;
1320 hdlc.src_ptr = data;
1321 hdlc.src_size = len;
1322 hdlc.src_idx = 0;
1323 hdlc.dest_idx = 0;
1324 hdlc.escaping = 0;
1325
1326 ret = diag_hdlc_decode(&hdlc);
1327
1328 if (ret)
1329 type = diag_process_apps_pkt(driver->hdlc_buf,
1330 hdlc.dest_idx - 3);
1331 else if (driver->debug_flag) {
1332 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1333 " errors or partial packet received, packet"
1334 " length = %d\n", len);
1335 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1336 DUMP_PREFIX_ADDRESS, data, len, 1);
1337 driver->debug_flag = 0;
1338 }
1339 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001340 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001341 diag_send_error_rsp(hdlc.dest_idx);
1342 type = 0;
1343 }
1344 /* implies this packet is NOT meant for apps */
1345 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001346 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001347 diag_send_error_rsp(hdlc.dest_idx);
1348 } else { /* APQ 8060, Let Q6 respond */
1349 if (driver->chqdsp)
1350 smd_write(driver->chqdsp, driver->hdlc_buf,
1351 hdlc.dest_idx - 3);
1352 }
1353 type = 0;
1354 }
1355
1356#ifdef DIAG_DEBUG
1357 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1358 for (i = 0; i < hdlc.dest_idx; i++)
1359 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1360 driver->hdlc_buf)+i));
1361#endif /* DIAG DEBUG */
1362 /* ignore 2 bytes for CRC, one for 7E and send */
1363 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1364 APPEND_DEBUG('g');
1365 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1366 APPEND_DEBUG('h');
1367#ifdef DIAG_DEBUG
1368 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1369 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1370 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1371#endif /* DIAG DEBUG */
1372 }
1373}
1374
1375#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001376/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1377#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001378#define N_LEGACY_READ 1
1379
1380int diagfwd_connect(void)
1381{
1382 int err;
1383
1384 printk(KERN_DEBUG "diag: USB connected\n");
1385 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1386 N_LEGACY_READ);
1387 if (err)
1388 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1389
1390 driver->usb_connected = 1;
1391 driver->in_busy_1 = 0;
1392 driver->in_busy_2 = 0;
1393 driver->in_busy_qdsp_1 = 0;
1394 driver->in_busy_qdsp_2 = 0;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301395 driver->in_busy_wcnss_1 = 0;
1396 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001397
1398 /* Poll SMD channels to check for data*/
1399 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1400 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1401 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001402 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001403 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1404 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1405 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001406 /* Poll USB channel to check for data*/
1407 queue_work(driver->diag_wq, &(driver->diag_read_work));
1408#ifdef CONFIG_DIAG_SDIO_PIPE
1409 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1410 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1411 diagfwd_connect_sdio();
1412 else
1413 printk(KERN_INFO "diag: No USB MDM ch");
1414 }
1415#endif
1416 return 0;
1417}
1418
1419int diagfwd_disconnect(void)
1420{
1421 printk(KERN_DEBUG "diag: USB disconnected\n");
1422 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001423 driver->debug_flag = 1;
1424 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001425 if (driver->logging_mode == USB_MODE) {
1426 driver->in_busy_1 = 1;
1427 driver->in_busy_2 = 1;
1428 driver->in_busy_qdsp_1 = 1;
1429 driver->in_busy_qdsp_2 = 1;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301430 driver->in_busy_wcnss_1 = 1;
1431 driver->in_busy_wcnss_2 = 1;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001432 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001433#ifdef CONFIG_DIAG_SDIO_PIPE
1434 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1435 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1436 diagfwd_disconnect_sdio();
1437#endif
1438 /* TBD - notify and flow control SMD */
1439 return 0;
1440}
1441
1442int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1443{
1444 unsigned char *buf = diag_write_ptr->buf;
1445 /*Determine if the write complete is for data from modem/apps/q6 */
1446 /* Need a context variable here instead */
1447 if (buf == (void *)driver->buf_in_1) {
1448 driver->in_busy_1 = 0;
1449 APPEND_DEBUG('o');
1450 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1451 } else if (buf == (void *)driver->buf_in_2) {
1452 driver->in_busy_2 = 0;
1453 APPEND_DEBUG('O');
1454 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1455 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1456 driver->in_busy_qdsp_1 = 0;
1457 APPEND_DEBUG('p');
1458 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1459 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1460 driver->in_busy_qdsp_2 = 0;
1461 APPEND_DEBUG('P');
1462 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
Ashay Jaiswal29620122012-03-21 12:02:36 +05301463 } else if (buf == driver->buf_in_wcnss_1) {
1464 driver->in_busy_wcnss_1 = 0;
1465 APPEND_DEBUG('r');
1466 queue_work(driver->diag_wq,
1467 &(driver->diag_read_smd_wcnss_work));
1468 } else if (buf == driver->buf_in_wcnss_2) {
1469 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001470 APPEND_DEBUG('R');
1471 queue_work(driver->diag_wq,
1472 &(driver->diag_read_smd_wcnss_work));
1473 }
1474#ifdef CONFIG_DIAG_SDIO_PIPE
1475 else if (buf == (void *)driver->buf_in_sdio)
1476 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001477 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001478 diagfwd_write_complete_sdio();
1479 else
1480 pr_err("diag: Incorrect buffer pointer while WRITE");
1481#endif
1482 else {
1483 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1484 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1485 POOL_TYPE_WRITE_STRUCT);
1486 APPEND_DEBUG('q');
1487 }
1488 return 0;
1489}
1490
1491int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1492{
1493 int status = diag_read_ptr->status;
1494 unsigned char *buf = diag_read_ptr->buf;
1495
1496 /* Determine if the read complete is for data on legacy/mdm ch */
1497 if (buf == (void *)driver->usb_buf_out) {
1498 driver->read_len_legacy = diag_read_ptr->actual;
1499 APPEND_DEBUG('s');
1500#ifdef DIAG_DEBUG
1501 printk(KERN_INFO "read data from USB, pkt length %d",
1502 diag_read_ptr->actual);
1503 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1504 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1505 diag_read_ptr->actual, 1);
1506#endif /* DIAG DEBUG */
1507 if (driver->logging_mode == USB_MODE) {
1508 if (status != -ECONNRESET && status != -ESHUTDOWN)
1509 queue_work(driver->diag_wq,
1510 &(driver->diag_proc_hdlc_work));
1511 else
1512 queue_work(driver->diag_wq,
1513 &(driver->diag_read_work));
1514 }
1515 }
1516#ifdef CONFIG_DIAG_SDIO_PIPE
1517 else if (buf == (void *)driver->usb_buf_mdm_out) {
1518 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001519 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001520 driver->read_len_mdm = diag_read_ptr->actual;
1521 diagfwd_read_complete_sdio();
1522 } else
1523 pr_err("diag: Incorrect buffer pointer while READ");
1524 }
1525#endif
1526 else
1527 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1528
1529 return 0;
1530}
1531
1532void diag_read_work_fn(struct work_struct *work)
1533{
1534 APPEND_DEBUG('d');
1535 driver->usb_read_ptr->buf = driver->usb_buf_out;
1536 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1537 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1538 APPEND_DEBUG('e');
1539}
1540
1541void diag_process_hdlc_fn(struct work_struct *work)
1542{
1543 APPEND_DEBUG('D');
1544 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1545 diag_read_work_fn(work);
1546 APPEND_DEBUG('E');
1547}
1548
1549void diag_usb_legacy_notifier(void *priv, unsigned event,
1550 struct diag_request *d_req)
1551{
1552 switch (event) {
1553 case USB_DIAG_CONNECT:
1554 diagfwd_connect();
1555 break;
1556 case USB_DIAG_DISCONNECT:
1557 diagfwd_disconnect();
1558 break;
1559 case USB_DIAG_READ_DONE:
1560 diagfwd_read_complete(d_req);
1561 break;
1562 case USB_DIAG_WRITE_DONE:
1563 diagfwd_write_complete(d_req);
1564 break;
1565 default:
1566 printk(KERN_ERR "Unknown event from USB diag\n");
1567 break;
1568 }
1569}
1570
1571#endif /* DIAG OVER USB */
1572
1573static void diag_smd_notify(void *ctxt, unsigned event)
1574{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001575 if (event == SMD_EVENT_CLOSE) {
1576 pr_info("diag: clean modem registration\n");
1577 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001578 driver->ch = 0;
1579 return;
1580 } else if (event == SMD_EVENT_OPEN) {
1581 driver->ch = ch_temp;
1582 }
1583 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001584}
1585
1586#if defined(CONFIG_MSM_N_WAY_SMD)
1587static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1588{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001589 if (event == SMD_EVENT_CLOSE) {
1590 pr_info("diag: clean lpass registration\n");
1591 diag_clear_reg(QDSP_PROC);
1592 driver->chqdsp = 0;
1593 return;
1594 } else if (event == SMD_EVENT_OPEN) {
1595 driver->chqdsp = chqdsp_temp;
1596 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001597 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1598}
1599#endif
1600
1601static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1602{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001603 if (event == SMD_EVENT_CLOSE) {
1604 pr_info("diag: clean wcnss registration\n");
1605 diag_clear_reg(WCNSS_PROC);
1606 driver->ch_wcnss = 0;
1607 return;
1608 } else if (event == SMD_EVENT_OPEN) {
1609 driver->ch_wcnss = ch_wcnss_temp;
1610 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001611 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1612}
1613
1614static int diag_smd_probe(struct platform_device *pdev)
1615{
1616 int r = 0;
1617
Shalabh Jaineefee052011-11-08 23:46:03 -08001618 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001619 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001620 ch_temp = driver->ch;
1621 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001622#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001623 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001624 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1625 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001626 chqdsp_temp = driver->chqdsp;
1627 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001628#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001629 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001630 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1631 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001632 ch_wcnss_temp = driver->ch_wcnss;
1633 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001634 pm_runtime_set_active(&pdev->dev);
1635 pm_runtime_enable(&pdev->dev);
1636 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1637
1638 return 0;
1639}
1640
1641static int diagfwd_runtime_suspend(struct device *dev)
1642{
1643 dev_dbg(dev, "pm_runtime: suspending...\n");
1644 return 0;
1645}
1646
1647static int diagfwd_runtime_resume(struct device *dev)
1648{
1649 dev_dbg(dev, "pm_runtime: resuming...\n");
1650 return 0;
1651}
1652
1653static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1654 .runtime_suspend = diagfwd_runtime_suspend,
1655 .runtime_resume = diagfwd_runtime_resume,
1656};
1657
1658static struct platform_driver msm_smd_ch1_driver = {
1659
1660 .probe = diag_smd_probe,
1661 .driver = {
1662 .name = "DIAG",
1663 .owner = THIS_MODULE,
1664 .pm = &diagfwd_dev_pm_ops,
1665 },
1666};
1667
1668static struct platform_driver diag_smd_lite_driver = {
1669
1670 .probe = diag_smd_probe,
1671 .driver = {
1672 .name = "APPS_RIVA_DATA",
1673 .owner = THIS_MODULE,
1674 .pm = &diagfwd_dev_pm_ops,
1675 },
1676};
1677
1678void diagfwd_init(void)
1679{
1680 diag_debug_buf_idx = 0;
1681 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001682 driver->use_device_tree = has_device_tree();
Shalabh Jain321c8b52012-02-22 12:37:06 -08001683
1684 if (driver->event_mask == NULL) {
1685 driver->event_mask = kzalloc(sizeof(
1686 struct diag_ctrl_event_mask), GFP_KERNEL);
1687 if (driver->event_mask == NULL)
1688 goto err;
1689 }
1690 if (driver->msg_mask == NULL) {
1691 driver->msg_mask = kzalloc(sizeof(
1692 struct diag_ctrl_msg_mask), GFP_KERNEL);
1693 if (driver->msg_mask == NULL)
1694 goto err;
1695 }
1696 if (driver->log_mask == NULL) {
1697 driver->log_mask = kzalloc(sizeof(
1698 struct diag_ctrl_log_mask), GFP_KERNEL);
1699 if (driver->log_mask == NULL)
1700 goto err;
1701 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001702 if (driver->buf_in_1 == NULL) {
1703 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1704 if (driver->buf_in_1 == NULL)
1705 goto err;
1706 }
1707 if (driver->buf_in_2 == NULL) {
1708 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1709 if (driver->buf_in_2 == NULL)
1710 goto err;
1711 }
1712 if (driver->buf_in_qdsp_1 == NULL) {
1713 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1714 if (driver->buf_in_qdsp_1 == NULL)
1715 goto err;
1716 }
1717 if (driver->buf_in_qdsp_2 == NULL) {
1718 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1719 if (driver->buf_in_qdsp_2 == NULL)
1720 goto err;
1721 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301722 if (driver->buf_in_wcnss_1 == NULL) {
1723 driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1724 if (driver->buf_in_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001725 goto err;
1726 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301727 if (driver->buf_in_wcnss_2 == NULL) {
1728 driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1729 if (driver->buf_in_wcnss_2 == NULL)
1730 goto err;
1731 }
1732
Shalabh Jain321c8b52012-02-22 12:37:06 -08001733 if (driver->buf_msg_mask_update == NULL) {
1734 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1735 GFP_KERNEL);
1736 if (driver->buf_msg_mask_update == NULL)
1737 goto err;
1738 }
1739 if (driver->buf_log_mask_update == NULL) {
1740 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1741 GFP_KERNEL);
1742 if (driver->buf_log_mask_update == NULL)
1743 goto err;
1744 }
1745 if (driver->buf_event_mask_update == NULL) {
1746 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1747 GFP_KERNEL);
1748 if (driver->buf_event_mask_update == NULL)
1749 goto err;
1750 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001751 if (driver->usb_buf_out == NULL &&
1752 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1753 GFP_KERNEL)) == NULL)
1754 goto err;
1755 if (driver->hdlc_buf == NULL
1756 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1757 goto err;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001758 if (driver->user_space_data == NULL)
1759 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1760 if (driver->user_space_data == NULL)
1761 goto err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001762 if (driver->msg_masks == NULL
1763 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1764 GFP_KERNEL)) == NULL)
1765 goto err;
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -07001766 diag_create_msg_mask_table();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001767 if (driver->log_masks == NULL &&
1768 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1769 goto err;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -07001770 driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001771 if (driver->event_masks == NULL &&
1772 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1773 GFP_KERNEL)) == NULL)
1774 goto err;
1775 if (driver->client_map == NULL &&
1776 (driver->client_map = kzalloc
1777 ((driver->num_clients) * sizeof(struct diag_client_map),
1778 GFP_KERNEL)) == NULL)
1779 goto err;
1780 if (driver->buf_tbl == NULL)
1781 driver->buf_tbl = kzalloc(buf_tbl_size *
1782 sizeof(struct diag_write_device), GFP_KERNEL);
1783 if (driver->buf_tbl == NULL)
1784 goto err;
1785 if (driver->data_ready == NULL &&
1786 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1787 , GFP_KERNEL)) == NULL)
1788 goto err;
1789 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001790 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001791 sizeof(struct diag_master_table),
1792 GFP_KERNEL)) == NULL)
1793 goto err;
1794 if (driver->write_ptr_1 == NULL) {
1795 driver->write_ptr_1 = kzalloc(
1796 sizeof(struct diag_request), GFP_KERNEL);
1797 if (driver->write_ptr_1 == NULL)
1798 goto err;
1799 }
1800 if (driver->write_ptr_2 == NULL) {
1801 driver->write_ptr_2 = kzalloc(
1802 sizeof(struct diag_request), GFP_KERNEL);
1803 if (driver->write_ptr_2 == NULL)
1804 goto err;
1805 }
1806 if (driver->write_ptr_qdsp_1 == NULL) {
1807 driver->write_ptr_qdsp_1 = kzalloc(
1808 sizeof(struct diag_request), GFP_KERNEL);
1809 if (driver->write_ptr_qdsp_1 == NULL)
1810 goto err;
1811 }
1812 if (driver->write_ptr_qdsp_2 == NULL) {
1813 driver->write_ptr_qdsp_2 = kzalloc(
1814 sizeof(struct diag_request), GFP_KERNEL);
1815 if (driver->write_ptr_qdsp_2 == NULL)
1816 goto err;
1817 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301818 if (driver->write_ptr_wcnss_1 == NULL) {
1819 driver->write_ptr_wcnss_1 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001820 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301821 if (driver->write_ptr_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001822 goto err;
1823 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301824 if (driver->write_ptr_wcnss_2 == NULL) {
1825 driver->write_ptr_wcnss_2 = kzalloc(
1826 sizeof(struct diag_request), GFP_KERNEL);
1827 if (driver->write_ptr_wcnss_2 == NULL)
1828 goto err;
1829 }
1830
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001831 if (driver->usb_read_ptr == NULL) {
1832 driver->usb_read_ptr = kzalloc(
1833 sizeof(struct diag_request), GFP_KERNEL);
1834 if (driver->usb_read_ptr == NULL)
1835 goto err;
1836 }
1837 if (driver->pkt_buf == NULL &&
1838 (driver->pkt_buf = kzalloc(PKT_SIZE,
1839 GFP_KERNEL)) == NULL)
1840 goto err;
1841 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001842 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001843 if (driver->apps_rsp_buf == NULL)
1844 goto err;
1845 }
1846 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1847#ifdef CONFIG_DIAG_OVER_USB
1848 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1849 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001850 INIT_WORK(&(driver->diag_modem_mask_update_work),
1851 diag_modem_mask_update_fn);
1852 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
1853 diag_qdsp_mask_update_fn);
1854 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
1855 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001856 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
1857 diag_usb_legacy_notifier);
1858 if (IS_ERR(driver->legacy_ch)) {
1859 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
1860 goto err;
1861 }
1862#endif
1863 platform_driver_register(&msm_smd_ch1_driver);
1864 platform_driver_register(&diag_smd_lite_driver);
1865
1866 return;
1867err:
1868 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08001869 kfree(driver->event_mask);
1870 kfree(driver->log_mask);
1871 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001872 kfree(driver->buf_in_1);
1873 kfree(driver->buf_in_2);
1874 kfree(driver->buf_in_qdsp_1);
1875 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301876 kfree(driver->buf_in_wcnss_1);
1877 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001878 kfree(driver->buf_msg_mask_update);
1879 kfree(driver->buf_log_mask_update);
1880 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001881 kfree(driver->usb_buf_out);
1882 kfree(driver->hdlc_buf);
1883 kfree(driver->msg_masks);
1884 kfree(driver->log_masks);
1885 kfree(driver->event_masks);
1886 kfree(driver->client_map);
1887 kfree(driver->buf_tbl);
1888 kfree(driver->data_ready);
1889 kfree(driver->table);
1890 kfree(driver->pkt_buf);
1891 kfree(driver->write_ptr_1);
1892 kfree(driver->write_ptr_2);
1893 kfree(driver->write_ptr_qdsp_1);
1894 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301895 kfree(driver->write_ptr_wcnss_1);
1896 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001897 kfree(driver->usb_read_ptr);
1898 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001899 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001900 if (driver->diag_wq)
1901 destroy_workqueue(driver->diag_wq);
1902}
1903
1904void diagfwd_exit(void)
1905{
1906 smd_close(driver->ch);
1907 smd_close(driver->chqdsp);
1908 smd_close(driver->ch_wcnss);
1909 driver->ch = 0; /* SMD can make this NULL */
1910 driver->chqdsp = 0;
1911 driver->ch_wcnss = 0;
1912#ifdef CONFIG_DIAG_OVER_USB
1913 if (driver->usb_connected)
1914 usb_diag_free_req(driver->legacy_ch);
1915 usb_diag_close(driver->legacy_ch);
1916#endif
1917 platform_driver_unregister(&msm_smd_ch1_driver);
1918 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001919 kfree(driver->event_mask);
1920 kfree(driver->log_mask);
1921 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001922 kfree(driver->buf_in_1);
1923 kfree(driver->buf_in_2);
1924 kfree(driver->buf_in_qdsp_1);
1925 kfree(driver->buf_in_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301926 kfree(driver->buf_in_wcnss_1);
1927 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001928 kfree(driver->buf_msg_mask_update);
1929 kfree(driver->buf_log_mask_update);
1930 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001931 kfree(driver->usb_buf_out);
1932 kfree(driver->hdlc_buf);
1933 kfree(driver->msg_masks);
1934 kfree(driver->log_masks);
1935 kfree(driver->event_masks);
1936 kfree(driver->client_map);
1937 kfree(driver->buf_tbl);
1938 kfree(driver->data_ready);
1939 kfree(driver->table);
1940 kfree(driver->pkt_buf);
1941 kfree(driver->write_ptr_1);
1942 kfree(driver->write_ptr_2);
1943 kfree(driver->write_ptr_qdsp_1);
1944 kfree(driver->write_ptr_qdsp_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301945 kfree(driver->write_ptr_wcnss_1);
1946 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001947 kfree(driver->usb_read_ptr);
1948 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001949 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001950 destroy_workqueue(driver->diag_wq);
1951}