1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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>
25#include <linux/fs.h>
26#include <linux/kthread.h>
27#include <linux/delay.h>
28#include <linux/platform_device.h>
29#include <linux/wakelock.h>
30
31#include <linux/msm_rpcrouter.h>
32#include <linux/uaccess.h>
33
34#include <mach/msm_rpcrouter.h>
35#include "smd_rpcrouter.h"
36
37static struct msm_rpc_endpoint *endpoint;
38
39#define FLAG_REGISTERED 0x0001
40
41static LIST_HEAD(rpc_server_list);
42static DEFINE_MUTEX(rpc_server_list_lock);
43static int rpc_servers_active;
44static struct wake_lock rpc_servers_wake_lock;
45
46static void rpc_server_register(struct msm_rpc_server *server)
47{
48 int rc;
49 rc = msm_rpc_register_server(endpoint, server->prog, server->vers);
50 if (rc < 0)
51 printk(KERN_ERR "[rpcserver] error registering %p @ %08x:%d\n",
52 server, server->prog, server->vers);
53}
54
55static struct msm_rpc_server *rpc_server_find(uint32_t prog, uint32_t vers)
56{
57 struct msm_rpc_server *server;
58
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)) {
64#else
65 server->vers == vers) {
66#endif
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
92 server->flags = 0;
93 INIT_LIST_HEAD(&server->list);
94
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;
100 }
101 mutex_unlock(&rpc_server_list_lock);
102
103 return 0;
104}
105
106static int rpc_send_accepted_void_reply(struct msm_rpc_endpoint *client,
107 uint32_t xid, uint32_t accept_status)
108{
109 int rc = 0;
110 uint8_t reply_buf[sizeof(struct rpc_reply_hdr)];
111 struct rpc_reply_hdr *reply = (struct rpc_reply_hdr *)reply_buf;
112
113 reply->xid = cpu_to_be32(xid);
114 reply->type = cpu_to_be32(1);
115 reply->reply_stat = cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
116
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;
120
121 rc = msm_rpc_write(client, reply_buf, sizeof(reply_buf));
122 if (rc < 0)
123 printk(KERN_ERR
124 "%s: could not write response: %d\n",
125 __FUNCTION__, rc);
126
127 return rc;
128}
129
130static int rpc_servers_thread(void *data)
131{
132 void *buffer;
133 struct rpc_request_hdr *req;
134 struct msm_rpc_server *server;
135 int rc;
136
137 for (;;) {
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);
143 if (rc < 0) {
144 printk(KERN_ERR "%s: could not read: %d\n",
145 __FUNCTION__, rc);
146 break;
147 }
148 req = (struct rpc_request_hdr *)buffer;
149
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);
156
157 server = rpc_server_find(req->prog, req->vers);
158
159 if (req->rpc_vers != 2)
160 continue;
161 if (req->type != 0)
162 continue;
163 if (!server) {
164 rpc_send_accepted_void_reply(
165 endpoint, req->xid,
166 RPC_ACCEPTSTAT_PROG_UNAVAIL);
167 continue;
168 }
169
170 rc = server->rpc_call(server, req, rc);
171
172 switch (rc) {
173 case 0:
174 rpc_send_accepted_void_reply(
175 endpoint, req->xid,
176 RPC_ACCEPTSTAT_SUCCESS);
177 break;
178 default:
179 rpc_send_accepted_void_reply(
180 endpoint, req->xid,
181 RPC_ACCEPTSTAT_PROG_UNAVAIL);
182 break;
183 }
184
185 kfree(buffer);
186 }
187
188 do_exit(0);
189}
190
191static int rpcservers_probe(struct platform_device *pdev)
192{
193 struct task_struct *server_thread;
194
195 endpoint = msm_rpc_open();
196 if (IS_ERR(endpoint))
197 return PTR_ERR(endpoint);
198
199
200 rpc_servers_active = 1;
201 rpc_server_register_all();
202
203
204 server_thread = kthread_run(rpc_servers_thread, NULL, "krpcserversd");
205 if (IS_ERR(server_thread))
206 return PTR_ERR(server_thread);
207
208 return 0;
209}
210
211static struct platform_driver rpcservers_driver = {
212 .probe = rpcservers_probe,
213 .driver = {
214 .name = "oncrpc_router",
215 .owner = THIS_MODULE,
216 },
217};
218
219static int __init rpc_servers_init(void)
220{
221 wake_lock_init(&rpc_servers_wake_lock, WAKE_LOCK_SUSPEND, "rpc_server");
222 return platform_driver_register(&rpcservers_driver);
223}
224
225module_init(rpc_servers_init);
226
227MODULE_DESCRIPTION("MSM RPC Servers");
228MODULE_AUTHOR("Iliyan Malchev <ibm@android.com>");
229MODULE_LICENSE("GPL");
230