Loading drivers/soc/qcom/ipc_router_smd_xprt.c +95 −9 Original line number Diff line number Diff line Loading @@ -129,6 +129,10 @@ static struct delayed_work ipc_router_smd_xprt_probe_work; static DEFINE_MUTEX(smd_remote_xprt_list_lock_lha1); static LIST_HEAD(smd_remote_xprt_list); static void pil_vote_load_worker(struct work_struct *work); static void pil_vote_unload_worker(struct work_struct *work); static struct workqueue_struct *pil_vote_wq; static int msm_ipc_router_smd_get_xprt_version( struct msm_ipc_router_xprt *xprt) { Loading Loading @@ -545,28 +549,104 @@ static int msm_ipc_router_smd_remote_probe(struct platform_device *pdev) return 0; } void *msm_ipc_load_default_node(void) struct pil_vote_info { void *pil_handle; struct work_struct load_work; struct work_struct unload_work; }; /** * pil_vote_load_worker() - Process vote to load the modem * * @work: Work item to process * * This function is called to process votes to load the modem that have been * queued by msm_ipc_load_default_node(). */ static void pil_vote_load_worker(struct work_struct *work) { void *pil = NULL; const char *peripheral; struct pil_vote_info *vote_info; vote_info = container_of(work, struct pil_vote_info, load_work); peripheral = smd_edge_to_pil_str(SMD_APPS_MODEM); if (!IS_ERR_OR_NULL(peripheral) && !strcmp(peripheral, "modem")) { pil = subsystem_get(peripheral); if (IS_ERR(pil)) { vote_info->pil_handle = subsystem_get(peripheral); if (IS_ERR(vote_info->pil_handle)) { pr_err("%s: Failed to load %s\n", __func__, peripheral); pil = NULL; vote_info->pil_handle = NULL; } } return pil; } /** * pil_vote_unload_worker() - Process vote to unload the modem * * @work: Work item to process * * This function is called to process votes to unload the modem that have been * queued by msm_ipc_unload_default_node(). */ static void pil_vote_unload_worker(struct work_struct *work) { struct pil_vote_info *vote_info; vote_info = container_of(work, struct pil_vote_info, unload_work); if (vote_info->pil_handle) { subsystem_put(vote_info->pil_handle); vote_info->pil_handle = NULL; } kfree(vote_info); } /** * msm_ipc_load_default_node() - Queue a vote to load the modem. * * @return: PIL vote info structure on success, NULL on failure. * * This function places a work item that loads the modem on the * single-threaded workqueue used for processing PIL votes to load * or unload the modem. */ void *msm_ipc_load_default_node(void) { struct pil_vote_info *vote_info; vote_info = kmalloc(sizeof(struct pil_vote_info), GFP_KERNEL); if (vote_info == NULL) { pr_err("%s: mem alloc for pil_vote_info failed\n", __func__); return NULL; } INIT_WORK(&vote_info->load_work, pil_vote_load_worker); queue_work(pil_vote_wq, &vote_info->load_work); return vote_info; } EXPORT_SYMBOL(msm_ipc_load_default_node); void msm_ipc_unload_default_node(void *pil) /** * msm_ipc_unload_default_node() - Queue a vote to unload the modem. * * @pil_vote: PIL vote info structure, containing the PIL handle * and work structure. * * This function places a work item that unloads the modem on the * single-threaded workqueue used for processing PIL votes to load * or unload the modem. */ void msm_ipc_unload_default_node(void *pil_vote) { if (pil) subsystem_put(pil); struct pil_vote_info *vote_info; if (pil_vote) { vote_info = (struct pil_vote_info *) pil_vote; INIT_WORK(&vote_info->unload_work, pil_vote_unload_worker); queue_work(pil_vote_wq, &vote_info->unload_work); } } EXPORT_SYMBOL(msm_ipc_unload_default_node); Loading Loading @@ -823,6 +903,12 @@ static int __init msm_ipc_router_smd_xprt_init(void) return rc; } pil_vote_wq = create_singlethread_workqueue("pil_vote_wq"); if (IS_ERR_OR_NULL(pil_vote_wq)) { pr_err("%s: create_singlethread_workqueue failed\n", __func__); return -EFAULT; } INIT_DELAYED_WORK(&ipc_router_smd_xprt_probe_work, ipc_router_smd_xprt_probe_worker); schedule_delayed_work(&ipc_router_smd_xprt_probe_work, Loading net/ipc_router/ipc_router_private.h +1 −1 Original line number Diff line number Diff line Loading @@ -67,7 +67,7 @@ enum { struct msm_ipc_sock { struct sock sk; struct msm_ipc_port *port; void *default_pil; void *default_node_vote_info; }; /** Loading net/ipc_router/ipc_router_socket.c +8 −9 Original line number Diff line number Diff line Loading @@ -303,7 +303,6 @@ int msm_ipc_router_bind(struct socket *sock, struct sockaddr *uaddr, struct sock *sk = sock->sk; struct msm_ipc_port *port_ptr; int ret; void *pil; if (!sk) return -EINVAL; Loading Loading @@ -333,8 +332,9 @@ int msm_ipc_router_bind(struct socket *sock, struct sockaddr *uaddr, if (!port_ptr) return -ENODEV; pil = msm_ipc_load_default_node(); msm_ipc_sk(sk)->default_pil = pil; if (!msm_ipc_sk(sk)->default_node_vote_info) msm_ipc_sk(sk)->default_node_vote_info = msm_ipc_load_default_node(); lock_sock(sk); ret = msm_ipc_router_register_server(port_ptr, &addr->address); Loading Loading @@ -445,7 +445,6 @@ static int msm_ipc_router_ioctl(struct socket *sock, unsigned int n; size_t srv_info_sz = 0; int ret; void *pil; if (!sk) return -EINVAL; Loading Loading @@ -473,8 +472,10 @@ static int msm_ipc_router_ioctl(struct socket *sock, break; case IPC_ROUTER_IOCTL_LOOKUP_SERVER: pil = msm_ipc_load_default_node(); msm_ipc_sk(sk)->default_pil = pil; if (!msm_ipc_sk(sk)->default_node_vote_info) msm_ipc_sk(sk)->default_node_vote_info = msm_ipc_load_default_node(); ret = copy_from_user(&server_arg, (void *)arg, sizeof(server_arg)); if (ret) { Loading Loading @@ -568,13 +569,11 @@ static int msm_ipc_router_close(struct socket *sock) { struct sock *sk = sock->sk; struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk); void *pil = msm_ipc_sk(sk)->default_pil; int ret; lock_sock(sk); ret = msm_ipc_router_close_port(port_ptr); if (pil) msm_ipc_unload_default_node(pil); msm_ipc_unload_default_node(msm_ipc_sk(sk)->default_node_vote_info); release_sock(sk); sock_put(sk); sock->sk = NULL; Loading Loading
drivers/soc/qcom/ipc_router_smd_xprt.c +95 −9 Original line number Diff line number Diff line Loading @@ -129,6 +129,10 @@ static struct delayed_work ipc_router_smd_xprt_probe_work; static DEFINE_MUTEX(smd_remote_xprt_list_lock_lha1); static LIST_HEAD(smd_remote_xprt_list); static void pil_vote_load_worker(struct work_struct *work); static void pil_vote_unload_worker(struct work_struct *work); static struct workqueue_struct *pil_vote_wq; static int msm_ipc_router_smd_get_xprt_version( struct msm_ipc_router_xprt *xprt) { Loading Loading @@ -545,28 +549,104 @@ static int msm_ipc_router_smd_remote_probe(struct platform_device *pdev) return 0; } void *msm_ipc_load_default_node(void) struct pil_vote_info { void *pil_handle; struct work_struct load_work; struct work_struct unload_work; }; /** * pil_vote_load_worker() - Process vote to load the modem * * @work: Work item to process * * This function is called to process votes to load the modem that have been * queued by msm_ipc_load_default_node(). */ static void pil_vote_load_worker(struct work_struct *work) { void *pil = NULL; const char *peripheral; struct pil_vote_info *vote_info; vote_info = container_of(work, struct pil_vote_info, load_work); peripheral = smd_edge_to_pil_str(SMD_APPS_MODEM); if (!IS_ERR_OR_NULL(peripheral) && !strcmp(peripheral, "modem")) { pil = subsystem_get(peripheral); if (IS_ERR(pil)) { vote_info->pil_handle = subsystem_get(peripheral); if (IS_ERR(vote_info->pil_handle)) { pr_err("%s: Failed to load %s\n", __func__, peripheral); pil = NULL; vote_info->pil_handle = NULL; } } return pil; } /** * pil_vote_unload_worker() - Process vote to unload the modem * * @work: Work item to process * * This function is called to process votes to unload the modem that have been * queued by msm_ipc_unload_default_node(). */ static void pil_vote_unload_worker(struct work_struct *work) { struct pil_vote_info *vote_info; vote_info = container_of(work, struct pil_vote_info, unload_work); if (vote_info->pil_handle) { subsystem_put(vote_info->pil_handle); vote_info->pil_handle = NULL; } kfree(vote_info); } /** * msm_ipc_load_default_node() - Queue a vote to load the modem. * * @return: PIL vote info structure on success, NULL on failure. * * This function places a work item that loads the modem on the * single-threaded workqueue used for processing PIL votes to load * or unload the modem. */ void *msm_ipc_load_default_node(void) { struct pil_vote_info *vote_info; vote_info = kmalloc(sizeof(struct pil_vote_info), GFP_KERNEL); if (vote_info == NULL) { pr_err("%s: mem alloc for pil_vote_info failed\n", __func__); return NULL; } INIT_WORK(&vote_info->load_work, pil_vote_load_worker); queue_work(pil_vote_wq, &vote_info->load_work); return vote_info; } EXPORT_SYMBOL(msm_ipc_load_default_node); void msm_ipc_unload_default_node(void *pil) /** * msm_ipc_unload_default_node() - Queue a vote to unload the modem. * * @pil_vote: PIL vote info structure, containing the PIL handle * and work structure. * * This function places a work item that unloads the modem on the * single-threaded workqueue used for processing PIL votes to load * or unload the modem. */ void msm_ipc_unload_default_node(void *pil_vote) { if (pil) subsystem_put(pil); struct pil_vote_info *vote_info; if (pil_vote) { vote_info = (struct pil_vote_info *) pil_vote; INIT_WORK(&vote_info->unload_work, pil_vote_unload_worker); queue_work(pil_vote_wq, &vote_info->unload_work); } } EXPORT_SYMBOL(msm_ipc_unload_default_node); Loading Loading @@ -823,6 +903,12 @@ static int __init msm_ipc_router_smd_xprt_init(void) return rc; } pil_vote_wq = create_singlethread_workqueue("pil_vote_wq"); if (IS_ERR_OR_NULL(pil_vote_wq)) { pr_err("%s: create_singlethread_workqueue failed\n", __func__); return -EFAULT; } INIT_DELAYED_WORK(&ipc_router_smd_xprt_probe_work, ipc_router_smd_xprt_probe_worker); schedule_delayed_work(&ipc_router_smd_xprt_probe_work, Loading
net/ipc_router/ipc_router_private.h +1 −1 Original line number Diff line number Diff line Loading @@ -67,7 +67,7 @@ enum { struct msm_ipc_sock { struct sock sk; struct msm_ipc_port *port; void *default_pil; void *default_node_vote_info; }; /** Loading
net/ipc_router/ipc_router_socket.c +8 −9 Original line number Diff line number Diff line Loading @@ -303,7 +303,6 @@ int msm_ipc_router_bind(struct socket *sock, struct sockaddr *uaddr, struct sock *sk = sock->sk; struct msm_ipc_port *port_ptr; int ret; void *pil; if (!sk) return -EINVAL; Loading Loading @@ -333,8 +332,9 @@ int msm_ipc_router_bind(struct socket *sock, struct sockaddr *uaddr, if (!port_ptr) return -ENODEV; pil = msm_ipc_load_default_node(); msm_ipc_sk(sk)->default_pil = pil; if (!msm_ipc_sk(sk)->default_node_vote_info) msm_ipc_sk(sk)->default_node_vote_info = msm_ipc_load_default_node(); lock_sock(sk); ret = msm_ipc_router_register_server(port_ptr, &addr->address); Loading Loading @@ -445,7 +445,6 @@ static int msm_ipc_router_ioctl(struct socket *sock, unsigned int n; size_t srv_info_sz = 0; int ret; void *pil; if (!sk) return -EINVAL; Loading Loading @@ -473,8 +472,10 @@ static int msm_ipc_router_ioctl(struct socket *sock, break; case IPC_ROUTER_IOCTL_LOOKUP_SERVER: pil = msm_ipc_load_default_node(); msm_ipc_sk(sk)->default_pil = pil; if (!msm_ipc_sk(sk)->default_node_vote_info) msm_ipc_sk(sk)->default_node_vote_info = msm_ipc_load_default_node(); ret = copy_from_user(&server_arg, (void *)arg, sizeof(server_arg)); if (ret) { Loading Loading @@ -568,13 +569,11 @@ static int msm_ipc_router_close(struct socket *sock) { struct sock *sk = sock->sk; struct msm_ipc_port *port_ptr = msm_ipc_sk_port(sk); void *pil = msm_ipc_sk(sk)->default_pil; int ret; lock_sock(sk); ret = msm_ipc_router_close_port(port_ptr); if (pil) msm_ipc_unload_default_node(pil); msm_ipc_unload_default_node(msm_ipc_sk(sk)->default_node_vote_info); release_sock(sk); sock_put(sk); sock->sk = NULL; Loading