Loading Documentation/devicetree/bindings/arm/msm/msm_ipc_router_mhi_xprt.txt +8 −6 Original line number Diff line number Diff line Qualcomm Technologies, Inc. IPC Router MHI Transport Required properties: -compatible: should be "qcom,ipc_router_mhi_xprt" -qcom,out-chan-id: MHI Channel ID for the transmit path -qcom,in-chan-id: MHI Channel ID for the receive path -qcom,xprt-remote: string that defines the edge of the transport (PIL Name) -compatible: should be "qcom,ipc_router_mhi_xprt". -qcom,mhi: phandle of MHI Device to connect to. -qcom,out-chan-id: MHI Channel ID for the transmit path. -qcom,in-chan-id: MHI Channel ID for the receive path. -qcom,xprt-remote: string that defines the edge of the transport(PIL Name). -qcom,xprt-linkid: unique integer to identify the tier to which the link belongs to in the network and is used to avoid the routing loops while forwarding the broadcast messages -qcom,xprt-version: unique version ID used by MHI transport header routing loops while forwarding the broadcast messages. -qcom,xprt-version: unique version ID used by MHI transport header. Example: qcom,ipc_router_external_modem_xprt2 { compatible = "qcom,ipc_router_mhi_xprt"; qcom,mhi = <&mhi_wlan>; qcom,out-chan-id = <34>; qcom,in-chan-id = <35>; qcom,xprt-remote = "external-modem"; Loading drivers/soc/qcom/ipc_router_mhi_xprt.c +45 −49 Original line number Diff line number Diff line Loading @@ -132,12 +132,11 @@ struct ipc_router_mhi_xprt { struct ipc_router_mhi_xprt_work { struct ipc_router_mhi_xprt *mhi_xprtp; enum MHI_CLIENT_CHANNEL chan_id; struct work_struct work; }; static void mhi_xprt_read_data(struct work_struct *work); static void mhi_xprt_enable_event(struct work_struct *work); static void mhi_xprt_disable_event(struct work_struct *work); static void mhi_xprt_enable_event(struct ipc_router_mhi_xprt_work *xprt_work); static void mhi_xprt_disable_event(struct ipc_router_mhi_xprt_work *xprt_work); /** * ipc_router_mhi_xprt_config - Config. Info. of each MHI XPRT Loading Loading @@ -574,8 +573,6 @@ static int ipc_router_mhi_close(struct msm_ipc_router_xprt *xprt) mhi_xprtp->ch_hndl.in_chan_enabled = false; mutex_unlock(&mhi_xprtp->ch_hndl.state_lock); flush_workqueue(mhi_xprtp->wq); mhi_close_channel(mhi_xprtp->ch_hndl.in_handle); mhi_close_channel(mhi_xprtp->ch_hndl.out_handle); return 0; } Loading @@ -600,10 +597,8 @@ static void mhi_xprt_sft_close_done(struct msm_ipc_router_xprt *xprt) * * This work is scheduled when the MHI link to the peripheral is up. */ static void mhi_xprt_enable_event(struct work_struct *work) static void mhi_xprt_enable_event(struct ipc_router_mhi_xprt_work *xprt_work) { struct ipc_router_mhi_xprt_work *xprt_work = container_of(work, struct ipc_router_mhi_xprt_work, work); struct ipc_router_mhi_xprt *mhi_xprtp = xprt_work->mhi_xprtp; int rc; bool notify = false; Loading @@ -613,7 +608,7 @@ static void mhi_xprt_enable_event(struct work_struct *work) if (rc) { IPC_RTR_ERR("%s Failed to open chan 0x%x, rc %d\n", __func__, mhi_xprtp->ch_hndl.out_chan_id, rc); goto out_enable_event; return; } mutex_lock(&mhi_xprtp->ch_hndl.state_lock); mhi_xprtp->ch_hndl.out_chan_enabled = true; Loading @@ -625,7 +620,7 @@ static void mhi_xprt_enable_event(struct work_struct *work) if (rc) { IPC_RTR_ERR("%s Failed to open chan 0x%x, rc %d\n", __func__, mhi_xprtp->ch_hndl.in_chan_id, rc); goto out_enable_event; return; } mutex_lock(&mhi_xprtp->ch_hndl.state_lock); mhi_xprtp->ch_hndl.in_chan_enabled = true; Loading @@ -643,11 +638,11 @@ static void mhi_xprt_enable_event(struct work_struct *work) } if (xprt_work->chan_id != mhi_xprtp->ch_hndl.in_chan_id) goto out_enable_event; return; rc = mhi_xprt_queue_in_buffers(mhi_xprtp, mhi_xprtp->ch_hndl.num_trbs); if (rc > 0) goto out_enable_event; return; IPC_RTR_ERR("%s: Could not queue one TRB atleast\n", __func__); mutex_lock(&mhi_xprtp->ch_hndl.state_lock); Loading @@ -656,9 +651,6 @@ static void mhi_xprt_enable_event(struct work_struct *work) if (notify) msm_ipc_router_xprt_notify(&mhi_xprtp->xprt, IPC_ROUTER_XPRT_EVENT_CLOSE, NULL); mhi_close_channel(mhi_xprtp->ch_hndl.in_handle); out_enable_event: kfree(xprt_work); } /** Loading @@ -667,10 +659,8 @@ out_enable_event: * * This work is scheduled when the MHI link to the peripheral is down. */ static void mhi_xprt_disable_event(struct work_struct *work) static void mhi_xprt_disable_event(struct ipc_router_mhi_xprt_work *xprt_work) { struct ipc_router_mhi_xprt_work *xprt_work = container_of(work, struct ipc_router_mhi_xprt_work, work); struct ipc_router_mhi_xprt *mhi_xprtp = xprt_work->mhi_xprtp; bool notify = false; Loading @@ -681,7 +671,6 @@ static void mhi_xprt_disable_event(struct work_struct *work) mhi_xprtp->ch_hndl.out_chan_enabled = false; mutex_unlock(&mhi_xprtp->ch_hndl.state_lock); wake_up(&mhi_xprtp->write_wait_q); mhi_close_channel(mhi_xprtp->ch_hndl.out_handle); } else if (xprt_work->chan_id == mhi_xprtp->ch_hndl.in_chan_id) { mutex_lock(&mhi_xprtp->ch_hndl.state_lock); notify = mhi_xprtp->ch_hndl.out_chan_enabled && Loading @@ -691,7 +680,6 @@ static void mhi_xprt_disable_event(struct work_struct *work) /* Queue a read work to remove any partially read packets */ queue_work(mhi_xprtp->wq, &mhi_xprtp->read_work); flush_workqueue(mhi_xprtp->wq); mhi_close_channel(mhi_xprtp->ch_hndl.in_handle); } if (notify) { Loading @@ -702,7 +690,6 @@ static void mhi_xprt_disable_event(struct work_struct *work) __func__, mhi_xprtp->xprt.name); wait_for_completion(&mhi_xprtp->sft_close_complete); } kfree(xprt_work); } /** Loading Loading @@ -743,7 +730,7 @@ static void mhi_xprt_xfer_event(struct mhi_cb_info *cb_info) static void ipc_router_mhi_xprt_cb(struct mhi_cb_info *cb_info) { struct ipc_router_mhi_xprt *mhi_xprtp; struct ipc_router_mhi_xprt_work *xprt_work; struct ipc_router_mhi_xprt_work xprt_work; if (cb_info->result == NULL) { IPC_RTR_ERR("%s: Result not available in cb_info\n", __func__); Loading @@ -751,23 +738,16 @@ static void ipc_router_mhi_xprt_cb(struct mhi_cb_info *cb_info) } mhi_xprtp = (struct ipc_router_mhi_xprt *)(cb_info->result->user_data); xprt_work.mhi_xprtp = mhi_xprtp; xprt_work.chan_id = cb_info->chan; switch (cb_info->cb_reason) { case MHI_CB_MHI_ENABLED: case MHI_CB_MHI_SHUTDOWN: case MHI_CB_SYS_ERROR: case MHI_CB_MHI_DISABLED: xprt_work = kmalloc(sizeof(*xprt_work), GFP_KERNEL); if (!xprt_work) { IPC_RTR_ERR("%s: Couldn't handle %d event on %s\n", __func__, cb_info->cb_reason, mhi_xprtp->xprt_name); return; } xprt_work->mhi_xprtp = mhi_xprtp; xprt_work->chan_id = cb_info->chan; if (cb_info->cb_reason == MHI_CB_MHI_ENABLED) INIT_WORK(&xprt_work->work, mhi_xprt_enable_event); else INIT_WORK(&xprt_work->work, mhi_xprt_disable_event); queue_work(mhi_xprtp->wq, &xprt_work->work); mhi_xprt_disable_event(&xprt_work); break; case MHI_CB_MHI_ENABLED: mhi_xprt_enable_event(&xprt_work); break; case MHI_CB_XFER: mhi_xprt_xfer_event(cb_info); Loading @@ -788,22 +768,37 @@ static void ipc_router_mhi_xprt_cb(struct mhi_cb_info *cb_info) * This function is called when a new XPRT is added. */ static int ipc_router_mhi_driver_register( struct ipc_router_mhi_xprt *mhi_xprtp) struct ipc_router_mhi_xprt *mhi_xprtp, struct device *dev) { int rc_status; rc_status = mhi_register_channel(&mhi_xprtp->ch_hndl.out_handle, NULL); if (rc_status) { int rc; const char *node_name = "qcom,mhi"; struct mhi_client_info_t *mhi_info; if (!mhi_is_device_ready(dev, node_name)) return -EPROBE_DEFER; mhi_info = &mhi_xprtp->ch_hndl.out_clnt_info; mhi_info->chan = mhi_xprtp->ch_hndl.out_chan_id; mhi_info->dev = dev; mhi_info->node_name = node_name; mhi_info->user_data = mhi_xprtp; rc = mhi_register_channel(&mhi_xprtp->ch_hndl.out_handle, mhi_info); if (rc) { IPC_RTR_ERR("%s: Error %d registering out_chan for %s\n", __func__, rc_status, mhi_xprtp->xprt_name); __func__, rc, mhi_xprtp->xprt_name); return -EFAULT; } rc_status = mhi_register_channel(&mhi_xprtp->ch_hndl.in_handle, NULL); if (rc_status) { mhi_info = &mhi_xprtp->ch_hndl.in_clnt_info; mhi_info->chan = mhi_xprtp->ch_hndl.in_chan_id; mhi_info->dev = dev; mhi_info->node_name = node_name; mhi_info->user_data = mhi_xprtp; rc = mhi_register_channel(&mhi_xprtp->ch_hndl.in_handle, mhi_info); if (rc) { mhi_deregister_channel(mhi_xprtp->ch_hndl.out_handle); IPC_RTR_ERR("%s: Error %d registering in_chan for %s\n", __func__, rc_status, mhi_xprtp->xprt_name); __func__, rc, mhi_xprtp->xprt_name); return -EFAULT; } return 0; Loading @@ -820,7 +815,8 @@ static int ipc_router_mhi_driver_register( * the MHI XPRT configurations from device tree. */ static int ipc_router_mhi_config_init( struct ipc_router_mhi_xprt_config *mhi_xprt_config) struct ipc_router_mhi_xprt_config *mhi_xprt_config, struct device *dev) { struct ipc_router_mhi_xprt *mhi_xprtp; char wq_name[XPRT_NAME_LEN]; Loading Loading @@ -879,7 +875,7 @@ static int ipc_router_mhi_config_init( INIT_LIST_HEAD(&mhi_xprtp->rx_addr_map_list); spin_lock_init(&mhi_xprtp->rx_addr_map_list_lock); rc = ipc_router_mhi_driver_register(mhi_xprtp); rc = ipc_router_mhi_driver_register(mhi_xprtp, dev); return rc; } Loading Loading @@ -963,7 +959,7 @@ static int ipc_router_mhi_xprt_probe(struct platform_device *pdev) return rc; } rc = ipc_router_mhi_config_init(&mhi_xprt_config); rc = ipc_router_mhi_config_init(&mhi_xprt_config, &pdev->dev); if (rc) { IPC_RTR_ERR("%s: init failed\n", __func__); return rc; Loading Loading
Documentation/devicetree/bindings/arm/msm/msm_ipc_router_mhi_xprt.txt +8 −6 Original line number Diff line number Diff line Qualcomm Technologies, Inc. IPC Router MHI Transport Required properties: -compatible: should be "qcom,ipc_router_mhi_xprt" -qcom,out-chan-id: MHI Channel ID for the transmit path -qcom,in-chan-id: MHI Channel ID for the receive path -qcom,xprt-remote: string that defines the edge of the transport (PIL Name) -compatible: should be "qcom,ipc_router_mhi_xprt". -qcom,mhi: phandle of MHI Device to connect to. -qcom,out-chan-id: MHI Channel ID for the transmit path. -qcom,in-chan-id: MHI Channel ID for the receive path. -qcom,xprt-remote: string that defines the edge of the transport(PIL Name). -qcom,xprt-linkid: unique integer to identify the tier to which the link belongs to in the network and is used to avoid the routing loops while forwarding the broadcast messages -qcom,xprt-version: unique version ID used by MHI transport header routing loops while forwarding the broadcast messages. -qcom,xprt-version: unique version ID used by MHI transport header. Example: qcom,ipc_router_external_modem_xprt2 { compatible = "qcom,ipc_router_mhi_xprt"; qcom,mhi = <&mhi_wlan>; qcom,out-chan-id = <34>; qcom,in-chan-id = <35>; qcom,xprt-remote = "external-modem"; Loading
drivers/soc/qcom/ipc_router_mhi_xprt.c +45 −49 Original line number Diff line number Diff line Loading @@ -132,12 +132,11 @@ struct ipc_router_mhi_xprt { struct ipc_router_mhi_xprt_work { struct ipc_router_mhi_xprt *mhi_xprtp; enum MHI_CLIENT_CHANNEL chan_id; struct work_struct work; }; static void mhi_xprt_read_data(struct work_struct *work); static void mhi_xprt_enable_event(struct work_struct *work); static void mhi_xprt_disable_event(struct work_struct *work); static void mhi_xprt_enable_event(struct ipc_router_mhi_xprt_work *xprt_work); static void mhi_xprt_disable_event(struct ipc_router_mhi_xprt_work *xprt_work); /** * ipc_router_mhi_xprt_config - Config. Info. of each MHI XPRT Loading Loading @@ -574,8 +573,6 @@ static int ipc_router_mhi_close(struct msm_ipc_router_xprt *xprt) mhi_xprtp->ch_hndl.in_chan_enabled = false; mutex_unlock(&mhi_xprtp->ch_hndl.state_lock); flush_workqueue(mhi_xprtp->wq); mhi_close_channel(mhi_xprtp->ch_hndl.in_handle); mhi_close_channel(mhi_xprtp->ch_hndl.out_handle); return 0; } Loading @@ -600,10 +597,8 @@ static void mhi_xprt_sft_close_done(struct msm_ipc_router_xprt *xprt) * * This work is scheduled when the MHI link to the peripheral is up. */ static void mhi_xprt_enable_event(struct work_struct *work) static void mhi_xprt_enable_event(struct ipc_router_mhi_xprt_work *xprt_work) { struct ipc_router_mhi_xprt_work *xprt_work = container_of(work, struct ipc_router_mhi_xprt_work, work); struct ipc_router_mhi_xprt *mhi_xprtp = xprt_work->mhi_xprtp; int rc; bool notify = false; Loading @@ -613,7 +608,7 @@ static void mhi_xprt_enable_event(struct work_struct *work) if (rc) { IPC_RTR_ERR("%s Failed to open chan 0x%x, rc %d\n", __func__, mhi_xprtp->ch_hndl.out_chan_id, rc); goto out_enable_event; return; } mutex_lock(&mhi_xprtp->ch_hndl.state_lock); mhi_xprtp->ch_hndl.out_chan_enabled = true; Loading @@ -625,7 +620,7 @@ static void mhi_xprt_enable_event(struct work_struct *work) if (rc) { IPC_RTR_ERR("%s Failed to open chan 0x%x, rc %d\n", __func__, mhi_xprtp->ch_hndl.in_chan_id, rc); goto out_enable_event; return; } mutex_lock(&mhi_xprtp->ch_hndl.state_lock); mhi_xprtp->ch_hndl.in_chan_enabled = true; Loading @@ -643,11 +638,11 @@ static void mhi_xprt_enable_event(struct work_struct *work) } if (xprt_work->chan_id != mhi_xprtp->ch_hndl.in_chan_id) goto out_enable_event; return; rc = mhi_xprt_queue_in_buffers(mhi_xprtp, mhi_xprtp->ch_hndl.num_trbs); if (rc > 0) goto out_enable_event; return; IPC_RTR_ERR("%s: Could not queue one TRB atleast\n", __func__); mutex_lock(&mhi_xprtp->ch_hndl.state_lock); Loading @@ -656,9 +651,6 @@ static void mhi_xprt_enable_event(struct work_struct *work) if (notify) msm_ipc_router_xprt_notify(&mhi_xprtp->xprt, IPC_ROUTER_XPRT_EVENT_CLOSE, NULL); mhi_close_channel(mhi_xprtp->ch_hndl.in_handle); out_enable_event: kfree(xprt_work); } /** Loading @@ -667,10 +659,8 @@ out_enable_event: * * This work is scheduled when the MHI link to the peripheral is down. */ static void mhi_xprt_disable_event(struct work_struct *work) static void mhi_xprt_disable_event(struct ipc_router_mhi_xprt_work *xprt_work) { struct ipc_router_mhi_xprt_work *xprt_work = container_of(work, struct ipc_router_mhi_xprt_work, work); struct ipc_router_mhi_xprt *mhi_xprtp = xprt_work->mhi_xprtp; bool notify = false; Loading @@ -681,7 +671,6 @@ static void mhi_xprt_disable_event(struct work_struct *work) mhi_xprtp->ch_hndl.out_chan_enabled = false; mutex_unlock(&mhi_xprtp->ch_hndl.state_lock); wake_up(&mhi_xprtp->write_wait_q); mhi_close_channel(mhi_xprtp->ch_hndl.out_handle); } else if (xprt_work->chan_id == mhi_xprtp->ch_hndl.in_chan_id) { mutex_lock(&mhi_xprtp->ch_hndl.state_lock); notify = mhi_xprtp->ch_hndl.out_chan_enabled && Loading @@ -691,7 +680,6 @@ static void mhi_xprt_disable_event(struct work_struct *work) /* Queue a read work to remove any partially read packets */ queue_work(mhi_xprtp->wq, &mhi_xprtp->read_work); flush_workqueue(mhi_xprtp->wq); mhi_close_channel(mhi_xprtp->ch_hndl.in_handle); } if (notify) { Loading @@ -702,7 +690,6 @@ static void mhi_xprt_disable_event(struct work_struct *work) __func__, mhi_xprtp->xprt.name); wait_for_completion(&mhi_xprtp->sft_close_complete); } kfree(xprt_work); } /** Loading Loading @@ -743,7 +730,7 @@ static void mhi_xprt_xfer_event(struct mhi_cb_info *cb_info) static void ipc_router_mhi_xprt_cb(struct mhi_cb_info *cb_info) { struct ipc_router_mhi_xprt *mhi_xprtp; struct ipc_router_mhi_xprt_work *xprt_work; struct ipc_router_mhi_xprt_work xprt_work; if (cb_info->result == NULL) { IPC_RTR_ERR("%s: Result not available in cb_info\n", __func__); Loading @@ -751,23 +738,16 @@ static void ipc_router_mhi_xprt_cb(struct mhi_cb_info *cb_info) } mhi_xprtp = (struct ipc_router_mhi_xprt *)(cb_info->result->user_data); xprt_work.mhi_xprtp = mhi_xprtp; xprt_work.chan_id = cb_info->chan; switch (cb_info->cb_reason) { case MHI_CB_MHI_ENABLED: case MHI_CB_MHI_SHUTDOWN: case MHI_CB_SYS_ERROR: case MHI_CB_MHI_DISABLED: xprt_work = kmalloc(sizeof(*xprt_work), GFP_KERNEL); if (!xprt_work) { IPC_RTR_ERR("%s: Couldn't handle %d event on %s\n", __func__, cb_info->cb_reason, mhi_xprtp->xprt_name); return; } xprt_work->mhi_xprtp = mhi_xprtp; xprt_work->chan_id = cb_info->chan; if (cb_info->cb_reason == MHI_CB_MHI_ENABLED) INIT_WORK(&xprt_work->work, mhi_xprt_enable_event); else INIT_WORK(&xprt_work->work, mhi_xprt_disable_event); queue_work(mhi_xprtp->wq, &xprt_work->work); mhi_xprt_disable_event(&xprt_work); break; case MHI_CB_MHI_ENABLED: mhi_xprt_enable_event(&xprt_work); break; case MHI_CB_XFER: mhi_xprt_xfer_event(cb_info); Loading @@ -788,22 +768,37 @@ static void ipc_router_mhi_xprt_cb(struct mhi_cb_info *cb_info) * This function is called when a new XPRT is added. */ static int ipc_router_mhi_driver_register( struct ipc_router_mhi_xprt *mhi_xprtp) struct ipc_router_mhi_xprt *mhi_xprtp, struct device *dev) { int rc_status; rc_status = mhi_register_channel(&mhi_xprtp->ch_hndl.out_handle, NULL); if (rc_status) { int rc; const char *node_name = "qcom,mhi"; struct mhi_client_info_t *mhi_info; if (!mhi_is_device_ready(dev, node_name)) return -EPROBE_DEFER; mhi_info = &mhi_xprtp->ch_hndl.out_clnt_info; mhi_info->chan = mhi_xprtp->ch_hndl.out_chan_id; mhi_info->dev = dev; mhi_info->node_name = node_name; mhi_info->user_data = mhi_xprtp; rc = mhi_register_channel(&mhi_xprtp->ch_hndl.out_handle, mhi_info); if (rc) { IPC_RTR_ERR("%s: Error %d registering out_chan for %s\n", __func__, rc_status, mhi_xprtp->xprt_name); __func__, rc, mhi_xprtp->xprt_name); return -EFAULT; } rc_status = mhi_register_channel(&mhi_xprtp->ch_hndl.in_handle, NULL); if (rc_status) { mhi_info = &mhi_xprtp->ch_hndl.in_clnt_info; mhi_info->chan = mhi_xprtp->ch_hndl.in_chan_id; mhi_info->dev = dev; mhi_info->node_name = node_name; mhi_info->user_data = mhi_xprtp; rc = mhi_register_channel(&mhi_xprtp->ch_hndl.in_handle, mhi_info); if (rc) { mhi_deregister_channel(mhi_xprtp->ch_hndl.out_handle); IPC_RTR_ERR("%s: Error %d registering in_chan for %s\n", __func__, rc_status, mhi_xprtp->xprt_name); __func__, rc, mhi_xprtp->xprt_name); return -EFAULT; } return 0; Loading @@ -820,7 +815,8 @@ static int ipc_router_mhi_driver_register( * the MHI XPRT configurations from device tree. */ static int ipc_router_mhi_config_init( struct ipc_router_mhi_xprt_config *mhi_xprt_config) struct ipc_router_mhi_xprt_config *mhi_xprt_config, struct device *dev) { struct ipc_router_mhi_xprt *mhi_xprtp; char wq_name[XPRT_NAME_LEN]; Loading Loading @@ -879,7 +875,7 @@ static int ipc_router_mhi_config_init( INIT_LIST_HEAD(&mhi_xprtp->rx_addr_map_list); spin_lock_init(&mhi_xprtp->rx_addr_map_list_lock); rc = ipc_router_mhi_driver_register(mhi_xprtp); rc = ipc_router_mhi_driver_register(mhi_xprtp, dev); return rc; } Loading Loading @@ -963,7 +959,7 @@ static int ipc_router_mhi_xprt_probe(struct platform_device *pdev) return rc; } rc = ipc_router_mhi_config_init(&mhi_xprt_config); rc = ipc_router_mhi_config_init(&mhi_xprt_config, &pdev->dev); if (rc) { IPC_RTR_ERR("%s: init failed\n", __func__); return rc; Loading