include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / dream / smd / smd_rpcrouter_servers.c
1 /* arch/arm/mach-msm/rpc_servers.c
2 *
3 * Copyright (C) 2007 Google, Inc.
4 * Author: Iliyan Malchev <ibm@android.com>
5 *
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.
9 *
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.
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 #include <linux/slab.h>
31
32 #include <linux/msm_rpcrouter.h>
33 #include <linux/uaccess.h>
34
35 #include <mach/msm_rpcrouter.h>
36 #include "smd_rpcrouter.h"
37
38 static struct msm_rpc_endpoint *endpoint;
39
40 #define FLAG_REGISTERED 0x0001
41
42 static LIST_HEAD(rpc_server_list);
43 static DEFINE_MUTEX(rpc_server_list_lock);
44 static int rpc_servers_active;
45 static struct wake_lock rpc_servers_wake_lock;
46
47 static void rpc_server_register(struct msm_rpc_server *server)
48 {
49 int rc;
50 rc = msm_rpc_register_server(endpoint, server->prog, server->vers);
51 if (rc < 0)
52 printk(KERN_ERR "[rpcserver] error registering %p @ %08x:%d\n",
53 server, server->prog, server->vers);
54 }
55
56 static struct msm_rpc_server *rpc_server_find(uint32_t prog, uint32_t vers)
57 {
58 struct msm_rpc_server *server;
59
60 mutex_lock(&rpc_server_list_lock);
61 list_for_each_entry(server, &rpc_server_list, list) {
62 if ((server->prog == prog) &&
63 #if CONFIG_MSM_AMSS_VERSION >= 6350
64 msm_rpc_is_compatible_version(server->vers, vers)) {
65 #else
66 server->vers == vers) {
67 #endif
68 mutex_unlock(&rpc_server_list_lock);
69 return server;
70 }
71 }
72 mutex_unlock(&rpc_server_list_lock);
73 return NULL;
74 }
75
76 static void rpc_server_register_all(void)
77 {
78 struct msm_rpc_server *server;
79
80 mutex_lock(&rpc_server_list_lock);
81 list_for_each_entry(server, &rpc_server_list, list) {
82 if (!(server->flags & FLAG_REGISTERED)) {
83 rpc_server_register(server);
84 server->flags |= FLAG_REGISTERED;
85 }
86 }
87 mutex_unlock(&rpc_server_list_lock);
88 }
89
90 int msm_rpc_create_server(struct msm_rpc_server *server)
91 {
92 /* make sure we're in a sane state first */
93 server->flags = 0;
94 INIT_LIST_HEAD(&server->list);
95
96 mutex_lock(&rpc_server_list_lock);
97 list_add(&server->list, &rpc_server_list);
98 if (rpc_servers_active) {
99 rpc_server_register(server);
100 server->flags |= FLAG_REGISTERED;
101 }
102 mutex_unlock(&rpc_server_list_lock);
103
104 return 0;
105 }
106
107 static int rpc_send_accepted_void_reply(struct msm_rpc_endpoint *client,
108 uint32_t xid, uint32_t accept_status)
109 {
110 int rc = 0;
111 uint8_t reply_buf[sizeof(struct rpc_reply_hdr)];
112 struct rpc_reply_hdr *reply = (struct rpc_reply_hdr *)reply_buf;
113
114 reply->xid = cpu_to_be32(xid);
115 reply->type = cpu_to_be32(1); /* reply */
116 reply->reply_stat = cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
117
118 reply->data.acc_hdr.accept_stat = cpu_to_be32(accept_status);
119 reply->data.acc_hdr.verf_flavor = 0;
120 reply->data.acc_hdr.verf_length = 0;
121
122 rc = msm_rpc_write(client, reply_buf, sizeof(reply_buf));
123 if (rc < 0)
124 printk(KERN_ERR
125 "%s: could not write response: %d\n",
126 __FUNCTION__, rc);
127
128 return rc;
129 }
130
131 static int rpc_servers_thread(void *data)
132 {
133 void *buffer;
134 struct rpc_request_hdr *req;
135 struct msm_rpc_server *server;
136 int rc;
137
138 for (;;) {
139 wake_unlock(&rpc_servers_wake_lock);
140 rc = wait_event_interruptible(endpoint->wait_q,
141 !list_empty(&endpoint->read_q));
142 wake_lock(&rpc_servers_wake_lock);
143 rc = msm_rpc_read(endpoint, &buffer, -1, -1);
144 if (rc < 0) {
145 printk(KERN_ERR "%s: could not read: %d\n",
146 __FUNCTION__, rc);
147 break;
148 }
149 req = (struct rpc_request_hdr *)buffer;
150
151 req->type = be32_to_cpu(req->type);
152 req->xid = be32_to_cpu(req->xid);
153 req->rpc_vers = be32_to_cpu(req->rpc_vers);
154 req->prog = be32_to_cpu(req->prog);
155 req->vers = be32_to_cpu(req->vers);
156 req->procedure = be32_to_cpu(req->procedure);
157
158 server = rpc_server_find(req->prog, req->vers);
159
160 if (req->rpc_vers != 2)
161 continue;
162 if (req->type != 0)
163 continue;
164 if (!server) {
165 rpc_send_accepted_void_reply(
166 endpoint, req->xid,
167 RPC_ACCEPTSTAT_PROG_UNAVAIL);
168 continue;
169 }
170
171 rc = server->rpc_call(server, req, rc);
172
173 switch (rc) {
174 case 0:
175 rpc_send_accepted_void_reply(
176 endpoint, req->xid,
177 RPC_ACCEPTSTAT_SUCCESS);
178 break;
179 default:
180 rpc_send_accepted_void_reply(
181 endpoint, req->xid,
182 RPC_ACCEPTSTAT_PROG_UNAVAIL);
183 break;
184 }
185
186 kfree(buffer);
187 }
188
189 do_exit(0);
190 }
191
192 static int rpcservers_probe(struct platform_device *pdev)
193 {
194 struct task_struct *server_thread;
195
196 endpoint = msm_rpc_open();
197 if (IS_ERR(endpoint))
198 return PTR_ERR(endpoint);
199
200 /* we're online -- register any servers installed beforehand */
201 rpc_servers_active = 1;
202 rpc_server_register_all();
203
204 /* start the kernel thread */
205 server_thread = kthread_run(rpc_servers_thread, NULL, "krpcserversd");
206 if (IS_ERR(server_thread))
207 return PTR_ERR(server_thread);
208
209 return 0;
210 }
211
212 static struct platform_driver rpcservers_driver = {
213 .probe = rpcservers_probe,
214 .driver = {
215 .name = "oncrpc_router",
216 .owner = THIS_MODULE,
217 },
218 };
219
220 static int __init rpc_servers_init(void)
221 {
222 wake_lock_init(&rpc_servers_wake_lock, WAKE_LOCK_SUSPEND, "rpc_server");
223 return platform_driver_register(&rpcservers_driver);
224 }
225
226 module_init(rpc_servers_init);
227
228 MODULE_DESCRIPTION("MSM RPC Servers");
229 MODULE_AUTHOR("Iliyan Malchev <ibm@android.com>");
230 MODULE_LICENSE("GPL");