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