blob: f9664c4bf1362cf20b07bddc16282d349273656a [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
2 *
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 */
12
13#include <linux/slab.h>
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/device.h>
17#include <linux/err.h>
18#include <linux/platform_device.h>
19#include <linux/sched.h>
20#include <linux/workqueue.h>
21#include <linux/pm_runtime.h>
22#include <linux/diagchar.h>
23#include <linux/delay.h>
24#include <linux/reboot.h>
25#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;
46
47struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
48struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
49
50#define ENCODE_RSP_AND_SEND(buf_length) \
51do { \
52 send.state = DIAG_STATE_START; \
53 send.pkt = driver->apps_rsp_buf; \
54 send.last = (void *)(driver->apps_rsp_buf + buf_length); \
55 send.terminate = 1; \
56 if (!driver->in_busy_1) { \
57 enc.dest = driver->buf_in_1; \
58 enc.dest_last = (void *)(driver->buf_in_1 + 499); \
59 diag_hdlc_encode(&send, &enc); \
60 driver->write_ptr_1->buf = driver->buf_in_1; \
61 driver->write_ptr_1->length = (int)(enc.dest - \
62 (void *)(driver->buf_in_1)); \
Shalabh Jain3893bf92011-09-18 18:37:16 -070063 driver->in_busy_1 = 1; \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070064 usb_diag_write(driver->legacy_ch, driver->write_ptr_1); \
65 memset(driver->apps_rsp_buf, '\0', 500); \
66 } \
67} while (0)
68
69#define CHK_OVERFLOW(bufStart, start, end, length) \
70((bufStart <= start) && (end - start >= length)) ? 1 : 0
71
72int chk_config_get_id()
73{
74 switch (socinfo_get_id()) {
75 case APQ8060_MACHINE_ID:
76 case MSM8660_MACHINE_ID:
77 return APQ8060_TOOLS_ID;
78 case AO8960_MACHINE_ID:
79 return AO8960_TOOLS_ID;
80 default:
81 return 0;
82 }
83}
84
85void __diag_smd_send_req(void)
86{
87 void *buf = NULL;
88 int *in_busy_ptr = NULL;
89 struct diag_request *write_ptr_modem = NULL;
90
91 if (!driver->in_busy_1) {
92 buf = driver->buf_in_1;
93 write_ptr_modem = driver->write_ptr_1;
94 in_busy_ptr = &(driver->in_busy_1);
95 } else if (!driver->in_busy_2) {
96 buf = driver->buf_in_2;
97 write_ptr_modem = driver->write_ptr_2;
98 in_busy_ptr = &(driver->in_busy_2);
99 }
100
101 if (driver->ch && buf) {
102 int r = smd_read_avail(driver->ch);
103
104 if (r > IN_BUF_SIZE) {
105 if (r < MAX_IN_BUF_SIZE) {
106 pr_err("diag: SMD sending in "
107 "packets upto %d bytes", r);
108 buf = krealloc(buf, r, GFP_KERNEL);
109 } else {
110 pr_err("diag: SMD sending in "
111 "packets more than %d bytes", MAX_IN_BUF_SIZE);
112 return;
113 }
114 }
115 if (r > 0) {
116 if (!buf)
117 pr_info("Out of diagmem for Modem\n");
118 else {
119 APPEND_DEBUG('i');
120 smd_read(driver->ch, buf, r);
121 APPEND_DEBUG('j');
122 write_ptr_modem->length = r;
123 *in_busy_ptr = 1;
124 diag_device_write(buf, MODEM_DATA,
125 write_ptr_modem);
126 }
127 }
128 }
129}
130
131int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr)
132{
133 int i, err = 0;
134
135 if (driver->logging_mode == MEMORY_DEVICE_MODE) {
136 if (proc_num == APPS_DATA) {
137 for (i = 0; i < driver->poolsize_write_struct; i++)
138 if (driver->buf_tbl[i].length == 0) {
139 driver->buf_tbl[i].buf = buf;
140 driver->buf_tbl[i].length =
141 driver->used;
142#ifdef DIAG_DEBUG
143 pr_debug("diag: ENQUEUE buf ptr"
144 " and length is %x , %d\n",
145 (unsigned int)(driver->buf_
146 tbl[i].buf), driver->buf_tbl[i].length);
147#endif
148 break;
149 }
150 }
151 for (i = 0; i < driver->num_clients; i++)
152 if (driver->client_map[i].pid ==
153 driver->logging_process_id)
154 break;
155 if (i < driver->num_clients) {
156 driver->data_ready[i] |= MEMORY_DEVICE_LOG_TYPE;
157 wake_up_interruptible(&driver->wait_q);
158 } else
159 return -EINVAL;
160 } else if (driver->logging_mode == NO_LOGGING_MODE) {
161 if (proc_num == MODEM_DATA) {
162 driver->in_busy_1 = 0;
163 driver->in_busy_2 = 0;
164 queue_work(driver->diag_wq, &(driver->
165 diag_read_smd_work));
166 } else if (proc_num == QDSP_DATA) {
167 driver->in_busy_qdsp_1 = 0;
168 driver->in_busy_qdsp_2 = 0;
169 queue_work(driver->diag_wq, &(driver->
170 diag_read_smd_qdsp_work));
171 } else if (proc_num == WCNSS_DATA) {
172 driver->in_busy_wcnss = 0;
173 queue_work(driver->diag_wq, &(driver->
174 diag_read_smd_wcnss_work));
175 }
176 err = -1;
177 }
178#ifdef CONFIG_DIAG_OVER_USB
179 else if (driver->logging_mode == USB_MODE) {
180 if (proc_num == APPS_DATA) {
181 driver->write_ptr_svc = (struct diag_request *)
182 (diagmem_alloc(driver, sizeof(struct diag_request),
183 POOL_TYPE_WRITE_STRUCT));
184 if (driver->write_ptr_svc) {
185 driver->write_ptr_svc->length = driver->used;
186 driver->write_ptr_svc->buf = buf;
187 err = usb_diag_write(driver->legacy_ch,
188 driver->write_ptr_svc);
189 } else
190 err = -1;
191 } else if (proc_num == MODEM_DATA) {
192 write_ptr->buf = buf;
193#ifdef DIAG_DEBUG
194 printk(KERN_INFO "writing data to USB,"
195 "pkt length %d\n", write_ptr->length);
196 print_hex_dump(KERN_DEBUG, "Written Packet Data to"
197 " USB: ", 16, 1, DUMP_PREFIX_ADDRESS,
198 buf, write_ptr->length, 1);
199#endif /* DIAG DEBUG */
200 err = usb_diag_write(driver->legacy_ch, write_ptr);
201 } else if (proc_num == QDSP_DATA) {
202 write_ptr->buf = buf;
203 err = usb_diag_write(driver->legacy_ch, write_ptr);
204 } else if (proc_num == WCNSS_DATA) {
205 write_ptr->buf = buf;
206 err = usb_diag_write(driver->legacy_ch, write_ptr);
207 }
208#ifdef CONFIG_DIAG_SDIO_PIPE
209 else if (proc_num == SDIO_DATA) {
210 if (machine_is_msm8x60_fusion() ||
211 machine_is_msm8x60_fusn_ffa()) {
212 write_ptr->buf = buf;
213 err = usb_diag_write(driver->mdm_ch, write_ptr);
214 } else
215 pr_err("diag: Incorrect data while USB write");
216 }
217#endif
218 APPEND_DEBUG('d');
219 }
220#endif /* DIAG OVER USB */
221 return err;
222}
223
224void __diag_smd_wcnss_send_req(void)
225{
226 void *buf = driver->buf_in_wcnss;
227 int *in_busy_wcnss_ptr = &(driver->in_busy_wcnss);
228 struct diag_request *write_ptr_wcnss = driver->write_ptr_wcnss;
229
Shalabh Jain3893bf92011-09-18 18:37:16 -0700230 if ((!driver->in_busy_wcnss) && driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700231 int r = smd_read_avail(driver->ch_wcnss);
232 if (r > IN_BUF_SIZE) {
233 if (r < MAX_IN_BUF_SIZE) {
234 pr_err("diag: wcnss packets > %d bytes", r);
235 buf = krealloc(buf, r, GFP_KERNEL);
236 } else {
237 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
238 return;
239 }
240 }
241 if (r > 0) {
242 if (!buf) {
243 pr_err("Out of diagmem for wcnss\n");
244 } else {
245 APPEND_DEBUG('i');
246 smd_read(driver->ch_wcnss, buf, r);
247 APPEND_DEBUG('j');
248 write_ptr_wcnss->length = r;
249 *in_busy_wcnss_ptr = 1;
250 diag_device_write(buf, WCNSS_DATA,
251 write_ptr_wcnss);
252 }
253 }
254 }
255}
256
257void __diag_smd_qdsp_send_req(void)
258{
259 void *buf = NULL;
260 int *in_busy_qdsp_ptr = NULL;
261 struct diag_request *write_ptr_qdsp = NULL;
262
263 if (!driver->in_busy_qdsp_1) {
264 buf = driver->buf_in_qdsp_1;
265 write_ptr_qdsp = driver->write_ptr_qdsp_1;
266 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1);
267 } else if (!driver->in_busy_qdsp_2) {
268 buf = driver->buf_in_qdsp_2;
269 write_ptr_qdsp = driver->write_ptr_qdsp_2;
270 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2);
271 }
272
273 if (driver->chqdsp && buf) {
274 int r = smd_read_avail(driver->chqdsp);
275
276 if (r > IN_BUF_SIZE) {
277 if (r < MAX_IN_BUF_SIZE) {
278 pr_err("diag: SMD sending in "
279 "packets upto %d bytes", r);
280 buf = krealloc(buf, r, GFP_KERNEL);
281 } else {
282 pr_err("diag: SMD sending in "
283 "packets more than %d bytes", MAX_IN_BUF_SIZE);
284 return;
285 }
286 }
287 if (r > 0) {
288 if (!buf)
289 printk(KERN_INFO "Out of diagmem for QDSP\n");
290 else {
291 APPEND_DEBUG('i');
292 smd_read(driver->chqdsp, buf, r);
293 APPEND_DEBUG('j');
294 write_ptr_qdsp->length = r;
295 *in_busy_qdsp_ptr = 1;
296 diag_device_write(buf, QDSP_DATA,
297 write_ptr_qdsp);
298 }
299 }
300 }
301}
302
303static void diag_print_mask_table(void)
304{
305/* Enable this to print mask table when updated */
306#ifdef MASK_DEBUG
307 int first;
308 int last;
309 uint8_t *ptr = driver->msg_masks;
310 int i = 0;
311
312 while (*(uint32_t *)(ptr + 4)) {
313 first = *(uint32_t *)ptr;
314 ptr += 4;
315 last = *(uint32_t *)ptr;
316 ptr += 4;
317 printk(KERN_INFO "SSID %d - %d\n", first, last);
318 for (i = 0 ; i <= last - first ; i++)
319 printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
320 ptr += ((last - first) + 1)*4;
321
322 }
323#endif
324}
325
326static void diag_update_msg_mask(int start, int end , uint8_t *buf)
327{
328 int found = 0;
329 int first;
330 int last;
331 uint8_t *ptr = driver->msg_masks;
332 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
333 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
334
335 mutex_lock(&driver->diagchar_mutex);
336 /* First SSID can be zero : So check that last is non-zero */
337
338 while (*(uint32_t *)(ptr + 4)) {
339 first = *(uint32_t *)ptr;
340 ptr += 4;
341 last = *(uint32_t *)ptr;
342 ptr += 4;
343 if (start >= first && start <= last) {
344 ptr += (start - first)*4;
345 if (end <= last)
346 if (CHK_OVERFLOW(ptr_buffer_start, ptr,
347 ptr_buffer_end,
348 (((end - start)+1)*4)))
349 memcpy(ptr, buf , ((end - start)+1)*4);
350 else
351 printk(KERN_CRIT "Not enough"
352 " buffer space for"
353 " MSG_MASK\n");
354 else
355 printk(KERN_INFO "Unable to copy"
356 " mask change\n");
357
358 found = 1;
359 break;
360 } else {
361 ptr += ((last - first) + 1)*4;
362 }
363 }
364 /* Entry was not found - add new table */
365 if (!found) {
366 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
367 8 + ((end - start) + 1)*4)) {
368 memcpy(ptr, &(start) , 4);
369 ptr += 4;
370 memcpy(ptr, &(end), 4);
371 ptr += 4;
372 memcpy(ptr, buf , ((end - start) + 1)*4);
373 } else
374 printk(KERN_CRIT " Not enough buffer"
375 " space for MSG_MASK\n");
376 }
377 mutex_unlock(&driver->diagchar_mutex);
378 diag_print_mask_table();
379
380}
381
382static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bits)
383{
384 uint8_t *ptr = driver->event_masks;
385 uint8_t *temp = buf + 2;
386
387 mutex_lock(&driver->diagchar_mutex);
388 if (!toggle)
389 memset(ptr, 0 , EVENT_MASK_SIZE);
390 else
391 if (CHK_OVERFLOW(ptr, ptr,
392 ptr+EVENT_MASK_SIZE,
393 num_bits/8 + 1))
394 memcpy(ptr, temp , num_bits/8 + 1);
395 else
396 printk(KERN_CRIT "Not enough buffer space "
397 "for EVENT_MASK\n");
398 mutex_unlock(&driver->diagchar_mutex);
399}
400
401static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
402{
403 uint8_t *temp = buf;
404 struct mask_info {
405 int equip_id;
406 int index;
407 };
408 int i = 0;
409 unsigned char *ptr_data;
410 int offset = 8*MAX_EQUIP_ID;
411 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
412
413 mutex_lock(&driver->diagchar_mutex);
414 /* Check if we already know index of this equipment ID */
415 for (i = 0; i < MAX_EQUIP_ID; i++) {
416 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
417 offset = ptr->index;
418 break;
419 }
420 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
421 /*Reached a null entry */
422 ptr->equip_id = equip_id;
423 ptr->index = driver->log_masks_length;
424 offset = driver->log_masks_length;
425 driver->log_masks_length += ((num_items+7)/8);
426 break;
427 }
428 ptr++;
429 }
430 ptr_data = driver->log_masks + offset;
431 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
432 + LOG_MASK_SIZE, (num_items+7)/8))
433 memcpy(ptr_data, temp , (num_items+7)/8);
434 else
435 printk(KERN_CRIT " Not enough buffer space for LOG_MASK\n");
436 mutex_unlock(&driver->diagchar_mutex);
437}
438
439static void diag_update_pkt_buffer(unsigned char *buf)
440{
441 unsigned char *ptr = driver->pkt_buf;
442 unsigned char *temp = buf;
443
444 mutex_lock(&driver->diagchar_mutex);
445 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
446 memcpy(ptr, temp , driver->pkt_length);
447 else
448 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
449 mutex_unlock(&driver->diagchar_mutex);
450}
451
452void diag_update_userspace_clients(unsigned int type)
453{
454 int i;
455
456 mutex_lock(&driver->diagchar_mutex);
457 for (i = 0; i < driver->num_clients; i++)
458 if (driver->client_map[i].pid != 0)
459 driver->data_ready[i] |= type;
460 wake_up_interruptible(&driver->wait_q);
461 mutex_unlock(&driver->diagchar_mutex);
462}
463
464void diag_update_sleeping_process(int process_id)
465{
466 int i;
467
468 mutex_lock(&driver->diagchar_mutex);
469 for (i = 0; i < driver->num_clients; i++)
470 if (driver->client_map[i].pid == process_id) {
471 driver->data_ready[i] |= PKT_TYPE;
472 break;
473 }
474 wake_up_interruptible(&driver->wait_q);
475 mutex_unlock(&driver->diagchar_mutex);
476}
477
478void diag_send_data(struct diag_master_table entry, unsigned char *buf,
479 int len, int type)
480{
481 driver->pkt_length = len;
482 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
483 diag_update_pkt_buffer(buf);
484 diag_update_sleeping_process(entry.process_id);
485 } else {
486 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700487 if (entry.client_id == MODEM_PROC && driver->ch) {
488 if (cpu_is_msm8960() &&
489 (int)(*(char *)buf) == MODE_CMD)
490 if ((int)(*(char *)(buf+1)) == RESET_ID)
491 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700492 smd_write(driver->ch, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700493 } else if (entry.client_id == QDSP_PROC &&
494 driver->chqdsp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700495 smd_write(driver->chqdsp, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700496 } else if (entry.client_id == WCNSS_PROC &&
497 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700498 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700499 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700500 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700501 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700502 }
503 }
504}
505
506static int diag_process_apps_pkt(unsigned char *buf, int len)
507{
508 uint16_t subsys_cmd_code;
509 int subsys_id, ssid_first, ssid_last, ssid_range;
510 int packet_type = 1, i, cmd_code;
511 unsigned char *temp = buf;
512 int data_type;
513#if defined(CONFIG_DIAG_OVER_USB)
514 int payload_length;
515 unsigned char *ptr;
516#endif
517
518 /* Check for registered clients and forward packet to apropriate proc */
519 cmd_code = (int)(*(char *)buf);
520 temp++;
521 subsys_id = (int)(*(char *)temp);
522 temp++;
523 subsys_cmd_code = *(uint16_t *)temp;
524 temp += 2;
525 data_type = APPS_DATA;
526 /* Dont send any command other than mode reset */
527 if (cpu_is_msm8960() && cmd_code == MODE_CMD) {
528 if (subsys_id != RESET_ID)
529 data_type = MODEM_DATA;
530 }
531
532 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
533 for (i = 0; i < diag_max_registration; i++) {
534 entry = driver->table[i];
535 if (entry.process_id != NO_PROCESS) {
536 if (entry.cmd_code == cmd_code && entry.subsys_id ==
537 subsys_id && entry.cmd_code_lo <=
538 subsys_cmd_code &&
539 entry.cmd_code_hi >= subsys_cmd_code) {
540 diag_send_data(entry, buf, len, data_type);
541 packet_type = 0;
542 } else if (entry.cmd_code == 255
543 && cmd_code == 75) {
544 if (entry.subsys_id ==
545 subsys_id &&
546 entry.cmd_code_lo <=
547 subsys_cmd_code &&
548 entry.cmd_code_hi >=
549 subsys_cmd_code) {
550 diag_send_data(entry, buf, len,
551 data_type);
552 packet_type = 0;
553 }
554 } else if (entry.cmd_code == 255 &&
555 entry.subsys_id == 255) {
556 if (entry.cmd_code_lo <=
557 cmd_code &&
558 entry.
559 cmd_code_hi >= cmd_code) {
560 diag_send_data(entry, buf, len,
561 data_type);
562 packet_type = 0;
563 }
564 }
565 }
566 }
567 /* set event mask */
568 if (*buf == 0x82) {
569 buf += 4;
570 diag_update_event_mask(buf, 1, *(uint16_t *)buf);
571 diag_update_userspace_clients(EVENT_MASKS_TYPE);
572 }
573 /* event mask change */
574 else if ((*buf == 0x60) && (*(buf+1) == 0x0)) {
575 diag_update_event_mask(buf+1, 0, 0);
576 diag_update_userspace_clients(EVENT_MASKS_TYPE);
577#if defined(CONFIG_DIAG_OVER_USB)
578 /* Check for Apps Only 8960 */
579 if (!(driver->ch) && (chk_config_get_id() == AO8960_TOOLS_ID)) {
580 /* echo response back for apps only DIAG */
581 driver->apps_rsp_buf[0] = 0x60;
582 driver->apps_rsp_buf[1] = 0x0;
583 driver->apps_rsp_buf[2] = 0x0;
584 ENCODE_RSP_AND_SEND(2);
585 return 0;
586 }
587#endif
588 }
589 /* Set log masks */
590 else if (*buf == 0x73 && *(int *)(buf+4) == 3) {
591 buf += 8;
592 /* Read Equip ID and pass as first param below*/
593 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
594 diag_update_userspace_clients(LOG_MASKS_TYPE);
595#if defined(CONFIG_DIAG_OVER_USB)
596 /* Check for Apps Only 8960 */
597 if (!(driver->ch) && (chk_config_get_id() == AO8960_TOOLS_ID)) {
598 /* echo response back for Apps only DIAG */
599 driver->apps_rsp_buf[0] = 0x73;
600 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
601 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
602 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
603 for (i = 0; i < payload_length; i++)
604 *(int *)(driver->apps_rsp_buf+12+i) =
605 *(buf+8+i);
606 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
607 return 0;
608 }
609#endif
610 }
611 /* Check for set message mask */
612 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
613 ssid_first = *(uint16_t *)(buf + 2);
614 ssid_last = *(uint16_t *)(buf + 4);
615 ssid_range = 4 * (ssid_last - ssid_first + 1);
616 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
617 diag_update_userspace_clients(MSG_MASKS_TYPE);
618#if defined(CONFIG_DIAG_OVER_USB)
619 if (!(driver->ch) && (chk_config_get_id() == AO8960_TOOLS_ID)) {
620 /* echo response back for apps only DIAG */
621 for (i = 0; i < 8 + ssid_range; i++)
622 *(driver->apps_rsp_buf + i) = *(buf+i);
623 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
624 return 0;
625 }
626#endif
627 }
628#if defined(CONFIG_DIAG_OVER_USB)
629 /* Check for Apps Only 8960 & get event mask request */
630 else if (!(driver->ch) && (chk_config_get_id() == AO8960_TOOLS_ID)
631 && *buf == 0x81) {
632 driver->apps_rsp_buf[0] = 0x81;
633 driver->apps_rsp_buf[1] = 0x0;
634 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
635 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
636 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
637 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
638 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
639 return 0;
640 }
641 /* Get log ID range & Check for Apps Only 8960 */
642 else if (!(driver->ch) && (chk_config_get_id() == AO8960_TOOLS_ID)
643 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
644 driver->apps_rsp_buf[0] = 0x73;
645 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
646 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
647 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
648 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
649 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
650 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
651 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
652 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
653 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
654 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
655 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
656 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
657 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
658 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
659 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
660 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
661 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
662 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
663 ENCODE_RSP_AND_SEND(75);
664 return 0;
665 }
666 /* Respond to Get SSID Range request message */
667 else if (!(driver->ch) && (chk_config_get_id() == AO8960_TOOLS_ID)
668 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
669 driver->apps_rsp_buf[0] = 0x7d;
670 driver->apps_rsp_buf[1] = 0x1;
671 driver->apps_rsp_buf[2] = 0x1;
672 driver->apps_rsp_buf[3] = 0x0;
673 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
674 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
675 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
676 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
677 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
678 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
679 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
680 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
681 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
682 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
683 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
684 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
685 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
686 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
687 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
688 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
689 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
690 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
691 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
692 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
693 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
694 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
695 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
696 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
697 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
698 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
699 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
700 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
701 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
702 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
703 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
704 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
705 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
706 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
707 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
708 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
709 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
710 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
711 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
712 ENCODE_RSP_AND_SEND(83);
713 return 0;
714 }
715 /* Check for AO8960 Respond to Get Subsys Build mask */
716 else if (!(driver->ch) && (chk_config_get_id() == AO8960_TOOLS_ID)
717 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
718 ssid_first = *(uint16_t *)(buf + 2);
719 ssid_last = *(uint16_t *)(buf + 4);
720 ssid_range = 4 * (ssid_last - ssid_first + 1);
721 /* frame response */
722 driver->apps_rsp_buf[0] = 0x7d;
723 driver->apps_rsp_buf[1] = 0x2;
724 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
725 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
726 driver->apps_rsp_buf[6] = 0x1;
727 driver->apps_rsp_buf[7] = 0x0;
728 ptr = driver->apps_rsp_buf + 8;
729 /* bld time masks */
730 switch (ssid_first) {
731 case MSG_SSID_0:
732 for (i = 0; i < ssid_range; i += 4)
733 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
734 break;
735 case MSG_SSID_1:
736 for (i = 0; i < ssid_range; i += 4)
737 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
738 break;
739 case MSG_SSID_2:
740 for (i = 0; i < ssid_range; i += 4)
741 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
742 break;
743 case MSG_SSID_3:
744 for (i = 0; i < ssid_range; i += 4)
745 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
746 break;
747 case MSG_SSID_4:
748 for (i = 0; i < ssid_range; i += 4)
749 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
750 break;
751 case MSG_SSID_5:
752 for (i = 0; i < ssid_range; i += 4)
753 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
754 break;
755 case MSG_SSID_6:
756 for (i = 0; i < ssid_range; i += 4)
757 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
758 break;
759 case MSG_SSID_7:
760 for (i = 0; i < ssid_range; i += 4)
761 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
762 break;
763 case MSG_SSID_8:
764 for (i = 0; i < ssid_range; i += 4)
765 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
766 break;
767 case MSG_SSID_9:
768 for (i = 0; i < ssid_range; i += 4)
769 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
770 break;
771 case MSG_SSID_10:
772 for (i = 0; i < ssid_range; i += 4)
773 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
774 break;
775 case MSG_SSID_11:
776 for (i = 0; i < ssid_range; i += 4)
777 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
778 break;
779 case MSG_SSID_12:
780 for (i = 0; i < ssid_range; i += 4)
781 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
782 break;
783 case MSG_SSID_13:
784 for (i = 0; i < ssid_range; i += 4)
785 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
786 break;
787 case MSG_SSID_14:
788 for (i = 0; i < ssid_range; i += 4)
789 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
790 break;
791 case MSG_SSID_15:
792 for (i = 0; i < ssid_range; i += 4)
793 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
794 break;
795 case MSG_SSID_16:
796 for (i = 0; i < ssid_range; i += 4)
797 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
798 break;
799 case MSG_SSID_17:
800 for (i = 0; i < ssid_range; i += 4)
801 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
802 break;
803 case MSG_SSID_18:
804 for (i = 0; i < ssid_range; i += 4)
805 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
806 break;
807 }
808 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
809 return 0;
810 }
811 /* Check for download command */
812 else if ((cpu_is_msm8x60() || cpu_is_msm8960()) && (*buf == 0x3A)) {
813 /* send response back */
814 driver->apps_rsp_buf[0] = *buf;
815 ENCODE_RSP_AND_SEND(0);
816 msleep(5000);
817 /* call download API */
818 msm_set_restart_mode(RESTART_DLOAD);
819 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
820 kernel_restart(NULL);
821 /* Not required, represents that command isnt sent to modem */
822 return 0;
823 }
824 /* Check for ID for NO MODEM present */
825 else if (!(driver->ch)) {
826 /* Respond to polling for Apps only DIAG */
827 if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
828 (*(buf+2) == 0x03)) {
829 for (i = 0; i < 3; i++)
830 driver->apps_rsp_buf[i] = *(buf+i);
831 for (i = 0; i < 13; i++)
832 driver->apps_rsp_buf[i+3] = 0;
833
834 ENCODE_RSP_AND_SEND(15);
835 return 0;
836 }
837 /* respond to 0x0 command */
838 else if (*buf == 0x00) {
839 for (i = 0; i < 55; i++)
840 driver->apps_rsp_buf[i] = 0;
841
842 ENCODE_RSP_AND_SEND(54);
843 return 0;
844 }
845 /* respond to 0x7c command */
846 else if (*buf == 0x7c) {
847 driver->apps_rsp_buf[0] = 0x7c;
848 for (i = 1; i < 8; i++)
849 driver->apps_rsp_buf[i] = 0;
850 /* Tools ID for APQ 8060 */
851 *(int *)(driver->apps_rsp_buf + 8) =
852 chk_config_get_id();
853 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
854 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
855 ENCODE_RSP_AND_SEND(13);
856 return 0;
857 }
858 }
859#endif
860 return packet_type;
861}
862
863#ifdef CONFIG_DIAG_OVER_USB
864void diag_send_error_rsp(int index)
865{
866 int i;
867 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
868 for (i = 0; i < index; i++)
869 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
870 ENCODE_RSP_AND_SEND(index - 3);
871}
872#else
873static inline void diag_send_error_rsp(int index) {}
874#endif
875
876void diag_process_hdlc(void *data, unsigned len)
877{
878 struct diag_hdlc_decode_type hdlc;
879 int ret, type = 0;
880 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
881 hdlc.dest_ptr = driver->hdlc_buf;
882 hdlc.dest_size = USB_MAX_OUT_BUF;
883 hdlc.src_ptr = data;
884 hdlc.src_size = len;
885 hdlc.src_idx = 0;
886 hdlc.dest_idx = 0;
887 hdlc.escaping = 0;
888
889 ret = diag_hdlc_decode(&hdlc);
890
891 if (ret)
892 type = diag_process_apps_pkt(driver->hdlc_buf,
893 hdlc.dest_idx - 3);
894 else if (driver->debug_flag) {
895 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
896 " errors or partial packet received, packet"
897 " length = %d\n", len);
898 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
899 DUMP_PREFIX_ADDRESS, data, len, 1);
900 driver->debug_flag = 0;
901 }
902 /* send error responses from APPS for Central Routing */
903 if (type == 1 && chk_config_get_id() == AO8960_TOOLS_ID) {
904 diag_send_error_rsp(hdlc.dest_idx);
905 type = 0;
906 }
907 /* implies this packet is NOT meant for apps */
908 if (!(driver->ch) && type == 1) {
909 if (chk_config_get_id() == AO8960_TOOLS_ID) {
910 diag_send_error_rsp(hdlc.dest_idx);
911 } else { /* APQ 8060, Let Q6 respond */
912 if (driver->chqdsp)
913 smd_write(driver->chqdsp, driver->hdlc_buf,
914 hdlc.dest_idx - 3);
915 }
916 type = 0;
917 }
918
919#ifdef DIAG_DEBUG
920 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
921 for (i = 0; i < hdlc.dest_idx; i++)
922 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
923 driver->hdlc_buf)+i));
924#endif /* DIAG DEBUG */
925 /* ignore 2 bytes for CRC, one for 7E and send */
926 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
927 APPEND_DEBUG('g');
928 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
929 APPEND_DEBUG('h');
930#ifdef DIAG_DEBUG
931 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
932 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
933 1, DUMP_PREFIX_ADDRESS, data, len, 1);
934#endif /* DIAG DEBUG */
935 }
936}
937
938#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -0700939/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
940#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700941#define N_LEGACY_READ 1
942
943int diagfwd_connect(void)
944{
945 int err;
946
947 printk(KERN_DEBUG "diag: USB connected\n");
948 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
949 N_LEGACY_READ);
950 if (err)
951 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
952
953 driver->usb_connected = 1;
954 driver->in_busy_1 = 0;
955 driver->in_busy_2 = 0;
956 driver->in_busy_qdsp_1 = 0;
957 driver->in_busy_qdsp_2 = 0;
958 driver->in_busy_wcnss = 0;
959
960 /* Poll SMD channels to check for data*/
961 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
962 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
963 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -0700964 /* Poll SMD CNTL channels to check for data */
965 queue_work(driver->diag_wq, &(driver->diag_read_smd_cntl_work));
966 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_cntl_work));
967 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_cntl_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700968 /* Poll USB channel to check for data*/
969 queue_work(driver->diag_wq, &(driver->diag_read_work));
970#ifdef CONFIG_DIAG_SDIO_PIPE
971 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
972 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
973 diagfwd_connect_sdio();
974 else
975 printk(KERN_INFO "diag: No USB MDM ch");
976 }
977#endif
978 return 0;
979}
980
981int diagfwd_disconnect(void)
982{
983 printk(KERN_DEBUG "diag: USB disconnected\n");
984 driver->usb_connected = 0;
985 driver->in_busy_1 = 1;
986 driver->in_busy_2 = 1;
987 driver->in_busy_qdsp_1 = 1;
988 driver->in_busy_qdsp_2 = 1;
989 driver->in_busy_wcnss = 1;
990 driver->debug_flag = 1;
991 usb_diag_free_req(driver->legacy_ch);
992#ifdef CONFIG_DIAG_SDIO_PIPE
993 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
994 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
995 diagfwd_disconnect_sdio();
996#endif
997 /* TBD - notify and flow control SMD */
998 return 0;
999}
1000
1001int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1002{
1003 unsigned char *buf = diag_write_ptr->buf;
1004 /*Determine if the write complete is for data from modem/apps/q6 */
1005 /* Need a context variable here instead */
1006 if (buf == (void *)driver->buf_in_1) {
1007 driver->in_busy_1 = 0;
1008 APPEND_DEBUG('o');
1009 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1010 } else if (buf == (void *)driver->buf_in_2) {
1011 driver->in_busy_2 = 0;
1012 APPEND_DEBUG('O');
1013 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1014 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1015 driver->in_busy_qdsp_1 = 0;
1016 APPEND_DEBUG('p');
1017 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1018 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1019 driver->in_busy_qdsp_2 = 0;
1020 APPEND_DEBUG('P');
1021 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1022 } else if (buf == (void *)driver->buf_in_wcnss) {
1023 driver->in_busy_wcnss = 0;
1024 APPEND_DEBUG('R');
1025 queue_work(driver->diag_wq,
1026 &(driver->diag_read_smd_wcnss_work));
1027 }
1028#ifdef CONFIG_DIAG_SDIO_PIPE
1029 else if (buf == (void *)driver->buf_in_sdio)
1030 if (machine_is_msm8x60_fusion() ||
1031 machine_is_msm8x60_fusn_ffa())
1032 diagfwd_write_complete_sdio();
1033 else
1034 pr_err("diag: Incorrect buffer pointer while WRITE");
1035#endif
1036 else {
1037 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1038 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1039 POOL_TYPE_WRITE_STRUCT);
1040 APPEND_DEBUG('q');
1041 }
1042 return 0;
1043}
1044
1045int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1046{
1047 int status = diag_read_ptr->status;
1048 unsigned char *buf = diag_read_ptr->buf;
1049
1050 /* Determine if the read complete is for data on legacy/mdm ch */
1051 if (buf == (void *)driver->usb_buf_out) {
1052 driver->read_len_legacy = diag_read_ptr->actual;
1053 APPEND_DEBUG('s');
1054#ifdef DIAG_DEBUG
1055 printk(KERN_INFO "read data from USB, pkt length %d",
1056 diag_read_ptr->actual);
1057 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1058 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1059 diag_read_ptr->actual, 1);
1060#endif /* DIAG DEBUG */
1061 if (driver->logging_mode == USB_MODE) {
1062 if (status != -ECONNRESET && status != -ESHUTDOWN)
1063 queue_work(driver->diag_wq,
1064 &(driver->diag_proc_hdlc_work));
1065 else
1066 queue_work(driver->diag_wq,
1067 &(driver->diag_read_work));
1068 }
1069 }
1070#ifdef CONFIG_DIAG_SDIO_PIPE
1071 else if (buf == (void *)driver->usb_buf_mdm_out) {
1072 if (machine_is_msm8x60_fusion() ||
1073 machine_is_msm8x60_fusn_ffa()) {
1074 driver->read_len_mdm = diag_read_ptr->actual;
1075 diagfwd_read_complete_sdio();
1076 } else
1077 pr_err("diag: Incorrect buffer pointer while READ");
1078 }
1079#endif
1080 else
1081 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1082
1083 return 0;
1084}
1085
1086void diag_read_work_fn(struct work_struct *work)
1087{
1088 APPEND_DEBUG('d');
1089 driver->usb_read_ptr->buf = driver->usb_buf_out;
1090 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1091 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1092 APPEND_DEBUG('e');
1093}
1094
1095void diag_process_hdlc_fn(struct work_struct *work)
1096{
1097 APPEND_DEBUG('D');
1098 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1099 diag_read_work_fn(work);
1100 APPEND_DEBUG('E');
1101}
1102
1103void diag_usb_legacy_notifier(void *priv, unsigned event,
1104 struct diag_request *d_req)
1105{
1106 switch (event) {
1107 case USB_DIAG_CONNECT:
1108 diagfwd_connect();
1109 break;
1110 case USB_DIAG_DISCONNECT:
1111 diagfwd_disconnect();
1112 break;
1113 case USB_DIAG_READ_DONE:
1114 diagfwd_read_complete(d_req);
1115 break;
1116 case USB_DIAG_WRITE_DONE:
1117 diagfwd_write_complete(d_req);
1118 break;
1119 default:
1120 printk(KERN_ERR "Unknown event from USB diag\n");
1121 break;
1122 }
1123}
1124
1125#endif /* DIAG OVER USB */
1126
1127static void diag_smd_notify(void *ctxt, unsigned event)
1128{
1129 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1130}
1131
1132#if defined(CONFIG_MSM_N_WAY_SMD)
1133static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1134{
1135 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1136}
1137#endif
1138
1139static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1140{
1141 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1142}
1143
1144static int diag_smd_probe(struct platform_device *pdev)
1145{
1146 int r = 0;
1147
1148 if (pdev->id == SMD_APPS_MODEM)
1149 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
1150#if defined(CONFIG_MSM_N_WAY_SMD)
1151 if (pdev->id == SMD_APPS_QDSP)
1152 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1153 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
1154#endif
1155 if (pdev->id == SMD_APPS_WCNSS)
1156 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1157 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
1158 pm_runtime_set_active(&pdev->dev);
1159 pm_runtime_enable(&pdev->dev);
1160 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1161
1162 return 0;
1163}
1164
1165static int diagfwd_runtime_suspend(struct device *dev)
1166{
1167 dev_dbg(dev, "pm_runtime: suspending...\n");
1168 return 0;
1169}
1170
1171static int diagfwd_runtime_resume(struct device *dev)
1172{
1173 dev_dbg(dev, "pm_runtime: resuming...\n");
1174 return 0;
1175}
1176
1177static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1178 .runtime_suspend = diagfwd_runtime_suspend,
1179 .runtime_resume = diagfwd_runtime_resume,
1180};
1181
1182static struct platform_driver msm_smd_ch1_driver = {
1183
1184 .probe = diag_smd_probe,
1185 .driver = {
1186 .name = "DIAG",
1187 .owner = THIS_MODULE,
1188 .pm = &diagfwd_dev_pm_ops,
1189 },
1190};
1191
1192static struct platform_driver diag_smd_lite_driver = {
1193
1194 .probe = diag_smd_probe,
1195 .driver = {
1196 .name = "APPS_RIVA_DATA",
1197 .owner = THIS_MODULE,
1198 .pm = &diagfwd_dev_pm_ops,
1199 },
1200};
1201
1202void diagfwd_init(void)
1203{
1204 diag_debug_buf_idx = 0;
1205 driver->read_len_legacy = 0;
1206 if (driver->buf_in_1 == NULL) {
1207 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1208 if (driver->buf_in_1 == NULL)
1209 goto err;
1210 }
1211 if (driver->buf_in_2 == NULL) {
1212 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1213 if (driver->buf_in_2 == NULL)
1214 goto err;
1215 }
1216 if (driver->buf_in_qdsp_1 == NULL) {
1217 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1218 if (driver->buf_in_qdsp_1 == NULL)
1219 goto err;
1220 }
1221 if (driver->buf_in_qdsp_2 == NULL) {
1222 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1223 if (driver->buf_in_qdsp_2 == NULL)
1224 goto err;
1225 }
1226 if (driver->buf_in_wcnss == NULL) {
1227 driver->buf_in_wcnss = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1228 if (driver->buf_in_wcnss == NULL)
1229 goto err;
1230 }
1231 if (driver->usb_buf_out == NULL &&
1232 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1233 GFP_KERNEL)) == NULL)
1234 goto err;
1235 if (driver->hdlc_buf == NULL
1236 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1237 goto err;
1238 if (driver->msg_masks == NULL
1239 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1240 GFP_KERNEL)) == NULL)
1241 goto err;
1242 if (driver->log_masks == NULL &&
1243 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1244 goto err;
1245 driver->log_masks_length = 8*MAX_EQUIP_ID;
1246 if (driver->event_masks == NULL &&
1247 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1248 GFP_KERNEL)) == NULL)
1249 goto err;
1250 if (driver->client_map == NULL &&
1251 (driver->client_map = kzalloc
1252 ((driver->num_clients) * sizeof(struct diag_client_map),
1253 GFP_KERNEL)) == NULL)
1254 goto err;
1255 if (driver->buf_tbl == NULL)
1256 driver->buf_tbl = kzalloc(buf_tbl_size *
1257 sizeof(struct diag_write_device), GFP_KERNEL);
1258 if (driver->buf_tbl == NULL)
1259 goto err;
1260 if (driver->data_ready == NULL &&
1261 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1262 , GFP_KERNEL)) == NULL)
1263 goto err;
1264 if (driver->table == NULL &&
1265 (driver->table = kzalloc(diag_max_registration*
1266 sizeof(struct diag_master_table),
1267 GFP_KERNEL)) == NULL)
1268 goto err;
1269 if (driver->write_ptr_1 == NULL) {
1270 driver->write_ptr_1 = kzalloc(
1271 sizeof(struct diag_request), GFP_KERNEL);
1272 if (driver->write_ptr_1 == NULL)
1273 goto err;
1274 }
1275 if (driver->write_ptr_2 == NULL) {
1276 driver->write_ptr_2 = kzalloc(
1277 sizeof(struct diag_request), GFP_KERNEL);
1278 if (driver->write_ptr_2 == NULL)
1279 goto err;
1280 }
1281 if (driver->write_ptr_qdsp_1 == NULL) {
1282 driver->write_ptr_qdsp_1 = kzalloc(
1283 sizeof(struct diag_request), GFP_KERNEL);
1284 if (driver->write_ptr_qdsp_1 == NULL)
1285 goto err;
1286 }
1287 if (driver->write_ptr_qdsp_2 == NULL) {
1288 driver->write_ptr_qdsp_2 = kzalloc(
1289 sizeof(struct diag_request), GFP_KERNEL);
1290 if (driver->write_ptr_qdsp_2 == NULL)
1291 goto err;
1292 }
1293 if (driver->write_ptr_wcnss == NULL) {
1294 driver->write_ptr_wcnss = kzalloc(
1295 sizeof(struct diag_request), GFP_KERNEL);
1296 if (driver->write_ptr_wcnss == NULL)
1297 goto err;
1298 }
1299 if (driver->usb_read_ptr == NULL) {
1300 driver->usb_read_ptr = kzalloc(
1301 sizeof(struct diag_request), GFP_KERNEL);
1302 if (driver->usb_read_ptr == NULL)
1303 goto err;
1304 }
1305 if (driver->pkt_buf == NULL &&
1306 (driver->pkt_buf = kzalloc(PKT_SIZE,
1307 GFP_KERNEL)) == NULL)
1308 goto err;
1309 if (driver->apps_rsp_buf == NULL) {
1310 driver->apps_rsp_buf = kzalloc(500, GFP_KERNEL);
1311 if (driver->apps_rsp_buf == NULL)
1312 goto err;
1313 }
1314 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1315#ifdef CONFIG_DIAG_OVER_USB
1316 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1317 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
1318 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
1319 diag_usb_legacy_notifier);
1320 if (IS_ERR(driver->legacy_ch)) {
1321 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
1322 goto err;
1323 }
1324#endif
1325 platform_driver_register(&msm_smd_ch1_driver);
1326 platform_driver_register(&diag_smd_lite_driver);
1327
1328 return;
1329err:
1330 pr_err("diag: Could not initialize diag buffers");
1331 kfree(driver->buf_in_1);
1332 kfree(driver->buf_in_2);
1333 kfree(driver->buf_in_qdsp_1);
1334 kfree(driver->buf_in_qdsp_2);
1335 kfree(driver->buf_in_wcnss);
1336 kfree(driver->usb_buf_out);
1337 kfree(driver->hdlc_buf);
1338 kfree(driver->msg_masks);
1339 kfree(driver->log_masks);
1340 kfree(driver->event_masks);
1341 kfree(driver->client_map);
1342 kfree(driver->buf_tbl);
1343 kfree(driver->data_ready);
1344 kfree(driver->table);
1345 kfree(driver->pkt_buf);
1346 kfree(driver->write_ptr_1);
1347 kfree(driver->write_ptr_2);
1348 kfree(driver->write_ptr_qdsp_1);
1349 kfree(driver->write_ptr_qdsp_2);
1350 kfree(driver->write_ptr_wcnss);
1351 kfree(driver->usb_read_ptr);
1352 kfree(driver->apps_rsp_buf);
1353 if (driver->diag_wq)
1354 destroy_workqueue(driver->diag_wq);
1355}
1356
1357void diagfwd_exit(void)
1358{
1359 smd_close(driver->ch);
1360 smd_close(driver->chqdsp);
1361 smd_close(driver->ch_wcnss);
1362 driver->ch = 0; /* SMD can make this NULL */
1363 driver->chqdsp = 0;
1364 driver->ch_wcnss = 0;
1365#ifdef CONFIG_DIAG_OVER_USB
1366 if (driver->usb_connected)
1367 usb_diag_free_req(driver->legacy_ch);
1368 usb_diag_close(driver->legacy_ch);
1369#endif
1370 platform_driver_unregister(&msm_smd_ch1_driver);
1371 platform_driver_unregister(&diag_smd_lite_driver);
1372 kfree(driver->buf_in_1);
1373 kfree(driver->buf_in_2);
1374 kfree(driver->buf_in_qdsp_1);
1375 kfree(driver->buf_in_qdsp_2);
1376 kfree(driver->buf_in_wcnss);
1377 kfree(driver->usb_buf_out);
1378 kfree(driver->hdlc_buf);
1379 kfree(driver->msg_masks);
1380 kfree(driver->log_masks);
1381 kfree(driver->event_masks);
1382 kfree(driver->client_map);
1383 kfree(driver->buf_tbl);
1384 kfree(driver->data_ready);
1385 kfree(driver->table);
1386 kfree(driver->pkt_buf);
1387 kfree(driver->write_ptr_1);
1388 kfree(driver->write_ptr_2);
1389 kfree(driver->write_ptr_qdsp_1);
1390 kfree(driver->write_ptr_qdsp_2);
1391 kfree(driver->write_ptr_wcnss);
1392 kfree(driver->usb_read_ptr);
1393 kfree(driver->apps_rsp_buf);
1394 destroy_workqueue(driver->diag_wq);
1395}