Linux Audio

Check our new training course

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