1 /* arch/arm/mach-msm/rpc_servers.c
3 * Copyright (C) 2007 Google, Inc.
4 * Author: Iliyan Malchev <ibm@android.com>
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/string.h>
20 #include <linux/errno.h>
21 #include <linux/cdev.h>
22 #include <linux/init.h>
23 #include <linux/device.h>
24 #include <linux/types.h>
26 #include <linux/kthread.h>
27 #include <linux/delay.h>
28 #include <linux/platform_device.h>
29 #include <linux/wakelock.h>
31 #include <linux/msm_rpcrouter.h>
32 #include <linux/uaccess.h>
34 #include <mach/msm_rpcrouter.h>
35 #include "smd_rpcrouter.h"
37 static struct msm_rpc_endpoint
*endpoint
;
39 #define FLAG_REGISTERED 0x0001
41 static LIST_HEAD(rpc_server_list
);
42 static DEFINE_MUTEX(rpc_server_list_lock
);
43 static int rpc_servers_active
;
44 static struct wake_lock rpc_servers_wake_lock
;
46 static void rpc_server_register(struct msm_rpc_server
*server
)
49 rc
= msm_rpc_register_server(endpoint
, server
->prog
, server
->vers
);
51 printk(KERN_ERR
"[rpcserver] error registering %p @ %08x:%d\n",
52 server
, server
->prog
, server
->vers
);
55 static struct msm_rpc_server
*rpc_server_find(uint32_t prog
, uint32_t vers
)
57 struct msm_rpc_server
*server
;
59 mutex_lock(&rpc_server_list_lock
);
60 list_for_each_entry(server
, &rpc_server_list
, list
) {
61 if ((server
->prog
== prog
) &&
62 #if CONFIG_MSM_AMSS_VERSION >= 6350
63 msm_rpc_is_compatible_version(server
->vers
, vers
)) {
65 server
->vers
== vers
) {
67 mutex_unlock(&rpc_server_list_lock
);
71 mutex_unlock(&rpc_server_list_lock
);
75 static void rpc_server_register_all(void)
77 struct msm_rpc_server
*server
;
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
;
86 mutex_unlock(&rpc_server_list_lock
);
89 int msm_rpc_create_server(struct msm_rpc_server
*server
)
91 /* make sure we're in a sane state first */
93 INIT_LIST_HEAD(&server
->list
);
95 mutex_lock(&rpc_server_list_lock
);
96 list_add(&server
->list
, &rpc_server_list
);
97 if (rpc_servers_active
) {
98 rpc_server_register(server
);
99 server
->flags
|= FLAG_REGISTERED
;
101 mutex_unlock(&rpc_server_list_lock
);
106 static int rpc_send_accepted_void_reply(struct msm_rpc_endpoint
*client
,
107 uint32_t xid
, uint32_t accept_status
)
110 uint8_t reply_buf
[sizeof(struct rpc_reply_hdr
)];
111 struct rpc_reply_hdr
*reply
= (struct rpc_reply_hdr
*)reply_buf
;
113 reply
->xid
= cpu_to_be32(xid
);
114 reply
->type
= cpu_to_be32(1); /* reply */
115 reply
->reply_stat
= cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED
);
117 reply
->data
.acc_hdr
.accept_stat
= cpu_to_be32(accept_status
);
118 reply
->data
.acc_hdr
.verf_flavor
= 0;
119 reply
->data
.acc_hdr
.verf_length
= 0;
121 rc
= msm_rpc_write(client
, reply_buf
, sizeof(reply_buf
));
124 "%s: could not write response: %d\n",
130 static int rpc_servers_thread(void *data
)
133 struct rpc_request_hdr
*req
;
134 struct msm_rpc_server
*server
;
138 wake_unlock(&rpc_servers_wake_lock
);
139 rc
= wait_event_interruptible(endpoint
->wait_q
,
140 !list_empty(&endpoint
->read_q
));
141 wake_lock(&rpc_servers_wake_lock
);
142 rc
= msm_rpc_read(endpoint
, &buffer
, -1, -1);
144 printk(KERN_ERR
"%s: could not read: %d\n",
148 req
= (struct rpc_request_hdr
*)buffer
;
150 req
->type
= be32_to_cpu(req
->type
);
151 req
->xid
= be32_to_cpu(req
->xid
);
152 req
->rpc_vers
= be32_to_cpu(req
->rpc_vers
);
153 req
->prog
= be32_to_cpu(req
->prog
);
154 req
->vers
= be32_to_cpu(req
->vers
);
155 req
->procedure
= be32_to_cpu(req
->procedure
);
157 server
= rpc_server_find(req
->prog
, req
->vers
);
159 if (req
->rpc_vers
!= 2)
164 rpc_send_accepted_void_reply(
166 RPC_ACCEPTSTAT_PROG_UNAVAIL
);
170 rc
= server
->rpc_call(server
, req
, rc
);
174 rpc_send_accepted_void_reply(
176 RPC_ACCEPTSTAT_SUCCESS
);
179 rpc_send_accepted_void_reply(
181 RPC_ACCEPTSTAT_PROG_UNAVAIL
);
191 static int rpcservers_probe(struct platform_device
*pdev
)
193 struct task_struct
*server_thread
;
195 endpoint
= msm_rpc_open();
196 if (IS_ERR(endpoint
))
197 return PTR_ERR(endpoint
);
199 /* we're online -- register any servers installed beforehand */
200 rpc_servers_active
= 1;
201 rpc_server_register_all();
203 /* start the kernel thread */
204 server_thread
= kthread_run(rpc_servers_thread
, NULL
, "krpcserversd");
205 if (IS_ERR(server_thread
))
206 return PTR_ERR(server_thread
);
211 static struct platform_driver rpcservers_driver
= {
212 .probe
= rpcservers_probe
,
214 .name
= "oncrpc_router",
215 .owner
= THIS_MODULE
,
219 static int __init
rpc_servers_init(void)
221 wake_lock_init(&rpc_servers_wake_lock
, WAKE_LOCK_SUSPEND
, "rpc_server");
222 return platform_driver_register(&rpcservers_driver
);
225 module_init(rpc_servers_init
);
227 MODULE_DESCRIPTION("MSM RPC Servers");
228 MODULE_AUTHOR("Iliyan Malchev <ibm@android.com>");
229 MODULE_LICENSE("GPL");