History

Merge branch 'Migrate-QRTR-Nameservice-to-Kernel'

Manivannan Sadhasivam says: ==================== Migrate QRTR Nameservice to Kernel This patchset migrates the Qualcomm IPC Router (QRTR) Nameservice from userspace to kernel under net/qrtr. The userspace implementation of it can be found here: https://github.com/andersson/qrtr/blob/master/src/ns.c This change is required for enabling the WiFi functionality of some Qualcomm WLAN devices using ATH11K without any dependency on a userspace daemon. Since the QRTR NS is not usually packed in most of the distros, users need to clone, build and install it to get the WiFi working. It will become a hassle when the user doesn't have any other source of network connectivity. The original userspace code is published under BSD3 license. For migrating it to Linux kernel, I have adapted Dual BSD/GPL license. This patchset has been verified on Dragonboard410c and Intel NUC with QCA6390 WLAN device. Changes in v2: * Sorted the local variables in reverse XMAS tree order ====================

David S. Miller committed 6 years ago

Commit b4d97852 parents cd26d72 31d6cbe4 files · +767 −41Browse files

Unified · Split

4 files
  1. net/qrtr/Makefile +1 −1
  2. net/qrtr/ns.c +751 −0
  3. net/qrtr/qrtr.c +11 −40
  4. net/qrtr/qrtr.h +4 −0
