Loading net/ipc_router/ipc_router_core.c +77 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,8 @@ struct msm_ipc_router_xprt_info { struct work_struct read_data; struct workqueue_struct *workqueue; void *log_ctx; struct kref ref; struct completion ref_complete; }; #define RT_HASH_SIZE 4 Loading Loading @@ -194,6 +196,9 @@ static void *ipc_router_get_log_ctx(char *sub_name); static int process_resume_tx_msg(union rr_control_msg *msg, struct rr_packet *pkt); static void ipc_router_reset_conn(struct msm_ipc_router_remote_port *rport_ptr); static int ipc_router_get_xprt_info_ref( struct msm_ipc_router_xprt_info *xprt_info); static void ipc_router_release_xprt_info_ref(struct kref *ref); struct pil_vote_info { void *pil_handle; Loading Loading @@ -2037,6 +2042,11 @@ static int forward_msg(struct msm_ipc_router_xprt_info *xprt_info, down_read(&rt_entry->lock_lha4); fwd_xprt_info = rt_entry->xprt_info; ret = ipc_router_get_xprt_info_ref(fwd_xprt_info); if (ret < 0) { IPC_RTR_ERR("%s: Abort invalid xprt\n", __func__); goto fm_error_xprt; } ret = prepend_header(pkt, fwd_xprt_info); if (ret < 0) { IPC_RTR_ERR("%s: Prepend Header failed\n", __func__); Loading Loading @@ -2071,6 +2081,8 @@ static int forward_msg(struct msm_ipc_router_xprt_info *xprt_info, fm_error3: mutex_unlock(&fwd_xprt_info->tx_lock_lhb2); fm_error2: kref_put(&fwd_xprt_info->ref, ipc_router_release_xprt_info_ref); fm_error_xprt: up_read(&rt_entry->lock_lha4); fm_error1: if (rt_entry) Loading Loading @@ -3037,6 +3049,13 @@ static int msm_ipc_router_write_pkt(struct msm_ipc_port *src, } down_read(&rt_entry->lock_lha4); xprt_info = rt_entry->xprt_info; ret = ipc_router_get_xprt_info_ref(xprt_info); if (ret < 0) { IPC_RTR_ERR("%s: Abort invalid xprt\n", __func__); up_read(&rt_entry->lock_lha4); kref_put(&rt_entry->ref, ipc_router_release_rtentry); return ret; } ret = prepend_header(pkt, xprt_info); if (ret < 0) { IPC_RTR_ERR("%s: Prepend Header failed\n", __func__); Loading Loading @@ -3065,6 +3084,7 @@ out_write_pkt: ipc_router_log_msg(xprt_info->log_ctx, IPC_ROUTER_LOG_EVENT_TX_ERR, pkt, hdr, src, rport_ptr); kref_put(&xprt_info->ref, ipc_router_release_xprt_info_ref); return ret; } update_comm_mode_info(&src->mode_info, xprt_info); Loading @@ -3082,6 +3102,7 @@ out_write_pkt: (hdr->size & 0xffff)); } kref_put(&xprt_info->ref, ipc_router_release_xprt_info_ref); return hdr->size; } Loading Loading @@ -3225,9 +3246,16 @@ static int msm_ipc_router_send_resume_tx(void *data) __func__, hdr->src_node_id); return -ENODEV; } ret = ipc_router_get_xprt_info_ref(rt_entry->xprt_info); if (ret < 0) { IPC_RTR_ERR("%s: Abort invalid xprt\n", __func__); kref_put(&rt_entry->ref, ipc_router_release_rtentry); return ret; } ret = ipc_router_send_ctl_msg(rt_entry->xprt_info, &msg, hdr->src_node_id); kref_put(&rt_entry->ref, ipc_router_release_rtentry); kref_put(&rt_entry->xprt_info->ref, ipc_router_release_xprt_info_ref); if (ret < 0) IPC_RTR_ERR( "%s: Send Resume_Tx Failed SRC_NODE: %d SRC_PORT: %d DEST_NODE: %d", Loading Loading @@ -3939,6 +3967,49 @@ static void *ipc_router_get_log_ctx(char *sub_name) return log_ctx; } /** * ipc_router_get_xprt_info_ref() - Get a reference to the xprt_info structure * @xprt_info: pointer to the xprt_info. * * @return: Zero on success, -ENODEV on failure. * * This function is used to obtain a reference to the xprt_info structure * corresponding to the requested @xprt_info pointer. */ static int ipc_router_get_xprt_info_ref( struct msm_ipc_router_xprt_info *xprt_info) { int ret = -ENODEV; struct msm_ipc_router_xprt_info *tmp_xprt_info; down_read(&xprt_info_list_lock_lha5); list_for_each_entry(tmp_xprt_info, &xprt_info_list, list) { if (tmp_xprt_info == xprt_info) { kref_get(&xprt_info->ref); ret = 0; break; } } up_read(&xprt_info_list_lock_lha5); return ret; } /** * ipc_router_release_xprt_info_ref() - release the xprt_info last reference * @ref: Reference to the xprt_info structure. * * This function is called when all references to the xprt_info structure * are released. */ static void ipc_router_release_xprt_info_ref(struct kref *ref) { struct msm_ipc_router_xprt_info *xprt_info = container_of(ref, struct msm_ipc_router_xprt_info, ref); complete_all(&xprt_info->ref_complete); } static int msm_ipc_router_add_xprt(struct msm_ipc_router_xprt *xprt) { struct msm_ipc_router_xprt_info *xprt_info; Loading @@ -3959,6 +4030,8 @@ static int msm_ipc_router_add_xprt(struct msm_ipc_router_xprt *xprt) xprt_info->abort_data_read = 0; INIT_WORK(&xprt_info->read_data, do_read_data); INIT_LIST_HEAD(&xprt_info->list); kref_init(&xprt_info->ref); init_completion(&xprt_info->ref_complete); xprt_info->workqueue = create_singlethread_workqueue(xprt->name); if (!xprt_info->workqueue) { Loading Loading @@ -4022,6 +4095,10 @@ static void msm_ipc_router_remove_xprt(struct msm_ipc_router_xprt *xprt) wakeup_source_trash(&xprt_info->ws); kref_put(&xprt_info->ref, ipc_router_release_xprt_info_ref); wait_for_completion(&xprt_info->ref_complete); xprt->priv = 0; kfree(xprt_info); } Loading Loading
net/ipc_router/ipc_router_core.c +77 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,8 @@ struct msm_ipc_router_xprt_info { struct work_struct read_data; struct workqueue_struct *workqueue; void *log_ctx; struct kref ref; struct completion ref_complete; }; #define RT_HASH_SIZE 4 Loading Loading @@ -194,6 +196,9 @@ static void *ipc_router_get_log_ctx(char *sub_name); static int process_resume_tx_msg(union rr_control_msg *msg, struct rr_packet *pkt); static void ipc_router_reset_conn(struct msm_ipc_router_remote_port *rport_ptr); static int ipc_router_get_xprt_info_ref( struct msm_ipc_router_xprt_info *xprt_info); static void ipc_router_release_xprt_info_ref(struct kref *ref); struct pil_vote_info { void *pil_handle; Loading Loading @@ -2037,6 +2042,11 @@ static int forward_msg(struct msm_ipc_router_xprt_info *xprt_info, down_read(&rt_entry->lock_lha4); fwd_xprt_info = rt_entry->xprt_info; ret = ipc_router_get_xprt_info_ref(fwd_xprt_info); if (ret < 0) { IPC_RTR_ERR("%s: Abort invalid xprt\n", __func__); goto fm_error_xprt; } ret = prepend_header(pkt, fwd_xprt_info); if (ret < 0) { IPC_RTR_ERR("%s: Prepend Header failed\n", __func__); Loading Loading @@ -2071,6 +2081,8 @@ static int forward_msg(struct msm_ipc_router_xprt_info *xprt_info, fm_error3: mutex_unlock(&fwd_xprt_info->tx_lock_lhb2); fm_error2: kref_put(&fwd_xprt_info->ref, ipc_router_release_xprt_info_ref); fm_error_xprt: up_read(&rt_entry->lock_lha4); fm_error1: if (rt_entry) Loading Loading @@ -3037,6 +3049,13 @@ static int msm_ipc_router_write_pkt(struct msm_ipc_port *src, } down_read(&rt_entry->lock_lha4); xprt_info = rt_entry->xprt_info; ret = ipc_router_get_xprt_info_ref(xprt_info); if (ret < 0) { IPC_RTR_ERR("%s: Abort invalid xprt\n", __func__); up_read(&rt_entry->lock_lha4); kref_put(&rt_entry->ref, ipc_router_release_rtentry); return ret; } ret = prepend_header(pkt, xprt_info); if (ret < 0) { IPC_RTR_ERR("%s: Prepend Header failed\n", __func__); Loading Loading @@ -3065,6 +3084,7 @@ out_write_pkt: ipc_router_log_msg(xprt_info->log_ctx, IPC_ROUTER_LOG_EVENT_TX_ERR, pkt, hdr, src, rport_ptr); kref_put(&xprt_info->ref, ipc_router_release_xprt_info_ref); return ret; } update_comm_mode_info(&src->mode_info, xprt_info); Loading @@ -3082,6 +3102,7 @@ out_write_pkt: (hdr->size & 0xffff)); } kref_put(&xprt_info->ref, ipc_router_release_xprt_info_ref); return hdr->size; } Loading Loading @@ -3225,9 +3246,16 @@ static int msm_ipc_router_send_resume_tx(void *data) __func__, hdr->src_node_id); return -ENODEV; } ret = ipc_router_get_xprt_info_ref(rt_entry->xprt_info); if (ret < 0) { IPC_RTR_ERR("%s: Abort invalid xprt\n", __func__); kref_put(&rt_entry->ref, ipc_router_release_rtentry); return ret; } ret = ipc_router_send_ctl_msg(rt_entry->xprt_info, &msg, hdr->src_node_id); kref_put(&rt_entry->ref, ipc_router_release_rtentry); kref_put(&rt_entry->xprt_info->ref, ipc_router_release_xprt_info_ref); if (ret < 0) IPC_RTR_ERR( "%s: Send Resume_Tx Failed SRC_NODE: %d SRC_PORT: %d DEST_NODE: %d", Loading Loading @@ -3939,6 +3967,49 @@ static void *ipc_router_get_log_ctx(char *sub_name) return log_ctx; } /** * ipc_router_get_xprt_info_ref() - Get a reference to the xprt_info structure * @xprt_info: pointer to the xprt_info. * * @return: Zero on success, -ENODEV on failure. * * This function is used to obtain a reference to the xprt_info structure * corresponding to the requested @xprt_info pointer. */ static int ipc_router_get_xprt_info_ref( struct msm_ipc_router_xprt_info *xprt_info) { int ret = -ENODEV; struct msm_ipc_router_xprt_info *tmp_xprt_info; down_read(&xprt_info_list_lock_lha5); list_for_each_entry(tmp_xprt_info, &xprt_info_list, list) { if (tmp_xprt_info == xprt_info) { kref_get(&xprt_info->ref); ret = 0; break; } } up_read(&xprt_info_list_lock_lha5); return ret; } /** * ipc_router_release_xprt_info_ref() - release the xprt_info last reference * @ref: Reference to the xprt_info structure. * * This function is called when all references to the xprt_info structure * are released. */ static void ipc_router_release_xprt_info_ref(struct kref *ref) { struct msm_ipc_router_xprt_info *xprt_info = container_of(ref, struct msm_ipc_router_xprt_info, ref); complete_all(&xprt_info->ref_complete); } static int msm_ipc_router_add_xprt(struct msm_ipc_router_xprt *xprt) { struct msm_ipc_router_xprt_info *xprt_info; Loading @@ -3959,6 +4030,8 @@ static int msm_ipc_router_add_xprt(struct msm_ipc_router_xprt *xprt) xprt_info->abort_data_read = 0; INIT_WORK(&xprt_info->read_data, do_read_data); INIT_LIST_HEAD(&xprt_info->list); kref_init(&xprt_info->ref); init_completion(&xprt_info->ref_complete); xprt_info->workqueue = create_singlethread_workqueue(xprt->name); if (!xprt_info->workqueue) { Loading Loading @@ -4022,6 +4095,10 @@ static void msm_ipc_router_remove_xprt(struct msm_ipc_router_xprt *xprt) wakeup_source_trash(&xprt_info->ws); kref_put(&xprt_info->ref, ipc_router_release_xprt_info_ref); wait_for_completion(&xprt_info->ref_complete); xprt->priv = 0; kfree(xprt_info); } Loading