blob: 90f10241f5b485d2bfb5e4934f058160b7313980 [file] [log] [blame]
Arun Prakash8c8dd7a2020-03-30 22:22:13 +05301/* Copyright (c) 2011-2020, The Linux Foundation. All rights reserved.
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002 *
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/slab.h>
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/string.h>
17#include <linux/errno.h>
18#include <linux/init.h>
19#include <linux/types.h>
20#include <linux/delay.h>
21#include <linux/err.h>
22#include <linux/sched.h>
23#include <linux/poll.h>
24#include <linux/pm.h>
25#include <linux/platform_device.h>
26#include <linux/uaccess.h>
27#include <linux/debugfs.h>
28#include <linux/rwsem.h>
29#include <linux/ipc_logging.h>
30#include <linux/uaccess.h>
31#include <linux/ipc_router.h>
32#include <linux/ipc_router_xprt.h>
33#include <linux/kref.h>
Arun Kumar Neelakantamd5eb2732018-06-19 14:40:01 +053034#include <linux/kthread.h>
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -060035#include <soc/qcom/subsystem_notif.h>
36#include <soc/qcom/subsystem_restart.h>
37
38#include <asm/byteorder.h>
39
40#include "ipc_router_private.h"
41#include "ipc_router_security.h"
42
43enum {
44 SMEM_LOG = 1U << 0,
45 RTR_DBG = 1U << 1,
46};
47
48static int msm_ipc_router_debug_mask;
49module_param_named(debug_mask, msm_ipc_router_debug_mask,
50 int, 0664);
51#define MODULE_NAME "ipc_router"
52
53#define IPC_RTR_INFO_PAGES 6
54
55#define IPC_RTR_INFO(log_ctx, x...) do { \
56typeof(log_ctx) _log_ctx = (log_ctx); \
57if (_log_ctx) \
58 ipc_log_string(_log_ctx, x); \
59if (msm_ipc_router_debug_mask & RTR_DBG) \
60 pr_info("[IPCRTR] "x); \
61} while (0)
62
63#define IPC_ROUTER_LOG_EVENT_TX 0x01
64#define IPC_ROUTER_LOG_EVENT_RX 0x02
65#define IPC_ROUTER_LOG_EVENT_TX_ERR 0x03
66#define IPC_ROUTER_LOG_EVENT_RX_ERR 0x04
67#define IPC_ROUTER_DUMMY_DEST_NODE 0xFFFFFFFF
68
69#define ipc_port_sk(port) ((struct sock *)(port))
70
71static LIST_HEAD(control_ports);
72static DECLARE_RWSEM(control_ports_lock_lha5);
73
74#define LP_HASH_SIZE 32
75static struct list_head local_ports[LP_HASH_SIZE];
76static DECLARE_RWSEM(local_ports_lock_lhc2);
77
78/* Server info is organized as a hash table. The server's service ID is
79 * used to index into the hash table. The instance ID of most of the servers
80 * are 1 or 2. The service IDs are well distributed compared to the instance
81 * IDs and hence choosing service ID to index into this hash table optimizes
82 * the hash table operations like add, lookup, destroy.
83 */
84#define SRV_HASH_SIZE 32
85static struct list_head server_list[SRV_HASH_SIZE];
86static DECLARE_RWSEM(server_list_lock_lha2);
87
88struct msm_ipc_server {
89 struct list_head list;
90 struct kref ref;
91 struct msm_ipc_port_name name;
92 char pdev_name[32];
93 int next_pdev_id;
94 int synced_sec_rule;
95 struct list_head server_port_list;
96};
97
98struct msm_ipc_server_port {
99 struct list_head list;
100 struct platform_device *pdev;
101 struct msm_ipc_port_addr server_addr;
102 struct msm_ipc_router_xprt_info *xprt_info;
103};
104
105struct msm_ipc_resume_tx_port {
106 struct list_head list;
107 u32 port_id;
108 u32 node_id;
109};
110
111struct ipc_router_conn_info {
112 struct list_head list;
113 u32 port_id;
114};
115
116enum {
117 RESET = 0,
118 VALID = 1,
119};
120
121#define RP_HASH_SIZE 32
122struct msm_ipc_router_remote_port {
123 struct list_head list;
124 struct kref ref;
125 struct mutex rport_lock_lhb2; /* lock for remote port state access */
126 u32 node_id;
127 u32 port_id;
128 int status;
129 u32 tx_quota_cnt;
130 struct list_head resume_tx_port_list;
131 struct list_head conn_info_list;
132 void *sec_rule;
133 struct msm_ipc_server *server;
134};
135
136struct msm_ipc_router_xprt_info {
137 struct list_head list;
138 struct msm_ipc_router_xprt *xprt;
139 u32 remote_node_id;
140 u32 initialized;
Arun Kumar Neelakantamf99191d2018-06-11 18:13:43 +0530141 u32 hello_sent;
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -0600142 struct list_head pkt_list;
143 struct wakeup_source ws;
144 struct mutex rx_lock_lhb2; /* lock for xprt rx operations */
145 struct mutex tx_lock_lhb2; /* lock for xprt tx operations */
146 u32 need_len;
147 u32 abort_data_read;
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -0600148 void *log_ctx;
149 struct kref ref;
150 struct completion ref_complete;
Arun Kumar Neelakantam74ff8562017-05-26 17:57:52 +0530151 bool dynamic_ws;
Arun Kumar Neelakantamd5eb2732018-06-19 14:40:01 +0530152
153 struct kthread_worker kworker;
154 struct task_struct *task;
155 struct kthread_work read_data;
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -0600156};
157
158#define RT_HASH_SIZE 4
159struct msm_ipc_routing_table_entry {
160 struct list_head list;
161 struct kref ref;
162 u32 node_id;
163 u32 neighbor_node_id;
164 struct list_head remote_port_list[RP_HASH_SIZE];
165 struct msm_ipc_router_xprt_info *xprt_info;
166 struct rw_semaphore lock_lha4;
167 unsigned long num_tx_bytes;
168 unsigned long num_rx_bytes;
169};
170
171#define LOG_CTX_NAME_LEN 32
172struct ipc_rtr_log_ctx {
173 struct list_head list;
174 char log_ctx_name[LOG_CTX_NAME_LEN];
175 void *log_ctx;
176};
177
178static struct list_head routing_table[RT_HASH_SIZE];
179static DECLARE_RWSEM(routing_table_lock_lha3);
180static int routing_table_inited;
181
Arun Kumar Neelakantamd5eb2732018-06-19 14:40:01 +0530182static void do_read_data(struct kthread_work *work);
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -0600183
184static LIST_HEAD(xprt_info_list);
185static DECLARE_RWSEM(xprt_info_list_lock_lha5);
186
187static DEFINE_MUTEX(log_ctx_list_lock_lha0);
188static LIST_HEAD(log_ctx_list);
189static DEFINE_MUTEX(ipc_router_init_lock);
190static bool is_ipc_router_inited;
191static int ipc_router_core_init(void);
192#define IPC_ROUTER_INIT_TIMEOUT (10 * HZ)
193
194static u32 next_port_id;
195static DEFINE_MUTEX(next_port_id_lock_lhc1);
196static struct workqueue_struct *msm_ipc_router_workqueue;
197
198static void *local_log_ctx;
199static void *ipc_router_get_log_ctx(char *sub_name);
200static int process_resume_tx_msg(union rr_control_msg *msg,
201 struct rr_packet *pkt);
202static void ipc_router_reset_conn(struct msm_ipc_router_remote_port *rport_ptr);
203static int ipc_router_get_xprt_info_ref(
204 struct msm_ipc_router_xprt_info *xprt_info);
205static void ipc_router_put_xprt_info_ref(
206 struct msm_ipc_router_xprt_info *xprt_info);
207static void ipc_router_release_xprt_info_ref(struct kref *ref);
208
209struct pil_vote_info {
210 void *pil_handle;
211 struct work_struct load_work;
212 struct work_struct unload_work;
213};
214
215#define PIL_SUBSYSTEM_NAME_LEN 32
216static char default_peripheral[PIL_SUBSYSTEM_NAME_LEN];
217
218enum {
219 DOWN,
220 UP,
221};
222
Arun Kumar Neelakantam74ff8562017-05-26 17:57:52 +0530223static bool is_wakeup_source_allowed;
224
225void msm_ipc_router_set_ws_allowed(bool flag)
226{
227 is_wakeup_source_allowed = flag;
228}
229
Arun Kumar Neelakantam029e8462018-04-19 18:10:47 +0530230/**
231 * is_sensor_port() - Check if the remote port is sensor service or not
232 * @rport: Pointer to the remote port.
233 *
234 * Return: true if the remote port is sensor service else false.
235 */
236static int is_sensor_port(struct msm_ipc_router_remote_port *rport)
237{
238 u32 svcid = 0;
239
240 if (rport && rport->server) {
241 svcid = rport->server->name.service;
242 if (svcid == 400 || (svcid >= 256 && svcid <= 320))
243 return true;
244 }
245
246 return false;
247}
248
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -0600249static void init_routing_table(void)
250{
251 int i;
252
253 for (i = 0; i < RT_HASH_SIZE; i++)
254 INIT_LIST_HEAD(&routing_table[i]);
255}
256
257/**
258 * ipc_router_calc_checksum() - compute the checksum for extended HELLO message
259 * @msg: Reference to the IPC Router HELLO message.
260 *
261 * Return: Computed checksum value, 0 if msg is NULL.
262 */
263static u32 ipc_router_calc_checksum(union rr_control_msg *msg)
264{
265 u32 checksum = 0;
266 int i, len;
267 u16 upper_nb;
268 u16 lower_nb;
269 void *hello;
270
271 if (!msg)
272 return checksum;
273 hello = msg;
274 len = sizeof(*msg);
275
276 for (i = 0; i < len / IPCR_WORD_SIZE; i++) {
277 lower_nb = (*((u32 *)hello)) & IPC_ROUTER_CHECKSUM_MASK;
278 upper_nb = ((*((u32 *)hello)) >> 16) &
279 IPC_ROUTER_CHECKSUM_MASK;
280 checksum = checksum + upper_nb + lower_nb;
281 hello = ((u32 *)hello) + 1;
282 }
283 while (checksum > 0xFFFF)
284 checksum = (checksum & IPC_ROUTER_CHECKSUM_MASK) +
285 ((checksum >> 16) & IPC_ROUTER_CHECKSUM_MASK);
286
287 checksum = ~checksum & IPC_ROUTER_CHECKSUM_MASK;
288 return checksum;
289}
290
291/**
292 * skb_copy_to_log_buf() - copies the required number bytes from the skb_queue
293 * @skb_head: skb_queue head that contains the data.
294 * @pl_len: length of payload need to be copied.
295 * @hdr_offset: length of the header present in first skb
296 * @log_buf: The output buffer which will contain the formatted log string
297 *
298 * This function copies the first specified number of bytes from the skb_queue
299 * to a new buffer and formats them to a string for logging.
300 */
301static void skb_copy_to_log_buf(struct sk_buff_head *skb_head,
302 unsigned int pl_len, unsigned int hdr_offset,
Arun Kumar Neelakantam7e4f46b2018-03-29 20:10:02 +0530303 unsigned char *log_buf)
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -0600304{
305 struct sk_buff *temp_skb;
306 unsigned int copied_len = 0, copy_len = 0;
307 int remaining;
308
309 if (!skb_head) {
310 IPC_RTR_ERR("%s: NULL skb_head\n", __func__);
311 return;
312 }
313 temp_skb = skb_peek(skb_head);
314 if (unlikely(!temp_skb || !temp_skb->data)) {
315 IPC_RTR_ERR("%s: No SKBs in skb_queue\n", __func__);
316 return;
317 }
318
319 remaining = temp_skb->len - hdr_offset;
320 skb_queue_walk(skb_head, temp_skb) {
321 copy_len = remaining < pl_len ? remaining : pl_len;
322 memcpy(log_buf + copied_len, temp_skb->data + hdr_offset,
323 copy_len);
324 copied_len += copy_len;
325 hdr_offset = 0;
326 if (copied_len == pl_len)
327 break;
328 remaining = pl_len - remaining;
329 }
330}
331
332/**
333 * ipc_router_log_msg() - log all data messages exchanged
334 * @log_ctx: IPC Logging context specific to each transport
335 * @xchng_type: Identifies the data to be a receive or send.
336 * @data: IPC Router data packet or control msg received or to be send.
337 * @hdr: Reference to the router header
338 * @port_ptr: Local IPC Router port.
339 * @rport_ptr: Remote IPC Router port
340 *
341 * This function builds the log message that would be passed on to the IPC
342 * logging framework. The data messages that would be passed corresponds to
343 * the information that is exchanged between the IPC Router and it's clients.
344 */
345static void ipc_router_log_msg(void *log_ctx, u32 xchng_type,
346 void *data, struct rr_header_v1 *hdr,
347 struct msm_ipc_port *port_ptr,
348 struct msm_ipc_router_remote_port *rport_ptr)
349{
350 struct sk_buff_head *skb_head = NULL;
351 union rr_control_msg *msg = NULL;
352 struct rr_packet *pkt = NULL;
353 u64 pl_buf = 0;
354 struct sk_buff *skb;
355 u32 buf_len = 8;
356 u32 svc_id = 0;
357 u32 svc_ins = 0;
358 unsigned int hdr_offset = 0;
359 u32 port_type = 0;
360
361 if (!log_ctx || !hdr || !data)
362 return;
363
364 if (hdr->type == IPC_ROUTER_CTRL_CMD_DATA) {
365 pkt = (struct rr_packet *)data;
366 skb_head = pkt->pkt_fragment_q;
367 skb = skb_peek(skb_head);
368 if (!skb || !skb->data) {
369 IPC_RTR_ERR("%s: No SKBs in skb_queue\n", __func__);
370 return;
371 }
372
373 if (skb_queue_len(skb_head) == 1 && skb->len < 8)
374 buf_len = skb->len;
375 if (xchng_type == IPC_ROUTER_LOG_EVENT_TX && hdr->dst_node_id
376 != IPC_ROUTER_NID_LOCAL) {
377 if (hdr->version == IPC_ROUTER_V1)
378 hdr_offset = sizeof(struct rr_header_v1);
379 else if (hdr->version == IPC_ROUTER_V2)
380 hdr_offset = sizeof(struct rr_header_v2);
381 }
Arun Kumar Neelakantam7e4f46b2018-03-29 20:10:02 +0530382 skb_copy_to_log_buf(skb_head, buf_len, hdr_offset,
383 (unsigned char *)&pl_buf);
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -0600384
385 if (port_ptr && rport_ptr && (port_ptr->type == CLIENT_PORT) &&
386 rport_ptr->server) {
387 svc_id = rport_ptr->server->name.service;
388 svc_ins = rport_ptr->server->name.instance;
389 port_type = CLIENT_PORT;
Dhoat Harpal3ad5fe32017-06-19 21:26:13 +0530390 port_ptr->last_served_svc_id =
391 rport_ptr->server->name.service;
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -0600392 } else if (port_ptr && (port_ptr->type == SERVER_PORT)) {
393 svc_id = port_ptr->port_name.service;
394 svc_ins = port_ptr->port_name.instance;
395 port_type = SERVER_PORT;
396 }
397 IPC_RTR_INFO(log_ctx,
398 "%s %s %s Len:0x%x T:0x%x CF:0x%x SVC:<0x%x:0x%x> SRC:<0x%x:0x%x> DST:<0x%x:0x%x> DATA: %08x %08x",
399 (xchng_type == IPC_ROUTER_LOG_EVENT_RX ? "" :
400 (xchng_type == IPC_ROUTER_LOG_EVENT_TX ?
401 current->comm : "")),
402 (port_type == CLIENT_PORT ? "CLI" : "SRV"),
403 (xchng_type == IPC_ROUTER_LOG_EVENT_RX ? "RX" :
404 (xchng_type == IPC_ROUTER_LOG_EVENT_TX ? "TX" :
405 (xchng_type == IPC_ROUTER_LOG_EVENT_TX_ERR ? "TX_ERR" :
406 (xchng_type == IPC_ROUTER_LOG_EVENT_RX_ERR ? "RX_ERR" :
407 "UNKNOWN")))),
408 hdr->size, hdr->type, hdr->control_flag,
409 svc_id, svc_ins, hdr->src_node_id, hdr->src_port_id,
410 hdr->dst_node_id, hdr->dst_port_id,
411 (unsigned int)pl_buf, (unsigned int)(pl_buf >> 32));
412
413 } else {
414 msg = (union rr_control_msg *)data;
415 if (msg->cmd == IPC_ROUTER_CTRL_CMD_NEW_SERVER ||
416 msg->cmd == IPC_ROUTER_CTRL_CMD_REMOVE_SERVER)
417 IPC_RTR_INFO(log_ctx,
418 "CTL MSG: %s cmd:0x%x SVC:<0x%x:0x%x> ADDR:<0x%x:0x%x>",
419 (xchng_type == IPC_ROUTER_LOG_EVENT_RX ? "RX" :
420 (xchng_type == IPC_ROUTER_LOG_EVENT_TX ? "TX" :
421 (xchng_type == IPC_ROUTER_LOG_EVENT_TX_ERR ? "TX_ERR" :
422 (xchng_type == IPC_ROUTER_LOG_EVENT_RX_ERR ? "RX_ERR" :
423 "UNKNOWN")))),
424 msg->cmd, msg->srv.service, msg->srv.instance,
425 msg->srv.node_id, msg->srv.port_id);
426 else if (msg->cmd == IPC_ROUTER_CTRL_CMD_REMOVE_CLIENT ||
427 msg->cmd == IPC_ROUTER_CTRL_CMD_RESUME_TX)
428 IPC_RTR_INFO(log_ctx,
429 "CTL MSG: %s cmd:0x%x ADDR: <0x%x:0x%x>",
430 (xchng_type == IPC_ROUTER_LOG_EVENT_RX ? "RX" :
431 (xchng_type == IPC_ROUTER_LOG_EVENT_TX ? "TX" : "ERR")),
432 msg->cmd, msg->cli.node_id, msg->cli.port_id);
Arun Prakash0fd19c22019-09-20 15:03:52 +0530433 else if (msg->cmd == IPC_ROUTER_CTRL_CMD_HELLO && hdr) {
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -0600434 IPC_RTR_INFO(log_ctx,
435 "CTL MSG %s cmd:0x%x ADDR:0x%x",
436 (xchng_type == IPC_ROUTER_LOG_EVENT_RX ? "RX" :
437 (xchng_type == IPC_ROUTER_LOG_EVENT_TX ? "TX" : "ERR")),
438 msg->cmd, hdr->src_node_id);
Arun Prakash0fd19c22019-09-20 15:03:52 +0530439 if (hdr->src_node_id == 0 || hdr->src_node_id == 3)
440 pr_err("%s: Modem QMI Readiness %s cmd:0x%x ADDR:0x%x\n",
441 __func__,
442 (xchng_type == IPC_ROUTER_LOG_EVENT_RX ? "RX" :
443 (xchng_type == IPC_ROUTER_LOG_EVENT_TX ? "TX" :
444 "ERR")), msg->cmd, hdr->src_node_id);
445 }
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -0600446 else
447 IPC_RTR_INFO(log_ctx,
448 "%s UNKNOWN cmd:0x%x",
449 (xchng_type == IPC_ROUTER_LOG_EVENT_RX ? "RX" :
450 (xchng_type == IPC_ROUTER_LOG_EVENT_TX ? "TX" : "ERR")),
451 msg->cmd);
452 }
453}
454
455/* Must be called with routing_table_lock_lha3 locked. */
456static struct msm_ipc_routing_table_entry *lookup_routing_table(
457 u32 node_id)
458{
459 u32 key = (node_id % RT_HASH_SIZE);
460 struct msm_ipc_routing_table_entry *rt_entry;
461
462 list_for_each_entry(rt_entry, &routing_table[key], list) {
463 if (rt_entry->node_id == node_id)
464 return rt_entry;
465 }
466 return NULL;
467}
468
469/**
470 * create_routing_table_entry() - Lookup and create a routing table entry
471 * @node_id: Node ID of the routing table entry to be created.
472 * @xprt_info: XPRT through which the node ID is reachable.
473 *
474 * @return: a reference to the routing table entry on success, NULL on failure.
475 */
476static struct msm_ipc_routing_table_entry *create_routing_table_entry(
477 u32 node_id, struct msm_ipc_router_xprt_info *xprt_info)
478{
479 int i;
480 struct msm_ipc_routing_table_entry *rt_entry;
481 u32 key;
482
483 down_write(&routing_table_lock_lha3);
484 rt_entry = lookup_routing_table(node_id);
485 if (rt_entry)
486 goto out_create_rtentry1;
487
488 rt_entry = kmalloc(sizeof(*rt_entry), GFP_KERNEL);
489 if (!rt_entry) {
490 IPC_RTR_ERR("%s: rt_entry allocation failed for %d\n",
491 __func__, node_id);
492 goto out_create_rtentry2;
493 }
494
495 for (i = 0; i < RP_HASH_SIZE; i++)
496 INIT_LIST_HEAD(&rt_entry->remote_port_list[i]);
497 init_rwsem(&rt_entry->lock_lha4);
498 kref_init(&rt_entry->ref);
499 rt_entry->node_id = node_id;
500 rt_entry->xprt_info = xprt_info;
501 if (xprt_info)
502 rt_entry->neighbor_node_id = xprt_info->remote_node_id;
503
504 key = (node_id % RT_HASH_SIZE);
505 list_add_tail(&rt_entry->list, &routing_table[key]);
506out_create_rtentry1:
507 kref_get(&rt_entry->ref);
508out_create_rtentry2:
509 up_write(&routing_table_lock_lha3);
510 return rt_entry;
511}
512
513/**
514 * ipc_router_get_rtentry_ref() - Get a reference to the routing table entry
515 * @node_id: Node ID of the routing table entry.
516 *
517 * @return: a reference to the routing table entry on success, NULL on failure.
518 *
519 * This function is used to obtain a reference to the rounting table entry
520 * corresponding to a node id.
521 */
522static struct msm_ipc_routing_table_entry *ipc_router_get_rtentry_ref(
523 u32 node_id)
524{
525 struct msm_ipc_routing_table_entry *rt_entry;
526
527 down_read(&routing_table_lock_lha3);
528 rt_entry = lookup_routing_table(node_id);
529 if (rt_entry)
530 kref_get(&rt_entry->ref);
531 up_read(&routing_table_lock_lha3);
532 return rt_entry;
533}
534
535/**
536 * ipc_router_release_rtentry() - Cleanup and release the routing table entry
537 * @ref: Reference to the entry.
538 *
539 * This function is called when all references to the routing table entry are
540 * released.
541 */
542void ipc_router_release_rtentry(struct kref *ref)
543{
544 struct msm_ipc_routing_table_entry *rt_entry =
545 container_of(ref, struct msm_ipc_routing_table_entry, ref);
546
547 /* All references to a routing entry will be put only under SSR.
548 * As part of SSR, all the internals of the routing table entry
549 * are cleaned. So just free the routing table entry.
550 */
551 kfree(rt_entry);
552}
553
554struct rr_packet *rr_read(struct msm_ipc_router_xprt_info *xprt_info)
555{
556 struct rr_packet *temp_pkt;
557
558 if (!xprt_info)
559 return NULL;
560
561 mutex_lock(&xprt_info->rx_lock_lhb2);
562 if (xprt_info->abort_data_read) {
563 mutex_unlock(&xprt_info->rx_lock_lhb2);
564 IPC_RTR_ERR("%s detected SSR & exiting now\n",
565 xprt_info->xprt->name);
566 return NULL;
567 }
568
569 if (list_empty(&xprt_info->pkt_list)) {
570 mutex_unlock(&xprt_info->rx_lock_lhb2);
571 return NULL;
572 }
573
574 temp_pkt = list_first_entry(&xprt_info->pkt_list,
575 struct rr_packet, list);
576 list_del(&temp_pkt->list);
577 if (list_empty(&xprt_info->pkt_list))
578 __pm_relax(&xprt_info->ws);
579 mutex_unlock(&xprt_info->rx_lock_lhb2);
580 return temp_pkt;
581}
582
583struct rr_packet *clone_pkt(struct rr_packet *pkt)
584{
585 struct rr_packet *cloned_pkt;
586 struct sk_buff *temp_skb, *cloned_skb;
587 struct sk_buff_head *pkt_fragment_q;
588
589 cloned_pkt = kzalloc(sizeof(*cloned_pkt), GFP_KERNEL);
590 if (!cloned_pkt) {
591 IPC_RTR_ERR("%s: failure\n", __func__);
592 return NULL;
593 }
594 memcpy(&cloned_pkt->hdr, &pkt->hdr, sizeof(struct rr_header_v1));
595 if (pkt->opt_hdr.len > 0) {
596 cloned_pkt->opt_hdr.data = kmalloc(pkt->opt_hdr.len,
597 GFP_KERNEL);
598 if (!cloned_pkt->opt_hdr.data) {
599 IPC_RTR_ERR("%s: Memory allocation Failed\n", __func__);
600 } else {
601 cloned_pkt->opt_hdr.len = pkt->opt_hdr.len;
602 memcpy(cloned_pkt->opt_hdr.data, pkt->opt_hdr.data,
603 pkt->opt_hdr.len);
604 }
605 }
606
607 pkt_fragment_q = kmalloc(sizeof(*pkt_fragment_q), GFP_KERNEL);
608 if (!pkt_fragment_q) {
609 IPC_RTR_ERR("%s: pkt_frag_q alloc failure\n", __func__);
610 kfree(cloned_pkt);
611 return NULL;
612 }
613 skb_queue_head_init(pkt_fragment_q);
614 kref_init(&cloned_pkt->ref);
615
616 skb_queue_walk(pkt->pkt_fragment_q, temp_skb) {
617 cloned_skb = skb_clone(temp_skb, GFP_KERNEL);
618 if (!cloned_skb)
619 goto fail_clone;
620 skb_queue_tail(pkt_fragment_q, cloned_skb);
621 }
622 cloned_pkt->pkt_fragment_q = pkt_fragment_q;
623 cloned_pkt->length = pkt->length;
Arun Kumar Neelakantam74ff8562017-05-26 17:57:52 +0530624 cloned_pkt->ws_need = pkt->ws_need;
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -0600625 return cloned_pkt;
626
627fail_clone:
628 while (!skb_queue_empty(pkt_fragment_q)) {
629 temp_skb = skb_dequeue(pkt_fragment_q);
630 kfree_skb(temp_skb);
631 }
632 kfree(pkt_fragment_q);
633 if (cloned_pkt->opt_hdr.len > 0)
634 kfree(cloned_pkt->opt_hdr.data);
635 kfree(cloned_pkt);
636 return NULL;
637}
638
639/**
640 * create_pkt() - Create a Router packet
641 * @data: SKB queue to be contained inside the packet.
642 *
643 * @return: pointer to packet on success, NULL on failure.
644 */
645struct rr_packet *create_pkt(struct sk_buff_head *data)
646{
647 struct rr_packet *pkt;
648 struct sk_buff *temp_skb;
649
650 pkt = kzalloc(sizeof(*pkt), GFP_KERNEL);
651 if (!pkt) {
652 IPC_RTR_ERR("%s: failure\n", __func__);
653 return NULL;
654 }
655
656 if (data) {
657 pkt->pkt_fragment_q = data;
658 skb_queue_walk(pkt->pkt_fragment_q, temp_skb)
659 pkt->length += temp_skb->len;
660 } else {
661 pkt->pkt_fragment_q = kmalloc(sizeof(*pkt->pkt_fragment_q),
662 GFP_KERNEL);
663 if (!pkt->pkt_fragment_q) {
664 IPC_RTR_ERR("%s: Couldn't alloc pkt_fragment_q\n",
665 __func__);
666 kfree(pkt);
667 return NULL;
668 }
669 skb_queue_head_init(pkt->pkt_fragment_q);
670 }
671 kref_init(&pkt->ref);
672 return pkt;
673}
674
675void release_pkt(struct rr_packet *pkt)
676{
677 struct sk_buff *temp_skb;
678
679 if (!pkt)
680 return;
681
682 if (!pkt->pkt_fragment_q) {
683 kfree(pkt);
684 return;
685 }
686
687 while (!skb_queue_empty(pkt->pkt_fragment_q)) {
688 temp_skb = skb_dequeue(pkt->pkt_fragment_q);
689 kfree_skb(temp_skb);
690 }
691 kfree(pkt->pkt_fragment_q);
692 if (pkt->opt_hdr.len > 0)
693 kfree(pkt->opt_hdr.data);
694 kfree(pkt);
695}
696
697static struct sk_buff_head *msm_ipc_router_buf_to_skb(void *buf,
698 unsigned int buf_len)
699{
700 struct sk_buff_head *skb_head;
701 struct sk_buff *skb;
702 int first = 1, offset = 0;
703 int skb_size, data_size;
704 void *data;
705 int last = 1;
706 int align_size;
707
708 skb_head = kmalloc(sizeof(*skb_head), GFP_KERNEL);
709 if (!skb_head) {
710 IPC_RTR_ERR("%s: Couldnot allocate skb_head\n", __func__);
711 return NULL;
712 }
713 skb_queue_head_init(skb_head);
714
715 data_size = buf_len;
716 align_size = ALIGN_SIZE(data_size);
717 while (offset != buf_len) {
718 skb_size = data_size;
719 if (first)
720 skb_size += IPC_ROUTER_HDR_SIZE;
721 if (last)
722 skb_size += align_size;
723
724 skb = alloc_skb(skb_size, GFP_KERNEL);
725 if (!skb) {
726 if (skb_size <= (PAGE_SIZE / 2)) {
727 IPC_RTR_ERR("%s: cannot allocate skb\n",
728 __func__);
729 goto buf_to_skb_error;
730 }
731 data_size = data_size / 2;
732 last = 0;
733 continue;
734 }
735
736 if (first) {
737 skb_reserve(skb, IPC_ROUTER_HDR_SIZE);
738 first = 0;
739 }
740
741 data = skb_put(skb, data_size);
742 memcpy(skb->data, buf + offset, data_size);
743 skb_queue_tail(skb_head, skb);
744 offset += data_size;
745 data_size = buf_len - offset;
746 last = 1;
747 }
748 return skb_head;
749
750buf_to_skb_error:
751 while (!skb_queue_empty(skb_head)) {
752 skb = skb_dequeue(skb_head);
753 kfree_skb(skb);
754 }
755 kfree(skb_head);
756 return NULL;
757}
758
759static void *msm_ipc_router_skb_to_buf(struct sk_buff_head *skb_head,
760 unsigned int len)
761{
762 struct sk_buff *temp;
763 unsigned int offset = 0, buf_len = 0, copy_len;
764 void *buf;
765
766 if (!skb_head) {
767 IPC_RTR_ERR("%s: NULL skb_head\n", __func__);
768 return NULL;
769 }
770
771 temp = skb_peek(skb_head);
772 buf_len = len;
773 buf = kmalloc(buf_len, GFP_KERNEL);
774 if (!buf) {
775 IPC_RTR_ERR("%s: cannot allocate buf\n", __func__);
776 return NULL;
777 }
778 skb_queue_walk(skb_head, temp) {
779 copy_len = buf_len < temp->len ? buf_len : temp->len;
780 memcpy(buf + offset, temp->data, copy_len);
781 offset += copy_len;
782 buf_len -= copy_len;
783 }
784 return buf;
785}
786
787void msm_ipc_router_free_skb(struct sk_buff_head *skb_head)
788{
789 struct sk_buff *temp_skb;
790
791 if (!skb_head)
792 return;
793
794 while (!skb_queue_empty(skb_head)) {
795 temp_skb = skb_dequeue(skb_head);
796 kfree_skb(temp_skb);
797 }
798 kfree(skb_head);
799}
800
801/**
802 * extract_optional_header() - Extract the optional header from skb
803 * @pkt: Packet structure into which the header has to be extracted.
804 * @opt_len: The optional header length in word size.
805 *
806 * @return: Length of optional header in bytes if success, zero otherwise.
807 */
808static int extract_optional_header(struct rr_packet *pkt, u8 opt_len)
809{
810 size_t offset = 0, buf_len = 0, copy_len, opt_hdr_len;
811 struct sk_buff *temp;
812 struct sk_buff_head *skb_head;
813
814 opt_hdr_len = opt_len * IPCR_WORD_SIZE;
815 pkt->opt_hdr.data = kmalloc(opt_hdr_len, GFP_KERNEL);
816 if (!pkt->opt_hdr.data) {
817 IPC_RTR_ERR("%s: Memory allocation Failed\n", __func__);
818 return 0;
819 }
820 skb_head = pkt->pkt_fragment_q;
821 buf_len = opt_hdr_len;
822 skb_queue_walk(skb_head, temp) {
823 copy_len = buf_len < temp->len ? buf_len : temp->len;
824 memcpy(pkt->opt_hdr.data + offset, temp->data, copy_len);
825 offset += copy_len;
826 buf_len -= copy_len;
827 skb_pull(temp, copy_len);
828 if (temp->len == 0) {
829 skb_dequeue(skb_head);
830 kfree_skb(temp);
831 }
832 }
833 pkt->opt_hdr.len = opt_hdr_len;
834 return opt_hdr_len;
835}
836
837/**
838 * extract_header_v1() - Extract IPC Router header of version 1
839 * @pkt: Packet structure into which the header has to be extraced.
840 * @skb: SKB from which the header has to be extracted.
841 *
842 * @return: 0 on success, standard Linux error codes on failure.
843 */
844static int extract_header_v1(struct rr_packet *pkt, struct sk_buff *skb)
845{
846 if (!pkt || !skb) {
847 IPC_RTR_ERR("%s: Invalid pkt or skb\n", __func__);
848 return -EINVAL;
849 }
850
851 memcpy(&pkt->hdr, skb->data, sizeof(struct rr_header_v1));
852 skb_pull(skb, sizeof(struct rr_header_v1));
853 pkt->length -= sizeof(struct rr_header_v1);
854 return 0;
855}
856
857/**
858 * extract_header_v2() - Extract IPC Router header of version 2
859 * @pkt: Packet structure into which the header has to be extraced.
860 * @skb: SKB from which the header has to be extracted.
861 *
862 * @return: 0 on success, standard Linux error codes on failure.
863 */
864static int extract_header_v2(struct rr_packet *pkt, struct sk_buff *skb)
865{
866 struct rr_header_v2 *hdr;
867 u8 opt_len;
868 size_t opt_hdr_len;
869 size_t total_hdr_size = sizeof(*hdr);
870
871 if (!pkt || !skb) {
872 IPC_RTR_ERR("%s: Invalid pkt or skb\n", __func__);
873 return -EINVAL;
874 }
875
876 hdr = (struct rr_header_v2 *)skb->data;
877 pkt->hdr.version = (u32)hdr->version;
878 pkt->hdr.type = (u32)hdr->type;
879 pkt->hdr.src_node_id = (u32)hdr->src_node_id;
880 pkt->hdr.src_port_id = (u32)hdr->src_port_id;
881 pkt->hdr.size = (u32)hdr->size;
882 pkt->hdr.control_flag = (u32)hdr->control_flag;
883 pkt->hdr.dst_node_id = (u32)hdr->dst_node_id;
884 pkt->hdr.dst_port_id = (u32)hdr->dst_port_id;
885 opt_len = hdr->opt_len;
886 skb_pull(skb, total_hdr_size);
887 if (opt_len > 0) {
888 opt_hdr_len = extract_optional_header(pkt, opt_len);
889 total_hdr_size += opt_hdr_len;
890 }
891 pkt->length -= total_hdr_size;
892 return 0;
893}
894
895/**
896 * extract_header() - Extract IPC Router header
897 * @pkt: Packet from which the header has to be extraced.
898 *
899 * @return: 0 on success, standard Linux error codes on failure.
900 *
901 * This function will check if the header version is v1 or v2 and invoke
902 * the corresponding helper function to extract the IPC Router header.
903 */
904static int extract_header(struct rr_packet *pkt)
905{
906 struct sk_buff *temp_skb;
907 int ret;
908
909 if (!pkt) {
910 IPC_RTR_ERR("%s: NULL PKT\n", __func__);
911 return -EINVAL;
912 }
913
914 temp_skb = skb_peek(pkt->pkt_fragment_q);
915 if (!temp_skb || !temp_skb->data) {
916 IPC_RTR_ERR("%s: No SKBs in skb_queue\n", __func__);
917 return -EINVAL;
918 }
919
920 if (temp_skb->data[0] == IPC_ROUTER_V1) {
921 ret = extract_header_v1(pkt, temp_skb);
922 } else if (temp_skb->data[0] == IPC_ROUTER_V2) {
923 ret = extract_header_v2(pkt, temp_skb);
924 } else {
925 IPC_RTR_ERR("%s: Invalid Header version %02x\n",
926 __func__, temp_skb->data[0]);
927 print_hex_dump(KERN_ERR, "Header: ", DUMP_PREFIX_ADDRESS,
928 16, 1, temp_skb->data, pkt->length, true);
929 return -EINVAL;
930 }
931 return ret;
932}
933
934/**
935 * calc_tx_header_size() - Calculate header size to be reserved in SKB
936 * @pkt: Packet in which the space for header has to be reserved.
937 * @dst_xprt_info: XPRT through which the destination is reachable.
938 *
939 * @return: required header size on success,
940 * starndard Linux error codes on failure.
941 *
942 * This function is used to calculate the header size that has to be reserved
943 * in a transmit SKB. The header size is calculated based on the XPRT through
944 * which the destination node is reachable.
945 */
946static int calc_tx_header_size(struct rr_packet *pkt,
947 struct msm_ipc_router_xprt_info *dst_xprt_info)
948{
949 int hdr_size = 0;
950 int xprt_version = 0;
951 struct msm_ipc_router_xprt_info *xprt_info = dst_xprt_info;
952
953 if (!pkt) {
954 IPC_RTR_ERR("%s: NULL PKT\n", __func__);
955 return -EINVAL;
956 }
957
958 if (xprt_info)
959 xprt_version = xprt_info->xprt->get_version(xprt_info->xprt);
960
961 if (xprt_version == IPC_ROUTER_V1) {
962 pkt->hdr.version = IPC_ROUTER_V1;
963 hdr_size = sizeof(struct rr_header_v1);
964 } else if (xprt_version == IPC_ROUTER_V2) {
965 pkt->hdr.version = IPC_ROUTER_V2;
966 hdr_size = sizeof(struct rr_header_v2) + pkt->opt_hdr.len;
967 } else {
968 IPC_RTR_ERR("%s: Invalid xprt_version %d\n",
969 __func__, xprt_version);
970 hdr_size = -EINVAL;
971 }
972
973 return hdr_size;
974}
975
976/**
977 * calc_rx_header_size() - Calculate the RX header size
978 * @xprt_info: XPRT info of the received message.
979 *
980 * @return: valid header size on success, INT_MAX on failure.
981 */
982static int calc_rx_header_size(struct msm_ipc_router_xprt_info *xprt_info)
983{
984 int xprt_version = 0;
985 int hdr_size = INT_MAX;
986
987 if (xprt_info)
988 xprt_version = xprt_info->xprt->get_version(xprt_info->xprt);
989
990 if (xprt_version == IPC_ROUTER_V1)
991 hdr_size = sizeof(struct rr_header_v1);
992 else if (xprt_version == IPC_ROUTER_V2)
993 hdr_size = sizeof(struct rr_header_v2);
994 return hdr_size;
995}
996
997/**
998 * prepend_header_v1() - Prepend IPC Router header of version 1
999 * @pkt: Packet structure which contains the header info to be prepended.
1000 * @hdr_size: Size of the header
1001 *
1002 * @return: 0 on success, standard Linux error codes on failure.
1003 */
1004static int prepend_header_v1(struct rr_packet *pkt, int hdr_size)
1005{
1006 struct sk_buff *temp_skb;
1007 struct rr_header_v1 *hdr;
1008
1009 if (!pkt || hdr_size <= 0) {
1010 IPC_RTR_ERR("%s: Invalid input parameters\n", __func__);
1011 return -EINVAL;
1012 }
1013
1014 temp_skb = skb_peek(pkt->pkt_fragment_q);
1015 if (!temp_skb || !temp_skb->data) {
1016 IPC_RTR_ERR("%s: No SKBs in skb_queue\n", __func__);
1017 return -EINVAL;
1018 }
1019
1020 if (skb_headroom(temp_skb) < hdr_size) {
1021 temp_skb = alloc_skb(hdr_size, GFP_KERNEL);
1022 if (!temp_skb) {
1023 IPC_RTR_ERR("%s: Could not allocate SKB of size %d\n",
1024 __func__, hdr_size);
1025 return -ENOMEM;
1026 }
1027 skb_reserve(temp_skb, hdr_size);
1028 }
1029
1030 hdr = (struct rr_header_v1 *)skb_push(temp_skb, hdr_size);
1031 memcpy(hdr, &pkt->hdr, hdr_size);
1032 if (temp_skb != skb_peek(pkt->pkt_fragment_q))
1033 skb_queue_head(pkt->pkt_fragment_q, temp_skb);
1034 pkt->length += hdr_size;
1035 return 0;
1036}
1037
1038/**
1039 * prepend_header_v2() - Prepend IPC Router header of version 2
1040 * @pkt: Packet structure which contains the header info to be prepended.
1041 * @hdr_size: Size of the header
1042 *
1043 * @return: 0 on success, standard Linux error codes on failure.
1044 */
1045static int prepend_header_v2(struct rr_packet *pkt, int hdr_size)
1046{
1047 struct sk_buff *temp_skb;
1048 struct rr_header_v2 *hdr;
1049
1050 if (!pkt || hdr_size <= 0) {
1051 IPC_RTR_ERR("%s: Invalid input parameters\n", __func__);
1052 return -EINVAL;
1053 }
1054
1055 temp_skb = skb_peek(pkt->pkt_fragment_q);
1056 if (!temp_skb || !temp_skb->data) {
1057 IPC_RTR_ERR("%s: No SKBs in skb_queue\n", __func__);
1058 return -EINVAL;
1059 }
1060
1061 if (skb_headroom(temp_skb) < hdr_size) {
1062 temp_skb = alloc_skb(hdr_size, GFP_KERNEL);
1063 if (!temp_skb) {
1064 IPC_RTR_ERR("%s: Could not allocate SKB of size %d\n",
1065 __func__, hdr_size);
1066 return -ENOMEM;
1067 }
1068 skb_reserve(temp_skb, hdr_size);
1069 }
1070
1071 hdr = (struct rr_header_v2 *)skb_push(temp_skb, hdr_size);
1072 hdr->version = (u8)pkt->hdr.version;
1073 hdr->type = (u8)pkt->hdr.type;
1074 hdr->control_flag = (u8)pkt->hdr.control_flag;
1075 hdr->size = (u32)pkt->hdr.size;
1076 hdr->src_node_id = (u16)pkt->hdr.src_node_id;
1077 hdr->src_port_id = (u16)pkt->hdr.src_port_id;
1078 hdr->dst_node_id = (u16)pkt->hdr.dst_node_id;
1079 hdr->dst_port_id = (u16)pkt->hdr.dst_port_id;
1080 if (pkt->opt_hdr.len > 0) {
1081 hdr->opt_len = pkt->opt_hdr.len / IPCR_WORD_SIZE;
1082 memcpy(hdr + sizeof(*hdr), pkt->opt_hdr.data, pkt->opt_hdr.len);
1083 } else {
1084 hdr->opt_len = 0;
1085 }
1086 if (temp_skb != skb_peek(pkt->pkt_fragment_q))
1087 skb_queue_head(pkt->pkt_fragment_q, temp_skb);
1088 pkt->length += hdr_size;
1089 return 0;
1090}
1091
1092/**
1093 * prepend_header() - Prepend IPC Router header
1094 * @pkt: Packet structure which contains the header info to be prepended.
1095 * @xprt_info: XPRT through which the packet is transmitted.
1096 *
1097 * @return: 0 on success, standard Linux error codes on failure.
1098 *
1099 * This function prepends the header to the packet to be transmitted. The
1100 * IPC Router header version to be prepended depends on the XPRT through
1101 * which the destination is reachable.
1102 */
1103static int prepend_header(struct rr_packet *pkt,
1104 struct msm_ipc_router_xprt_info *xprt_info)
1105{
1106 int hdr_size;
1107 struct sk_buff *temp_skb;
1108
1109 if (!pkt) {
1110 IPC_RTR_ERR("%s: NULL PKT\n", __func__);
1111 return -EINVAL;
1112 }
1113
1114 temp_skb = skb_peek(pkt->pkt_fragment_q);
1115 if (!temp_skb || !temp_skb->data) {
1116 IPC_RTR_ERR("%s: No SKBs in skb_queue\n", __func__);
1117 return -EINVAL;
1118 }
1119
1120 hdr_size = calc_tx_header_size(pkt, xprt_info);
1121 if (hdr_size <= 0)
1122 return hdr_size;
1123
1124 if (pkt->hdr.version == IPC_ROUTER_V1)
1125 return prepend_header_v1(pkt, hdr_size);
1126 else if (pkt->hdr.version == IPC_ROUTER_V2)
1127 return prepend_header_v2(pkt, hdr_size);
1128 else
1129 return -EINVAL;
1130}
1131
1132/**
1133 * defragment_pkt() - Defragment and linearize the packet
1134 * @pkt: Packet to be linearized.
1135 *
1136 * @return: 0 on success, standard Linux error codes on failure.
1137 *
1138 * Some packets contain fragments of data over multiple SKBs. If an XPRT
1139 * does not supported fragmented writes, linearize multiple SKBs into one
1140 * single SKB.
1141 */
1142static int defragment_pkt(struct rr_packet *pkt)
1143{
1144 struct sk_buff *dst_skb, *src_skb, *temp_skb;
1145 int offset = 0, buf_len = 0, copy_len;
1146 void *buf;
1147 int align_size;
1148
1149 if (!pkt || pkt->length <= 0) {
1150 IPC_RTR_ERR("%s: Invalid PKT\n", __func__);
1151 return -EINVAL;
1152 }
1153
1154 if (skb_queue_len(pkt->pkt_fragment_q) == 1)
1155 return 0;
1156
1157 align_size = ALIGN_SIZE(pkt->length);
1158 dst_skb = alloc_skb(pkt->length + align_size, GFP_KERNEL);
1159 if (!dst_skb) {
1160 IPC_RTR_ERR("%s: could not allocate one skb of size %d\n",
1161 __func__, pkt->length);
1162 return -ENOMEM;
1163 }
1164 buf = skb_put(dst_skb, pkt->length);
1165 buf_len = pkt->length;
1166
1167 skb_queue_walk(pkt->pkt_fragment_q, src_skb) {
1168 copy_len = buf_len < src_skb->len ? buf_len : src_skb->len;
1169 memcpy(buf + offset, src_skb->data, copy_len);
1170 offset += copy_len;
1171 buf_len -= copy_len;
1172 }
1173
1174 while (!skb_queue_empty(pkt->pkt_fragment_q)) {
1175 temp_skb = skb_dequeue(pkt->pkt_fragment_q);
1176 kfree_skb(temp_skb);
1177 }
1178 skb_queue_tail(pkt->pkt_fragment_q, dst_skb);
1179 return 0;
1180}
1181
1182static int post_pkt_to_port(struct msm_ipc_port *port_ptr,
1183 struct rr_packet *pkt, int clone)
1184{
1185 struct rr_packet *temp_pkt = pkt;
1186 void (*notify)(unsigned int event, void *oob_data,
1187 size_t oob_data_len, void *priv);
1188 void (*data_ready)(struct sock *sk) = NULL;
1189 struct sock *sk;
1190 u32 pkt_type;
1191
1192 if (unlikely(!port_ptr || !pkt))
1193 return -EINVAL;
1194
1195 if (clone) {
1196 temp_pkt = clone_pkt(pkt);
1197 if (!temp_pkt) {
1198 IPC_RTR_ERR(
1199 "%s: Error cloning packet for port %08x:%08x\n",
1200 __func__, port_ptr->this_port.node_id,
1201 port_ptr->this_port.port_id);
1202 return -ENOMEM;
1203 }
1204 }
1205
1206 mutex_lock(&port_ptr->port_rx_q_lock_lhc3);
Arun Kumar Neelakantam74ff8562017-05-26 17:57:52 +05301207 if (pkt->ws_need)
1208 __pm_stay_awake(port_ptr->port_rx_ws);
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06001209 list_add_tail(&temp_pkt->list, &port_ptr->port_rx_q);
1210 wake_up(&port_ptr->port_rx_wait_q);
1211 notify = port_ptr->notify;
1212 pkt_type = temp_pkt->hdr.type;
1213 sk = (struct sock *)port_ptr->endpoint;
1214 if (sk) {
1215 read_lock(&sk->sk_callback_lock);
1216 data_ready = sk->sk_data_ready;
1217 read_unlock(&sk->sk_callback_lock);
1218 }
1219 mutex_unlock(&port_ptr->port_rx_q_lock_lhc3);
1220 if (notify)
1221 notify(pkt_type, NULL, 0, port_ptr->priv);
1222 else if (sk && data_ready)
1223 data_ready(sk);
1224
1225 return 0;
1226}
1227
1228/**
1229 * ipc_router_peek_pkt_size() - Peek into the packet header to get potential
1230 * packet size
1231 * @data: Starting address of the packet which points to router header.
1232 *
1233 * @returns: potential packet size on success, < 0 on error.
1234 *
1235 * This function is used by the underlying transport abstraction layer to
1236 * peek into the potential packet size of an incoming packet. This information
1237 * is used to perform link layer fragmentation and re-assembly
1238 */
1239int ipc_router_peek_pkt_size(char *data)
1240{
1241 int size;
1242
1243 if (!data) {
1244 pr_err("%s: NULL PKT\n", __func__);
1245 return -EINVAL;
1246 }
1247
1248 if (data[0] == IPC_ROUTER_V1)
1249 size = ((struct rr_header_v1 *)data)->size +
1250 sizeof(struct rr_header_v1);
1251 else if (data[0] == IPC_ROUTER_V2)
1252 size = ((struct rr_header_v2 *)data)->size +
1253 ((struct rr_header_v2 *)data)->opt_len * IPCR_WORD_SIZE
1254 + sizeof(struct rr_header_v2);
1255 else
1256 return -EINVAL;
1257
1258 size += ALIGN_SIZE(size);
1259 return size;
1260}
1261
1262static int post_control_ports(struct rr_packet *pkt)
1263{
1264 struct msm_ipc_port *port_ptr;
1265
1266 if (!pkt)
1267 return -EINVAL;
1268
1269 down_read(&control_ports_lock_lha5);
1270 list_for_each_entry(port_ptr, &control_ports, list)
1271 post_pkt_to_port(port_ptr, pkt, 1);
1272 up_read(&control_ports_lock_lha5);
1273 return 0;
1274}
1275
1276static u32 allocate_port_id(void)
1277{
1278 u32 port_id = 0, prev_port_id, key;
1279 struct msm_ipc_port *port_ptr;
1280
1281 mutex_lock(&next_port_id_lock_lhc1);
1282 prev_port_id = next_port_id;
1283 down_read(&local_ports_lock_lhc2);
1284 do {
1285 next_port_id++;
1286 if ((next_port_id & IPC_ROUTER_ADDRESS) == IPC_ROUTER_ADDRESS)
1287 next_port_id = 1;
1288
1289 key = (next_port_id & (LP_HASH_SIZE - 1));
1290 if (list_empty(&local_ports[key])) {
1291 port_id = next_port_id;
1292 break;
1293 }
1294 list_for_each_entry(port_ptr, &local_ports[key], list) {
1295 if (port_ptr->this_port.port_id == next_port_id) {
1296 port_id = next_port_id;
1297 break;
1298 }
1299 }
1300 if (!port_id) {
1301 port_id = next_port_id;
1302 break;
1303 }
1304 port_id = 0;
1305 } while (next_port_id != prev_port_id);
1306 up_read(&local_ports_lock_lhc2);
1307 mutex_unlock(&next_port_id_lock_lhc1);
1308
1309 return port_id;
1310}
1311
1312void msm_ipc_router_add_local_port(struct msm_ipc_port *port_ptr)
1313{
1314 u32 key;
1315
1316 if (!port_ptr)
1317 return;
1318
1319 key = (port_ptr->this_port.port_id & (LP_HASH_SIZE - 1));
1320 down_write(&local_ports_lock_lhc2);
1321 list_add_tail(&port_ptr->list, &local_ports[key]);
1322 up_write(&local_ports_lock_lhc2);
1323}
1324
1325/**
1326 * msm_ipc_router_create_raw_port() - Create an IPC Router port
1327 * @endpoint: User-space space socket information to be cached.
1328 * @notify: Function to notify incoming events on the port.
1329 * @event: Event ID to be handled.
1330 * @oob_data: Any out-of-band data associated with the event.
1331 * @oob_data_len: Size of the out-of-band data, if valid.
1332 * @priv: Private data registered during the port creation.
1333 * @priv: Private Data to be passed during the event notification.
1334 *
1335 * @return: Valid pointer to port on success, NULL on failure.
1336 *
1337 * This function is used to create an IPC Router port. The port is used for
1338 * communication locally or outside the subsystem.
1339 */
1340struct msm_ipc_port *
1341msm_ipc_router_create_raw_port(void *endpoint,
1342 void (*notify)(unsigned int event,
1343 void *oob_data,
1344 size_t oob_data_len, void *priv),
1345 void *priv)
1346{
1347 struct msm_ipc_port *port_ptr;
1348
1349 port_ptr = kzalloc(sizeof(*port_ptr), GFP_KERNEL);
1350 if (!port_ptr)
1351 return NULL;
1352
1353 port_ptr->this_port.node_id = IPC_ROUTER_NID_LOCAL;
1354 port_ptr->this_port.port_id = allocate_port_id();
1355 if (!port_ptr->this_port.port_id) {
1356 IPC_RTR_ERR("%s: All port ids are in use\n", __func__);
1357 kfree(port_ptr);
1358 return NULL;
1359 }
1360
1361 mutex_init(&port_ptr->port_lock_lhc3);
1362 INIT_LIST_HEAD(&port_ptr->port_rx_q);
1363 mutex_init(&port_ptr->port_rx_q_lock_lhc3);
1364 init_waitqueue_head(&port_ptr->port_rx_wait_q);
1365 snprintf(port_ptr->rx_ws_name, MAX_WS_NAME_SZ,
Dhoat Harpal3ad5fe32017-06-19 21:26:13 +05301366 "ipc%08x_%d_%s",
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06001367 port_ptr->this_port.port_id,
Dhoat Harpal3ad5fe32017-06-19 21:26:13 +05301368 task_pid_nr(current),
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06001369 current->comm);
1370 port_ptr->port_rx_ws = wakeup_source_register(port_ptr->rx_ws_name);
1371 if (!port_ptr->port_rx_ws) {
1372 kfree(port_ptr);
1373 return NULL;
1374 }
1375 init_waitqueue_head(&port_ptr->port_tx_wait_q);
1376 kref_init(&port_ptr->ref);
1377
1378 port_ptr->endpoint = endpoint;
1379 port_ptr->notify = notify;
1380 port_ptr->priv = priv;
1381
1382 msm_ipc_router_add_local_port(port_ptr);
1383 if (endpoint)
1384 sock_hold(ipc_port_sk(endpoint));
1385 return port_ptr;
1386}
1387
1388/**
1389 * ipc_router_get_port_ref() - Get a reference to the local port
1390 * @port_id: Port ID of the local port for which reference is get.
1391 *
1392 * @return: If port is found, a reference to the port is returned.
1393 * Else NULL is returned.
1394 */
1395static struct msm_ipc_port *ipc_router_get_port_ref(u32 port_id)
1396{
1397 int key = (port_id & (LP_HASH_SIZE - 1));
1398 struct msm_ipc_port *port_ptr;
1399
1400 down_read(&local_ports_lock_lhc2);
1401 list_for_each_entry(port_ptr, &local_ports[key], list) {
1402 if (port_ptr->this_port.port_id == port_id) {
1403 kref_get(&port_ptr->ref);
1404 up_read(&local_ports_lock_lhc2);
1405 return port_ptr;
1406 }
1407 }
1408 up_read(&local_ports_lock_lhc2);
1409 return NULL;
1410}
1411
1412/**
1413 * ipc_router_release_port() - Cleanup and release the port
1414 * @ref: Reference to the port.
1415 *
1416 * This function is called when all references to the port are released.
1417 */
1418void ipc_router_release_port(struct kref *ref)
1419{
1420 struct rr_packet *pkt, *temp_pkt;
1421 struct msm_ipc_port *port_ptr =
1422 container_of(ref, struct msm_ipc_port, ref);
1423
1424 mutex_lock(&port_ptr->port_rx_q_lock_lhc3);
1425 list_for_each_entry_safe(pkt, temp_pkt, &port_ptr->port_rx_q, list) {
1426 list_del(&pkt->list);
1427 release_pkt(pkt);
1428 }
1429 mutex_unlock(&port_ptr->port_rx_q_lock_lhc3);
1430 wakeup_source_unregister(port_ptr->port_rx_ws);
1431 if (port_ptr->endpoint)
1432 sock_put(ipc_port_sk(port_ptr->endpoint));
1433 kfree(port_ptr);
1434}
1435
1436/**
1437 * ipc_router_get_rport_ref()- Get reference to the remote port
1438 * @node_id: Node ID corresponding to the remote port.
1439 * @port_id: Port ID corresponding to the remote port.
1440 *
1441 * @return: a reference to the remote port on success, NULL on failure.
1442 */
1443static struct msm_ipc_router_remote_port *ipc_router_get_rport_ref(
1444 u32 node_id, u32 port_id)
1445{
1446 struct msm_ipc_router_remote_port *rport_ptr;
1447 struct msm_ipc_routing_table_entry *rt_entry;
1448 int key = (port_id & (RP_HASH_SIZE - 1));
1449
1450 rt_entry = ipc_router_get_rtentry_ref(node_id);
1451 if (!rt_entry) {
1452 IPC_RTR_ERR("%s: Node is not up\n", __func__);
1453 return NULL;
1454 }
1455
1456 down_read(&rt_entry->lock_lha4);
1457 list_for_each_entry(rport_ptr,
1458 &rt_entry->remote_port_list[key], list) {
1459 if (rport_ptr->port_id == port_id) {
1460 kref_get(&rport_ptr->ref);
1461 goto out_lookup_rmt_port1;
1462 }
1463 }
1464 rport_ptr = NULL;
1465out_lookup_rmt_port1:
1466 up_read(&rt_entry->lock_lha4);
1467 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
1468 return rport_ptr;
1469}
1470
1471/**
1472 * ipc_router_create_rport() - Create a remote port
1473 * @node_id: Node ID corresponding to the remote port.
1474 * @port_id: Port ID corresponding to the remote port.
1475 * @xprt_info: XPRT through which the concerned node is reachable.
1476 *
1477 * @return: a reference to the remote port on success, NULL on failure.
1478 */
1479static struct msm_ipc_router_remote_port *ipc_router_create_rport(
1480 u32 node_id, u32 port_id,
1481 struct msm_ipc_router_xprt_info *xprt_info)
1482{
1483 struct msm_ipc_router_remote_port *rport_ptr;
1484 struct msm_ipc_routing_table_entry *rt_entry;
1485 int key = (port_id & (RP_HASH_SIZE - 1));
1486
1487 rt_entry = create_routing_table_entry(node_id, xprt_info);
1488 if (!rt_entry) {
1489 IPC_RTR_ERR("%s: Node cannot be created\n", __func__);
1490 return NULL;
1491 }
1492
1493 down_write(&rt_entry->lock_lha4);
1494 list_for_each_entry(rport_ptr,
1495 &rt_entry->remote_port_list[key], list) {
1496 if (rport_ptr->port_id == port_id)
1497 goto out_create_rmt_port1;
1498 }
1499
1500 rport_ptr = kmalloc(sizeof(*rport_ptr), GFP_KERNEL);
1501 if (!rport_ptr) {
1502 IPC_RTR_ERR("%s: Remote port alloc failed\n", __func__);
1503 goto out_create_rmt_port2;
1504 }
1505 rport_ptr->port_id = port_id;
1506 rport_ptr->node_id = node_id;
1507 rport_ptr->status = VALID;
1508 rport_ptr->sec_rule = NULL;
1509 rport_ptr->server = NULL;
1510 rport_ptr->tx_quota_cnt = 0;
1511 kref_init(&rport_ptr->ref);
1512 mutex_init(&rport_ptr->rport_lock_lhb2);
1513 INIT_LIST_HEAD(&rport_ptr->resume_tx_port_list);
1514 INIT_LIST_HEAD(&rport_ptr->conn_info_list);
1515 list_add_tail(&rport_ptr->list,
1516 &rt_entry->remote_port_list[key]);
1517out_create_rmt_port1:
1518 kref_get(&rport_ptr->ref);
1519out_create_rmt_port2:
1520 up_write(&rt_entry->lock_lha4);
1521 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
1522 return rport_ptr;
1523}
1524
1525/**
1526 * msm_ipc_router_free_resume_tx_port() - Free the resume_tx ports
1527 * @rport_ptr: Pointer to the remote port.
1528 *
1529 * This function deletes all the resume_tx ports associated with a remote port
1530 * and frees the memory allocated to each resume_tx port.
1531 *
1532 * Must be called with rport_ptr->rport_lock_lhb2 locked.
1533 */
1534static void msm_ipc_router_free_resume_tx_port(
1535 struct msm_ipc_router_remote_port *rport_ptr)
1536{
1537 struct msm_ipc_resume_tx_port *rtx_port, *tmp_rtx_port;
1538
1539 list_for_each_entry_safe(rtx_port, tmp_rtx_port,
1540 &rport_ptr->resume_tx_port_list, list) {
1541 list_del(&rtx_port->list);
1542 kfree(rtx_port);
1543 }
1544}
1545
1546/**
1547 * msm_ipc_router_lookup_resume_tx_port() - Lookup resume_tx port list
1548 * @rport_ptr: Remote port whose resume_tx port list needs to be looked.
1549 * @port_id: Port ID which needs to be looked from the list.
1550 *
1551 * return 1 if the port_id is found in the list, else 0.
1552 *
1553 * This function is used to lookup the existence of a local port in
1554 * remote port's resume_tx list. This function is used to ensure that
1555 * the same port is not added to the remote_port's resume_tx list repeatedly.
1556 *
1557 * Must be called with rport_ptr->rport_lock_lhb2 locked.
1558 */
1559static int msm_ipc_router_lookup_resume_tx_port(
1560 struct msm_ipc_router_remote_port *rport_ptr, u32 port_id)
1561{
1562 struct msm_ipc_resume_tx_port *rtx_port;
1563
1564 list_for_each_entry(rtx_port, &rport_ptr->resume_tx_port_list, list) {
1565 if (port_id == rtx_port->port_id)
1566 return 1;
1567 }
1568 return 0;
1569}
1570
1571/**
1572 * ipc_router_dummy_write_space() - Dummy write space available callback
1573 * @sk: Socket pointer for which the callback is called.
1574 */
1575void ipc_router_dummy_write_space(struct sock *sk)
1576{
1577}
1578
1579/**
1580 * post_resume_tx() - Post the resume_tx event
1581 * @rport_ptr: Pointer to the remote port
1582 * @pkt : The data packet that is received on a resume_tx event
1583 * @msg: Out of band data to be passed to kernel drivers
1584 *
1585 * This function informs about the reception of the resume_tx message from a
1586 * remote port pointed by rport_ptr to all the local ports that are in the
1587 * resume_tx_ports_list of this remote port. On posting the information, this
1588 * function sequentially deletes each entry in the resume_tx_port_list of the
1589 * remote port.
1590 *
1591 * Must be called with rport_ptr->rport_lock_lhb2 locked.
1592 */
1593static void post_resume_tx(struct msm_ipc_router_remote_port *rport_ptr,
1594 struct rr_packet *pkt, union rr_control_msg *msg)
1595{
1596 struct msm_ipc_resume_tx_port *rtx_port, *tmp_rtx_port;
1597 struct msm_ipc_port *local_port;
1598 struct sock *sk;
1599 void (*write_space)(struct sock *sk) = NULL;
1600
1601 list_for_each_entry_safe(rtx_port, tmp_rtx_port,
1602 &rport_ptr->resume_tx_port_list, list) {
1603 local_port = ipc_router_get_port_ref(rtx_port->port_id);
1604 if (local_port && local_port->notify) {
1605 wake_up(&local_port->port_tx_wait_q);
1606 local_port->notify(IPC_ROUTER_CTRL_CMD_RESUME_TX, msg,
1607 sizeof(*msg), local_port->priv);
1608 } else if (local_port) {
1609 wake_up(&local_port->port_tx_wait_q);
1610 sk = ipc_port_sk(local_port->endpoint);
1611 if (sk) {
1612 read_lock(&sk->sk_callback_lock);
1613 write_space = sk->sk_write_space;
1614 read_unlock(&sk->sk_callback_lock);
1615 }
1616 if (write_space &&
1617 write_space != ipc_router_dummy_write_space)
1618 write_space(sk);
1619 else
1620 post_pkt_to_port(local_port, pkt, 1);
1621 } else {
1622 IPC_RTR_ERR("%s: Local Port %d not Found",
1623 __func__, rtx_port->port_id);
1624 }
1625 if (local_port)
1626 kref_put(&local_port->ref, ipc_router_release_port);
1627 list_del(&rtx_port->list);
1628 kfree(rtx_port);
1629 }
1630}
1631
1632/**
1633 * signal_rport_exit() - Signal the local ports of remote port exit
1634 * @rport_ptr: Remote port that is exiting.
1635 *
1636 * This function is used to signal the local ports that are waiting
1637 * to resume transmission to a remote port that is exiting.
1638 */
1639static void signal_rport_exit(struct msm_ipc_router_remote_port *rport_ptr)
1640{
1641 struct msm_ipc_resume_tx_port *rtx_port, *tmp_rtx_port;
1642 struct msm_ipc_port *local_port;
1643
1644 mutex_lock(&rport_ptr->rport_lock_lhb2);
1645 rport_ptr->status = RESET;
1646 list_for_each_entry_safe(rtx_port, tmp_rtx_port,
1647 &rport_ptr->resume_tx_port_list, list) {
1648 local_port = ipc_router_get_port_ref(rtx_port->port_id);
1649 if (local_port) {
1650 wake_up(&local_port->port_tx_wait_q);
1651 kref_put(&local_port->ref, ipc_router_release_port);
1652 }
1653 list_del(&rtx_port->list);
1654 kfree(rtx_port);
1655 }
1656 mutex_unlock(&rport_ptr->rport_lock_lhb2);
1657}
1658
1659/**
1660 * ipc_router_release_rport() - Cleanup and release the remote port
1661 * @ref: Reference to the remote port.
1662 *
1663 * This function is called when all references to the remote port are released.
1664 */
1665static void ipc_router_release_rport(struct kref *ref)
1666{
1667 struct msm_ipc_router_remote_port *rport_ptr =
1668 container_of(ref, struct msm_ipc_router_remote_port, ref);
1669
1670 mutex_lock(&rport_ptr->rport_lock_lhb2);
1671 msm_ipc_router_free_resume_tx_port(rport_ptr);
1672 mutex_unlock(&rport_ptr->rport_lock_lhb2);
1673 kfree(rport_ptr);
1674}
1675
1676/**
1677 * ipc_router_destroy_rport() - Destroy the remote port
1678 * @rport_ptr: Pointer to the remote port to be destroyed.
1679 */
1680static void ipc_router_destroy_rport(
1681 struct msm_ipc_router_remote_port *rport_ptr)
1682{
1683 u32 node_id;
1684 struct msm_ipc_routing_table_entry *rt_entry;
1685
1686 if (!rport_ptr)
1687 return;
1688
1689 node_id = rport_ptr->node_id;
1690 rt_entry = ipc_router_get_rtentry_ref(node_id);
1691 if (!rt_entry) {
1692 IPC_RTR_ERR("%s: Node %d is not up\n", __func__, node_id);
1693 return;
1694 }
1695 down_write(&rt_entry->lock_lha4);
1696 list_del(&rport_ptr->list);
1697 up_write(&rt_entry->lock_lha4);
1698 signal_rport_exit(rport_ptr);
1699 kref_put(&rport_ptr->ref, ipc_router_release_rport);
1700 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
1701}
1702
1703/**
1704 * msm_ipc_router_lookup_server() - Lookup server information
1705 * @service: Service ID of the server info to be looked up.
1706 * @instance: Instance ID of the server info to be looked up.
1707 * @node_id: Node/Processor ID in which the server is hosted.
1708 * @port_id: Port ID within the node in which the server is hosted.
1709 *
1710 * @return: If found Pointer to server structure, else NULL.
1711 *
1712 * Note1: Lock the server_list_lock_lha2 before accessing this function.
1713 * Note2: If the <node_id:port_id> are <0:0>, then the lookup is restricted
1714 * to <service:instance>. Used only when a client wants to send a
1715 * message to any QMI server.
1716 */
1717static struct msm_ipc_server *msm_ipc_router_lookup_server(
1718 u32 service,
1719 u32 instance,
1720 u32 node_id,
1721 u32 port_id)
1722{
1723 struct msm_ipc_server *server;
1724 struct msm_ipc_server_port *server_port;
1725 int key = (service & (SRV_HASH_SIZE - 1));
1726
1727 list_for_each_entry(server, &server_list[key], list) {
1728 if ((server->name.service != service) ||
1729 (server->name.instance != instance))
1730 continue;
1731 if ((node_id == 0) && (port_id == 0))
1732 return server;
1733 list_for_each_entry(server_port, &server->server_port_list,
1734 list) {
1735 if ((server_port->server_addr.node_id == node_id) &&
1736 (server_port->server_addr.port_id == port_id))
1737 return server;
1738 }
1739 }
1740 return NULL;
1741}
1742
1743/**
1744 * ipc_router_get_server_ref() - Get reference to the server
1745 * @svc: Service ID for which the reference is required.
1746 * @ins: Instance ID for which the reference is required.
1747 * @node_id: Node/Processor ID in which the server is hosted.
1748 * @port_id: Port ID within the node in which the server is hosted.
1749 *
1750 * @return: If found return reference to server, else NULL.
1751 */
1752static struct msm_ipc_server *ipc_router_get_server_ref(
1753 u32 svc, u32 ins, u32 node_id, u32 port_id)
1754{
1755 struct msm_ipc_server *server;
1756
1757 down_read(&server_list_lock_lha2);
1758 server = msm_ipc_router_lookup_server(svc, ins, node_id, port_id);
1759 if (server)
1760 kref_get(&server->ref);
1761 up_read(&server_list_lock_lha2);
1762 return server;
1763}
1764
1765/**
1766 * ipc_router_release_server() - Cleanup and release the server
1767 * @ref: Reference to the server.
1768 *
1769 * This function is called when all references to the server are released.
1770 */
1771static void ipc_router_release_server(struct kref *ref)
1772{
1773 struct msm_ipc_server *server =
1774 container_of(ref, struct msm_ipc_server, ref);
1775
1776 kfree(server);
1777}
1778
1779/**
1780 * msm_ipc_router_create_server() - Add server info to hash table
1781 * @service: Service ID of the server info to be created.
1782 * @instance: Instance ID of the server info to be created.
1783 * @node_id: Node/Processor ID in which the server is hosted.
1784 * @port_id: Port ID within the node in which the server is hosted.
1785 * @xprt_info: XPRT through which the node hosting the server is reached.
1786 *
1787 * @return: Pointer to server structure on success, else NULL.
1788 *
1789 * This function adds the server info to the hash table. If the same
1790 * server(i.e. <service_id:instance_id>) is hosted in different nodes,
1791 * they are maintained as list of "server_port" under "server" structure.
1792 */
1793static struct msm_ipc_server *msm_ipc_router_create_server(
1794 u32 service,
1795 u32 instance,
1796 u32 node_id,
1797 u32 port_id,
1798 struct msm_ipc_router_xprt_info *xprt_info)
1799{
1800 struct msm_ipc_server *server = NULL;
1801 struct msm_ipc_server_port *server_port;
1802 struct platform_device *pdev;
1803 int key = (service & (SRV_HASH_SIZE - 1));
1804
1805 down_write(&server_list_lock_lha2);
1806 server = msm_ipc_router_lookup_server(service, instance, 0, 0);
1807 if (server) {
1808 list_for_each_entry(server_port, &server->server_port_list,
1809 list) {
1810 if ((server_port->server_addr.node_id == node_id) &&
1811 (server_port->server_addr.port_id == port_id))
1812 goto return_server;
1813 }
1814 goto create_srv_port;
1815 }
1816
1817 server = kzalloc(sizeof(*server), GFP_KERNEL);
1818 if (!server) {
1819 up_write(&server_list_lock_lha2);
1820 IPC_RTR_ERR("%s: Server allocation failed\n", __func__);
1821 return NULL;
1822 }
1823 server->name.service = service;
1824 server->name.instance = instance;
1825 server->synced_sec_rule = 0;
1826 INIT_LIST_HEAD(&server->server_port_list);
1827 kref_init(&server->ref);
1828 list_add_tail(&server->list, &server_list[key]);
1829 scnprintf(server->pdev_name, sizeof(server->pdev_name),
1830 "SVC%08x:%08x", service, instance);
1831 server->next_pdev_id = 1;
1832
1833create_srv_port:
1834 server_port = kzalloc(sizeof(*server_port), GFP_KERNEL);
1835 pdev = platform_device_alloc(server->pdev_name, server->next_pdev_id);
1836 if (!server_port || !pdev) {
1837 kfree(server_port);
1838 if (pdev)
1839 platform_device_put(pdev);
1840 if (list_empty(&server->server_port_list)) {
1841 list_del(&server->list);
1842 kfree(server);
1843 }
1844 up_write(&server_list_lock_lha2);
1845 IPC_RTR_ERR("%s: Server Port allocation failed\n", __func__);
1846 return NULL;
1847 }
1848 server_port->pdev = pdev;
1849 server_port->server_addr.node_id = node_id;
1850 server_port->server_addr.port_id = port_id;
1851 server_port->xprt_info = xprt_info;
1852 list_add_tail(&server_port->list, &server->server_port_list);
1853 server->next_pdev_id++;
1854 platform_device_add(server_port->pdev);
1855
1856return_server:
1857 /* Add a reference so that the caller can put it back */
1858 kref_get(&server->ref);
1859 up_write(&server_list_lock_lha2);
1860 return server;
1861}
1862
1863/**
1864 * ipc_router_destroy_server_nolock() - Remove server info from hash table
1865 * @server: Server info to be removed.
1866 * @node_id: Node/Processor ID in which the server is hosted.
1867 * @port_id: Port ID within the node in which the server is hosted.
1868 *
1869 * This function removes the server_port identified using <node_id:port_id>
1870 * from the server structure. If the server_port list under server structure
1871 * is empty after removal, then remove the server structure from the server
1872 * hash table. This function must be called with server_list_lock_lha2 locked.
1873 */
1874static void ipc_router_destroy_server_nolock(struct msm_ipc_server *server,
1875 u32 node_id, u32 port_id)
1876{
1877 struct msm_ipc_server_port *server_port;
1878 bool server_port_found = false;
1879
1880 if (!server)
1881 return;
1882
1883 list_for_each_entry(server_port, &server->server_port_list, list) {
1884 if ((server_port->server_addr.node_id == node_id) &&
1885 (server_port->server_addr.port_id == port_id)) {
1886 server_port_found = true;
1887 break;
1888 }
1889 }
1890 if (server_port_found && server_port) {
1891 platform_device_unregister(server_port->pdev);
1892 list_del(&server_port->list);
1893 kfree(server_port);
1894 }
1895 if (list_empty(&server->server_port_list)) {
1896 list_del(&server->list);
1897 kref_put(&server->ref, ipc_router_release_server);
1898 }
1899}
1900
1901/**
1902 * ipc_router_destroy_server() - Remove server info from hash table
1903 * @server: Server info to be removed.
1904 * @node_id: Node/Processor ID in which the server is hosted.
1905 * @port_id: Port ID within the node in which the server is hosted.
1906 *
1907 * This function removes the server_port identified using <node_id:port_id>
1908 * from the server structure. If the server_port list under server structure
1909 * is empty after removal, then remove the server structure from the server
1910 * hash table.
1911 */
1912static void ipc_router_destroy_server(struct msm_ipc_server *server,
1913 u32 node_id, u32 port_id)
1914{
1915 down_write(&server_list_lock_lha2);
1916 ipc_router_destroy_server_nolock(server, node_id, port_id);
1917 up_write(&server_list_lock_lha2);
1918}
1919
1920static int ipc_router_send_ctl_msg(
1921 struct msm_ipc_router_xprt_info *xprt_info,
1922 union rr_control_msg *msg,
1923 u32 dst_node_id)
1924{
1925 struct rr_packet *pkt;
1926 struct sk_buff *ipc_rtr_pkt;
1927 struct rr_header_v1 *hdr;
1928 int pkt_size;
1929 void *data;
1930 int ret = -EINVAL;
1931
1932 pkt = create_pkt(NULL);
1933 if (!pkt) {
1934 IPC_RTR_ERR("%s: pkt alloc failed\n", __func__);
1935 return -ENOMEM;
1936 }
1937
1938 pkt_size = IPC_ROUTER_HDR_SIZE + sizeof(*msg);
1939 ipc_rtr_pkt = alloc_skb(pkt_size, GFP_KERNEL);
1940 if (!ipc_rtr_pkt) {
1941 IPC_RTR_ERR("%s: ipc_rtr_pkt alloc failed\n", __func__);
1942 release_pkt(pkt);
1943 return -ENOMEM;
1944 }
1945
1946 skb_reserve(ipc_rtr_pkt, IPC_ROUTER_HDR_SIZE);
1947 data = skb_put(ipc_rtr_pkt, sizeof(*msg));
1948 memcpy(data, msg, sizeof(*msg));
1949 skb_queue_tail(pkt->pkt_fragment_q, ipc_rtr_pkt);
1950 pkt->length = sizeof(*msg);
1951
1952 hdr = &pkt->hdr;
1953 hdr->version = IPC_ROUTER_V1;
1954 hdr->type = msg->cmd;
1955 hdr->src_node_id = IPC_ROUTER_NID_LOCAL;
1956 hdr->src_port_id = IPC_ROUTER_ADDRESS;
1957 hdr->control_flag = 0;
1958 hdr->size = sizeof(*msg);
1959 if (hdr->type == IPC_ROUTER_CTRL_CMD_RESUME_TX ||
1960 (!xprt_info && dst_node_id == IPC_ROUTER_NID_LOCAL))
1961 hdr->dst_node_id = dst_node_id;
1962 else if (xprt_info)
1963 hdr->dst_node_id = xprt_info->remote_node_id;
1964 hdr->dst_port_id = IPC_ROUTER_ADDRESS;
1965
1966 if (dst_node_id == IPC_ROUTER_NID_LOCAL &&
1967 msg->cmd != IPC_ROUTER_CTRL_CMD_RESUME_TX) {
1968 ipc_router_log_msg(local_log_ctx, IPC_ROUTER_LOG_EVENT_TX, msg,
1969 hdr, NULL, NULL);
1970 ret = post_control_ports(pkt);
1971 } else if (dst_node_id == IPC_ROUTER_NID_LOCAL &&
1972 msg->cmd == IPC_ROUTER_CTRL_CMD_RESUME_TX) {
1973 ipc_router_log_msg(local_log_ctx, IPC_ROUTER_LOG_EVENT_TX, msg,
1974 hdr, NULL, NULL);
1975 ret = process_resume_tx_msg(msg, pkt);
1976 } else if (xprt_info && (msg->cmd == IPC_ROUTER_CTRL_CMD_HELLO ||
1977 xprt_info->initialized)) {
1978 mutex_lock(&xprt_info->tx_lock_lhb2);
1979 ipc_router_log_msg(xprt_info->log_ctx, IPC_ROUTER_LOG_EVENT_TX,
1980 msg, hdr, NULL, NULL);
1981 ret = prepend_header(pkt, xprt_info);
1982 if (ret < 0) {
1983 mutex_unlock(&xprt_info->tx_lock_lhb2);
1984 IPC_RTR_ERR("%s: Prepend Header failed\n", __func__);
1985 release_pkt(pkt);
1986 return ret;
1987 }
1988
1989 ret = xprt_info->xprt->write(pkt, pkt->length, xprt_info->xprt);
1990 mutex_unlock(&xprt_info->tx_lock_lhb2);
1991 }
1992
1993 release_pkt(pkt);
1994 return ret;
1995}
1996
1997static int
1998msm_ipc_router_send_server_list(u32 node_id,
1999 struct msm_ipc_router_xprt_info *xprt_info)
2000{
2001 union rr_control_msg ctl;
2002 struct msm_ipc_server *server;
2003 struct msm_ipc_server_port *server_port;
2004 int i;
2005
2006 if (!xprt_info || !xprt_info->initialized) {
2007 IPC_RTR_ERR("%s: Xprt info not initialized\n", __func__);
2008 return -EINVAL;
2009 }
2010
2011 memset(&ctl, 0, sizeof(ctl));
2012 ctl.cmd = IPC_ROUTER_CTRL_CMD_NEW_SERVER;
2013
2014 for (i = 0; i < SRV_HASH_SIZE; i++) {
2015 list_for_each_entry(server, &server_list[i], list) {
2016 ctl.srv.service = server->name.service;
2017 ctl.srv.instance = server->name.instance;
2018 list_for_each_entry(server_port,
2019 &server->server_port_list, list) {
2020 if (server_port->server_addr.node_id !=
2021 node_id)
2022 continue;
2023
2024 ctl.srv.node_id =
2025 server_port->server_addr.node_id;
2026 ctl.srv.port_id =
2027 server_port->server_addr.port_id;
2028 ipc_router_send_ctl_msg
2029 (xprt_info, &ctl,
2030 IPC_ROUTER_DUMMY_DEST_NODE);
2031 }
2032 }
2033 }
2034
2035 return 0;
2036}
2037
2038static int broadcast_ctl_msg_locally(union rr_control_msg *msg)
2039{
2040 return ipc_router_send_ctl_msg(NULL, msg, IPC_ROUTER_NID_LOCAL);
2041}
2042
2043static int broadcast_ctl_msg(union rr_control_msg *ctl)
2044{
2045 struct msm_ipc_router_xprt_info *xprt_info;
2046
2047 down_read(&xprt_info_list_lock_lha5);
2048 list_for_each_entry(xprt_info, &xprt_info_list, list) {
2049 ipc_router_send_ctl_msg(xprt_info, ctl,
2050 IPC_ROUTER_DUMMY_DEST_NODE);
2051 }
2052 up_read(&xprt_info_list_lock_lha5);
2053 broadcast_ctl_msg_locally(ctl);
2054
2055 return 0;
2056}
2057
2058static int relay_ctl_msg(struct msm_ipc_router_xprt_info *xprt_info,
2059 union rr_control_msg *ctl)
2060{
2061 struct msm_ipc_router_xprt_info *fwd_xprt_info;
2062
2063 if (!xprt_info || !ctl)
2064 return -EINVAL;
2065
2066 down_read(&xprt_info_list_lock_lha5);
2067 list_for_each_entry(fwd_xprt_info, &xprt_info_list, list) {
2068 if (xprt_info->xprt->link_id != fwd_xprt_info->xprt->link_id)
2069 ipc_router_send_ctl_msg(fwd_xprt_info, ctl,
2070 IPC_ROUTER_DUMMY_DEST_NODE);
2071 }
2072 up_read(&xprt_info_list_lock_lha5);
2073
2074 return 0;
2075}
2076
2077static int forward_msg(struct msm_ipc_router_xprt_info *xprt_info,
2078 struct rr_packet *pkt)
2079{
2080 struct rr_header_v1 *hdr;
2081 struct msm_ipc_router_xprt_info *fwd_xprt_info;
2082 struct msm_ipc_routing_table_entry *rt_entry;
2083 int ret = 0;
2084 int fwd_xprt_option;
2085
2086 if (!xprt_info || !pkt)
2087 return -EINVAL;
2088
2089 hdr = &pkt->hdr;
2090 rt_entry = ipc_router_get_rtentry_ref(hdr->dst_node_id);
2091 if (!(rt_entry) || !(rt_entry->xprt_info)) {
2092 IPC_RTR_ERR("%s: Routing table not initialized\n", __func__);
2093 ret = -ENODEV;
2094 goto fm_error1;
2095 }
2096
2097 down_read(&rt_entry->lock_lha4);
2098 fwd_xprt_info = rt_entry->xprt_info;
2099 ret = ipc_router_get_xprt_info_ref(fwd_xprt_info);
2100 if (ret < 0) {
2101 IPC_RTR_ERR("%s: Abort invalid xprt\n", __func__);
2102 goto fm_error_xprt;
2103 }
2104 ret = prepend_header(pkt, fwd_xprt_info);
2105 if (ret < 0) {
2106 IPC_RTR_ERR("%s: Prepend Header failed\n", __func__);
2107 goto fm_error2;
2108 }
2109 fwd_xprt_option = fwd_xprt_info->xprt->get_option(fwd_xprt_info->xprt);
2110 if (!(fwd_xprt_option & FRAG_PKT_WRITE_ENABLE)) {
2111 ret = defragment_pkt(pkt);
2112 if (ret < 0)
2113 goto fm_error2;
2114 }
2115
2116 mutex_lock(&fwd_xprt_info->tx_lock_lhb2);
2117 if (xprt_info->remote_node_id == fwd_xprt_info->remote_node_id) {
2118 IPC_RTR_ERR("%s: Discarding Command to route back\n", __func__);
2119 ret = -EINVAL;
2120 goto fm_error3;
2121 }
2122
2123 if (xprt_info->xprt->link_id == fwd_xprt_info->xprt->link_id) {
2124 IPC_RTR_ERR("%s: DST in the same cluster\n", __func__);
2125 ret = 0;
2126 goto fm_error3;
2127 }
2128 fwd_xprt_info->xprt->write(pkt, pkt->length, fwd_xprt_info->xprt);
2129 IPC_RTR_INFO(fwd_xprt_info->log_ctx,
2130 "%s %s Len:0x%x T:0x%x CF:0x%x SRC:<0x%x:0x%x> DST:<0x%x:0x%x>\n",
2131 "FWD", "TX", hdr->size, hdr->type, hdr->control_flag,
2132 hdr->src_node_id, hdr->src_port_id,
2133 hdr->dst_node_id, hdr->dst_port_id);
2134
2135fm_error3:
2136 mutex_unlock(&fwd_xprt_info->tx_lock_lhb2);
2137fm_error2:
2138 ipc_router_put_xprt_info_ref(fwd_xprt_info);
2139fm_error_xprt:
2140 up_read(&rt_entry->lock_lha4);
2141fm_error1:
2142 if (rt_entry)
2143 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
2144 return ret;
2145}
2146
2147static int msm_ipc_router_send_remove_client(struct comm_mode_info *mode_info,
2148 u32 node_id, u32 port_id)
2149{
2150 union rr_control_msg msg;
2151 struct msm_ipc_router_xprt_info *tmp_xprt_info;
2152 int mode;
2153 void *xprt_info;
2154 int rc = 0;
2155
2156 if (!mode_info) {
2157 IPC_RTR_ERR("%s: NULL mode_info\n", __func__);
2158 return -EINVAL;
2159 }
2160 mode = mode_info->mode;
2161 xprt_info = mode_info->xprt_info;
2162
2163 memset(&msg, 0, sizeof(msg));
2164 msg.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_CLIENT;
2165 msg.cli.node_id = node_id;
2166 msg.cli.port_id = port_id;
2167
2168 if ((mode == SINGLE_LINK_MODE) && xprt_info) {
2169 down_read(&xprt_info_list_lock_lha5);
2170 list_for_each_entry(tmp_xprt_info, &xprt_info_list, list) {
2171 if (tmp_xprt_info != xprt_info)
2172 continue;
2173 ipc_router_send_ctl_msg(tmp_xprt_info, &msg,
2174 IPC_ROUTER_DUMMY_DEST_NODE);
2175 break;
2176 }
2177 up_read(&xprt_info_list_lock_lha5);
2178 } else if ((mode == SINGLE_LINK_MODE) && !xprt_info) {
2179 broadcast_ctl_msg_locally(&msg);
2180 } else if (mode == MULTI_LINK_MODE) {
2181 broadcast_ctl_msg(&msg);
2182 } else if (mode != NULL_MODE) {
2183 IPC_RTR_ERR(
2184 "%s: Invalid mode(%d) + xprt_inf(%p) for %08x:%08x\n",
2185 __func__, mode, xprt_info, node_id, port_id);
2186 rc = -EINVAL;
2187 }
2188 return rc;
2189}
2190
2191static void update_comm_mode_info(struct comm_mode_info *mode_info,
2192 struct msm_ipc_router_xprt_info *xprt_info)
2193{
2194 if (!mode_info) {
2195 IPC_RTR_ERR("%s: NULL mode_info\n", __func__);
2196 return;
2197 }
2198
2199 if (mode_info->mode == NULL_MODE) {
2200 mode_info->xprt_info = xprt_info;
2201 mode_info->mode = SINGLE_LINK_MODE;
2202 } else if (mode_info->mode == SINGLE_LINK_MODE &&
2203 mode_info->xprt_info != xprt_info) {
2204 mode_info->mode = MULTI_LINK_MODE;
2205 }
2206}
2207
2208/**
2209 * cleanup_rmt_server() - Cleanup server hosted in the remote port
2210 * @xprt_info: XPRT through which this cleanup event is handled.
2211 * @rport_ptr: Remote port that is being cleaned up.
2212 * @server: Server that is hosted in the remote port.
2213 */
2214static void cleanup_rmt_server(struct msm_ipc_router_xprt_info *xprt_info,
2215 struct msm_ipc_router_remote_port *rport_ptr,
2216 struct msm_ipc_server *server)
2217{
2218 union rr_control_msg ctl;
2219
2220 memset(&ctl, 0, sizeof(ctl));
2221 ctl.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_SERVER;
2222 ctl.srv.service = server->name.service;
2223 ctl.srv.instance = server->name.instance;
2224 ctl.srv.node_id = rport_ptr->node_id;
2225 ctl.srv.port_id = rport_ptr->port_id;
2226 if (xprt_info)
2227 relay_ctl_msg(xprt_info, &ctl);
2228 broadcast_ctl_msg_locally(&ctl);
2229 ipc_router_destroy_server_nolock(server, rport_ptr->node_id,
2230 rport_ptr->port_id);
2231}
2232
2233static void cleanup_rmt_ports(struct msm_ipc_router_xprt_info *xprt_info,
2234 struct msm_ipc_routing_table_entry *rt_entry)
2235{
2236 struct msm_ipc_router_remote_port *rport_ptr, *tmp_rport_ptr;
2237 struct msm_ipc_server *server;
2238 union rr_control_msg ctl;
2239 int j;
2240
2241 memset(&ctl, 0, sizeof(ctl));
2242 for (j = 0; j < RP_HASH_SIZE; j++) {
2243 list_for_each_entry_safe(rport_ptr, tmp_rport_ptr,
2244 &rt_entry->remote_port_list[j], list) {
2245 list_del(&rport_ptr->list);
2246 mutex_lock(&rport_ptr->rport_lock_lhb2);
2247 server = rport_ptr->server;
2248 rport_ptr->server = NULL;
2249 mutex_unlock(&rport_ptr->rport_lock_lhb2);
2250 ipc_router_reset_conn(rport_ptr);
2251 if (server) {
2252 cleanup_rmt_server(xprt_info, rport_ptr,
2253 server);
2254 server = NULL;
2255 }
2256
2257 ctl.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_CLIENT;
2258 ctl.cli.node_id = rport_ptr->node_id;
2259 ctl.cli.port_id = rport_ptr->port_id;
2260 kref_put(&rport_ptr->ref, ipc_router_release_rport);
2261
2262 relay_ctl_msg(xprt_info, &ctl);
2263 broadcast_ctl_msg_locally(&ctl);
2264 }
2265 }
2266}
2267
2268static void msm_ipc_cleanup_routing_table(
2269 struct msm_ipc_router_xprt_info *xprt_info)
2270{
2271 int i;
2272 struct msm_ipc_routing_table_entry *rt_entry, *tmp_rt_entry;
2273
2274 if (!xprt_info) {
2275 IPC_RTR_ERR("%s: Invalid xprt_info\n", __func__);
2276 return;
2277 }
2278
2279 down_write(&server_list_lock_lha2);
2280 down_write(&routing_table_lock_lha3);
2281 for (i = 0; i < RT_HASH_SIZE; i++) {
2282 list_for_each_entry_safe(rt_entry, tmp_rt_entry,
2283 &routing_table[i], list) {
2284 down_write(&rt_entry->lock_lha4);
2285 if (rt_entry->xprt_info != xprt_info) {
2286 up_write(&rt_entry->lock_lha4);
2287 continue;
2288 }
2289 cleanup_rmt_ports(xprt_info, rt_entry);
2290 rt_entry->xprt_info = NULL;
2291 up_write(&rt_entry->lock_lha4);
2292 list_del(&rt_entry->list);
2293 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
2294 }
2295 }
2296 up_write(&routing_table_lock_lha3);
2297 up_write(&server_list_lock_lha2);
2298}
2299
2300/**
2301 * sync_sec_rule() - Synchrnoize the security rule into the server structure
2302 * @server: Server structure where the rule has to be synchronized.
2303 * @rule: Security tule to be synchronized.
2304 *
2305 * This function is used to update the server structure with the security
2306 * rule configured for the <service:instance> corresponding to that server.
2307 */
2308static void sync_sec_rule(struct msm_ipc_server *server, void *rule)
2309{
2310 struct msm_ipc_server_port *server_port;
2311 struct msm_ipc_router_remote_port *rport_ptr = NULL;
2312
2313 list_for_each_entry(server_port, &server->server_port_list, list) {
2314 rport_ptr = ipc_router_get_rport_ref(
2315 server_port->server_addr.node_id,
2316 server_port->server_addr.port_id);
2317 if (!rport_ptr)
2318 continue;
2319 rport_ptr->sec_rule = rule;
2320 kref_put(&rport_ptr->ref, ipc_router_release_rport);
2321 }
2322 server->synced_sec_rule = 1;
2323}
2324
2325/**
2326 * msm_ipc_sync_sec_rule() - Sync the security rule to the service
2327 * @service: Service for which the rule has to be synchronized.
2328 * @instance: Instance for which the rule has to be synchronized.
2329 * @rule: Security rule to be synchronized.
2330 *
2331 * This function is used to syncrhonize the security rule with the server
2332 * hash table, if the user-space script configures the rule after the service
2333 * has come up. This function is used to synchronize the security rule to a
2334 * specific service and optionally a specific instance.
2335 */
2336void msm_ipc_sync_sec_rule(u32 service, u32 instance, void *rule)
2337{
2338 int key = (service & (SRV_HASH_SIZE - 1));
2339 struct msm_ipc_server *server;
2340
2341 down_write(&server_list_lock_lha2);
2342 list_for_each_entry(server, &server_list[key], list) {
2343 if (server->name.service != service)
2344 continue;
2345
2346 if (server->name.instance != instance &&
2347 instance != ALL_INSTANCE)
2348 continue;
2349
2350 /* If the rule applies to all instances and if the specific
2351 * instance of a service has a rule synchronized already,
2352 * do not apply the rule for that specific instance.
2353 */
2354 if (instance == ALL_INSTANCE && server->synced_sec_rule)
2355 continue;
2356
2357 sync_sec_rule(server, rule);
2358 }
2359 up_write(&server_list_lock_lha2);
2360}
2361
2362/**
2363 * msm_ipc_sync_default_sec_rule() - Default security rule to all services
2364 * @rule: Security rule to be synchronized.
2365 *
2366 * This function is used to syncrhonize the security rule with the server
2367 * hash table, if the user-space script configures the rule after the service
2368 * has come up. This function is used to synchronize the security rule that
2369 * applies to all services, if the concerned service do not have any rule
2370 * defined.
2371 */
2372void msm_ipc_sync_default_sec_rule(void *rule)
2373{
2374 int key;
2375 struct msm_ipc_server *server;
2376
2377 down_write(&server_list_lock_lha2);
2378 for (key = 0; key < SRV_HASH_SIZE; key++) {
2379 list_for_each_entry(server, &server_list[key], list) {
2380 if (server->synced_sec_rule)
2381 continue;
2382
2383 sync_sec_rule(server, rule);
2384 }
2385 }
2386 up_write(&server_list_lock_lha2);
2387}
2388
2389/**
2390 * ipc_router_reset_conn() - Reset the connection to remote port
2391 * @rport_ptr: Pointer to the remote port to be disconnected.
2392 *
2393 * This function is used to reset all the local ports that are connected to
2394 * the remote port being passed.
2395 */
2396static void ipc_router_reset_conn(struct msm_ipc_router_remote_port *rport_ptr)
2397{
2398 struct msm_ipc_port *port_ptr;
2399 struct ipc_router_conn_info *conn_info, *tmp_conn_info;
2400
2401 mutex_lock(&rport_ptr->rport_lock_lhb2);
2402 list_for_each_entry_safe(conn_info, tmp_conn_info,
2403 &rport_ptr->conn_info_list, list) {
2404 port_ptr = ipc_router_get_port_ref(conn_info->port_id);
2405 if (port_ptr) {
2406 mutex_lock(&port_ptr->port_lock_lhc3);
2407 port_ptr->conn_status = CONNECTION_RESET;
2408 mutex_unlock(&port_ptr->port_lock_lhc3);
2409 wake_up(&port_ptr->port_rx_wait_q);
2410 kref_put(&port_ptr->ref, ipc_router_release_port);
2411 }
2412
2413 list_del(&conn_info->list);
2414 kfree(conn_info);
2415 }
2416 mutex_unlock(&rport_ptr->rport_lock_lhb2);
2417}
2418
2419/**
2420 * ipc_router_set_conn() - Set the connection by initializing dest address
2421 * @port_ptr: Local port in which the connection has to be set.
2422 * @addr: Destination address of the connection.
2423 *
2424 * @return: 0 on success, standard Linux error codes on failure.
2425 */
2426int ipc_router_set_conn(struct msm_ipc_port *port_ptr,
2427 struct msm_ipc_addr *addr)
2428{
2429 struct msm_ipc_router_remote_port *rport_ptr;
2430 struct ipc_router_conn_info *conn_info;
2431
2432 if (unlikely(!port_ptr || !addr))
2433 return -EINVAL;
2434
2435 if (addr->addrtype != MSM_IPC_ADDR_ID) {
2436 IPC_RTR_ERR("%s: Invalid Address type\n", __func__);
2437 return -EINVAL;
2438 }
2439
2440 if (port_ptr->type == SERVER_PORT) {
2441 IPC_RTR_ERR("%s: Connection refused on a server port\n",
2442 __func__);
2443 return -ECONNREFUSED;
2444 }
2445
2446 if (port_ptr->conn_status == CONNECTED) {
2447 IPC_RTR_ERR("%s: Port %08x already connected\n",
2448 __func__, port_ptr->this_port.port_id);
2449 return -EISCONN;
2450 }
2451
2452 conn_info = kzalloc(sizeof(*conn_info), GFP_KERNEL);
2453 if (!conn_info) {
2454 IPC_RTR_ERR("%s: Error allocating conn_info\n", __func__);
2455 return -ENOMEM;
2456 }
2457 INIT_LIST_HEAD(&conn_info->list);
2458 conn_info->port_id = port_ptr->this_port.port_id;
2459
2460 rport_ptr = ipc_router_get_rport_ref(addr->addr.port_addr.node_id,
2461 addr->addr.port_addr.port_id);
2462 if (!rport_ptr) {
2463 IPC_RTR_ERR("%s: Invalid remote endpoint\n", __func__);
2464 kfree(conn_info);
2465 return -ENODEV;
2466 }
2467 mutex_lock(&rport_ptr->rport_lock_lhb2);
2468 list_add_tail(&conn_info->list, &rport_ptr->conn_info_list);
2469 mutex_unlock(&rport_ptr->rport_lock_lhb2);
2470
2471 mutex_lock(&port_ptr->port_lock_lhc3);
2472 memcpy(&port_ptr->dest_addr, &addr->addr.port_addr,
2473 sizeof(struct msm_ipc_port_addr));
2474 port_ptr->conn_status = CONNECTED;
2475 mutex_unlock(&port_ptr->port_lock_lhc3);
2476 kref_put(&rport_ptr->ref, ipc_router_release_rport);
2477 return 0;
2478}
2479
2480/**
2481 * do_version_negotiation() - perform a version negotiation and set the version
2482 * @xprt_info: Pointer to the IPC Router transport info structure.
2483 * @msg: Pointer to the IPC Router HELLO message.
2484 *
2485 * This function performs the version negotiation by verifying the computed
2486 * checksum first. If the checksum matches with the magic number, it sets the
2487 * negotiated IPC Router version in transport.
2488 */
2489static void do_version_negotiation(struct msm_ipc_router_xprt_info *xprt_info,
2490 union rr_control_msg *msg)
2491{
2492 u32 magic;
2493 unsigned int version;
2494
2495 if (!xprt_info)
2496 return;
2497 magic = ipc_router_calc_checksum(msg);
2498 if (magic == IPC_ROUTER_HELLO_MAGIC) {
2499 version = fls(msg->hello.versions & IPC_ROUTER_VER_BITMASK) - 1;
2500 /*Bit 0 & 31 are reserved for future usage*/
2501 if ((version > 0) &&
2502 (version != (sizeof(version) * BITS_PER_BYTE - 1)) &&
2503 xprt_info->xprt->set_version)
2504 xprt_info->xprt->set_version(xprt_info->xprt, version);
2505 }
2506}
2507
Arun Kumar Neelakantamf99191d2018-06-11 18:13:43 +05302508static int send_hello_msg(struct msm_ipc_router_xprt_info *xprt_info)
2509{
2510 int rc = 0;
2511 union rr_control_msg ctl;
2512
2513 if (!xprt_info->hello_sent) {
2514 xprt_info->hello_sent = 1;
2515 /* Send a HELLO message */
2516 memset(&ctl, 0, sizeof(ctl));
2517 ctl.hello.cmd = IPC_ROUTER_CTRL_CMD_HELLO;
2518 ctl.hello.checksum = IPC_ROUTER_HELLO_MAGIC;
2519 ctl.hello.versions = (uint32_t)IPC_ROUTER_VER_BITMASK;
2520 ctl.hello.checksum = ipc_router_calc_checksum(&ctl);
2521 rc = ipc_router_send_ctl_msg(xprt_info, &ctl,
2522 IPC_ROUTER_DUMMY_DEST_NODE);
2523 if (rc < 0) {
2524 xprt_info->hello_sent = 0;
2525 IPC_RTR_ERR("%s: Error sending HELLO message\n",
2526 __func__);
2527 return rc;
2528 }
2529 }
2530 return rc;
2531}
2532
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002533static int process_hello_msg(struct msm_ipc_router_xprt_info *xprt_info,
2534 union rr_control_msg *msg,
2535 struct rr_header_v1 *hdr)
2536{
2537 int i, rc = 0;
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002538 struct msm_ipc_routing_table_entry *rt_entry;
2539
2540 if (!hdr)
2541 return -EINVAL;
2542
2543 xprt_info->remote_node_id = hdr->src_node_id;
2544 rt_entry = create_routing_table_entry(hdr->src_node_id, xprt_info);
2545 if (!rt_entry) {
2546 IPC_RTR_ERR("%s: rt_entry allocation failed\n", __func__);
2547 return -ENOMEM;
2548 }
2549 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
2550
2551 do_version_negotiation(xprt_info, msg);
Arun Kumar Neelakantamf99191d2018-06-11 18:13:43 +05302552 rc = send_hello_msg(xprt_info);
2553 if (rc < 0)
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002554 return rc;
Arun Kumar Neelakantamf99191d2018-06-11 18:13:43 +05302555
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002556 xprt_info->initialized = 1;
2557
2558 /* Send list of servers from the local node and from nodes
2559 * outside the mesh network in which this XPRT is part of.
2560 */
2561 down_read(&server_list_lock_lha2);
2562 down_read(&routing_table_lock_lha3);
2563 for (i = 0; i < RT_HASH_SIZE; i++) {
2564 list_for_each_entry(rt_entry, &routing_table[i], list) {
2565 if ((rt_entry->node_id != IPC_ROUTER_NID_LOCAL) &&
2566 (!rt_entry->xprt_info ||
2567 (rt_entry->xprt_info->xprt->link_id ==
2568 xprt_info->xprt->link_id)))
2569 continue;
2570 rc = msm_ipc_router_send_server_list(rt_entry->node_id,
2571 xprt_info);
2572 if (rc < 0) {
2573 up_read(&routing_table_lock_lha3);
2574 up_read(&server_list_lock_lha2);
2575 return rc;
2576 }
2577 }
2578 }
2579 up_read(&routing_table_lock_lha3);
2580 up_read(&server_list_lock_lha2);
2581 return rc;
2582}
2583
2584static int process_resume_tx_msg(union rr_control_msg *msg,
2585 struct rr_packet *pkt)
2586{
2587 struct msm_ipc_router_remote_port *rport_ptr;
2588
2589 rport_ptr = ipc_router_get_rport_ref(msg->cli.node_id,
2590 msg->cli.port_id);
2591 if (!rport_ptr) {
2592 IPC_RTR_ERR("%s: Unable to resume client\n", __func__);
2593 return -ENODEV;
2594 }
2595 mutex_lock(&rport_ptr->rport_lock_lhb2);
2596 rport_ptr->tx_quota_cnt = 0;
2597 post_resume_tx(rport_ptr, pkt, msg);
2598 mutex_unlock(&rport_ptr->rport_lock_lhb2);
2599 kref_put(&rport_ptr->ref, ipc_router_release_rport);
2600 return 0;
2601}
2602
2603static int process_new_server_msg(struct msm_ipc_router_xprt_info *xprt_info,
2604 union rr_control_msg *msg,
2605 struct rr_packet *pkt)
2606{
2607 struct msm_ipc_routing_table_entry *rt_entry;
2608 struct msm_ipc_server *server;
2609 struct msm_ipc_router_remote_port *rport_ptr;
2610
2611 if (msg->srv.instance == 0) {
2612 IPC_RTR_ERR("%s: Server %08x create rejected, version = 0\n",
2613 __func__, msg->srv.service);
2614 return -EINVAL;
2615 }
2616
2617 rt_entry = ipc_router_get_rtentry_ref(msg->srv.node_id);
2618 if (!rt_entry) {
2619 rt_entry = create_routing_table_entry(msg->srv.node_id,
2620 xprt_info);
2621 if (!rt_entry) {
2622 IPC_RTR_ERR("%s: rt_entry allocation failed\n",
2623 __func__);
2624 return -ENOMEM;
2625 }
2626 }
2627 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
2628
2629 /* If the service already exists in the table, create_server returns
2630 * a reference to it.
2631 */
2632 rport_ptr = ipc_router_create_rport(msg->srv.node_id,
2633 msg->srv.port_id, xprt_info);
2634 if (!rport_ptr)
2635 return -ENOMEM;
2636
2637 server = msm_ipc_router_create_server(
2638 msg->srv.service, msg->srv.instance,
2639 msg->srv.node_id, msg->srv.port_id, xprt_info);
2640 if (!server) {
2641 IPC_RTR_ERR("%s: Server %08x:%08x Create failed\n",
2642 __func__, msg->srv.service, msg->srv.instance);
2643 kref_put(&rport_ptr->ref, ipc_router_release_rport);
2644 ipc_router_destroy_rport(rport_ptr);
2645 return -ENOMEM;
2646 }
2647 mutex_lock(&rport_ptr->rport_lock_lhb2);
2648 rport_ptr->server = server;
2649 mutex_unlock(&rport_ptr->rport_lock_lhb2);
2650 rport_ptr->sec_rule = msm_ipc_get_security_rule(
2651 msg->srv.service, msg->srv.instance);
2652 kref_put(&rport_ptr->ref, ipc_router_release_rport);
2653 kref_put(&server->ref, ipc_router_release_server);
2654
2655 /* Relay the new server message to other subsystems that do not belong
2656 * to the cluster from which this message is received. Notify the
2657 * local clients waiting for this service.
2658 */
2659 relay_ctl_msg(xprt_info, msg);
2660 post_control_ports(pkt);
2661 return 0;
2662}
2663
2664static int process_rmv_server_msg(struct msm_ipc_router_xprt_info *xprt_info,
2665 union rr_control_msg *msg,
2666 struct rr_packet *pkt)
2667{
2668 struct msm_ipc_server *server;
2669 struct msm_ipc_router_remote_port *rport_ptr;
2670
2671 server = ipc_router_get_server_ref(msg->srv.service, msg->srv.instance,
2672 msg->srv.node_id, msg->srv.port_id);
2673 rport_ptr = ipc_router_get_rport_ref(msg->srv.node_id,
2674 msg->srv.port_id);
2675 if (rport_ptr) {
2676 mutex_lock(&rport_ptr->rport_lock_lhb2);
2677 if (rport_ptr->server == server)
2678 rport_ptr->server = NULL;
2679 mutex_unlock(&rport_ptr->rport_lock_lhb2);
2680 kref_put(&rport_ptr->ref, ipc_router_release_rport);
2681 }
2682
2683 if (server) {
2684 kref_put(&server->ref, ipc_router_release_server);
2685 ipc_router_destroy_server(server, msg->srv.node_id,
2686 msg->srv.port_id);
2687 /* Relay the new server message to other subsystems that do not
2688 * belong to the cluster from which this message is received.
2689 * Notify the local clients communicating with the service.
2690 */
2691 relay_ctl_msg(xprt_info, msg);
2692 post_control_ports(pkt);
2693 }
2694 return 0;
2695}
2696
2697static int process_rmv_client_msg(struct msm_ipc_router_xprt_info *xprt_info,
2698 union rr_control_msg *msg,
2699 struct rr_packet *pkt)
2700{
2701 struct msm_ipc_router_remote_port *rport_ptr;
2702 struct msm_ipc_server *server;
2703
2704 rport_ptr = ipc_router_get_rport_ref(msg->cli.node_id,
2705 msg->cli.port_id);
2706 if (rport_ptr) {
2707 mutex_lock(&rport_ptr->rport_lock_lhb2);
2708 server = rport_ptr->server;
2709 rport_ptr->server = NULL;
2710 mutex_unlock(&rport_ptr->rport_lock_lhb2);
2711 ipc_router_reset_conn(rport_ptr);
2712 down_write(&server_list_lock_lha2);
2713 if (server)
2714 cleanup_rmt_server(NULL, rport_ptr, server);
2715 up_write(&server_list_lock_lha2);
2716 kref_put(&rport_ptr->ref, ipc_router_release_rport);
2717 ipc_router_destroy_rport(rport_ptr);
2718 }
2719
2720 relay_ctl_msg(xprt_info, msg);
2721 post_control_ports(pkt);
2722 return 0;
2723}
2724
2725static int process_control_msg(struct msm_ipc_router_xprt_info *xprt_info,
2726 struct rr_packet *pkt)
2727{
2728 union rr_control_msg *msg;
2729 int rc = 0;
2730 struct rr_header_v1 *hdr;
2731
2732 if (pkt->length != sizeof(*msg)) {
2733 IPC_RTR_ERR("%s: r2r msg size %d != %zu\n", __func__,
2734 pkt->length, sizeof(*msg));
2735 return -EINVAL;
2736 }
2737
2738 hdr = &pkt->hdr;
2739 msg = msm_ipc_router_skb_to_buf(pkt->pkt_fragment_q, sizeof(*msg));
2740 if (!msg) {
2741 IPC_RTR_ERR("%s: Error extracting control msg\n", __func__);
2742 return -ENOMEM;
2743 }
2744
2745 ipc_router_log_msg(xprt_info->log_ctx, IPC_ROUTER_LOG_EVENT_RX, msg,
2746 hdr, NULL, NULL);
2747
2748 switch (msg->cmd) {
2749 case IPC_ROUTER_CTRL_CMD_HELLO:
2750 rc = process_hello_msg(xprt_info, msg, hdr);
2751 break;
2752 case IPC_ROUTER_CTRL_CMD_RESUME_TX:
2753 rc = process_resume_tx_msg(msg, pkt);
2754 break;
2755 case IPC_ROUTER_CTRL_CMD_NEW_SERVER:
2756 rc = process_new_server_msg(xprt_info, msg, pkt);
2757 break;
2758 case IPC_ROUTER_CTRL_CMD_REMOVE_SERVER:
2759 rc = process_rmv_server_msg(xprt_info, msg, pkt);
2760 break;
2761 case IPC_ROUTER_CTRL_CMD_REMOVE_CLIENT:
2762 rc = process_rmv_client_msg(xprt_info, msg, pkt);
2763 break;
2764 default:
2765 rc = -EINVAL;
2766 }
2767 kfree(msg);
2768 return rc;
2769}
2770
Arun Kumar Neelakantamd5eb2732018-06-19 14:40:01 +05302771static void do_read_data(struct kthread_work *work)
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002772{
2773 struct rr_header_v1 *hdr;
2774 struct rr_packet *pkt = NULL;
2775 struct msm_ipc_port *port_ptr;
2776 struct msm_ipc_router_remote_port *rport_ptr;
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002777
2778 struct msm_ipc_router_xprt_info *xprt_info =
2779 container_of(work,
2780 struct msm_ipc_router_xprt_info,
2781 read_data);
2782
2783 while ((pkt = rr_read(xprt_info)) != NULL) {
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002784
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002785 hdr = &pkt->hdr;
2786
2787 if ((hdr->dst_node_id != IPC_ROUTER_NID_LOCAL) &&
2788 ((hdr->type == IPC_ROUTER_CTRL_CMD_RESUME_TX) ||
2789 (hdr->type == IPC_ROUTER_CTRL_CMD_DATA))) {
2790 IPC_RTR_INFO(xprt_info->log_ctx,
2791 "%s %s Len:0x%x T:0x%x CF:0x%x SRC:<0x%x:0x%x> DST:<0x%x:0x%x>\n",
2792 "FWD", "RX", hdr->size, hdr->type,
2793 hdr->control_flag, hdr->src_node_id,
2794 hdr->src_port_id, hdr->dst_node_id,
2795 hdr->dst_port_id);
Arun Prakash8c8dd7a2020-03-30 22:22:13 +05302796 /**
2797 * update forwarding port information as well in routing
2798 * table which will help to cleanup clients/services
2799 * running in modem when MSM goes down
2800 */
2801 rport_ptr = ipc_router_get_rport_ref(hdr->src_node_id,
2802 hdr->src_port_id);
2803 if (!rport_ptr) {
2804 rport_ptr =
2805 ipc_router_create_rport(hdr->src_node_id,
2806 hdr->src_port_id,
2807 xprt_info);
2808 if (!rport_ptr) {
2809 IPC_RTR_ERR(
2810 "%s: Rmt Prt %08x:%08x create failed\n",
2811 __func__, hdr->src_node_id,
2812 hdr->src_port_id);
2813 }
2814 }
2815 /**
2816 * just to fail safe check is added, if rport
2817 * allocation failed above we still forward the
2818 * packet to remote.
2819 */
2820 if (rport_ptr)
2821 kref_put(&rport_ptr->ref,
2822 ipc_router_release_rport);
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002823 forward_msg(xprt_info, pkt);
2824 goto read_next_pkt1;
2825 }
2826
2827 if (hdr->type != IPC_ROUTER_CTRL_CMD_DATA) {
2828 process_control_msg(xprt_info, pkt);
2829 goto read_next_pkt1;
2830 }
2831
2832 port_ptr = ipc_router_get_port_ref(hdr->dst_port_id);
2833 if (!port_ptr) {
2834 IPC_RTR_ERR("%s: No local port id %08x\n", __func__,
2835 hdr->dst_port_id);
2836 goto read_next_pkt1;
2837 }
2838
2839 rport_ptr = ipc_router_get_rport_ref(hdr->src_node_id,
2840 hdr->src_port_id);
2841 if (!rport_ptr) {
2842 rport_ptr = ipc_router_create_rport(hdr->src_node_id,
2843 hdr->src_port_id,
2844 xprt_info);
2845 if (!rport_ptr) {
2846 IPC_RTR_ERR(
2847 "%s: Rmt Prt %08x:%08x create failed\n",
2848 __func__, hdr->src_node_id,
2849 hdr->src_port_id);
2850 goto read_next_pkt2;
2851 }
2852 }
2853
2854 ipc_router_log_msg(xprt_info->log_ctx, IPC_ROUTER_LOG_EVENT_RX,
2855 pkt, hdr, port_ptr, rport_ptr);
2856 kref_put(&rport_ptr->ref, ipc_router_release_rport);
2857 post_pkt_to_port(port_ptr, pkt, 0);
2858 kref_put(&port_ptr->ref, ipc_router_release_port);
2859 continue;
2860read_next_pkt2:
2861 kref_put(&port_ptr->ref, ipc_router_release_port);
2862read_next_pkt1:
2863 release_pkt(pkt);
2864 }
2865}
2866
2867int msm_ipc_router_register_server(struct msm_ipc_port *port_ptr,
2868 struct msm_ipc_addr *name)
2869{
2870 struct msm_ipc_server *server;
2871 union rr_control_msg ctl;
2872 struct msm_ipc_router_remote_port *rport_ptr;
2873
2874 if (!port_ptr || !name)
2875 return -EINVAL;
2876
Karthikeyan Ramasubramanian63cf3592016-12-15 08:13:20 -07002877 if (port_ptr->type != CLIENT_PORT)
2878 return -EINVAL;
2879
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002880 if (name->addrtype != MSM_IPC_ADDR_NAME)
2881 return -EINVAL;
2882
2883 rport_ptr = ipc_router_create_rport(IPC_ROUTER_NID_LOCAL,
2884 port_ptr->this_port.port_id, NULL);
2885 if (!rport_ptr) {
2886 IPC_RTR_ERR("%s: RPort %08x:%08x creation failed\n", __func__,
2887 IPC_ROUTER_NID_LOCAL, port_ptr->this_port.port_id);
2888 return -ENOMEM;
2889 }
2890
2891 server = msm_ipc_router_create_server(name->addr.port_name.service,
2892 name->addr.port_name.instance,
2893 IPC_ROUTER_NID_LOCAL,
2894 port_ptr->this_port.port_id,
2895 NULL);
2896 if (!server) {
2897 IPC_RTR_ERR("%s: Server %08x:%08x Create failed\n",
2898 __func__, name->addr.port_name.service,
2899 name->addr.port_name.instance);
2900 kref_put(&rport_ptr->ref, ipc_router_release_rport);
2901 ipc_router_destroy_rport(rport_ptr);
2902 return -ENOMEM;
2903 }
2904
2905 memset(&ctl, 0, sizeof(ctl));
2906 ctl.cmd = IPC_ROUTER_CTRL_CMD_NEW_SERVER;
2907 ctl.srv.service = server->name.service;
2908 ctl.srv.instance = server->name.instance;
2909 ctl.srv.node_id = IPC_ROUTER_NID_LOCAL;
2910 ctl.srv.port_id = port_ptr->this_port.port_id;
2911 broadcast_ctl_msg(&ctl);
2912 mutex_lock(&port_ptr->port_lock_lhc3);
2913 port_ptr->type = SERVER_PORT;
2914 port_ptr->mode_info.mode = MULTI_LINK_MODE;
2915 port_ptr->port_name.service = server->name.service;
2916 port_ptr->port_name.instance = server->name.instance;
2917 port_ptr->rport_info = rport_ptr;
2918 mutex_unlock(&port_ptr->port_lock_lhc3);
2919 kref_put(&rport_ptr->ref, ipc_router_release_rport);
2920 kref_put(&server->ref, ipc_router_release_server);
2921 return 0;
2922}
2923
2924int msm_ipc_router_unregister_server(struct msm_ipc_port *port_ptr)
2925{
2926 struct msm_ipc_server *server;
2927 union rr_control_msg ctl;
2928 struct msm_ipc_router_remote_port *rport_ptr;
2929
2930 if (!port_ptr)
2931 return -EINVAL;
2932
2933 if (port_ptr->type != SERVER_PORT) {
2934 IPC_RTR_ERR("%s: Trying to unregister a non-server port\n",
2935 __func__);
2936 return -EINVAL;
2937 }
2938
2939 if (port_ptr->this_port.node_id != IPC_ROUTER_NID_LOCAL) {
2940 IPC_RTR_ERR(
2941 "%s: Trying to unregister a remote server locally\n",
2942 __func__);
2943 return -EINVAL;
2944 }
2945
2946 server = ipc_router_get_server_ref(port_ptr->port_name.service,
2947 port_ptr->port_name.instance,
2948 port_ptr->this_port.node_id,
2949 port_ptr->this_port.port_id);
2950 if (!server) {
2951 IPC_RTR_ERR("%s: Server lookup failed\n", __func__);
2952 return -ENODEV;
2953 }
2954
2955 mutex_lock(&port_ptr->port_lock_lhc3);
2956 port_ptr->type = CLIENT_PORT;
2957 rport_ptr = (struct msm_ipc_router_remote_port *)port_ptr->rport_info;
2958 mutex_unlock(&port_ptr->port_lock_lhc3);
2959 if (rport_ptr)
2960 ipc_router_reset_conn(rport_ptr);
2961 memset(&ctl, 0, sizeof(ctl));
2962 ctl.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_SERVER;
2963 ctl.srv.service = server->name.service;
2964 ctl.srv.instance = server->name.instance;
2965 ctl.srv.node_id = IPC_ROUTER_NID_LOCAL;
2966 ctl.srv.port_id = port_ptr->this_port.port_id;
2967 kref_put(&server->ref, ipc_router_release_server);
2968 ipc_router_destroy_server(server, port_ptr->this_port.node_id,
2969 port_ptr->this_port.port_id);
2970 broadcast_ctl_msg(&ctl);
2971 mutex_lock(&port_ptr->port_lock_lhc3);
2972 port_ptr->type = CLIENT_PORT;
2973 mutex_unlock(&port_ptr->port_lock_lhc3);
2974 return 0;
2975}
2976
2977static int loopback_data(struct msm_ipc_port *src,
2978 u32 port_id,
2979 struct rr_packet *pkt)
2980{
2981 struct msm_ipc_port *port_ptr;
2982 struct sk_buff *temp_skb;
2983 int align_size;
2984
2985 if (!pkt) {
2986 IPC_RTR_ERR("%s: Invalid pkt pointer\n", __func__);
2987 return -EINVAL;
2988 }
2989
2990 temp_skb = skb_peek_tail(pkt->pkt_fragment_q);
Chris Lew42ea9612017-10-04 15:58:16 -07002991 if (!temp_skb) {
2992 IPC_RTR_ERR("%s: Empty skb\n", __func__);
2993 return -EINVAL;
2994 }
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06002995 align_size = ALIGN_SIZE(pkt->length);
2996 skb_put(temp_skb, align_size);
2997 pkt->length += align_size;
2998
2999 port_ptr = ipc_router_get_port_ref(port_id);
3000 if (!port_ptr) {
3001 IPC_RTR_ERR("%s: Local port %d not present\n", __func__,
3002 port_id);
3003 return -ENODEV;
3004 }
3005 post_pkt_to_port(port_ptr, pkt, 1);
3006 update_comm_mode_info(&src->mode_info, NULL);
3007 kref_put(&port_ptr->ref, ipc_router_release_port);
3008
3009 return pkt->hdr.size;
3010}
3011
3012static int ipc_router_tx_wait(struct msm_ipc_port *src,
3013 struct msm_ipc_router_remote_port *rport_ptr,
3014 u32 *set_confirm_rx,
3015 long timeout)
3016{
3017 struct msm_ipc_resume_tx_port *resume_tx_port;
3018 int ret;
3019
3020 if (unlikely(!src || !rport_ptr))
3021 return -EINVAL;
3022
3023 for (;;) {
3024 mutex_lock(&rport_ptr->rport_lock_lhb2);
3025 if (rport_ptr->status == RESET) {
3026 mutex_unlock(&rport_ptr->rport_lock_lhb2);
3027 IPC_RTR_ERR("%s: RPort %08x:%08x is in reset state\n",
3028 __func__, rport_ptr->node_id,
3029 rport_ptr->port_id);
3030 return -ENETRESET;
3031 }
3032
3033 if (rport_ptr->tx_quota_cnt < IPC_ROUTER_HIGH_RX_QUOTA)
3034 break;
3035
3036 if (msm_ipc_router_lookup_resume_tx_port(
3037 rport_ptr, src->this_port.port_id))
3038 goto check_timeo;
3039
3040 resume_tx_port =
3041 kzalloc(sizeof(struct msm_ipc_resume_tx_port),
3042 GFP_KERNEL);
3043 if (!resume_tx_port) {
3044 IPC_RTR_ERR("%s: Resume_Tx port allocation failed\n",
3045 __func__);
3046 mutex_unlock(&rport_ptr->rport_lock_lhb2);
3047 return -ENOMEM;
3048 }
3049 INIT_LIST_HEAD(&resume_tx_port->list);
3050 resume_tx_port->port_id = src->this_port.port_id;
3051 resume_tx_port->node_id = src->this_port.node_id;
3052 list_add_tail(&resume_tx_port->list,
3053 &rport_ptr->resume_tx_port_list);
3054check_timeo:
3055 mutex_unlock(&rport_ptr->rport_lock_lhb2);
3056 if (!timeout) {
3057 return -EAGAIN;
3058 } else if (timeout < 0) {
3059 ret =
3060 wait_event_interruptible(src->port_tx_wait_q,
3061 (rport_ptr->tx_quota_cnt !=
3062 IPC_ROUTER_HIGH_RX_QUOTA ||
3063 rport_ptr->status == RESET));
3064 if (ret)
3065 return ret;
3066 } else {
3067 ret = wait_event_interruptible_timeout(
3068 src->port_tx_wait_q,
3069 (rport_ptr->tx_quota_cnt !=
3070 IPC_ROUTER_HIGH_RX_QUOTA ||
3071 rport_ptr->status == RESET),
3072 msecs_to_jiffies(timeout));
3073 if (ret < 0) {
3074 return ret;
3075 } else if (ret == 0) {
3076 IPC_RTR_ERR("%s: Resume_tx Timeout %08x:%08x\n",
3077 __func__, rport_ptr->node_id,
3078 rport_ptr->port_id);
3079 return -ETIMEDOUT;
3080 }
3081 }
3082 }
3083 rport_ptr->tx_quota_cnt++;
3084 if (rport_ptr->tx_quota_cnt == IPC_ROUTER_LOW_RX_QUOTA)
3085 *set_confirm_rx = 1;
3086 mutex_unlock(&rport_ptr->rport_lock_lhb2);
3087 return 0;
3088}
3089
3090static int
3091msm_ipc_router_write_pkt(struct msm_ipc_port *src,
3092 struct msm_ipc_router_remote_port *rport_ptr,
3093 struct rr_packet *pkt, long timeout)
3094{
3095 struct rr_header_v1 *hdr;
3096 struct msm_ipc_router_xprt_info *xprt_info;
3097 struct msm_ipc_routing_table_entry *rt_entry;
3098 struct sk_buff *temp_skb;
3099 int xprt_option;
3100 int ret;
3101 int align_size;
3102 u32 set_confirm_rx = 0;
3103
3104 if (!rport_ptr || !src || !pkt)
3105 return -EINVAL;
3106
3107 hdr = &pkt->hdr;
3108 hdr->version = IPC_ROUTER_V1;
3109 hdr->type = IPC_ROUTER_CTRL_CMD_DATA;
3110 hdr->src_node_id = src->this_port.node_id;
3111 hdr->src_port_id = src->this_port.port_id;
3112 hdr->size = pkt->length;
3113 hdr->control_flag = 0;
3114 hdr->dst_node_id = rport_ptr->node_id;
3115 hdr->dst_port_id = rport_ptr->port_id;
3116
3117 ret = ipc_router_tx_wait(src, rport_ptr, &set_confirm_rx, timeout);
3118 if (ret < 0)
3119 return ret;
3120 if (set_confirm_rx)
3121 hdr->control_flag |= CONTROL_FLAG_CONFIRM_RX;
3122
3123 if (hdr->dst_node_id == IPC_ROUTER_NID_LOCAL) {
3124 ipc_router_log_msg(local_log_ctx,
3125 IPC_ROUTER_LOG_EVENT_TX, pkt, hdr, src,
3126 rport_ptr);
3127 ret = loopback_data(src, hdr->dst_port_id, pkt);
3128 return ret;
3129 }
3130
3131 rt_entry = ipc_router_get_rtentry_ref(hdr->dst_node_id);
3132 if (!rt_entry) {
3133 IPC_RTR_ERR("%s: Remote node %d not up\n",
3134 __func__, hdr->dst_node_id);
3135 return -ENODEV;
3136 }
3137 down_read(&rt_entry->lock_lha4);
3138 xprt_info = rt_entry->xprt_info;
3139 ret = ipc_router_get_xprt_info_ref(xprt_info);
3140 if (ret < 0) {
3141 IPC_RTR_ERR("%s: Abort invalid xprt\n", __func__);
3142 up_read(&rt_entry->lock_lha4);
3143 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
3144 return ret;
3145 }
3146 ret = prepend_header(pkt, xprt_info);
3147 if (ret < 0) {
3148 IPC_RTR_ERR("%s: Prepend Header failed\n", __func__);
3149 goto out_write_pkt;
3150 }
3151 xprt_option = xprt_info->xprt->get_option(xprt_info->xprt);
3152 if (!(xprt_option & FRAG_PKT_WRITE_ENABLE)) {
3153 ret = defragment_pkt(pkt);
3154 if (ret < 0)
3155 goto out_write_pkt;
3156 }
3157
3158 temp_skb = skb_peek_tail(pkt->pkt_fragment_q);
Chris Lew42ea9612017-10-04 15:58:16 -07003159 if (!temp_skb) {
3160 IPC_RTR_ERR("%s: Abort invalid pkt\n", __func__);
3161 ret = -EINVAL;
3162 goto out_write_pkt;
3163 }
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06003164 align_size = ALIGN_SIZE(pkt->length);
3165 skb_put(temp_skb, align_size);
3166 pkt->length += align_size;
3167 mutex_lock(&xprt_info->tx_lock_lhb2);
3168 ret = xprt_info->xprt->write(pkt, pkt->length, xprt_info->xprt);
3169 mutex_unlock(&xprt_info->tx_lock_lhb2);
3170out_write_pkt:
3171 up_read(&rt_entry->lock_lha4);
3172 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
3173
3174 if (ret < 0) {
3175 IPC_RTR_ERR("%s: Write on XPRT failed\n", __func__);
3176 ipc_router_log_msg(xprt_info->log_ctx,
3177 IPC_ROUTER_LOG_EVENT_TX_ERR, pkt, hdr, src,
3178 rport_ptr);
3179
3180 ipc_router_put_xprt_info_ref(xprt_info);
3181 return ret;
3182 }
3183 update_comm_mode_info(&src->mode_info, xprt_info);
3184 ipc_router_log_msg(xprt_info->log_ctx,
3185 IPC_ROUTER_LOG_EVENT_TX, pkt, hdr, src, rport_ptr);
3186
3187 ipc_router_put_xprt_info_ref(xprt_info);
3188 return hdr->size;
3189}
3190
3191int msm_ipc_router_send_to(struct msm_ipc_port *src,
3192 struct sk_buff_head *data,
3193 struct msm_ipc_addr *dest,
3194 long timeout)
3195{
3196 u32 dst_node_id = 0, dst_port_id = 0;
3197 struct msm_ipc_server *server;
3198 struct msm_ipc_server_port *server_port;
3199 struct msm_ipc_router_remote_port *rport_ptr = NULL;
3200 struct msm_ipc_router_remote_port *src_rport_ptr = NULL;
3201 struct rr_packet *pkt;
3202 int ret;
3203
3204 if (!src || !data || !dest) {
3205 IPC_RTR_ERR("%s: Invalid Parameters\n", __func__);
3206 return -EINVAL;
3207 }
3208
3209 /* Resolve Address*/
3210 if (dest->addrtype == MSM_IPC_ADDR_ID) {
3211 dst_node_id = dest->addr.port_addr.node_id;
3212 dst_port_id = dest->addr.port_addr.port_id;
3213 } else if (dest->addrtype == MSM_IPC_ADDR_NAME) {
3214 server =
3215 ipc_router_get_server_ref(dest->addr.port_name.service,
3216 dest->addr.port_name.instance,
3217 0, 0);
3218 if (!server) {
3219 IPC_RTR_ERR("%s: Destination not reachable\n",
3220 __func__);
3221 return -ENODEV;
3222 }
3223 server_port = list_first_entry(&server->server_port_list,
3224 struct msm_ipc_server_port,
3225 list);
3226 dst_node_id = server_port->server_addr.node_id;
3227 dst_port_id = server_port->server_addr.port_id;
3228 kref_put(&server->ref, ipc_router_release_server);
3229 }
3230
3231 rport_ptr = ipc_router_get_rport_ref(dst_node_id, dst_port_id);
3232 if (!rport_ptr) {
3233 IPC_RTR_ERR("%s: Remote port not found\n", __func__);
3234 return -ENODEV;
3235 }
3236
3237 if (src->check_send_permissions) {
3238 ret = src->check_send_permissions(rport_ptr->sec_rule);
3239 if (ret <= 0) {
3240 kref_put(&rport_ptr->ref, ipc_router_release_rport);
3241 IPC_RTR_ERR("%s: permission failure for %s\n",
3242 __func__, current->comm);
3243 return -EPERM;
3244 }
3245 }
3246
3247 if (dst_node_id == IPC_ROUTER_NID_LOCAL && !src->rport_info) {
3248 src_rport_ptr = ipc_router_create_rport(IPC_ROUTER_NID_LOCAL,
3249 src->this_port.port_id,
3250 NULL);
3251 if (!src_rport_ptr) {
3252 kref_put(&rport_ptr->ref, ipc_router_release_rport);
3253 IPC_RTR_ERR("%s: RPort creation failed\n", __func__);
3254 return -ENOMEM;
3255 }
3256 mutex_lock(&src->port_lock_lhc3);
3257 src->rport_info = src_rport_ptr;
3258 mutex_unlock(&src->port_lock_lhc3);
3259 kref_put(&src_rport_ptr->ref, ipc_router_release_rport);
3260 }
3261
3262 pkt = create_pkt(data);
3263 if (!pkt) {
3264 kref_put(&rport_ptr->ref, ipc_router_release_rport);
3265 IPC_RTR_ERR("%s: Pkt creation failed\n", __func__);
3266 return -ENOMEM;
3267 }
3268
3269 ret = msm_ipc_router_write_pkt(src, rport_ptr, pkt, timeout);
3270 kref_put(&rport_ptr->ref, ipc_router_release_rport);
3271 if (ret < 0)
3272 pkt->pkt_fragment_q = NULL;
3273 release_pkt(pkt);
3274
3275 return ret;
3276}
3277
3278int msm_ipc_router_send_msg(struct msm_ipc_port *src,
3279 struct msm_ipc_addr *dest,
3280 void *data, unsigned int data_len)
3281{
3282 struct sk_buff_head *out_skb_head;
3283 int ret;
3284
3285 out_skb_head = msm_ipc_router_buf_to_skb(data, data_len);
3286 if (!out_skb_head) {
3287 IPC_RTR_ERR("%s: SKB conversion failed\n", __func__);
3288 return -EFAULT;
3289 }
3290
3291 ret = msm_ipc_router_send_to(src, out_skb_head, dest, 0);
3292 if (ret < 0) {
3293 if (ret != -EAGAIN)
3294 IPC_RTR_ERR(
3295 "%s: msm_ipc_router_send_to failed - ret: %d\n",
3296 __func__, ret);
3297 msm_ipc_router_free_skb(out_skb_head);
3298 return ret;
3299 }
3300 return 0;
3301}
3302
3303/**
3304 * msm_ipc_router_send_resume_tx() - Send Resume_Tx message
3305 * @data: Pointer to received data packet that has confirm_rx bit set
3306 *
3307 * @return: On success, number of bytes transferred is returned, else
3308 * standard linux error code is returned.
3309 *
3310 * This function sends the Resume_Tx event to the remote node that
3311 * sent the data with confirm_rx field set. In case of a multi-hop
3312 * scenario also, this function makes sure that the destination node_id
3313 * to which the resume_tx event should reach is right.
3314 */
3315static int msm_ipc_router_send_resume_tx(void *data)
3316{
3317 union rr_control_msg msg;
3318 struct rr_header_v1 *hdr = (struct rr_header_v1 *)data;
3319 struct msm_ipc_routing_table_entry *rt_entry;
3320 int ret;
3321
3322 memset(&msg, 0, sizeof(msg));
3323 msg.cmd = IPC_ROUTER_CTRL_CMD_RESUME_TX;
3324 msg.cli.node_id = hdr->dst_node_id;
3325 msg.cli.port_id = hdr->dst_port_id;
3326 rt_entry = ipc_router_get_rtentry_ref(hdr->src_node_id);
3327 if (!rt_entry) {
3328 IPC_RTR_ERR("%s: %d Node is not present", __func__,
3329 hdr->src_node_id);
3330 return -ENODEV;
3331 }
3332 ret = ipc_router_get_xprt_info_ref(rt_entry->xprt_info);
3333 if (ret < 0) {
3334 IPC_RTR_ERR("%s: Abort invalid xprt\n", __func__);
3335 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
3336 return ret;
3337 }
3338 ret = ipc_router_send_ctl_msg(rt_entry->xprt_info, &msg,
3339 hdr->src_node_id);
3340 ipc_router_put_xprt_info_ref(rt_entry->xprt_info);
3341 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
3342 if (ret < 0)
3343 IPC_RTR_ERR(
3344 "%s: Send Resume_Tx Failed SRC_NODE: %d SRC_PORT: %d DEST_NODE: %d",
3345 __func__, hdr->dst_node_id, hdr->dst_port_id,
3346 hdr->src_node_id);
3347
3348 return ret;
3349}
3350
3351int msm_ipc_router_read(struct msm_ipc_port *port_ptr,
3352 struct rr_packet **read_pkt,
3353 size_t buf_len)
3354{
3355 struct rr_packet *pkt;
3356
3357 if (!port_ptr || !read_pkt)
3358 return -EINVAL;
3359
3360 mutex_lock(&port_ptr->port_rx_q_lock_lhc3);
3361 if (list_empty(&port_ptr->port_rx_q)) {
3362 mutex_unlock(&port_ptr->port_rx_q_lock_lhc3);
3363 return -EAGAIN;
3364 }
3365
3366 pkt = list_first_entry(&port_ptr->port_rx_q, struct rr_packet, list);
3367 if ((buf_len) && (pkt->hdr.size > buf_len)) {
3368 mutex_unlock(&port_ptr->port_rx_q_lock_lhc3);
3369 return -ETOOSMALL;
3370 }
3371 list_del(&pkt->list);
3372 if (list_empty(&port_ptr->port_rx_q))
3373 __pm_relax(port_ptr->port_rx_ws);
3374 *read_pkt = pkt;
3375 mutex_unlock(&port_ptr->port_rx_q_lock_lhc3);
3376 if (pkt->hdr.control_flag & CONTROL_FLAG_CONFIRM_RX)
3377 msm_ipc_router_send_resume_tx(&pkt->hdr);
3378
3379 return pkt->length;
3380}
3381
3382/**
3383 * msm_ipc_router_rx_data_wait() - Wait for new message destined to a local
3384 * port.
3385 * @port_ptr: Pointer to the local port
3386 * @timeout: < 0 timeout indicates infinite wait till a message arrives.
3387 * > 0 timeout indicates the wait time.
3388 * 0 indicates that we do not wait.
3389 * @return: 0 if there are pending messages to read,
3390 * standard Linux error code otherwise.
3391 *
3392 * Checks for the availability of messages that are destined to a local port.
3393 * If no messages are present then waits as per @timeout.
3394 */
3395int msm_ipc_router_rx_data_wait(struct msm_ipc_port *port_ptr, long timeout)
3396{
3397 int ret = 0;
3398
3399 mutex_lock(&port_ptr->port_rx_q_lock_lhc3);
3400 while (list_empty(&port_ptr->port_rx_q)) {
3401 mutex_unlock(&port_ptr->port_rx_q_lock_lhc3);
3402 if (timeout < 0) {
3403 ret = wait_event_interruptible(
3404 port_ptr->port_rx_wait_q,
3405 !list_empty(&port_ptr->port_rx_q));
3406 if (ret)
3407 return ret;
3408 } else if (timeout > 0) {
3409 timeout = wait_event_interruptible_timeout(
3410 port_ptr->port_rx_wait_q,
3411 !list_empty(&port_ptr->port_rx_q),
3412 timeout);
3413 if (timeout < 0)
3414 return -EFAULT;
3415 }
3416 if (timeout == 0)
3417 return -ENOMSG;
3418 mutex_lock(&port_ptr->port_rx_q_lock_lhc3);
3419 }
3420 mutex_unlock(&port_ptr->port_rx_q_lock_lhc3);
3421
3422 return ret;
3423}
3424
3425/**
3426 * msm_ipc_router_recv_from() - Receive messages destined to a local port.
3427 * @port_ptr: Pointer to the local port
3428 * @pkt : Pointer to the router-to-router packet
3429 * @src: Pointer to local port address
3430 * @timeout: < 0 timeout indicates infinite wait till a message arrives.
3431 * > 0 timeout indicates the wait time.
3432 * 0 indicates that we do not wait.
3433 * @return: = Number of bytes read(On successful read operation).
3434 * = -ENOMSG (If there are no pending messages and timeout is 0).
3435 * = -EINVAL (If either of the arguments, port_ptr or data is invalid)
3436 * = -EFAULT (If there are no pending messages when timeout is > 0
3437 * and the wait_event_interruptible_timeout has returned value > 0)
3438 * = -ERESTARTSYS (If there are no pending messages when timeout
3439 * is < 0 and wait_event_interruptible was interrupted by a signal)
3440 *
3441 * This function reads the messages that are destined for a local port. It
3442 * is used by modules that exist with-in the kernel and use IPC Router for
3443 * transport. The function checks if there are any messages that are already
3444 * received. If yes, it reads them, else it waits as per the timeout value.
3445 * On a successful read, the return value of the function indicates the number
3446 * of bytes that are read.
3447 */
3448int msm_ipc_router_recv_from(struct msm_ipc_port *port_ptr,
3449 struct rr_packet **pkt,
3450 struct msm_ipc_addr *src,
3451 long timeout)
3452{
3453 int ret, data_len, align_size;
3454 struct sk_buff *temp_skb;
3455 struct rr_header_v1 *hdr = NULL;
3456
3457 if (!port_ptr || !pkt) {
3458 IPC_RTR_ERR("%s: Invalid pointers being passed\n", __func__);
3459 return -EINVAL;
3460 }
3461
3462 *pkt = NULL;
3463
3464 ret = msm_ipc_router_rx_data_wait(port_ptr, timeout);
3465 if (ret)
3466 return ret;
3467
3468 ret = msm_ipc_router_read(port_ptr, pkt, 0);
3469 if (ret <= 0 || !(*pkt))
3470 return ret;
3471
3472 hdr = &((*pkt)->hdr);
3473 if (src) {
3474 src->addrtype = MSM_IPC_ADDR_ID;
3475 src->addr.port_addr.node_id = hdr->src_node_id;
3476 src->addr.port_addr.port_id = hdr->src_port_id;
3477 }
3478
3479 data_len = hdr->size;
3480 align_size = ALIGN_SIZE(data_len);
3481 if (align_size) {
3482 temp_skb = skb_peek_tail((*pkt)->pkt_fragment_q);
Chris Lew42ea9612017-10-04 15:58:16 -07003483 if (temp_skb)
3484 skb_trim(temp_skb, (temp_skb->len - align_size));
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06003485 }
3486 return data_len;
3487}
3488
3489int msm_ipc_router_read_msg(struct msm_ipc_port *port_ptr,
3490 struct msm_ipc_addr *src,
3491 unsigned char **data,
3492 unsigned int *len)
3493{
3494 struct rr_packet *pkt;
3495 int ret;
3496
3497 ret = msm_ipc_router_recv_from(port_ptr, &pkt, src, 0);
3498 if (ret < 0) {
3499 if (ret != -ENOMSG)
3500 IPC_RTR_ERR(
3501 "%s: msm_ipc_router_recv_from failed - ret: %d\n",
3502 __func__, ret);
3503 return ret;
3504 }
3505
3506 *data = msm_ipc_router_skb_to_buf(pkt->pkt_fragment_q, ret);
3507 if (!(*data)) {
3508 IPC_RTR_ERR("%s: Buf conversion failed\n", __func__);
3509 release_pkt(pkt);
3510 return -ENOMEM;
3511 }
3512
3513 *len = ret;
3514 release_pkt(pkt);
3515 return 0;
3516}
3517
3518/**
3519 * msm_ipc_router_create_port() - Create a IPC Router port/endpoint
3520 * @notify: Callback function to notify any event on the port.
3521 * @event: Event ID to be handled.
3522 * @oob_data: Any out-of-band data associated with the event.
3523 * @oob_data_len: Size of the out-of-band data, if valid.
3524 * @priv: Private data registered during the port creation.
3525 * @priv: Private info to be passed while the notification is generated.
3526 *
3527 * @return: Pointer to the port on success, NULL on error.
3528 */
3529struct msm_ipc_port *msm_ipc_router_create_port(
3530 void (*notify)(unsigned int event, void *oob_data,
3531 size_t oob_data_len, void *priv),
3532 void *priv)
3533{
3534 struct msm_ipc_port *port_ptr;
3535 int ret;
3536
3537 ret = ipc_router_core_init();
3538 if (ret < 0) {
3539 IPC_RTR_ERR("%s: Error %d initializing IPC Router\n",
3540 __func__, ret);
3541 return NULL;
3542 }
3543
3544 port_ptr = msm_ipc_router_create_raw_port(NULL, notify, priv);
3545 if (!port_ptr)
3546 IPC_RTR_ERR("%s: port_ptr alloc failed\n", __func__);
3547
3548 return port_ptr;
3549}
3550
3551int msm_ipc_router_close_port(struct msm_ipc_port *port_ptr)
3552{
3553 union rr_control_msg msg;
3554 struct msm_ipc_server *server;
3555 struct msm_ipc_router_remote_port *rport_ptr;
3556
3557 if (!port_ptr)
3558 return -EINVAL;
3559
3560 if (port_ptr->type == SERVER_PORT || port_ptr->type == CLIENT_PORT) {
3561 down_write(&local_ports_lock_lhc2);
3562 list_del(&port_ptr->list);
3563 up_write(&local_ports_lock_lhc2);
3564
3565 mutex_lock(&port_ptr->port_lock_lhc3);
3566 rport_ptr = (struct msm_ipc_router_remote_port *)
3567 port_ptr->rport_info;
3568 port_ptr->rport_info = NULL;
3569 mutex_unlock(&port_ptr->port_lock_lhc3);
3570 if (rport_ptr) {
3571 ipc_router_reset_conn(rport_ptr);
3572 ipc_router_destroy_rport(rport_ptr);
3573 }
3574
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06003575 /* Server port could have been a client port earlier.
3576 * Send REMOVE_CLIENT message in either case.
3577 */
3578 msm_ipc_router_send_remove_client(&port_ptr->mode_info,
3579 port_ptr->this_port.node_id,
3580 port_ptr->this_port.port_id);
3581 } else if (port_ptr->type == CONTROL_PORT) {
3582 down_write(&control_ports_lock_lha5);
3583 list_del(&port_ptr->list);
3584 up_write(&control_ports_lock_lha5);
3585 } else if (port_ptr->type == IRSC_PORT) {
3586 down_write(&local_ports_lock_lhc2);
3587 list_del(&port_ptr->list);
3588 up_write(&local_ports_lock_lhc2);
3589 signal_irsc_completion();
3590 }
3591
3592 if (port_ptr->type == SERVER_PORT) {
3593 server = ipc_router_get_server_ref(
3594 port_ptr->port_name.service,
3595 port_ptr->port_name.instance,
3596 port_ptr->this_port.node_id,
3597 port_ptr->this_port.port_id);
3598 if (server) {
3599 kref_put(&server->ref, ipc_router_release_server);
3600 ipc_router_destroy_server(server,
3601 port_ptr->this_port.node_id,
3602 port_ptr->this_port.port_id);
3603 }
Arun Prakash72cd4122020-04-25 21:23:11 +05303604 /**
3605 * released server information from hash table, now
3606 * it is safe to broadcast remove server message so that
3607 * next call to lookup server will not succeed until
3608 * server open the port again
3609 */
3610 memset(&msg, 0, sizeof(msg));
3611 msg.cmd = IPC_ROUTER_CTRL_CMD_REMOVE_SERVER;
3612 msg.srv.service = port_ptr->port_name.service;
3613 msg.srv.instance = port_ptr->port_name.instance;
3614 msg.srv.node_id = port_ptr->this_port.node_id;
3615 msg.srv.port_id = port_ptr->this_port.port_id;
3616 broadcast_ctl_msg(&msg);
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06003617 }
3618
3619 mutex_lock(&port_ptr->port_lock_lhc3);
3620 rport_ptr = (struct msm_ipc_router_remote_port *)port_ptr->rport_info;
3621 port_ptr->rport_info = NULL;
3622 mutex_unlock(&port_ptr->port_lock_lhc3);
3623 if (rport_ptr)
3624 ipc_router_destroy_rport(rport_ptr);
3625
3626 kref_put(&port_ptr->ref, ipc_router_release_port);
3627 return 0;
3628}
3629
3630int msm_ipc_router_get_curr_pkt_size(struct msm_ipc_port *port_ptr)
3631{
3632 struct rr_packet *pkt;
3633 int rc = 0;
3634
3635 if (!port_ptr)
3636 return -EINVAL;
3637
3638 mutex_lock(&port_ptr->port_rx_q_lock_lhc3);
3639 if (!list_empty(&port_ptr->port_rx_q)) {
3640 pkt = list_first_entry(&port_ptr->port_rx_q, struct rr_packet,
3641 list);
3642 rc = pkt->hdr.size;
3643 }
3644 mutex_unlock(&port_ptr->port_rx_q_lock_lhc3);
3645
3646 return rc;
3647}
3648
3649int msm_ipc_router_bind_control_port(struct msm_ipc_port *port_ptr)
3650{
3651 if (unlikely(!port_ptr || port_ptr->type != CLIENT_PORT))
3652 return -EINVAL;
3653
3654 down_write(&local_ports_lock_lhc2);
3655 list_del(&port_ptr->list);
3656 up_write(&local_ports_lock_lhc2);
3657 port_ptr->type = CONTROL_PORT;
3658 down_write(&control_ports_lock_lha5);
3659 list_add_tail(&port_ptr->list, &control_ports);
3660 up_write(&control_ports_lock_lha5);
3661
3662 return 0;
3663}
3664
3665int msm_ipc_router_lookup_server_name(struct msm_ipc_port_name *srv_name,
3666 struct msm_ipc_server_info *srv_info,
3667 int num_entries_in_array, u32 lookup_mask)
3668{
3669 struct msm_ipc_server *server;
3670 struct msm_ipc_server_port *server_port;
3671 int key, i = 0; /*num_entries_found*/
3672
3673 if (!srv_name) {
3674 IPC_RTR_ERR("%s: Invalid srv_name\n", __func__);
3675 return -EINVAL;
3676 }
3677
3678 if (num_entries_in_array && !srv_info) {
3679 IPC_RTR_ERR("%s: srv_info NULL\n", __func__);
3680 return -EINVAL;
3681 }
3682
3683 down_read(&server_list_lock_lha2);
3684 key = (srv_name->service & (SRV_HASH_SIZE - 1));
3685 list_for_each_entry(server, &server_list[key], list) {
3686 if ((server->name.service != srv_name->service) ||
3687 ((server->name.instance & lookup_mask) !=
3688 srv_name->instance))
3689 continue;
3690
3691 list_for_each_entry(server_port, &server->server_port_list,
3692 list) {
3693 if (i < num_entries_in_array) {
3694 srv_info[i].node_id =
3695 server_port->server_addr.node_id;
3696 srv_info[i].port_id =
3697 server_port->server_addr.port_id;
3698 srv_info[i].service = server->name.service;
3699 srv_info[i].instance = server->name.instance;
3700 }
3701 i++;
3702 }
3703 }
3704 up_read(&server_list_lock_lha2);
3705
3706 return i;
3707}
3708
3709int msm_ipc_router_close(void)
3710{
3711 struct msm_ipc_router_xprt_info *xprt_info, *tmp_xprt_info;
3712
3713 down_write(&xprt_info_list_lock_lha5);
3714 list_for_each_entry_safe(xprt_info, tmp_xprt_info,
3715 &xprt_info_list, list) {
3716 xprt_info->xprt->close(xprt_info->xprt);
3717 list_del(&xprt_info->list);
3718 kfree(xprt_info);
3719 }
3720 up_write(&xprt_info_list_lock_lha5);
3721 return 0;
3722}
3723
3724/**
3725 * pil_vote_load_worker() - Process vote to load the modem
3726 *
3727 * @work: Work item to process
3728 *
3729 * This function is called to process votes to load the modem that have been
3730 * queued by msm_ipc_load_default_node().
3731 */
3732static void pil_vote_load_worker(struct work_struct *work)
3733{
3734 struct pil_vote_info *vote_info;
3735
3736 vote_info = container_of(work, struct pil_vote_info, load_work);
3737 if (strlen(default_peripheral)) {
3738 vote_info->pil_handle = subsystem_get(default_peripheral);
3739 if (IS_ERR(vote_info->pil_handle)) {
3740 IPC_RTR_ERR("%s: Failed to load %s\n",
3741 __func__, default_peripheral);
3742 vote_info->pil_handle = NULL;
3743 }
3744 } else {
3745 vote_info->pil_handle = NULL;
3746 }
3747}
3748
3749/**
3750 * pil_vote_unload_worker() - Process vote to unload the modem
3751 *
3752 * @work: Work item to process
3753 *
3754 * This function is called to process votes to unload the modem that have been
3755 * queued by msm_ipc_unload_default_node().
3756 */
3757static void pil_vote_unload_worker(struct work_struct *work)
3758{
3759 struct pil_vote_info *vote_info;
3760
3761 vote_info = container_of(work, struct pil_vote_info, unload_work);
3762
3763 if (vote_info->pil_handle) {
3764 subsystem_put(vote_info->pil_handle);
3765 vote_info->pil_handle = NULL;
3766 }
3767 kfree(vote_info);
3768}
3769
3770/**
3771 * msm_ipc_load_default_node() - Queue a vote to load the modem.
3772 *
3773 * @return: PIL vote info structure on success, NULL on failure.
3774 *
3775 * This function places a work item that loads the modem on the
3776 * single-threaded workqueue used for processing PIL votes to load
3777 * or unload the modem.
3778 */
3779void *msm_ipc_load_default_node(void)
3780{
3781 struct pil_vote_info *vote_info;
3782
3783 vote_info = kmalloc(sizeof(*vote_info), GFP_KERNEL);
3784 if (!vote_info)
3785 return vote_info;
3786
3787 INIT_WORK(&vote_info->load_work, pil_vote_load_worker);
3788 queue_work(msm_ipc_router_workqueue, &vote_info->load_work);
3789
3790 return vote_info;
3791}
3792
3793/**
3794 * msm_ipc_unload_default_node() - Queue a vote to unload the modem.
3795 *
3796 * @pil_vote: PIL vote info structure, containing the PIL handle
3797 * and work structure.
3798 *
3799 * This function places a work item that unloads the modem on the
3800 * single-threaded workqueue used for processing PIL votes to load
3801 * or unload the modem.
3802 */
3803void msm_ipc_unload_default_node(void *pil_vote)
3804{
3805 struct pil_vote_info *vote_info;
3806
3807 if (pil_vote) {
3808 vote_info = (struct pil_vote_info *)pil_vote;
3809 INIT_WORK(&vote_info->unload_work, pil_vote_unload_worker);
3810 queue_work(msm_ipc_router_workqueue, &vote_info->unload_work);
3811 }
3812}
3813
3814#if defined(CONFIG_DEBUG_FS)
3815static void dump_routing_table(struct seq_file *s)
3816{
3817 int j;
3818 struct msm_ipc_routing_table_entry *rt_entry;
3819
3820 seq_printf(s, "%-10s|%-20s|%-10s|\n", "Node Id", "XPRT Name",
3821 "Next Hop");
3822 seq_puts(s, "----------------------------------------------\n");
3823 for (j = 0; j < RT_HASH_SIZE; j++) {
3824 down_read(&routing_table_lock_lha3);
3825 list_for_each_entry(rt_entry, &routing_table[j], list) {
3826 down_read(&rt_entry->lock_lha4);
3827 seq_printf(s, "0x%08x|", rt_entry->node_id);
3828 if (rt_entry->node_id == IPC_ROUTER_NID_LOCAL)
3829 seq_printf(s, "%-20s|0x%08x|\n", "Loopback",
3830 rt_entry->node_id);
3831 else
3832 seq_printf(s, "%-20s|0x%08x|\n",
3833 rt_entry->xprt_info->xprt->name,
3834 rt_entry->node_id);
3835 up_read(&rt_entry->lock_lha4);
3836 }
3837 up_read(&routing_table_lock_lha3);
3838 }
3839}
3840
3841static void dump_xprt_info(struct seq_file *s)
3842{
3843 struct msm_ipc_router_xprt_info *xprt_info;
3844
3845 seq_printf(s, "%-20s|%-10s|%-12s|%-15s|\n", "XPRT Name", "Link ID",
3846 "Initialized", "Remote Node Id");
3847 seq_puts(s, "------------------------------------------------------------\n");
3848 down_read(&xprt_info_list_lock_lha5);
3849 list_for_each_entry(xprt_info, &xprt_info_list, list)
3850 seq_printf(s, "%-20s|0x%08x|%-12s|0x%08x|\n",
3851 xprt_info->xprt->name, xprt_info->xprt->link_id,
3852 (xprt_info->initialized ? "Y" : "N"),
3853 xprt_info->remote_node_id);
3854 up_read(&xprt_info_list_lock_lha5);
3855}
3856
3857static void dump_servers(struct seq_file *s)
3858{
3859 int j;
3860 struct msm_ipc_server *server;
3861 struct msm_ipc_server_port *server_port;
3862
3863 seq_printf(s, "%-11s|%-11s|%-11s|%-11s|\n", "Service", "Instance",
3864 "Node_id", "Port_id");
3865 seq_puts(s, "------------------------------------------------------------\n");
3866 down_read(&server_list_lock_lha2);
3867 for (j = 0; j < SRV_HASH_SIZE; j++) {
3868 list_for_each_entry(server, &server_list[j], list) {
3869 list_for_each_entry(server_port,
3870 &server->server_port_list,
3871 list)
3872 seq_printf(s, "0x%08x |0x%08x |0x%08x |0x%08x |\n",
3873 server->name.service,
3874 server->name.instance,
3875 server_port->server_addr.node_id,
3876 server_port->server_addr.port_id);
3877 }
3878 }
3879 up_read(&server_list_lock_lha2);
3880}
3881
3882static void dump_remote_ports(struct seq_file *s)
3883{
3884 int j, k;
3885 struct msm_ipc_router_remote_port *rport_ptr;
3886 struct msm_ipc_routing_table_entry *rt_entry;
3887
3888 seq_printf(s, "%-11s|%-11s|%-10s|\n", "Node_id", "Port_id",
3889 "Quota_cnt");
3890 seq_puts(s, "------------------------------------------------------------\n");
3891 for (j = 0; j < RT_HASH_SIZE; j++) {
3892 down_read(&routing_table_lock_lha3);
3893 list_for_each_entry(rt_entry, &routing_table[j], list) {
3894 down_read(&rt_entry->lock_lha4);
3895 for (k = 0; k < RP_HASH_SIZE; k++) {
3896 list_for_each_entry
3897 (rport_ptr,
3898 &rt_entry->remote_port_list[k],
3899 list)
3900 seq_printf(s, "0x%08x |0x%08x |0x%08x|\n",
3901 rport_ptr->node_id,
3902 rport_ptr->port_id,
3903 rport_ptr->tx_quota_cnt);
3904 }
3905 up_read(&rt_entry->lock_lha4);
3906 }
3907 up_read(&routing_table_lock_lha3);
3908 }
3909}
3910
3911static void dump_control_ports(struct seq_file *s)
3912{
3913 struct msm_ipc_port *port_ptr;
3914
3915 seq_printf(s, "%-11s|%-11s|\n", "Node_id", "Port_id");
3916 seq_puts(s, "------------------------------------------------------------\n");
3917 down_read(&control_ports_lock_lha5);
3918 list_for_each_entry(port_ptr, &control_ports, list)
3919 seq_printf(s, "0x%08x |0x%08x |\n", port_ptr->this_port.node_id,
3920 port_ptr->this_port.port_id);
3921 up_read(&control_ports_lock_lha5);
3922}
3923
3924static void dump_local_ports(struct seq_file *s)
3925{
3926 int j;
3927 struct msm_ipc_port *port_ptr;
3928
Dhoat Harpal3ad5fe32017-06-19 21:26:13 +05303929 seq_printf(s, "%-11s|%-11s|%-32s|%-11s|\n",
3930 "Node_id", "Port_id", "Wakelock", "Last SVCID");
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06003931 seq_puts(s, "------------------------------------------------------------\n");
3932 down_read(&local_ports_lock_lhc2);
3933 for (j = 0; j < LP_HASH_SIZE; j++) {
3934 list_for_each_entry(port_ptr, &local_ports[j], list) {
3935 mutex_lock(&port_ptr->port_lock_lhc3);
Dhoat Harpal3ad5fe32017-06-19 21:26:13 +05303936 seq_printf(s, "0x%08x |0x%08x |%-32s|0x%08x |\n",
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06003937 port_ptr->this_port.node_id,
Dhoat Harpal3ad5fe32017-06-19 21:26:13 +05303938 port_ptr->this_port.port_id,
3939 port_ptr->rx_ws_name,
3940 port_ptr->last_served_svc_id);
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06003941 mutex_unlock(&port_ptr->port_lock_lhc3);
3942 }
3943 }
3944 up_read(&local_ports_lock_lhc2);
3945}
3946
3947static int debugfs_show(struct seq_file *s, void *data)
3948{
3949 void (*show)(struct seq_file *) = s->private;
3950
3951 show(s);
3952 return 0;
3953}
3954
3955static int debug_open(struct inode *inode, struct file *file)
3956{
3957 return single_open(file, debugfs_show, inode->i_private);
3958}
3959
3960static const struct file_operations debug_ops = {
3961 .open = debug_open,
3962 .release = single_release,
3963 .read = seq_read,
3964 .llseek = seq_lseek,
3965};
3966
3967static void debug_create(const char *name, struct dentry *dent,
3968 void (*show)(struct seq_file *))
3969{
3970 debugfs_create_file(name, 0444, dent, show, &debug_ops);
3971}
3972
3973static void debugfs_init(void)
3974{
3975 struct dentry *dent;
3976
3977 dent = debugfs_create_dir("msm_ipc_router", 0);
3978 if (IS_ERR(dent))
3979 return;
3980
3981 debug_create("dump_local_ports", dent, dump_local_ports);
3982 debug_create("dump_remote_ports", dent, dump_remote_ports);
3983 debug_create("dump_control_ports", dent, dump_control_ports);
3984 debug_create("dump_servers", dent, dump_servers);
3985 debug_create("dump_xprt_info", dent, dump_xprt_info);
3986 debug_create("dump_routing_table", dent, dump_routing_table);
3987}
3988
3989#else
3990static void debugfs_init(void) {}
3991#endif
3992
3993/**
3994 * ipc_router_create_log_ctx() - Create and add the log context based on
3995 * transport
3996 * @name: subsystem name
3997 *
3998 * Return: a reference to the log context created
3999 *
4000 * This function creates ipc log context based on transport and adds it to a
4001 * global list. This log context can be reused from the list in case of a
4002 * subsystem restart.
4003 */
4004static void *ipc_router_create_log_ctx(char *name)
4005{
4006 struct ipc_rtr_log_ctx *sub_log_ctx;
4007
4008 sub_log_ctx = kmalloc(sizeof(*sub_log_ctx), GFP_KERNEL);
4009 if (!sub_log_ctx)
4010 return NULL;
4011 sub_log_ctx->log_ctx = ipc_log_context_create(
4012 IPC_RTR_INFO_PAGES, name, 0);
4013 if (!sub_log_ctx->log_ctx) {
4014 IPC_RTR_ERR("%s: Unable to create IPC logging for [%s]",
4015 __func__, name);
4016 kfree(sub_log_ctx);
4017 return NULL;
4018 }
4019 strlcpy(sub_log_ctx->log_ctx_name, name, LOG_CTX_NAME_LEN);
4020 INIT_LIST_HEAD(&sub_log_ctx->list);
4021 list_add_tail(&sub_log_ctx->list, &log_ctx_list);
4022 return sub_log_ctx->log_ctx;
4023}
4024
4025static void ipc_router_log_ctx_init(void)
4026{
4027 mutex_lock(&log_ctx_list_lock_lha0);
4028 local_log_ctx = ipc_router_create_log_ctx("local_IPCRTR");
4029 mutex_unlock(&log_ctx_list_lock_lha0);
4030}
4031
4032/**
4033 * ipc_router_get_log_ctx() - Retrieves the ipc log context based on subsystem
4034 * name.
4035 * @sub_name: subsystem name
4036 *
4037 * Return: a reference to the log context
4038 */
4039static void *ipc_router_get_log_ctx(char *sub_name)
4040{
4041 void *log_ctx = NULL;
4042 struct ipc_rtr_log_ctx *temp_log_ctx;
4043
4044 mutex_lock(&log_ctx_list_lock_lha0);
4045 list_for_each_entry(temp_log_ctx, &log_ctx_list, list)
4046 if (!strcmp(temp_log_ctx->log_ctx_name, sub_name)) {
4047 log_ctx = temp_log_ctx->log_ctx;
4048 mutex_unlock(&log_ctx_list_lock_lha0);
4049 return log_ctx;
4050 }
4051 log_ctx = ipc_router_create_log_ctx(sub_name);
4052 mutex_unlock(&log_ctx_list_lock_lha0);
4053
4054 return log_ctx;
4055}
4056
4057/**
4058 * ipc_router_get_xprt_info_ref() - Get a reference to the xprt_info structure
4059 * @xprt_info: pointer to the xprt_info.
4060 *
4061 * @return: Zero on success, -ENODEV on failure.
4062 *
4063 * This function is used to obtain a reference to the xprt_info structure
4064 * corresponding to the requested @xprt_info pointer.
4065 */
4066static int ipc_router_get_xprt_info_ref(
4067 struct msm_ipc_router_xprt_info *xprt_info)
4068{
4069 int ret = -ENODEV;
4070 struct msm_ipc_router_xprt_info *tmp_xprt_info;
4071
4072 if (!xprt_info)
4073 return 0;
4074
4075 down_read(&xprt_info_list_lock_lha5);
4076 list_for_each_entry(tmp_xprt_info, &xprt_info_list, list) {
4077 if (tmp_xprt_info == xprt_info) {
4078 kref_get(&xprt_info->ref);
4079 ret = 0;
4080 break;
4081 }
4082 }
4083 up_read(&xprt_info_list_lock_lha5);
4084
4085 return ret;
4086}
4087
4088/**
4089 * ipc_router_put_xprt_info_ref() - Put a reference to the xprt_info structure
4090 * @xprt_info: pointer to the xprt_info.
4091 *
4092 * This function is used to put the reference to the xprt_info structure
4093 * corresponding to the requested @xprt_info pointer.
4094 */
4095static void ipc_router_put_xprt_info_ref(
4096 struct msm_ipc_router_xprt_info *xprt_info)
4097{
4098 if (xprt_info)
4099 kref_put(&xprt_info->ref, ipc_router_release_xprt_info_ref);
4100}
4101
4102/**
4103 * ipc_router_release_xprt_info_ref() - release the xprt_info last reference
4104 * @ref: Reference to the xprt_info structure.
4105 *
4106 * This function is called when all references to the xprt_info structure
4107 * are released.
4108 */
4109static void ipc_router_release_xprt_info_ref(struct kref *ref)
4110{
4111 struct msm_ipc_router_xprt_info *xprt_info =
4112 container_of(ref, struct msm_ipc_router_xprt_info, ref);
4113
4114 complete_all(&xprt_info->ref_complete);
4115}
4116
4117static int msm_ipc_router_add_xprt(struct msm_ipc_router_xprt *xprt)
4118{
4119 struct msm_ipc_router_xprt_info *xprt_info;
Arun Kumar Neelakantamd5eb2732018-06-19 14:40:01 +05304120 struct sched_param param = {.sched_priority = 1};
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004121
4122 xprt_info = kmalloc(sizeof(*xprt_info), GFP_KERNEL);
4123 if (!xprt_info)
4124 return -ENOMEM;
4125
4126 xprt_info->xprt = xprt;
4127 xprt_info->initialized = 0;
Arun Kumar Neelakantamf99191d2018-06-11 18:13:43 +05304128 xprt_info->hello_sent = 0;
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004129 xprt_info->remote_node_id = -1;
4130 INIT_LIST_HEAD(&xprt_info->pkt_list);
4131 mutex_init(&xprt_info->rx_lock_lhb2);
4132 mutex_init(&xprt_info->tx_lock_lhb2);
4133 wakeup_source_init(&xprt_info->ws, xprt->name);
4134 xprt_info->need_len = 0;
4135 xprt_info->abort_data_read = 0;
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004136 INIT_LIST_HEAD(&xprt_info->list);
4137 kref_init(&xprt_info->ref);
4138 init_completion(&xprt_info->ref_complete);
Arun Kumar Neelakantam74ff8562017-05-26 17:57:52 +05304139 xprt_info->dynamic_ws = 0;
4140 if (xprt->get_ws_info)
4141 xprt_info->dynamic_ws = xprt->get_ws_info(xprt);
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004142
Arun Kumar Neelakantamd5eb2732018-06-19 14:40:01 +05304143 kthread_init_work(&xprt_info->read_data, do_read_data);
4144 kthread_init_worker(&xprt_info->kworker);
4145 xprt_info->task = kthread_run(kthread_worker_fn,
4146 &xprt_info->kworker,
4147 "%s", xprt->name);
4148 if (IS_ERR(xprt_info->task)) {
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004149 kfree(xprt_info);
4150 return -ENOMEM;
4151 }
Arun Kumar Neelakantamd5eb2732018-06-19 14:40:01 +05304152 if (xprt->get_latency_info && xprt->get_latency_info(xprt))
4153 sched_setscheduler(xprt_info->task, SCHED_FIFO, &param);
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004154
4155 xprt_info->log_ctx = ipc_router_get_log_ctx(xprt->name);
4156
4157 if (!strcmp(xprt->name, "msm_ipc_router_loopback_xprt")) {
4158 xprt_info->remote_node_id = IPC_ROUTER_NID_LOCAL;
4159 xprt_info->initialized = 1;
4160 }
4161
4162 IPC_RTR_INFO(xprt_info->log_ctx, "Adding xprt: [%s]\n", xprt->name);
4163 down_write(&xprt_info_list_lock_lha5);
4164 list_add_tail(&xprt_info->list, &xprt_info_list);
4165 up_write(&xprt_info_list_lock_lha5);
4166
4167 down_write(&routing_table_lock_lha3);
4168 if (!routing_table_inited) {
4169 init_routing_table();
4170 routing_table_inited = 1;
4171 }
4172 up_write(&routing_table_lock_lha3);
4173
4174 xprt->priv = xprt_info;
Arun Kumar Neelakantamf99191d2018-06-11 18:13:43 +05304175 send_hello_msg(xprt_info);
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004176
4177 return 0;
4178}
4179
4180static void msm_ipc_router_remove_xprt(struct msm_ipc_router_xprt *xprt)
4181{
4182 struct msm_ipc_router_xprt_info *xprt_info;
4183 struct rr_packet *temp_pkt, *pkt;
4184
4185 if (xprt && xprt->priv) {
4186 xprt_info = xprt->priv;
4187
4188 IPC_RTR_INFO(xprt_info->log_ctx, "Removing xprt: [%s]\n",
4189 xprt->name);
4190 mutex_lock(&xprt_info->rx_lock_lhb2);
4191 xprt_info->abort_data_read = 1;
4192 mutex_unlock(&xprt_info->rx_lock_lhb2);
Arun Kumar Neelakantamd5eb2732018-06-19 14:40:01 +05304193 kthread_flush_worker(&xprt_info->kworker);
4194 kthread_stop(xprt_info->task);
4195 xprt_info->task = NULL;
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004196 mutex_lock(&xprt_info->rx_lock_lhb2);
4197 list_for_each_entry_safe(pkt, temp_pkt,
4198 &xprt_info->pkt_list, list) {
4199 list_del(&pkt->list);
4200 release_pkt(pkt);
4201 }
4202 mutex_unlock(&xprt_info->rx_lock_lhb2);
4203
4204 down_write(&xprt_info_list_lock_lha5);
4205 list_del(&xprt_info->list);
4206 up_write(&xprt_info_list_lock_lha5);
4207
4208 msm_ipc_cleanup_routing_table(xprt_info);
4209
4210 wakeup_source_trash(&xprt_info->ws);
4211
4212 ipc_router_put_xprt_info_ref(xprt_info);
4213 wait_for_completion(&xprt_info->ref_complete);
4214
4215 xprt->priv = 0;
4216 kfree(xprt_info);
4217 }
4218}
4219
4220struct msm_ipc_router_xprt_work {
4221 struct msm_ipc_router_xprt *xprt;
4222 struct work_struct work;
4223};
4224
4225static void xprt_open_worker(struct work_struct *work)
4226{
4227 struct msm_ipc_router_xprt_work *xprt_work =
4228 container_of(work, struct msm_ipc_router_xprt_work, work);
4229
4230 msm_ipc_router_add_xprt(xprt_work->xprt);
4231 kfree(xprt_work);
4232}
4233
4234static void xprt_close_worker(struct work_struct *work)
4235{
4236 struct msm_ipc_router_xprt_work *xprt_work =
4237 container_of(work, struct msm_ipc_router_xprt_work, work);
4238
4239 msm_ipc_router_remove_xprt(xprt_work->xprt);
4240 xprt_work->xprt->sft_close_done(xprt_work->xprt);
4241 kfree(xprt_work);
4242}
4243
4244void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt,
4245 unsigned int event,
4246 void *data)
4247{
4248 struct msm_ipc_router_xprt_info *xprt_info = xprt->priv;
4249 struct msm_ipc_router_xprt_work *xprt_work;
Arun Kumar Neelakantam029e8462018-04-19 18:10:47 +05304250 struct msm_ipc_router_remote_port *rport_ptr = NULL;
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004251 struct rr_packet *pkt;
4252 int ret;
4253
4254 ret = ipc_router_core_init();
4255 if (ret < 0) {
4256 IPC_RTR_ERR("%s: Error %d initializing IPC Router\n",
4257 __func__, ret);
4258 return;
4259 }
4260
4261 switch (event) {
4262 case IPC_ROUTER_XPRT_EVENT_OPEN:
4263 xprt_work = kmalloc(sizeof(*xprt_work), GFP_ATOMIC);
4264 if (xprt_work) {
4265 xprt_work->xprt = xprt;
4266 INIT_WORK(&xprt_work->work, xprt_open_worker);
4267 queue_work(msm_ipc_router_workqueue, &xprt_work->work);
4268 } else {
4269 IPC_RTR_ERR(
4270 "%s: malloc failure - Couldn't notify OPEN event",
4271 __func__);
4272 }
4273 break;
4274
4275 case IPC_ROUTER_XPRT_EVENT_CLOSE:
4276 xprt_work = kmalloc(sizeof(*xprt_work), GFP_ATOMIC);
4277 if (xprt_work) {
4278 xprt_work->xprt = xprt;
4279 INIT_WORK(&xprt_work->work, xprt_close_worker);
4280 queue_work(msm_ipc_router_workqueue, &xprt_work->work);
4281 } else {
4282 IPC_RTR_ERR(
4283 "%s: malloc failure - Couldn't notify CLOSE event",
4284 __func__);
4285 }
4286 break;
4287 }
4288
4289 if (!data)
4290 return;
4291
4292 while (!xprt_info) {
4293 msleep(100);
4294 xprt_info = xprt->priv;
4295 }
4296
4297 pkt = clone_pkt((struct rr_packet *)data);
4298 if (!pkt)
4299 return;
4300
Arun Kumar Neelakantam029e8462018-04-19 18:10:47 +05304301 if (pkt->length < calc_rx_header_size(xprt_info) ||
4302 pkt->length > MAX_IPC_PKT_SIZE) {
4303 IPC_RTR_ERR("%s: Invalid pkt length %d\n",
4304 __func__, pkt->length);
4305 release_pkt(pkt);
4306 return;
4307 }
4308
4309 ret = extract_header(pkt);
4310 if (ret < 0) {
4311 release_pkt(pkt);
4312 return;
4313 }
4314
Arun Kumar Neelakantam74ff8562017-05-26 17:57:52 +05304315 pkt->ws_need = false;
Arun Kumar Neelakantam029e8462018-04-19 18:10:47 +05304316
4317 if (pkt->hdr.type == IPC_ROUTER_CTRL_CMD_DATA)
4318 rport_ptr = ipc_router_get_rport_ref(pkt->hdr.src_node_id,
4319 pkt->hdr.src_port_id);
4320
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004321 mutex_lock(&xprt_info->rx_lock_lhb2);
4322 list_add_tail(&pkt->list, &xprt_info->pkt_list);
Arun Kumar Neelakantam029e8462018-04-19 18:10:47 +05304323 /* check every pkt is from SENSOR services or not and
4324 * avoid holding both edge and port specific wake-up sources
4325 */
4326 if (!is_sensor_port(rport_ptr)) {
4327 if (!xprt_info->dynamic_ws) {
Arun Kumar Neelakantam74ff8562017-05-26 17:57:52 +05304328 __pm_stay_awake(&xprt_info->ws);
4329 pkt->ws_need = true;
Arun Kumar Neelakantam029e8462018-04-19 18:10:47 +05304330 } else {
4331 if (is_wakeup_source_allowed) {
4332 __pm_stay_awake(&xprt_info->ws);
4333 pkt->ws_need = true;
4334 }
Arun Kumar Neelakantam74ff8562017-05-26 17:57:52 +05304335 }
4336 }
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004337 mutex_unlock(&xprt_info->rx_lock_lhb2);
Deepak Kumar Singh77d41ac2018-09-19 17:15:17 +05304338 if (rport_ptr)
4339 kref_put(&rport_ptr->ref, ipc_router_release_rport);
Arun Kumar Neelakantamd5eb2732018-06-19 14:40:01 +05304340 kthread_queue_work(&xprt_info->kworker, &xprt_info->read_data);
Karthikeyan Ramasubramanian6a116d62016-09-16 16:05:32 -06004341}
4342
4343/**
4344 * parse_devicetree() - parse device tree binding
4345 *
4346 * @node: pointer to device tree node
4347 *
4348 * @return: 0 on success, -ENODEV on failure.
4349 */
4350static int parse_devicetree(struct device_node *node)
4351{
4352 char *key;
4353 const char *peripheral = NULL;
4354
4355 key = "qcom,default-peripheral";
4356 peripheral = of_get_property(node, key, NULL);
4357 if (peripheral)
4358 strlcpy(default_peripheral, peripheral, PIL_SUBSYSTEM_NAME_LEN);
4359
4360 return 0;
4361}
4362
4363/**
4364 * ipc_router_probe() - Probe the IPC Router
4365 *
4366 * @pdev: Platform device corresponding to IPC Router.
4367 *
4368 * @return: 0 on success, standard Linux error codes on error.
4369 *
4370 * This function is called when the underlying device tree driver registers
4371 * a platform device, mapped to IPC Router.
4372 */
4373static int ipc_router_probe(struct platform_device *pdev)
4374{
4375 int ret = 0;
4376
4377 if (pdev && pdev->dev.of_node) {
4378 ret = parse_devicetree(pdev->dev.of_node);
4379 if (ret)
4380 IPC_RTR_ERR("%s: Failed to parse device tree\n",
4381 __func__);
4382 }
4383 return ret;
4384}
4385
4386static const struct of_device_id ipc_router_match_table[] = {
4387 { .compatible = "qcom,ipc_router" },
4388 {},
4389};
4390
4391static struct platform_driver ipc_router_driver = {
4392 .probe = ipc_router_probe,
4393 .driver = {
4394 .name = MODULE_NAME,
4395 .owner = THIS_MODULE,
4396 .of_match_table = ipc_router_match_table,
4397 },
4398};
4399
4400/**
4401 * ipc_router_core_init() - Initialize all IPC Router core data structures
4402 *
4403 * Return: 0 on Success or Standard error code otherwise.
4404 *
4405 * This function only initializes all the core data structures to the IPC Router
4406 * module. The remaining initialization is done inside msm_ipc_router_init().
4407 */
4408static int ipc_router_core_init(void)
4409{
4410 int i;
4411 int ret;
4412 struct msm_ipc_routing_table_entry *rt_entry;
4413
4414 mutex_lock(&ipc_router_init_lock);
4415 if (likely(is_ipc_router_inited)) {
4416 mutex_unlock(&ipc_router_init_lock);
4417 return 0;
4418 }
4419
4420 debugfs_init();
4421
4422 for (i = 0; i < SRV_HASH_SIZE; i++)
4423 INIT_LIST_HEAD(&server_list[i]);
4424
4425 for (i = 0; i < LP_HASH_SIZE; i++)
4426 INIT_LIST_HEAD(&local_ports[i]);
4427
4428 down_write(&routing_table_lock_lha3);
4429 if (!routing_table_inited) {
4430 init_routing_table();
4431 routing_table_inited = 1;
4432 }
4433 up_write(&routing_table_lock_lha3);
4434 rt_entry = create_routing_table_entry(IPC_ROUTER_NID_LOCAL, NULL);
4435 kref_put(&rt_entry->ref, ipc_router_release_rtentry);
4436
4437 msm_ipc_router_workqueue =
4438 create_singlethread_workqueue("msm_ipc_router");
4439 if (!msm_ipc_router_workqueue) {
4440 mutex_unlock(&ipc_router_init_lock);
4441 return -ENOMEM;
4442 }
4443
4444 ret = msm_ipc_router_security_init();
4445 if (ret < 0)
4446 IPC_RTR_ERR("%s: Security Init failed\n", __func__);
4447 else
4448 is_ipc_router_inited = true;
4449 mutex_unlock(&ipc_router_init_lock);
4450
4451 return ret;
4452}
4453
4454static int msm_ipc_router_init(void)
4455{
4456 int ret;
4457
4458 ret = ipc_router_core_init();
4459 if (ret < 0)
4460 return ret;
4461
4462 ret = platform_driver_register(&ipc_router_driver);
4463 if (ret)
4464 IPC_RTR_ERR(
4465 "%s: ipc_router_driver register failed %d\n", __func__, ret);
4466
4467 ret = msm_ipc_router_init_sockets();
4468 if (ret < 0)
4469 IPC_RTR_ERR("%s: Init sockets failed\n", __func__);
4470
4471 ipc_router_log_ctx_init();
4472 return ret;
4473}
4474
4475module_init(msm_ipc_router_init);
4476MODULE_DESCRIPTION("MSM IPC Router");
4477MODULE_LICENSE("GPL v2");