net/qrtr/Makefile+1−1
@@ -1,5 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2obj-$(CONFIG_QRTR) := qrtr.o2obj-$(CONFIG_QRTR) := qrtr.o ns.o
3 3
4obj-$(CONFIG_QRTR_SMD) += qrtr-smd.o4obj-$(CONFIG_QRTR_SMD) += qrtr-smd.o
5qrtr-smd-y := smd.o5qrtr-smd-y := smd.o
net/qrtr/ns.c+751−0
@@ -0,0 +1,751 @@
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
15static RADIX_TREE(nodes, GFP_KERNEL);
16
17static struct {
18 struct socket *sock;
19 struct sockaddr_qrtr bcast_sq;
20 struct list_head lookups;
21 struct workqueue_struct *workqueue;
22 struct work_struct work;
23 int local_node;
24} qrtr_ns;
25
26static const char * const qrtr_ctrl_pkt_strings[] = {
27 [QRTR_TYPE_HELLO] = "hello",
28 [QRTR_TYPE_BYE] = "bye",
29 [QRTR_TYPE_NEW_SERVER] = "new-server",
30 [QRTR_TYPE_DEL_SERVER] = "del-server",
31 [QRTR_TYPE_DEL_CLIENT] = "del-client",
32 [QRTR_TYPE_RESUME_TX] = "resume-tx",
33 [QRTR_TYPE_EXIT] = "exit",
34 [QRTR_TYPE_PING] = "ping",
35 [QRTR_TYPE_NEW_LOOKUP] = "new-lookup",
36 [QRTR_TYPE_DEL_LOOKUP] = "del-lookup",
37};
38
39struct qrtr_server_filter {
40 unsigned int service;
41 unsigned int instance;
42 unsigned int ifilter;
43};
44
45struct qrtr_lookup {
46 unsigned int service;
47 unsigned int instance;
48
49 struct sockaddr_qrtr sq;
50 struct list_head li;
51};
52
53struct qrtr_server {
54 unsigned int service;
55 unsigned int instance;
56
57 unsigned int node;
58 unsigned int port;
59
60 struct list_head qli;
61};
62
63struct qrtr_node {
64 unsigned int id;
65 struct radix_tree_root servers;
66};
67
68static struct qrtr_node *node_get(unsigned int node_id)
69{
70 struct qrtr_node *node;
71
72 node = radix_tree_lookup(&nodes, node_id);
73 if (node)
74 return node;
75
76 /* If node didn't exist, allocate and insert it to the tree */
77 node = kzalloc(sizeof(*node), GFP_KERNEL);
78 if (!node)
79 return ERR_PTR(-ENOMEM);
80
81 node->id = node_id;
82
83 radix_tree_insert(&nodes, node_id, node);
84
85 return node;
86}
87
88static int server_match(const struct qrtr_server *srv,
89 const struct qrtr_server_filter *f)
90{
91 unsigned int ifilter = f->ifilter;
92
93 if (f->service != 0 && srv->service != f->service)
94 return 0;
95 if (!ifilter && f->instance)
96 ifilter = ~0;
97
98 return (srv->instance & ifilter) == f->instance;
99}
100
101static int service_announce_new(struct sockaddr_qrtr *dest,
102 struct qrtr_server *srv)
103{
104 struct qrtr_ctrl_pkt pkt;
105 struct msghdr msg = { };
106 struct kvec iv;
107
108 trace_printk("advertising new server [%d:%x]@[%d:%d]\n",
109 srv->service, srv->instance, srv->node, srv->port);
110
111 iv.iov_base = &pkt;
112 iv.iov_len = sizeof(pkt);
113
114 memset(&pkt, 0, sizeof(pkt));
115 pkt.cmd = cpu_to_le32(QRTR_TYPE_NEW_SERVER);
116 pkt.server.service = cpu_to_le32(srv->service);
117 pkt.server.instance = cpu_to_le32(srv->instance);
118 pkt.server.node = cpu_to_le32(srv->node);
119 pkt.server.port = cpu_to_le32(srv->port);
120
121 msg.msg_name = (struct sockaddr *)dest;
122 msg.msg_namelen = sizeof(*dest);
123
124 return kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
125}
126
127static int service_announce_del(struct sockaddr_qrtr *dest,
128 struct qrtr_server *srv)
129{
130 struct qrtr_ctrl_pkt pkt;
131 struct msghdr msg = { };
132 struct kvec iv;
133 int ret;
134
135 trace_printk("advertising removal of server [%d:%x]@[%d:%d]\n",
136 srv->service, srv->instance, srv->node, srv->port);
137
138 iv.iov_base = &pkt;
139 iv.iov_len = sizeof(pkt);
140
141 memset(&pkt, 0, sizeof(pkt));
142 pkt.cmd = cpu_to_le32(QRTR_TYPE_DEL_SERVER);
143 pkt.server.service = cpu_to_le32(srv->service);
144 pkt.server.instance = cpu_to_le32(srv->instance);
145 pkt.server.node = cpu_to_le32(srv->node);
146 pkt.server.port = cpu_to_le32(srv->port);
147
148 msg.msg_name = (struct sockaddr *)dest;
149 msg.msg_namelen = sizeof(*dest);
150
151 ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
152 if (ret < 0)
153 pr_err("failed to announce del serivce\n");
154
155 return ret;
156}
157
158static void lookup_notify(struct sockaddr_qrtr *to, struct qrtr_server *srv,
159 bool new)
160{
161 struct qrtr_ctrl_pkt pkt;
162 struct msghdr msg = { };
163 struct kvec iv;
164 int ret;
165
166 iv.iov_base = &pkt;
167 iv.iov_len = sizeof(pkt);
168
169 memset(&pkt, 0, sizeof(pkt));
170 pkt.cmd = new ? cpu_to_le32(QRTR_TYPE_NEW_SERVER) :
171 cpu_to_le32(QRTR_TYPE_DEL_SERVER);
172 if (srv) {
173 pkt.server.service = cpu_to_le32(srv->service);
174 pkt.server.instance = cpu_to_le32(srv->instance);
175 pkt.server.node = cpu_to_le32(srv->node);
176 pkt.server.port = cpu_to_le32(srv->port);
177 }
178
179 msg.msg_name = (struct sockaddr *)to;
180 msg.msg_namelen = sizeof(*to);
181
182 ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
183 if (ret < 0)
184 pr_err("failed to send lookup notification\n");
185}
186
187static int announce_servers(struct sockaddr_qrtr *sq)
188{
189 struct radix_tree_iter iter;
190 struct qrtr_server *srv;
191 struct qrtr_node *node;
192 void __rcu **slot;
193 int ret;
194
195 node = node_get(qrtr_ns.local_node);
196 if (!node)
197 return 0;
198
199 /* Announce the list of servers registered in this node */
200 radix_tree_for_each_slot(slot, &node->servers, &iter, 0) {
201 srv = radix_tree_deref_slot(slot);
202
203 ret = service_announce_new(sq, srv);
204 if (ret < 0) {
205 pr_err("failed to announce new service\n");
206 return ret;
207 }
208 }
209
210 return 0;
211}
212
213static struct qrtr_server *server_add(unsigned int service,
214 unsigned int instance,
215 unsigned int node_id,
216 unsigned int port)
217{
218 struct qrtr_server *srv;
219 struct qrtr_server *old;
220 struct qrtr_node *node;
221
222 if (!service || !port)
223 return NULL;
224
225 srv = kzalloc(sizeof(*srv), GFP_KERNEL);
226 if (!srv)
227 return ERR_PTR(-ENOMEM);
228
229 srv->service = service;
230 srv->instance = instance;
231 srv->node = node_id;
232 srv->port = port;
233
234 node = node_get(node_id);
235 if (!node)
236 goto err;
237
238 /* Delete the old server on the same port */
239 old = radix_tree_lookup(&node->servers, port);
240 if (old) {
241 radix_tree_delete(&node->servers, port);
242 kfree(old);
243 }
244
245 radix_tree_insert(&node->servers, port, srv);
246
247 trace_printk("add server [%d:%x]@[%d:%d]\n", srv->service,
248 srv->instance, srv->node, srv->port);
249
250 return srv;
251
252err:
253 kfree(srv);
254 return NULL;
255}
256
257static int server_del(struct qrtr_node *node, unsigned int port)
258{
259 struct qrtr_lookup *lookup;
260 struct qrtr_server *srv;
261 struct list_head *li;
262
263 srv = radix_tree_lookup(&node->servers, port);
264 if (!srv)
265 return -ENOENT;
266
267 radix_tree_delete(&node->servers, port);
268
269 /* Broadcast the removal of local servers */
270 if (srv->node == qrtr_ns.local_node)
271 service_announce_del(&qrtr_ns.bcast_sq, srv);
272
273 /* Announce the service's disappearance to observers */
274 list_for_each(li, &qrtr_ns.lookups) {
275 lookup = container_of(li, struct qrtr_lookup, li);
276 if (lookup->service && lookup->service != srv->service)
277 continue;
278 if (lookup->instance && lookup->instance != srv->instance)
279 continue;
280
281 lookup_notify(&lookup->sq, srv, false);
282 }
283
284 kfree(srv);
285
286 return 0;
287}
288
289/* Announce the list of servers registered on the local node */
290static int ctrl_cmd_hello(struct sockaddr_qrtr *sq)
291{
292 return announce_servers(sq);
293}
294
295static int ctrl_cmd_bye(struct sockaddr_qrtr *from)
296{
297 struct qrtr_node *local_node;
298 struct radix_tree_iter iter;
299 struct qrtr_ctrl_pkt pkt;
300 struct qrtr_server *srv;
301 struct sockaddr_qrtr sq;
302 struct msghdr msg = { };
303 struct qrtr_node *node;
304 void __rcu **slot;
305 struct kvec iv;
306 int ret;
307
308 iv.iov_base = &pkt;
309 iv.iov_len = sizeof(pkt);
310
311 node = node_get(from->sq_node);
312 if (!node)
313 return 0;
314
315 /* Advertise removal of this client to all servers of remote node */
316 radix_tree_for_each_slot(slot, &node->servers, &iter, 0) {
317 srv = radix_tree_deref_slot(slot);
318 server_del(node, srv->port);
319 }
320
321 /* Advertise the removal of this client to all local servers */
322 local_node = node_get(qrtr_ns.local_node);
323 if (!local_node)
324 return 0;
325
326 memset(&pkt, 0, sizeof(pkt));
327 pkt.cmd = cpu_to_le32(QRTR_TYPE_BYE);
328 pkt.client.node = cpu_to_le32(from->sq_node);
329
330 radix_tree_for_each_slot(slot, &local_node->servers, &iter, 0) {
331 srv = radix_tree_deref_slot(slot);
332
333 sq.sq_family = AF_QIPCRTR;
334 sq.sq_node = srv->node;
335 sq.sq_port = srv->port;
336
337 msg.msg_name = (struct sockaddr *)&sq;
338 msg.msg_namelen = sizeof(sq);
339
340 ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
341 if (ret < 0) {
342 pr_err("failed to send bye cmd\n");
343 return ret;
344 }
345 }
346
347 return 0;
348}
349
350static int ctrl_cmd_del_client(struct sockaddr_qrtr *from,
351 unsigned int node_id, unsigned int port)
352{
353 struct qrtr_node *local_node;
354 struct radix_tree_iter iter;
355 struct qrtr_lookup *lookup;
356 struct qrtr_ctrl_pkt pkt;
357 struct msghdr msg = { };
358 struct qrtr_server *srv;
359 struct sockaddr_qrtr sq;
360 struct qrtr_node *node;
361 struct list_head *tmp;
362 struct list_head *li;
363 void __rcu **slot;
364 struct kvec iv;
365 int ret;
366
367 iv.iov_base = &pkt;
368 iv.iov_len = sizeof(pkt);
369
370 /* Don't accept spoofed messages */
371 if (from->sq_node != node_id)
372 return -EINVAL;
373
374 /* Local DEL_CLIENT messages comes from the port being closed */
375 if (from->sq_node == qrtr_ns.local_node && from->sq_port != port)
376 return -EINVAL;
377
378 /* Remove any lookups by this client */
379 list_for_each_safe(li, tmp, &qrtr_ns.lookups) {
380 lookup = container_of(li, struct qrtr_lookup, li);
381 if (lookup->sq.sq_node != node_id)
382 continue;
383 if (lookup->sq.sq_port != port)
384 continue;
385
386 list_del(&lookup->li);
387 kfree(lookup);
388 }
389
390 /* Remove the server belonging to this port */
391 node = node_get(node_id);
392 if (node)
393 server_del(node, port);
394
395 /* Advertise the removal of this client to all local servers */
396 local_node = node_get(qrtr_ns.local_node);
397 if (!local_node)
398 return 0;
399
400 memset(&pkt, 0, sizeof(pkt));
401 pkt.cmd = cpu_to_le32(QRTR_TYPE_DEL_CLIENT);
402 pkt.client.node = cpu_to_le32(node_id);
403 pkt.client.port = cpu_to_le32(port);
404
405 radix_tree_for_each_slot(slot, &local_node->servers, &iter, 0) {
406 srv = radix_tree_deref_slot(slot);
407
408 sq.sq_family = AF_QIPCRTR;
409 sq.sq_node = srv->node;
410 sq.sq_port = srv->port;
411
412 msg.msg_name = (struct sockaddr *)&sq;
413 msg.msg_namelen = sizeof(sq);
414
415 ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
416 if (ret < 0) {
417 pr_err("failed to send del client cmd\n");
418 return ret;
419 }
420 }
421
422 return 0;
423}
424
425static int ctrl_cmd_new_server(struct sockaddr_qrtr *from,
426 unsigned int service, unsigned int instance,
427 unsigned int node_id, unsigned int port)
428{
429 struct qrtr_lookup *lookup;
430 struct qrtr_server *srv;
431 struct list_head *li;
432 int ret = 0;
433
434 /* Ignore specified node and port for local servers */
435 if (from->sq_node == qrtr_ns.local_node) {
436 node_id = from->sq_node;
437 port = from->sq_port;
438 }
439
440 /* Don't accept spoofed messages */
441 if (from->sq_node != node_id)
442 return -EINVAL;
443
444 srv = server_add(service, instance, node_id, port);
445 if (!srv)
446 return -EINVAL;
447
448 if (srv->node == qrtr_ns.local_node) {
449 ret = service_announce_new(&qrtr_ns.bcast_sq, srv);
450 if (ret < 0) {
451 pr_err("failed to announce new service\n");
452 return ret;
453 }
454 }
455
456 /* Notify any potential lookups about the new server */
457 list_for_each(li, &qrtr_ns.lookups) {
458 lookup = container_of(li, struct qrtr_lookup, li);
459 if (lookup->service && lookup->service != service)
460 continue;
461 if (lookup->instance && lookup->instance != instance)
462 continue;
463
464 lookup_notify(&lookup->sq, srv, true);
465 }
466
467 return ret;
468}
469
470static int ctrl_cmd_del_server(struct sockaddr_qrtr *from,
471 unsigned int service, unsigned int instance,
472 unsigned int node_id, unsigned int port)
473{
474 struct qrtr_node *node;
475
476 /* Ignore specified node and port for local servers*/
477 if (from->sq_node == qrtr_ns.local_node) {
478 node_id = from->sq_node;
479 port = from->sq_port;
480 }
481
482 /* Don't accept spoofed messages */
483 if (from->sq_node != node_id)
484 return -EINVAL;
485
486 /* Local servers may only unregister themselves */
487 if (from->sq_node == qrtr_ns.local_node && from->sq_port != port)
488 return -EINVAL;
489
490 node = node_get(node_id);
491 if (!node)
492 return -ENOENT;
493
494 return server_del(node, port);
495}
496
497static int ctrl_cmd_new_lookup(struct sockaddr_qrtr *from,
498 unsigned int service, unsigned int instance)
499{
500 struct radix_tree_iter node_iter;
501 struct qrtr_server_filter filter;
502 struct radix_tree_iter srv_iter;
503 struct qrtr_lookup *lookup;
504 struct qrtr_node *node;
505 void __rcu **node_slot;
506 void __rcu **srv_slot;
507
508 /* Accept only local observers */
509 if (from->sq_node != qrtr_ns.local_node)
510 return -EINVAL;
511
512 lookup = kzalloc(sizeof(*lookup), GFP_KERNEL);
513 if (!lookup)
514 return -ENOMEM;
515
516 lookup->sq = *from;
517 lookup->service = service;
518 lookup->instance = instance;
519 list_add_tail(&lookup->li, &qrtr_ns.lookups);
520
521 memset(&filter, 0, sizeof(filter));
522 filter.service = service;
523 filter.instance = instance;
524
525 radix_tree_for_each_slot(node_slot, &nodes, &node_iter, 0) {
526 node = radix_tree_deref_slot(node_slot);
527
528 radix_tree_for_each_slot(srv_slot, &node->servers,
529 &srv_iter, 0) {
530 struct qrtr_server *srv;
531
532 srv = radix_tree_deref_slot(srv_slot);
533 if (!server_match(srv, &filter))
534 continue;
535
536 lookup_notify(from, srv, true);
537 }
538 }
539
540 /* Empty notification, to indicate end of listing */
541 lookup_notify(from, NULL, true);
542
543 return 0;
544}
545
546static void ctrl_cmd_del_lookup(struct sockaddr_qrtr *from,
547 unsigned int service, unsigned int instance)
548{
549 struct qrtr_lookup *lookup;
550 struct list_head *tmp;
551 struct list_head *li;
552
553 list_for_each_safe(li, tmp, &qrtr_ns.lookups) {
554 lookup = container_of(li, struct qrtr_lookup, li);
555 if (lookup->sq.sq_node != from->sq_node)
556 continue;
557 if (lookup->sq.sq_port != from->sq_port)
558 continue;
559 if (lookup->service != service)
560 continue;
561 if (lookup->instance && lookup->instance != instance)
562 continue;
563
564 list_del(&lookup->li);
565 kfree(lookup);
566 }
567}
568
569static int say_hello(void)
570{
571 struct qrtr_ctrl_pkt pkt;
572 struct msghdr msg = { };
573 struct kvec iv;
574 int ret;
575
576 iv.iov_base = &pkt;
577 iv.iov_len = sizeof(pkt);
578
579 memset(&pkt, 0, sizeof(pkt));
580 pkt.cmd = cpu_to_le32(QRTR_TYPE_HELLO);
581
582 msg.msg_name = (struct sockaddr *)&qrtr_ns.bcast_sq;
583 msg.msg_namelen = sizeof(qrtr_ns.bcast_sq);
584
585 ret = kernel_sendmsg(qrtr_ns.sock, &msg, &iv, 1, sizeof(pkt));
586 if (ret < 0)
587 pr_err("failed to send hello msg\n");
588
589 return ret;
590}
591
592static void qrtr_ns_worker(struct work_struct *work)
593{
594 const struct qrtr_ctrl_pkt *pkt;
595 size_t recv_buf_size = 4096;
596 struct sockaddr_qrtr sq;
597 struct msghdr msg = { };
598 unsigned int cmd;
599 ssize_t msglen;
600 void *recv_buf;
601 struct kvec iv;
602 int ret;
603
604 msg.msg_name = (struct sockaddr *)&sq;
605 msg.msg_namelen = sizeof(sq);
606
607 recv_buf = kzalloc(recv_buf_size, GFP_KERNEL);
608 if (!recv_buf)
609 return;
610
611 for (;;) {
612 iv.iov_base = recv_buf;
613 iv.iov_len = recv_buf_size;
614
615 msglen = kernel_recvmsg(qrtr_ns.sock, &msg, &iv, 1,
616 iv.iov_len, MSG_DONTWAIT);
617
618 if (msglen == -EAGAIN)
619 break;
620
621 if (msglen < 0) {
622 pr_err("error receiving packet: %zd\n", msglen);
623 break;
624 }
625
626 pkt = recv_buf;
627 cmd = le32_to_cpu(pkt->cmd);
628 if (cmd < ARRAY_SIZE(qrtr_ctrl_pkt_strings) &&
629 qrtr_ctrl_pkt_strings[cmd])
630 trace_printk("%s from %d:%d\n",
631 qrtr_ctrl_pkt_strings[cmd], sq.sq_node,
632 sq.sq_port);
633
634 ret = 0;
635 switch (cmd) {
636 case QRTR_TYPE_HELLO:
637 ret = ctrl_cmd_hello(&sq);
638 break;
639 case QRTR_TYPE_BYE:
640 ret = ctrl_cmd_bye(&sq);
641 break;
642 case QRTR_TYPE_DEL_CLIENT:
643 ret = ctrl_cmd_del_client(&sq,
644 le32_to_cpu(pkt->client.node),
645 le32_to_cpu(pkt->client.port));
646 break;
647 case QRTR_TYPE_NEW_SERVER:
648 ret = ctrl_cmd_new_server(&sq,
649 le32_to_cpu(pkt->server.service),
650 le32_to_cpu(pkt->server.instance),
651 le32_to_cpu(pkt->server.node),
652 le32_to_cpu(pkt->server.port));
653 break;
654 case QRTR_TYPE_DEL_SERVER:
655 ret = ctrl_cmd_del_server(&sq,
656 le32_to_cpu(pkt->server.service),
657 le32_to_cpu(pkt->server.instance),
658 le32_to_cpu(pkt->server.node),
659 le32_to_cpu(pkt->server.port));
660 break;
661 case QRTR_TYPE_EXIT:
662 case QRTR_TYPE_PING:
663 case QRTR_TYPE_RESUME_TX:
664 break;
665 case QRTR_TYPE_NEW_LOOKUP:
666 ret = ctrl_cmd_new_lookup(&sq,
667 le32_to_cpu(pkt->server.service),
668 le32_to_cpu(pkt->server.instance));
669 break;
670 case QRTR_TYPE_DEL_LOOKUP:
671 ctrl_cmd_del_lookup(&sq,
672 le32_to_cpu(pkt->server.service),
673 le32_to_cpu(pkt->server.instance));
674 break;
675 }
676
677 if (ret < 0)
678 pr_err("failed while handling packet from %d:%d",
679 sq.sq_node, sq.sq_port);
680 }
681
682 kfree(recv_buf);
683}
684
685static void qrtr_ns_data_ready(struct sock *sk)
686{
687 queue_work(qrtr_ns.workqueue, &qrtr_ns.work);
688}
689
690void qrtr_ns_init(struct work_struct *work)
691{
692 struct sockaddr_qrtr sq;
693 int ret;
694
695 INIT_LIST_HEAD(&qrtr_ns.lookups);
696 INIT_WORK(&qrtr_ns.work, qrtr_ns_worker);
697
698 ret = sock_create_kern(&init_net, AF_QIPCRTR, SOCK_DGRAM,
699 PF_QIPCRTR, &qrtr_ns.sock);
700 if (ret < 0)
701 return;
702
703 ret = kernel_getsockname(qrtr_ns.sock, (struct sockaddr *)&sq);
704 if (ret < 0) {
705 pr_err("failed to get socket name\n");
706 goto err_sock;
707 }
708
709 qrtr_ns.sock->sk->sk_data_ready = qrtr_ns_data_ready;
710
711 sq.sq_port = QRTR_PORT_CTRL;
712 qrtr_ns.local_node = sq.sq_node;
713
714 ret = kernel_bind(qrtr_ns.sock, (struct sockaddr *)&sq, sizeof(sq));
715 if (ret < 0) {
716 pr_err("failed to bind to socket\n");
717 goto err_sock;
718 }
719
720 qrtr_ns.bcast_sq.sq_family = AF_QIPCRTR;
721 qrtr_ns.bcast_sq.sq_node = QRTR_NODE_BCAST;
722 qrtr_ns.bcast_sq.sq_port = QRTR_PORT_CTRL;
723
724 qrtr_ns.workqueue = alloc_workqueue("qrtr_ns_handler", WQ_UNBOUND, 1);
725 if (!qrtr_ns.workqueue)
726 goto err_sock;
727
728 ret = say_hello();
729 if (ret < 0)
730 goto err_wq;
731
732 return;
733
734err_wq:
735 destroy_workqueue(qrtr_ns.workqueue);
736err_sock:
737 sock_release(qrtr_ns.sock);
738}
739EXPORT_SYMBOL_GPL(qrtr_ns_init);
740
741void qrtr_ns_remove(void)
742{
743 cancel_work_sync(&qrtr_ns.work);
744 destroy_workqueue(qrtr_ns.workqueue);
745 sock_release(qrtr_ns.sock);
746}
747EXPORT_SYMBOL_GPL(qrtr_ns_remove);
748
749MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>");
750MODULE_DESCRIPTION("Qualcomm IPC Router Nameservice");
751MODULE_LICENSE("Dual BSD/GPL");
net/qrtr/qrtr.c+11−40
@@ -7,9 +7,9 @@ · 6 unmodified lines
7#include <linux/netlink.h>7#include <linux/netlink.h>
8#include <linux/qrtr.h>8#include <linux/qrtr.h>
9#include <linux/termios.h> /* For TIOCINQ/OUTQ */9#include <linux/termios.h> /* For TIOCINQ/OUTQ */
10#include <linux/numa.h>
11#include <linux/spinlock.h>10#include <linux/spinlock.h>
12#include <linux/wait.h>11#include <linux/wait.h>
12#include <linux/workqueue.h>
13 13
14#include <net/sock.h>14#include <net/sock.h>
15 15
@@ -96,7 +96,7 @@ static inline struct qrtr_sock *qrtr_sk(struct sock *sk) · 80 unmodified lines
96 return container_of(sk, struct qrtr_sock, sk);96 return container_of(sk, struct qrtr_sock, sk);
97}97}
98 98
99static unsigned int qrtr_local_nid = NUMA_NO_NODE;99static unsigned int qrtr_local_nid = 1;
100 100
101/* for node ids */101/* for node ids */
102static RADIX_TREE(qrtr_nodes, GFP_ATOMIC);102static RADIX_TREE(qrtr_nodes, GFP_ATOMIC);
@@ -110,6 +110,8 @@ static DEFINE_MUTEX(qrtr_node_lock); · 7 unmodified lines
110static DEFINE_IDR(qrtr_ports);110static DEFINE_IDR(qrtr_ports);
111static DEFINE_MUTEX(qrtr_port_lock);111static DEFINE_MUTEX(qrtr_port_lock);
112 112
113static struct delayed_work qrtr_ns_work;
114
113/**115/**
114 * struct qrtr_node - endpoint node116 * struct qrtr_node - endpoint node
115 * @ep_lock: lock for endpoint management and callbacks117 * @ep_lock: lock for endpoint management and callbacks
@@ -1241,38 +1243,6 @@ static int qrtr_create(struct net *net, struct socket *sock, · 1125 unmodified lines
1241 return 0;1243 return 0;
1242}1244}
1243 1245
1244static const struct nla_policy qrtr_policy[IFA_MAX + 1] = {
1245 [IFA_LOCAL] = { .type = NLA_U32 },
1246};
1247
1248static int qrtr_addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
1249 struct netlink_ext_ack *extack)
1250{
1251 struct nlattr *tb[IFA_MAX + 1];
1252 struct ifaddrmsg *ifm;
1253 int rc;
1254
1255 if (!netlink_capable(skb, CAP_NET_ADMIN))
1256 return -EPERM;
1257
1258 if (!netlink_capable(skb, CAP_SYS_ADMIN))
1259 return -EPERM;
1260
1261 ASSERT_RTNL();
1262
1263 rc = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
1264 qrtr_policy, extack);
1265 if (rc < 0)
1266 return rc;
1267
1268 ifm = nlmsg_data(nlh);
1269 if (!tb[IFA_LOCAL])
1270 return -EINVAL;
1271
1272 qrtr_local_nid = nla_get_u32(tb[IFA_LOCAL]);
1273 return 0;
1274}
1275
1276static const struct net_proto_family qrtr_family = {1246static const struct net_proto_family qrtr_family = {
1277 .owner = THIS_MODULE,1247 .owner = THIS_MODULE,
1278 .family = AF_QIPCRTR,1248 .family = AF_QIPCRTR,
@@ -1293,11 +1263,11 @@ static int __init qrtr_proto_init(void) · 14 unmodified lines
1293 return rc;1263 return rc;
1294 }1264 }
1295 1265
1296 rc = rtnl_register_module(THIS_MODULE, PF_QIPCRTR, RTM_NEWADDR, qrtr_addr_doit, NULL, 0);1266 /* FIXME: Currently, this 2s delay is required to catch the NEW_SERVER
1297 if (rc) {1267 * messages from routers. But the fix could be somewhere else.
1298 sock_unregister(qrtr_family.family);1268 */
1299 proto_unregister(&qrtr_proto);1269 INIT_DELAYED_WORK(&qrtr_ns_work, qrtr_ns_init);
1300 }1270 schedule_delayed_work(&qrtr_ns_work, msecs_to_jiffies(2000));
1301 1271
1302 return rc;1272 return rc;
1303}1273}
@@ -1305,7 +1275,8 @@ postcore_initcall(qrtr_proto_init); · 1 unmodified line
1305 1275
1306static void __exit qrtr_proto_fini(void)1276static void __exit qrtr_proto_fini(void)
1307{1277{
1308 rtnl_unregister(PF_QIPCRTR, RTM_NEWADDR);1278 cancel_delayed_work_sync(&qrtr_ns_work);
1279 qrtr_ns_remove();
1309 sock_unregister(qrtr_family.family);1280 sock_unregister(qrtr_family.family);
1310 proto_unregister(&qrtr_proto);1281 proto_unregister(&qrtr_proto);
1311}1282}
net/qrtr/qrtr.h+4−0
@@ -29,4 +29,8 @@ void qrtr_endpoint_unregister(struct qrtr_endpoint *ep); · 28 unmodified lines
29 29
30int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len);30int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len);
31 31
32void qrtr_ns_init(struct work_struct *work);
33
34void qrtr_ns_remove(void);
35
32#endif36#endif