Merge "soc: qcom: ipc_router_mhi_xprt: Do not defer MHI open and close work"
This commit is contained in:
commit
4e9710b652
2 changed files with 52 additions and 54 deletions
|
@ -1,18 +1,20 @@
|
|||
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";
|
||||
|
|
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 &&
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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__);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
int rc;
|
||||
const char *node_name = "qcom,mhi";
|
||||
struct mhi_client_info_t *mhi_info;
|
||||
|
||||
rc_status = mhi_register_channel(&mhi_xprtp->ch_hndl.out_handle, NULL);
|
||||
if (rc_status) {
|
||||
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;
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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…
Add table
Reference in a new issue