blob: cc2b6e55077e0a0719f742014c8460aa03120334 [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;
Shalabh Jain321c8b52012-02-22 12:37:06 -080046int diag_event_num_bytes;
47int diag_event_config;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070048struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
49struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
Shalabh Jain321c8b52012-02-22 12:37:06 -080050struct mask_info {
51 int equip_id;
52 int num_items;
53 int index;
54};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070055
56#define ENCODE_RSP_AND_SEND(buf_length) \
57do { \
58 send.state = DIAG_STATE_START; \
59 send.pkt = driver->apps_rsp_buf; \
60 send.last = (void *)(driver->apps_rsp_buf + buf_length); \
61 send.terminate = 1; \
62 if (!driver->in_busy_1) { \
63 enc.dest = driver->buf_in_1; \
Shalabh Jain321c8b52012-02-22 12:37:06 -080064 enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);\
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070065 diag_hdlc_encode(&send, &enc); \
66 driver->write_ptr_1->buf = driver->buf_in_1; \
67 driver->write_ptr_1->length = (int)(enc.dest - \
68 (void *)(driver->buf_in_1)); \
Shalabh Jain3893bf92011-09-18 18:37:16 -070069 driver->in_busy_1 = 1; \
Shalabh Jain69890aa2011-10-10 12:59:16 -070070 diag_device_write(driver->buf_in_1, MODEM_DATA, \
71 driver->write_ptr_1); \
Shalabh Jain321c8b52012-02-22 12:37:06 -080072 memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE); \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070073 } \
74} while (0)
75
76#define CHK_OVERFLOW(bufStart, start, end, length) \
77((bufStart <= start) && (end - start >= length)) ? 1 : 0
78
Shalabh Jainfb8e3c12011-10-19 17:29:42 -070079int chk_config_get_id(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070080{
Shalabh Jain482bf122011-12-06 03:54:47 -080081 /* For all Fusion targets, Modem will always be present */
82 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
83 return 0;
84
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070085 switch (socinfo_get_id()) {
86 case APQ8060_MACHINE_ID:
87 case MSM8660_MACHINE_ID:
88 return APQ8060_TOOLS_ID;
89 case AO8960_MACHINE_ID:
Shalabh Jain10f5f432012-01-11 11:45:44 +053090 case MSM8260A_MACHINE_ID:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070091 return AO8960_TOOLS_ID;
Shalabh Jainfb8e3c12011-10-19 17:29:42 -070092 case APQ8064_MACHINE_ID:
93 return APQ8064_TOOLS_ID;
Shalabh Jain2f4cea62011-12-19 21:50:03 -080094 case MSM8930_MACHINE_ID:
95 return MSM8930_TOOLS_ID;
Shalabh Jain10f5f432012-01-11 11:45:44 +053096 case MSM8974_MACHINE_ID:
97 return MSM8974_TOOLS_ID;
Shalabh Jainfb8e3c12011-10-19 17:29:42 -070098 default:
99 return 0;
100 }
101}
102
103/*
Shalabh Jain321c8b52012-02-22 12:37:06 -0800104 * This will return TRUE for targets which support apps only mode and hence SSR.
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700105 * This applies to 8960 and newer targets.
106 */
107int chk_apps_only(void)
108{
109 switch (socinfo_get_id()) {
110 case AO8960_MACHINE_ID:
111 case APQ8064_MACHINE_ID:
Shalabh Jain2f4cea62011-12-19 21:50:03 -0800112 case MSM8930_MACHINE_ID:
113 case MSM8630_MACHINE_ID:
114 case MSM8230_MACHINE_ID:
115 case APQ8030_MACHINE_ID:
116 case MSM8627_MACHINE_ID:
117 case MSM8227_MACHINE_ID:
Shalabh Jain10f5f432012-01-11 11:45:44 +0530118 case MSM8974_MACHINE_ID:
119 case MDM9615_MACHINE_ID:
120 case MSM8260A_MACHINE_ID:
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700121 return 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700122 default:
123 return 0;
124 }
125}
126
Shalabh Jain10f5f432012-01-11 11:45:44 +0530127/*
128 * This will return TRUE for targets which support apps as master.
129 * Thus, SW DLOAD and Mode Reset are supported on apps processor.
130 * This applies to 8960 and newer targets.
131 */
132int chk_apps_master(void)
133{
Shalabh Jain118bd8a2012-02-06 11:37:39 -0800134 if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615() ||
135 cpu_is_apq8064() || cpu_is_msm8627())
Shalabh Jain10f5f432012-01-11 11:45:44 +0530136 return 1;
137 else
138 return 0;
139}
140
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141void __diag_smd_send_req(void)
142{
143 void *buf = NULL;
144 int *in_busy_ptr = NULL;
145 struct diag_request *write_ptr_modem = NULL;
146
147 if (!driver->in_busy_1) {
148 buf = driver->buf_in_1;
149 write_ptr_modem = driver->write_ptr_1;
150 in_busy_ptr = &(driver->in_busy_1);
151 } else if (!driver->in_busy_2) {
152 buf = driver->buf_in_2;
153 write_ptr_modem = driver->write_ptr_2;
154 in_busy_ptr = &(driver->in_busy_2);
155 }
156
157 if (driver->ch && buf) {
158 int r = smd_read_avail(driver->ch);
159
160 if (r > IN_BUF_SIZE) {
161 if (r < MAX_IN_BUF_SIZE) {
162 pr_err("diag: SMD sending in "
163 "packets upto %d bytes", r);
164 buf = krealloc(buf, r, GFP_KERNEL);
165 } else {
166 pr_err("diag: SMD sending in "
167 "packets more than %d bytes", MAX_IN_BUF_SIZE);
168 return;
169 }
170 }
171 if (r > 0) {
172 if (!buf)
173 pr_info("Out of diagmem for Modem\n");
174 else {
175 APPEND_DEBUG('i');
176 smd_read(driver->ch, buf, r);
177 APPEND_DEBUG('j');
178 write_ptr_modem->length = r;
179 *in_busy_ptr = 1;
180 diag_device_write(buf, MODEM_DATA,
181 write_ptr_modem);
182 }
183 }
184 }
185}
186
187int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr)
188{
189 int i, err = 0;
190
191 if (driver->logging_mode == MEMORY_DEVICE_MODE) {
192 if (proc_num == APPS_DATA) {
193 for (i = 0; i < driver->poolsize_write_struct; i++)
194 if (driver->buf_tbl[i].length == 0) {
195 driver->buf_tbl[i].buf = buf;
196 driver->buf_tbl[i].length =
197 driver->used;
198#ifdef DIAG_DEBUG
199 pr_debug("diag: ENQUEUE buf ptr"
200 " and length is %x , %d\n",
201 (unsigned int)(driver->buf_
202 tbl[i].buf), driver->buf_tbl[i].length);
203#endif
204 break;
205 }
206 }
207 for (i = 0; i < driver->num_clients; i++)
208 if (driver->client_map[i].pid ==
209 driver->logging_process_id)
210 break;
211 if (i < driver->num_clients) {
Shalabh Jain69890aa2011-10-10 12:59:16 -0700212 driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700213 wake_up_interruptible(&driver->wait_q);
214 } else
215 return -EINVAL;
216 } else if (driver->logging_mode == NO_LOGGING_MODE) {
217 if (proc_num == MODEM_DATA) {
218 driver->in_busy_1 = 0;
219 driver->in_busy_2 = 0;
220 queue_work(driver->diag_wq, &(driver->
221 diag_read_smd_work));
222 } else if (proc_num == QDSP_DATA) {
223 driver->in_busy_qdsp_1 = 0;
224 driver->in_busy_qdsp_2 = 0;
225 queue_work(driver->diag_wq, &(driver->
226 diag_read_smd_qdsp_work));
227 } else if (proc_num == WCNSS_DATA) {
228 driver->in_busy_wcnss = 0;
229 queue_work(driver->diag_wq, &(driver->
230 diag_read_smd_wcnss_work));
231 }
Shalabh Jain482bf122011-12-06 03:54:47 -0800232#ifdef CONFIG_DIAG_SDIO_PIPE
233 else if (proc_num == SDIO_DATA) {
234 driver->in_busy_sdio = 0;
235 queue_work(driver->diag_sdio_wq,
236 &(driver->diag_read_sdio_work));
237 }
238#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700239 err = -1;
240 }
241#ifdef CONFIG_DIAG_OVER_USB
242 else if (driver->logging_mode == USB_MODE) {
243 if (proc_num == APPS_DATA) {
244 driver->write_ptr_svc = (struct diag_request *)
245 (diagmem_alloc(driver, sizeof(struct diag_request),
246 POOL_TYPE_WRITE_STRUCT));
247 if (driver->write_ptr_svc) {
248 driver->write_ptr_svc->length = driver->used;
249 driver->write_ptr_svc->buf = buf;
250 err = usb_diag_write(driver->legacy_ch,
251 driver->write_ptr_svc);
252 } else
253 err = -1;
254 } else if (proc_num == MODEM_DATA) {
255 write_ptr->buf = buf;
256#ifdef DIAG_DEBUG
257 printk(KERN_INFO "writing data to USB,"
258 "pkt length %d\n", write_ptr->length);
259 print_hex_dump(KERN_DEBUG, "Written Packet Data to"
260 " USB: ", 16, 1, DUMP_PREFIX_ADDRESS,
261 buf, write_ptr->length, 1);
262#endif /* DIAG DEBUG */
263 err = usb_diag_write(driver->legacy_ch, write_ptr);
264 } else if (proc_num == QDSP_DATA) {
265 write_ptr->buf = buf;
266 err = usb_diag_write(driver->legacy_ch, write_ptr);
267 } else if (proc_num == WCNSS_DATA) {
268 write_ptr->buf = buf;
269 err = usb_diag_write(driver->legacy_ch, write_ptr);
270 }
271#ifdef CONFIG_DIAG_SDIO_PIPE
272 else if (proc_num == SDIO_DATA) {
273 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -0800274 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700275 write_ptr->buf = buf;
276 err = usb_diag_write(driver->mdm_ch, write_ptr);
277 } else
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800278 pr_err("diag: Incorrect sdio data "
279 "while USB write\n");
280 }
281#endif
282#ifdef CONFIG_DIAG_HSIC_PIPE
283 else if (proc_num == HSIC_DATA) {
284 if (driver->hsic_device_enabled) {
285 write_ptr->buf = buf;
286 err = usb_diag_write(driver->mdm_ch, write_ptr);
287 } else
288 pr_err("diag: Incorrect hsic data "
289 "while USB write\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700290 }
291#endif
292 APPEND_DEBUG('d');
293 }
294#endif /* DIAG OVER USB */
295 return err;
296}
297
298void __diag_smd_wcnss_send_req(void)
299{
300 void *buf = driver->buf_in_wcnss;
301 int *in_busy_wcnss_ptr = &(driver->in_busy_wcnss);
302 struct diag_request *write_ptr_wcnss = driver->write_ptr_wcnss;
303
Shalabh Jain3893bf92011-09-18 18:37:16 -0700304 if ((!driver->in_busy_wcnss) && driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700305 int r = smd_read_avail(driver->ch_wcnss);
306 if (r > IN_BUF_SIZE) {
307 if (r < MAX_IN_BUF_SIZE) {
308 pr_err("diag: wcnss packets > %d bytes", r);
309 buf = krealloc(buf, r, GFP_KERNEL);
310 } else {
311 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
312 return;
313 }
314 }
315 if (r > 0) {
316 if (!buf) {
317 pr_err("Out of diagmem for wcnss\n");
318 } else {
319 APPEND_DEBUG('i');
320 smd_read(driver->ch_wcnss, buf, r);
321 APPEND_DEBUG('j');
322 write_ptr_wcnss->length = r;
323 *in_busy_wcnss_ptr = 1;
324 diag_device_write(buf, WCNSS_DATA,
325 write_ptr_wcnss);
326 }
327 }
328 }
329}
330
331void __diag_smd_qdsp_send_req(void)
332{
333 void *buf = NULL;
334 int *in_busy_qdsp_ptr = NULL;
335 struct diag_request *write_ptr_qdsp = NULL;
336
337 if (!driver->in_busy_qdsp_1) {
338 buf = driver->buf_in_qdsp_1;
339 write_ptr_qdsp = driver->write_ptr_qdsp_1;
340 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_1);
341 } else if (!driver->in_busy_qdsp_2) {
342 buf = driver->buf_in_qdsp_2;
343 write_ptr_qdsp = driver->write_ptr_qdsp_2;
344 in_busy_qdsp_ptr = &(driver->in_busy_qdsp_2);
345 }
346
347 if (driver->chqdsp && buf) {
348 int r = smd_read_avail(driver->chqdsp);
349
350 if (r > IN_BUF_SIZE) {
351 if (r < MAX_IN_BUF_SIZE) {
352 pr_err("diag: SMD sending in "
353 "packets upto %d bytes", r);
354 buf = krealloc(buf, r, GFP_KERNEL);
355 } else {
356 pr_err("diag: SMD sending in "
357 "packets more than %d bytes", MAX_IN_BUF_SIZE);
358 return;
359 }
360 }
361 if (r > 0) {
362 if (!buf)
363 printk(KERN_INFO "Out of diagmem for QDSP\n");
364 else {
365 APPEND_DEBUG('i');
366 smd_read(driver->chqdsp, buf, r);
367 APPEND_DEBUG('j');
368 write_ptr_qdsp->length = r;
369 *in_busy_qdsp_ptr = 1;
370 diag_device_write(buf, QDSP_DATA,
371 write_ptr_qdsp);
372 }
373 }
374 }
375}
376
377static void diag_print_mask_table(void)
378{
379/* Enable this to print mask table when updated */
380#ifdef MASK_DEBUG
381 int first;
382 int last;
383 uint8_t *ptr = driver->msg_masks;
384 int i = 0;
385
386 while (*(uint32_t *)(ptr + 4)) {
387 first = *(uint32_t *)ptr;
388 ptr += 4;
389 last = *(uint32_t *)ptr;
390 ptr += 4;
391 printk(KERN_INFO "SSID %d - %d\n", first, last);
392 for (i = 0 ; i <= last - first ; i++)
393 printk(KERN_INFO "MASK:%x\n", *((uint32_t *)ptr + i));
394 ptr += ((last - first) + 1)*4;
395
396 }
397#endif
398}
399
400static void diag_update_msg_mask(int start, int end , uint8_t *buf)
401{
402 int found = 0;
403 int first;
404 int last;
405 uint8_t *ptr = driver->msg_masks;
406 uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
407 uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
408
409 mutex_lock(&driver->diagchar_mutex);
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530410
Shalabh Jain321c8b52012-02-22 12:37:06 -0800411 /* First SSID can be zero : So check that last is non-zero */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700412 while (*(uint32_t *)(ptr + 4)) {
413 first = *(uint32_t *)ptr;
414 ptr += 4;
415 last = *(uint32_t *)ptr;
416 ptr += 4;
417 if (start >= first && start <= last) {
418 ptr += (start - first)*4;
419 if (end <= last)
420 if (CHK_OVERFLOW(ptr_buffer_start, ptr,
421 ptr_buffer_end,
422 (((end - start)+1)*4)))
423 memcpy(ptr, buf , ((end - start)+1)*4);
424 else
425 printk(KERN_CRIT "Not enough"
426 " buffer space for"
427 " MSG_MASK\n");
428 else
429 printk(KERN_INFO "Unable to copy"
430 " mask change\n");
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530431
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700432 found = 1;
433 break;
434 } else {
435 ptr += ((last - first) + 1)*4;
436 }
437 }
438 /* Entry was not found - add new table */
439 if (!found) {
440 if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
441 8 + ((end - start) + 1)*4)) {
442 memcpy(ptr, &(start) , 4);
443 ptr += 4;
444 memcpy(ptr, &(end), 4);
445 ptr += 4;
446 memcpy(ptr, buf , ((end - start) + 1)*4);
447 } else
448 printk(KERN_CRIT " Not enough buffer"
449 " space for MSG_MASK\n");
450 }
451 mutex_unlock(&driver->diagchar_mutex);
452 diag_print_mask_table();
Shalabh Jain2c783cb2012-01-15 11:09:29 +0530453
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700454}
455
Shalabh Jain321c8b52012-02-22 12:37:06 -0800456static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700457{
458 uint8_t *ptr = driver->event_masks;
459 uint8_t *temp = buf + 2;
460
461 mutex_lock(&driver->diagchar_mutex);
462 if (!toggle)
463 memset(ptr, 0 , EVENT_MASK_SIZE);
464 else
465 if (CHK_OVERFLOW(ptr, ptr,
Shalabh Jain321c8b52012-02-22 12:37:06 -0800466 ptr+EVENT_MASK_SIZE, num_bytes))
467 memcpy(ptr, temp , num_bytes);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700468 else
469 printk(KERN_CRIT "Not enough buffer space "
470 "for EVENT_MASK\n");
471 mutex_unlock(&driver->diagchar_mutex);
472}
473
474static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
475{
476 uint8_t *temp = buf;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700477 int i = 0;
478 unsigned char *ptr_data;
479 int offset = 8*MAX_EQUIP_ID;
480 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
481
482 mutex_lock(&driver->diagchar_mutex);
483 /* Check if we already know index of this equipment ID */
484 for (i = 0; i < MAX_EQUIP_ID; i++) {
485 if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
486 offset = ptr->index;
487 break;
488 }
489 if ((ptr->equip_id == 0) && (ptr->index == 0)) {
Shalabh Jain321c8b52012-02-22 12:37:06 -0800490 /* Reached a null entry */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700491 ptr->equip_id = equip_id;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800492 ptr->num_items = num_items;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700493 ptr->index = driver->log_masks_length;
494 offset = driver->log_masks_length;
495 driver->log_masks_length += ((num_items+7)/8);
496 break;
497 }
498 ptr++;
499 }
500 ptr_data = driver->log_masks + offset;
501 if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
502 + LOG_MASK_SIZE, (num_items+7)/8))
503 memcpy(ptr_data, temp , (num_items+7)/8);
504 else
505 printk(KERN_CRIT " Not enough buffer space for LOG_MASK\n");
506 mutex_unlock(&driver->diagchar_mutex);
507}
508
509static void diag_update_pkt_buffer(unsigned char *buf)
510{
511 unsigned char *ptr = driver->pkt_buf;
512 unsigned char *temp = buf;
513
514 mutex_lock(&driver->diagchar_mutex);
515 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
516 memcpy(ptr, temp , driver->pkt_length);
517 else
518 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
519 mutex_unlock(&driver->diagchar_mutex);
520}
521
522void diag_update_userspace_clients(unsigned int type)
523{
524 int i;
525
526 mutex_lock(&driver->diagchar_mutex);
527 for (i = 0; i < driver->num_clients; i++)
528 if (driver->client_map[i].pid != 0)
529 driver->data_ready[i] |= type;
530 wake_up_interruptible(&driver->wait_q);
531 mutex_unlock(&driver->diagchar_mutex);
532}
533
534void diag_update_sleeping_process(int process_id)
535{
536 int i;
537
538 mutex_lock(&driver->diagchar_mutex);
539 for (i = 0; i < driver->num_clients; i++)
540 if (driver->client_map[i].pid == process_id) {
541 driver->data_ready[i] |= PKT_TYPE;
542 break;
543 }
544 wake_up_interruptible(&driver->wait_q);
545 mutex_unlock(&driver->diagchar_mutex);
546}
547
548void diag_send_data(struct diag_master_table entry, unsigned char *buf,
549 int len, int type)
550{
551 driver->pkt_length = len;
552 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
553 diag_update_pkt_buffer(buf);
554 diag_update_sleeping_process(entry.process_id);
555 } else {
556 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700557 if (entry.client_id == MODEM_PROC && driver->ch) {
Shalabh Jain10f5f432012-01-11 11:45:44 +0530558 if (chk_apps_master() &&
Shalabh Jainc9f35092011-07-28 18:36:17 -0700559 (int)(*(char *)buf) == MODE_CMD)
Dixon Petersonff425d12011-12-06 18:12:35 -0800560 if ((int)(*(char *)(buf+1)) ==
561 RESET_ID)
Shalabh Jainc9f35092011-07-28 18:36:17 -0700562 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700563 smd_write(driver->ch, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700564 } else if (entry.client_id == QDSP_PROC &&
565 driver->chqdsp) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700566 smd_write(driver->chqdsp, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700567 } else if (entry.client_id == WCNSS_PROC &&
568 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700569 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700570 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700571 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700572 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700573 }
574 }
575}
576
Shalabh Jain321c8b52012-02-22 12:37:06 -0800577void diag_modem_mask_update_fn(struct work_struct *work)
578{
579 diag_send_msg_mask_update(driver->ch_cntl);
580 diag_send_log_mask_update(driver->ch_cntl);
581 diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
582}
583
584void diag_qdsp_mask_update_fn(struct work_struct *work)
585{
586 diag_send_msg_mask_update(driver->chqdsp_cntl);
587 diag_send_log_mask_update(driver->chqdsp_cntl);
588 diag_send_event_mask_update(driver->chqdsp_cntl, diag_event_num_bytes);
589}
590
591void diag_wcnss_mask_update_fn(struct work_struct *work)
592{
593 diag_send_msg_mask_update(driver->ch_wcnss_cntl);
594 diag_send_log_mask_update(driver->ch_wcnss_cntl);
595 diag_send_event_mask_update(driver->ch_wcnss_cntl,
596 diag_event_num_bytes);
597}
598
599void diag_msg_mask_update_fn(struct work_struct *work)
600{
601 diag_send_msg_mask_update(driver->ch_cntl);
602 diag_send_msg_mask_update(driver->chqdsp_cntl);
603 diag_send_msg_mask_update(driver->ch_wcnss_cntl);
604}
605
606void diag_log_mask_update_fn(struct work_struct *work)
607{
608 diag_send_log_mask_update(driver->ch_cntl);
609 diag_send_log_mask_update(driver->chqdsp_cntl);
610 diag_send_log_mask_update(driver->ch_wcnss_cntl);
611}
612
613void diag_send_log_mask_update(smd_channel_t *ch)
614{
615 void *buf = driver->buf_log_mask_update;
616 int header_size = sizeof(struct diag_ctrl_log_mask);
617 struct mask_info *ptr = (struct mask_info *)driver->log_masks;
618 int i, size = (driver->log_mask->num_items+7)/8;
619
620 for (i = 0; i < MAX_EQUIP_ID; i++) {
621 /* reached null entry */
622 if ((ptr->equip_id == 0) && (ptr->index == 0))
623 break;
624 driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
625 driver->log_mask->num_items = ptr->num_items;
626 driver->log_mask->data_len = 11 + size;
627 driver->log_mask->stream_id = 1; /* 2, if dual stream */
628 driver->log_mask->status = 3; /* status for valid mask */
629 driver->log_mask->equip_id = ptr->equip_id;
630 driver->log_mask->log_mask_size = size;
631 memcpy(buf, driver->log_mask, header_size);
632 memcpy(buf+header_size, driver->log_masks+ptr->index, size);
633 msleep(100);
634 if (ch)
635 smd_write(ch, buf, header_size + size);
636 ptr++;
637 }
638}
639
640void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
641{
642 void *buf = driver->buf_event_mask_update;
643 int header_size = sizeof(struct diag_ctrl_event_mask);
644
645 /* send event mask update */
646 driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
647 driver->event_mask->data_len = 7 + num_bytes;
648 driver->event_mask->stream_id = 1; /* 2, if dual stream */
649 driver->event_mask->status = 3; /* status for valid mask */
650 driver->event_mask->event_config = diag_event_config; /* event config */
651 driver->event_mask->event_mask_size = num_bytes;
652 memcpy(buf, driver->event_mask, header_size);
653 memcpy(buf+header_size, driver->event_masks, num_bytes);
654 msleep(100);
655 if (ch)
656 smd_write(ch, buf, header_size + num_bytes);
657}
658
659void diag_send_msg_mask_update(smd_channel_t *ch)
660{
661 void *buf = driver->buf_msg_mask_update;
662 int first, last;
663 int header_size = sizeof(struct diag_ctrl_msg_mask);
664 uint8_t *ptr = driver->msg_masks;
665
666 while (*(uint32_t *)(ptr + 4)) {
667 first = *(uint32_t *)ptr;
668 ptr += 4;
669 last = *(uint32_t *)ptr;
670 ptr += 4;
671 /* send event mask update */
672 driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
673 driver->msg_mask->msg_mask_size = last - first + 1;
674 driver->msg_mask->data_len = 11 +
675 4 * (driver->msg_mask->msg_mask_size);
676 driver->msg_mask->stream_id = 1; /* 2, if dual stream */
677 driver->msg_mask->status = 3; /* status for valid mask */
678 driver->msg_mask->msg_mode = 0; /* Legcay mode */
679 driver->msg_mask->ssid_first = first;
680 driver->msg_mask->ssid_last = last;
681 memcpy(buf, driver->msg_mask, header_size);
682 memcpy(buf+header_size, ptr,
683 4 * (driver->msg_mask->msg_mask_size));
684 /* since mask updates are slow, so sleep needed as to
685 prevent modem running out of DSM items */
686 msleep(100);
687 if (ch)
688 smd_write(ch, buf,
689 header_size + 4*(driver->msg_mask->msg_mask_size));
690 ptr += ((last - first) + 1)*4;
691 }
692}
693
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700694static int diag_process_apps_pkt(unsigned char *buf, int len)
695{
696 uint16_t subsys_cmd_code;
697 int subsys_id, ssid_first, ssid_last, ssid_range;
698 int packet_type = 1, i, cmd_code;
699 unsigned char *temp = buf;
700 int data_type;
701#if defined(CONFIG_DIAG_OVER_USB)
702 int payload_length;
703 unsigned char *ptr;
704#endif
705
Shalabh Jain321c8b52012-02-22 12:37:06 -0800706 /* Set log masks */
707 if (*buf == 0x73 && *(int *)(buf+4) == 3) {
708 buf += 8;
709 /* Read Equip ID and pass as first param below*/
710 diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
711 diag_update_userspace_clients(LOG_MASKS_TYPE);
712#if defined(CONFIG_DIAG_OVER_USB)
713 if (chk_apps_only()) {
714 driver->apps_rsp_buf[0] = 0x73;
715 *(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
716 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
717 payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
718 for (i = 0; i < payload_length; i++)
719 *(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
720 queue_work(driver->diag_cntl_wq,
721 &(driver->diag_log_mask_update_work));
722 ENCODE_RSP_AND_SEND(12 + payload_length - 1);
723 return 0;
724 } else
725 buf = temp;
726#endif
727 } /* Check for set message mask */
728 else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
729 ssid_first = *(uint16_t *)(buf + 2);
730 ssid_last = *(uint16_t *)(buf + 4);
731 ssid_range = 4 * (ssid_last - ssid_first + 1);
732 diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
733 diag_update_userspace_clients(MSG_MASKS_TYPE);
734#if defined(CONFIG_DIAG_OVER_USB)
735 if (chk_apps_only()) {
736 for (i = 0; i < 8 + ssid_range; i++)
737 *(driver->apps_rsp_buf + i) = *(buf+i);
738 *(driver->apps_rsp_buf + 6) = 0x1;
739 queue_work(driver->diag_cntl_wq,
740 &(driver->diag_msg_mask_update_work));
741 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
742 return 0;
743 } else
744 buf = temp;
745#endif
746 } else if (*buf == 0x82) { /* event mask change */
747 buf += 4;
748 diag_event_num_bytes = (*(uint16_t *)buf)/8+1;
749 diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
750 diag_update_userspace_clients(EVENT_MASKS_TYPE);
751#if defined(CONFIG_DIAG_OVER_USB)
752 if (chk_apps_only()) {
753 driver->apps_rsp_buf[0] = 0x82;
754 driver->apps_rsp_buf[1] = 0x0;
755 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
756 *(uint16_t *)(driver->apps_rsp_buf + 4) =
757 EVENT_LAST_ID + 1;
758 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
759 *(unsigned char *)(driver->apps_rsp_buf + 6 + i)
760 = 0x0;
761 /* cannot do this on work queue, as each event update
762 needs a num_bytes variable. Each queue_work call will
763 overwrite the previous input, as its the same struct */
764 diag_send_event_mask_update(driver->ch_cntl,
765 diag_event_num_bytes);
766 diag_send_event_mask_update(driver->chqdsp_cntl,
767 diag_event_num_bytes);
768 diag_send_event_mask_update(driver->ch_wcnss_cntl,
769 diag_event_num_bytes);
770 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
771 return 0;
772 } else
773 buf = temp;
774#endif
775 } else if (*buf == 0x60) {
776 diag_event_config = *(buf+1);
777#if defined(CONFIG_DIAG_OVER_USB)
778 if (chk_apps_only()) {
779 driver->apps_rsp_buf[0] = 0x60;
780 driver->apps_rsp_buf[1] = 0x0;
781 driver->apps_rsp_buf[2] = 0x0;
782 diag_send_event_mask_update(driver->ch_cntl,
783 diag_event_num_bytes);
784 diag_send_event_mask_update(driver->chqdsp_cntl,
785 diag_event_num_bytes);
786 diag_send_event_mask_update(driver->ch_wcnss_cntl,
787 diag_event_num_bytes);
788 ENCODE_RSP_AND_SEND(2);
789 return 0;
790 }
791#endif
792 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700793 /* Check for registered clients and forward packet to apropriate proc */
794 cmd_code = (int)(*(char *)buf);
795 temp++;
796 subsys_id = (int)(*(char *)temp);
797 temp++;
798 subsys_cmd_code = *(uint16_t *)temp;
799 temp += 2;
800 data_type = APPS_DATA;
801 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530802 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700803 if (subsys_id != RESET_ID)
804 data_type = MODEM_DATA;
805 }
806
807 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -0800808 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700809 entry = driver->table[i];
810 if (entry.process_id != NO_PROCESS) {
811 if (entry.cmd_code == cmd_code && entry.subsys_id ==
812 subsys_id && entry.cmd_code_lo <=
813 subsys_cmd_code &&
814 entry.cmd_code_hi >= subsys_cmd_code) {
815 diag_send_data(entry, buf, len, data_type);
816 packet_type = 0;
817 } else if (entry.cmd_code == 255
818 && cmd_code == 75) {
819 if (entry.subsys_id ==
820 subsys_id &&
821 entry.cmd_code_lo <=
822 subsys_cmd_code &&
823 entry.cmd_code_hi >=
824 subsys_cmd_code) {
825 diag_send_data(entry, buf, len,
826 data_type);
827 packet_type = 0;
828 }
829 } else if (entry.cmd_code == 255 &&
830 entry.subsys_id == 255) {
831 if (entry.cmd_code_lo <=
832 cmd_code &&
833 entry.
834 cmd_code_hi >= cmd_code) {
835 diag_send_data(entry, buf, len,
836 data_type);
837 packet_type = 0;
838 }
839 }
840 }
841 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700842#if defined(CONFIG_DIAG_OVER_USB)
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700843 /* Check for Apps Only & get event mask request */
Shalabh Jain321c8b52012-02-22 12:37:06 -0800844 if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700845 driver->apps_rsp_buf[0] = 0x81;
846 driver->apps_rsp_buf[1] = 0x0;
847 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
848 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
849 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
850 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
851 ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
852 return 0;
853 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700854 /* Get log ID range & Check for Apps Only */
855 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700856 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
857 driver->apps_rsp_buf[0] = 0x73;
858 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
859 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
860 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
861 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
862 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
863 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
864 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
865 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
866 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
867 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
868 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
869 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
870 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
871 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
872 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
873 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
874 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
875 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
876 ENCODE_RSP_AND_SEND(75);
877 return 0;
878 }
879 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700880 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700881 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
882 driver->apps_rsp_buf[0] = 0x7d;
883 driver->apps_rsp_buf[1] = 0x1;
884 driver->apps_rsp_buf[2] = 0x1;
885 driver->apps_rsp_buf[3] = 0x0;
886 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT;
887 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
888 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
889 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
890 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
891 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
892 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
893 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
894 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
895 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
896 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
897 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
898 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
899 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
900 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
901 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
902 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
903 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
904 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
905 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
906 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
907 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
908 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
909 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
910 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
911 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
912 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
913 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
914 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
915 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
916 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
917 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
918 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
919 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
920 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
921 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
922 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
923 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
924 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800925 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
926 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
927 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
928 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
929 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
930 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
931 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
932 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
933 ENCODE_RSP_AND_SEND(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700934 return 0;
935 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700936 /* Check for Apps Only Respond to Get Subsys Build mask */
937 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700938 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
939 ssid_first = *(uint16_t *)(buf + 2);
940 ssid_last = *(uint16_t *)(buf + 4);
941 ssid_range = 4 * (ssid_last - ssid_first + 1);
942 /* frame response */
943 driver->apps_rsp_buf[0] = 0x7d;
944 driver->apps_rsp_buf[1] = 0x2;
945 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
946 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
947 driver->apps_rsp_buf[6] = 0x1;
948 driver->apps_rsp_buf[7] = 0x0;
949 ptr = driver->apps_rsp_buf + 8;
950 /* bld time masks */
951 switch (ssid_first) {
952 case MSG_SSID_0:
953 for (i = 0; i < ssid_range; i += 4)
954 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
955 break;
956 case MSG_SSID_1:
957 for (i = 0; i < ssid_range; i += 4)
958 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
959 break;
960 case MSG_SSID_2:
961 for (i = 0; i < ssid_range; i += 4)
962 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
963 break;
964 case MSG_SSID_3:
965 for (i = 0; i < ssid_range; i += 4)
966 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
967 break;
968 case MSG_SSID_4:
969 for (i = 0; i < ssid_range; i += 4)
970 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
971 break;
972 case MSG_SSID_5:
973 for (i = 0; i < ssid_range; i += 4)
974 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
975 break;
976 case MSG_SSID_6:
977 for (i = 0; i < ssid_range; i += 4)
978 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
979 break;
980 case MSG_SSID_7:
981 for (i = 0; i < ssid_range; i += 4)
982 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
983 break;
984 case MSG_SSID_8:
985 for (i = 0; i < ssid_range; i += 4)
986 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
987 break;
988 case MSG_SSID_9:
989 for (i = 0; i < ssid_range; i += 4)
990 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
991 break;
992 case MSG_SSID_10:
993 for (i = 0; i < ssid_range; i += 4)
994 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
995 break;
996 case MSG_SSID_11:
997 for (i = 0; i < ssid_range; i += 4)
998 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
999 break;
1000 case MSG_SSID_12:
1001 for (i = 0; i < ssid_range; i += 4)
1002 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
1003 break;
1004 case MSG_SSID_13:
1005 for (i = 0; i < ssid_range; i += 4)
1006 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
1007 break;
1008 case MSG_SSID_14:
1009 for (i = 0; i < ssid_range; i += 4)
1010 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
1011 break;
1012 case MSG_SSID_15:
1013 for (i = 0; i < ssid_range; i += 4)
1014 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
1015 break;
1016 case MSG_SSID_16:
1017 for (i = 0; i < ssid_range; i += 4)
1018 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
1019 break;
1020 case MSG_SSID_17:
1021 for (i = 0; i < ssid_range; i += 4)
1022 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
1023 break;
1024 case MSG_SSID_18:
1025 for (i = 0; i < ssid_range; i += 4)
1026 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
1027 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001028 case MSG_SSID_19:
1029 for (i = 0; i < ssid_range; i += 4)
1030 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
1031 break;
1032 case MSG_SSID_20:
1033 for (i = 0; i < ssid_range; i += 4)
1034 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
1035 break;
1036 case MSG_SSID_21:
1037 for (i = 0; i < ssid_range; i += 4)
1038 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
1039 break;
1040 case MSG_SSID_22:
1041 for (i = 0; i < ssid_range; i += 4)
1042 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
1043 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001044 }
1045 ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
1046 return 0;
1047 }
1048 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +05301049 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001050 /* send response back */
1051 driver->apps_rsp_buf[0] = *buf;
1052 ENCODE_RSP_AND_SEND(0);
1053 msleep(5000);
1054 /* call download API */
1055 msm_set_restart_mode(RESTART_DLOAD);
1056 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
1057 kernel_restart(NULL);
1058 /* Not required, represents that command isnt sent to modem */
1059 return 0;
1060 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001061 /* Check for polling for Apps only DIAG */
1062 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
1063 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001064 /* If no one has registered for polling */
1065 if (!(driver->polling_reg_flag)) {
Dixon Petersonb46bb992012-01-12 19:16:56 -08001066 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001067 for (i = 0; i < 3; i++)
1068 driver->apps_rsp_buf[i] = *(buf+i);
1069 for (i = 0; i < 13; i++)
1070 driver->apps_rsp_buf[i+3] = 0;
1071
1072 ENCODE_RSP_AND_SEND(15);
1073 return 0;
1074 }
Dixon Petersonb46bb992012-01-12 19:16:56 -08001075 }
1076 /* Check for ID for NO MODEM present */
Shalabh Jain3d29fc32012-02-09 17:15:59 -08001077 else if (!(driver->polling_reg_flag)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001078 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -08001079 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001080 for (i = 0; i < 55; i++)
1081 driver->apps_rsp_buf[i] = 0;
1082
1083 ENCODE_RSP_AND_SEND(54);
1084 return 0;
1085 }
1086 /* respond to 0x7c command */
1087 else if (*buf == 0x7c) {
1088 driver->apps_rsp_buf[0] = 0x7c;
1089 for (i = 1; i < 8; i++)
1090 driver->apps_rsp_buf[i] = 0;
1091 /* Tools ID for APQ 8060 */
1092 *(int *)(driver->apps_rsp_buf + 8) =
1093 chk_config_get_id();
1094 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
1095 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
1096 ENCODE_RSP_AND_SEND(13);
1097 return 0;
1098 }
1099 }
1100#endif
1101 return packet_type;
1102}
1103
1104#ifdef CONFIG_DIAG_OVER_USB
1105void diag_send_error_rsp(int index)
1106{
1107 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +05301108
1109 if (index > 490) {
1110 pr_err("diag: error response too huge, aborting\n");
1111 return;
1112 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001113 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
1114 for (i = 0; i < index; i++)
1115 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
1116 ENCODE_RSP_AND_SEND(index - 3);
1117}
1118#else
1119static inline void diag_send_error_rsp(int index) {}
1120#endif
1121
1122void diag_process_hdlc(void *data, unsigned len)
1123{
1124 struct diag_hdlc_decode_type hdlc;
1125 int ret, type = 0;
1126 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
1127 hdlc.dest_ptr = driver->hdlc_buf;
1128 hdlc.dest_size = USB_MAX_OUT_BUF;
1129 hdlc.src_ptr = data;
1130 hdlc.src_size = len;
1131 hdlc.src_idx = 0;
1132 hdlc.dest_idx = 0;
1133 hdlc.escaping = 0;
1134
1135 ret = diag_hdlc_decode(&hdlc);
1136
1137 if (ret)
1138 type = diag_process_apps_pkt(driver->hdlc_buf,
1139 hdlc.dest_idx - 3);
1140 else if (driver->debug_flag) {
1141 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
1142 " errors or partial packet received, packet"
1143 " length = %d\n", len);
1144 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
1145 DUMP_PREFIX_ADDRESS, data, len, 1);
1146 driver->debug_flag = 0;
1147 }
1148 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001149 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001150 diag_send_error_rsp(hdlc.dest_idx);
1151 type = 0;
1152 }
1153 /* implies this packet is NOT meant for apps */
1154 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -07001155 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001156 diag_send_error_rsp(hdlc.dest_idx);
1157 } else { /* APQ 8060, Let Q6 respond */
1158 if (driver->chqdsp)
1159 smd_write(driver->chqdsp, driver->hdlc_buf,
1160 hdlc.dest_idx - 3);
1161 }
1162 type = 0;
1163 }
1164
1165#ifdef DIAG_DEBUG
1166 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1167 for (i = 0; i < hdlc.dest_idx; i++)
1168 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1169 driver->hdlc_buf)+i));
1170#endif /* DIAG DEBUG */
1171 /* ignore 2 bytes for CRC, one for 7E and send */
1172 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1173 APPEND_DEBUG('g');
1174 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1175 APPEND_DEBUG('h');
1176#ifdef DIAG_DEBUG
1177 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1178 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1179 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1180#endif /* DIAG DEBUG */
1181 }
1182}
1183
1184#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001185/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1186#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001187#define N_LEGACY_READ 1
1188
1189int diagfwd_connect(void)
1190{
1191 int err;
1192
1193 printk(KERN_DEBUG "diag: USB connected\n");
1194 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1195 N_LEGACY_READ);
1196 if (err)
1197 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1198
1199 driver->usb_connected = 1;
1200 driver->in_busy_1 = 0;
1201 driver->in_busy_2 = 0;
1202 driver->in_busy_qdsp_1 = 0;
1203 driver->in_busy_qdsp_2 = 0;
1204 driver->in_busy_wcnss = 0;
1205
1206 /* Poll SMD channels to check for data*/
1207 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1208 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1209 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001210 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001211 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
1212 diag_smd_qdsp_cntl_notify(NULL, SMD_EVENT_DATA);
1213 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001214 /* Poll USB channel to check for data*/
1215 queue_work(driver->diag_wq, &(driver->diag_read_work));
1216#ifdef CONFIG_DIAG_SDIO_PIPE
1217 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1218 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1219 diagfwd_connect_sdio();
1220 else
1221 printk(KERN_INFO "diag: No USB MDM ch");
1222 }
1223#endif
1224 return 0;
1225}
1226
1227int diagfwd_disconnect(void)
1228{
1229 printk(KERN_DEBUG "diag: USB disconnected\n");
1230 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001231 driver->debug_flag = 1;
1232 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001233 if (driver->logging_mode == USB_MODE) {
1234 driver->in_busy_1 = 1;
1235 driver->in_busy_2 = 1;
1236 driver->in_busy_qdsp_1 = 1;
1237 driver->in_busy_qdsp_2 = 1;
1238 driver->in_busy_wcnss = 1;
1239 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001240#ifdef CONFIG_DIAG_SDIO_PIPE
1241 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1242 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1243 diagfwd_disconnect_sdio();
1244#endif
1245 /* TBD - notify and flow control SMD */
1246 return 0;
1247}
1248
1249int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1250{
1251 unsigned char *buf = diag_write_ptr->buf;
1252 /*Determine if the write complete is for data from modem/apps/q6 */
1253 /* Need a context variable here instead */
1254 if (buf == (void *)driver->buf_in_1) {
1255 driver->in_busy_1 = 0;
1256 APPEND_DEBUG('o');
1257 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1258 } else if (buf == (void *)driver->buf_in_2) {
1259 driver->in_busy_2 = 0;
1260 APPEND_DEBUG('O');
1261 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1262 } else if (buf == (void *)driver->buf_in_qdsp_1) {
1263 driver->in_busy_qdsp_1 = 0;
1264 APPEND_DEBUG('p');
1265 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1266 } else if (buf == (void *)driver->buf_in_qdsp_2) {
1267 driver->in_busy_qdsp_2 = 0;
1268 APPEND_DEBUG('P');
1269 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1270 } else if (buf == (void *)driver->buf_in_wcnss) {
1271 driver->in_busy_wcnss = 0;
1272 APPEND_DEBUG('R');
1273 queue_work(driver->diag_wq,
1274 &(driver->diag_read_smd_wcnss_work));
1275 }
1276#ifdef CONFIG_DIAG_SDIO_PIPE
1277 else if (buf == (void *)driver->buf_in_sdio)
1278 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001279 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001280 diagfwd_write_complete_sdio();
1281 else
1282 pr_err("diag: Incorrect buffer pointer while WRITE");
1283#endif
1284 else {
1285 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1286 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1287 POOL_TYPE_WRITE_STRUCT);
1288 APPEND_DEBUG('q');
1289 }
1290 return 0;
1291}
1292
1293int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1294{
1295 int status = diag_read_ptr->status;
1296 unsigned char *buf = diag_read_ptr->buf;
1297
1298 /* Determine if the read complete is for data on legacy/mdm ch */
1299 if (buf == (void *)driver->usb_buf_out) {
1300 driver->read_len_legacy = diag_read_ptr->actual;
1301 APPEND_DEBUG('s');
1302#ifdef DIAG_DEBUG
1303 printk(KERN_INFO "read data from USB, pkt length %d",
1304 diag_read_ptr->actual);
1305 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1306 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1307 diag_read_ptr->actual, 1);
1308#endif /* DIAG DEBUG */
1309 if (driver->logging_mode == USB_MODE) {
1310 if (status != -ECONNRESET && status != -ESHUTDOWN)
1311 queue_work(driver->diag_wq,
1312 &(driver->diag_proc_hdlc_work));
1313 else
1314 queue_work(driver->diag_wq,
1315 &(driver->diag_read_work));
1316 }
1317 }
1318#ifdef CONFIG_DIAG_SDIO_PIPE
1319 else if (buf == (void *)driver->usb_buf_mdm_out) {
1320 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001321 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001322 driver->read_len_mdm = diag_read_ptr->actual;
1323 diagfwd_read_complete_sdio();
1324 } else
1325 pr_err("diag: Incorrect buffer pointer while READ");
1326 }
1327#endif
1328 else
1329 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1330
1331 return 0;
1332}
1333
1334void diag_read_work_fn(struct work_struct *work)
1335{
1336 APPEND_DEBUG('d');
1337 driver->usb_read_ptr->buf = driver->usb_buf_out;
1338 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1339 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1340 APPEND_DEBUG('e');
1341}
1342
1343void diag_process_hdlc_fn(struct work_struct *work)
1344{
1345 APPEND_DEBUG('D');
1346 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1347 diag_read_work_fn(work);
1348 APPEND_DEBUG('E');
1349}
1350
1351void diag_usb_legacy_notifier(void *priv, unsigned event,
1352 struct diag_request *d_req)
1353{
1354 switch (event) {
1355 case USB_DIAG_CONNECT:
1356 diagfwd_connect();
1357 break;
1358 case USB_DIAG_DISCONNECT:
1359 diagfwd_disconnect();
1360 break;
1361 case USB_DIAG_READ_DONE:
1362 diagfwd_read_complete(d_req);
1363 break;
1364 case USB_DIAG_WRITE_DONE:
1365 diagfwd_write_complete(d_req);
1366 break;
1367 default:
1368 printk(KERN_ERR "Unknown event from USB diag\n");
1369 break;
1370 }
1371}
1372
1373#endif /* DIAG OVER USB */
1374
1375static void diag_smd_notify(void *ctxt, unsigned event)
1376{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001377 if (event == SMD_EVENT_CLOSE) {
1378 pr_info("diag: clean modem registration\n");
1379 diag_clear_reg(MODEM_PROC);
Shalabh Jaineefee052011-11-08 23:46:03 -08001380 driver->ch = 0;
1381 return;
1382 } else if (event == SMD_EVENT_OPEN) {
1383 driver->ch = ch_temp;
1384 }
1385 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001386}
1387
1388#if defined(CONFIG_MSM_N_WAY_SMD)
1389static void diag_smd_qdsp_notify(void *ctxt, unsigned event)
1390{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001391 if (event == SMD_EVENT_CLOSE) {
1392 pr_info("diag: clean lpass registration\n");
1393 diag_clear_reg(QDSP_PROC);
1394 driver->chqdsp = 0;
1395 return;
1396 } else if (event == SMD_EVENT_OPEN) {
1397 driver->chqdsp = chqdsp_temp;
1398 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001399 queue_work(driver->diag_wq, &(driver->diag_read_smd_qdsp_work));
1400}
1401#endif
1402
1403static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1404{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001405 if (event == SMD_EVENT_CLOSE) {
1406 pr_info("diag: clean wcnss registration\n");
1407 diag_clear_reg(WCNSS_PROC);
1408 driver->ch_wcnss = 0;
1409 return;
1410 } else if (event == SMD_EVENT_OPEN) {
1411 driver->ch_wcnss = ch_wcnss_temp;
1412 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001413 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1414}
1415
1416static int diag_smd_probe(struct platform_device *pdev)
1417{
1418 int r = 0;
1419
Shalabh Jaineefee052011-11-08 23:46:03 -08001420 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001421 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001422 ch_temp = driver->ch;
1423 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001424#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001425 if (pdev->id == SMD_APPS_QDSP) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001426 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP
1427 , &driver->chqdsp, driver, diag_smd_qdsp_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001428 chqdsp_temp = driver->chqdsp;
1429 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001430#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001431 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001432 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1433 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001434 ch_wcnss_temp = driver->ch_wcnss;
1435 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001436 pm_runtime_set_active(&pdev->dev);
1437 pm_runtime_enable(&pdev->dev);
1438 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1439
1440 return 0;
1441}
1442
1443static int diagfwd_runtime_suspend(struct device *dev)
1444{
1445 dev_dbg(dev, "pm_runtime: suspending...\n");
1446 return 0;
1447}
1448
1449static int diagfwd_runtime_resume(struct device *dev)
1450{
1451 dev_dbg(dev, "pm_runtime: resuming...\n");
1452 return 0;
1453}
1454
1455static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1456 .runtime_suspend = diagfwd_runtime_suspend,
1457 .runtime_resume = diagfwd_runtime_resume,
1458};
1459
1460static struct platform_driver msm_smd_ch1_driver = {
1461
1462 .probe = diag_smd_probe,
1463 .driver = {
1464 .name = "DIAG",
1465 .owner = THIS_MODULE,
1466 .pm = &diagfwd_dev_pm_ops,
1467 },
1468};
1469
1470static struct platform_driver diag_smd_lite_driver = {
1471
1472 .probe = diag_smd_probe,
1473 .driver = {
1474 .name = "APPS_RIVA_DATA",
1475 .owner = THIS_MODULE,
1476 .pm = &diagfwd_dev_pm_ops,
1477 },
1478};
1479
1480void diagfwd_init(void)
1481{
1482 diag_debug_buf_idx = 0;
1483 driver->read_len_legacy = 0;
Shalabh Jain321c8b52012-02-22 12:37:06 -08001484
1485 if (driver->event_mask == NULL) {
1486 driver->event_mask = kzalloc(sizeof(
1487 struct diag_ctrl_event_mask), GFP_KERNEL);
1488 if (driver->event_mask == NULL)
1489 goto err;
1490 }
1491 if (driver->msg_mask == NULL) {
1492 driver->msg_mask = kzalloc(sizeof(
1493 struct diag_ctrl_msg_mask), GFP_KERNEL);
1494 if (driver->msg_mask == NULL)
1495 goto err;
1496 }
1497 if (driver->log_mask == NULL) {
1498 driver->log_mask = kzalloc(sizeof(
1499 struct diag_ctrl_log_mask), GFP_KERNEL);
1500 if (driver->log_mask == NULL)
1501 goto err;
1502 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001503 if (driver->buf_in_1 == NULL) {
1504 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1505 if (driver->buf_in_1 == NULL)
1506 goto err;
1507 }
1508 if (driver->buf_in_2 == NULL) {
1509 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1510 if (driver->buf_in_2 == NULL)
1511 goto err;
1512 }
1513 if (driver->buf_in_qdsp_1 == NULL) {
1514 driver->buf_in_qdsp_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1515 if (driver->buf_in_qdsp_1 == NULL)
1516 goto err;
1517 }
1518 if (driver->buf_in_qdsp_2 == NULL) {
1519 driver->buf_in_qdsp_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1520 if (driver->buf_in_qdsp_2 == NULL)
1521 goto err;
1522 }
1523 if (driver->buf_in_wcnss == NULL) {
1524 driver->buf_in_wcnss = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1525 if (driver->buf_in_wcnss == NULL)
1526 goto err;
1527 }
Shalabh Jain321c8b52012-02-22 12:37:06 -08001528 if (driver->buf_msg_mask_update == NULL) {
1529 driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
1530 GFP_KERNEL);
1531 if (driver->buf_msg_mask_update == NULL)
1532 goto err;
1533 }
1534 if (driver->buf_log_mask_update == NULL) {
1535 driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
1536 GFP_KERNEL);
1537 if (driver->buf_log_mask_update == NULL)
1538 goto err;
1539 }
1540 if (driver->buf_event_mask_update == NULL) {
1541 driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
1542 GFP_KERNEL);
1543 if (driver->buf_event_mask_update == NULL)
1544 goto err;
1545 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001546 if (driver->usb_buf_out == NULL &&
1547 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1548 GFP_KERNEL)) == NULL)
1549 goto err;
1550 if (driver->hdlc_buf == NULL
1551 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1552 goto err;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001553 if (driver->user_space_data == NULL)
1554 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1555 if (driver->user_space_data == NULL)
1556 goto err;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001557 if (driver->msg_masks == NULL
1558 && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
1559 GFP_KERNEL)) == NULL)
1560 goto err;
1561 if (driver->log_masks == NULL &&
1562 (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
1563 goto err;
1564 driver->log_masks_length = 8*MAX_EQUIP_ID;
1565 if (driver->event_masks == NULL &&
1566 (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
1567 GFP_KERNEL)) == NULL)
1568 goto err;
1569 if (driver->client_map == NULL &&
1570 (driver->client_map = kzalloc
1571 ((driver->num_clients) * sizeof(struct diag_client_map),
1572 GFP_KERNEL)) == NULL)
1573 goto err;
1574 if (driver->buf_tbl == NULL)
1575 driver->buf_tbl = kzalloc(buf_tbl_size *
1576 sizeof(struct diag_write_device), GFP_KERNEL);
1577 if (driver->buf_tbl == NULL)
1578 goto err;
1579 if (driver->data_ready == NULL &&
1580 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1581 , GFP_KERNEL)) == NULL)
1582 goto err;
1583 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001584 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001585 sizeof(struct diag_master_table),
1586 GFP_KERNEL)) == NULL)
1587 goto err;
1588 if (driver->write_ptr_1 == NULL) {
1589 driver->write_ptr_1 = kzalloc(
1590 sizeof(struct diag_request), GFP_KERNEL);
1591 if (driver->write_ptr_1 == NULL)
1592 goto err;
1593 }
1594 if (driver->write_ptr_2 == NULL) {
1595 driver->write_ptr_2 = kzalloc(
1596 sizeof(struct diag_request), GFP_KERNEL);
1597 if (driver->write_ptr_2 == NULL)
1598 goto err;
1599 }
1600 if (driver->write_ptr_qdsp_1 == NULL) {
1601 driver->write_ptr_qdsp_1 = kzalloc(
1602 sizeof(struct diag_request), GFP_KERNEL);
1603 if (driver->write_ptr_qdsp_1 == NULL)
1604 goto err;
1605 }
1606 if (driver->write_ptr_qdsp_2 == NULL) {
1607 driver->write_ptr_qdsp_2 = kzalloc(
1608 sizeof(struct diag_request), GFP_KERNEL);
1609 if (driver->write_ptr_qdsp_2 == NULL)
1610 goto err;
1611 }
1612 if (driver->write_ptr_wcnss == NULL) {
1613 driver->write_ptr_wcnss = kzalloc(
1614 sizeof(struct diag_request), GFP_KERNEL);
1615 if (driver->write_ptr_wcnss == NULL)
1616 goto err;
1617 }
1618 if (driver->usb_read_ptr == NULL) {
1619 driver->usb_read_ptr = kzalloc(
1620 sizeof(struct diag_request), GFP_KERNEL);
1621 if (driver->usb_read_ptr == NULL)
1622 goto err;
1623 }
1624 if (driver->pkt_buf == NULL &&
1625 (driver->pkt_buf = kzalloc(PKT_SIZE,
1626 GFP_KERNEL)) == NULL)
1627 goto err;
1628 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001629 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001630 if (driver->apps_rsp_buf == NULL)
1631 goto err;
1632 }
1633 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1634#ifdef CONFIG_DIAG_OVER_USB
1635 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1636 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001637 INIT_WORK(&(driver->diag_msg_mask_update_work),
1638 diag_msg_mask_update_fn);
1639 INIT_WORK(&(driver->diag_log_mask_update_work),
1640 diag_log_mask_update_fn);
1641 INIT_WORK(&(driver->diag_modem_mask_update_work),
1642 diag_modem_mask_update_fn);
1643 INIT_WORK(&(driver->diag_qdsp_mask_update_work),
1644 diag_qdsp_mask_update_fn);
1645 INIT_WORK(&(driver->diag_wcnss_mask_update_work),
1646 diag_wcnss_mask_update_fn);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001647 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
1648 diag_usb_legacy_notifier);
1649 if (IS_ERR(driver->legacy_ch)) {
1650 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
1651 goto err;
1652 }
1653#endif
1654 platform_driver_register(&msm_smd_ch1_driver);
1655 platform_driver_register(&diag_smd_lite_driver);
1656
1657 return;
1658err:
1659 pr_err("diag: Could not initialize diag buffers");
Shalabh Jain321c8b52012-02-22 12:37:06 -08001660 kfree(driver->event_mask);
1661 kfree(driver->log_mask);
1662 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001663 kfree(driver->buf_in_1);
1664 kfree(driver->buf_in_2);
1665 kfree(driver->buf_in_qdsp_1);
1666 kfree(driver->buf_in_qdsp_2);
1667 kfree(driver->buf_in_wcnss);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001668 kfree(driver->buf_msg_mask_update);
1669 kfree(driver->buf_log_mask_update);
1670 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001671 kfree(driver->usb_buf_out);
1672 kfree(driver->hdlc_buf);
1673 kfree(driver->msg_masks);
1674 kfree(driver->log_masks);
1675 kfree(driver->event_masks);
1676 kfree(driver->client_map);
1677 kfree(driver->buf_tbl);
1678 kfree(driver->data_ready);
1679 kfree(driver->table);
1680 kfree(driver->pkt_buf);
1681 kfree(driver->write_ptr_1);
1682 kfree(driver->write_ptr_2);
1683 kfree(driver->write_ptr_qdsp_1);
1684 kfree(driver->write_ptr_qdsp_2);
1685 kfree(driver->write_ptr_wcnss);
1686 kfree(driver->usb_read_ptr);
1687 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001688 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001689 if (driver->diag_wq)
1690 destroy_workqueue(driver->diag_wq);
1691}
1692
1693void diagfwd_exit(void)
1694{
1695 smd_close(driver->ch);
1696 smd_close(driver->chqdsp);
1697 smd_close(driver->ch_wcnss);
1698 driver->ch = 0; /* SMD can make this NULL */
1699 driver->chqdsp = 0;
1700 driver->ch_wcnss = 0;
1701#ifdef CONFIG_DIAG_OVER_USB
1702 if (driver->usb_connected)
1703 usb_diag_free_req(driver->legacy_ch);
1704 usb_diag_close(driver->legacy_ch);
1705#endif
1706 platform_driver_unregister(&msm_smd_ch1_driver);
1707 platform_driver_unregister(&diag_smd_lite_driver);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001708 kfree(driver->event_mask);
1709 kfree(driver->log_mask);
1710 kfree(driver->msg_mask);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001711 kfree(driver->buf_in_1);
1712 kfree(driver->buf_in_2);
1713 kfree(driver->buf_in_qdsp_1);
1714 kfree(driver->buf_in_qdsp_2);
1715 kfree(driver->buf_in_wcnss);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001716 kfree(driver->buf_msg_mask_update);
1717 kfree(driver->buf_log_mask_update);
1718 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001719 kfree(driver->usb_buf_out);
1720 kfree(driver->hdlc_buf);
1721 kfree(driver->msg_masks);
1722 kfree(driver->log_masks);
1723 kfree(driver->event_masks);
1724 kfree(driver->client_map);
1725 kfree(driver->buf_tbl);
1726 kfree(driver->data_ready);
1727 kfree(driver->table);
1728 kfree(driver->pkt_buf);
1729 kfree(driver->write_ptr_1);
1730 kfree(driver->write_ptr_2);
1731 kfree(driver->write_ptr_qdsp_1);
1732 kfree(driver->write_ptr_qdsp_2);
1733 kfree(driver->write_ptr_wcnss);
1734 kfree(driver->usb_read_ptr);
1735 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001736 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001737 destroy_workqueue(driver->diag_wq);
1738}