blob: 4cf6d3383290b5e18bb7d9d06690a7e793ce6fe7 [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>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070025#ifdef CONFIG_DIAG_OVER_USB
26#include <mach/usbdiag.h>
27#endif
28#include <mach/msm_smd.h>
29#include <mach/socinfo.h>
30#include <mach/restart.h>
31#include "diagmem.h"
32#include "diagchar.h"
33#include "diagfwd.h"
34#include "diagfwd_cntl.h"
35#include "diagchar_hdlc.h"
36#ifdef CONFIG_DIAG_SDIO_PIPE
37#include "diagfwd_sdio.h"
38#endif
39#define MODE_CMD 41
40#define RESET_ID 2
41
42int diag_debug_buf_idx;
43unsigned char diag_debug_buf[1024];
44static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
45struct diag_master_table entry;
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -080046smd_channel_t *ch_temp, *chqdsp_temp, *ch_wcnss_temp;
Shalabh Jain321c8b52012-02-22 12:37:06 -080047int diag_event_num_bytes;
48int diag_event_config;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070049struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
50struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
Shalabh Jain321c8b52012-02-22 12:37:06 -080051struct mask_info {
52 int equip_id;
53 int num_items;
54 int index;
55};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070056
57#define ENCODE_RSP_AND_SEND(buf_length) \
58do { \
59 send.state = DIAG_STATE_START; \
60 send.pkt = driver->apps_rsp_buf; \
61 send.last = (void *)(driver->apps_rsp_buf + buf_length); \
62 send.terminate = 1; \
63 if (!driver->in_busy_1) { \
64 enc.dest = driver->buf_in_1; \
Shalabh Jain321c8b52012-02-22 12:37:06 -080065 enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);\
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070066 diag_hdlc_encode(&send, &enc); \
67 driver->write_ptr_1->buf = driver->buf_in_1; \
68 driver->write_ptr_1->length = (int)(enc.dest - \
69 (void *)(driver->buf_in_1)); \
Shalabh Jain3893bf92011-09-18 18:37:16 -070070 driver->in_busy_1 = 1; \
Shalabh Jain69890aa2011-10-10 12:59:16 -070071 diag_device_write(driver->buf_in_1, MODEM_DATA, \
72 driver->write_ptr_1); \
Shalabh Jain321c8b52012-02-22 12:37:06 -080073 memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE); \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070074 } \
75} while (0)
76
77#define CHK_OVERFLOW(bufStart, start, end, length) \
78((bufStart <= start) && (end - start >= length)) ? 1 : 0
79
Dixon Petersonb4618a42012-02-29 18:56:31 -080080/* Determine if this device uses a device tree */
81#ifdef CONFIG_OF
82static int has_device_tree(void)
83{
84 struct device_node *node;
85
86 node = of_find_node_by_path("/");
87 if (node) {
88 of_node_put(node);
89 return 1;
90 }
91 return 0;
92}
93#else
94static int has_device_tree(void)
95{
96 return 0;
97}
98#endif
99
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700100int chk_config_get_id(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700101{
Shalabh Jain482bf122011-12-06 03:54:47 -0800102 /* For all Fusion targets, Modem will always be present */
103 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
104 return 0;
105
Dixon Petersonb4618a42012-02-29 18:56:31 -0800106 if (driver->use_device_tree) {
107 if (machine_is_copper())
108 return MSM8974_TOOLS_ID;
109 else
110 return 0;
111 } else {
112 switch (socinfo_get_msm_cpu()) {
113 case MSM_CPU_8X60:
114 return APQ8060_TOOLS_ID;
115 case MSM_CPU_8960:
116 return AO8960_TOOLS_ID;
117 case MSM_CPU_8064:
118 return APQ8064_TOOLS_ID;
119 case MSM_CPU_8930:
120 return MSM8930_TOOLS_ID;
121 case MSM_CPU_COPPER:
122 return MSM8974_TOOLS_ID;
123 case MSM_CPU_8625:
124 return MSM8625_TOOLS_ID;
125 default:
126 return 0;
127 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700128 }
129}
130
131/*
Shalabh Jain321c8b52012-02-22 12:37:06 -0800132 * This will return TRUE for targets which support apps only mode and hence SSR.
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700133 * This applies to 8960 and newer targets.
134 */
135int chk_apps_only(void)
136{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800137 if (driver->use_device_tree)
138 return 1;
139
140 switch (socinfo_get_msm_cpu()) {
141 case MSM_CPU_8960:
142 case MSM_CPU_8064:
143 case MSM_CPU_8930:
144 case MSM_CPU_8627:
145 case MSM_CPU_9615:
146 case MSM_CPU_COPPER:
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700147 return 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700148 default:
149 return 0;
150 }
151}
152
Shalabh Jain10f5f432012-01-11 11:45:44 +0530153/*
154 * This will return TRUE for targets which support apps as master.
155 * Thus, SW DLOAD and Mode Reset are supported on apps processor.
156 * This applies to 8960 and newer targets.
157 */
158int chk_apps_master(void)
159{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800160 if (driver->use_device_tree)
161 return 1;
162 else if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615() ||
163 cpu_is_apq8064() || cpu_is_msm8627())
164 return 1;
165 else
166 return 0;
167}
168
169inline int chk_polling_response(void)
170{
171 if (!(driver->polling_reg_flag) && chk_apps_master())
172 /*
173 * If the apps processor is master and no other processor
174 * has registered to respond for polling
175 */
176 return 1;
177 else if (!(driver->ch) && !(chk_apps_master()))
178 /*
179 * If the apps processor is not the master and the modem
180 * is not up
181 */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530182 return 1;
183 else
184 return 0;
185}
186
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700187void __diag_smd_send_req(void)
188{
189 void *buf = NULL;
190 int *in_busy_ptr = NULL;
191 struct diag_request *write_ptr_modem = NULL;
192
193 if (!driver->in_busy_1) {
194 buf = driver->buf_in_1;
195 write_ptr_modem = driver->write_ptr_1;
196 in_busy_ptr = &(driver->in_busy_1);
197 } else if (!driver->in_busy_2) {
198 buf = driver->buf_in_2;
199 write_ptr_modem = driver->write_ptr_2;
200 in_busy_ptr = &(driver->in_busy_2);
201 }
202
203 if (driver->ch && buf) {
204 int r = smd_read_avail(driver->ch);
205
206 if (r > IN_BUF_SIZE) {
207 if (r < MAX_IN_BUF_SIZE) {
208 pr_err("diag: SMD sending in "
209 "packets upto %d bytes", r);
210 buf = krealloc(buf, r, GFP_KERNEL);
211 } else {
212 pr_err("diag: SMD sending in "
213 "packets more than %d bytes", MAX_IN_BUF_SIZE);
214 return;
215 }
216 }
217 if (r > 0) {
218 if (!buf)
219 pr_info("Out of diagmem for Modem\n");
220 else {
221 APPEND_DEBUG('i');
222 smd_read(driver->ch, buf, r);
223 APPEND_DEBUG('j');
224 write_ptr_modem->length = r;
225 *in_busy_ptr = 1;
226 diag_device_write(buf, MODEM_DATA,
227 write_ptr_modem);
228 }
229 }
230 }
231}
232
233int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr)
234{
235 int i, err = 0;
236
237 if (driver->logging_mode == MEMORY_DEVICE_MODE) {
238 if (proc_num == APPS_DATA) {
239 for (i = 0; i < driver->poolsize_write_struct; i++)
240 if (driver->buf_tbl[i].length == 0) {
241 driver->buf_tbl[i].buf = buf;
242 driver->buf_tbl[i].length =
243 driver->used;
244#ifdef DIAG_DEBUG
245 pr_debug("diag: ENQUEUE buf ptr"
246 " and length is %x , %d\n",
247 (unsigned int)(driver->buf_
248 tbl[i].buf), driver->buf_tbl[i].length);
249#endif
250 break;
251 }
252 }
253 for (i = 0; i < driver->num_clients; i++)
254 if (driver->client_map[i].pid ==
255 driver->logging_process_id)
256 break;
257 if (i < driver->num_clients) {
Shalabh Jain69890aa2011-10-10 12:59:16 -0700258 driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700259 wake_up_interruptible(&driver->wait_q);
260 } else
261 return -EINVAL;
262 } else if (driver->logging_mode == NO_LOGGING_MODE) {
263 if (proc_num == MODEM_DATA) {
264 driver->in_busy_1 = 0;
265 driver->in_busy_2 = 0;
266 queue_work(driver->diag_wq, &(driver->
267 diag_read_smd_work));
268 } else if (proc_num == QDSP_DATA) {
269 driver->in_busy_qdsp_1 = 0;
270 driver->in_busy_qdsp_2 = 0;
271 queue_work(driver->diag_wq, &(driver->
272 diag_read_smd_qdsp_work));
273 } else if (proc_num == WCNSS_DATA) {
274 driver->in_busy_wcnss = 0;
275 queue_work(driver->diag_wq, &(driver->
276 diag_read_smd_wcnss_work));
277 }
Shalabh Jain482bf122011-12-06 03:54:47 -0800278#ifdef CONFIG_DIAG_SDIO_PIPE
279 else if (proc_num == SDIO_DATA) {
280 driver->in_busy_sdio = 0;
281 queue_work(driver->diag_sdio_wq,
282 &(driver->diag_read_sdio_work));
283 }
284#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700285 err = -1;
286 }
287#ifdef CONFIG_DIAG_OVER_USB
288 else if (driver->logging_mode == USB_MODE) {
289 if (proc_num == APPS_DATA) {
290 driver->write_ptr_svc = (struct diag_request *)
291 (diagmem_alloc(driver, sizeof(struct diag_request),
292 POOL_TYPE_WRITE_STRUCT));
293 if (driver->write_ptr_svc) {
294 driver->write_ptr_svc->length = driver->used;
295 driver->write_ptr_svc->buf = buf;
296 err = usb_diag_write(driver->legacy_ch,
297 driver->write_ptr_svc);
298 } else
299 err = -1;
300 } else if (proc_num == MODEM_DATA) {
301 write_ptr->buf = buf;
302#ifdef DIAG_DEBUG
303 printk(KERN_INFO "writing data to USB,"
304 "pkt length %d\n", write_ptr->length);
305 print_hex_dump(KERN_DEBUG, "Written Packet Data to"
306 " USB: ", 16, 1, DUMP_PREFIX_ADDRESS,
307 buf, write_ptr->length, 1);
308#endif /* DIAG DEBUG */
309 err = usb_diag_write(driver->legacy_ch, write_ptr);
310 } else if (proc_num == QDSP_DATA) {
311 write_ptr->buf = buf;
312 err = usb_diag_write(driver->legacy_ch, write_ptr);
313 } else if (proc_num == WCNSS_DATA) {
314 write_ptr->buf = buf;
315 err = usb_diag_write(driver->legacy_ch, write_ptr);
316 }
317#ifdef CONFIG_DIAG_SDIO_PIPE
318 else if (proc_num == SDIO_DATA) {
319 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -0800320 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700321 write_ptr->buf = buf;
322 err = usb_diag_write(driver->mdm_ch, write_ptr);
323 } else
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800324 pr_err("diag: Incorrect sdio data "
325 "while USB write\n");
326 }
327#endif
328#ifdef CONFIG_DIAG_HSIC_PIPE
329 else if (proc_num == HSIC_DATA) {
330 if (driver->hsic_device_enabled) {
331 write_ptr->buf = buf;
332 err = usb_diag_write(driver->mdm_ch, write_ptr);
333 } else
334 pr_err("diag: Incorrect hsic data "
335 "while USB write\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336 }
337#endif
338 APPEND_DEBUG('d');
339 }
340#endif /* DIAG OVER USB */
341 return err;
342}
343
344void __diag_smd_wcnss_send_req(void)
345{
346 void *buf = driver->buf_in_wcnss;
347 int *in_busy_wcnss_ptr = &(driver->in_busy_wcnss);
348 struct diag_request *write_ptr_wcnss = driver->write_ptr_wcnss;
349
Shalabh Jain3893bf92011-09-18 18:37:16 -0700350 if ((!driver->in_busy_wcnss) && driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700351 int r = smd_read_avail(driver->ch_wcnss);
352 if (r > IN_BUF_SIZE) {
353 if (r < MAX_IN_BUF_SIZE) {
354 pr_err("diag: wcnss packets > %d bytes", r);
355 buf = krealloc(buf, r, GFP_KERNEL);
356 } else {
357 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
358 return;
359 }
360 }
361 if (r > 0) {
362 if (!buf) {
363 pr_err("Out of diagmem for wcnss\n");
364 } else {
365 APPEND_DEBUG('i');
366 smd_read(driver->ch_wcnss, buf, r);
367 APPEND_DEBUG('j');
368 write_ptr_wcnss->length = r;
369 *in_busy_wcnss_ptr = 1;
370 diag_device_write(buf, WCNSS_DATA,
371 write_ptr_wcnss);
372 }
373 }
374 }
375}
376
377void __diag_smd_qdsp_send_req(void)
378{
379 void *buf = NULL;
380 int *in_busy_qdsp_ptr = NULL;
381 struct diag_request *write_ptr_qdsp = NULL;
382
383 if (!driver->in_busy_qdsp_1) {
384 buf = driver->buf_in_qdsp_1;
385 write_ptr_qdsp = driver->write_ptr_qdsp_1;
386 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1);
387 } else if (!driver->in_busy_qdsp_2) {
388 buf = driver->buf_in_qdsp_2;
389 write_ptr_qdsp = driver->write_ptr_qdsp_2;
390 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2);
391 }
392
393 if (driver->chqdsp && buf) {
394 int r = smd_read_avail(driver->chqdsp);
395
396 if (r > IN_BUF_SIZE) {
397 if (r < MAX_IN_BUF_SIZE) {
398 pr_err("diag: SMD sending in "
399 "packets upto %d bytes", r);
400 buf = krealloc(buf, r, GFP_KERNEL);
401 } else {
402 pr_err("diag: SMD sending in "
403 "packets more than %d bytes", MAX_IN_BUF_SIZE);
404 return;
405 }
406 }
407 if (r > 0) {
408 if (!buf)
409 printk(KERN_INFO "Out of diagmem for QDSP\n");
410 else {
411 APPEND_DEBUG('i');
412 smd_read(driver->chqdsp, buf, r);
413 APPEND_DEBUG('j');
414 write_ptr_qdsp->length = r;
415 *in_busy_qdsp_ptr = 1;
416 diag_device_write(buf, QDSP_DATA,
417 write_ptr_qdsp);
418 }
419 }
420 }
421}
422
423static void diag_print_mask_table(void)
424{
425/* Enable this to print mask table when updated */
426#ifdef MASK_DEBUG
427 int first;
428 int last;
429 uint8_t *ptr = driver->msg_masks;
430 int i = 0;
431
432 while (*(uint32_t *)(ptr + 4)) {
433 first = *(uint32_t *)ptr;
434 ptr += 4;
435 last = *(uint32_t *)ptr;
436 ptr += 4;
437 printk(KERN_INFO "SSID %d - %d\n", first, last);
438 for (i = 0 ; i <= last - first ; i++)
439 printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
440 ptr += ((last - first) + 1)*4;
441
442 }
443#endif
444}
445
446static void diag_update_msg_mask(int start, int end , uint8_t *buf)
447{
448 int found = 0;
449 int first;
450 int last;
451 uint8_t *ptr = driver->msg_masks;
452 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
453 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
454
455 mutex_lock(&driver->diagchar_mutex);
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530456
Shalabh Jain321c8b52012-02-22 12:37:06 -0800457 /* First SSID can be zero : So check that last is non-zero */
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 if (start >= first && start <= last) {
464 ptr += (start - first)*4;
465 if (end <= last)
466 if (CHK_OVERFLOW(ptr_buffer_start, ptr,
467 ptr_buffer_end,
468 (((end - start)+1)*4)))
469 memcpy(ptr, buf , ((end - start)+1)*4);
470 else
471 printk(KERN_CRIT "Not enough"
472 " buffer space for"
473 " MSG_MASK\n");
474 else
475 printk(KERN_INFO "Unable to copy"
476 " mask change\n");
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530477
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700478 found = 1;
479 break;
480 } else {
481 ptr += ((last - first) + 1)*4;
482 }
483 }
484 /* Entry was not found - add new table */
485 if (!found) {
486 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
487 8 + ((end - start) + 1)*4)) {
488 memcpy(ptr, &(start) , 4);
489 ptr += 4;
490 memcpy(ptr, &(end), 4);
491 ptr += 4;
492 memcpy(ptr, buf , ((end - start) + 1)*4);
493 } else
494 printk(KERN_CRIT " Not enough buffer"
495 " space for MSG_MASK\n");
496 }
497 mutex_unlock(&driver->diagchar_mutex);
498 diag_print_mask_table();
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530499
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700500}
501
Shalabh Jain321c8b52012-02-22 12:37:06 -0800502static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700503{
504 uint8_t *ptr = driver->event_masks;
505 uint8_t *temp = buf + 2;
506
507 mutex_lock(&driver->diagchar_mutex);
508 if (!toggle)
509 memset(ptr, 0 , EVENT_MASK_SIZE);
510 else
511 if (CHK_OVERFLOW(ptr, ptr,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800512 ptr+EVENT_MASK_SIZE, num_bytes))
513 memcpy(ptr, temp , num_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700514 else
515 printk(KERN_CRIT "Not enough buffer space "
516 "for EVENT_MASK\n");
517 mutex_unlock(&driver->diagchar_mutex);
518}
519
520static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
521{
522 uint8_t *temp = buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700523 int i = 0;
524 unsigned char *ptr_data;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700525 int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700526 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
527
528 mutex_lock(&driver->diagchar_mutex);
529 /* Check if we already know index of this equipment ID */
530 for (i = 0; i < MAX_EQUIP_ID; i++) {
531 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
532 offset = ptr->index;
533 break;
534 }
535 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
Shalabh Jain321c8b52012-02-22 12:37:06 -0800536 /* Reached a null entry */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700537 ptr->equip_id = equip_id;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800538 ptr->num_items = num_items;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700539 ptr->index = driver->log_masks_length;
540 offset = driver->log_masks_length;
541 driver->log_masks_length += ((num_items+7)/8);
542 break;
543 }
544 ptr++;
545 }
546 ptr_data = driver->log_masks + offset;
547 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
548 + LOG_MASK_SIZE, (num_items+7)/8))
549 memcpy(ptr_data, temp , (num_items+7)/8);
550 else
551 printk(KERN_CRIT " Not enough buffer space for LOG_MASK\n");
552 mutex_unlock(&driver->diagchar_mutex);
553}
554
555static void diag_update_pkt_buffer(unsigned char *buf)
556{
557 unsigned char *ptr = driver->pkt_buf;
558 unsigned char *temp = buf;
559
560 mutex_lock(&driver->diagchar_mutex);
561 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
562 memcpy(ptr, temp , driver->pkt_length);
563 else
564 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
565 mutex_unlock(&driver->diagchar_mutex);
566}
567
568void diag_update_userspace_clients(unsigned int type)
569{
570 int i;
571
572 mutex_lock(&driver->diagchar_mutex);
573 for (i = 0; i < driver->num_clients; i++)
574 if (driver->client_map[i].pid != 0)
575 driver->data_ready[i] |= type;
576 wake_up_interruptible(&driver->wait_q);
577 mutex_unlock(&driver->diagchar_mutex);
578}
579
580void diag_update_sleeping_process(int process_id)
581{
582 int i;
583
584 mutex_lock(&driver->diagchar_mutex);
585 for (i = 0; i < driver->num_clients; i++)
586 if (driver->client_map[i].pid == process_id) {
587 driver->data_ready[i] |= PKT_TYPE;
588 break;
589 }
590 wake_up_interruptible(&driver->wait_q);
591 mutex_unlock(&driver->diagchar_mutex);
592}
593
594void diag_send_data(struct diag_master_table entry, unsigned char *buf,
595 int len, int type)
596{
597 driver->pkt_length = len;
598 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
599 diag_update_pkt_buffer(buf);
600 diag_update_sleeping_process(entry.process_id);
601 } else {
602 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700603 if (entry.client_id == MODEM_PROC && driver->ch) {
Shalabh Jain10f5f432012-01-11 11:45:44 +0530604 if (chk_apps_master() &&
Shalabh Jainc9f35092011-07-28 18:36:17 -0700605 (int)(*(char *)buf) == MODE_CMD)
Dixon Petersonff425d12011-12-06 18:12:35 -0800606 if ((int)(*(char *)(buf+1)) ==
607 RESET_ID)
Shalabh Jainc9f35092011-07-28 18:36:17 -0700608 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700609 smd_write(driver->ch, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700610 } else if (entry.client_id == QDSP_PROC &&
611 driver->chqdsp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700612 smd_write(driver->chqdsp, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700613 } else if (entry.client_id == WCNSS_PROC &&
614 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700615 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700616 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700617 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700618 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700619 }
620 }
621}
622
Shalabh Jain321c8b52012-02-22 12:37:06 -0800623void diag_modem_mask_update_fn(struct work_struct *work)
624{
625 diag_send_msg_mask_update(driver->ch_cntl);
626 diag_send_log_mask_update(driver->ch_cntl);
627 diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
628}
629
630void diag_qdsp_mask_update_fn(struct work_struct *work)
631{
632 diag_send_msg_mask_update(driver->chqdsp_cntl);
633 diag_send_log_mask_update(driver->chqdsp_cntl);
634 diag_send_event_mask_update(driver->chqdsp_cntl, diag_event_num_bytes);
635}
636
637void diag_wcnss_mask_update_fn(struct work_struct *work)
638{
639 diag_send_msg_mask_update(driver->ch_wcnss_cntl);
640 diag_send_log_mask_update(driver->ch_wcnss_cntl);
641 diag_send_event_mask_update(driver->ch_wcnss_cntl,
642 diag_event_num_bytes);
643}
644
645void diag_msg_mask_update_fn(struct work_struct *work)
646{
647 diag_send_msg_mask_update(driver->ch_cntl);
648 diag_send_msg_mask_update(driver->chqdsp_cntl);
649 diag_send_msg_mask_update(driver->ch_wcnss_cntl);
650}
651
652void diag_log_mask_update_fn(struct work_struct *work)
653{
654 diag_send_log_mask_update(driver->ch_cntl);
655 diag_send_log_mask_update(driver->chqdsp_cntl);
656 diag_send_log_mask_update(driver->ch_wcnss_cntl);
657}
658
659void diag_send_log_mask_update(smd_channel_t *ch)
660{
661 void *buf = driver->buf_log_mask_update;
662 int header_size = sizeof(struct diag_ctrl_log_mask);
663 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700664 int i, size;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800665
666 for (i = 0; i < MAX_EQUIP_ID; i++) {
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -0700667 size = (ptr->num_items+7)/8;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800668 /* reached null entry */
669 if ((ptr->equip_id == 0) && (ptr->index == 0))
670 break;
671 driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
672 driver->log_mask->num_items = ptr->num_items;
673 driver->log_mask->data_len = 11 + size;
674 driver->log_mask->stream_id = 1; /* 2, if dual stream */
675 driver->log_mask->status = 3; /* status for valid mask */
676 driver->log_mask->equip_id = ptr->equip_id;
677 driver->log_mask->log_mask_size = size;
678 memcpy(buf, driver->log_mask, header_size);
679 memcpy(buf+header_size, driver->log_masks+ptr->index, size);
680 msleep(100);
681 if (ch)
682 smd_write(ch, buf, header_size + size);
683 ptr++;
684 }
685}
686
687void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
688{
689 void *buf = driver->buf_event_mask_update;
690 int header_size = sizeof(struct diag_ctrl_event_mask);
691
692 /* send event mask update */
693 driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
694 driver->event_mask->data_len = 7 + num_bytes;
695 driver->event_mask->stream_id = 1; /* 2, if dual stream */
696 driver->event_mask->status = 3; /* status for valid mask */
697 driver->event_mask->event_config = diag_event_config; /* event config */
698 driver->event_mask->event_mask_size = num_bytes;
699 memcpy(buf, driver->event_mask, header_size);
700 memcpy(buf+header_size, driver->event_masks, num_bytes);
701 msleep(100);
702 if (ch)
703 smd_write(ch, buf, header_size + num_bytes);
704}
705
706void diag_send_msg_mask_update(smd_channel_t *ch)
707{
708 void *buf = driver->buf_msg_mask_update;
709 int first, last;
710 int header_size = sizeof(struct diag_ctrl_msg_mask);
711 uint8_t *ptr = driver->msg_masks;
712
713 while (*(uint32_t *)(ptr + 4)) {
714 first = *(uint32_t *)ptr;
715 ptr += 4;
716 last = *(uint32_t *)ptr;
717 ptr += 4;
718 /* send event mask update */
719 driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
720 driver->msg_mask->msg_mask_size = last - first + 1;
721 driver->msg_mask->data_len = 11 +
722 4 * (driver->msg_mask->msg_mask_size);
723 driver->msg_mask->stream_id = 1; /* 2, if dual stream */
724 driver->msg_mask->status = 3; /* status for valid mask */
725 driver->msg_mask->msg_mode = 0; /* Legcay mode */
726 driver->msg_mask->ssid_first = first;
727 driver->msg_mask->ssid_last = last;
728 memcpy(buf, driver->msg_mask, header_size);
729 memcpy(buf+header_size, ptr,
730 4 * (driver->msg_mask->msg_mask_size));
731 /* since mask updates are slow, so sleep needed as to
732 prevent modem running out of DSM items */
733 msleep(100);
734 if (ch)
735 smd_write(ch, buf,
736 header_size + 4*(driver->msg_mask->msg_mask_size));
737 ptr += ((last - first) + 1)*4;
738 }
739}
740
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700741static int diag_process_apps_pkt(unsigned char *buf, int len)
742{
743 uint16_t subsys_cmd_code;
744 int subsys_id, ssid_first, ssid_last, ssid_range;
745 int packet_type = 1, i, cmd_code;
746 unsigned char *temp = buf;
747 int data_type;
748#if defined(CONFIG_DIAG_OVER_USB)
749 int payload_length;
750 unsigned char *ptr;
751#endif
752
Shalabh Jain321c8b52012-02-22 12:37:06 -0800753 /* Set log masks */
754 if (*buf == 0x73 && *(int *)(buf+4) == 3) {
755 buf += 8;
756 /* Read Equip ID and pass as first param below*/
757 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
758 diag_update_userspace_clients(LOG_MASKS_TYPE);
759#if defined(CONFIG_DIAG_OVER_USB)
760 if (chk_apps_only()) {
761 driver->apps_rsp_buf[0] = 0x73;
762 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
763 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
764 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
765 for (i = 0; i < payload_length; i++)
766 *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
767 queue_work(driver->diag_cntl_wq,
768 &(driver->diag_log_mask_update_work));
769 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
770 return 0;
771 } else
772 buf = temp;
773#endif
774 } /* Check for set message mask */
775 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
776 ssid_first = *(uint16_t *)(buf + 2);
777 ssid_last = *(uint16_t *)(buf + 4);
778 ssid_range = 4 * (ssid_last - ssid_first + 1);
779 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
780 diag_update_userspace_clients(MSG_MASKS_TYPE);
781#if defined(CONFIG_DIAG_OVER_USB)
782 if (chk_apps_only()) {
783 for (i = 0; i < 8 + ssid_range; i++)
784 *(driver->apps_rsp_buf + i) = *(buf+i);
785 *(driver->apps_rsp_buf + 6) = 0x1;
786 queue_work(driver->diag_cntl_wq,
787 &(driver->diag_msg_mask_update_work));
788 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
789 return 0;
790 } else
791 buf = temp;
792#endif
793 } else if (*buf == 0x82) { /* event mask change */
794 buf += 4;
795 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
796 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
797 diag_update_userspace_clients(EVENT_MASKS_TYPE);
798#if defined(CONFIG_DIAG_OVER_USB)
799 if (chk_apps_only()) {
800 driver->apps_rsp_buf[0] = 0x82;
801 driver->apps_rsp_buf[1] = 0x0;
802 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
803 *(uint16_t *)(driver->apps_rsp_buf + 4) =
804 EVENT_LAST_ID + 1;
805 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
806 *(unsigned char *)(driver->apps_rsp_buf + 6 + i)
807 = 0x0;
808 /* cannot do this on work queue, as each event update
809 needs a num_bytes variable. Each queue_work call will
810 overwrite the previous input, as its the same struct */
811 diag_send_event_mask_update(driver->ch_cntl,
812 diag_event_num_bytes);
813 diag_send_event_mask_update(driver->chqdsp_cntl,
814 diag_event_num_bytes);
815 diag_send_event_mask_update(driver->ch_wcnss_cntl,
816 diag_event_num_bytes);
817 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
818 return 0;
819 } else
820 buf = temp;
821#endif
822 } else if (*buf == 0x60) {
823 diag_event_config = *(buf+1);
824#if defined(CONFIG_DIAG_OVER_USB)
825 if (chk_apps_only()) {
826 driver->apps_rsp_buf[0] = 0x60;
827 driver->apps_rsp_buf[1] = 0x0;
828 driver->apps_rsp_buf[2] = 0x0;
829 diag_send_event_mask_update(driver->ch_cntl,
830 diag_event_num_bytes);
831 diag_send_event_mask_update(driver->chqdsp_cntl,
832 diag_event_num_bytes);
833 diag_send_event_mask_update(driver->ch_wcnss_cntl,
834 diag_event_num_bytes);
835 ENCODE_RSP_AND_SEND(2);
836 return 0;
837 }
838#endif
839 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700840 /* Check for registered clients and forward packet to apropriate proc */
841 cmd_code = (int)(*(char *)buf);
842 temp++;
843 subsys_id = (int)(*(char *)temp);
844 temp++;
845 subsys_cmd_code = *(uint16_t *)temp;
846 temp += 2;
847 data_type = APPS_DATA;
848 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530849 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700850 if (subsys_id != RESET_ID)
851 data_type = MODEM_DATA;
852 }
853
854 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -0800855 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700856 entry = driver->table[i];
857 if (entry.process_id != NO_PROCESS) {
858 if (entry.cmd_code == cmd_code && entry.subsys_id ==
859 subsys_id && entry.cmd_code_lo <=
860 subsys_cmd_code &&
861 entry.cmd_code_hi >= subsys_cmd_code) {
862 diag_send_data(entry, buf, len, data_type);
863 packet_type = 0;
864 } else if (entry.cmd_code == 255
865 && cmd_code == 75) {
866 if (entry.subsys_id ==
867 subsys_id &&
868 entry.cmd_code_lo <=
869 subsys_cmd_code &&
870 entry.cmd_code_hi >=
871 subsys_cmd_code) {
872 diag_send_data(entry, buf, len,
873 data_type);
874 packet_type = 0;
875 }
876 } else if (entry.cmd_code == 255 &&
877 entry.subsys_id == 255) {
878 if (entry.cmd_code_lo <=
879 cmd_code &&
880 entry.
881 cmd_code_hi >= cmd_code) {
882 diag_send_data(entry, buf, len,
883 data_type);
884 packet_type = 0;
885 }
886 }
887 }
888 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700889#if defined(CONFIG_DIAG_OVER_USB)
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700890 /* Check for Apps Only & get event mask request */
Shalabh Jain321c8b52012-02-22 12:37:06 -0800891 if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700892 driver->apps_rsp_buf[0] = 0x81;
893 driver->apps_rsp_buf[1] = 0x0;
894 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
895 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
896 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
897 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
898 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
899 return 0;
900 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700901 /* Get log ID range & Check for Apps Only */
902 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700903 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
904 driver->apps_rsp_buf[0] = 0x73;
905 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
906 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
907 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
908 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
909 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
910 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
911 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
912 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
913 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
914 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
915 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
916 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
917 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
918 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
919 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
920 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
921 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
922 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
923 ENCODE_RSP_AND_SEND(75);
924 return 0;
925 }
926 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700927 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700928 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
929 driver->apps_rsp_buf[0] = 0x7d;
930 driver->apps_rsp_buf[1] = 0x1;
931 driver->apps_rsp_buf[2] = 0x1;
932 driver->apps_rsp_buf[3] = 0x0;
933 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
934 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
935 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
936 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
937 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
938 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
939 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
940 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
941 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
942 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
943 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
944 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
945 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
946 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
947 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
948 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
949 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
950 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
951 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
952 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
953 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
954 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
955 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
956 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
957 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
958 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
959 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
960 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
961 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
962 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
963 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
964 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
965 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
966 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
967 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
968 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
969 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
970 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
971 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800972 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
973 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
974 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
975 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
976 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
977 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
978 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
979 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
980 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700981 return 0;
982 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700983 /* Check for Apps Only Respond to Get Subsys Build mask */
984 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700985 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
986 ssid_first = *(uint16_t *)(buf + 2);
987 ssid_last = *(uint16_t *)(buf + 4);
988 ssid_range = 4 * (ssid_last - ssid_first + 1);
989 /* frame response */
990 driver->apps_rsp_buf[0] = 0x7d;
991 driver->apps_rsp_buf[1] = 0x2;
992 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
993 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
994 driver->apps_rsp_buf[6] = 0x1;
995 driver->apps_rsp_buf[7] = 0x0;
996 ptr = driver->apps_rsp_buf + 8;
997 /* bld time masks */
998 switch (ssid_first) {
999 case MSG_SSID_0:
1000 for (i = 0; i < ssid_range; i += 4)
1001 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
1002 break;
1003 case MSG_SSID_1:
1004 for (i = 0; i < ssid_range; i += 4)
1005 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
1006 break;
1007 case MSG_SSID_2:
1008 for (i = 0; i < ssid_range; i += 4)
1009 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
1010 break;
1011 case MSG_SSID_3:
1012 for (i = 0; i < ssid_range; i += 4)
1013 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
1014 break;
1015 case MSG_SSID_4:
1016 for (i = 0; i < ssid_range; i += 4)
1017 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
1018 break;
1019 case MSG_SSID_5:
1020 for (i = 0; i < ssid_range; i += 4)
1021 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
1022 break;
1023 case MSG_SSID_6:
1024 for (i = 0; i < ssid_range; i += 4)
1025 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
1026 break;
1027 case MSG_SSID_7:
1028 for (i = 0; i < ssid_range; i += 4)
1029 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
1030 break;
1031 case MSG_SSID_8:
1032 for (i = 0; i < ssid_range; i += 4)
1033 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
1034 break;
1035 case MSG_SSID_9:
1036 for (i = 0; i < ssid_range; i += 4)
1037 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
1038 break;
1039 case MSG_SSID_10:
1040 for (i = 0; i < ssid_range; i += 4)
1041 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
1042 break;
1043 case MSG_SSID_11:
1044 for (i = 0; i < ssid_range; i += 4)
1045 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
1046 break;
1047 case MSG_SSID_12:
1048 for (i = 0; i < ssid_range; i += 4)
1049 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1050 break;
1051 case MSG_SSID_13:
1052 for (i = 0; i < ssid_range; i += 4)
1053 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1054 break;
1055 case MSG_SSID_14:
1056 for (i = 0; i < ssid_range; i += 4)
1057 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1058 break;
1059 case MSG_SSID_15:
1060 for (i = 0; i < ssid_range; i += 4)
1061 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1062 break;
1063 case MSG_SSID_16:
1064 for (i = 0; i < ssid_range; i += 4)
1065 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1066 break;
1067 case MSG_SSID_17:
1068 for (i = 0; i < ssid_range; i += 4)
1069 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1070 break;
1071 case MSG_SSID_18:
1072 for (i = 0; i < ssid_range; i += 4)
1073 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1074 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001075 case MSG_SSID_19:
1076 for (i = 0; i < ssid_range; i += 4)
1077 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1078 break;
1079 case MSG_SSID_20:
1080 for (i = 0; i < ssid_range; i += 4)
1081 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1082 break;
1083 case MSG_SSID_21:
1084 for (i = 0; i < ssid_range; i += 4)
1085 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1086 break;
1087 case MSG_SSID_22:
1088 for (i = 0; i < ssid_range; i += 4)
1089 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1090 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001091 }
1092 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1093 return 0;
1094 }
1095 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301096 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001097 /* send response back */
1098 driver->apps_rsp_buf[0] = *buf;
1099 ENCODE_RSP_AND_SEND(0);
1100 msleep(5000);
1101 /* call download API */
1102 msm_set_restart_mode(RESTART_DLOAD);
1103 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1104 kernel_restart(NULL);
1105 /* Not required, represents that command isnt sent to modem */
1106 return 0;
1107 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001108 /* Check for polling for Apps only DIAG */
1109 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1110 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001111 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001112 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001113 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001114 for (i = 0; i < 3; i++)
1115 driver->apps_rsp_buf[i] = *(buf+i);
1116 for (i = 0; i < 13; i++)
1117 driver->apps_rsp_buf[i+3] = 0;
1118
1119 ENCODE_RSP_AND_SEND(15);
1120 return 0;
1121 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001122 }
1123 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001124 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001125 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001126 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001127 for (i = 0; i < 55; i++)
1128 driver->apps_rsp_buf[i] = 0;
1129
1130 ENCODE_RSP_AND_SEND(54);
1131 return 0;
1132 }
1133 /* respond to 0x7c command */
1134 else if (*buf == 0x7c) {
1135 driver->apps_rsp_buf[0] = 0x7c;
1136 for (i = 1; i < 8; i++)
1137 driver->apps_rsp_buf[i] = 0;
1138 /* Tools ID for APQ 8060 */
1139 *(int *)(driver->apps_rsp_buf + 8) =
1140 chk_config_get_id();
1141 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1142 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1143 ENCODE_RSP_AND_SEND(13);
1144 return 0;
1145 }
1146 }
1147#endif
1148 return packet_type;
1149}
1150
1151#ifdef CONFIG_DIAG_OVER_USB
1152void diag_send_error_rsp(int index)
1153{
1154 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301155
1156 if (index > 490) {
1157 pr_err("diag: error response too huge, aborting\n");
1158 return;
1159 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001160 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1161 for (i = 0; i < index; i++)
1162 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1163 ENCODE_RSP_AND_SEND(index - 3);
1164}
1165#else
1166static inline void diag_send_error_rsp(int index) {}
1167#endif
1168
1169void diag_process_hdlc(void *data, unsigned len)
1170{
1171 struct diag_hdlc_decode_type hdlc;
1172 int ret, type = 0;
1173 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1174 hdlc.dest_ptr = driver->hdlc_buf;
1175 hdlc.dest_size = USB_MAX_OUT_BUF;
1176 hdlc.src_ptr = data;
1177 hdlc.src_size = len;
1178 hdlc.src_idx = 0;
1179 hdlc.dest_idx = 0;
1180 hdlc.escaping = 0;
1181
1182 ret = diag_hdlc_decode(&hdlc);
1183
1184 if (ret)
1185 type = diag_process_apps_pkt(driver->hdlc_buf,
1186 hdlc.dest_idx - 3);
1187 else if (driver->debug_flag) {
1188 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1189 " errors or partial packet received, packet"
1190 " length = %d\n", len);
1191 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1192 DUMP_PREFIX_ADDRESS, data, len, 1);
1193 driver->debug_flag = 0;
1194 }
1195 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001196 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001197 diag_send_error_rsp(hdlc.dest_idx);
1198 type = 0;
1199 }
1200 /* implies this packet is NOT meant for apps */
1201 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001202 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001203 diag_send_error_rsp(hdlc.dest_idx);
1204 } else { /* APQ 8060, Let Q6 respond */
1205 if (driver->chqdsp)
1206 smd_write(driver->chqdsp, driver->hdlc_buf,
1207 hdlc.dest_idx - 3);
1208 }
1209 type = 0;
1210 }
1211
1212#ifdef DIAG_DEBUG
1213 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1214 for (i = 0; i < hdlc.dest_idx; i++)
1215 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1216 driver->hdlc_buf)+i));
1217#endif /* DIAG DEBUG */
1218 /* ignore 2 bytes for CRC, one for 7E and send */
1219 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1220 APPEND_DEBUG('g');
1221 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1222 APPEND_DEBUG('h');
1223#ifdef DIAG_DEBUG
1224 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1225 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1226 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1227#endif /* DIAG DEBUG */
1228 }
1229}
1230
1231#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001232/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1233#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001234#define N_LEGACY_READ 1
1235
1236int diagfwd_connect(void)
1237{
1238 int err;
1239
1240 printk(KERN_DEBUG "diag: USB connected\n");
1241 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1242 N_LEGACY_READ);
1243 if (err)
1244 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1245
1246 driver->usb_connected = 1;
1247 driver->in_busy_1 = 0;
1248 driver->in_busy_2 = 0;
1249 driver->in_busy_qdsp_1 = 0;
1250 driver->in_busy_qdsp_2 = 0;
1251 driver->in_busy_wcnss = 0;
1252
1253 /* Poll SMD channels to check for data*/
1254 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1255 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1256 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001257 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001258 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1259 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1260 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001261 /* Poll USB channel to check for data*/
1262 queue_work(driver->diag_wq, &(driver->diag_read_work));
1263#ifdef CONFIG_DIAG_SDIO_PIPE
1264 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1265 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1266 diagfwd_connect_sdio();
1267 else
1268 printk(KERN_INFO "diag: No USB MDM ch");
1269 }
1270#endif
1271 return 0;
1272}
1273
1274int diagfwd_disconnect(void)
1275{
1276 printk(KERN_DEBUG "diag: USB disconnected\n");
1277 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001278 driver->debug_flag = 1;
1279 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001280 if (driver->logging_mode == USB_MODE) {
1281 driver->in_busy_1 = 1;
1282 driver->in_busy_2 = 1;
1283 driver->in_busy_qdsp_1 = 1;
1284 driver->in_busy_qdsp_2 = 1;
1285 driver->in_busy_wcnss = 1;
1286 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001287#ifdef CONFIG_DIAG_SDIO_PIPE
1288 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1289 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1290 diagfwd_disconnect_sdio();
1291#endif
1292 /* TBD - notify and flow control SMD */
1293 return 0;
1294}
1295
1296int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1297{
1298 unsigned char *buf = diag_write_ptr->buf;
1299 /*Determine if the write complete is for data from modem/apps/q6 */
1300 /* Need a context variable here instead */
1301 if (buf == (void *)driver->buf_in_1) {
1302 driver->in_busy_1 = 0;
1303 APPEND_DEBUG('o');
1304 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1305 } else if (buf == (void *)driver->buf_in_2) {
1306 driver->in_busy_2 = 0;
1307 APPEND_DEBUG('O');
1308 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1309 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1310 driver->in_busy_qdsp_1 = 0;
1311 APPEND_DEBUG('p');
1312 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1313 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1314 driver->in_busy_qdsp_2 = 0;
1315 APPEND_DEBUG('P');
1316 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1317 } else if (buf == (void *)driver->buf_in_wcnss) {
1318 driver->in_busy_wcnss = 0;
1319 APPEND_DEBUG('R');
1320 queue_work(driver->diag_wq,
1321 &(driver->diag_read_smd_wcnss_work));
1322 }
1323#ifdef CONFIG_DIAG_SDIO_PIPE
1324 else if (buf == (void *)driver->buf_in_sdio)
1325 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001326 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001327 diagfwd_write_complete_sdio();
1328 else
1329 pr_err("diag: Incorrect buffer pointer while WRITE");
1330#endif
1331 else {
1332 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1333 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1334 POOL_TYPE_WRITE_STRUCT);
1335 APPEND_DEBUG('q');
1336 }
1337 return 0;
1338}
1339
1340int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1341{
1342 int status = diag_read_ptr->status;
1343 unsigned char *buf = diag_read_ptr->buf;
1344
1345 /* Determine if the read complete is for data on legacy/mdm ch */
1346 if (buf == (void *)driver->usb_buf_out) {
1347 driver->read_len_legacy = diag_read_ptr->actual;
1348 APPEND_DEBUG('s');
1349#ifdef DIAG_DEBUG
1350 printk(KERN_INFO "read data from USB, pkt length %d",
1351 diag_read_ptr->actual);
1352 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1353 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1354 diag_read_ptr->actual, 1);
1355#endif /* DIAG DEBUG */
1356 if (driver->logging_mode == USB_MODE) {
1357 if (status != -ECONNRESET && status != -ESHUTDOWN)
1358 queue_work(driver->diag_wq,
1359 &(driver->diag_proc_hdlc_work));
1360 else
1361 queue_work(driver->diag_wq,
1362 &(driver->diag_read_work));
1363 }
1364 }
1365#ifdef CONFIG_DIAG_SDIO_PIPE
1366 else if (buf == (void *)driver->usb_buf_mdm_out) {
1367 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001368 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001369 driver->read_len_mdm = diag_read_ptr->actual;
1370 diagfwd_read_complete_sdio();
1371 } else
1372 pr_err("diag: Incorrect buffer pointer while READ");
1373 }
1374#endif
1375 else
1376 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1377
1378 return 0;
1379}
1380
1381void diag_read_work_fn(struct work_struct *work)
1382{
1383 APPEND_DEBUG('d');
1384 driver->usb_read_ptr->buf = driver->usb_buf_out;
1385 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1386 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1387 APPEND_DEBUG('e');
1388}
1389
1390void diag_process_hdlc_fn(struct work_struct *work)
1391{
1392 APPEND_DEBUG('D');
1393 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1394 diag_read_work_fn(work);
1395 APPEND_DEBUG('E');
1396}
1397
1398void diag_usb_legacy_notifier(void *priv, unsigned event,
1399 struct diag_request *d_req)
1400{
1401 switch (event) {
1402 case USB_DIAG_CONNECT:
1403 diagfwd_connect();
1404 break;
1405 case USB_DIAG_DISCONNECT:
1406 diagfwd_disconnect();
1407 break;
1408 case USB_DIAG_READ_DONE:
1409 diagfwd_read_complete(d_req);
1410 break;
1411 case USB_DIAG_WRITE_DONE:
1412 diagfwd_write_complete(d_req);
1413 break;
1414 default:
1415 printk(KERN_ERR "Unknown event from USB diag\n");
1416 break;
1417 }
1418}
1419
1420#endif /* DIAG OVER USB */
1421
1422static void diag_smd_notify(void *ctxt, unsigned event)
1423{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001424 if (event == SMD_EVENT_CLOSE) {
1425 pr_info("diag: clean modem registration\n");
1426 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001427 driver->ch = 0;
1428 return;
1429 } else if (event == SMD_EVENT_OPEN) {
1430 driver->ch = ch_temp;
1431 }
1432 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001433}
1434
1435#if defined(CONFIG_MSM_N_WAY_SMD)
1436static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1437{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001438 if (event == SMD_EVENT_CLOSE) {
1439 pr_info("diag: clean lpass registration\n");
1440 diag_clear_reg(QDSP_PROC);
1441 driver->chqdsp = 0;
1442 return;
1443 } else if (event == SMD_EVENT_OPEN) {
1444 driver->chqdsp = chqdsp_temp;
1445 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001446 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1447}
1448#endif
1449
1450static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1451{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001452 if (event == SMD_EVENT_CLOSE) {
1453 pr_info("diag: clean wcnss registration\n");
1454 diag_clear_reg(WCNSS_PROC);
1455 driver->ch_wcnss = 0;
1456 return;
1457 } else if (event == SMD_EVENT_OPEN) {
1458 driver->ch_wcnss = ch_wcnss_temp;
1459 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001460 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1461}
1462
1463static int diag_smd_probe(struct platform_device *pdev)
1464{
1465 int r = 0;
1466
Shalabh Jaineefee052011-11-08 23:46:03 -08001467 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001468 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001469 ch_temp = driver->ch;
1470 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001471#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001472 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001473 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1474 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001475 chqdsp_temp = driver->chqdsp;
1476 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001477#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001478 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001479 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1480 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001481 ch_wcnss_temp = driver->ch_wcnss;
1482 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001483 pm_runtime_set_active(&pdev->dev);
1484 pm_runtime_enable(&pdev->dev);
1485 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1486
1487 return 0;
1488}
1489
1490static int diagfwd_runtime_suspend(struct device *dev)
1491{
1492 dev_dbg(dev, "pm_runtime: suspending...\n");
1493 return 0;
1494}
1495
1496static int diagfwd_runtime_resume(struct device *dev)
1497{
1498 dev_dbg(dev, "pm_runtime: resuming...\n");
1499 return 0;
1500}
1501
1502static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1503 .runtime_suspend = diagfwd_runtime_suspend,
1504 .runtime_resume = diagfwd_runtime_resume,
1505};
1506
1507static struct platform_driver msm_smd_ch1_driver = {
1508
1509 .probe = diag_smd_probe,
1510 .driver = {
1511 .name = "DIAG",
1512 .owner = THIS_MODULE,
1513 .pm = &diagfwd_dev_pm_ops,
1514 },
1515};
1516
1517static struct platform_driver diag_smd_lite_driver = {
1518
1519 .probe = diag_smd_probe,
1520 .driver = {
1521 .name = "APPS_RIVA_DATA",
1522 .owner = THIS_MODULE,
1523 .pm = &diagfwd_dev_pm_ops,
1524 },
1525};
1526
1527void diagfwd_init(void)
1528{
1529 diag_debug_buf_idx = 0;
1530 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001531 driver->use_device_tree = has_device_tree();
Shalabh Jain321c8b52012-02-22 12:37:06 -08001532
1533 if (driver->event_mask == NULL) {
1534 driver->event_mask = kzalloc(sizeof(
1535 struct diag_ctrl_event_mask), GFP_KERNEL);
1536 if (driver->event_mask == NULL)
1537 goto err;
1538 }
1539 if (driver->msg_mask == NULL) {
1540 driver->msg_mask = kzalloc(sizeof(
1541 struct diag_ctrl_msg_mask), GFP_KERNEL);
1542 if (driver->msg_mask == NULL)
1543 goto err;
1544 }
1545 if (driver->log_mask == NULL) {
1546 driver->log_mask = kzalloc(sizeof(
1547 struct diag_ctrl_log_mask), GFP_KERNEL);
1548 if (driver->log_mask == NULL)
1549 goto err;
1550 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001551 if (driver->buf_in_1 == NULL) {
1552 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1553 if (driver->buf_in_1 == NULL)
1554 goto err;
1555 }
1556 if (driver->buf_in_2 == NULL) {
1557 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1558 if (driver->buf_in_2 == NULL)
1559 goto err;
1560 }
1561 if (driver->buf_in_qdsp_1 == NULL) {
1562 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1563 if (driver->buf_in_qdsp_1 == NULL)
1564 goto err;
1565 }
1566 if (driver->buf_in_qdsp_2 == NULL) {
1567 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1568 if (driver->buf_in_qdsp_2 == NULL)
1569 goto err;
1570 }
1571 if (driver->buf_in_wcnss == NULL) {
1572 driver->buf_in_wcnss = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1573 if (driver->buf_in_wcnss == NULL)
1574 goto err;
1575 }
Shalabh Jain321c8b52012-02-22 12:37:06 -08001576 if (driver->buf_msg_mask_update == NULL) {
1577 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1578 GFP_KERNEL);
1579 if (driver->buf_msg_mask_update == NULL)
1580 goto err;
1581 }
1582 if (driver->buf_log_mask_update == NULL) {
1583 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1584 GFP_KERNEL);
1585 if (driver->buf_log_mask_update == NULL)
1586 goto err;
1587 }
1588 if (driver->buf_event_mask_update == NULL) {
1589 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1590 GFP_KERNEL);
1591 if (driver->buf_event_mask_update == NULL)
1592 goto err;
1593 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001594 if (driver->usb_buf_out == NULL &&
1595 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1596 GFP_KERNEL)) == NULL)
1597 goto err;
1598 if (driver->hdlc_buf == NULL
1599 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1600 goto err;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001601 if (driver->user_space_data == NULL)
1602 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1603 if (driver->user_space_data == NULL)
1604 goto err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001605 if (driver->msg_masks == NULL
1606 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1607 GFP_KERNEL)) == NULL)
1608 goto err;
1609 if (driver->log_masks == NULL &&
1610 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1611 goto err;
Shalabh Jainfbf3bdc2012-03-16 21:02:50 -07001612 driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001613 if (driver->event_masks == NULL &&
1614 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1615 GFP_KERNEL)) == NULL)
1616 goto err;
1617 if (driver->client_map == NULL &&
1618 (driver->client_map = kzalloc
1619 ((driver->num_clients) * sizeof(struct diag_client_map),
1620 GFP_KERNEL)) == NULL)
1621 goto err;
1622 if (driver->buf_tbl == NULL)
1623 driver->buf_tbl = kzalloc(buf_tbl_size *
1624 sizeof(struct diag_write_device), GFP_KERNEL);
1625 if (driver->buf_tbl == NULL)
1626 goto err;
1627 if (driver->data_ready == NULL &&
1628 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1629 , GFP_KERNEL)) == NULL)
1630 goto err;
1631 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001632 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001633 sizeof(struct diag_master_table),
1634 GFP_KERNEL)) == NULL)
1635 goto err;
1636 if (driver->write_ptr_1 == NULL) {
1637 driver->write_ptr_1 = kzalloc(
1638 sizeof(struct diag_request), GFP_KERNEL);
1639 if (driver->write_ptr_1 == NULL)
1640 goto err;
1641 }
1642 if (driver->write_ptr_2 == NULL) {
1643 driver->write_ptr_2 = kzalloc(
1644 sizeof(struct diag_request), GFP_KERNEL);
1645 if (driver->write_ptr_2 == NULL)
1646 goto err;
1647 }
1648 if (driver->write_ptr_qdsp_1 == NULL) {
1649 driver->write_ptr_qdsp_1 = kzalloc(
1650 sizeof(struct diag_request), GFP_KERNEL);
1651 if (driver->write_ptr_qdsp_1 == NULL)
1652 goto err;
1653 }
1654 if (driver->write_ptr_qdsp_2 == NULL) {
1655 driver->write_ptr_qdsp_2 = kzalloc(
1656 sizeof(struct diag_request), GFP_KERNEL);
1657 if (driver->write_ptr_qdsp_2 == NULL)
1658 goto err;
1659 }
1660 if (driver->write_ptr_wcnss == NULL) {
1661 driver->write_ptr_wcnss = kzalloc(
1662 sizeof(struct diag_request), GFP_KERNEL);
1663 if (driver->write_ptr_wcnss == NULL)
1664 goto err;
1665 }
1666 if (driver->usb_read_ptr == NULL) {
1667 driver->usb_read_ptr = kzalloc(
1668 sizeof(struct diag_request), GFP_KERNEL);
1669 if (driver->usb_read_ptr == NULL)
1670 goto err;
1671 }
1672 if (driver->pkt_buf == NULL &&
1673 (driver->pkt_buf = kzalloc(PKT_SIZE,
1674 GFP_KERNEL)) == NULL)
1675 goto err;
1676 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001677 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001678 if (driver->apps_rsp_buf == NULL)
1679 goto err;
1680 }
1681 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1682#ifdef CONFIG_DIAG_OVER_USB
1683 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1684 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001685 INIT_WORK(&(driver->diag_msg_mask_update_work),
1686 diag_msg_mask_update_fn);
1687 INIT_WORK(&(driver->diag_log_mask_update_work),
1688 diag_log_mask_update_fn);
1689 INIT_WORK(&(driver->diag_modem_mask_update_work),
1690 diag_modem_mask_update_fn);
1691 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
1692 diag_qdsp_mask_update_fn);
1693 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
1694 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001695 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
1696 diag_usb_legacy_notifier);
1697 if (IS_ERR(driver->legacy_ch)) {
1698 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
1699 goto err;
1700 }
1701#endif
1702 platform_driver_register(&msm_smd_ch1_driver);
1703 platform_driver_register(&diag_smd_lite_driver);
1704
1705 return;
1706err:
1707 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08001708 kfree(driver->event_mask);
1709 kfree(driver->log_mask);
1710 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001711 kfree(driver->buf_in_1);
1712 kfree(driver->buf_in_2);
1713 kfree(driver->buf_in_qdsp_1);
1714 kfree(driver->buf_in_qdsp_2);
1715 kfree(driver->buf_in_wcnss);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001716 kfree(driver->buf_msg_mask_update);
1717 kfree(driver->buf_log_mask_update);
1718 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001719 kfree(driver->usb_buf_out);
1720 kfree(driver->hdlc_buf);
1721 kfree(driver->msg_masks);
1722 kfree(driver->log_masks);
1723 kfree(driver->event_masks);
1724 kfree(driver->client_map);
1725 kfree(driver->buf_tbl);
1726 kfree(driver->data_ready);
1727 kfree(driver->table);
1728 kfree(driver->pkt_buf);
1729 kfree(driver->write_ptr_1);
1730 kfree(driver->write_ptr_2);
1731 kfree(driver->write_ptr_qdsp_1);
1732 kfree(driver->write_ptr_qdsp_2);
1733 kfree(driver->write_ptr_wcnss);
1734 kfree(driver->usb_read_ptr);
1735 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001736 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001737 if (driver->diag_wq)
1738 destroy_workqueue(driver->diag_wq);
1739}
1740
1741void diagfwd_exit(void)
1742{
1743 smd_close(driver->ch);
1744 smd_close(driver->chqdsp);
1745 smd_close(driver->ch_wcnss);
1746 driver->ch = 0; /* SMD can make this NULL */
1747 driver->chqdsp = 0;
1748 driver->ch_wcnss = 0;
1749#ifdef CONFIG_DIAG_OVER_USB
1750 if (driver->usb_connected)
1751 usb_diag_free_req(driver->legacy_ch);
1752 usb_diag_close(driver->legacy_ch);
1753#endif
1754 platform_driver_unregister(&msm_smd_ch1_driver);
1755 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001756 kfree(driver->event_mask);
1757 kfree(driver->log_mask);
1758 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001759 kfree(driver->buf_in_1);
1760 kfree(driver->buf_in_2);
1761 kfree(driver->buf_in_qdsp_1);
1762 kfree(driver->buf_in_qdsp_2);
1763 kfree(driver->buf_in_wcnss);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001764 kfree(driver->buf_msg_mask_update);
1765 kfree(driver->buf_log_mask_update);
1766 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001767 kfree(driver->usb_buf_out);
1768 kfree(driver->hdlc_buf);
1769 kfree(driver->msg_masks);
1770 kfree(driver->log_masks);
1771 kfree(driver->event_masks);
1772 kfree(driver->client_map);
1773 kfree(driver->buf_tbl);
1774 kfree(driver->data_ready);
1775 kfree(driver->table);
1776 kfree(driver->pkt_buf);
1777 kfree(driver->write_ptr_1);
1778 kfree(driver->write_ptr_2);
1779 kfree(driver->write_ptr_qdsp_1);
1780 kfree(driver->write_ptr_qdsp_2);
1781 kfree(driver->write_ptr_wcnss);
1782 kfree(driver->usb_read_ptr);
1783 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001784 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001785 destroy_workqueue(driver->diag_wq);
1786}