Merge tag 'mm-stable-2023-09-04-14-00' of git://git.kernel.org/pub/scm/linux/kernel...
[platform/kernel/linux-rpi.git] / net / qrtr / ns.c
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /*
3  * Copyright (c) 2015, Sony Mobile Communications Inc.
4  * Copyright (c) 2013, The Linux Foundation. All rights reserved.
5  * Copyright (c) 2020, Linaro Ltd.
6  */
7
8 #include <linux/module.h>
9 #include <linux/qrtr.h>
10 #include <linux/workqueue.h>
11 #include <net/sock.h>
12
13 #include "qrtr.h"
14
15 #include <trace/events/sock.h>
16 #define CREATE_TRACE_POINTS
17 #include <trace/events/qrtr.h>
18
19 static DEFINE_XARRAY(nodes);
20
21 static struct {
22         struct socket *sock;
23         struct sockaddr_qrtr bcast_sq;
24         struct list_head lookups;
25         struct workqueue_struct *workqueue;
26         struct work_struct work;
27         int local_node;
28 } qrtr_ns;
29
30 static const char * const qrtr_ctrl_pkt_strings[] = {
31         [QRTR_TYPE_HELLO]       = "hello",
32         [QRTR_TYPE_BYE]         = "bye",
33         [QRTR_TYPE_NEW_SERVER]  = "new-server",
34         [QRTR_TYPE_DEL_SERVER]  = "del-server",
35         [QRTR_TYPE_DEL_CLIENT]  = "del-client",
36         [QRTR_TYPE_RESUME_TX]   = "resume-tx",
37         [QRTR_TYPE_EXIT]        = "exit",
38         [QRTR_TYPE_PING]        = "ping",
39         [QRTR_TYPE_NEW_LOOKUP]  = "new-lookup",
40         [QRTR_TYPE_DEL_LOOKUP]  = "del-lookup",
41 };
42
43 struct qrtr_server_filter {
44         unsigned int service;
45         unsigned int instance;
46         unsigned int ifilter;
47 };
48
49 struct qrtr_lookup {
50         unsigned int service;
51         unsigned int instance;
52
53         struct sockaddr_qrtr sq;
54         struct list_head li;
55 };
56
57 struct qrtr_server {
58         unsigned int service;
59         unsigned int instance;
60
61         unsigned int node;
62         unsigned int port;
63
64         struct list_head qli;
65 };
66
67 struct qrtr_node {
68         unsigned int id;
69         struct xarray servers;
70 };
71
72 static struct qrtr_node *node_get(unsigned int node_id)
73 {
74         struct qrtr_node *node;
75
76         node = xa_load(&nodes, node_id);
77         if (node)
78                 return node;
79
80         /* If node didn't exist, allocate and insert it to the tree */
81         node = kzalloc(sizeof(*node), GFP_KERNEL);
82         if (!node)
83                 return NULL;
84
85         node->id = node_id;
86         xa_init(&node->servers);
87
88         if (xa_store(&nodes, node_id, node, GFP_KERNEL)) {
89                 kfree(node);
90                 return NULL;
91         }
92
93         return node;
94 }
95
96 static int server_match(const struct qrtr_server *srv,
97                         const struct qrtr_server_filter *f)
98 {
99         unsigned int ifilter = f->ifilter;
100
101         if (f->service != 0 && srv->service != f->service)
102                 return 0;
103         if (!ifilter && f->instance)
104                 ifilter = ~0;
105
106         return (srv->instance & ifilter) == f->instance;
107 }
108
109 static int service_announce_new(struct sockaddr_qrtr *dest,
110                                 struct qrtr_server *srv)
111 {
112         struct qrtr_ctrl_pkt pkt;
113         struct msghdr msg = { };
114         struct kvec iv;
115
116         trace_qrtr_ns_service_announce_new(srv->service, srv->instance,
117                                            srv->node, srv->port);
118
119         iv.iov_base = &pkt;
120         iv.iov_len = sizeof(pkt);
121
122         memset(&pkt, 0, sizeof(pkt));
123         pkt.cmd = cpu_to_le32(QRTR_TYPE_NEW_SERVER);
124         pkt.server.service = cpu_to_le32(srv->service);
125         pkt.server.instance = cpu_to_le32(srv->instance);
126         pkt.server.node = cpu_to_le32(srv->node);
127         pkt.server.port = cpu_to_le32(srv->port);
128
129         msg.msg_name = (struct sockaddr *)dest;
130         msg.msg_namelen = sizeof(*dest);
131
132         return kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
133 }
134
135 static int service_announce_del(struct sockaddr_qrtr *dest,
136                                 struct qrtr_server *srv)
137 {
138         struct qrtr_ctrl_pkt pkt;
139         struct msghdr msg = { };
140         struct kvec iv;
141         int ret;
142
143         trace_qrtr_ns_service_announce_del(srv->service, srv->instance,
144                                            srv->node, srv->port);
145
146         iv.iov_base = &pkt;
147         iv.iov_len = sizeof(pkt);
148
149         memset(&pkt, 0, sizeof(pkt));
150         pkt.cmd = cpu_to_le32(QRTR_TYPE_DEL_SERVER);
151         pkt.server.service = cpu_to_le32(srv->service);
152         pkt.server.instance = cpu_to_le32(srv->instance);
153         pkt.server.node = cpu_to_le32(srv->node);
154         pkt.server.port = cpu_to_le32(srv->port);
155
156         msg.msg_name = (struct sockaddr *)dest;
157         msg.msg_namelen = sizeof(*dest);
158
159         ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
160         if (ret < 0)
161                 pr_err("failed to announce del service\n");
162
163         return ret;
164 }
165
166 static void lookup_notify(struct sockaddr_qrtr *to, struct qrtr_server *srv,
167                           bool new)
168 {
169         struct qrtr_ctrl_pkt pkt;
170         struct msghdr msg = { };
171         struct kvec iv;
172         int ret;
173
174         iv.iov_base = &pkt;
175         iv.iov_len = sizeof(pkt);
176
177         memset(&pkt, 0, sizeof(pkt));
178         pkt.cmd = new ? cpu_to_le32(QRTR_TYPE_NEW_SERVER) :
179                         cpu_to_le32(QRTR_TYPE_DEL_SERVER);
180         if (srv) {
181                 pkt.server.service = cpu_to_le32(srv->service);
182                 pkt.server.instance = cpu_to_le32(srv->instance);
183                 pkt.server.node = cpu_to_le32(srv->node);
184                 pkt.server.port = cpu_to_le32(srv->port);
185         }
186
187         msg.msg_name = (struct sockaddr *)to;
188         msg.msg_namelen = sizeof(*to);
189
190         ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
191         if (ret < 0)
192                 pr_err("failed to send lookup notification\n");
193 }
194
195 static int announce_servers(struct sockaddr_qrtr *sq)
196 {
197         struct qrtr_server *srv;
198         struct qrtr_node *node;
199         unsigned long index;
200         int ret;
201
202         node = node_get(qrtr_ns.local_node);
203         if (!node)
204                 return 0;
205
206         /* Announce the list of servers registered in this node */
207         xa_for_each(&node->servers, index, srv) {
208                 ret = service_announce_new(sq, srv);
209                 if (ret < 0) {
210                         pr_err("failed to announce new service\n");
211                         return ret;
212                 }
213         }
214         return 0;
215 }
216
217 static struct qrtr_server *server_add(unsigned int service,
218                                       unsigned int instance,
219                                       unsigned int node_id,
220                                       unsigned int port)
221 {
222         struct qrtr_server *srv;
223         struct qrtr_server *old;
224         struct qrtr_node *node;
225
226         if (!service || !port)
227                 return NULL;
228
229         srv = kzalloc(sizeof(*srv), GFP_KERNEL);
230         if (!srv)
231                 return NULL;
232
233         srv->service = service;
234         srv->instance = instance;
235         srv->node = node_id;
236         srv->port = port;
237
238         node = node_get(node_id);
239         if (!node)
240                 goto err;
241
242         /* Delete the old server on the same port */
243         old = xa_store(&node->servers, port, srv, GFP_KERNEL);
244         if (old) {
245                 if (xa_is_err(old)) {
246                         pr_err("failed to add server [0x%x:0x%x] ret:%d\n",
247                                srv->service, srv->instance, xa_err(old));
248                         goto err;
249                 } else {
250                         kfree(old);
251                 }
252         }
253
254         trace_qrtr_ns_server_add(srv->service, srv->instance,
255                                  srv->node, srv->port);
256
257         return srv;
258
259 err:
260         kfree(srv);
261         return NULL;
262 }
263
264 static int server_del(struct qrtr_node *node, unsigned int port, bool bcast)
265 {
266         struct qrtr_lookup *lookup;
267         struct qrtr_server *srv;
268         struct list_head *li;
269
270         srv = xa_load(&node->servers, port);
271         if (!srv)
272                 return -ENOENT;
273
274         xa_erase(&node->servers, port);
275
276         /* Broadcast the removal of local servers */
277         if (srv->node == qrtr_ns.local_node && bcast)
278                 service_announce_del(&qrtr_ns.bcast_sq, srv);
279
280         /* Announce the service's disappearance to observers */
281         list_for_each(li, &qrtr_ns.lookups) {
282                 lookup = container_of(li, struct qrtr_lookup, li);
283                 if (lookup->service && lookup->service != srv->service)
284                         continue;
285                 if (lookup->instance && lookup->instance != srv->instance)
286                         continue;
287
288                 lookup_notify(&lookup->sq, srv, false);
289         }
290
291         kfree(srv);
292
293         return 0;
294 }
295
296 static int say_hello(struct sockaddr_qrtr *dest)
297 {
298         struct qrtr_ctrl_pkt pkt;
299         struct msghdr msg = { };
300         struct kvec iv;
301         int ret;
302
303         iv.iov_base = &pkt;
304         iv.iov_len = sizeof(pkt);
305
306         memset(&pkt, 0, sizeof(pkt));
307         pkt.cmd = cpu_to_le32(QRTR_TYPE_HELLO);
308
309         msg.msg_name = (struct sockaddr *)dest;
310         msg.msg_namelen = sizeof(*dest);
311
312         ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
313         if (ret < 0)
314                 pr_err("failed to send hello msg\n");
315
316         return ret;
317 }
318
319 /* Announce the list of servers registered on the local node */
320 static int ctrl_cmd_hello(struct sockaddr_qrtr *sq)
321 {
322         int ret;
323
324         ret = say_hello(sq);
325         if (ret < 0)
326                 return ret;
327
328         return announce_servers(sq);
329 }
330
331 static int ctrl_cmd_bye(struct sockaddr_qrtr *from)
332 {
333         struct qrtr_node *local_node;
334         struct qrtr_ctrl_pkt pkt;
335         struct qrtr_server *srv;
336         struct sockaddr_qrtr sq;
337         struct msghdr msg = { };
338         struct qrtr_node *node;
339         unsigned long index;
340         struct kvec iv;
341         int ret;
342
343         iv.iov_base = &pkt;
344         iv.iov_len = sizeof(pkt);
345
346         node = node_get(from->sq_node);
347         if (!node)
348                 return 0;
349
350         /* Advertise removal of this client to all servers of remote node */
351         xa_for_each(&node->servers, index, srv)
352                 server_del(node, srv->port, true);
353
354         /* Advertise the removal of this client to all local servers */
355         local_node = node_get(qrtr_ns.local_node);
356         if (!local_node)
357                 return 0;
358
359         memset(&pkt, 0, sizeof(pkt));
360         pkt.cmd = cpu_to_le32(QRTR_TYPE_BYE);
361         pkt.client.node = cpu_to_le32(from->sq_node);
362
363         xa_for_each(&local_node->servers, index, srv) {
364                 sq.sq_family = AF_QIPCRTR;
365                 sq.sq_node = srv->node;
366                 sq.sq_port = srv->port;
367
368                 msg.msg_name = (struct sockaddr *)&sq;
369                 msg.msg_namelen = sizeof(sq);
370
371                 ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
372                 if (ret < 0) {
373                         pr_err("failed to send bye cmd\n");
374                         return ret;
375                 }
376         }
377         return 0;
378 }
379
380 static int ctrl_cmd_del_client(struct sockaddr_qrtr *from,
381                                unsigned int node_id, unsigned int port)
382 {
383         struct qrtr_node *local_node;
384         struct qrtr_lookup *lookup;
385         struct qrtr_ctrl_pkt pkt;
386         struct msghdr msg = { };
387         struct qrtr_server *srv;
388         struct sockaddr_qrtr sq;
389         struct qrtr_node *node;
390         struct list_head *tmp;
391         struct list_head *li;
392         unsigned long index;
393         struct kvec iv;
394         int ret;
395
396         iv.iov_base = &pkt;
397         iv.iov_len = sizeof(pkt);
398
399         /* Don't accept spoofed messages */
400         if (from->sq_node != node_id)
401                 return -EINVAL;
402
403         /* Local DEL_CLIENT messages comes from the port being closed */
404         if (from->sq_node == qrtr_ns.local_node && from->sq_port != port)
405                 return -EINVAL;
406
407         /* Remove any lookups by this client */
408         list_for_each_safe(li, tmp, &qrtr_ns.lookups) {
409                 lookup = container_of(li, struct qrtr_lookup, li);
410                 if (lookup->sq.sq_node != node_id)
411                         continue;
412                 if (lookup->sq.sq_port != port)
413                         continue;
414
415                 list_del(&lookup->li);
416                 kfree(lookup);
417         }
418
419         /* Remove the server belonging to this port but don't broadcast
420          * DEL_SERVER. Neighbours would've already removed the server belonging
421          * to this port due to the DEL_CLIENT broadcast from qrtr_port_remove().
422          */
423         node = node_get(node_id);
424         if (node)
425                 server_del(node, port, false);
426
427         /* Advertise the removal of this client to all local servers */
428         local_node = node_get(qrtr_ns.local_node);
429         if (!local_node)
430                 return 0;
431
432         memset(&pkt, 0, sizeof(pkt));
433         pkt.cmd = cpu_to_le32(QRTR_TYPE_DEL_CLIENT);
434         pkt.client.node = cpu_to_le32(node_id);
435         pkt.client.port = cpu_to_le32(port);
436
437         xa_for_each(&local_node->servers, index, srv) {
438                 sq.sq_family = AF_QIPCRTR;
439                 sq.sq_node = srv->node;
440                 sq.sq_port = srv->port;
441
442                 msg.msg_name = (struct sockaddr *)&sq;
443                 msg.msg_namelen = sizeof(sq);
444
445                 ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
446                 if (ret < 0) {
447                         pr_err("failed to send del client cmd\n");
448                         return ret;
449                 }
450         }
451         return 0;
452 }
453
454 static int ctrl_cmd_new_server(struct sockaddr_qrtr *from,
455                                unsigned int service, unsigned int instance,
456                                unsigned int node_id, unsigned int port)
457 {
458         struct qrtr_lookup *lookup;
459         struct qrtr_server *srv;
460         struct list_head *li;
461         int ret = 0;
462
463         /* Ignore specified node and port for local servers */
464         if (from->sq_node == qrtr_ns.local_node) {
465                 node_id = from->sq_node;
466                 port = from->sq_port;
467         }
468
469         srv = server_add(service, instance, node_id, port);
470         if (!srv)
471                 return -EINVAL;
472
473         if (srv->node == qrtr_ns.local_node) {
474                 ret = service_announce_new(&qrtr_ns.bcast_sq, srv);
475                 if (ret < 0) {
476                         pr_err("failed to announce new service\n");
477                         return ret;
478                 }
479         }
480
481         /* Notify any potential lookups about the new server */
482         list_for_each(li, &qrtr_ns.lookups) {
483                 lookup = container_of(li, struct qrtr_lookup, li);
484                 if (lookup->service && lookup->service != service)
485                         continue;
486                 if (lookup->instance && lookup->instance != instance)
487                         continue;
488
489                 lookup_notify(&lookup->sq, srv, true);
490         }
491
492         return ret;
493 }
494
495 static int ctrl_cmd_del_server(struct sockaddr_qrtr *from,
496                                unsigned int service, unsigned int instance,
497                                unsigned int node_id, unsigned int port)
498 {
499         struct qrtr_node *node;
500
501         /* Ignore specified node and port for local servers*/
502         if (from->sq_node == qrtr_ns.local_node) {
503                 node_id = from->sq_node;
504                 port = from->sq_port;
505         }
506
507         /* Local servers may only unregister themselves */
508         if (from->sq_node == qrtr_ns.local_node && from->sq_port != port)
509                 return -EINVAL;
510
511         node = node_get(node_id);
512         if (!node)
513                 return -ENOENT;
514
515         return server_del(node, port, true);
516 }
517
518 static int ctrl_cmd_new_lookup(struct sockaddr_qrtr *from,
519                                unsigned int service, unsigned int instance)
520 {
521         struct qrtr_server_filter filter;
522         struct qrtr_lookup *lookup;
523         struct qrtr_server *srv;
524         struct qrtr_node *node;
525         unsigned long node_idx;
526         unsigned long srv_idx;
527
528         /* Accept only local observers */
529         if (from->sq_node != qrtr_ns.local_node)
530                 return -EINVAL;
531
532         lookup = kzalloc(sizeof(*lookup), GFP_KERNEL);
533         if (!lookup)
534                 return -ENOMEM;
535
536         lookup->sq = *from;
537         lookup->service = service;
538         lookup->instance = instance;
539         list_add_tail(&lookup->li, &qrtr_ns.lookups);
540
541         memset(&filter, 0, sizeof(filter));
542         filter.service = service;
543         filter.instance = instance;
544
545         xa_for_each(&nodes, node_idx, node) {
546                 xa_for_each(&node->servers, srv_idx, srv) {
547                         if (!server_match(srv, &filter))
548                                 continue;
549
550                         lookup_notify(from, srv, true);
551                 }
552         }
553
554         /* Empty notification, to indicate end of listing */
555         lookup_notify(from, NULL, true);
556
557         return 0;
558 }
559
560 static void ctrl_cmd_del_lookup(struct sockaddr_qrtr *from,
561                                 unsigned int service, unsigned int instance)
562 {
563         struct qrtr_lookup *lookup;
564         struct list_head *tmp;
565         struct list_head *li;
566
567         list_for_each_safe(li, tmp, &qrtr_ns.lookups) {
568                 lookup = container_of(li, struct qrtr_lookup, li);
569                 if (lookup->sq.sq_node != from->sq_node)
570                         continue;
571                 if (lookup->sq.sq_port != from->sq_port)
572                         continue;
573                 if (lookup->service != service)
574                         continue;
575                 if (lookup->instance && lookup->instance != instance)
576                         continue;
577
578                 list_del(&lookup->li);
579                 kfree(lookup);
580         }
581 }
582
583 static void qrtr_ns_worker(struct work_struct *work)
584 {
585         const struct qrtr_ctrl_pkt *pkt;
586         size_t recv_buf_size = 4096;
587         struct sockaddr_qrtr sq;
588         struct msghdr msg = { };
589         unsigned int cmd;
590         ssize_t msglen;
591         void *recv_buf;
592         struct kvec iv;
593         int ret;
594
595         msg.msg_name = (struct sockaddr *)&sq;
596         msg.msg_namelen = sizeof(sq);
597
598         recv_buf = kzalloc(recv_buf_size, GFP_KERNEL);
599         if (!recv_buf)
600                 return;
601
602         for (;;) {
603                 iv.iov_base = recv_buf;
604                 iv.iov_len = recv_buf_size;
605
606                 msglen = kernel_recvmsg(qrtr_ns.sock, &msg, &iv, 1,
607                                         iv.iov_len, MSG_DONTWAIT);
608
609                 if (msglen == -EAGAIN)
610                         break;
611
612                 if (msglen < 0) {
613                         pr_err("error receiving packet: %zd\n", msglen);
614                         break;
615                 }
616
617                 pkt = recv_buf;
618                 cmd = le32_to_cpu(pkt->cmd);
619                 if (cmd < ARRAY_SIZE(qrtr_ctrl_pkt_strings) &&
620                     qrtr_ctrl_pkt_strings[cmd])
621                         trace_qrtr_ns_message(qrtr_ctrl_pkt_strings[cmd],
622                                               sq.sq_node, sq.sq_port);
623
624                 ret = 0;
625                 switch (cmd) {
626                 case QRTR_TYPE_HELLO:
627                         ret = ctrl_cmd_hello(&sq);
628                         break;
629                 case QRTR_TYPE_BYE:
630                         ret = ctrl_cmd_bye(&sq);
631                         break;
632                 case QRTR_TYPE_DEL_CLIENT:
633                         ret = ctrl_cmd_del_client(&sq,
634                                         le32_to_cpu(pkt->client.node),
635                                         le32_to_cpu(pkt->client.port));
636                         break;
637                 case QRTR_TYPE_NEW_SERVER:
638                         ret = ctrl_cmd_new_server(&sq,
639                                         le32_to_cpu(pkt->server.service),
640                                         le32_to_cpu(pkt->server.instance),
641                                         le32_to_cpu(pkt->server.node),
642                                         le32_to_cpu(pkt->server.port));
643                         break;
644                 case QRTR_TYPE_DEL_SERVER:
645                         ret = ctrl_cmd_del_server(&sq,
646                                          le32_to_cpu(pkt->server.service),
647                                          le32_to_cpu(pkt->server.instance),
648                                          le32_to_cpu(pkt->server.node),
649                                          le32_to_cpu(pkt->server.port));
650                         break;
651                 case QRTR_TYPE_EXIT:
652                 case QRTR_TYPE_PING:
653                 case QRTR_TYPE_RESUME_TX:
654                         break;
655                 case QRTR_TYPE_NEW_LOOKUP:
656                         ret = ctrl_cmd_new_lookup(&sq,
657                                          le32_to_cpu(pkt->server.service),
658                                          le32_to_cpu(pkt->server.instance));
659                         break;
660                 case QRTR_TYPE_DEL_LOOKUP:
661                         ctrl_cmd_del_lookup(&sq,
662                                     le32_to_cpu(pkt->server.service),
663                                     le32_to_cpu(pkt->server.instance));
664                         break;
665                 }
666
667                 if (ret < 0)
668                         pr_err("failed while handling packet from %d:%d",
669                                sq.sq_node, sq.sq_port);
670         }
671
672         kfree(recv_buf);
673 }
674
675 static void qrtr_ns_data_ready(struct sock *sk)
676 {
677         trace_sk_data_ready(sk);
678
679         queue_work(qrtr_ns.workqueue, &qrtr_ns.work);
680 }
681
682 int qrtr_ns_init(void)
683 {
684         struct sockaddr_qrtr sq;
685         int ret;
686
687         INIT_LIST_HEAD(&qrtr_ns.lookups);
688         INIT_WORK(&qrtr_ns.work, qrtr_ns_worker);
689
690         ret = sock_create_kern(&init_net, AF_QIPCRTR, SOCK_DGRAM,
691                                PF_QIPCRTR, &qrtr_ns.sock);
692         if (ret < 0)
693                 return ret;
694
695         ret = kernel_getsockname(qrtr_ns.sock, (struct sockaddr *)&sq);
696         if (ret < 0) {
697                 pr_err("failed to get socket name\n");
698                 goto err_sock;
699         }
700
701         qrtr_ns.workqueue = alloc_ordered_workqueue("qrtr_ns_handler", 0);
702         if (!qrtr_ns.workqueue) {
703                 ret = -ENOMEM;
704                 goto err_sock;
705         }
706
707         qrtr_ns.sock->sk->sk_data_ready = qrtr_ns_data_ready;
708
709         sq.sq_port = QRTR_PORT_CTRL;
710         qrtr_ns.local_node = sq.sq_node;
711
712         ret = kernel_bind(qrtr_ns.sock, (struct sockaddr *)&sq, sizeof(sq));
713         if (ret < 0) {
714                 pr_err("failed to bind to socket\n");
715                 goto err_wq;
716         }
717
718         qrtr_ns.bcast_sq.sq_family = AF_QIPCRTR;
719         qrtr_ns.bcast_sq.sq_node = QRTR_NODE_BCAST;
720         qrtr_ns.bcast_sq.sq_port = QRTR_PORT_CTRL;
721
722         ret = say_hello(&qrtr_ns.bcast_sq);
723         if (ret < 0)
724                 goto err_wq;
725
726         return 0;
727
728 err_wq:
729         destroy_workqueue(qrtr_ns.workqueue);
730 err_sock:
731         sock_release(qrtr_ns.sock);
732         return ret;
733 }
734 EXPORT_SYMBOL_GPL(qrtr_ns_init);
735
736 void qrtr_ns_remove(void)
737 {
738         cancel_work_sync(&qrtr_ns.work);
739         destroy_workqueue(qrtr_ns.workqueue);
740         sock_release(qrtr_ns.sock);
741 }
742 EXPORT_SYMBOL_GPL(qrtr_ns_remove);
743
744 MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
745 MODULE_DESCRIPTION("Qualcomm IPC Router Nameservice");
746 MODULE_LICENSE("Dual BSD/GPL");