blob: 478eb1fabd95c043ac33f6c2cd0819d71dc4d883 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/rpc_servers.c
2 *
3 * Copyright (C) 2007 Google, Inc.
Duy Truong790f06d2013-02-13 16:38:12 -08004 * Copyright (c) 2009-2010, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07005 * Author: Iliyan Malchev <ibm@android.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/slab.h>
19#include <linux/module.h>
20#include <linux/kernel.h>
21#include <linux/string.h>
22#include <linux/errno.h>
23#include <linux/cdev.h>
24#include <linux/init.h>
25#include <linux/device.h>
26#include <linux/types.h>
27#include <linux/fs.h>
28#include <linux/kthread.h>
29#include <linux/delay.h>
30#include <linux/platform_device.h>
31#include <linux/wakelock.h>
32
33#include <linux/msm_rpcrouter.h>
34#include <linux/uaccess.h>
35
36#include <mach/msm_rpcrouter.h>
37#include "smd_rpcrouter.h"
38
39static struct msm_rpc_endpoint *endpoint;
40
41#define FLAG_REGISTERED 0x0001
42
43static LIST_HEAD(rpc_server_list);
44static DEFINE_MUTEX(rpc_server_list_lock);
45static int rpc_servers_active;
46static struct wake_lock rpc_servers_wake_lock;
47static struct msm_rpc_xdr server_xdr;
48static uint32_t current_xid;
49
50static void rpc_server_register(struct msm_rpc_server *server)
51{
52 int rc;
53 rc = msm_rpc_register_server(endpoint, server->prog, server->vers);
54 if (rc < 0)
55 printk(KERN_ERR "[rpcserver] error registering %p @ %08x:%d\n",
56 server, server->prog, server->vers);
57}
58
59static struct msm_rpc_server *rpc_server_find(uint32_t prog, uint32_t vers)
60{
61 struct msm_rpc_server *server;
62
63 mutex_lock(&rpc_server_list_lock);
64 list_for_each_entry(server, &rpc_server_list, list) {
65 if ((server->prog == prog) &&
66 msm_rpc_is_compatible_version(server->vers, vers)) {
67 mutex_unlock(&rpc_server_list_lock);
68 return server;
69 }
70 }
71 mutex_unlock(&rpc_server_list_lock);
72 return NULL;
73}
74
75static void rpc_server_register_all(void)
76{
77 struct msm_rpc_server *server;
78
79 mutex_lock(&rpc_server_list_lock);
80 list_for_each_entry(server, &rpc_server_list, list) {
81 if (!(server->flags & FLAG_REGISTERED)) {
82 rpc_server_register(server);
83 server->flags |= FLAG_REGISTERED;
84 }
85 }
86 mutex_unlock(&rpc_server_list_lock);
87}
88
89int msm_rpc_create_server(struct msm_rpc_server *server)
90{
91 void *buf;
92
93 /* make sure we're in a sane state first */
94 server->flags = 0;
95 INIT_LIST_HEAD(&server->list);
96 mutex_init(&server->cb_req_lock);
97
98 server->version = 1;
99
100 xdr_init(&server->cb_xdr);
101 buf = kmalloc(MSM_RPC_MSGSIZE_MAX, GFP_KERNEL);
102 if (!buf)
103 return -ENOMEM;
104
105 xdr_init_output(&server->cb_xdr, buf, MSM_RPC_MSGSIZE_MAX);
106
107 server->cb_ept = server->cb_xdr.ept = msm_rpc_open();
108 if (IS_ERR(server->cb_ept)) {
109 xdr_clean_output(&server->cb_xdr);
110 return PTR_ERR(server->cb_ept);
111 }
112
113 server->cb_ept->flags = MSM_RPC_UNINTERRUPTIBLE;
114 server->cb_ept->dst_prog = cpu_to_be32(server->prog | 0x01000000);
115 server->cb_ept->dst_vers = cpu_to_be32(server->vers);
116
117 mutex_lock(&rpc_server_list_lock);
118 list_add(&server->list, &rpc_server_list);
119 if (rpc_servers_active) {
120 rpc_server_register(server);
121 server->flags |= FLAG_REGISTERED;
122 }
123 mutex_unlock(&rpc_server_list_lock);
124
125 return 0;
126}
127EXPORT_SYMBOL(msm_rpc_create_server);
128
129int msm_rpc_create_server2(struct msm_rpc_server *server)
130{
131 int rc;
132
133 rc = msm_rpc_create_server(server);
134 server->version = 2;
135
136 return rc;
137}
138EXPORT_SYMBOL(msm_rpc_create_server2);
139
140static int rpc_send_accepted_void_reply(struct msm_rpc_endpoint *client,
141 uint32_t xid, uint32_t accept_status)
142{
143 int rc = 0;
144 uint8_t reply_buf[sizeof(struct rpc_reply_hdr)];
145 struct rpc_reply_hdr *reply = (struct rpc_reply_hdr *)reply_buf;
146
147 reply->xid = cpu_to_be32(xid);
148 reply->type = cpu_to_be32(1); /* reply */
149 reply->reply_stat = cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
150
151 reply->data.acc_hdr.accept_stat = cpu_to_be32(accept_status);
152 reply->data.acc_hdr.verf_flavor = 0;
153 reply->data.acc_hdr.verf_length = 0;
154
155 rc = msm_rpc_write(client, reply_buf, sizeof(reply_buf));
156 if (rc == -ENETRESET) {
157 /* Modem restarted, drop reply, clear state */
158 msm_rpc_clear_netreset(client);
159 }
160 if (rc < 0)
161 printk(KERN_ERR
162 "%s: could not write response: %d\n",
163 __FUNCTION__, rc);
164
165 return rc;
166}
167
168/*
169 * Interface to be used to start accepted reply message for a
170 * request. Returns the buffer pointer to attach any payload.
171 * Should call msm_rpc_server_send_accepted_reply to complete sending
172 * reply. Marshaling should be handled by user for the payload.
173 *
174 * server: pointer to server data structure
175 *
176 * xid: transaction id. Has to be same as the one in request.
177 *
178 * accept_status: acceptance status
179 *
180 * Return Value:
181 * pointer to buffer to attach the payload.
182 */
183void *msm_rpc_server_start_accepted_reply(struct msm_rpc_server *server,
184 uint32_t xid, uint32_t accept_status)
185{
186 struct rpc_reply_hdr *reply;
187
188 mutex_lock(&server_xdr.out_lock);
189
190 reply = (struct rpc_reply_hdr *)server_xdr.out_buf;
191
192 reply->xid = cpu_to_be32(xid);
193 reply->type = cpu_to_be32(1); /* reply */
194 reply->reply_stat = cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
195
196 reply->data.acc_hdr.accept_stat = cpu_to_be32(accept_status);
197 reply->data.acc_hdr.verf_flavor = 0;
198 reply->data.acc_hdr.verf_length = 0;
199
200 server_xdr.out_index += sizeof(*reply);
201
202 return reply + 1;
203}
204EXPORT_SYMBOL(msm_rpc_server_start_accepted_reply);
205
206/*
207 * Interface to be used to send accepted reply for a request.
208 * msm_rpc_server_start_accepted_reply should have been called before.
209 * Marshaling should be handled by user for the payload.
210 *
211 * server: pointer to server data structure
212 *
213 * size: additional payload size
214 *
215 * Return Value:
216 * 0 on success, otherwise returns an error code.
217 */
218int msm_rpc_server_send_accepted_reply(struct msm_rpc_server *server,
219 uint32_t size)
220{
221 int rc = 0;
222
223 server_xdr.out_index += size;
224 rc = msm_rpc_write(endpoint, server_xdr.out_buf,
225 server_xdr.out_index);
226 if (rc > 0)
227 rc = 0;
228
229 mutex_unlock(&server_xdr.out_lock);
230 return rc;
231}
232EXPORT_SYMBOL(msm_rpc_server_send_accepted_reply);
233
234/*
235 * Interface to be used to send a server callback request.
236 * If the request takes any arguments or expects any return, the user
237 * should handle it in 'arg_func' and 'ret_func' respectively.
238 * Marshaling and Unmarshaling should be handled by the user in argument
239 * and return functions.
240 *
241 * server: pointer to server data sturcture
242 *
243 * clnt_info: pointer to client information data structure.
244 * callback will be sent to this client.
245 *
246 * cb_proc: callback procedure being requested
247 *
248 * arg_func: argument function pointer. 'buf' is where arguments needs to
249 * be filled. 'data' is arg_data.
250 *
251 * ret_func: return function pointer. 'buf' is where returned data should
252 * be read from. 'data' is ret_data.
253 *
254 * arg_data: passed as an input parameter to argument function.
255 *
256 * ret_data: passed as an input parameter to return function.
257 *
258 * timeout: timeout for reply wait in jiffies. If negative timeout is
259 * specified a default timeout of 10s is used.
260 *
261 * Return Value:
262 * 0 on success, otherwise an error code is returned.
263 */
264int msm_rpc_server_cb_req(struct msm_rpc_server *server,
265 struct msm_rpc_client_info *clnt_info,
266 uint32_t cb_proc,
267 int (*arg_func)(struct msm_rpc_server *server,
268 void *buf, void *data),
269 void *arg_data,
270 int (*ret_func)(struct msm_rpc_server *server,
271 void *buf, void *data),
272 void *ret_data, long timeout)
273{
274 struct rpc_reply_hdr *rpc_rsp;
275 void *buffer;
276 int rc = 0;
277 uint32_t req_xid;
278
279 if (!clnt_info)
280 return -EINVAL;
281
282 mutex_lock(&server->cb_req_lock);
283
284 msm_rpc_setup_req((struct rpc_request_hdr *)server->cb_xdr.out_buf,
285 (server->prog | 0x01000000),
286 be32_to_cpu(clnt_info->vers), cb_proc);
287 server->cb_xdr.out_index = sizeof(struct rpc_request_hdr);
288 req_xid = *(uint32_t *)server->cb_xdr.out_buf;
289
290 if (arg_func) {
291 rc = arg_func(server, (void *)((struct rpc_request_hdr *)
292 server->cb_xdr.out_buf + 1),
293 arg_data);
294 if (rc < 0)
295 goto release_locks;
296 else
297 server->cb_xdr.out_index += rc;
298 }
299
300 server->cb_ept->dst_pid = clnt_info->pid;
301 server->cb_ept->dst_cid = clnt_info->cid;
302 rc = msm_rpc_write(server->cb_ept, server->cb_xdr.out_buf,
303 server->cb_xdr.out_index);
304 if (rc < 0) {
305 pr_err("%s: couldn't send RPC CB request:%d\n", __func__, rc);
306 goto release_locks;
307 } else
308 rc = 0;
309
310 if (timeout < 0)
311 timeout = msecs_to_jiffies(10000);
312
313 do {
314 buffer = NULL;
315 rc = msm_rpc_read(server->cb_ept, &buffer, -1, timeout);
316 xdr_init_input(&server->cb_xdr, buffer, rc);
317 if ((rc < ((int)(sizeof(uint32_t) * 2))) ||
318 (be32_to_cpu(*((uint32_t *)buffer + 1)) != 1)) {
319 printk(KERN_ERR "%s: Invalid reply: %d\n",
320 __func__, rc);
321 goto free_and_release;
322 }
323
324 rpc_rsp = (struct rpc_reply_hdr *)server->cb_xdr.in_buf;
325 if (req_xid != rpc_rsp->xid) {
326 pr_info("%s: xid mismatch, req %d reply %d\n",
327 __func__, be32_to_cpu(req_xid),
328 be32_to_cpu(rpc_rsp->xid));
329 xdr_clean_input(&server->cb_xdr);
330 rc = timeout;
331 /* timeout is not adjusted, but it is not critical */
332 } else
333 rc = 0;
334 } while (rc);
335
336 if (be32_to_cpu(rpc_rsp->reply_stat) != RPCMSG_REPLYSTAT_ACCEPTED) {
337 pr_err("%s: RPC cb req was denied! %d\n", __func__,
338 be32_to_cpu(rpc_rsp->reply_stat));
339 rc = -EPERM;
340 goto free_and_release;
341 }
342
343 if (be32_to_cpu(rpc_rsp->data.acc_hdr.accept_stat) !=
344 RPC_ACCEPTSTAT_SUCCESS) {
345 pr_err("%s: RPC cb req was not successful (%d)\n", __func__,
346 be32_to_cpu(rpc_rsp->data.acc_hdr.accept_stat));
347 rc = -EINVAL;
348 goto free_and_release;
349 }
350
351 if (ret_func)
352 rc = ret_func(server, (void *)(rpc_rsp + 1), ret_data);
353
354free_and_release:
355 xdr_clean_input(&server->cb_xdr);
356 server->cb_xdr.out_index = 0;
357release_locks:
358 mutex_unlock(&server->cb_req_lock);
359 return rc;
360}
361EXPORT_SYMBOL(msm_rpc_server_cb_req);
362
363/*
364 * Interface to be used to send a server callback request.
365 * If the request takes any arguments or expects any return, the user
366 * should handle it in 'arg_func' and 'ret_func' respectively.
367 * Marshaling and Unmarshaling should be handled by the user in argument
368 * and return functions.
369 *
370 * server: pointer to server data sturcture
371 *
372 * clnt_info: pointer to client information data structure.
373 * callback will be sent to this client.
374 *
375 * cb_proc: callback procedure being requested
376 *
377 * arg_func: argument function pointer. 'xdr' is the xdr being used.
378 * 'data' is arg_data.
379 *
380 * ret_func: return function pointer. 'xdr' is the xdr being used.
381 * 'data' is ret_data.
382 *
383 * arg_data: passed as an input parameter to argument function.
384 *
385 * ret_data: passed as an input parameter to return function.
386 *
387 * timeout: timeout for reply wait in jiffies. If negative timeout is
388 * specified a default timeout of 10s is used.
389 *
390 * Return Value:
391 * 0 on success, otherwise an error code is returned.
392 */
393int msm_rpc_server_cb_req2(struct msm_rpc_server *server,
394 struct msm_rpc_client_info *clnt_info,
395 uint32_t cb_proc,
396 int (*arg_func)(struct msm_rpc_server *server,
397 struct msm_rpc_xdr *xdr, void *data),
398 void *arg_data,
399 int (*ret_func)(struct msm_rpc_server *server,
400 struct msm_rpc_xdr *xdr, void *data),
401 void *ret_data, long timeout)
402{
403 int size = 0;
404 struct rpc_reply_hdr rpc_rsp;
405 void *buffer;
406 int rc = 0;
407 uint32_t req_xid;
408
409 if (!clnt_info)
410 return -EINVAL;
411
412 mutex_lock(&server->cb_req_lock);
413
414 xdr_start_request(&server->cb_xdr, (server->prog | 0x01000000),
415 be32_to_cpu(clnt_info->vers), cb_proc);
416 req_xid = be32_to_cpu(*(uint32_t *)server->cb_xdr.out_buf);
417 if (arg_func) {
418 rc = arg_func(server, &server->cb_xdr, arg_data);
419 if (rc < 0)
420 goto release_locks;
421 else
422 size += rc;
423 }
424
425 server->cb_ept->dst_pid = clnt_info->pid;
426 server->cb_ept->dst_cid = clnt_info->cid;
427 rc = xdr_send_msg(&server->cb_xdr);
428 if (rc < 0) {
429 pr_err("%s: couldn't send RPC CB request:%d\n", __func__, rc);
430 goto release_locks;
431 } else
432 rc = 0;
433
434 if (timeout < 0)
435 timeout = msecs_to_jiffies(10000);
436
437 do {
438 buffer = NULL;
439 rc = msm_rpc_read(server->cb_ept, &buffer, -1, timeout);
440 if (rc < 0) {
441 server->cb_xdr.out_index = 0;
442 goto release_locks;
443 }
444
445 xdr_init_input(&server->cb_xdr, buffer, rc);
446 rc = xdr_recv_reply(&server->cb_xdr, &rpc_rsp);
447 if (rc || (rpc_rsp.type != 1)) {
448 printk(KERN_ERR "%s: Invalid reply :%d\n",
449 __func__, rc);
450 rc = -EINVAL;
451 goto free_and_release;
452 }
453
454 if (req_xid != rpc_rsp.xid) {
455 pr_info("%s: xid mismatch, req %d reply %d\n",
456 __func__, req_xid, rpc_rsp.xid);
457 xdr_clean_input(&server->cb_xdr);
458 rc = timeout;
459 /* timeout is not adjusted, but it is not critical */
460 } else
461 rc = 0;
462
463 } while (rc);
464
465 if (rpc_rsp.reply_stat != RPCMSG_REPLYSTAT_ACCEPTED) {
466 pr_err("%s: RPC cb req was denied! %d\n", __func__,
467 rpc_rsp.reply_stat);
468 rc = -EPERM;
469 goto free_and_release;
470 }
471
472 if (rpc_rsp.data.acc_hdr.accept_stat != RPC_ACCEPTSTAT_SUCCESS) {
473 pr_err("%s: RPC cb req was not successful (%d)\n", __func__,
474 rpc_rsp.data.acc_hdr.accept_stat);
475 rc = -EINVAL;
476 goto free_and_release;
477 }
478
479 if (ret_func)
480 rc = ret_func(server, &server->cb_xdr, ret_data);
481
482free_and_release:
483 xdr_clean_input(&server->cb_xdr);
484 server->cb_xdr.out_index = 0;
485release_locks:
486 mutex_unlock(&server->cb_req_lock);
487 return rc;
488}
489EXPORT_SYMBOL(msm_rpc_server_cb_req2);
490
491void msm_rpc_server_get_requesting_client(struct msm_rpc_client_info *clnt_info)
492{
493 if (!clnt_info)
494 return;
495
496 get_requesting_client(endpoint, current_xid, clnt_info);
497}
498
499static int rpc_servers_thread(void *data)
500{
501 void *buffer, *buf;
502 struct rpc_request_hdr req;
503 struct rpc_request_hdr *req1;
504 struct msm_rpc_server *server;
505 int rc;
506
507 xdr_init(&server_xdr);
508 server_xdr.ept = endpoint;
509
510 buf = kmalloc(MSM_RPC_MSGSIZE_MAX, GFP_KERNEL);
511 if (!buf)
512 return -ENOMEM;
513
514 xdr_init_output(&server_xdr, buf, MSM_RPC_MSGSIZE_MAX);
515
516 for (;;) {
517 wake_unlock(&rpc_servers_wake_lock);
518 rc = wait_event_interruptible(endpoint->wait_q,
519 !list_empty(&endpoint->read_q));
520 wake_lock(&rpc_servers_wake_lock);
521
522 rc = msm_rpc_read(endpoint, &buffer, -1, -1);
523 if (rc < 0) {
524 printk(KERN_ERR "%s: could not read: %d\n",
525 __FUNCTION__, rc);
526 break;
527 }
528
529 req1 = (struct rpc_request_hdr *)buffer;
530 current_xid = req1->xid;
531
532 xdr_init_input(&server_xdr, buffer, rc);
533 xdr_recv_req(&server_xdr, &req);
534
535 server = rpc_server_find(req.prog, req.vers);
536
537 if (req.rpc_vers != 2)
538 goto free_buffer;
539 if (req.type != 0)
540 goto free_buffer;
541 if (!server) {
542 rpc_send_accepted_void_reply(
543 endpoint, req.xid,
544 RPC_ACCEPTSTAT_PROG_UNAVAIL);
545 goto free_buffer;
546 }
547
548 if (server->version == 2)
549 rc = server->rpc_call2(server, &req, &server_xdr);
550 else {
551 req1->type = be32_to_cpu(req1->type);
552 req1->xid = be32_to_cpu(req1->xid);
553 req1->rpc_vers = be32_to_cpu(req1->rpc_vers);
554 req1->prog = be32_to_cpu(req1->prog);
555 req1->vers = be32_to_cpu(req1->vers);
556 req1->procedure = be32_to_cpu(req1->procedure);
557
558 rc = server->rpc_call(server, req1, rc);
559 }
560
561 if (rc == 0) {
562 msm_rpc_server_start_accepted_reply(
563 server, req.xid,
564 RPC_ACCEPTSTAT_SUCCESS);
565 msm_rpc_server_send_accepted_reply(server, 0);
566 } else if (rc < 0) {
567 msm_rpc_server_start_accepted_reply(
568 server, req.xid,
569 RPC_ACCEPTSTAT_PROC_UNAVAIL);
570 msm_rpc_server_send_accepted_reply(server, 0);
571 }
572 free_buffer:
573 xdr_clean_input(&server_xdr);
574 server_xdr.out_index = 0;
575 }
576 do_exit(0);
577}
578
579static int rpcservers_probe(struct platform_device *pdev)
580{
581 struct task_struct *server_thread;
582
583 endpoint = msm_rpc_open();
584 if (IS_ERR(endpoint))
585 return PTR_ERR(endpoint);
586
587 /* we're online -- register any servers installed beforehand */
588 rpc_servers_active = 1;
589 current_xid = 0;
590 rpc_server_register_all();
591
592 /* start the kernel thread */
593 server_thread = kthread_run(rpc_servers_thread, NULL, "krpcserversd");
594 if (IS_ERR(server_thread))
595 return PTR_ERR(server_thread);
596
597 return 0;
598}
599
600static struct platform_driver rpcservers_driver = {
601 .probe = rpcservers_probe,
602 .driver = {
603 .name = "oncrpc_router",
604 .owner = THIS_MODULE,
605 },
606};
607
608static int __init rpc_servers_init(void)
609{
610 wake_lock_init(&rpc_servers_wake_lock, WAKE_LOCK_SUSPEND, "rpc_server");
611 return platform_driver_register(&rpcservers_driver);
612}
613
614module_init(rpc_servers_init);
615
616MODULE_DESCRIPTION("MSM RPC Servers");
617MODULE_AUTHOR("Iliyan Malchev <ibm@android.com>");
618MODULE_LICENSE("GPL");