blob: 079e04b514de296a819fcc31553b15c7bffba467 [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>
24#ifdef CONFIG_DIAG_OVER_USB
25#include <mach/usbdiag.h>
26#endif
27#include <mach/msm_smd.h>
28#include <mach/socinfo.h>
29#include <mach/restart.h>
30#include "diagmem.h"
31#include "diagchar.h"
32#include "diagfwd.h"
33#include "diagfwd_cntl.h"
34#include "diagchar_hdlc.h"
35#ifdef CONFIG_DIAG_SDIO_PIPE
36#include "diagfwd_sdio.h"
37#endif
38#define MODE_CMD 41
39#define RESET_ID 2
40
41int diag_debug_buf_idx;
42unsigned char diag_debug_buf[1024];
43static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
44struct diag_master_table entry;
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -080045smd_channel_t *ch_temp, *chqdsp_temp, *ch_wcnss_temp;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070046struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
47struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
48
49#define ENCODE_RSP_AND_SEND(buf_length) \
50do { \
51 send.state = DIAG_STATE_START; \
52 send.pkt = driver->apps_rsp_buf; \
53 send.last = (void *)(driver->apps_rsp_buf + buf_length); \
54 send.terminate = 1; \
55 if (!driver->in_busy_1) { \
56 enc.dest = driver->buf_in_1; \
57 enc.dest_last = (void *)(driver->buf_in_1 + 499); \
58 diag_hdlc_encode(&send, &enc); \
59 driver->write_ptr_1->buf = driver->buf_in_1; \
60 driver->write_ptr_1->length = (int)(enc.dest - \
61 (void *)(driver->buf_in_1)); \
Shalabh Jain3893bf92011-09-18 18:37:16 -070062 driver->in_busy_1 = 1; \
Shalabh Jain69890aa2011-10-10 12:59:16 -070063 diag_device_write(driver->buf_in_1, MODEM_DATA, \
64 driver->write_ptr_1); \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070065 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
Shalabh Jainfb8e3c12011-10-19 17:29:42 -070072int chk_config_get_id(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070073{
Shalabh Jain482bf122011-12-06 03:54:47 -080074 /* For all Fusion targets, Modem will always be present */
75 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
76 return 0;
77
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070078 switch (socinfo_get_id()) {
79 case APQ8060_MACHINE_ID:
80 case MSM8660_MACHINE_ID:
81 return APQ8060_TOOLS_ID;
82 case AO8960_MACHINE_ID:
Shalabh Jain10f5f432012-01-11 11:45:44 +053083 case MSM8260A_MACHINE_ID:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070084 return AO8960_TOOLS_ID;
Shalabh Jainfb8e3c12011-10-19 17:29:42 -070085 case APQ8064_MACHINE_ID:
86 return APQ8064_TOOLS_ID;
Shalabh Jain2f4cea62011-12-19 21:50:03 -080087 case MSM8930_MACHINE_ID:
88 return MSM8930_TOOLS_ID;
Shalabh Jain10f5f432012-01-11 11:45:44 +053089 case MSM8974_MACHINE_ID:
90 return MSM8974_TOOLS_ID;
Shalabh Jainfb8e3c12011-10-19 17:29:42 -070091 default:
92 return 0;
93 }
94}
95
96/*
Shalabh Jain2c783cb2012-01-15 11:09:29 +053097 * This will return TRUE for targets which support apps only mode.
Shalabh Jainfb8e3c12011-10-19 17:29:42 -070098 * This applies to 8960 and newer targets.
99 */
100int chk_apps_only(void)
101{
102 switch (socinfo_get_id()) {
103 case AO8960_MACHINE_ID:
104 case APQ8064_MACHINE_ID:
Shalabh Jain2f4cea62011-12-19 21:50:03 -0800105 case MSM8930_MACHINE_ID:
106 case MSM8630_MACHINE_ID:
107 case MSM8230_MACHINE_ID:
108 case APQ8030_MACHINE_ID:
109 case MSM8627_MACHINE_ID:
110 case MSM8227_MACHINE_ID:
Shalabh Jain10f5f432012-01-11 11:45:44 +0530111 case MSM8974_MACHINE_ID:
112 case MDM9615_MACHINE_ID:
113 case MSM8260A_MACHINE_ID:
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700114 return 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700115 default:
116 return 0;
117 }
118}
119
Shalabh Jain10f5f432012-01-11 11:45:44 +0530120/*
121 * This will return TRUE for targets which support apps as master.
122 * Thus, SW DLOAD and Mode Reset are supported on apps processor.
123 * This applies to 8960 and newer targets.
124 */
125int chk_apps_master(void)
126{
Shalabh Jain118bd8a2012-02-06 11:37:39 -0800127 if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615() ||
128 cpu_is_apq8064() || cpu_is_msm8627())
Shalabh Jain10f5f432012-01-11 11:45:44 +0530129 return 1;
130 else
131 return 0;
132}
133
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700134void __diag_smd_send_req(void)
135{
136 void *buf = NULL;
137 int *in_busy_ptr = NULL;
138 struct diag_request *write_ptr_modem = NULL;
139
140 if (!driver->in_busy_1) {
141 buf = driver->buf_in_1;
142 write_ptr_modem = driver->write_ptr_1;
143 in_busy_ptr = &(driver->in_busy_1);
144 } else if (!driver->in_busy_2) {
145 buf = driver->buf_in_2;
146 write_ptr_modem = driver->write_ptr_2;
147 in_busy_ptr = &(driver->in_busy_2);
148 }
149
150 if (driver->ch && buf) {
151 int r = smd_read_avail(driver->ch);
152
153 if (r > IN_BUF_SIZE) {
154 if (r < MAX_IN_BUF_SIZE) {
155 pr_err("diag: SMD sending in "
156 "packets upto %d bytes", r);
157 buf = krealloc(buf, r, GFP_KERNEL);
158 } else {
159 pr_err("diag: SMD sending in "
160 "packets more than %d bytes", MAX_IN_BUF_SIZE);
161 return;
162 }
163 }
164 if (r > 0) {
165 if (!buf)
166 pr_info("Out of diagmem for Modem\n");
167 else {
168 APPEND_DEBUG('i');
169 smd_read(driver->ch, buf, r);
170 APPEND_DEBUG('j');
171 write_ptr_modem->length = r;
172 *in_busy_ptr = 1;
173 diag_device_write(buf, MODEM_DATA,
174 write_ptr_modem);
175 }
176 }
177 }
178}
179
180int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr)
181{
182 int i, err = 0;
183
184 if (driver->logging_mode == MEMORY_DEVICE_MODE) {
185 if (proc_num == APPS_DATA) {
186 for (i = 0; i < driver->poolsize_write_struct; i++)
187 if (driver->buf_tbl[i].length == 0) {
188 driver->buf_tbl[i].buf = buf;
189 driver->buf_tbl[i].length =
190 driver->used;
191#ifdef DIAG_DEBUG
192 pr_debug("diag: ENQUEUE buf ptr"
193 " and length is %x , %d\n",
194 (unsigned int)(driver->buf_
195 tbl[i].buf), driver->buf_tbl[i].length);
196#endif
197 break;
198 }
199 }
200 for (i = 0; i < driver->num_clients; i++)
201 if (driver->client_map[i].pid ==
202 driver->logging_process_id)
203 break;
204 if (i < driver->num_clients) {
Shalabh Jain69890aa2011-10-10 12:59:16 -0700205 driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700206 wake_up_interruptible(&driver->wait_q);
207 } else
208 return -EINVAL;
209 } else if (driver->logging_mode == NO_LOGGING_MODE) {
210 if (proc_num == MODEM_DATA) {
211 driver->in_busy_1 = 0;
212 driver->in_busy_2 = 0;
213 queue_work(driver->diag_wq, &(driver->
214 diag_read_smd_work));
215 } else if (proc_num == QDSP_DATA) {
216 driver->in_busy_qdsp_1 = 0;
217 driver->in_busy_qdsp_2 = 0;
218 queue_work(driver->diag_wq, &(driver->
219 diag_read_smd_qdsp_work));
220 } else if (proc_num == WCNSS_DATA) {
221 driver->in_busy_wcnss = 0;
222 queue_work(driver->diag_wq, &(driver->
223 diag_read_smd_wcnss_work));
224 }
Shalabh Jain482bf122011-12-06 03:54:47 -0800225#ifdef CONFIG_DIAG_SDIO_PIPE
226 else if (proc_num == SDIO_DATA) {
227 driver->in_busy_sdio = 0;
228 queue_work(driver->diag_sdio_wq,
229 &(driver->diag_read_sdio_work));
230 }
231#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700232 err = -1;
233 }
234#ifdef CONFIG_DIAG_OVER_USB
235 else if (driver->logging_mode == USB_MODE) {
236 if (proc_num == APPS_DATA) {
237 driver->write_ptr_svc = (struct diag_request *)
238 (diagmem_alloc(driver, sizeof(struct diag_request),
239 POOL_TYPE_WRITE_STRUCT));
240 if (driver->write_ptr_svc) {
241 driver->write_ptr_svc->length = driver->used;
242 driver->write_ptr_svc->buf = buf;
243 err = usb_diag_write(driver->legacy_ch,
244 driver->write_ptr_svc);
245 } else
246 err = -1;
247 } else if (proc_num == MODEM_DATA) {
248 write_ptr->buf = buf;
249#ifdef DIAG_DEBUG
250 printk(KERN_INFO "writing data to USB,"
251 "pkt length %d\n", write_ptr->length);
252 print_hex_dump(KERN_DEBUG, "Written Packet Data to"
253 " USB: ", 16, 1, DUMP_PREFIX_ADDRESS,
254 buf, write_ptr->length, 1);
255#endif /* DIAG DEBUG */
256 err = usb_diag_write(driver->legacy_ch, write_ptr);
257 } else if (proc_num == QDSP_DATA) {
258 write_ptr->buf = buf;
259 err = usb_diag_write(driver->legacy_ch, write_ptr);
260 } else if (proc_num == WCNSS_DATA) {
261 write_ptr->buf = buf;
262 err = usb_diag_write(driver->legacy_ch, write_ptr);
263 }
264#ifdef CONFIG_DIAG_SDIO_PIPE
265 else if (proc_num == SDIO_DATA) {
266 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -0800267 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700268 write_ptr->buf = buf;
269 err = usb_diag_write(driver->mdm_ch, write_ptr);
270 } else
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800271 pr_err("diag: Incorrect sdio data "
272 "while USB write\n");
273 }
274#endif
275#ifdef CONFIG_DIAG_HSIC_PIPE
276 else if (proc_num == HSIC_DATA) {
277 if (driver->hsic_device_enabled) {
278 write_ptr->buf = buf;
279 err = usb_diag_write(driver->mdm_ch, write_ptr);
280 } else
281 pr_err("diag: Incorrect hsic data "
282 "while USB write\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700283 }
284#endif
285 APPEND_DEBUG('d');
286 }
287#endif /* DIAG OVER USB */
288 return err;
289}
290
291void __diag_smd_wcnss_send_req(void)
292{
293 void *buf = driver->buf_in_wcnss;
294 int *in_busy_wcnss_ptr = &(driver->in_busy_wcnss);
295 struct diag_request *write_ptr_wcnss = driver->write_ptr_wcnss;
296
Shalabh Jain3893bf92011-09-18 18:37:16 -0700297 if ((!driver->in_busy_wcnss) && driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700298 int r = smd_read_avail(driver->ch_wcnss);
299 if (r > IN_BUF_SIZE) {
300 if (r < MAX_IN_BUF_SIZE) {
301 pr_err("diag: wcnss packets > %d bytes", r);
302 buf = krealloc(buf, r, GFP_KERNEL);
303 } else {
304 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
305 return;
306 }
307 }
308 if (r > 0) {
309 if (!buf) {
310 pr_err("Out of diagmem for wcnss\n");
311 } else {
312 APPEND_DEBUG('i');
313 smd_read(driver->ch_wcnss, buf, r);
314 APPEND_DEBUG('j');
315 write_ptr_wcnss->length = r;
316 *in_busy_wcnss_ptr = 1;
317 diag_device_write(buf, WCNSS_DATA,
318 write_ptr_wcnss);
319 }
320 }
321 }
322}
323
324void __diag_smd_qdsp_send_req(void)
325{
326 void *buf = NULL;
327 int *in_busy_qdsp_ptr = NULL;
328 struct diag_request *write_ptr_qdsp = NULL;
329
330 if (!driver->in_busy_qdsp_1) {
331 buf = driver->buf_in_qdsp_1;
332 write_ptr_qdsp = driver->write_ptr_qdsp_1;
333 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1);
334 } else if (!driver->in_busy_qdsp_2) {
335 buf = driver->buf_in_qdsp_2;
336 write_ptr_qdsp = driver->write_ptr_qdsp_2;
337 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2);
338 }
339
340 if (driver->chqdsp && buf) {
341 int r = smd_read_avail(driver->chqdsp);
342
343 if (r > IN_BUF_SIZE) {
344 if (r < MAX_IN_BUF_SIZE) {
345 pr_err("diag: SMD sending in "
346 "packets upto %d bytes", r);
347 buf = krealloc(buf, r, GFP_KERNEL);
348 } else {
349 pr_err("diag: SMD sending in "
350 "packets more than %d bytes", MAX_IN_BUF_SIZE);
351 return;
352 }
353 }
354 if (r > 0) {
355 if (!buf)
356 printk(KERN_INFO "Out of diagmem for QDSP\n");
357 else {
358 APPEND_DEBUG('i');
359 smd_read(driver->chqdsp, buf, r);
360 APPEND_DEBUG('j');
361 write_ptr_qdsp->length = r;
362 *in_busy_qdsp_ptr = 1;
363 diag_device_write(buf, QDSP_DATA,
364 write_ptr_qdsp);
365 }
366 }
367 }
368}
369
370static void diag_print_mask_table(void)
371{
372/* Enable this to print mask table when updated */
373#ifdef MASK_DEBUG
374 int first;
375 int last;
376 uint8_t *ptr = driver->msg_masks;
377 int i = 0;
378
379 while (*(uint32_t *)(ptr + 4)) {
380 first = *(uint32_t *)ptr;
381 ptr += 4;
382 last = *(uint32_t *)ptr;
383 ptr += 4;
384 printk(KERN_INFO "SSID %d - %d\n", first, last);
385 for (i = 0 ; i <= last - first ; i++)
386 printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
387 ptr += ((last - first) + 1)*4;
388
389 }
390#endif
391}
392
393static void diag_update_msg_mask(int start, int end , uint8_t *buf)
394{
395 int found = 0;
396 int first;
397 int last;
398 uint8_t *ptr = driver->msg_masks;
399 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
400 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
401
402 mutex_lock(&driver->diagchar_mutex);
403 /* First SSID can be zero : So check that last is non-zero */
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530404
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405 while (*(uint32_t *)(ptr + 4)) {
406 first = *(uint32_t *)ptr;
407 ptr += 4;
408 last = *(uint32_t *)ptr;
409 ptr += 4;
410 if (start >= first && start <= last) {
411 ptr += (start - first)*4;
412 if (end <= last)
413 if (CHK_OVERFLOW(ptr_buffer_start, ptr,
414 ptr_buffer_end,
415 (((end - start)+1)*4)))
416 memcpy(ptr, buf , ((end - start)+1)*4);
417 else
418 printk(KERN_CRIT "Not enough"
419 " buffer space for"
420 " MSG_MASK\n");
421 else
422 printk(KERN_INFO "Unable to copy"
423 " mask change\n");
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530424
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700425 found = 1;
426 break;
427 } else {
428 ptr += ((last - first) + 1)*4;
429 }
430 }
431 /* Entry was not found - add new table */
432 if (!found) {
433 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
434 8 + ((end - start) + 1)*4)) {
435 memcpy(ptr, &(start) , 4);
436 ptr += 4;
437 memcpy(ptr, &(end), 4);
438 ptr += 4;
439 memcpy(ptr, buf , ((end - start) + 1)*4);
440 } else
441 printk(KERN_CRIT " Not enough buffer"
442 " space for MSG_MASK\n");
443 }
444 mutex_unlock(&driver->diagchar_mutex);
445 diag_print_mask_table();
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530446
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700447}
448
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530449static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bits)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700450{
451 uint8_t *ptr = driver->event_masks;
452 uint8_t *temp = buf + 2;
453
454 mutex_lock(&driver->diagchar_mutex);
455 if (!toggle)
456 memset(ptr, 0 , EVENT_MASK_SIZE);
457 else
458 if (CHK_OVERFLOW(ptr, ptr,
459 ptr+EVENT_MASK_SIZE,
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530460 num_bits/8 + 1))
461 memcpy(ptr, temp , num_bits/8 + 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700462 else
463 printk(KERN_CRIT "Not enough buffer space "
464 "for EVENT_MASK\n");
465 mutex_unlock(&driver->diagchar_mutex);
466}
467
468static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
469{
470 uint8_t *temp = buf;
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530471 struct mask_info {
472 int equip_id;
473 int index;
474 };
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700475 int i = 0;
476 unsigned char *ptr_data;
477 int offset = 8*MAX_EQUIP_ID;
478 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
479
480 mutex_lock(&driver->diagchar_mutex);
481 /* Check if we already know index of this equipment ID */
482 for (i = 0; i < MAX_EQUIP_ID; i++) {
483 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
484 offset = ptr->index;
485 break;
486 }
487 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530488 /*Reached a null entry */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700489 ptr->equip_id = equip_id;
490 ptr->index = driver->log_masks_length;
491 offset = driver->log_masks_length;
492 driver->log_masks_length += ((num_items+7)/8);
493 break;
494 }
495 ptr++;
496 }
497 ptr_data = driver->log_masks + offset;
498 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
499 + LOG_MASK_SIZE, (num_items+7)/8))
500 memcpy(ptr_data, temp , (num_items+7)/8);
501 else
502 printk(KERN_CRIT " Not enough buffer space for LOG_MASK\n");
503 mutex_unlock(&driver->diagchar_mutex);
504}
505
506static void diag_update_pkt_buffer(unsigned char *buf)
507{
508 unsigned char *ptr = driver->pkt_buf;
509 unsigned char *temp = buf;
510
511 mutex_lock(&driver->diagchar_mutex);
512 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
513 memcpy(ptr, temp , driver->pkt_length);
514 else
515 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
516 mutex_unlock(&driver->diagchar_mutex);
517}
518
519void diag_update_userspace_clients(unsigned int type)
520{
521 int i;
522
523 mutex_lock(&driver->diagchar_mutex);
524 for (i = 0; i < driver->num_clients; i++)
525 if (driver->client_map[i].pid != 0)
526 driver->data_ready[i] |= type;
527 wake_up_interruptible(&driver->wait_q);
528 mutex_unlock(&driver->diagchar_mutex);
529}
530
531void diag_update_sleeping_process(int process_id)
532{
533 int i;
534
535 mutex_lock(&driver->diagchar_mutex);
536 for (i = 0; i < driver->num_clients; i++)
537 if (driver->client_map[i].pid == process_id) {
538 driver->data_ready[i] |= PKT_TYPE;
539 break;
540 }
541 wake_up_interruptible(&driver->wait_q);
542 mutex_unlock(&driver->diagchar_mutex);
543}
544
545void diag_send_data(struct diag_master_table entry, unsigned char *buf,
546 int len, int type)
547{
548 driver->pkt_length = len;
549 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
550 diag_update_pkt_buffer(buf);
551 diag_update_sleeping_process(entry.process_id);
552 } else {
553 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700554 if (entry.client_id == MODEM_PROC && driver->ch) {
Shalabh Jain10f5f432012-01-11 11:45:44 +0530555 if (chk_apps_master() &&
Shalabh Jainc9f35092011-07-28 18:36:17 -0700556 (int)(*(char *)buf) == MODE_CMD)
Dixon Petersonff425d12011-12-06 18:12:35 -0800557 if ((int)(*(char *)(buf+1)) ==
558 RESET_ID)
Shalabh Jainc9f35092011-07-28 18:36:17 -0700559 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700560 smd_write(driver->ch, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700561 } else if (entry.client_id == QDSP_PROC &&
562 driver->chqdsp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700563 smd_write(driver->chqdsp, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700564 } else if (entry.client_id == WCNSS_PROC &&
565 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700566 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700567 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700568 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700569 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700570 }
571 }
572}
573
574static int diag_process_apps_pkt(unsigned char *buf, int len)
575{
576 uint16_t subsys_cmd_code;
577 int subsys_id, ssid_first, ssid_last, ssid_range;
578 int packet_type = 1, i, cmd_code;
579 unsigned char *temp = buf;
580 int data_type;
581#if defined(CONFIG_DIAG_OVER_USB)
582 int payload_length;
583 unsigned char *ptr;
584#endif
585
586 /* Check for registered clients and forward packet to apropriate proc */
587 cmd_code = (int)(*(char *)buf);
588 temp++;
589 subsys_id = (int)(*(char *)temp);
590 temp++;
591 subsys_cmd_code = *(uint16_t *)temp;
592 temp += 2;
593 data_type = APPS_DATA;
594 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530595 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700596 if (subsys_id != RESET_ID)
597 data_type = MODEM_DATA;
598 }
599
600 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
601 for (i = 0; i < diag_max_registration; i++) {
602 entry = driver->table[i];
603 if (entry.process_id != NO_PROCESS) {
604 if (entry.cmd_code == cmd_code && entry.subsys_id ==
605 subsys_id && entry.cmd_code_lo <=
606 subsys_cmd_code &&
607 entry.cmd_code_hi >= subsys_cmd_code) {
608 diag_send_data(entry, buf, len, data_type);
609 packet_type = 0;
610 } else if (entry.cmd_code == 255
611 && cmd_code == 75) {
612 if (entry.subsys_id ==
613 subsys_id &&
614 entry.cmd_code_lo <=
615 subsys_cmd_code &&
616 entry.cmd_code_hi >=
617 subsys_cmd_code) {
618 diag_send_data(entry, buf, len,
619 data_type);
620 packet_type = 0;
621 }
622 } else if (entry.cmd_code == 255 &&
623 entry.subsys_id == 255) {
624 if (entry.cmd_code_lo <=
625 cmd_code &&
626 entry.
627 cmd_code_hi >= cmd_code) {
628 diag_send_data(entry, buf, len,
629 data_type);
630 packet_type = 0;
631 }
632 }
633 }
634 }
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530635 /* set event mask */
636 if (*buf == 0x82) {
637 buf += 4;
638 diag_update_event_mask(buf, 1, *(uint16_t *)buf);
639 diag_update_userspace_clients(EVENT_MASKS_TYPE);
640 }
641 /* event mask change */
642 else if ((*buf == 0x60) && (*(buf+1) == 0x0)) {
643 diag_update_event_mask(buf+1, 0, 0);
644 diag_update_userspace_clients(EVENT_MASKS_TYPE);
645#if defined(CONFIG_DIAG_OVER_USB)
646 /* Check for Apps Only */
647 if (!(driver->ch) && chk_apps_only()) {
648 /* echo response back for apps only DIAG */
649 driver->apps_rsp_buf[0] = 0x60;
650 driver->apps_rsp_buf[1] = 0x0;
651 driver->apps_rsp_buf[2] = 0x0;
652 ENCODE_RSP_AND_SEND(2);
653 return 0;
654 }
655#endif
656 }
657 /* Set log masks */
658 else if (*buf == 0x73 && *(int *)(buf+4) == 3) {
659 buf += 8;
660 /* Read Equip ID and pass as first param below*/
661 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
662 diag_update_userspace_clients(LOG_MASKS_TYPE);
663#if defined(CONFIG_DIAG_OVER_USB)
664 /* Check for Apps Only */
665 if (!(driver->ch) && chk_apps_only()) {
666 /* echo response back for Apps only DIAG */
667 driver->apps_rsp_buf[0] = 0x73;
668 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
669 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
670 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
671 for (i = 0; i < payload_length; i++)
672 *(int *)(driver->apps_rsp_buf+12+i) =
673 *(buf+8+i);
674 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
675 return 0;
676 }
677#endif
678 }
679 /* Check for set message mask */
680 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
681 ssid_first = *(uint16_t *)(buf + 2);
682 ssid_last = *(uint16_t *)(buf + 4);
683 ssid_range = 4 * (ssid_last - ssid_first + 1);
684 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
685 diag_update_userspace_clients(MSG_MASKS_TYPE);
686#if defined(CONFIG_DIAG_OVER_USB)
687 if (!(driver->ch) && chk_apps_only()) {
688 /* echo response back for apps only DIAG */
689 for (i = 0; i < 8 + ssid_range; i++)
690 *(driver->apps_rsp_buf + i) = *(buf+i);
691 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
692 return 0;
693 }
694#endif
695 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700696#if defined(CONFIG_DIAG_OVER_USB)
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700697 /* Check for Apps Only & get event mask request */
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530698 else if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700699 driver->apps_rsp_buf[0] = 0x81;
700 driver->apps_rsp_buf[1] = 0x0;
701 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
702 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
703 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
704 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
705 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
706 return 0;
707 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700708 /* Get log ID range & Check for Apps Only */
709 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700710 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
711 driver->apps_rsp_buf[0] = 0x73;
712 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
713 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
714 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
715 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
716 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
717 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
718 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
719 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
720 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
721 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
722 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
723 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
724 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
725 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
726 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
727 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
728 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
729 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
730 ENCODE_RSP_AND_SEND(75);
731 return 0;
732 }
733 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700734 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700735 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
736 driver->apps_rsp_buf[0] = 0x7d;
737 driver->apps_rsp_buf[1] = 0x1;
738 driver->apps_rsp_buf[2] = 0x1;
739 driver->apps_rsp_buf[3] = 0x0;
740 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
741 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
742 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
743 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
744 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
745 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
746 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
747 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
748 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
749 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
750 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
751 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
752 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
753 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
754 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
755 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
756 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
757 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
758 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
759 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
760 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
761 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
762 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
763 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
764 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
765 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
766 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
767 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
768 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
769 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
770 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
771 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
772 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
773 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
774 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
775 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
776 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
777 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
778 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
779 ENCODE_RSP_AND_SEND(83);
780 return 0;
781 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700782 /* Check for Apps Only Respond to Get Subsys Build mask */
783 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
785 ssid_first = *(uint16_t *)(buf + 2);
786 ssid_last = *(uint16_t *)(buf + 4);
787 ssid_range = 4 * (ssid_last - ssid_first + 1);
788 /* frame response */
789 driver->apps_rsp_buf[0] = 0x7d;
790 driver->apps_rsp_buf[1] = 0x2;
791 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
792 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
793 driver->apps_rsp_buf[6] = 0x1;
794 driver->apps_rsp_buf[7] = 0x0;
795 ptr = driver->apps_rsp_buf + 8;
796 /* bld time masks */
797 switch (ssid_first) {
798 case MSG_SSID_0:
799 for (i = 0; i < ssid_range; i += 4)
800 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
801 break;
802 case MSG_SSID_1:
803 for (i = 0; i < ssid_range; i += 4)
804 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
805 break;
806 case MSG_SSID_2:
807 for (i = 0; i < ssid_range; i += 4)
808 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
809 break;
810 case MSG_SSID_3:
811 for (i = 0; i < ssid_range; i += 4)
812 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
813 break;
814 case MSG_SSID_4:
815 for (i = 0; i < ssid_range; i += 4)
816 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
817 break;
818 case MSG_SSID_5:
819 for (i = 0; i < ssid_range; i += 4)
820 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
821 break;
822 case MSG_SSID_6:
823 for (i = 0; i < ssid_range; i += 4)
824 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
825 break;
826 case MSG_SSID_7:
827 for (i = 0; i < ssid_range; i += 4)
828 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
829 break;
830 case MSG_SSID_8:
831 for (i = 0; i < ssid_range; i += 4)
832 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
833 break;
834 case MSG_SSID_9:
835 for (i = 0; i < ssid_range; i += 4)
836 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
837 break;
838 case MSG_SSID_10:
839 for (i = 0; i < ssid_range; i += 4)
840 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
841 break;
842 case MSG_SSID_11:
843 for (i = 0; i < ssid_range; i += 4)
844 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
845 break;
846 case MSG_SSID_12:
847 for (i = 0; i < ssid_range; i += 4)
848 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
849 break;
850 case MSG_SSID_13:
851 for (i = 0; i < ssid_range; i += 4)
852 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
853 break;
854 case MSG_SSID_14:
855 for (i = 0; i < ssid_range; i += 4)
856 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
857 break;
858 case MSG_SSID_15:
859 for (i = 0; i < ssid_range; i += 4)
860 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
861 break;
862 case MSG_SSID_16:
863 for (i = 0; i < ssid_range; i += 4)
864 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
865 break;
866 case MSG_SSID_17:
867 for (i = 0; i < ssid_range; i += 4)
868 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
869 break;
870 case MSG_SSID_18:
871 for (i = 0; i < ssid_range; i += 4)
872 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
873 break;
874 }
875 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
876 return 0;
877 }
878 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530879 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700880 /* send response back */
881 driver->apps_rsp_buf[0] = *buf;
882 ENCODE_RSP_AND_SEND(0);
883 msleep(5000);
884 /* call download API */
885 msm_set_restart_mode(RESTART_DLOAD);
886 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
887 kernel_restart(NULL);
888 /* Not required, represents that command isnt sent to modem */
889 return 0;
890 }
Dixon Petersonb46bb992012-01-12 19:16:56 -0800891 /* Check for polling for Apps only DIAG */
892 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
893 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -0800894 /* If no one has registered for polling */
895 if (!(driver->polling_reg_flag)) {
Dixon Petersonb46bb992012-01-12 19:16:56 -0800896 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700897 for (i = 0; i < 3; i++)
898 driver->apps_rsp_buf[i] = *(buf+i);
899 for (i = 0; i < 13; i++)
900 driver->apps_rsp_buf[i+3] = 0;
901
902 ENCODE_RSP_AND_SEND(15);
903 return 0;
904 }
Dixon Petersonb46bb992012-01-12 19:16:56 -0800905 }
906 /* Check for ID for NO MODEM present */
Shalabh Jain3d29fc32012-02-09 17:15:59 -0800907 else if (!(driver->polling_reg_flag)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700908 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -0800909 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700910 for (i = 0; i < 55; i++)
911 driver->apps_rsp_buf[i] = 0;
912
913 ENCODE_RSP_AND_SEND(54);
914 return 0;
915 }
916 /* respond to 0x7c command */
917 else if (*buf == 0x7c) {
918 driver->apps_rsp_buf[0] = 0x7c;
919 for (i = 1; i < 8; i++)
920 driver->apps_rsp_buf[i] = 0;
921 /* Tools ID for APQ 8060 */
922 *(int *)(driver->apps_rsp_buf + 8) =
923 chk_config_get_id();
924 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
925 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
926 ENCODE_RSP_AND_SEND(13);
927 return 0;
928 }
929 }
930#endif
931 return packet_type;
932}
933
934#ifdef CONFIG_DIAG_OVER_USB
935void diag_send_error_rsp(int index)
936{
937 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +0530938
939 if (index > 490) {
940 pr_err("diag: error response too huge, aborting\n");
941 return;
942 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700943 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
944 for (i = 0; i < index; i++)
945 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
946 ENCODE_RSP_AND_SEND(index - 3);
947}
948#else
949static inline void diag_send_error_rsp(int index) {}
950#endif
951
952void diag_process_hdlc(void *data, unsigned len)
953{
954 struct diag_hdlc_decode_type hdlc;
955 int ret, type = 0;
956 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
957 hdlc.dest_ptr = driver->hdlc_buf;
958 hdlc.dest_size = USB_MAX_OUT_BUF;
959 hdlc.src_ptr = data;
960 hdlc.src_size = len;
961 hdlc.src_idx = 0;
962 hdlc.dest_idx = 0;
963 hdlc.escaping = 0;
964
965 ret = diag_hdlc_decode(&hdlc);
966
967 if (ret)
968 type = diag_process_apps_pkt(driver->hdlc_buf,
969 hdlc.dest_idx - 3);
970 else if (driver->debug_flag) {
971 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
972 " errors or partial packet received, packet"
973 " length = %d\n", len);
974 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
975 DUMP_PREFIX_ADDRESS, data, len, 1);
976 driver->debug_flag = 0;
977 }
978 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700979 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700980 diag_send_error_rsp(hdlc.dest_idx);
981 type = 0;
982 }
983 /* implies this packet is NOT meant for apps */
984 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700985 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700986 diag_send_error_rsp(hdlc.dest_idx);
987 } else { /* APQ 8060, Let Q6 respond */
988 if (driver->chqdsp)
989 smd_write(driver->chqdsp, driver->hdlc_buf,
990 hdlc.dest_idx - 3);
991 }
992 type = 0;
993 }
994
995#ifdef DIAG_DEBUG
996 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
997 for (i = 0; i < hdlc.dest_idx; i++)
998 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
999 driver->hdlc_buf)+i));
1000#endif /* DIAG DEBUG */
1001 /* ignore 2 bytes for CRC, one for 7E and send */
1002 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1003 APPEND_DEBUG('g');
1004 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1005 APPEND_DEBUG('h');
1006#ifdef DIAG_DEBUG
1007 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1008 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1009 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1010#endif /* DIAG DEBUG */
1011 }
1012}
1013
1014#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001015/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1016#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001017#define N_LEGACY_READ 1
1018
1019int diagfwd_connect(void)
1020{
1021 int err;
1022
1023 printk(KERN_DEBUG "diag: USB connected\n");
1024 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1025 N_LEGACY_READ);
1026 if (err)
1027 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1028
1029 driver->usb_connected = 1;
1030 driver->in_busy_1 = 0;
1031 driver->in_busy_2 = 0;
1032 driver->in_busy_qdsp_1 = 0;
1033 driver->in_busy_qdsp_2 = 0;
1034 driver->in_busy_wcnss = 0;
1035
1036 /* Poll SMD channels to check for data*/
1037 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1038 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1039 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001040 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001041 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1042 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1043 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001044 /* Poll USB channel to check for data*/
1045 queue_work(driver->diag_wq, &(driver->diag_read_work));
1046#ifdef CONFIG_DIAG_SDIO_PIPE
1047 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1048 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1049 diagfwd_connect_sdio();
1050 else
1051 printk(KERN_INFO "diag: No USB MDM ch");
1052 }
1053#endif
1054 return 0;
1055}
1056
1057int diagfwd_disconnect(void)
1058{
1059 printk(KERN_DEBUG "diag: USB disconnected\n");
1060 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001061 driver->debug_flag = 1;
1062 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001063 if (driver->logging_mode == USB_MODE) {
1064 driver->in_busy_1 = 1;
1065 driver->in_busy_2 = 1;
1066 driver->in_busy_qdsp_1 = 1;
1067 driver->in_busy_qdsp_2 = 1;
1068 driver->in_busy_wcnss = 1;
1069 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001070#ifdef CONFIG_DIAG_SDIO_PIPE
1071 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1072 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1073 diagfwd_disconnect_sdio();
1074#endif
1075 /* TBD - notify and flow control SMD */
1076 return 0;
1077}
1078
1079int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1080{
1081 unsigned char *buf = diag_write_ptr->buf;
1082 /*Determine if the write complete is for data from modem/apps/q6 */
1083 /* Need a context variable here instead */
1084 if (buf == (void *)driver->buf_in_1) {
1085 driver->in_busy_1 = 0;
1086 APPEND_DEBUG('o');
1087 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1088 } else if (buf == (void *)driver->buf_in_2) {
1089 driver->in_busy_2 = 0;
1090 APPEND_DEBUG('O');
1091 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1092 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1093 driver->in_busy_qdsp_1 = 0;
1094 APPEND_DEBUG('p');
1095 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1096 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1097 driver->in_busy_qdsp_2 = 0;
1098 APPEND_DEBUG('P');
1099 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1100 } else if (buf == (void *)driver->buf_in_wcnss) {
1101 driver->in_busy_wcnss = 0;
1102 APPEND_DEBUG('R');
1103 queue_work(driver->diag_wq,
1104 &(driver->diag_read_smd_wcnss_work));
1105 }
1106#ifdef CONFIG_DIAG_SDIO_PIPE
1107 else if (buf == (void *)driver->buf_in_sdio)
1108 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001109 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001110 diagfwd_write_complete_sdio();
1111 else
1112 pr_err("diag: Incorrect buffer pointer while WRITE");
1113#endif
1114 else {
1115 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1116 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1117 POOL_TYPE_WRITE_STRUCT);
1118 APPEND_DEBUG('q');
1119 }
1120 return 0;
1121}
1122
1123int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1124{
1125 int status = diag_read_ptr->status;
1126 unsigned char *buf = diag_read_ptr->buf;
1127
1128 /* Determine if the read complete is for data on legacy/mdm ch */
1129 if (buf == (void *)driver->usb_buf_out) {
1130 driver->read_len_legacy = diag_read_ptr->actual;
1131 APPEND_DEBUG('s');
1132#ifdef DIAG_DEBUG
1133 printk(KERN_INFO "read data from USB, pkt length %d",
1134 diag_read_ptr->actual);
1135 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1136 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1137 diag_read_ptr->actual, 1);
1138#endif /* DIAG DEBUG */
1139 if (driver->logging_mode == USB_MODE) {
1140 if (status != -ECONNRESET && status != -ESHUTDOWN)
1141 queue_work(driver->diag_wq,
1142 &(driver->diag_proc_hdlc_work));
1143 else
1144 queue_work(driver->diag_wq,
1145 &(driver->diag_read_work));
1146 }
1147 }
1148#ifdef CONFIG_DIAG_SDIO_PIPE
1149 else if (buf == (void *)driver->usb_buf_mdm_out) {
1150 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001151 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001152 driver->read_len_mdm = diag_read_ptr->actual;
1153 diagfwd_read_complete_sdio();
1154 } else
1155 pr_err("diag: Incorrect buffer pointer while READ");
1156 }
1157#endif
1158 else
1159 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1160
1161 return 0;
1162}
1163
1164void diag_read_work_fn(struct work_struct *work)
1165{
1166 APPEND_DEBUG('d');
1167 driver->usb_read_ptr->buf = driver->usb_buf_out;
1168 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1169 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1170 APPEND_DEBUG('e');
1171}
1172
1173void diag_process_hdlc_fn(struct work_struct *work)
1174{
1175 APPEND_DEBUG('D');
1176 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1177 diag_read_work_fn(work);
1178 APPEND_DEBUG('E');
1179}
1180
1181void diag_usb_legacy_notifier(void *priv, unsigned event,
1182 struct diag_request *d_req)
1183{
1184 switch (event) {
1185 case USB_DIAG_CONNECT:
1186 diagfwd_connect();
1187 break;
1188 case USB_DIAG_DISCONNECT:
1189 diagfwd_disconnect();
1190 break;
1191 case USB_DIAG_READ_DONE:
1192 diagfwd_read_complete(d_req);
1193 break;
1194 case USB_DIAG_WRITE_DONE:
1195 diagfwd_write_complete(d_req);
1196 break;
1197 default:
1198 printk(KERN_ERR "Unknown event from USB diag\n");
1199 break;
1200 }
1201}
1202
1203#endif /* DIAG OVER USB */
1204
1205static void diag_smd_notify(void *ctxt, unsigned event)
1206{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001207 if (event == SMD_EVENT_CLOSE) {
1208 pr_info("diag: clean modem registration\n");
1209 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001210 driver->ch = 0;
1211 return;
1212 } else if (event == SMD_EVENT_OPEN) {
1213 driver->ch = ch_temp;
1214 }
1215 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001216}
1217
1218#if defined(CONFIG_MSM_N_WAY_SMD)
1219static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1220{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001221 if (event == SMD_EVENT_CLOSE) {
1222 pr_info("diag: clean lpass registration\n");
1223 diag_clear_reg(QDSP_PROC);
1224 driver->chqdsp = 0;
1225 return;
1226 } else if (event == SMD_EVENT_OPEN) {
1227 driver->chqdsp = chqdsp_temp;
1228 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001229 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1230}
1231#endif
1232
1233static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1234{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001235 if (event == SMD_EVENT_CLOSE) {
1236 pr_info("diag: clean wcnss registration\n");
1237 diag_clear_reg(WCNSS_PROC);
1238 driver->ch_wcnss = 0;
1239 return;
1240 } else if (event == SMD_EVENT_OPEN) {
1241 driver->ch_wcnss = ch_wcnss_temp;
1242 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001243 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1244}
1245
1246static int diag_smd_probe(struct platform_device *pdev)
1247{
1248 int r = 0;
1249
Shalabh Jaineefee052011-11-08 23:46:03 -08001250 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001251 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001252 ch_temp = driver->ch;
1253 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001254#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001255 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001256 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1257 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001258 chqdsp_temp = driver->chqdsp;
1259 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001260#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001261 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001262 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1263 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001264 ch_wcnss_temp = driver->ch_wcnss;
1265 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001266 pm_runtime_set_active(&pdev->dev);
1267 pm_runtime_enable(&pdev->dev);
1268 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1269
1270 return 0;
1271}
1272
1273static int diagfwd_runtime_suspend(struct device *dev)
1274{
1275 dev_dbg(dev, "pm_runtime: suspending...\n");
1276 return 0;
1277}
1278
1279static int diagfwd_runtime_resume(struct device *dev)
1280{
1281 dev_dbg(dev, "pm_runtime: resuming...\n");
1282 return 0;
1283}
1284
1285static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1286 .runtime_suspend = diagfwd_runtime_suspend,
1287 .runtime_resume = diagfwd_runtime_resume,
1288};
1289
1290static struct platform_driver msm_smd_ch1_driver = {
1291
1292 .probe = diag_smd_probe,
1293 .driver = {
1294 .name = "DIAG",
1295 .owner = THIS_MODULE,
1296 .pm = &diagfwd_dev_pm_ops,
1297 },
1298};
1299
1300static struct platform_driver diag_smd_lite_driver = {
1301
1302 .probe = diag_smd_probe,
1303 .driver = {
1304 .name = "APPS_RIVA_DATA",
1305 .owner = THIS_MODULE,
1306 .pm = &diagfwd_dev_pm_ops,
1307 },
1308};
1309
1310void diagfwd_init(void)
1311{
1312 diag_debug_buf_idx = 0;
1313 driver->read_len_legacy = 0;
1314 if (driver->buf_in_1 == NULL) {
1315 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1316 if (driver->buf_in_1 == NULL)
1317 goto err;
1318 }
1319 if (driver->buf_in_2 == NULL) {
1320 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1321 if (driver->buf_in_2 == NULL)
1322 goto err;
1323 }
1324 if (driver->buf_in_qdsp_1 == NULL) {
1325 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1326 if (driver->buf_in_qdsp_1 == NULL)
1327 goto err;
1328 }
1329 if (driver->buf_in_qdsp_2 == NULL) {
1330 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1331 if (driver->buf_in_qdsp_2 == NULL)
1332 goto err;
1333 }
1334 if (driver->buf_in_wcnss == NULL) {
1335 driver->buf_in_wcnss = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1336 if (driver->buf_in_wcnss == NULL)
1337 goto err;
1338 }
1339 if (driver->usb_buf_out == NULL &&
1340 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1341 GFP_KERNEL)) == NULL)
1342 goto err;
1343 if (driver->hdlc_buf == NULL
1344 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1345 goto err;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001346 if (driver->user_space_data == NULL)
1347 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1348 if (driver->user_space_data == NULL)
1349 goto err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001350 if (driver->msg_masks == NULL
1351 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1352 GFP_KERNEL)) == NULL)
1353 goto err;
1354 if (driver->log_masks == NULL &&
1355 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1356 goto err;
1357 driver->log_masks_length = 8*MAX_EQUIP_ID;
1358 if (driver->event_masks == NULL &&
1359 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1360 GFP_KERNEL)) == NULL)
1361 goto err;
1362 if (driver->client_map == NULL &&
1363 (driver->client_map = kzalloc
1364 ((driver->num_clients) * sizeof(struct diag_client_map),
1365 GFP_KERNEL)) == NULL)
1366 goto err;
1367 if (driver->buf_tbl == NULL)
1368 driver->buf_tbl = kzalloc(buf_tbl_size *
1369 sizeof(struct diag_write_device), GFP_KERNEL);
1370 if (driver->buf_tbl == NULL)
1371 goto err;
1372 if (driver->data_ready == NULL &&
1373 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1374 , GFP_KERNEL)) == NULL)
1375 goto err;
1376 if (driver->table == NULL &&
1377 (driver->table = kzalloc(diag_max_registration*
1378 sizeof(struct diag_master_table),
1379 GFP_KERNEL)) == NULL)
1380 goto err;
1381 if (driver->write_ptr_1 == NULL) {
1382 driver->write_ptr_1 = kzalloc(
1383 sizeof(struct diag_request), GFP_KERNEL);
1384 if (driver->write_ptr_1 == NULL)
1385 goto err;
1386 }
1387 if (driver->write_ptr_2 == NULL) {
1388 driver->write_ptr_2 = kzalloc(
1389 sizeof(struct diag_request), GFP_KERNEL);
1390 if (driver->write_ptr_2 == NULL)
1391 goto err;
1392 }
1393 if (driver->write_ptr_qdsp_1 == NULL) {
1394 driver->write_ptr_qdsp_1 = kzalloc(
1395 sizeof(struct diag_request), GFP_KERNEL);
1396 if (driver->write_ptr_qdsp_1 == NULL)
1397 goto err;
1398 }
1399 if (driver->write_ptr_qdsp_2 == NULL) {
1400 driver->write_ptr_qdsp_2 = kzalloc(
1401 sizeof(struct diag_request), GFP_KERNEL);
1402 if (driver->write_ptr_qdsp_2 == NULL)
1403 goto err;
1404 }
1405 if (driver->write_ptr_wcnss == NULL) {
1406 driver->write_ptr_wcnss = kzalloc(
1407 sizeof(struct diag_request), GFP_KERNEL);
1408 if (driver->write_ptr_wcnss == NULL)
1409 goto err;
1410 }
1411 if (driver->usb_read_ptr == NULL) {
1412 driver->usb_read_ptr = kzalloc(
1413 sizeof(struct diag_request), GFP_KERNEL);
1414 if (driver->usb_read_ptr == NULL)
1415 goto err;
1416 }
1417 if (driver->pkt_buf == NULL &&
1418 (driver->pkt_buf = kzalloc(PKT_SIZE,
1419 GFP_KERNEL)) == NULL)
1420 goto err;
1421 if (driver->apps_rsp_buf == NULL) {
1422 driver->apps_rsp_buf = kzalloc(500, GFP_KERNEL);
1423 if (driver->apps_rsp_buf == NULL)
1424 goto err;
1425 }
1426 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1427#ifdef CONFIG_DIAG_OVER_USB
1428 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1429 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
1430 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
1431 diag_usb_legacy_notifier);
1432 if (IS_ERR(driver->legacy_ch)) {
1433 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
1434 goto err;
1435 }
1436#endif
1437 platform_driver_register(&msm_smd_ch1_driver);
1438 platform_driver_register(&diag_smd_lite_driver);
1439
1440 return;
1441err:
1442 pr_err("diag: Could not initialize diag buffers");
1443 kfree(driver->buf_in_1);
1444 kfree(driver->buf_in_2);
1445 kfree(driver->buf_in_qdsp_1);
1446 kfree(driver->buf_in_qdsp_2);
1447 kfree(driver->buf_in_wcnss);
1448 kfree(driver->usb_buf_out);
1449 kfree(driver->hdlc_buf);
1450 kfree(driver->msg_masks);
1451 kfree(driver->log_masks);
1452 kfree(driver->event_masks);
1453 kfree(driver->client_map);
1454 kfree(driver->buf_tbl);
1455 kfree(driver->data_ready);
1456 kfree(driver->table);
1457 kfree(driver->pkt_buf);
1458 kfree(driver->write_ptr_1);
1459 kfree(driver->write_ptr_2);
1460 kfree(driver->write_ptr_qdsp_1);
1461 kfree(driver->write_ptr_qdsp_2);
1462 kfree(driver->write_ptr_wcnss);
1463 kfree(driver->usb_read_ptr);
1464 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001465 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001466 if (driver->diag_wq)
1467 destroy_workqueue(driver->diag_wq);
1468}
1469
1470void diagfwd_exit(void)
1471{
1472 smd_close(driver->ch);
1473 smd_close(driver->chqdsp);
1474 smd_close(driver->ch_wcnss);
1475 driver->ch = 0; /* SMD can make this NULL */
1476 driver->chqdsp = 0;
1477 driver->ch_wcnss = 0;
1478#ifdef CONFIG_DIAG_OVER_USB
1479 if (driver->usb_connected)
1480 usb_diag_free_req(driver->legacy_ch);
1481 usb_diag_close(driver->legacy_ch);
1482#endif
1483 platform_driver_unregister(&msm_smd_ch1_driver);
1484 platform_driver_unregister(&diag_smd_lite_driver);
1485 kfree(driver->buf_in_1);
1486 kfree(driver->buf_in_2);
1487 kfree(driver->buf_in_qdsp_1);
1488 kfree(driver->buf_in_qdsp_2);
1489 kfree(driver->buf_in_wcnss);
1490 kfree(driver->usb_buf_out);
1491 kfree(driver->hdlc_buf);
1492 kfree(driver->msg_masks);
1493 kfree(driver->log_masks);
1494 kfree(driver->event_masks);
1495 kfree(driver->client_map);
1496 kfree(driver->buf_tbl);
1497 kfree(driver->data_ready);
1498 kfree(driver->table);
1499 kfree(driver->pkt_buf);
1500 kfree(driver->write_ptr_1);
1501 kfree(driver->write_ptr_2);
1502 kfree(driver->write_ptr_qdsp_1);
1503 kfree(driver->write_ptr_qdsp_2);
1504 kfree(driver->write_ptr_wcnss);
1505 kfree(driver->usb_read_ptr);
1506 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001507 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001508 destroy_workqueue(driver->diag_wq);
1509}