blob: f16aa0c5c4d0e9cb2b295772b1aa7a4d1c747d23 [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;
525 int offset = 8*MAX_EQUIP_ID;
526 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;
664 int i, size = (driver->log_mask->num_items+7)/8;
665
666 for (i = 0; i < MAX_EQUIP_ID; i++) {
667 /* reached null entry */
668 if ((ptr->equip_id == 0) && (ptr->index == 0))
669 break;
670 driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
671 driver->log_mask->num_items = ptr->num_items;
672 driver->log_mask->data_len = 11 + size;
673 driver->log_mask->stream_id = 1; /* 2, if dual stream */
674 driver->log_mask->status = 3; /* status for valid mask */
675 driver->log_mask->equip_id = ptr->equip_id;
676 driver->log_mask->log_mask_size = size;
677 memcpy(buf, driver->log_mask, header_size);
678 memcpy(buf+header_size, driver->log_masks+ptr->index, size);
679 msleep(100);
680 if (ch)
681 smd_write(ch, buf, header_size + size);
682 ptr++;
683 }
684}
685
686void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
687{
688 void *buf = driver->buf_event_mask_update;
689 int header_size = sizeof(struct diag_ctrl_event_mask);
690
691 /* send event mask update */
692 driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
693 driver->event_mask->data_len = 7 + num_bytes;
694 driver->event_mask->stream_id = 1; /* 2, if dual stream */
695 driver->event_mask->status = 3; /* status for valid mask */
696 driver->event_mask->event_config = diag_event_config; /* event config */
697 driver->event_mask->event_mask_size = num_bytes;
698 memcpy(buf, driver->event_mask, header_size);
699 memcpy(buf+header_size, driver->event_masks, num_bytes);
700 msleep(100);
701 if (ch)
702 smd_write(ch, buf, header_size + num_bytes);
703}
704
705void diag_send_msg_mask_update(smd_channel_t *ch)
706{
707 void *buf = driver->buf_msg_mask_update;
708 int first, last;
709 int header_size = sizeof(struct diag_ctrl_msg_mask);
710 uint8_t *ptr = driver->msg_masks;
711
712 while (*(uint32_t *)(ptr + 4)) {
713 first = *(uint32_t *)ptr;
714 ptr += 4;
715 last = *(uint32_t *)ptr;
716 ptr += 4;
717 /* send event mask update */
718 driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
719 driver->msg_mask->msg_mask_size = last - first + 1;
720 driver->msg_mask->data_len = 11 +
721 4 * (driver->msg_mask->msg_mask_size);
722 driver->msg_mask->stream_id = 1; /* 2, if dual stream */
723 driver->msg_mask->status = 3; /* status for valid mask */
724 driver->msg_mask->msg_mode = 0; /* Legcay mode */
725 driver->msg_mask->ssid_first = first;
726 driver->msg_mask->ssid_last = last;
727 memcpy(buf, driver->msg_mask, header_size);
728 memcpy(buf+header_size, ptr,
729 4 * (driver->msg_mask->msg_mask_size));
730 /* since mask updates are slow, so sleep needed as to
731 prevent modem running out of DSM items */
732 msleep(100);
733 if (ch)
734 smd_write(ch, buf,
735 header_size + 4*(driver->msg_mask->msg_mask_size));
736 ptr += ((last - first) + 1)*4;
737 }
738}
739
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700740static int diag_process_apps_pkt(unsigned char *buf, int len)
741{
742 uint16_t subsys_cmd_code;
743 int subsys_id, ssid_first, ssid_last, ssid_range;
744 int packet_type = 1, i, cmd_code;
745 unsigned char *temp = buf;
746 int data_type;
747#if defined(CONFIG_DIAG_OVER_USB)
748 int payload_length;
749 unsigned char *ptr;
750#endif
751
Shalabh Jain321c8b52012-02-22 12:37:06 -0800752 /* Set log masks */
753 if (*buf == 0x73 && *(int *)(buf+4) == 3) {
754 buf += 8;
755 /* Read Equip ID and pass as first param below*/
756 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
757 diag_update_userspace_clients(LOG_MASKS_TYPE);
758#if defined(CONFIG_DIAG_OVER_USB)
759 if (chk_apps_only()) {
760 driver->apps_rsp_buf[0] = 0x73;
761 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
762 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
763 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
764 for (i = 0; i < payload_length; i++)
765 *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
766 queue_work(driver->diag_cntl_wq,
767 &(driver->diag_log_mask_update_work));
768 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
769 return 0;
770 } else
771 buf = temp;
772#endif
773 } /* Check for set message mask */
774 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
775 ssid_first = *(uint16_t *)(buf + 2);
776 ssid_last = *(uint16_t *)(buf + 4);
777 ssid_range = 4 * (ssid_last - ssid_first + 1);
778 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
779 diag_update_userspace_clients(MSG_MASKS_TYPE);
780#if defined(CONFIG_DIAG_OVER_USB)
781 if (chk_apps_only()) {
782 for (i = 0; i < 8 + ssid_range; i++)
783 *(driver->apps_rsp_buf + i) = *(buf+i);
784 *(driver->apps_rsp_buf + 6) = 0x1;
785 queue_work(driver->diag_cntl_wq,
786 &(driver->diag_msg_mask_update_work));
787 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
788 return 0;
789 } else
790 buf = temp;
791#endif
792 } else if (*buf == 0x82) { /* event mask change */
793 buf += 4;
794 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
795 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
796 diag_update_userspace_clients(EVENT_MASKS_TYPE);
797#if defined(CONFIG_DIAG_OVER_USB)
798 if (chk_apps_only()) {
799 driver->apps_rsp_buf[0] = 0x82;
800 driver->apps_rsp_buf[1] = 0x0;
801 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
802 *(uint16_t *)(driver->apps_rsp_buf + 4) =
803 EVENT_LAST_ID + 1;
804 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
805 *(unsigned char *)(driver->apps_rsp_buf + 6 + i)
806 = 0x0;
807 /* cannot do this on work queue, as each event update
808 needs a num_bytes variable. Each queue_work call will
809 overwrite the previous input, as its the same struct */
810 diag_send_event_mask_update(driver->ch_cntl,
811 diag_event_num_bytes);
812 diag_send_event_mask_update(driver->chqdsp_cntl,
813 diag_event_num_bytes);
814 diag_send_event_mask_update(driver->ch_wcnss_cntl,
815 diag_event_num_bytes);
816 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
817 return 0;
818 } else
819 buf = temp;
820#endif
821 } else if (*buf == 0x60) {
822 diag_event_config = *(buf+1);
823#if defined(CONFIG_DIAG_OVER_USB)
824 if (chk_apps_only()) {
825 driver->apps_rsp_buf[0] = 0x60;
826 driver->apps_rsp_buf[1] = 0x0;
827 driver->apps_rsp_buf[2] = 0x0;
828 diag_send_event_mask_update(driver->ch_cntl,
829 diag_event_num_bytes);
830 diag_send_event_mask_update(driver->chqdsp_cntl,
831 diag_event_num_bytes);
832 diag_send_event_mask_update(driver->ch_wcnss_cntl,
833 diag_event_num_bytes);
834 ENCODE_RSP_AND_SEND(2);
835 return 0;
836 }
837#endif
838 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700839 /* Check for registered clients and forward packet to apropriate proc */
840 cmd_code = (int)(*(char *)buf);
841 temp++;
842 subsys_id = (int)(*(char *)temp);
843 temp++;
844 subsys_cmd_code = *(uint16_t *)temp;
845 temp += 2;
846 data_type = APPS_DATA;
847 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530848 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700849 if (subsys_id != RESET_ID)
850 data_type = MODEM_DATA;
851 }
852
853 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -0800854 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700855 entry = driver->table[i];
856 if (entry.process_id != NO_PROCESS) {
857 if (entry.cmd_code == cmd_code && entry.subsys_id ==
858 subsys_id && entry.cmd_code_lo <=
859 subsys_cmd_code &&
860 entry.cmd_code_hi >= subsys_cmd_code) {
861 diag_send_data(entry, buf, len, data_type);
862 packet_type = 0;
863 } else if (entry.cmd_code == 255
864 && cmd_code == 75) {
865 if (entry.subsys_id ==
866 subsys_id &&
867 entry.cmd_code_lo <=
868 subsys_cmd_code &&
869 entry.cmd_code_hi >=
870 subsys_cmd_code) {
871 diag_send_data(entry, buf, len,
872 data_type);
873 packet_type = 0;
874 }
875 } else if (entry.cmd_code == 255 &&
876 entry.subsys_id == 255) {
877 if (entry.cmd_code_lo <=
878 cmd_code &&
879 entry.
880 cmd_code_hi >= cmd_code) {
881 diag_send_data(entry, buf, len,
882 data_type);
883 packet_type = 0;
884 }
885 }
886 }
887 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700888#if defined(CONFIG_DIAG_OVER_USB)
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700889 /* Check for Apps Only & get event mask request */
Shalabh Jain321c8b52012-02-22 12:37:06 -0800890 if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700891 driver->apps_rsp_buf[0] = 0x81;
892 driver->apps_rsp_buf[1] = 0x0;
893 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
894 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
895 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
896 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
897 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
898 return 0;
899 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700900 /* Get log ID range & Check for Apps Only */
901 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700902 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
903 driver->apps_rsp_buf[0] = 0x73;
904 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
905 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
906 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
907 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
908 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
909 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
910 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
911 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
912 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
913 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
914 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
915 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
916 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
917 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
918 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
919 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
920 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
921 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
922 ENCODE_RSP_AND_SEND(75);
923 return 0;
924 }
925 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700926 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700927 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
928 driver->apps_rsp_buf[0] = 0x7d;
929 driver->apps_rsp_buf[1] = 0x1;
930 driver->apps_rsp_buf[2] = 0x1;
931 driver->apps_rsp_buf[3] = 0x0;
932 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
933 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
934 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
935 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
936 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
937 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
938 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
939 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
940 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
941 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
942 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
943 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
944 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
945 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
946 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
947 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
948 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
949 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
950 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
951 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
952 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
953 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
954 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
955 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
956 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
957 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
958 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
959 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
960 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
961 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
962 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
963 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
964 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
965 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
966 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
967 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
968 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
969 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
970 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800971 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
972 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
973 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
974 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
975 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
976 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
977 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
978 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
979 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700980 return 0;
981 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700982 /* Check for Apps Only Respond to Get Subsys Build mask */
983 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700984 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
985 ssid_first = *(uint16_t *)(buf + 2);
986 ssid_last = *(uint16_t *)(buf + 4);
987 ssid_range = 4 * (ssid_last - ssid_first + 1);
988 /* frame response */
989 driver->apps_rsp_buf[0] = 0x7d;
990 driver->apps_rsp_buf[1] = 0x2;
991 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
992 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
993 driver->apps_rsp_buf[6] = 0x1;
994 driver->apps_rsp_buf[7] = 0x0;
995 ptr = driver->apps_rsp_buf + 8;
996 /* bld time masks */
997 switch (ssid_first) {
998 case MSG_SSID_0:
999 for (i = 0; i < ssid_range; i += 4)
1000 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
1001 break;
1002 case MSG_SSID_1:
1003 for (i = 0; i < ssid_range; i += 4)
1004 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
1005 break;
1006 case MSG_SSID_2:
1007 for (i = 0; i < ssid_range; i += 4)
1008 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
1009 break;
1010 case MSG_SSID_3:
1011 for (i = 0; i < ssid_range; i += 4)
1012 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
1013 break;
1014 case MSG_SSID_4:
1015 for (i = 0; i < ssid_range; i += 4)
1016 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
1017 break;
1018 case MSG_SSID_5:
1019 for (i = 0; i < ssid_range; i += 4)
1020 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
1021 break;
1022 case MSG_SSID_6:
1023 for (i = 0; i < ssid_range; i += 4)
1024 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
1025 break;
1026 case MSG_SSID_7:
1027 for (i = 0; i < ssid_range; i += 4)
1028 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
1029 break;
1030 case MSG_SSID_8:
1031 for (i = 0; i < ssid_range; i += 4)
1032 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
1033 break;
1034 case MSG_SSID_9:
1035 for (i = 0; i < ssid_range; i += 4)
1036 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
1037 break;
1038 case MSG_SSID_10:
1039 for (i = 0; i < ssid_range; i += 4)
1040 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
1041 break;
1042 case MSG_SSID_11:
1043 for (i = 0; i < ssid_range; i += 4)
1044 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
1045 break;
1046 case MSG_SSID_12:
1047 for (i = 0; i < ssid_range; i += 4)
1048 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1049 break;
1050 case MSG_SSID_13:
1051 for (i = 0; i < ssid_range; i += 4)
1052 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1053 break;
1054 case MSG_SSID_14:
1055 for (i = 0; i < ssid_range; i += 4)
1056 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1057 break;
1058 case MSG_SSID_15:
1059 for (i = 0; i < ssid_range; i += 4)
1060 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1061 break;
1062 case MSG_SSID_16:
1063 for (i = 0; i < ssid_range; i += 4)
1064 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1065 break;
1066 case MSG_SSID_17:
1067 for (i = 0; i < ssid_range; i += 4)
1068 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1069 break;
1070 case MSG_SSID_18:
1071 for (i = 0; i < ssid_range; i += 4)
1072 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1073 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001074 case MSG_SSID_19:
1075 for (i = 0; i < ssid_range; i += 4)
1076 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1077 break;
1078 case MSG_SSID_20:
1079 for (i = 0; i < ssid_range; i += 4)
1080 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1081 break;
1082 case MSG_SSID_21:
1083 for (i = 0; i < ssid_range; i += 4)
1084 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1085 break;
1086 case MSG_SSID_22:
1087 for (i = 0; i < ssid_range; i += 4)
1088 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1089 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001090 }
1091 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1092 return 0;
1093 }
1094 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301095 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001096 /* send response back */
1097 driver->apps_rsp_buf[0] = *buf;
1098 ENCODE_RSP_AND_SEND(0);
1099 msleep(5000);
1100 /* call download API */
1101 msm_set_restart_mode(RESTART_DLOAD);
1102 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1103 kernel_restart(NULL);
1104 /* Not required, represents that command isnt sent to modem */
1105 return 0;
1106 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001107 /* Check for polling for Apps only DIAG */
1108 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1109 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001110 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001111 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001112 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001113 for (i = 0; i < 3; i++)
1114 driver->apps_rsp_buf[i] = *(buf+i);
1115 for (i = 0; i < 13; i++)
1116 driver->apps_rsp_buf[i+3] = 0;
1117
1118 ENCODE_RSP_AND_SEND(15);
1119 return 0;
1120 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001121 }
1122 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -08001123 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001124 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001125 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001126 for (i = 0; i < 55; i++)
1127 driver->apps_rsp_buf[i] = 0;
1128
1129 ENCODE_RSP_AND_SEND(54);
1130 return 0;
1131 }
1132 /* respond to 0x7c command */
1133 else if (*buf == 0x7c) {
1134 driver->apps_rsp_buf[0] = 0x7c;
1135 for (i = 1; i < 8; i++)
1136 driver->apps_rsp_buf[i] = 0;
1137 /* Tools ID for APQ 8060 */
1138 *(int *)(driver->apps_rsp_buf + 8) =
1139 chk_config_get_id();
1140 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1141 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1142 ENCODE_RSP_AND_SEND(13);
1143 return 0;
1144 }
1145 }
1146#endif
1147 return packet_type;
1148}
1149
1150#ifdef CONFIG_DIAG_OVER_USB
1151void diag_send_error_rsp(int index)
1152{
1153 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301154
1155 if (index > 490) {
1156 pr_err("diag: error response too huge, aborting\n");
1157 return;
1158 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001159 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1160 for (i = 0; i < index; i++)
1161 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1162 ENCODE_RSP_AND_SEND(index - 3);
1163}
1164#else
1165static inline void diag_send_error_rsp(int index) {}
1166#endif
1167
1168void diag_process_hdlc(void *data, unsigned len)
1169{
1170 struct diag_hdlc_decode_type hdlc;
1171 int ret, type = 0;
1172 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1173 hdlc.dest_ptr = driver->hdlc_buf;
1174 hdlc.dest_size = USB_MAX_OUT_BUF;
1175 hdlc.src_ptr = data;
1176 hdlc.src_size = len;
1177 hdlc.src_idx = 0;
1178 hdlc.dest_idx = 0;
1179 hdlc.escaping = 0;
1180
1181 ret = diag_hdlc_decode(&hdlc);
1182
1183 if (ret)
1184 type = diag_process_apps_pkt(driver->hdlc_buf,
1185 hdlc.dest_idx - 3);
1186 else if (driver->debug_flag) {
1187 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1188 " errors or partial packet received, packet"
1189 " length = %d\n", len);
1190 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1191 DUMP_PREFIX_ADDRESS, data, len, 1);
1192 driver->debug_flag = 0;
1193 }
1194 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001195 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001196 diag_send_error_rsp(hdlc.dest_idx);
1197 type = 0;
1198 }
1199 /* implies this packet is NOT meant for apps */
1200 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001201 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001202 diag_send_error_rsp(hdlc.dest_idx);
1203 } else { /* APQ 8060, Let Q6 respond */
1204 if (driver->chqdsp)
1205 smd_write(driver->chqdsp, driver->hdlc_buf,
1206 hdlc.dest_idx - 3);
1207 }
1208 type = 0;
1209 }
1210
1211#ifdef DIAG_DEBUG
1212 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1213 for (i = 0; i < hdlc.dest_idx; i++)
1214 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1215 driver->hdlc_buf)+i));
1216#endif /* DIAG DEBUG */
1217 /* ignore 2 bytes for CRC, one for 7E and send */
1218 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1219 APPEND_DEBUG('g');
1220 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1221 APPEND_DEBUG('h');
1222#ifdef DIAG_DEBUG
1223 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1224 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1225 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1226#endif /* DIAG DEBUG */
1227 }
1228}
1229
1230#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001231/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1232#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001233#define N_LEGACY_READ 1
1234
1235int diagfwd_connect(void)
1236{
1237 int err;
1238
1239 printk(KERN_DEBUG "diag: USB connected\n");
1240 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1241 N_LEGACY_READ);
1242 if (err)
1243 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1244
1245 driver->usb_connected = 1;
1246 driver->in_busy_1 = 0;
1247 driver->in_busy_2 = 0;
1248 driver->in_busy_qdsp_1 = 0;
1249 driver->in_busy_qdsp_2 = 0;
1250 driver->in_busy_wcnss = 0;
1251
1252 /* Poll SMD channels to check for data*/
1253 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1254 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1255 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001256 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001257 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1258 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1259 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001260 /* Poll USB channel to check for data*/
1261 queue_work(driver->diag_wq, &(driver->diag_read_work));
1262#ifdef CONFIG_DIAG_SDIO_PIPE
1263 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1264 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1265 diagfwd_connect_sdio();
1266 else
1267 printk(KERN_INFO "diag: No USB MDM ch");
1268 }
1269#endif
1270 return 0;
1271}
1272
1273int diagfwd_disconnect(void)
1274{
1275 printk(KERN_DEBUG "diag: USB disconnected\n");
1276 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001277 driver->debug_flag = 1;
1278 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001279 if (driver->logging_mode == USB_MODE) {
1280 driver->in_busy_1 = 1;
1281 driver->in_busy_2 = 1;
1282 driver->in_busy_qdsp_1 = 1;
1283 driver->in_busy_qdsp_2 = 1;
1284 driver->in_busy_wcnss = 1;
1285 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001286#ifdef CONFIG_DIAG_SDIO_PIPE
1287 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1288 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1289 diagfwd_disconnect_sdio();
1290#endif
1291 /* TBD - notify and flow control SMD */
1292 return 0;
1293}
1294
1295int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1296{
1297 unsigned char *buf = diag_write_ptr->buf;
1298 /*Determine if the write complete is for data from modem/apps/q6 */
1299 /* Need a context variable here instead */
1300 if (buf == (void *)driver->buf_in_1) {
1301 driver->in_busy_1 = 0;
1302 APPEND_DEBUG('o');
1303 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1304 } else if (buf == (void *)driver->buf_in_2) {
1305 driver->in_busy_2 = 0;
1306 APPEND_DEBUG('O');
1307 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1308 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1309 driver->in_busy_qdsp_1 = 0;
1310 APPEND_DEBUG('p');
1311 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1312 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1313 driver->in_busy_qdsp_2 = 0;
1314 APPEND_DEBUG('P');
1315 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1316 } else if (buf == (void *)driver->buf_in_wcnss) {
1317 driver->in_busy_wcnss = 0;
1318 APPEND_DEBUG('R');
1319 queue_work(driver->diag_wq,
1320 &(driver->diag_read_smd_wcnss_work));
1321 }
1322#ifdef CONFIG_DIAG_SDIO_PIPE
1323 else if (buf == (void *)driver->buf_in_sdio)
1324 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001325 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001326 diagfwd_write_complete_sdio();
1327 else
1328 pr_err("diag: Incorrect buffer pointer while WRITE");
1329#endif
1330 else {
1331 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1332 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1333 POOL_TYPE_WRITE_STRUCT);
1334 APPEND_DEBUG('q');
1335 }
1336 return 0;
1337}
1338
1339int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1340{
1341 int status = diag_read_ptr->status;
1342 unsigned char *buf = diag_read_ptr->buf;
1343
1344 /* Determine if the read complete is for data on legacy/mdm ch */
1345 if (buf == (void *)driver->usb_buf_out) {
1346 driver->read_len_legacy = diag_read_ptr->actual;
1347 APPEND_DEBUG('s');
1348#ifdef DIAG_DEBUG
1349 printk(KERN_INFO "read data from USB, pkt length %d",
1350 diag_read_ptr->actual);
1351 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1352 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1353 diag_read_ptr->actual, 1);
1354#endif /* DIAG DEBUG */
1355 if (driver->logging_mode == USB_MODE) {
1356 if (status != -ECONNRESET && status != -ESHUTDOWN)
1357 queue_work(driver->diag_wq,
1358 &(driver->diag_proc_hdlc_work));
1359 else
1360 queue_work(driver->diag_wq,
1361 &(driver->diag_read_work));
1362 }
1363 }
1364#ifdef CONFIG_DIAG_SDIO_PIPE
1365 else if (buf == (void *)driver->usb_buf_mdm_out) {
1366 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001367 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001368 driver->read_len_mdm = diag_read_ptr->actual;
1369 diagfwd_read_complete_sdio();
1370 } else
1371 pr_err("diag: Incorrect buffer pointer while READ");
1372 }
1373#endif
1374 else
1375 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1376
1377 return 0;
1378}
1379
1380void diag_read_work_fn(struct work_struct *work)
1381{
1382 APPEND_DEBUG('d');
1383 driver->usb_read_ptr->buf = driver->usb_buf_out;
1384 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1385 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1386 APPEND_DEBUG('e');
1387}
1388
1389void diag_process_hdlc_fn(struct work_struct *work)
1390{
1391 APPEND_DEBUG('D');
1392 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1393 diag_read_work_fn(work);
1394 APPEND_DEBUG('E');
1395}
1396
1397void diag_usb_legacy_notifier(void *priv, unsigned event,
1398 struct diag_request *d_req)
1399{
1400 switch (event) {
1401 case USB_DIAG_CONNECT:
1402 diagfwd_connect();
1403 break;
1404 case USB_DIAG_DISCONNECT:
1405 diagfwd_disconnect();
1406 break;
1407 case USB_DIAG_READ_DONE:
1408 diagfwd_read_complete(d_req);
1409 break;
1410 case USB_DIAG_WRITE_DONE:
1411 diagfwd_write_complete(d_req);
1412 break;
1413 default:
1414 printk(KERN_ERR "Unknown event from USB diag\n");
1415 break;
1416 }
1417}
1418
1419#endif /* DIAG OVER USB */
1420
1421static void diag_smd_notify(void *ctxt, unsigned event)
1422{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001423 if (event == SMD_EVENT_CLOSE) {
1424 pr_info("diag: clean modem registration\n");
1425 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001426 driver->ch = 0;
1427 return;
1428 } else if (event == SMD_EVENT_OPEN) {
1429 driver->ch = ch_temp;
1430 }
1431 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001432}
1433
1434#if defined(CONFIG_MSM_N_WAY_SMD)
1435static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1436{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001437 if (event == SMD_EVENT_CLOSE) {
1438 pr_info("diag: clean lpass registration\n");
1439 diag_clear_reg(QDSP_PROC);
1440 driver->chqdsp = 0;
1441 return;
1442 } else if (event == SMD_EVENT_OPEN) {
1443 driver->chqdsp = chqdsp_temp;
1444 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001445 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1446}
1447#endif
1448
1449static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1450{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001451 if (event == SMD_EVENT_CLOSE) {
1452 pr_info("diag: clean wcnss registration\n");
1453 diag_clear_reg(WCNSS_PROC);
1454 driver->ch_wcnss = 0;
1455 return;
1456 } else if (event == SMD_EVENT_OPEN) {
1457 driver->ch_wcnss = ch_wcnss_temp;
1458 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001459 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1460}
1461
1462static int diag_smd_probe(struct platform_device *pdev)
1463{
1464 int r = 0;
1465
Shalabh Jaineefee052011-11-08 23:46:03 -08001466 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001467 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001468 ch_temp = driver->ch;
1469 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001470#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001471 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001472 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1473 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001474 chqdsp_temp = driver->chqdsp;
1475 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001476#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001477 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001478 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1479 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001480 ch_wcnss_temp = driver->ch_wcnss;
1481 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001482 pm_runtime_set_active(&pdev->dev);
1483 pm_runtime_enable(&pdev->dev);
1484 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1485
1486 return 0;
1487}
1488
1489static int diagfwd_runtime_suspend(struct device *dev)
1490{
1491 dev_dbg(dev, "pm_runtime: suspending...\n");
1492 return 0;
1493}
1494
1495static int diagfwd_runtime_resume(struct device *dev)
1496{
1497 dev_dbg(dev, "pm_runtime: resuming...\n");
1498 return 0;
1499}
1500
1501static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1502 .runtime_suspend = diagfwd_runtime_suspend,
1503 .runtime_resume = diagfwd_runtime_resume,
1504};
1505
1506static struct platform_driver msm_smd_ch1_driver = {
1507
1508 .probe = diag_smd_probe,
1509 .driver = {
1510 .name = "DIAG",
1511 .owner = THIS_MODULE,
1512 .pm = &diagfwd_dev_pm_ops,
1513 },
1514};
1515
1516static struct platform_driver diag_smd_lite_driver = {
1517
1518 .probe = diag_smd_probe,
1519 .driver = {
1520 .name = "APPS_RIVA_DATA",
1521 .owner = THIS_MODULE,
1522 .pm = &diagfwd_dev_pm_ops,
1523 },
1524};
1525
1526void diagfwd_init(void)
1527{
1528 diag_debug_buf_idx = 0;
1529 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001530 driver->use_device_tree = has_device_tree();
Shalabh Jain321c8b52012-02-22 12:37:06 -08001531
1532 if (driver->event_mask == NULL) {
1533 driver->event_mask = kzalloc(sizeof(
1534 struct diag_ctrl_event_mask), GFP_KERNEL);
1535 if (driver->event_mask == NULL)
1536 goto err;
1537 }
1538 if (driver->msg_mask == NULL) {
1539 driver->msg_mask = kzalloc(sizeof(
1540 struct diag_ctrl_msg_mask), GFP_KERNEL);
1541 if (driver->msg_mask == NULL)
1542 goto err;
1543 }
1544 if (driver->log_mask == NULL) {
1545 driver->log_mask = kzalloc(sizeof(
1546 struct diag_ctrl_log_mask), GFP_KERNEL);
1547 if (driver->log_mask == NULL)
1548 goto err;
1549 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001550 if (driver->buf_in_1 == NULL) {
1551 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1552 if (driver->buf_in_1 == NULL)
1553 goto err;
1554 }
1555 if (driver->buf_in_2 == NULL) {
1556 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1557 if (driver->buf_in_2 == NULL)
1558 goto err;
1559 }
1560 if (driver->buf_in_qdsp_1 == NULL) {
1561 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1562 if (driver->buf_in_qdsp_1 == NULL)
1563 goto err;
1564 }
1565 if (driver->buf_in_qdsp_2 == NULL) {
1566 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1567 if (driver->buf_in_qdsp_2 == NULL)
1568 goto err;
1569 }
1570 if (driver->buf_in_wcnss == NULL) {
1571 driver->buf_in_wcnss = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1572 if (driver->buf_in_wcnss == NULL)
1573 goto err;
1574 }
Shalabh Jain321c8b52012-02-22 12:37:06 -08001575 if (driver->buf_msg_mask_update == NULL) {
1576 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1577 GFP_KERNEL);
1578 if (driver->buf_msg_mask_update == NULL)
1579 goto err;
1580 }
1581 if (driver->buf_log_mask_update == NULL) {
1582 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1583 GFP_KERNEL);
1584 if (driver->buf_log_mask_update == NULL)
1585 goto err;
1586 }
1587 if (driver->buf_event_mask_update == NULL) {
1588 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1589 GFP_KERNEL);
1590 if (driver->buf_event_mask_update == NULL)
1591 goto err;
1592 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001593 if (driver->usb_buf_out == NULL &&
1594 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1595 GFP_KERNEL)) == NULL)
1596 goto err;
1597 if (driver->hdlc_buf == NULL
1598 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1599 goto err;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001600 if (driver->user_space_data == NULL)
1601 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1602 if (driver->user_space_data == NULL)
1603 goto err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001604 if (driver->msg_masks == NULL
1605 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1606 GFP_KERNEL)) == NULL)
1607 goto err;
1608 if (driver->log_masks == NULL &&
1609 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1610 goto err;
1611 driver->log_masks_length = 8*MAX_EQUIP_ID;
1612 if (driver->event_masks == NULL &&
1613 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1614 GFP_KERNEL)) == NULL)
1615 goto err;
1616 if (driver->client_map == NULL &&
1617 (driver->client_map = kzalloc
1618 ((driver->num_clients) * sizeof(struct diag_client_map),
1619 GFP_KERNEL)) == NULL)
1620 goto err;
1621 if (driver->buf_tbl == NULL)
1622 driver->buf_tbl = kzalloc(buf_tbl_size *
1623 sizeof(struct diag_write_device), GFP_KERNEL);
1624 if (driver->buf_tbl == NULL)
1625 goto err;
1626 if (driver->data_ready == NULL &&
1627 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1628 , GFP_KERNEL)) == NULL)
1629 goto err;
1630 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001631 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001632 sizeof(struct diag_master_table),
1633 GFP_KERNEL)) == NULL)
1634 goto err;
1635 if (driver->write_ptr_1 == NULL) {
1636 driver->write_ptr_1 = kzalloc(
1637 sizeof(struct diag_request), GFP_KERNEL);
1638 if (driver->write_ptr_1 == NULL)
1639 goto err;
1640 }
1641 if (driver->write_ptr_2 == NULL) {
1642 driver->write_ptr_2 = kzalloc(
1643 sizeof(struct diag_request), GFP_KERNEL);
1644 if (driver->write_ptr_2 == NULL)
1645 goto err;
1646 }
1647 if (driver->write_ptr_qdsp_1 == NULL) {
1648 driver->write_ptr_qdsp_1 = kzalloc(
1649 sizeof(struct diag_request), GFP_KERNEL);
1650 if (driver->write_ptr_qdsp_1 == NULL)
1651 goto err;
1652 }
1653 if (driver->write_ptr_qdsp_2 == NULL) {
1654 driver->write_ptr_qdsp_2 = kzalloc(
1655 sizeof(struct diag_request), GFP_KERNEL);
1656 if (driver->write_ptr_qdsp_2 == NULL)
1657 goto err;
1658 }
1659 if (driver->write_ptr_wcnss == NULL) {
1660 driver->write_ptr_wcnss = kzalloc(
1661 sizeof(struct diag_request), GFP_KERNEL);
1662 if (driver->write_ptr_wcnss == NULL)
1663 goto err;
1664 }
1665 if (driver->usb_read_ptr == NULL) {
1666 driver->usb_read_ptr = kzalloc(
1667 sizeof(struct diag_request), GFP_KERNEL);
1668 if (driver->usb_read_ptr == NULL)
1669 goto err;
1670 }
1671 if (driver->pkt_buf == NULL &&
1672 (driver->pkt_buf = kzalloc(PKT_SIZE,
1673 GFP_KERNEL)) == NULL)
1674 goto err;
1675 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001676 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001677 if (driver->apps_rsp_buf == NULL)
1678 goto err;
1679 }
1680 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1681#ifdef CONFIG_DIAG_OVER_USB
1682 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1683 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001684 INIT_WORK(&(driver->diag_msg_mask_update_work),
1685 diag_msg_mask_update_fn);
1686 INIT_WORK(&(driver->diag_log_mask_update_work),
1687 diag_log_mask_update_fn);
1688 INIT_WORK(&(driver->diag_modem_mask_update_work),
1689 diag_modem_mask_update_fn);
1690 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
1691 diag_qdsp_mask_update_fn);
1692 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
1693 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001694 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
1695 diag_usb_legacy_notifier);
1696 if (IS_ERR(driver->legacy_ch)) {
1697 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
1698 goto err;
1699 }
1700#endif
1701 platform_driver_register(&msm_smd_ch1_driver);
1702 platform_driver_register(&diag_smd_lite_driver);
1703
1704 return;
1705err:
1706 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08001707 kfree(driver->event_mask);
1708 kfree(driver->log_mask);
1709 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001710 kfree(driver->buf_in_1);
1711 kfree(driver->buf_in_2);
1712 kfree(driver->buf_in_qdsp_1);
1713 kfree(driver->buf_in_qdsp_2);
1714 kfree(driver->buf_in_wcnss);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001715 kfree(driver->buf_msg_mask_update);
1716 kfree(driver->buf_log_mask_update);
1717 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001718 kfree(driver->usb_buf_out);
1719 kfree(driver->hdlc_buf);
1720 kfree(driver->msg_masks);
1721 kfree(driver->log_masks);
1722 kfree(driver->event_masks);
1723 kfree(driver->client_map);
1724 kfree(driver->buf_tbl);
1725 kfree(driver->data_ready);
1726 kfree(driver->table);
1727 kfree(driver->pkt_buf);
1728 kfree(driver->write_ptr_1);
1729 kfree(driver->write_ptr_2);
1730 kfree(driver->write_ptr_qdsp_1);
1731 kfree(driver->write_ptr_qdsp_2);
1732 kfree(driver->write_ptr_wcnss);
1733 kfree(driver->usb_read_ptr);
1734 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001735 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001736 if (driver->diag_wq)
1737 destroy_workqueue(driver->diag_wq);
1738}
1739
1740void diagfwd_exit(void)
1741{
1742 smd_close(driver->ch);
1743 smd_close(driver->chqdsp);
1744 smd_close(driver->ch_wcnss);
1745 driver->ch = 0; /* SMD can make this NULL */
1746 driver->chqdsp = 0;
1747 driver->ch_wcnss = 0;
1748#ifdef CONFIG_DIAG_OVER_USB
1749 if (driver->usb_connected)
1750 usb_diag_free_req(driver->legacy_ch);
1751 usb_diag_close(driver->legacy_ch);
1752#endif
1753 platform_driver_unregister(&msm_smd_ch1_driver);
1754 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001755 kfree(driver->event_mask);
1756 kfree(driver->log_mask);
1757 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001758 kfree(driver->buf_in_1);
1759 kfree(driver->buf_in_2);
1760 kfree(driver->buf_in_qdsp_1);
1761 kfree(driver->buf_in_qdsp_2);
1762 kfree(driver->buf_in_wcnss);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001763 kfree(driver->buf_msg_mask_update);
1764 kfree(driver->buf_log_mask_update);
1765 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001766 kfree(driver->usb_buf_out);
1767 kfree(driver->hdlc_buf);
1768 kfree(driver->msg_masks);
1769 kfree(driver->log_masks);
1770 kfree(driver->event_masks);
1771 kfree(driver->client_map);
1772 kfree(driver->buf_tbl);
1773 kfree(driver->data_ready);
1774 kfree(driver->table);
1775 kfree(driver->pkt_buf);
1776 kfree(driver->write_ptr_1);
1777 kfree(driver->write_ptr_2);
1778 kfree(driver->write_ptr_qdsp_1);
1779 kfree(driver->write_ptr_qdsp_2);
1780 kfree(driver->write_ptr_wcnss);
1781 kfree(driver->usb_read_ptr);
1782 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001783 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001784 destroy_workqueue(driver->diag_wq);
1785}