blob: 18380761818c91575917c234615be216716c12bf [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>
Dixon Peterson6beff2d2012-09-13 18:51:47 -070019#include <linux/ratelimit.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070020#include <linux/workqueue.h>
21#include <linux/pm_runtime.h>
22#include <linux/diagchar.h>
23#include <linux/delay.h>
24#include <linux/reboot.h>
Dixon Petersonb4618a42012-02-29 18:56:31 -080025#include <linux/of.h>
Dixon Petersoncc0bea772012-04-11 20:45:37 -070026#include <linux/kmemleak.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070027#ifdef CONFIG_DIAG_OVER_USB
28#include <mach/usbdiag.h>
29#endif
30#include <mach/msm_smd.h>
31#include <mach/socinfo.h>
32#include <mach/restart.h>
33#include "diagmem.h"
34#include "diagchar.h"
35#include "diagfwd.h"
36#include "diagfwd_cntl.h"
37#include "diagchar_hdlc.h"
38#ifdef CONFIG_DIAG_SDIO_PIPE
39#include "diagfwd_sdio.h"
40#endif
Shalabh Jain1c99e4c2012-03-26 18:47:59 -070041#include "diag_dci.h"
Dixon Petersond6a20a92012-09-27 15:58:50 -070042#include "diag_masks.h"
Shalabh Jain1c99e4c2012-03-26 18:47:59 -070043
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070044#define MODE_CMD 41
45#define RESET_ID 2
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070046
47int diag_debug_buf_idx;
48unsigned char diag_debug_buf[1024];
49static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
50struct diag_master_table entry;
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -070051smd_channel_t *ch_temp = NULL, *chlpass_temp = NULL, *ch_wcnss_temp = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070052struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
53struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
Shalabh Jain6a2ca7c2012-04-10 14:35:15 -070054
Dixon Petersond6a20a92012-09-27 15:58:50 -070055void encode_rsp_and_send(int buf_length)
56{
57 send.state = DIAG_STATE_START;
58 send.pkt = driver->apps_rsp_buf;
59 send.last = (void *)(driver->apps_rsp_buf + buf_length);
60 send.terminate = 1;
61 if (!driver->in_busy_1) {
62 enc.dest = driver->buf_in_1;
63 enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);
64 diag_hdlc_encode(&send, &enc);
65 driver->write_ptr_1->buf = driver->buf_in_1;
66 driver->write_ptr_1->length = (int)(enc.dest -
67 (void *)(driver->buf_in_1));
68 driver->in_busy_1 = 1;
69 diag_device_write(driver->buf_in_1, MODEM_DATA,
70 driver->write_ptr_1);
71 memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE);
72 }
73}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070074
Dixon Petersonb4618a42012-02-29 18:56:31 -080075/* Determine if this device uses a device tree */
76#ifdef CONFIG_OF
77static int has_device_tree(void)
78{
79 struct device_node *node;
80
81 node = of_find_node_by_path("/");
82 if (node) {
83 of_node_put(node);
84 return 1;
85 }
86 return 0;
87}
88#else
89static int has_device_tree(void)
90{
91 return 0;
92}
93#endif
94
Shalabh Jainfb8e3c12011-10-19 17:29:42 -070095int chk_config_get_id(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070096{
Shalabh Jain482bf122011-12-06 03:54:47 -080097 /* For all Fusion targets, Modem will always be present */
98 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
99 return 0;
100
Dixon Petersonb4618a42012-02-29 18:56:31 -0800101 if (driver->use_device_tree) {
Abhimanyu Kapur90ced6e2012-06-26 17:41:25 -0700102 if (machine_is_msm8974())
Dixon Petersonb4618a42012-02-29 18:56:31 -0800103 return MSM8974_TOOLS_ID;
104 else
105 return 0;
106 } else {
107 switch (socinfo_get_msm_cpu()) {
108 case MSM_CPU_8X60:
109 return APQ8060_TOOLS_ID;
110 case MSM_CPU_8960:
Stepan Moskovchenko9c749262012-07-09 19:30:44 -0700111 case MSM_CPU_8960AB:
Dixon Petersonb4618a42012-02-29 18:56:31 -0800112 return AO8960_TOOLS_ID;
113 case MSM_CPU_8064:
114 return APQ8064_TOOLS_ID;
115 case MSM_CPU_8930:
Stepan Moskovchenko0df9bb22012-07-06 18:19:15 -0700116 case MSM_CPU_8930AA:
Dixon Petersonb4618a42012-02-29 18:56:31 -0800117 return MSM8930_TOOLS_ID;
Abhimanyu Kapur90ced6e2012-06-26 17:41:25 -0700118 case MSM_CPU_8974:
Dixon Petersonb4618a42012-02-29 18:56:31 -0800119 return MSM8974_TOOLS_ID;
120 case MSM_CPU_8625:
121 return MSM8625_TOOLS_ID;
122 default:
123 return 0;
124 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700125 }
126}
127
128/*
Shalabh Jain321c8b52012-02-22 12:37:06 -0800129 * This will return TRUE for targets which support apps only mode and hence SSR.
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700130 * This applies to 8960 and newer targets.
131 */
132int chk_apps_only(void)
133{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800134 if (driver->use_device_tree)
135 return 1;
136
137 switch (socinfo_get_msm_cpu()) {
138 case MSM_CPU_8960:
Stepan Moskovchenko9c749262012-07-09 19:30:44 -0700139 case MSM_CPU_8960AB:
Dixon Petersonb4618a42012-02-29 18:56:31 -0800140 case MSM_CPU_8064:
141 case MSM_CPU_8930:
Stepan Moskovchenko0df9bb22012-07-06 18:19:15 -0700142 case MSM_CPU_8930AA:
Dixon Petersonb4618a42012-02-29 18:56:31 -0800143 case MSM_CPU_8627:
144 case MSM_CPU_9615:
Abhimanyu Kapur90ced6e2012-06-26 17:41:25 -0700145 case MSM_CPU_8974:
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700146 return 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700147 default:
148 return 0;
149 }
150}
151
Shalabh Jain10f5f432012-01-11 11:45:44 +0530152/*
153 * This will return TRUE for targets which support apps as master.
154 * Thus, SW DLOAD and Mode Reset are supported on apps processor.
155 * This applies to 8960 and newer targets.
156 */
157int chk_apps_master(void)
158{
Dixon Petersonb4618a42012-02-29 18:56:31 -0800159 if (driver->use_device_tree)
160 return 1;
Stepan Moskovchenko0df9bb22012-07-06 18:19:15 -0700161 else if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
Stepan Moskovchenko9c749262012-07-09 19:30:44 -0700162 cpu_is_msm9615() || cpu_is_apq8064() || cpu_is_msm8627() ||
163 cpu_is_msm8960ab())
Dixon Petersonb4618a42012-02-29 18:56:31 -0800164 return 1;
165 else
166 return 0;
167}
168
Dixon Peterson29aebee2012-04-06 12:44:08 -0700169int chk_polling_response(void)
Dixon Petersonb4618a42012-02-29 18:56:31 -0800170{
171 if (!(driver->polling_reg_flag) && chk_apps_master())
172 /*
173 * If the apps processor is master and no other processor
174 * has registered to respond for polling
175 */
176 return 1;
177 else if (!(driver->ch) && !(chk_apps_master()))
178 /*
179 * If the apps processor is not the master and the modem
180 * is not up
181 */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530182 return 1;
183 else
184 return 0;
185}
186
Dixon Peterson743a11e2012-07-30 17:42:20 -0700187/*
188 * This function should be called if you feel that the logging process may
189 * need to be woken up. For instance, if the logging mode is MEMORY_DEVICE MODE
190 * and while trying to read data from a SMD data channel there are no buffers
191 * available to read the data into, then this function should be called to
192 * determine if the logging process needs to be woken up.
193 */
194void chk_logging_wakeup(void)
195{
196 int i;
197
198 /* Find the index of the logging process */
199 for (i = 0; i < driver->num_clients; i++)
200 if (driver->client_map[i].pid ==
201 driver->logging_process_id)
202 break;
203
204 if (i < driver->num_clients) {
205 /* At very high logging rates a race condition can
206 * occur where the buffers containing the data from
207 * an smd channel are all in use, but the data_ready
208 * flag is cleared. In this case, the buffers never
209 * have their data read/logged. Detect and remedy this
210 * situation.
211 */
212 if ((driver->data_ready[i] & USER_SPACE_LOG_TYPE) == 0) {
213 driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
214 pr_debug("diag: Force wakeup of logging process\n");
215 wake_up_interruptible(&driver->wait_q);
216 }
217 }
218}
219
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700220void __diag_smd_send_req(void)
221{
222 void *buf = NULL;
223 int *in_busy_ptr = NULL;
224 struct diag_request *write_ptr_modem = NULL;
225
226 if (!driver->in_busy_1) {
227 buf = driver->buf_in_1;
228 write_ptr_modem = driver->write_ptr_1;
229 in_busy_ptr = &(driver->in_busy_1);
230 } else if (!driver->in_busy_2) {
231 buf = driver->buf_in_2;
232 write_ptr_modem = driver->write_ptr_2;
233 in_busy_ptr = &(driver->in_busy_2);
234 }
235
236 if (driver->ch && buf) {
237 int r = smd_read_avail(driver->ch);
238
239 if (r > IN_BUF_SIZE) {
240 if (r < MAX_IN_BUF_SIZE) {
241 pr_err("diag: SMD sending in "
242 "packets upto %d bytes", r);
243 buf = krealloc(buf, r, GFP_KERNEL);
244 } else {
245 pr_err("diag: SMD sending in "
246 "packets more than %d bytes", MAX_IN_BUF_SIZE);
247 return;
248 }
249 }
250 if (r > 0) {
251 if (!buf)
252 pr_info("Out of diagmem for Modem\n");
253 else {
254 APPEND_DEBUG('i');
255 smd_read(driver->ch, buf, r);
256 APPEND_DEBUG('j');
257 write_ptr_modem->length = r;
258 *in_busy_ptr = 1;
259 diag_device_write(buf, MODEM_DATA,
260 write_ptr_modem);
261 }
262 }
Dixon Peterson743a11e2012-07-30 17:42:20 -0700263 } else if (driver->ch && !buf &&
264 (driver->logging_mode == MEMORY_DEVICE_MODE)) {
265 chk_logging_wakeup();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700266 }
267}
268
269int diag_device_write(void *buf, int proc_num, struct diag_request *write_ptr)
270{
271 int i, err = 0;
272
273 if (driver->logging_mode == MEMORY_DEVICE_MODE) {
274 if (proc_num == APPS_DATA) {
275 for (i = 0; i < driver->poolsize_write_struct; i++)
276 if (driver->buf_tbl[i].length == 0) {
277 driver->buf_tbl[i].buf = buf;
278 driver->buf_tbl[i].length =
279 driver->used;
280#ifdef DIAG_DEBUG
281 pr_debug("diag: ENQUEUE buf ptr"
282 " and length is %x , %d\n",
283 (unsigned int)(driver->buf_
284 tbl[i].buf), driver->buf_tbl[i].length);
285#endif
286 break;
287 }
288 }
Dixon Peterson938f8602012-08-17 20:02:57 -0700289
290#ifdef CONFIG_DIAG_BRIDGE_CODE
291 else if (proc_num == HSIC_DATA) {
Dixon Peterson5db2e3c2012-09-06 19:13:14 -0700292 unsigned long flags;
293 int foundIndex = -1;
294
295 spin_lock_irqsave(&driver->hsic_spinlock, flags);
Dixon Peterson938f8602012-08-17 20:02:57 -0700296 for (i = 0; i < driver->poolsize_hsic_write; i++) {
297 if (driver->hsic_buf_tbl[i].length == 0) {
298 driver->hsic_buf_tbl[i].buf = buf;
299 driver->hsic_buf_tbl[i].length =
300 driver->write_len_mdm;
301 driver->num_hsic_buf_tbl_entries++;
Dixon Peterson5db2e3c2012-09-06 19:13:14 -0700302 foundIndex = i;
Dixon Peterson938f8602012-08-17 20:02:57 -0700303 break;
304 }
305 }
Dixon Peterson5db2e3c2012-09-06 19:13:14 -0700306 spin_unlock_irqrestore(&driver->hsic_spinlock, flags);
307 if (foundIndex == -1)
308 err = -1;
309 else
310 pr_debug("diag: ENQUEUE HSIC buf ptr and length is %x , %d\n",
311 (unsigned int)buf,
312 driver->write_len_mdm);
Dixon Peterson938f8602012-08-17 20:02:57 -0700313 }
314#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700315 for (i = 0; i < driver->num_clients; i++)
316 if (driver->client_map[i].pid ==
317 driver->logging_process_id)
318 break;
319 if (i < driver->num_clients) {
Shalabh Jain69890aa2011-10-10 12:59:16 -0700320 driver->data_ready[i] |= USER_SPACE_LOG_TYPE;
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700321 pr_debug("diag: wake up logging process\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700322 wake_up_interruptible(&driver->wait_q);
323 } else
324 return -EINVAL;
325 } else if (driver->logging_mode == NO_LOGGING_MODE) {
326 if (proc_num == MODEM_DATA) {
327 driver->in_busy_1 = 0;
328 driver->in_busy_2 = 0;
329 queue_work(driver->diag_wq, &(driver->
330 diag_read_smd_work));
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700331 } else if (proc_num == LPASS_DATA) {
332 driver->in_busy_lpass_1 = 0;
333 driver->in_busy_lpass_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700334 queue_work(driver->diag_wq, &(driver->
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700335 diag_read_smd_lpass_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336 } else if (proc_num == WCNSS_DATA) {
Ashay Jaiswal29620122012-03-21 12:02:36 +0530337 driver->in_busy_wcnss_1 = 0;
338 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700339 queue_work(driver->diag_wq, &(driver->
340 diag_read_smd_wcnss_work));
341 }
Shalabh Jain482bf122011-12-06 03:54:47 -0800342#ifdef CONFIG_DIAG_SDIO_PIPE
343 else if (proc_num == SDIO_DATA) {
344 driver->in_busy_sdio = 0;
345 queue_work(driver->diag_sdio_wq,
346 &(driver->diag_read_sdio_work));
347 }
348#endif
Shalabh Jainf7228dc2012-05-23 17:32:05 -0700349#ifdef CONFIG_DIAG_BRIDGE_CODE
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700350 else if (proc_num == HSIC_DATA) {
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700351 if (driver->hsic_ch)
Shalabh Jainf7228dc2012-05-23 17:32:05 -0700352 queue_work(driver->diag_bridge_wq,
Dixon Petersonf79b66f2012-04-26 13:21:26 -0700353 &(driver->diag_read_hsic_work));
354 }
355#endif
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700356 err = -1;
357 }
358#ifdef CONFIG_DIAG_OVER_USB
359 else if (driver->logging_mode == USB_MODE) {
360 if (proc_num == APPS_DATA) {
361 driver->write_ptr_svc = (struct diag_request *)
362 (diagmem_alloc(driver, sizeof(struct diag_request),
363 POOL_TYPE_WRITE_STRUCT));
364 if (driver->write_ptr_svc) {
365 driver->write_ptr_svc->length = driver->used;
366 driver->write_ptr_svc->buf = buf;
367 err = usb_diag_write(driver->legacy_ch,
368 driver->write_ptr_svc);
369 } else
370 err = -1;
371 } else if (proc_num == MODEM_DATA) {
372 write_ptr->buf = buf;
373#ifdef DIAG_DEBUG
374 printk(KERN_INFO "writing data to USB,"
375 "pkt length %d\n", write_ptr->length);
376 print_hex_dump(KERN_DEBUG, "Written Packet Data to"
377 " USB: ", 16, 1, DUMP_PREFIX_ADDRESS,
378 buf, write_ptr->length, 1);
379#endif /* DIAG DEBUG */
380 err = usb_diag_write(driver->legacy_ch, write_ptr);
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700381 } else if (proc_num == LPASS_DATA) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700382 write_ptr->buf = buf;
383 err = usb_diag_write(driver->legacy_ch, write_ptr);
384 } else if (proc_num == WCNSS_DATA) {
385 write_ptr->buf = buf;
386 err = usb_diag_write(driver->legacy_ch, write_ptr);
387 }
388#ifdef CONFIG_DIAG_SDIO_PIPE
389 else if (proc_num == SDIO_DATA) {
390 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -0800391 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700392 write_ptr->buf = buf;
393 err = usb_diag_write(driver->mdm_ch, write_ptr);
394 } else
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800395 pr_err("diag: Incorrect sdio data "
396 "while USB write\n");
397 }
398#endif
Shalabh Jainf7228dc2012-05-23 17:32:05 -0700399#ifdef CONFIG_DIAG_BRIDGE_CODE
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800400 else if (proc_num == HSIC_DATA) {
401 if (driver->hsic_device_enabled) {
Dixon Peterson938f8602012-08-17 20:02:57 -0700402 struct diag_request *write_ptr_mdm;
403 write_ptr_mdm = (struct diag_request *)
404 diagmem_alloc(driver,
405 sizeof(struct diag_request),
406 POOL_TYPE_HSIC_WRITE);
407 if (write_ptr_mdm) {
408 write_ptr_mdm->buf = buf;
409 write_ptr_mdm->length =
410 driver->write_len_mdm;
411 err = usb_diag_write(driver->mdm_ch,
412 write_ptr_mdm);
413 /* Return to the pool immediately */
414 if (err) {
415 diagmem_free(driver,
416 write_ptr_mdm,
417 POOL_TYPE_HSIC_WRITE);
Dixon Peterson6beff2d2012-09-13 18:51:47 -0700418 pr_err_ratelimited("diag: HSIC write failure, err: %d\n",
419 err);
Dixon Peterson938f8602012-08-17 20:02:57 -0700420 }
421 } else {
422 pr_err("diag: allocate write fail\n");
423 err = -1;
424 }
425 } else {
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800426 pr_err("diag: Incorrect hsic data "
427 "while USB write\n");
Dixon Peterson938f8602012-08-17 20:02:57 -0700428 err = -1;
429 }
Shalabh Jainf7228dc2012-05-23 17:32:05 -0700430 } else if (proc_num == SMUX_DATA) {
431 write_ptr->buf = buf;
432 pr_debug("diag: writing SMUX data\n");
433 err = usb_diag_write(driver->mdm_ch, write_ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700434 }
435#endif
436 APPEND_DEBUG('d');
437 }
438#endif /* DIAG OVER USB */
439 return err;
440}
441
442void __diag_smd_wcnss_send_req(void)
443{
Ashay Jaiswal29620122012-03-21 12:02:36 +0530444 void *buf = NULL;
445 int *in_busy_wcnss_ptr = NULL;
446 struct diag_request *write_ptr_wcnss = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700447
Ashay Jaiswal29620122012-03-21 12:02:36 +0530448 if (!driver->in_busy_wcnss_1) {
449 buf = driver->buf_in_wcnss_1;
450 write_ptr_wcnss = driver->write_ptr_wcnss_1;
451 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_1);
452 } else if (!driver->in_busy_wcnss_2) {
453 buf = driver->buf_in_wcnss_2;
454 write_ptr_wcnss = driver->write_ptr_wcnss_2;
455 in_busy_wcnss_ptr = &(driver->in_busy_wcnss_2);
456 }
457
458 if (driver->ch_wcnss && buf) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700459 int r = smd_read_avail(driver->ch_wcnss);
460 if (r > IN_BUF_SIZE) {
461 if (r < MAX_IN_BUF_SIZE) {
462 pr_err("diag: wcnss packets > %d bytes", r);
463 buf = krealloc(buf, r, GFP_KERNEL);
464 } else {
465 pr_err("diag: wcnss pkt > %d", MAX_IN_BUF_SIZE);
466 return;
467 }
468 }
469 if (r > 0) {
470 if (!buf) {
471 pr_err("Out of diagmem for wcnss\n");
472 } else {
473 APPEND_DEBUG('i');
474 smd_read(driver->ch_wcnss, buf, r);
475 APPEND_DEBUG('j');
476 write_ptr_wcnss->length = r;
477 *in_busy_wcnss_ptr = 1;
478 diag_device_write(buf, WCNSS_DATA,
479 write_ptr_wcnss);
480 }
481 }
Dixon Peterson743a11e2012-07-30 17:42:20 -0700482 } else if (driver->ch_wcnss && !buf &&
483 (driver->logging_mode == MEMORY_DEVICE_MODE)) {
484 chk_logging_wakeup();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700485 }
486}
487
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700488void __diag_smd_lpass_send_req(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700489{
490 void *buf = NULL;
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700491 int *in_busy_lpass_ptr = NULL;
492 struct diag_request *write_ptr_lpass = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700493
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700494 if (!driver->in_busy_lpass_1) {
495 buf = driver->buf_in_lpass_1;
496 write_ptr_lpass = driver->write_ptr_lpass_1;
497 in_busy_lpass_ptr = &(driver->in_busy_lpass_1);
498 } else if (!driver->in_busy_lpass_2) {
499 buf = driver->buf_in_lpass_2;
500 write_ptr_lpass = driver->write_ptr_lpass_2;
501 in_busy_lpass_ptr = &(driver->in_busy_lpass_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700502 }
503
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700504 if (driver->chlpass && buf) {
505 int r = smd_read_avail(driver->chlpass);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700506
507 if (r > IN_BUF_SIZE) {
508 if (r < MAX_IN_BUF_SIZE) {
509 pr_err("diag: SMD sending in "
510 "packets upto %d bytes", r);
511 buf = krealloc(buf, r, GFP_KERNEL);
512 } else {
513 pr_err("diag: SMD sending in "
514 "packets more than %d bytes", MAX_IN_BUF_SIZE);
515 return;
516 }
517 }
518 if (r > 0) {
519 if (!buf)
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700520 printk(KERN_INFO "Out of diagmem for LPASS\n");
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700521 else {
522 APPEND_DEBUG('i');
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700523 smd_read(driver->chlpass, buf, r);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700524 APPEND_DEBUG('j');
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700525 write_ptr_lpass->length = r;
526 *in_busy_lpass_ptr = 1;
527 diag_device_write(buf, LPASS_DATA,
528 write_ptr_lpass);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700529 }
530 }
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700531 } else if (driver->chlpass && !buf &&
Dixon Peterson743a11e2012-07-30 17:42:20 -0700532 (driver->logging_mode == MEMORY_DEVICE_MODE)) {
533 chk_logging_wakeup();
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700534 }
535}
536
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700537static void diag_update_pkt_buffer(unsigned char *buf)
538{
539 unsigned char *ptr = driver->pkt_buf;
540 unsigned char *temp = buf;
541
542 mutex_lock(&driver->diagchar_mutex);
543 if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
544 memcpy(ptr, temp , driver->pkt_length);
545 else
546 printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
547 mutex_unlock(&driver->diagchar_mutex);
548}
549
550void diag_update_userspace_clients(unsigned int type)
551{
552 int i;
553
554 mutex_lock(&driver->diagchar_mutex);
555 for (i = 0; i < driver->num_clients; i++)
556 if (driver->client_map[i].pid != 0)
557 driver->data_ready[i] |= type;
558 wake_up_interruptible(&driver->wait_q);
559 mutex_unlock(&driver->diagchar_mutex);
560}
561
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700562void diag_update_sleeping_process(int process_id, int data_type)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700563{
564 int i;
565
566 mutex_lock(&driver->diagchar_mutex);
567 for (i = 0; i < driver->num_clients; i++)
568 if (driver->client_map[i].pid == process_id) {
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700569 driver->data_ready[i] |= data_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700570 break;
571 }
572 wake_up_interruptible(&driver->wait_q);
573 mutex_unlock(&driver->diagchar_mutex);
574}
575
576void diag_send_data(struct diag_master_table entry, unsigned char *buf,
577 int len, int type)
578{
579 driver->pkt_length = len;
580 if (entry.process_id != NON_APPS_PROC && type != MODEM_DATA) {
581 diag_update_pkt_buffer(buf);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -0700582 diag_update_sleeping_process(entry.process_id, PKT_TYPE);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700583 } else {
584 if (len > 0) {
Shalabh Jainc9f35092011-07-28 18:36:17 -0700585 if (entry.client_id == MODEM_PROC && driver->ch) {
Shalabh Jain10f5f432012-01-11 11:45:44 +0530586 if (chk_apps_master() &&
Shalabh Jainc9f35092011-07-28 18:36:17 -0700587 (int)(*(char *)buf) == MODE_CMD)
Dixon Petersonff425d12011-12-06 18:12:35 -0800588 if ((int)(*(char *)(buf+1)) ==
589 RESET_ID)
Shalabh Jainc9f35092011-07-28 18:36:17 -0700590 return;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700591 smd_write(driver->ch, buf, len);
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700592 } else if (entry.client_id == LPASS_PROC &&
593 driver->chlpass) {
594 smd_write(driver->chlpass, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700595 } else if (entry.client_id == WCNSS_PROC &&
596 driver->ch_wcnss) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700597 smd_write(driver->ch_wcnss, buf, len);
Shalabh Jainc9f35092011-07-28 18:36:17 -0700598 } else {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700599 pr_alert("diag: incorrect channel");
Shalabh Jainc9f35092011-07-28 18:36:17 -0700600 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700601 }
602 }
603}
604
605static int diag_process_apps_pkt(unsigned char *buf, int len)
606{
607 uint16_t subsys_cmd_code;
608 int subsys_id, ssid_first, ssid_last, ssid_range;
Shalabh Jain3fd986f2012-05-30 18:42:26 -0700609 int packet_type = 1, i, cmd_code;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700610 unsigned char *temp = buf;
Dixon Petersond6a20a92012-09-27 15:58:50 -0700611 int data_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700612#if defined(CONFIG_DIAG_OVER_USB)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700613 unsigned char *ptr;
614#endif
615
Dixon Petersond6a20a92012-09-27 15:58:50 -0700616 /* Check if the command is a supported mask command */
617 if (diag_process_apps_masks(buf, len) == 0)
618 return 0;
619
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700620 /* Check for registered clients and forward packet to apropriate proc */
621 cmd_code = (int)(*(char *)buf);
622 temp++;
623 subsys_id = (int)(*(char *)temp);
624 temp++;
625 subsys_cmd_code = *(uint16_t *)temp;
626 temp += 2;
627 data_type = APPS_DATA;
628 /* Dont send any command other than mode reset */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530629 if (chk_apps_master() && cmd_code == MODE_CMD) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700630 if (subsys_id != RESET_ID)
631 data_type = MODEM_DATA;
632 }
633
634 pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
Shalabh Jainfe02b0c2012-02-21 14:48:03 -0800635 for (i = 0; i < diag_max_reg; i++) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700636 entry = driver->table[i];
637 if (entry.process_id != NO_PROCESS) {
638 if (entry.cmd_code == cmd_code && entry.subsys_id ==
639 subsys_id && entry.cmd_code_lo <=
640 subsys_cmd_code &&
641 entry.cmd_code_hi >= subsys_cmd_code) {
642 diag_send_data(entry, buf, len, data_type);
643 packet_type = 0;
644 } else if (entry.cmd_code == 255
645 && cmd_code == 75) {
646 if (entry.subsys_id ==
647 subsys_id &&
648 entry.cmd_code_lo <=
649 subsys_cmd_code &&
650 entry.cmd_code_hi >=
651 subsys_cmd_code) {
652 diag_send_data(entry, buf, len,
653 data_type);
654 packet_type = 0;
655 }
656 } else if (entry.cmd_code == 255 &&
657 entry.subsys_id == 255) {
658 if (entry.cmd_code_lo <=
659 cmd_code &&
660 entry.
661 cmd_code_hi >= cmd_code) {
662 diag_send_data(entry, buf, len,
663 data_type);
664 packet_type = 0;
665 }
666 }
667 }
668 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700669#if defined(CONFIG_DIAG_OVER_USB)
Dixon Petersona2dd7352012-05-21 17:37:10 -0700670 /* Check for the command/respond msg for the maximum packet length */
671 if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
672 (*(uint16_t *)(buf+2) == 0x0055)) {
673 for (i = 0; i < 4; i++)
674 *(driver->apps_rsp_buf+i) = *(buf+i);
675 *(uint32_t *)(driver->apps_rsp_buf+4) = PKT_SIZE;
Dixon Petersond6a20a92012-09-27 15:58:50 -0700676 encode_rsp_and_send(7);
Dixon Petersona2dd7352012-05-21 17:37:10 -0700677 return 0;
678 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700679 /* Check for Apps Only & get event mask request */
Dixon Petersona2dd7352012-05-21 17:37:10 -0700680 else if (!(driver->ch) && chk_apps_only() && *buf == 0x81) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700681 driver->apps_rsp_buf[0] = 0x81;
682 driver->apps_rsp_buf[1] = 0x0;
683 *(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
684 *(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
685 for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
686 *(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
Dixon Petersond6a20a92012-09-27 15:58:50 -0700687 encode_rsp_and_send(6 + EVENT_LAST_ID/8);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700688 return 0;
689 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700690 /* Get log ID range & Check for Apps Only */
691 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700692 && (*buf == 0x73) && *(int *)(buf+4) == 1) {
693 driver->apps_rsp_buf[0] = 0x73;
694 *(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
695 *(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
696 *(int *)(driver->apps_rsp_buf + 12) = LOG_GET_ITEM_NUM(LOG_0);
697 *(int *)(driver->apps_rsp_buf + 16) = LOG_GET_ITEM_NUM(LOG_1);
698 *(int *)(driver->apps_rsp_buf + 20) = LOG_GET_ITEM_NUM(LOG_2);
699 *(int *)(driver->apps_rsp_buf + 24) = LOG_GET_ITEM_NUM(LOG_3);
700 *(int *)(driver->apps_rsp_buf + 28) = LOG_GET_ITEM_NUM(LOG_4);
701 *(int *)(driver->apps_rsp_buf + 32) = LOG_GET_ITEM_NUM(LOG_5);
702 *(int *)(driver->apps_rsp_buf + 36) = LOG_GET_ITEM_NUM(LOG_6);
703 *(int *)(driver->apps_rsp_buf + 40) = LOG_GET_ITEM_NUM(LOG_7);
704 *(int *)(driver->apps_rsp_buf + 44) = LOG_GET_ITEM_NUM(LOG_8);
705 *(int *)(driver->apps_rsp_buf + 48) = LOG_GET_ITEM_NUM(LOG_9);
706 *(int *)(driver->apps_rsp_buf + 52) = LOG_GET_ITEM_NUM(LOG_10);
707 *(int *)(driver->apps_rsp_buf + 56) = LOG_GET_ITEM_NUM(LOG_11);
708 *(int *)(driver->apps_rsp_buf + 60) = LOG_GET_ITEM_NUM(LOG_12);
709 *(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
710 *(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
711 *(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
Dixon Petersond6a20a92012-09-27 15:58:50 -0700712 encode_rsp_and_send(75);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700713 return 0;
714 }
715 /* Respond to Get SSID Range request message */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700716 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700717 && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
718 driver->apps_rsp_buf[0] = 0x7d;
719 driver->apps_rsp_buf[1] = 0x1;
720 driver->apps_rsp_buf[2] = 0x1;
721 driver->apps_rsp_buf[3] = 0x0;
Shalabh Jain44b79b72012-06-15 13:39:27 -0700722 /* -1 to un-account for OEM SSID range */
723 *(int *)(driver->apps_rsp_buf + 4) = MSG_MASK_TBL_CNT - 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700724 *(uint16_t *)(driver->apps_rsp_buf + 8) = MSG_SSID_0;
725 *(uint16_t *)(driver->apps_rsp_buf + 10) = MSG_SSID_0_LAST;
726 *(uint16_t *)(driver->apps_rsp_buf + 12) = MSG_SSID_1;
727 *(uint16_t *)(driver->apps_rsp_buf + 14) = MSG_SSID_1_LAST;
728 *(uint16_t *)(driver->apps_rsp_buf + 16) = MSG_SSID_2;
729 *(uint16_t *)(driver->apps_rsp_buf + 18) = MSG_SSID_2_LAST;
730 *(uint16_t *)(driver->apps_rsp_buf + 20) = MSG_SSID_3;
731 *(uint16_t *)(driver->apps_rsp_buf + 22) = MSG_SSID_3_LAST;
732 *(uint16_t *)(driver->apps_rsp_buf + 24) = MSG_SSID_4;
733 *(uint16_t *)(driver->apps_rsp_buf + 26) = MSG_SSID_4_LAST;
734 *(uint16_t *)(driver->apps_rsp_buf + 28) = MSG_SSID_5;
735 *(uint16_t *)(driver->apps_rsp_buf + 30) = MSG_SSID_5_LAST;
736 *(uint16_t *)(driver->apps_rsp_buf + 32) = MSG_SSID_6;
737 *(uint16_t *)(driver->apps_rsp_buf + 34) = MSG_SSID_6_LAST;
738 *(uint16_t *)(driver->apps_rsp_buf + 36) = MSG_SSID_7;
739 *(uint16_t *)(driver->apps_rsp_buf + 38) = MSG_SSID_7_LAST;
740 *(uint16_t *)(driver->apps_rsp_buf + 40) = MSG_SSID_8;
741 *(uint16_t *)(driver->apps_rsp_buf + 42) = MSG_SSID_8_LAST;
742 *(uint16_t *)(driver->apps_rsp_buf + 44) = MSG_SSID_9;
743 *(uint16_t *)(driver->apps_rsp_buf + 46) = MSG_SSID_9_LAST;
744 *(uint16_t *)(driver->apps_rsp_buf + 48) = MSG_SSID_10;
745 *(uint16_t *)(driver->apps_rsp_buf + 50) = MSG_SSID_10_LAST;
746 *(uint16_t *)(driver->apps_rsp_buf + 52) = MSG_SSID_11;
747 *(uint16_t *)(driver->apps_rsp_buf + 54) = MSG_SSID_11_LAST;
748 *(uint16_t *)(driver->apps_rsp_buf + 56) = MSG_SSID_12;
749 *(uint16_t *)(driver->apps_rsp_buf + 58) = MSG_SSID_12_LAST;
750 *(uint16_t *)(driver->apps_rsp_buf + 60) = MSG_SSID_13;
751 *(uint16_t *)(driver->apps_rsp_buf + 62) = MSG_SSID_13_LAST;
752 *(uint16_t *)(driver->apps_rsp_buf + 64) = MSG_SSID_14;
753 *(uint16_t *)(driver->apps_rsp_buf + 66) = MSG_SSID_14_LAST;
754 *(uint16_t *)(driver->apps_rsp_buf + 68) = MSG_SSID_15;
755 *(uint16_t *)(driver->apps_rsp_buf + 70) = MSG_SSID_15_LAST;
756 *(uint16_t *)(driver->apps_rsp_buf + 72) = MSG_SSID_16;
757 *(uint16_t *)(driver->apps_rsp_buf + 74) = MSG_SSID_16_LAST;
758 *(uint16_t *)(driver->apps_rsp_buf + 76) = MSG_SSID_17;
759 *(uint16_t *)(driver->apps_rsp_buf + 78) = MSG_SSID_17_LAST;
760 *(uint16_t *)(driver->apps_rsp_buf + 80) = MSG_SSID_18;
761 *(uint16_t *)(driver->apps_rsp_buf + 82) = MSG_SSID_18_LAST;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800762 *(uint16_t *)(driver->apps_rsp_buf + 84) = MSG_SSID_19;
763 *(uint16_t *)(driver->apps_rsp_buf + 86) = MSG_SSID_19_LAST;
764 *(uint16_t *)(driver->apps_rsp_buf + 88) = MSG_SSID_20;
765 *(uint16_t *)(driver->apps_rsp_buf + 90) = MSG_SSID_20_LAST;
766 *(uint16_t *)(driver->apps_rsp_buf + 92) = MSG_SSID_21;
767 *(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
768 *(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
769 *(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
Dixon Petersond6a20a92012-09-27 15:58:50 -0700770 encode_rsp_and_send(99);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700771 return 0;
772 }
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700773 /* Check for Apps Only Respond to Get Subsys Build mask */
774 else if (!(driver->ch) && chk_apps_only()
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700775 && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
776 ssid_first = *(uint16_t *)(buf + 2);
777 ssid_last = *(uint16_t *)(buf + 4);
778 ssid_range = 4 * (ssid_last - ssid_first + 1);
779 /* frame response */
780 driver->apps_rsp_buf[0] = 0x7d;
781 driver->apps_rsp_buf[1] = 0x2;
782 *(uint16_t *)(driver->apps_rsp_buf + 2) = ssid_first;
783 *(uint16_t *)(driver->apps_rsp_buf + 4) = ssid_last;
784 driver->apps_rsp_buf[6] = 0x1;
785 driver->apps_rsp_buf[7] = 0x0;
786 ptr = driver->apps_rsp_buf + 8;
787 /* bld time masks */
788 switch (ssid_first) {
789 case MSG_SSID_0:
790 for (i = 0; i < ssid_range; i += 4)
791 *(int *)(ptr + i) = msg_bld_masks_0[i/4];
792 break;
793 case MSG_SSID_1:
794 for (i = 0; i < ssid_range; i += 4)
795 *(int *)(ptr + i) = msg_bld_masks_1[i/4];
796 break;
797 case MSG_SSID_2:
798 for (i = 0; i < ssid_range; i += 4)
799 *(int *)(ptr + i) = msg_bld_masks_2[i/4];
800 break;
801 case MSG_SSID_3:
802 for (i = 0; i < ssid_range; i += 4)
803 *(int *)(ptr + i) = msg_bld_masks_3[i/4];
804 break;
805 case MSG_SSID_4:
806 for (i = 0; i < ssid_range; i += 4)
807 *(int *)(ptr + i) = msg_bld_masks_4[i/4];
808 break;
809 case MSG_SSID_5:
810 for (i = 0; i < ssid_range; i += 4)
811 *(int *)(ptr + i) = msg_bld_masks_5[i/4];
812 break;
813 case MSG_SSID_6:
814 for (i = 0; i < ssid_range; i += 4)
815 *(int *)(ptr + i) = msg_bld_masks_6[i/4];
816 break;
817 case MSG_SSID_7:
818 for (i = 0; i < ssid_range; i += 4)
819 *(int *)(ptr + i) = msg_bld_masks_7[i/4];
820 break;
821 case MSG_SSID_8:
822 for (i = 0; i < ssid_range; i += 4)
823 *(int *)(ptr + i) = msg_bld_masks_8[i/4];
824 break;
825 case MSG_SSID_9:
826 for (i = 0; i < ssid_range; i += 4)
827 *(int *)(ptr + i) = msg_bld_masks_9[i/4];
828 break;
829 case MSG_SSID_10:
830 for (i = 0; i < ssid_range; i += 4)
831 *(int *)(ptr + i) = msg_bld_masks_10[i/4];
832 break;
833 case MSG_SSID_11:
834 for (i = 0; i < ssid_range; i += 4)
835 *(int *)(ptr + i) = msg_bld_masks_11[i/4];
836 break;
837 case MSG_SSID_12:
838 for (i = 0; i < ssid_range; i += 4)
839 *(int *)(ptr + i) = msg_bld_masks_12[i/4];
840 break;
841 case MSG_SSID_13:
842 for (i = 0; i < ssid_range; i += 4)
843 *(int *)(ptr + i) = msg_bld_masks_13[i/4];
844 break;
845 case MSG_SSID_14:
846 for (i = 0; i < ssid_range; i += 4)
847 *(int *)(ptr + i) = msg_bld_masks_14[i/4];
848 break;
849 case MSG_SSID_15:
850 for (i = 0; i < ssid_range; i += 4)
851 *(int *)(ptr + i) = msg_bld_masks_15[i/4];
852 break;
853 case MSG_SSID_16:
854 for (i = 0; i < ssid_range; i += 4)
855 *(int *)(ptr + i) = msg_bld_masks_16[i/4];
856 break;
857 case MSG_SSID_17:
858 for (i = 0; i < ssid_range; i += 4)
859 *(int *)(ptr + i) = msg_bld_masks_17[i/4];
860 break;
861 case MSG_SSID_18:
862 for (i = 0; i < ssid_range; i += 4)
863 *(int *)(ptr + i) = msg_bld_masks_18[i/4];
864 break;
Shalabh Jain321c8b52012-02-22 12:37:06 -0800865 case MSG_SSID_19:
866 for (i = 0; i < ssid_range; i += 4)
867 *(int *)(ptr + i) = msg_bld_masks_19[i/4];
868 break;
869 case MSG_SSID_20:
870 for (i = 0; i < ssid_range; i += 4)
871 *(int *)(ptr + i) = msg_bld_masks_20[i/4];
872 break;
873 case MSG_SSID_21:
874 for (i = 0; i < ssid_range; i += 4)
875 *(int *)(ptr + i) = msg_bld_masks_21[i/4];
876 break;
877 case MSG_SSID_22:
878 for (i = 0; i < ssid_range; i += 4)
879 *(int *)(ptr + i) = msg_bld_masks_22[i/4];
880 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700881 }
Dixon Petersond6a20a92012-09-27 15:58:50 -0700882 encode_rsp_and_send(8 + ssid_range - 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700883 return 0;
884 }
885 /* Check for download command */
Shalabh Jain10f5f432012-01-11 11:45:44 +0530886 else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700887 /* send response back */
888 driver->apps_rsp_buf[0] = *buf;
Dixon Petersond6a20a92012-09-27 15:58:50 -0700889 encode_rsp_and_send(0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700890 msleep(5000);
891 /* call download API */
892 msm_set_restart_mode(RESTART_DLOAD);
893 printk(KERN_CRIT "diag: download mode set, Rebooting SoC..\n");
894 kernel_restart(NULL);
895 /* Not required, represents that command isnt sent to modem */
896 return 0;
897 }
Dixon Petersonb46bb992012-01-12 19:16:56 -0800898 /* Check for polling for Apps only DIAG */
899 else if ((*buf == 0x4b) && (*(buf+1) == 0x32) &&
900 (*(buf+2) == 0x03)) {
Shalabh Jain3d29fc32012-02-09 17:15:59 -0800901 /* If no one has registered for polling */
Dixon Petersonb4618a42012-02-29 18:56:31 -0800902 if (chk_polling_response()) {
Dixon Petersonb46bb992012-01-12 19:16:56 -0800903 /* Respond to polling for Apps only DIAG */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700904 for (i = 0; i < 3; i++)
905 driver->apps_rsp_buf[i] = *(buf+i);
906 for (i = 0; i < 13; i++)
907 driver->apps_rsp_buf[i+3] = 0;
908
Dixon Petersond6a20a92012-09-27 15:58:50 -0700909 encode_rsp_and_send(15);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700910 return 0;
911 }
Dixon Petersonb46bb992012-01-12 19:16:56 -0800912 }
913 /* Check for ID for NO MODEM present */
Dixon Petersonb4618a42012-02-29 18:56:31 -0800914 else if (chk_polling_response()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700915 /* respond to 0x0 command */
Dixon Petersonb46bb992012-01-12 19:16:56 -0800916 if (*buf == 0x00) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700917 for (i = 0; i < 55; i++)
918 driver->apps_rsp_buf[i] = 0;
919
Dixon Petersond6a20a92012-09-27 15:58:50 -0700920 encode_rsp_and_send(54);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700921 return 0;
922 }
923 /* respond to 0x7c command */
924 else if (*buf == 0x7c) {
925 driver->apps_rsp_buf[0] = 0x7c;
926 for (i = 1; i < 8; i++)
927 driver->apps_rsp_buf[i] = 0;
928 /* Tools ID for APQ 8060 */
929 *(int *)(driver->apps_rsp_buf + 8) =
930 chk_config_get_id();
931 *(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
932 *(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
Dixon Petersond6a20a92012-09-27 15:58:50 -0700933 encode_rsp_and_send(13);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700934 return 0;
935 }
936 }
937#endif
Dixon Petersond6a20a92012-09-27 15:58:50 -0700938 return packet_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700939}
940
941#ifdef CONFIG_DIAG_OVER_USB
942void diag_send_error_rsp(int index)
943{
944 int i;
Shalabh Jain1fedab92011-12-22 13:15:22 +0530945
946 if (index > 490) {
947 pr_err("diag: error response too huge, aborting\n");
948 return;
949 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700950 driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
951 for (i = 0; i < index; i++)
952 driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
Dixon Petersond6a20a92012-09-27 15:58:50 -0700953 encode_rsp_and_send(index - 3);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700954}
955#else
956static inline void diag_send_error_rsp(int index) {}
957#endif
958
959void diag_process_hdlc(void *data, unsigned len)
960{
961 struct diag_hdlc_decode_type hdlc;
962 int ret, type = 0;
963 pr_debug("diag: HDLC decode fn, len of data %d\n", len);
964 hdlc.dest_ptr = driver->hdlc_buf;
965 hdlc.dest_size = USB_MAX_OUT_BUF;
966 hdlc.src_ptr = data;
967 hdlc.src_size = len;
968 hdlc.src_idx = 0;
969 hdlc.dest_idx = 0;
970 hdlc.escaping = 0;
971
972 ret = diag_hdlc_decode(&hdlc);
973
974 if (ret)
975 type = diag_process_apps_pkt(driver->hdlc_buf,
976 hdlc.dest_idx - 3);
977 else if (driver->debug_flag) {
978 printk(KERN_ERR "Packet dropped due to bad HDLC coding/CRC"
979 " errors or partial packet received, packet"
980 " length = %d\n", len);
981 print_hex_dump(KERN_DEBUG, "Dropped Packet Data: ", 16, 1,
982 DUMP_PREFIX_ADDRESS, data, len, 1);
983 driver->debug_flag = 0;
984 }
985 /* send error responses from APPS for Central Routing */
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700986 if (type == 1 && chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700987 diag_send_error_rsp(hdlc.dest_idx);
988 type = 0;
989 }
990 /* implies this packet is NOT meant for apps */
991 if (!(driver->ch) && type == 1) {
Shalabh Jainfb8e3c12011-10-19 17:29:42 -0700992 if (chk_apps_only()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700993 diag_send_error_rsp(hdlc.dest_idx);
994 } else { /* APQ 8060, Let Q6 respond */
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -0700995 if (driver->chlpass)
996 smd_write(driver->chlpass, driver->hdlc_buf,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700997 hdlc.dest_idx - 3);
998 }
999 type = 0;
1000 }
1001
1002#ifdef DIAG_DEBUG
1003 pr_debug("diag: hdlc.dest_idx = %d", hdlc.dest_idx);
1004 for (i = 0; i < hdlc.dest_idx; i++)
1005 printk(KERN_DEBUG "\t%x", *(((unsigned char *)
1006 driver->hdlc_buf)+i));
1007#endif /* DIAG DEBUG */
1008 /* ignore 2 bytes for CRC, one for 7E and send */
1009 if ((driver->ch) && (ret) && (type) && (hdlc.dest_idx > 3)) {
1010 APPEND_DEBUG('g');
1011 smd_write(driver->ch, driver->hdlc_buf, hdlc.dest_idx - 3);
1012 APPEND_DEBUG('h');
1013#ifdef DIAG_DEBUG
1014 printk(KERN_INFO "writing data to SMD, pkt length %d\n", len);
1015 print_hex_dump(KERN_DEBUG, "Written Packet Data to SMD: ", 16,
1016 1, DUMP_PREFIX_ADDRESS, data, len, 1);
1017#endif /* DIAG DEBUG */
1018 }
1019}
1020
1021#ifdef CONFIG_DIAG_OVER_USB
Shalabh Jain8e9750a2011-09-09 13:06:29 -07001022/* 2+1 for modem ; 2 for LPASS ; 1 for WCNSS */
1023#define N_LEGACY_WRITE (driver->poolsize + 6)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001024#define N_LEGACY_READ 1
1025
1026int diagfwd_connect(void)
1027{
1028 int err;
1029
1030 printk(KERN_DEBUG "diag: USB connected\n");
1031 err = usb_diag_alloc_req(driver->legacy_ch, N_LEGACY_WRITE,
1032 N_LEGACY_READ);
1033 if (err)
1034 printk(KERN_ERR "diag: unable to alloc USB req on legacy ch");
1035
1036 driver->usb_connected = 1;
1037 driver->in_busy_1 = 0;
1038 driver->in_busy_2 = 0;
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001039 driver->in_busy_lpass_1 = 0;
1040 driver->in_busy_lpass_2 = 0;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301041 driver->in_busy_wcnss_1 = 0;
1042 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001043
1044 /* Poll SMD channels to check for data*/
1045 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001046 queue_work(driver->diag_wq, &(driver->diag_read_smd_lpass_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001047 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
Shalabh Jaincf5f20e2011-08-22 12:29:52 -07001048 /* Poll SMD CNTL channels to check for data */
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001049 diag_smd_cntl_notify(NULL, SMD_EVENT_DATA);
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001050 diag_smd_lpass_cntl_notify(NULL, SMD_EVENT_DATA);
Shalabh Jain4e1bd312012-02-16 19:33:05 -08001051 diag_smd_wcnss_cntl_notify(NULL, SMD_EVENT_DATA);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001052 /* Poll USB channel to check for data*/
1053 queue_work(driver->diag_wq, &(driver->diag_read_work));
1054#ifdef CONFIG_DIAG_SDIO_PIPE
1055 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa()) {
1056 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1057 diagfwd_connect_sdio();
1058 else
1059 printk(KERN_INFO "diag: No USB MDM ch");
1060 }
1061#endif
1062 return 0;
1063}
1064
1065int diagfwd_disconnect(void)
1066{
1067 printk(KERN_DEBUG "diag: USB disconnected\n");
1068 driver->usb_connected = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001069 driver->debug_flag = 1;
1070 usb_diag_free_req(driver->legacy_ch);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001071 if (driver->logging_mode == USB_MODE) {
1072 driver->in_busy_1 = 1;
1073 driver->in_busy_2 = 1;
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001074 driver->in_busy_lpass_1 = 1;
1075 driver->in_busy_lpass_2 = 1;
Ashay Jaiswal29620122012-03-21 12:02:36 +05301076 driver->in_busy_wcnss_1 = 1;
1077 driver->in_busy_wcnss_2 = 1;
Shalabh Jain69890aa2011-10-10 12:59:16 -07001078 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001079#ifdef CONFIG_DIAG_SDIO_PIPE
1080 if (machine_is_msm8x60_fusion() || machine_is_msm8x60_fusn_ffa())
1081 if (driver->mdm_ch && !IS_ERR(driver->mdm_ch))
1082 diagfwd_disconnect_sdio();
1083#endif
1084 /* TBD - notify and flow control SMD */
1085 return 0;
1086}
1087
1088int diagfwd_write_complete(struct diag_request *diag_write_ptr)
1089{
1090 unsigned char *buf = diag_write_ptr->buf;
1091 /*Determine if the write complete is for data from modem/apps/q6 */
1092 /* Need a context variable here instead */
1093 if (buf == (void *)driver->buf_in_1) {
1094 driver->in_busy_1 = 0;
1095 APPEND_DEBUG('o');
1096 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
1097 } else if (buf == (void *)driver->buf_in_2) {
1098 driver->in_busy_2 = 0;
1099 APPEND_DEBUG('O');
1100 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001101 } else if (buf == (void *)driver->buf_in_lpass_1) {
1102 driver->in_busy_lpass_1 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001103 APPEND_DEBUG('p');
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001104 queue_work(driver->diag_wq,
1105 &(driver->diag_read_smd_lpass_work));
1106 } else if (buf == (void *)driver->buf_in_lpass_2) {
1107 driver->in_busy_lpass_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001108 APPEND_DEBUG('P');
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001109 queue_work(driver->diag_wq,
1110 &(driver->diag_read_smd_lpass_work));
Ashay Jaiswal29620122012-03-21 12:02:36 +05301111 } else if (buf == driver->buf_in_wcnss_1) {
1112 driver->in_busy_wcnss_1 = 0;
1113 APPEND_DEBUG('r');
1114 queue_work(driver->diag_wq,
1115 &(driver->diag_read_smd_wcnss_work));
1116 } else if (buf == driver->buf_in_wcnss_2) {
1117 driver->in_busy_wcnss_2 = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001118 APPEND_DEBUG('R');
1119 queue_work(driver->diag_wq,
1120 &(driver->diag_read_smd_wcnss_work));
1121 }
1122#ifdef CONFIG_DIAG_SDIO_PIPE
1123 else if (buf == (void *)driver->buf_in_sdio)
1124 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001125 machine_is_msm8x60_fusn_ffa())
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001126 diagfwd_write_complete_sdio();
1127 else
1128 pr_err("diag: Incorrect buffer pointer while WRITE");
1129#endif
1130 else {
1131 diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HDLC);
1132 diagmem_free(driver, (unsigned char *)diag_write_ptr,
1133 POOL_TYPE_WRITE_STRUCT);
1134 APPEND_DEBUG('q');
1135 }
1136 return 0;
1137}
1138
1139int diagfwd_read_complete(struct diag_request *diag_read_ptr)
1140{
1141 int status = diag_read_ptr->status;
1142 unsigned char *buf = diag_read_ptr->buf;
1143
1144 /* Determine if the read complete is for data on legacy/mdm ch */
1145 if (buf == (void *)driver->usb_buf_out) {
1146 driver->read_len_legacy = diag_read_ptr->actual;
1147 APPEND_DEBUG('s');
1148#ifdef DIAG_DEBUG
1149 printk(KERN_INFO "read data from USB, pkt length %d",
1150 diag_read_ptr->actual);
1151 print_hex_dump(KERN_DEBUG, "Read Packet Data from USB: ", 16, 1,
1152 DUMP_PREFIX_ADDRESS, diag_read_ptr->buf,
1153 diag_read_ptr->actual, 1);
1154#endif /* DIAG DEBUG */
1155 if (driver->logging_mode == USB_MODE) {
1156 if (status != -ECONNRESET && status != -ESHUTDOWN)
1157 queue_work(driver->diag_wq,
1158 &(driver->diag_proc_hdlc_work));
1159 else
1160 queue_work(driver->diag_wq,
1161 &(driver->diag_read_work));
1162 }
1163 }
1164#ifdef CONFIG_DIAG_SDIO_PIPE
1165 else if (buf == (void *)driver->usb_buf_mdm_out) {
1166 if (machine_is_msm8x60_fusion() ||
Shalabh Jain482bf122011-12-06 03:54:47 -08001167 machine_is_msm8x60_fusn_ffa()) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001168 driver->read_len_mdm = diag_read_ptr->actual;
1169 diagfwd_read_complete_sdio();
1170 } else
1171 pr_err("diag: Incorrect buffer pointer while READ");
1172 }
1173#endif
1174 else
1175 printk(KERN_ERR "diag: Unknown buffer ptr from USB");
1176
1177 return 0;
1178}
1179
1180void diag_read_work_fn(struct work_struct *work)
1181{
1182 APPEND_DEBUG('d');
1183 driver->usb_read_ptr->buf = driver->usb_buf_out;
1184 driver->usb_read_ptr->length = USB_MAX_OUT_BUF;
1185 usb_diag_read(driver->legacy_ch, driver->usb_read_ptr);
1186 APPEND_DEBUG('e');
1187}
1188
1189void diag_process_hdlc_fn(struct work_struct *work)
1190{
1191 APPEND_DEBUG('D');
1192 diag_process_hdlc(driver->usb_buf_out, driver->read_len_legacy);
1193 diag_read_work_fn(work);
1194 APPEND_DEBUG('E');
1195}
1196
1197void diag_usb_legacy_notifier(void *priv, unsigned event,
1198 struct diag_request *d_req)
1199{
1200 switch (event) {
1201 case USB_DIAG_CONNECT:
1202 diagfwd_connect();
1203 break;
1204 case USB_DIAG_DISCONNECT:
1205 diagfwd_disconnect();
1206 break;
1207 case USB_DIAG_READ_DONE:
1208 diagfwd_read_complete(d_req);
1209 break;
1210 case USB_DIAG_WRITE_DONE:
1211 diagfwd_write_complete(d_req);
1212 break;
1213 default:
1214 printk(KERN_ERR "Unknown event from USB diag\n");
1215 break;
1216 }
1217}
1218
1219#endif /* DIAG OVER USB */
1220
1221static void diag_smd_notify(void *ctxt, unsigned event)
1222{
Shalabh Jainc2ec8292011-10-14 12:34:55 -07001223 if (event == SMD_EVENT_CLOSE) {
Shalabh Jain7b20eab2012-06-19 17:50:58 -07001224 queue_work(driver->diag_cntl_wq,
1225 &(driver->diag_clean_modem_reg_work));
Shalabh Jaineefee052011-11-08 23:46:03 -08001226 driver->ch = 0;
1227 return;
1228 } else if (event == SMD_EVENT_OPEN) {
Shalabh Jainaeaab622012-06-04 18:01:02 -07001229 if (ch_temp)
1230 driver->ch = ch_temp;
Shalabh Jaineefee052011-11-08 23:46:03 -08001231 }
1232 queue_work(driver->diag_wq, &(driver->diag_read_smd_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001233}
1234
1235#if defined(CONFIG_MSM_N_WAY_SMD)
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001236static void diag_smd_lpass_notify(void *ctxt, unsigned event)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001237{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001238 if (event == SMD_EVENT_CLOSE) {
Shalabh Jain7b20eab2012-06-19 17:50:58 -07001239 queue_work(driver->diag_cntl_wq,
1240 &(driver->diag_clean_lpass_reg_work));
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001241 driver->chlpass = 0;
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001242 return;
1243 } else if (event == SMD_EVENT_OPEN) {
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001244 if (chlpass_temp)
1245 driver->chlpass = chlpass_temp;
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001246 }
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001247 queue_work(driver->diag_wq, &(driver->diag_read_smd_lpass_work));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001248}
1249#endif
1250
1251static void diag_smd_wcnss_notify(void *ctxt, unsigned event)
1252{
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001253 if (event == SMD_EVENT_CLOSE) {
Shalabh Jain7b20eab2012-06-19 17:50:58 -07001254 queue_work(driver->diag_cntl_wq,
1255 &(driver->diag_clean_wcnss_reg_work));
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001256 driver->ch_wcnss = 0;
1257 return;
1258 } else if (event == SMD_EVENT_OPEN) {
Shalabh Jainaeaab622012-06-04 18:01:02 -07001259 if (ch_wcnss_temp)
1260 driver->ch_wcnss = ch_wcnss_temp;
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001261 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001262 queue_work(driver->diag_wq, &(driver->diag_read_smd_wcnss_work));
1263}
1264
1265static int diag_smd_probe(struct platform_device *pdev)
1266{
1267 int r = 0;
1268
Shalabh Jaineefee052011-11-08 23:46:03 -08001269 if (pdev->id == SMD_APPS_MODEM) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001270 r = smd_open("DIAG", &driver->ch, driver, diag_smd_notify);
Shalabh Jaineefee052011-11-08 23:46:03 -08001271 ch_temp = driver->ch;
1272 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001273#if defined(CONFIG_MSM_N_WAY_SMD)
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001274 if (pdev->id == SMD_APPS_QDSP) {
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001275 r = smd_named_open_on_edge("DIAG", SMD_APPS_QDSP,
1276 &driver->chlpass, driver, diag_smd_lpass_notify);
1277 chlpass_temp = driver->chlpass;
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001278 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001279#endif
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001280 if (pdev->id == SMD_APPS_WCNSS) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001281 r = smd_named_open_on_edge("APPS_RIVA_DATA", SMD_APPS_WCNSS
1282 , &driver->ch_wcnss, driver, diag_smd_wcnss_notify);
Shalabh Jainc6c2b1d2011-12-20 04:32:34 -08001283 ch_wcnss_temp = driver->ch_wcnss;
1284 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001285 pm_runtime_set_active(&pdev->dev);
1286 pm_runtime_enable(&pdev->dev);
1287 pr_debug("diag: open SMD port, Id = %d, r = %d\n", pdev->id, r);
1288
1289 return 0;
1290}
1291
1292static int diagfwd_runtime_suspend(struct device *dev)
1293{
1294 dev_dbg(dev, "pm_runtime: suspending...\n");
1295 return 0;
1296}
1297
1298static int diagfwd_runtime_resume(struct device *dev)
1299{
1300 dev_dbg(dev, "pm_runtime: resuming...\n");
1301 return 0;
1302}
1303
1304static const struct dev_pm_ops diagfwd_dev_pm_ops = {
1305 .runtime_suspend = diagfwd_runtime_suspend,
1306 .runtime_resume = diagfwd_runtime_resume,
1307};
1308
1309static struct platform_driver msm_smd_ch1_driver = {
1310
1311 .probe = diag_smd_probe,
1312 .driver = {
1313 .name = "DIAG",
1314 .owner = THIS_MODULE,
1315 .pm = &diagfwd_dev_pm_ops,
1316 },
1317};
1318
1319static struct platform_driver diag_smd_lite_driver = {
1320
1321 .probe = diag_smd_probe,
1322 .driver = {
1323 .name = "APPS_RIVA_DATA",
1324 .owner = THIS_MODULE,
1325 .pm = &diagfwd_dev_pm_ops,
1326 },
1327};
1328
1329void diagfwd_init(void)
1330{
1331 diag_debug_buf_idx = 0;
1332 driver->read_len_legacy = 0;
Dixon Petersonb4618a42012-02-29 18:56:31 -08001333 driver->use_device_tree = has_device_tree();
Shalabh Jaina06c6d72012-04-30 13:40:35 -07001334 mutex_init(&driver->diag_cntl_mutex);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001335
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001336 if (driver->buf_in_1 == NULL) {
1337 driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1338 if (driver->buf_in_1 == NULL)
1339 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001340 kmemleak_not_leak(driver->buf_in_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001341 }
1342 if (driver->buf_in_2 == NULL) {
1343 driver->buf_in_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1344 if (driver->buf_in_2 == NULL)
1345 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001346 kmemleak_not_leak(driver->buf_in_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001347 }
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001348 if (driver->buf_in_lpass_1 == NULL) {
1349 driver->buf_in_lpass_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1350 if (driver->buf_in_lpass_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001351 goto err;
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001352 kmemleak_not_leak(driver->buf_in_lpass_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001353 }
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001354 if (driver->buf_in_lpass_2 == NULL) {
1355 driver->buf_in_lpass_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1356 if (driver->buf_in_lpass_2 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001357 goto err;
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001358 kmemleak_not_leak(driver->buf_in_lpass_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001359 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301360 if (driver->buf_in_wcnss_1 == NULL) {
1361 driver->buf_in_wcnss_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1362 if (driver->buf_in_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001363 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001364 kmemleak_not_leak(driver->buf_in_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001365 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301366 if (driver->buf_in_wcnss_2 == NULL) {
1367 driver->buf_in_wcnss_2 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
1368 if (driver->buf_in_wcnss_2 == NULL)
1369 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001370 kmemleak_not_leak(driver->buf_in_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301371 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001372 if (driver->usb_buf_out == NULL &&
1373 (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
1374 GFP_KERNEL)) == NULL)
1375 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001376 kmemleak_not_leak(driver->usb_buf_out);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001377 if (driver->hdlc_buf == NULL
1378 && (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
1379 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001380 kmemleak_not_leak(driver->hdlc_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001381 if (driver->user_space_data == NULL)
1382 driver->user_space_data = kzalloc(USER_SPACE_DATA, GFP_KERNEL);
1383 if (driver->user_space_data == NULL)
1384 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001385 kmemleak_not_leak(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001386 if (driver->client_map == NULL &&
1387 (driver->client_map = kzalloc
1388 ((driver->num_clients) * sizeof(struct diag_client_map),
1389 GFP_KERNEL)) == NULL)
1390 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001391 kmemleak_not_leak(driver->client_map);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001392 if (driver->buf_tbl == NULL)
1393 driver->buf_tbl = kzalloc(buf_tbl_size *
1394 sizeof(struct diag_write_device), GFP_KERNEL);
1395 if (driver->buf_tbl == NULL)
1396 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001397 kmemleak_not_leak(driver->buf_tbl);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001398 if (driver->data_ready == NULL &&
1399 (driver->data_ready = kzalloc(driver->num_clients * sizeof(int)
1400 , GFP_KERNEL)) == NULL)
1401 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001402 kmemleak_not_leak(driver->data_ready);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001403 if (driver->table == NULL &&
Shalabh Jainfe02b0c2012-02-21 14:48:03 -08001404 (driver->table = kzalloc(diag_max_reg*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001405 sizeof(struct diag_master_table),
1406 GFP_KERNEL)) == NULL)
1407 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001408 kmemleak_not_leak(driver->table);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001409 if (driver->write_ptr_1 == NULL) {
1410 driver->write_ptr_1 = kzalloc(
1411 sizeof(struct diag_request), GFP_KERNEL);
1412 if (driver->write_ptr_1 == NULL)
1413 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001414 kmemleak_not_leak(driver->write_ptr_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001415 }
1416 if (driver->write_ptr_2 == NULL) {
1417 driver->write_ptr_2 = kzalloc(
1418 sizeof(struct diag_request), GFP_KERNEL);
1419 if (driver->write_ptr_2 == NULL)
1420 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001421 kmemleak_not_leak(driver->write_ptr_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001422 }
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001423 if (driver->write_ptr_lpass_1 == NULL) {
1424 driver->write_ptr_lpass_1 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001425 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001426 if (driver->write_ptr_lpass_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001427 goto err;
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001428 kmemleak_not_leak(driver->write_ptr_lpass_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001429 }
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001430 if (driver->write_ptr_lpass_2 == NULL) {
1431 driver->write_ptr_lpass_2 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001432 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001433 if (driver->write_ptr_lpass_2 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001434 goto err;
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001435 kmemleak_not_leak(driver->write_ptr_lpass_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001436 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301437 if (driver->write_ptr_wcnss_1 == NULL) {
1438 driver->write_ptr_wcnss_1 = kzalloc(
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001439 sizeof(struct diag_request), GFP_KERNEL);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301440 if (driver->write_ptr_wcnss_1 == NULL)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001441 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001442 kmemleak_not_leak(driver->write_ptr_wcnss_1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001443 }
Ashay Jaiswal29620122012-03-21 12:02:36 +05301444 if (driver->write_ptr_wcnss_2 == NULL) {
1445 driver->write_ptr_wcnss_2 = kzalloc(
1446 sizeof(struct diag_request), GFP_KERNEL);
1447 if (driver->write_ptr_wcnss_2 == NULL)
1448 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001449 kmemleak_not_leak(driver->write_ptr_wcnss_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301450 }
1451
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001452 if (driver->usb_read_ptr == NULL) {
1453 driver->usb_read_ptr = kzalloc(
1454 sizeof(struct diag_request), GFP_KERNEL);
1455 if (driver->usb_read_ptr == NULL)
1456 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001457 kmemleak_not_leak(driver->usb_read_ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001458 }
1459 if (driver->pkt_buf == NULL &&
1460 (driver->pkt_buf = kzalloc(PKT_SIZE,
1461 GFP_KERNEL)) == NULL)
1462 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001463 kmemleak_not_leak(driver->pkt_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001464 if (driver->apps_rsp_buf == NULL) {
Shalabh Jain321c8b52012-02-22 12:37:06 -08001465 driver->apps_rsp_buf = kzalloc(APPS_BUF_SIZE, GFP_KERNEL);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001466 if (driver->apps_rsp_buf == NULL)
1467 goto err;
Dixon Petersoncc0bea772012-04-11 20:45:37 -07001468 kmemleak_not_leak(driver->apps_rsp_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001469 }
1470 driver->diag_wq = create_singlethread_workqueue("diag_wq");
1471#ifdef CONFIG_DIAG_OVER_USB
1472 INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
1473 INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
1474 driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
1475 diag_usb_legacy_notifier);
1476 if (IS_ERR(driver->legacy_ch)) {
1477 printk(KERN_ERR "Unable to open USB diag legacy channel\n");
1478 goto err;
1479 }
1480#endif
1481 platform_driver_register(&msm_smd_ch1_driver);
1482 platform_driver_register(&diag_smd_lite_driver);
1483
1484 return;
1485err:
Dixon Petersond6a20a92012-09-27 15:58:50 -07001486 pr_err("diag: Could not initialize diag buffers");
1487 kfree(driver->buf_in_1);
1488 kfree(driver->buf_in_2);
1489 kfree(driver->buf_in_lpass_1);
1490 kfree(driver->buf_in_lpass_2);
1491 kfree(driver->buf_in_wcnss_1);
1492 kfree(driver->buf_in_wcnss_2);
1493 kfree(driver->buf_msg_mask_update);
1494 kfree(driver->buf_log_mask_update);
1495 kfree(driver->buf_event_mask_update);
1496 kfree(driver->usb_buf_out);
1497 kfree(driver->hdlc_buf);
1498 kfree(driver->client_map);
1499 kfree(driver->buf_tbl);
1500 kfree(driver->data_ready);
1501 kfree(driver->table);
1502 kfree(driver->pkt_buf);
1503 kfree(driver->write_ptr_1);
1504 kfree(driver->write_ptr_2);
1505 kfree(driver->write_ptr_lpass_1);
1506 kfree(driver->write_ptr_lpass_2);
1507 kfree(driver->write_ptr_wcnss_1);
1508 kfree(driver->write_ptr_wcnss_2);
1509 kfree(driver->usb_read_ptr);
1510 kfree(driver->apps_rsp_buf);
1511 kfree(driver->user_space_data);
1512 if (driver->diag_wq)
1513 destroy_workqueue(driver->diag_wq);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001514}
1515
1516void diagfwd_exit(void)
1517{
1518 smd_close(driver->ch);
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001519 smd_close(driver->chlpass);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001520 smd_close(driver->ch_wcnss);
1521 driver->ch = 0; /* SMD can make this NULL */
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001522 driver->chlpass = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001523 driver->ch_wcnss = 0;
1524#ifdef CONFIG_DIAG_OVER_USB
1525 if (driver->usb_connected)
1526 usb_diag_free_req(driver->legacy_ch);
1527 usb_diag_close(driver->legacy_ch);
1528#endif
1529 platform_driver_unregister(&msm_smd_ch1_driver);
Shalabh Jain1c99e4c2012-03-26 18:47:59 -07001530 platform_driver_unregister(&msm_diag_dci_driver);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001531 platform_driver_unregister(&diag_smd_lite_driver);
1532 kfree(driver->buf_in_1);
1533 kfree(driver->buf_in_2);
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001534 kfree(driver->buf_in_lpass_1);
1535 kfree(driver->buf_in_lpass_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301536 kfree(driver->buf_in_wcnss_1);
1537 kfree(driver->buf_in_wcnss_2);
Shalabh Jain321c8b52012-02-22 12:37:06 -08001538 kfree(driver->buf_msg_mask_update);
1539 kfree(driver->buf_log_mask_update);
1540 kfree(driver->buf_event_mask_update);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001541 kfree(driver->usb_buf_out);
1542 kfree(driver->hdlc_buf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001543 kfree(driver->client_map);
1544 kfree(driver->buf_tbl);
1545 kfree(driver->data_ready);
1546 kfree(driver->table);
1547 kfree(driver->pkt_buf);
1548 kfree(driver->write_ptr_1);
1549 kfree(driver->write_ptr_2);
Ashay Jaiswal8be3ce82012-09-13 16:01:54 -07001550 kfree(driver->write_ptr_lpass_1);
1551 kfree(driver->write_ptr_lpass_2);
Ashay Jaiswal29620122012-03-21 12:02:36 +05301552 kfree(driver->write_ptr_wcnss_1);
1553 kfree(driver->write_ptr_wcnss_2);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001554 kfree(driver->usb_read_ptr);
1555 kfree(driver->apps_rsp_buf);
Shalabh Jain69890aa2011-10-10 12:59:16 -07001556 kfree(driver->user_space_data);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001557 destroy_workqueue(driver->diag_wq);
1558}