summaryrefslogtreecommitdiffstats
path: root/drivers/rpmsg
diff options
context:
space:
mode:
authorBjorn Andersson <bjorn.andersson@linaro.org>2017-12-12 18:58:53 -0500
committerBjorn Andersson <bjorn.andersson@linaro.org>2017-12-19 00:49:32 -0500
commit268105fbc0f82e1daa44b57112ef3fd81f69a174 (patch)
tree157c90d6a2f722cc0aae4c2dde805807d4fd11a4 /drivers/rpmsg
parent9d32497361ff89d2fc8306407de6f04b2bfb2836 (diff)
rpmsg: smd: Perform handshake during open
Validate the the remote side is opening the channel that we've found by performing a handshake when opening the channel. Tested-by: Will Newton <will.newton@gmail.com> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Diffstat (limited to 'drivers/rpmsg')
-rw-r--r--drivers/rpmsg/qcom_smd.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
index b01774e9fac0..58dd44493420 100644
--- a/drivers/rpmsg/qcom_smd.c
+++ b/drivers/rpmsg/qcom_smd.c
@@ -200,6 +200,7 @@ struct qcom_smd_channel {
200 char *name; 200 char *name;
201 enum smd_channel_state state; 201 enum smd_channel_state state;
202 enum smd_channel_state remote_state; 202 enum smd_channel_state remote_state;
203 wait_queue_head_t state_change_event;
203 204
204 struct smd_channel_info_pair *info; 205 struct smd_channel_info_pair *info;
205 struct smd_channel_info_word_pair *info_word; 206 struct smd_channel_info_word_pair *info_word;
@@ -570,6 +571,8 @@ static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
570 if (remote_state != channel->remote_state) { 571 if (remote_state != channel->remote_state) {
571 channel->remote_state = remote_state; 572 channel->remote_state = remote_state;
572 need_state_scan = true; 573 need_state_scan = true;
574
575 wake_up_interruptible_all(&channel->state_change_event);
573 } 576 }
574 /* Indicate that we have seen any state change */ 577 /* Indicate that we have seen any state change */
575 SET_RX_CHANNEL_FLAG(channel, fSTATE, 0); 578 SET_RX_CHANNEL_FLAG(channel, fSTATE, 0);
@@ -786,7 +789,9 @@ out:
786static int qcom_smd_channel_open(struct qcom_smd_channel *channel, 789static int qcom_smd_channel_open(struct qcom_smd_channel *channel,
787 rpmsg_rx_cb_t cb) 790 rpmsg_rx_cb_t cb)
788{ 791{
792 struct qcom_smd_edge *edge = channel->edge;
789 size_t bb_size; 793 size_t bb_size;
794 int ret;
790 795
791 /* 796 /*
792 * Packets are maximum 4k, but reduce if the fifo is smaller 797 * Packets are maximum 4k, but reduce if the fifo is smaller
@@ -798,9 +803,33 @@ static int qcom_smd_channel_open(struct qcom_smd_channel *channel,
798 803
799 qcom_smd_channel_set_callback(channel, cb); 804 qcom_smd_channel_set_callback(channel, cb);
800 qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENING); 805 qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENING);
806
807 /* Wait for remote to enter opening or opened */
808 ret = wait_event_interruptible_timeout(channel->state_change_event,
809 channel->remote_state == SMD_CHANNEL_OPENING ||
810 channel->remote_state == SMD_CHANNEL_OPENED,
811 HZ);
812 if (!ret) {
813 dev_err(&edge->dev, "remote side did not enter opening state\n");
814 goto out_close_timeout;
815 }
816
801 qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENED); 817 qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENED);
802 818
819 /* Wait for remote to enter opened */
820 ret = wait_event_interruptible_timeout(channel->state_change_event,
821 channel->remote_state == SMD_CHANNEL_OPENED,
822 HZ);
823 if (!ret) {
824 dev_err(&edge->dev, "remote side did not enter open state\n");
825 goto out_close_timeout;
826 }
827
803 return 0; 828 return 0;
829
830out_close_timeout:
831 qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED);
832 return -ETIMEDOUT;
804} 833}
805 834
806/* 835/*
@@ -1055,6 +1084,7 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
1055 mutex_init(&channel->tx_lock); 1084 mutex_init(&channel->tx_lock);
1056 spin_lock_init(&channel->recv_lock); 1085 spin_lock_init(&channel->recv_lock);
1057 init_waitqueue_head(&channel->fblockread_event); 1086 init_waitqueue_head(&channel->fblockread_event);
1087 init_waitqueue_head(&channel->state_change_event);
1058 1088
1059 info = qcom_smem_get(edge->remote_pid, smem_info_item, &info_size); 1089 info = qcom_smem_get(edge->remote_pid, smem_info_item, &info_size);
1060 if (IS_ERR(info)) { 1090 if (IS_ERR(info)) {