blob: 041430ea02b59962ac037a6ba9b2b162c0731dab [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14/*
15 * SMD RPC PING MODEM Driver
16 */
17
18#include <linux/slab.h>
19#include <linux/kernel.h>
20#include <linux/err.h>
21#include <linux/fs.h>
22#include <linux/sched.h>
23#include <linux/debugfs.h>
24#include <linux/uaccess.h>
25#include <linux/kfifo.h>
26#include <mach/msm_rpcrouter.h>
27
28#define PING_TEST_BASE 0x31
29
30#define PTIOC_NULL_TEST _IO(PING_TEST_BASE, 1)
31#define PTIOC_REG_TEST _IO(PING_TEST_BASE, 2)
32#define PTIOC_DATA_REG_TEST _IO(PING_TEST_BASE, 3)
33#define PTIOC_DATA_CB_REG_TEST _IO(PING_TEST_BASE, 4)
34
35#define PING_MDM_PROG 0x30000081
36#define PING_MDM_VERS 0x00010001
37#define PING_MDM_CB_PROG 0x31000081
38#define PING_MDM_CB_VERS 0x00010001
39
40#define PING_MDM_NULL_PROC 0
41#define PING_MDM_RPC_GLUE_CODE_INFO_REMOTE_PROC 1
42#define PING_MDM_REGISTER_PROC 2
43#define PING_MDM_UNREGISTER_PROC 3
44#define PING_MDM_REGISTER_DATA_PROC 4
45#define PING_MDM_UNREGISTER_DATA_CB_PROC 5
46#define PING_MDM_REGISTER_DATA_CB_PROC 6
47
48#define PING_MDM_DATA_CB_PROC 1
49#define PING_MDM_CB_PROC 2
50
51#define PING_MAX_RETRY 5
52
53static struct msm_rpc_client *rpc_client;
54static uint32_t open_count;
55static DEFINE_MUTEX(ping_mdm_lock);
56
57struct ping_mdm_register_cb_arg {
58 uint32_t cb_id;
59 int val;
60};
61
62struct ping_mdm_register_data_cb_cb_arg {
63 uint32_t cb_id;
64 uint32_t *data;
65 uint32_t size;
66 uint32_t sum;
67};
68
69struct ping_mdm_register_data_cb_cb_ret {
70 uint32_t result;
71};
72
73static struct dentry *dent;
74static uint32_t test_res;
75static int reg_cb_num, reg_cb_num_req;
76static int data_cb_num, data_cb_num_req;
77static int reg_done_flag, data_cb_done_flag;
78static DECLARE_WAIT_QUEUE_HEAD(reg_test_wait);
79static DECLARE_WAIT_QUEUE_HEAD(data_cb_test_wait);
80
81enum {
82 PING_MODEM_NOT_IN_RESET = 0,
83 PING_MODEM_IN_RESET,
84 PING_LEAVING_RESET,
85 PING_MODEM_REGISTER_CB
86};
87static int fifo_event;
88static DEFINE_MUTEX(event_fifo_lock);
89static DEFINE_KFIFO(event_fifo, int, sizeof(int)*16);
90
91static int ping_mdm_register_cb(struct msm_rpc_client *client,
92 struct msm_rpc_xdr *xdr)
93{
94 int rc;
95 uint32_t accept_status;
96 struct ping_mdm_register_cb_arg arg;
97 void *cb_func;
98
99 xdr_recv_uint32(xdr, &arg.cb_id); /* cb_id */
100 xdr_recv_int32(xdr, &arg.val); /* val */
101
102 cb_func = msm_rpc_get_cb_func(client, arg.cb_id);
103 if (cb_func) {
104 rc = ((int (*)(struct ping_mdm_register_cb_arg *, void *))
105 cb_func)(&arg, NULL);
106 if (rc)
107 accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
108 else
109 accept_status = RPC_ACCEPTSTAT_SUCCESS;
110 } else
111 accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
112
113 xdr_start_accepted_reply(xdr, accept_status);
114 rc = xdr_send_msg(xdr);
115 if (rc)
116 pr_err("%s: send accepted reply failed: %d\n", __func__, rc);
117
118 return rc;
119}
120
121static int ping_mdm_data_cb(struct msm_rpc_client *client,
122 struct msm_rpc_xdr *xdr)
123{
124 int rc;
125 void *cb_func;
126 uint32_t size, accept_status;
127 struct ping_mdm_register_data_cb_cb_arg arg;
128 struct ping_mdm_register_data_cb_cb_ret ret;
129
130 xdr_recv_uint32(xdr, &arg.cb_id); /* cb_id */
131
132 /* data */
133 xdr_recv_array(xdr, (void **)(&(arg.data)), &size, 64,
134 sizeof(uint32_t), (void *)xdr_recv_uint32);
135
136 xdr_recv_uint32(xdr, &arg.size); /* size */
137 xdr_recv_uint32(xdr, &arg.sum); /* sum */
138
139 cb_func = msm_rpc_get_cb_func(client, arg.cb_id);
140 if (cb_func) {
141 rc = ((int (*)
142 (struct ping_mdm_register_data_cb_cb_arg *,
143 struct ping_mdm_register_data_cb_cb_ret *))
144 cb_func)(&arg, &ret);
145 if (rc)
146 accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
147 else
148 accept_status = RPC_ACCEPTSTAT_SUCCESS;
149 } else
150 accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
151
152 xdr_start_accepted_reply(xdr, accept_status);
153
154 if (accept_status == RPC_ACCEPTSTAT_SUCCESS)
155 xdr_send_uint32(xdr, &ret.result); /* result */
156
157 rc = xdr_send_msg(xdr);
158 if (rc)
159 pr_err("%s: send accepted reply failed: %d\n", __func__, rc);
160
161 kfree(arg.data);
162 return rc;
163}
164
165static int ping_mdm_cb_func(struct msm_rpc_client *client,
166 struct rpc_request_hdr *req,
167 struct msm_rpc_xdr *xdr)
168{
169 int rc = 0;
170
171 switch (req->procedure) {
172 case PING_MDM_CB_PROC:
173 rc = ping_mdm_register_cb(client, xdr);
174 break;
175 case PING_MDM_DATA_CB_PROC:
176 rc = ping_mdm_data_cb(client, xdr);
177 break;
178 default:
179 pr_err("%s: procedure not supported %d\n",
180 __func__, req->procedure);
181 xdr_start_accepted_reply(xdr, RPC_ACCEPTSTAT_PROC_UNAVAIL);
182 rc = xdr_send_msg(xdr);
183 if (rc)
184 pr_err("%s: sending reply failed: %d\n", __func__, rc);
185 break;
186 }
187 return rc;
188}
189
190struct ping_mdm_unregister_data_cb_arg {
191 int (*cb_func)(
192 struct ping_mdm_register_data_cb_cb_arg *arg,
193 struct ping_mdm_register_data_cb_cb_ret *ret);
194};
195
196struct ping_mdm_register_data_cb_arg {
197 int (*cb_func)(
198 struct ping_mdm_register_data_cb_cb_arg *arg,
199 struct ping_mdm_register_data_cb_cb_ret *ret);
200 uint32_t num;
201 uint32_t size;
202 uint32_t interval_ms;
203 uint32_t num_tasks;
204};
205
206struct ping_mdm_register_data_cb_ret {
207 uint32_t result;
208};
209
210struct ping_mdm_unregister_data_cb_ret {
211 uint32_t result;
212};
213
214static int ping_mdm_data_cb_register_arg(struct msm_rpc_client *client,
215 struct msm_rpc_xdr *xdr, void *data)
216{
217 struct ping_mdm_register_data_cb_arg *arg = data;
218 int cb_id;
219
220 cb_id = msm_rpc_add_cb_func(client, (void *)arg->cb_func);
221 if ((cb_id < 0) && (cb_id != MSM_RPC_CLIENT_NULL_CB_ID))
222 return cb_id;
223
224 xdr_send_uint32(xdr, &cb_id); /* cb_id */
225 xdr_send_uint32(xdr, &arg->num); /* num */
226 xdr_send_uint32(xdr, &arg->size); /* size */
227 xdr_send_uint32(xdr, &arg->interval_ms); /* interval_ms */
228 xdr_send_uint32(xdr, &arg->num_tasks); /* num_tasks */
229
230 return 0;
231}
232
233static int ping_mdm_data_cb_unregister_arg(struct msm_rpc_client *client,
234 struct msm_rpc_xdr *xdr, void *data)
235{
236 struct ping_mdm_unregister_data_cb_arg *arg = data;
237 int cb_id;
238
239 cb_id = msm_rpc_add_cb_func(client, (void *)arg->cb_func);
240 if ((cb_id < 0) && (cb_id != MSM_RPC_CLIENT_NULL_CB_ID))
241 return cb_id;
242
243 xdr_send_uint32(xdr, &cb_id); /* cb_id */
244
245 return 0;
246}
247
248static int ping_mdm_data_cb_register_ret(struct msm_rpc_client *client,
249 struct msm_rpc_xdr *xdr, void *data)
250{
251 struct ping_mdm_register_data_cb_ret *ret = data;
252
253 xdr_recv_uint32(xdr, &ret->result); /* result */
254
255 return 0;
256}
257
258static int ping_mdm_register_data_cb(
259 struct msm_rpc_client *client,
260 struct ping_mdm_register_data_cb_arg *arg,
261 struct ping_mdm_register_data_cb_ret *ret)
262{
263 return msm_rpc_client_req2(client,
264 PING_MDM_REGISTER_DATA_CB_PROC,
265 ping_mdm_data_cb_register_arg, arg,
266 ping_mdm_data_cb_register_ret, ret, -1);
267}
268
269static int ping_mdm_unregister_data_cb(
270 struct msm_rpc_client *client,
271 struct ping_mdm_unregister_data_cb_arg *arg,
272 struct ping_mdm_unregister_data_cb_ret *ret)
273{
274 return msm_rpc_client_req2(client,
275 PING_MDM_UNREGISTER_DATA_CB_PROC,
276 ping_mdm_data_cb_unregister_arg, arg,
277 ping_mdm_data_cb_register_ret, ret, -1);
278}
279
280struct ping_mdm_data_arg {
281 uint32_t *data;
282 uint32_t size;
283};
284
285struct ping_mdm_data_ret {
286 uint32_t result;
287};
288
289static int ping_mdm_data_register_arg(struct msm_rpc_client *client,
290 struct msm_rpc_xdr *xdr, void *data)
291{
292 struct ping_mdm_data_arg *arg = data;
293
294 /* data */
295 xdr_send_array(xdr, (void **)&arg->data, &arg->size, 64,
296 sizeof(uint32_t), (void *)xdr_send_uint32);
297
298 xdr_send_uint32(xdr, &arg->size); /* size */
299
300 return 0;
301}
302
303static int ping_mdm_data_register_ret(struct msm_rpc_client *client,
304 struct msm_rpc_xdr *xdr, void *data)
305{
306 struct ping_mdm_data_ret *ret = data;
307
308 xdr_recv_uint32(xdr, &ret->result); /* result */
309
310 return 0;
311}
312
313static int ping_mdm_data_register(
314 struct msm_rpc_client *client,
315 struct ping_mdm_data_arg *arg,
316 struct ping_mdm_data_ret *ret)
317{
318 return msm_rpc_client_req2(client,
319 PING_MDM_REGISTER_DATA_PROC,
320 ping_mdm_data_register_arg, arg,
321 ping_mdm_data_register_ret, ret, -1);
322}
323
324struct ping_mdm_register_arg {
325 int (*cb_func)(struct ping_mdm_register_cb_arg *, void *);
326 int num;
327};
328
329struct ping_mdm_unregister_arg {
330 int (*cb_func)(struct ping_mdm_register_cb_arg *, void *);
331};
332
333struct ping_mdm_register_ret {
334 uint32_t result;
335};
336
337struct ping_mdm_unregister_ret {
338 uint32_t result;
339};
340
341static int ping_mdm_register_arg(struct msm_rpc_client *client,
342 struct msm_rpc_xdr *xdr, void *data)
343{
344 struct ping_mdm_register_arg *arg = data;
345 int cb_id;
346
347 cb_id = msm_rpc_add_cb_func(client, (void *)arg->cb_func);
348 if ((cb_id < 0) && (cb_id != MSM_RPC_CLIENT_NULL_CB_ID))
349 return cb_id;
350
351 xdr_send_uint32(xdr, &cb_id); /* cb_id */
352 xdr_send_uint32(xdr, &arg->num); /* num */
353
354 return 0;
355}
356
357static int ping_mdm_unregister_arg(struct msm_rpc_client *client,
358 struct msm_rpc_xdr *xdr, void *data)
359{
360 struct ping_mdm_unregister_arg *arg = data;
361 int cb_id;
362
363 cb_id = msm_rpc_add_cb_func(client, (void *)arg->cb_func);
364 if ((cb_id < 0) && (cb_id != MSM_RPC_CLIENT_NULL_CB_ID))
365 return cb_id;
366
367 xdr_send_uint32(xdr, &cb_id); /* cb_id */
368
369 return 0;
370}
371
372static int ping_mdm_register_ret(struct msm_rpc_client *client,
373 struct msm_rpc_xdr *xdr, void *data)
374{
375 struct ping_mdm_register_ret *ret = data;
376
377 xdr_recv_uint32(xdr, &ret->result); /* result */
378
379 return 0;
380}
381
382static int ping_mdm_register(
383 struct msm_rpc_client *client,
384 struct ping_mdm_register_arg *arg,
385 struct ping_mdm_register_ret *ret)
386{
387 return msm_rpc_client_req2(client,
388 PING_MDM_REGISTER_PROC,
389 ping_mdm_register_arg, arg,
390 ping_mdm_register_ret, ret, -1);
391}
392
393static int ping_mdm_unregister(
394 struct msm_rpc_client *client,
395 struct ping_mdm_unregister_arg *arg,
396 struct ping_mdm_unregister_ret *ret)
397{
398 return msm_rpc_client_req2(client,
399 PING_MDM_UNREGISTER_PROC,
400 ping_mdm_unregister_arg, arg,
401 ping_mdm_register_ret, ret, -1);
402}
403
404static int ping_mdm_null(struct msm_rpc_client *client,
405 void *arg, void *ret)
406{
407 return msm_rpc_client_req2(client, PING_MDM_NULL_PROC,
408 NULL, NULL, NULL, NULL, -1);
409}
410
411static int ping_mdm_close(void)
412{
413 mutex_lock(&ping_mdm_lock);
414 if (--open_count == 0) {
415 msm_rpc_unregister_client(rpc_client);
416 pr_info("%s: disconnected from remote ping server\n",
417 __func__);
418 }
419 mutex_unlock(&ping_mdm_lock);
420 return 0;
421}
422
423static void handle_restart_teardown(struct msm_rpc_client *client)
424{
425 int event = PING_MODEM_IN_RESET;
426
427 pr_info("%s: modem in reset\n", __func__);
428
429 mutex_lock(&event_fifo_lock);
430 kfifo_in(&event_fifo, &event, sizeof(event));
431 fifo_event = 1;
432 mutex_unlock(&event_fifo_lock);
433
434 wake_up(&data_cb_test_wait);
435}
436
437static void handle_restart_setup(struct msm_rpc_client *client)
438{
439 int event = PING_LEAVING_RESET;
440
441 pr_info("%s: modem leaving reset\n", __func__);
442
443 mutex_lock(&event_fifo_lock);
444 kfifo_in(&event_fifo, &event, sizeof(event));
445 fifo_event = 1;
446 mutex_unlock(&event_fifo_lock);
447
448 wake_up(&data_cb_test_wait);
449}
450
451static struct msm_rpc_client *ping_mdm_init(void)
452{
453 mutex_lock(&ping_mdm_lock);
454 if (open_count == 0) {
455 rpc_client = msm_rpc_register_client2("pingdef",
456 PING_MDM_PROG,
457 PING_MDM_VERS, 1,
458 ping_mdm_cb_func);
459 if (!IS_ERR(rpc_client)) {
460 open_count++;
461 msm_rpc_register_reset_callbacks(rpc_client,
462 handle_restart_teardown,
463 handle_restart_setup);
464 }
465 }
466 mutex_unlock(&ping_mdm_lock);
467 return rpc_client;
468}
469
470static int ping_mdm_data_register_test(void)
471{
472 int i, rc = 0;
473 uint32_t my_data[64];
474 uint32_t my_sum = 0;
475 struct ping_mdm_data_arg data_arg;
476 struct ping_mdm_data_ret data_ret;
477
478 for (i = 0; i < 64; i++) {
479 my_data[i] = (42 + i);
480 my_sum ^= (42 + i);
481 }
482
483 data_arg.data = my_data;
484 data_arg.size = 64;
485
486 rc = ping_mdm_data_register(rpc_client, &data_arg, &data_ret);
487 if (rc)
488 return rc;
489
490 if (my_sum != data_ret.result) {
491 pr_err("%s: sum mismatch %d %d\n",
492 __func__, my_sum, data_ret.result);
493 rc = -1;
494 }
495
496 return rc;
497}
498
499static int ping_mdm_test_register_data_cb(
500 struct ping_mdm_register_data_cb_cb_arg *arg,
501 struct ping_mdm_register_data_cb_cb_ret *ret)
502{
503 uint32_t i, sum = 0;
504
505 data_cb_num++;
506
507 pr_info("%s: received cb_id %d, size = %d, sum = %u, num = %u of %u\n",
508 __func__, arg->cb_id, arg->size, arg->sum, data_cb_num,
509 data_cb_num_req);
510
511 if (arg->data)
512 for (i = 0; i < arg->size; i++)
513 sum ^= arg->data[i];
514
515 if (sum != arg->sum)
516 pr_err("%s: sum mismatch %u %u\n", __func__, sum, arg->sum);
517
518 if (data_cb_num == data_cb_num_req) {
519 data_cb_done_flag = 1;
520 wake_up(&data_cb_test_wait);
521 }
522
523 ret->result = 1;
524 return 0;
525}
526
527static int ping_mdm_data_cb_register(
528 struct ping_mdm_register_data_cb_ret *reg_ret)
529{
530 int rc;
531 struct ping_mdm_register_data_cb_arg reg_arg;
532
533 reg_arg.cb_func = ping_mdm_test_register_data_cb;
534 reg_arg.num = data_cb_num_req - data_cb_num;
535 reg_arg.size = 64;
536 reg_arg.interval_ms = 10;
537 reg_arg.num_tasks = 1;
538
539 pr_info("%s: registering callback\n", __func__);
540 rc = ping_mdm_register_data_cb(rpc_client, &reg_arg, reg_ret);
541 if (rc)
542 pr_err("%s: failed to register callback %d\n", __func__, rc);
543
544 return rc;
545}
546
547
548static void retry_timer_cb(unsigned long data)
549{
550 int event = (int)data;
551
552 pr_info("%s: retry timer triggered\n", __func__);
553
554 mutex_lock(&event_fifo_lock);
555 kfifo_in(&event_fifo, &event, sizeof(event));
556 fifo_event = 1;
557 mutex_unlock(&event_fifo_lock);
558
559 wake_up(&data_cb_test_wait);
560}
561
562static int ping_mdm_data_cb_register_test(void)
563{
564 int rc;
565 int event;
566 int retry_count = 0;
567 struct ping_mdm_register_data_cb_ret reg_ret;
568 struct ping_mdm_unregister_data_cb_arg unreg_arg;
569 struct ping_mdm_unregister_data_cb_ret unreg_ret;
570 struct timer_list retry_timer;
571
572 mutex_init(&event_fifo_lock);
573 init_timer(&retry_timer);
574
575 data_cb_done_flag = 0;
576 data_cb_num = 0;
577 if (!data_cb_num_req)
578 data_cb_num_req = 10;
579
580 rc = ping_mdm_data_cb_register(&reg_ret);
581 if (rc)
582 return rc;
583
584 pr_info("%s: data_cb_register result: 0x%x\n",
585 __func__, reg_ret.result);
586
587 while (!data_cb_done_flag) {
588 wait_event(data_cb_test_wait, data_cb_done_flag || fifo_event);
589 fifo_event = 0;
590
591 for (;;) {
592 mutex_lock(&event_fifo_lock);
593
594 if (kfifo_is_empty(&event_fifo)) {
595 mutex_unlock(&event_fifo_lock);
596 break;
597 }
598 rc = kfifo_out(&event_fifo, &event, sizeof(event));
599 mutex_unlock(&event_fifo_lock);
600 BUG_ON(rc != sizeof(event));
601
602 pr_info("%s: processing event data_cb_done_flag=%d,event=%d\n",
603 __func__, data_cb_done_flag, event);
604
605 if (event == PING_MODEM_IN_RESET) {
606 pr_info("%s: modem entering reset\n", __func__);
607 retry_count = 0;
608 } else if (event == PING_LEAVING_RESET) {
609 pr_info("%s: modem exiting reset - "
610 "re-registering cb\n", __func__);
611
612 rc = ping_mdm_data_cb_register(&reg_ret);
613 if (rc) {
614 retry_count++;
615 if (retry_count < PING_MAX_RETRY) {
616 pr_info("%s: retry %d failed\n",
617 __func__, retry_count);
618
619 retry_timer.expires = jiffies +
620 msecs_to_jiffies(1000);
621 retry_timer.data =
622 PING_LEAVING_RESET;
623 retry_timer.function =
624 retry_timer_cb;
625 add_timer(&retry_timer);
626 } else {
627 pr_err("%s: max retries exceeded, aborting\n",
628 __func__);
629 return -ENETRESET;
630 }
631 } else
632 pr_info("%s: data_cb_register result: 0x%x\n",
633 __func__, reg_ret.result);
634 }
635 }
636 }
637
638 while (del_timer(&retry_timer))
639 ;
640
641 unreg_arg.cb_func = ping_mdm_test_register_data_cb;
642 rc = ping_mdm_unregister_data_cb(rpc_client, &unreg_arg, &unreg_ret);
643 if (rc)
644 return rc;
645
646 pr_info("%s: data_cb_unregister result: 0x%x\n",
647 __func__, unreg_ret.result);
648
649 pr_info("%s: Test completed\n", __func__);
650
651 return 0;
652}
653
654static int ping_mdm_test_register_cb(
655 struct ping_mdm_register_cb_arg *arg, void *ret)
656{
657 pr_info("%s: received cb_id %d, val = %d\n",
658 __func__, arg->cb_id, arg->val);
659
660 reg_cb_num++;
661 if (reg_cb_num == reg_cb_num_req) {
662 reg_done_flag = 1;
663 wake_up(&reg_test_wait);
664 }
665 return 0;
666}
667
668static int ping_mdm_register_test(void)
669{
670 int rc = 0;
671 struct ping_mdm_register_arg reg_arg;
672 struct ping_mdm_unregister_arg unreg_arg;
673 struct ping_mdm_register_ret reg_ret;
674 struct ping_mdm_unregister_ret unreg_ret;
675
676 reg_cb_num = 0;
677 reg_cb_num_req = 10;
678 reg_done_flag = 0;
679
680 reg_arg.num = 10;
681 reg_arg.cb_func = ping_mdm_test_register_cb;
682
683 rc = ping_mdm_register(rpc_client, &reg_arg, &reg_ret);
684 if (rc)
685 return rc;
686
687 pr_info("%s: register result: 0x%x\n",
688 __func__, reg_ret.result);
689
690 wait_event(reg_test_wait, reg_done_flag);
691
692 unreg_arg.cb_func = ping_mdm_test_register_cb;
693 rc = ping_mdm_unregister(rpc_client, &unreg_arg, &unreg_ret);
694 if (rc)
695 return rc;
696
697 pr_info("%s: unregister result: 0x%x\n",
698 __func__, unreg_ret.result);
699
700 return 0;
701}
702
703static int ping_mdm_null_test(void)
704{
705 return ping_mdm_null(rpc_client, NULL, NULL);
706}
707
708static int ping_test_release(struct inode *ip, struct file *fp)
709{
710 return ping_mdm_close();
711}
712
713static int ping_test_open(struct inode *ip, struct file *fp)
714{
715 struct msm_rpc_client *client;
716
717 client = ping_mdm_init();
718 if (IS_ERR(client)) {
719 pr_err("%s: couldn't open ping client\n", __func__);
720 return PTR_ERR(client);
721 } else
722 pr_info("%s: connected to remote ping server\n",
723 __func__);
724
725 return 0;
726}
727
728static ssize_t ping_test_read(struct file *fp, char __user *buf,
729 size_t count, loff_t *pos)
730{
731 char _buf[16];
732
733 snprintf(_buf, sizeof(_buf), "%i\n", test_res);
734
735 return simple_read_from_buffer(buf, count, pos, _buf, strlen(_buf));
736}
737
738static ssize_t ping_test_write(struct file *fp, const char __user *buf,
739 size_t count, loff_t *pos)
740{
741 unsigned char cmd[64];
742 int len;
743
744 if (count < 1)
745 return 0;
746
747 len = count > 63 ? 63 : count;
748
749 if (copy_from_user(cmd, buf, len))
750 return -EFAULT;
751
752 cmd[len] = 0;
753
754 /* lazy */
755 if (cmd[len-1] == '\n') {
756 cmd[len-1] = 0;
757 len--;
758 }
759
760 if (!strncmp(cmd, "null_test", 64))
761 test_res = ping_mdm_null_test();
762 else if (!strncmp(cmd, "reg_test", 64))
763 test_res = ping_mdm_register_test();
764 else if (!strncmp(cmd, "data_reg_test", 64))
765 test_res = ping_mdm_data_register_test();
766 else if (!strncmp(cmd, "data_cb_reg_test", 64))
767 test_res = ping_mdm_data_cb_register_test();
768 else if (!strncmp(cmd, "count=", 6)) {
769 long tmp;
770
771 if (strict_strtol(cmd + 6, 0, &tmp) == 0) {
772 data_cb_num_req = tmp;
773 pr_info("Set repetition count to %d\n",
774 data_cb_num_req);
775 } else {
776 data_cb_num_req = 10;
777 pr_err("invalid number %s, defaulting to %d\n",
778 cmd + 6, data_cb_num_req);
779 }
780 }
781 else
782 test_res = -EINVAL;
783
784 return count;
785}
786
787static const struct file_operations debug_ops = {
788 .owner = THIS_MODULE,
789 .open = ping_test_open,
790 .read = ping_test_read,
791 .write = ping_test_write,
792 .release = ping_test_release,
793};
794
795static void __exit ping_test_exit(void)
796{
797 debugfs_remove(dent);
798}
799
800static int __init ping_test_init(void)
801{
802 dent = debugfs_create_file("ping_mdm", 0444, 0, NULL, &debug_ops);
803 test_res = 0;
804 open_count = 0;
805 return 0;
806}
807
808module_init(ping_test_init);
809module_exit(ping_test_exit);
810
811MODULE_DESCRIPTION("PING TEST Driver");
812MODULE_LICENSE("GPL v2");