blob: 5999979d8379619fe374cc4d178f0a6e3522e198 [file] [log] [blame]
Nicholas Flintham1e3d3112013-04-10 10:48:38 +01001/* Copyright (c) 2011-2012, 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#include <linux/module.h>
14#include <linux/types.h>
15#include <linux/net.h>
16#include <linux/socket.h>
17#include <linux/errno.h>
18#include <linux/mm.h>
19#include <linux/poll.h>
20#include <linux/fcntl.h>
21#include <linux/gfp.h>
22#include <linux/msm_ipc.h>
23
24#include <asm/string.h>
25#include <asm/atomic.h>
26
27#include <net/sock.h>
28
29#include "ipc_router.h"
30
31#define msm_ipc_sk(sk) ((struct msm_ipc_sock *)(sk))
32#define msm_ipc_sk_port(sk) ((struct msm_ipc_port *)(msm_ipc_sk(sk)->port))
33
34static int sockets_enabled;
35static struct proto msm_ipc_proto;
36static const struct proto_ops msm_ipc_proto_ops;
37
38
39static struct sk_buff_head *msm_ipc_router_build_msg(unsigned int num_sect,
40 struct iovec const *msg_sect,
41 size_t total_len)
42{
43 struct sk_buff_head *msg_head;
44 struct sk_buff *msg;
45 int i, copied, first = 1;
46 int data_size = 0, request_size, offset;
47 void *data;
48
49 for (i = 0; i < num_sect; i++)
50 data_size += msg_sect[i].iov_len;
51
52 if (!data_size)
53 return NULL;
54
55 msg_head = kmalloc(sizeof(struct sk_buff_head), GFP_KERNEL);
56 if (!msg_head) {
57 pr_err("%s: cannot allocate skb_head\n", __func__);
58 return NULL;
59 }
60 skb_queue_head_init(msg_head);
61
62 for (copied = 1, i = 0; copied && (i < num_sect); i++) {
63 data_size = msg_sect[i].iov_len;
64 offset = 0;
65 while (offset != msg_sect[i].iov_len) {
66 request_size = data_size;
67 if (first)
68 request_size += IPC_ROUTER_HDR_SIZE;
69
70 msg = alloc_skb(request_size, GFP_KERNEL);
71 if (!msg) {
72 if (request_size <= (PAGE_SIZE/2)) {
73 pr_err("%s: cannot allocated skb\n",
74 __func__);
75 goto msg_build_failure;
76 }
77 data_size = data_size / 2;
78 continue;
79 }
80
81 if (first) {
82 skb_reserve(msg, IPC_ROUTER_HDR_SIZE);
83 first = 0;
84 }
85
86 data = skb_put(msg, data_size);
87 copied = !copy_from_user(msg->data,
88 msg_sect[i].iov_base + offset,
89 data_size);
90 if (!copied) {
91 pr_err("%s: copy_from_user failed\n",
92 __func__);
93 kfree_skb(msg);
94 goto msg_build_failure;
95 }
96 skb_queue_tail(msg_head, msg);
97 offset += data_size;
98 data_size = msg_sect[i].iov_len - offset;
99 }
100 }
101 return msg_head;
102
103msg_build_failure:
104 while (!skb_queue_empty(msg_head)) {
105 msg = skb_dequeue(msg_head);
106 kfree_skb(msg);
107 }
108 kfree(msg_head);
109 return NULL;
110}
111
112static int msm_ipc_router_extract_msg(struct msghdr *m,
113 struct sk_buff_head *msg_head)
114{
115 struct sockaddr_msm_ipc *addr = (struct sockaddr_msm_ipc *)m->msg_name;
116 struct rr_header *hdr;
117 struct sk_buff *temp;
118 int offset = 0, data_len = 0, copy_len;
119
120 if (!m || !msg_head) {
121 pr_err("%s: Invalid pointers passed\n", __func__);
122 return -EINVAL;
123 }
124
125 temp = skb_peek(msg_head);
126 hdr = (struct rr_header *)(temp->data);
127 if (addr || (hdr->src_port_id != IPC_ROUTER_ADDRESS)) {
128 addr->family = AF_MSM_IPC;
129 addr->address.addrtype = MSM_IPC_ADDR_ID;
130 addr->address.addr.port_addr.node_id = hdr->src_node_id;
131 addr->address.addr.port_addr.port_id = hdr->src_port_id;
132 m->msg_namelen = sizeof(struct sockaddr_msm_ipc);
133 }
134
135 data_len = hdr->size;
136 skb_pull(temp, IPC_ROUTER_HDR_SIZE);
137 skb_queue_walk(msg_head, temp) {
138 copy_len = data_len < temp->len ? data_len : temp->len;
139 if (copy_to_user(m->msg_iov->iov_base + offset, temp->data,
140 copy_len)) {
141 pr_err("%s: Copy to user failed\n", __func__);
142 return -EFAULT;
143 }
144 offset += copy_len;
145 data_len -= copy_len;
146 }
147 return offset;
148}
149
150static void msm_ipc_router_release_msg(struct sk_buff_head *msg_head)
151{
152 struct sk_buff *temp;
153
154 if (!msg_head) {
155 pr_err("%s: Invalid msg pointer\n", __func__);
156 return;
157 }
158
159 while (!skb_queue_empty(msg_head)) {
160 temp = skb_dequeue(msg_head);
161 kfree_skb(temp);
162 }
163 kfree(msg_head);
164}
165
166static int msm_ipc_router_create(struct net *net,
167 struct socket *sock,
168 int protocol,
169 int kern)
170{
171 struct sock *sk;
172 struct msm_ipc_port *port_ptr;
173 void *pil;
174
175 if (unlikely(protocol != 0)) {
176 pr_err("%s: Protocol not supported\n", __func__);
177 return -EPROTONOSUPPORT;
178 }
179
180 switch (sock->type) {
181 case SOCK_DGRAM:
182 break;
183 default:
184 pr_err("%s: Protocol type not supported\n", __func__);
185 return -EPROTOTYPE;
186 }
187
188 sk = sk_alloc(net, AF_MSM_IPC, GFP_KERNEL, &msm_ipc_proto);
189 if (!sk) {
190 pr_err("%s: sk_alloc failed\n", __func__);
191 return -ENOMEM;
192 }
193
194 port_ptr = msm_ipc_router_create_raw_port(sk, NULL, NULL);
195 if (!port_ptr) {
196 pr_err("%s: port_ptr alloc failed\n", __func__);
197 sk_free(sk);
198 return -ENOMEM;
199 }
200
201 sock->ops = &msm_ipc_proto_ops;
202 sock_init_data(sock, sk);
203 sk->sk_rcvtimeo = DEFAULT_RCV_TIMEO;
204
205 pil = msm_ipc_load_default_node();
206 msm_ipc_sk(sk)->port = port_ptr;
207 msm_ipc_sk(sk)->default_pil = pil;
208
209 return 0;
210}
211
212int msm_ipc_router_bind(struct socket *sock, struct sockaddr *uaddr,
213 int uaddr_len)
214{
215 struct sockaddr_msm_ipc *addr = (struct sockaddr_msm_ipc *)uaddr;
216 struct sock *sk = sock->sk;
217 struct msm_ipc_port *port_ptr;
218 int ret;
219
220 if (!sk)
221 return -EINVAL;
222
223 if (!uaddr_len) {
224 pr_err("%s: Invalid address length\n", __func__);
225 return -EINVAL;
226 }
227
228 if (addr->family != AF_MSM_IPC) {
229 pr_err("%s: Address family is incorrect\n", __func__);
230 return -EAFNOSUPPORT;
231 }
232
233 if (addr->address.addrtype != MSM_IPC_ADDR_NAME) {
234 pr_err("%s: Address type is incorrect\n", __func__);
235 return -EINVAL;
236 }
237
238 port_ptr = msm_ipc_sk_port(sk);
239 if (!port_ptr)
240 return -ENODEV;
241
242 lock_sock(sk);
243
244 ret = msm_ipc_router_register_server(port_ptr, &addr->address);
245
246 release_sock(sk);
247 return ret;
248}
249
250static int msm_ipc_router_sendmsg(struct kiocb *iocb, struct socket *sock,
251 struct msghdr *m, size_t total_len)
252{
253 struct sock *sk = sock->sk;
254 struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
255 struct sockaddr_msm_ipc *dest = (struct sockaddr_msm_ipc *)m->msg_name;
256 struct sk_buff_head *msg;
257 int ret;
258
259 if (!dest)
260 return -EDESTADDRREQ;
261
262 if (m->msg_namelen < sizeof(*dest) || dest->family != AF_MSM_IPC)
263 return -EINVAL;
264
265 if (total_len > MAX_IPC_PKT_SIZE)
266 return -EINVAL;
267
268 lock_sock(sk);
269 msg = msm_ipc_router_build_msg(m->msg_iovlen, m->msg_iov, total_len);
270 if (!msg) {
271 pr_err("%s: Msg build failure\n", __func__);
272 ret = -ENOMEM;
273 goto out_sendmsg;
274 }
275
276 ret = msm_ipc_router_send_to(port_ptr, msg, &dest->address);
277 if (ret == (IPC_ROUTER_HDR_SIZE + total_len))
278 ret = total_len;
279
280out_sendmsg:
281 release_sock(sk);
282 return ret;
283}
284
285static int msm_ipc_router_recvmsg(struct kiocb *iocb, struct socket *sock,
286 struct msghdr *m, size_t buf_len, int flags)
287{
288 struct sock *sk = sock->sk;
289 struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
290 struct sk_buff_head *msg;
291 long timeout;
292 int ret;
293
294 if (m->msg_iovlen != 1)
295 return -EOPNOTSUPP;
296
297 if (!buf_len)
298 return -EINVAL;
299
300 lock_sock(sk);
301 timeout = sk->sk_rcvtimeo;
302 mutex_lock(&port_ptr->port_rx_q_lock);
303 while (list_empty(&port_ptr->port_rx_q)) {
304 mutex_unlock(&port_ptr->port_rx_q_lock);
305 release_sock(sk);
306 if (timeout < 0) {
307 ret = wait_event_interruptible(
308 port_ptr->port_rx_wait_q,
309 !list_empty(&port_ptr->port_rx_q));
310 if (ret)
311 return ret;
312 } else if (timeout > 0) {
313 timeout = wait_event_interruptible_timeout(
314 port_ptr->port_rx_wait_q,
315 !list_empty(&port_ptr->port_rx_q),
316 timeout);
317 if (timeout < 0)
318 return -EFAULT;
319 }
320
321 if (timeout == 0)
322 return -ETIMEDOUT;
323 lock_sock(sk);
324 mutex_lock(&port_ptr->port_rx_q_lock);
325 }
326 mutex_unlock(&port_ptr->port_rx_q_lock);
327
328 ret = msm_ipc_router_read(port_ptr, &msg, buf_len);
329 if (ret <= 0 || !msg) {
330 release_sock(sk);
331 return ret;
332 }
333
334 ret = msm_ipc_router_extract_msg(m, msg);
335 msm_ipc_router_release_msg(msg);
336 msg = NULL;
337 release_sock(sk);
338 return ret;
339}
340
341static int msm_ipc_router_ioctl(struct socket *sock,
342 unsigned int cmd, unsigned long arg)
343{
344 struct sock *sk = sock->sk;
345 struct msm_ipc_port *port_ptr;
346 struct server_lookup_args server_arg;
347#ifdef CONFIG_MSM8960_ONLY
348 struct msm_ipc_port_addr *port_addr = NULL;
349 unsigned int n, port_addr_sz = 0;
350#else
351 struct msm_ipc_server_info *srv_info = NULL;
352 unsigned int n, srv_info_sz = 0;
353#endif
354 int ret;
355
356 if (!sk)
357 return -EINVAL;
358
359 lock_sock(sk);
360 port_ptr = msm_ipc_sk_port(sock->sk);
361 if (!port_ptr) {
362 release_sock(sk);
363 return -EINVAL;
364 }
365
366 switch (cmd) {
367 case IPC_ROUTER_IOCTL_GET_VERSION:
368 n = IPC_ROUTER_VERSION;
369 ret = put_user(n, (unsigned int *)arg);
370 break;
371
372 case IPC_ROUTER_IOCTL_GET_MTU:
373 n = (MAX_IPC_PKT_SIZE - IPC_ROUTER_HDR_SIZE);
374 ret = put_user(n, (unsigned int *)arg);
375 break;
376
377 case IPC_ROUTER_IOCTL_GET_CURR_PKT_SIZE:
378 ret = msm_ipc_router_get_curr_pkt_size(port_ptr);
379 break;
380
381 case IPC_ROUTER_IOCTL_LOOKUP_SERVER:
382 ret = copy_from_user(&server_arg, (void *)arg,
383 sizeof(server_arg));
384 if (ret) {
385 ret = -EFAULT;
386 break;
387 }
388
389 if (server_arg.num_entries_in_array < 0) {
390 ret = -EINVAL;
391 break;
392 }
393#ifdef CONFIG_MSM8960_ONLY
394 if (server_arg.num_entries_in_array) {
395 port_addr_sz = server_arg.num_entries_in_array *
396 sizeof(*port_addr);
397 port_addr = kmalloc(port_addr_sz, GFP_KERNEL);
398 if (!port_addr) {
399 ret = -ENOMEM;
400 break;
401 }
402 }
403 ret = msm_ipc_router_lookup_server_name(&server_arg.port_name,
404 port_addr, server_arg.num_entries_in_array,
405 server_arg.lookup_mask);
406 if (ret < 0) {
407 pr_err("%s: Server not found\n", __func__);
408 ret = -ENODEV;
409 kfree(port_addr);
410 break;
411 }
412 server_arg.num_entries_found = ret;
413
414 ret = copy_to_user((void *)arg, &server_arg,
415 sizeof(server_arg));
416 if (port_addr_sz) {
417 ret = copy_to_user((void *)(arg + sizeof(server_arg)),
418 port_addr, port_addr_sz);
419 if (ret)
420 ret = -EFAULT;
421 kfree(port_addr);
422 }
423
424#else
425
426 if (server_arg.num_entries_in_array) {
427 srv_info_sz = server_arg.num_entries_in_array *
428 sizeof(*srv_info);
429 srv_info = kmalloc(srv_info_sz, GFP_KERNEL);
430 if (!srv_info) {
431 ret = -ENOMEM;
432 break;
433 }
434 }
435 ret = msm_ipc_router_lookup_server_name(&server_arg.port_name,
436 srv_info, server_arg.num_entries_in_array,
437 server_arg.lookup_mask);
438 if (ret < 0) {
439 pr_err("%s: Server not found\n", __func__);
440 ret = -ENODEV;
441 kfree(srv_info);
442 break;
443 }
444 server_arg.num_entries_found = ret;
445
446 ret = copy_to_user((void *)arg, &server_arg,
447 sizeof(server_arg));
448 if (srv_info_sz) {
449 ret = copy_to_user((void *)(arg + sizeof(server_arg)),
450 srv_info, srv_info_sz);
451 if (ret)
452 ret = -EFAULT;
453 kfree(srv_info);
454 }
455#endif
456 break;
457
458 case IPC_ROUTER_IOCTL_BIND_CONTROL_PORT:
459 ret = msm_ipc_router_bind_control_port(port_ptr);
460 break;
461
462 default:
463 ret = -EINVAL;
464 }
465 release_sock(sk);
466 return ret;
467}
468
469static unsigned int msm_ipc_router_poll(struct file *file,
470 struct socket *sock, poll_table *wait)
471{
472 struct sock *sk = sock->sk;
473 struct msm_ipc_port *port_ptr;
474 uint32_t mask = 0;
475
476 if (!sk)
477 return -EINVAL;
478
479 port_ptr = msm_ipc_sk_port(sk);
480 if (!port_ptr)
481 return -EINVAL;
482
483 poll_wait(file, &port_ptr->port_rx_wait_q, wait);
484
485 if (!list_empty(&port_ptr->port_rx_q))
486 mask |= (POLLRDNORM | POLLIN);
487
488 return mask;
489}
490
491static int msm_ipc_router_close(struct socket *sock)
492{
493 struct sock *sk = sock->sk;
494 struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk);
495 void *pil = msm_ipc_sk(sk)->default_pil;
496 int ret;
497
498 lock_sock(sk);
499 ret = msm_ipc_router_close_port(port_ptr);
500 msm_ipc_unload_default_node(pil);
501 release_sock(sk);
502 sock_put(sk);
503 sock->sk = NULL;
504
505 return ret;
506}
507
508static const struct net_proto_family msm_ipc_family_ops = {
509 .owner = THIS_MODULE,
510 .family = AF_MSM_IPC,
511 .create = msm_ipc_router_create
512};
513
514static const struct proto_ops msm_ipc_proto_ops = {
515 .owner = THIS_MODULE,
516 .family = AF_MSM_IPC,
517 .bind = msm_ipc_router_bind,
518 .connect = sock_no_connect,
519 .sendmsg = msm_ipc_router_sendmsg,
520 .recvmsg = msm_ipc_router_recvmsg,
521 .ioctl = msm_ipc_router_ioctl,
522 .poll = msm_ipc_router_poll,
523 .setsockopt = sock_no_setsockopt,
524 .getsockopt = sock_no_getsockopt,
525 .release = msm_ipc_router_close,
526};
527
528static struct proto msm_ipc_proto = {
529 .name = "MSM_IPC",
530 .owner = THIS_MODULE,
531 .obj_size = sizeof(struct msm_ipc_sock),
532};
533
534int msm_ipc_router_init_sockets(void)
535{
536 int ret;
537
538 ret = proto_register(&msm_ipc_proto, 1);
539 if (ret) {
540 pr_err("Failed to register MSM_IPC protocol type\n");
541 goto out_init_sockets;
542 }
543
544 ret = sock_register(&msm_ipc_family_ops);
545 if (ret) {
546 pr_err("Failed to register MSM_IPC socket type\n");
547 proto_unregister(&msm_ipc_proto);
548 goto out_init_sockets;
549 }
550
551 sockets_enabled = 1;
552out_init_sockets:
553 return ret;
554}
555
556void msm_ipc_router_exit_sockets(void)
557{
558 if (!sockets_enabled)
559 return;
560
561 sockets_enabled = 0;
562 sock_unregister(msm_ipc_family_ops.family);
563 proto_unregister(&msm_ipc_proto);
564}