Merge "rpmsg: glink: wait for intent request completion"

This commit is contained in:
qctecmdr 2021-05-27 07:23:21 -07:00 • committed by Gerrit - the friendly Code Review server
commit 41973f0671

View file

@ -198,8 +198,10 @@ enum {
* @open_req: completed once open-request has been received
* @intent_req_lock: Synchronises multiple intent requests
* @intent_req_result: Result of intent request
* @intent_req_comp: Status of intent request completion
* @intent_req_event: Waitqueue for @intent_req_comp
* @intent_req_acked: Status of intent request acknowledgment
* @intent_req_completed: Status of intent request completion
* @intent_req_ack: Waitqueue for @intent_req_acked
* @intent_req_comp: Waitqueue for @intent_req_completed
* @lsigs: local side signals
* @rsigs: remote side signals
*/
@ -233,8 +235,10 @@ struct glink_channel {
struct mutex intent_req_lock;
bool intent_req_result;
bool channel_ready;
atomic_t intent_req_comp;
wait_queue_head_t intent_req_event;
atomic_t intent_req_acked;
atomic_t intent_req_completed;
wait_queue_head_t intent_req_ack;
wait_queue_head_t intent_req_comp;
unsigned int lsigs;
unsigned int rsigs;
@ -288,8 +292,10 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
init_completion(&channel->open_req);
init_completion(&channel->open_ack);
atomic_set(&channel->intent_req_comp, 0);
init_waitqueue_head(&channel->intent_req_event);
atomic_set(&channel->intent_req_acked, 0);
atomic_set(&channel->intent_req_completed, 0);
init_waitqueue_head(&channel->intent_req_ack);
init_waitqueue_head(&channel->intent_req_comp);
INIT_LIST_HEAD(&channel->done_intents);
kthread_init_work(&channel->intent_work, qcom_glink_rx_done_work);
@ -312,8 +318,10 @@ static void qcom_glink_channel_release(struct kref *ref)
CH_INFO(channel, "\n");
channel->intent_req_result = false;
atomic_inc(&channel->intent_req_comp);
wake_up(&channel->intent_req_event);
atomic_inc(&channel->intent_req_acked);
wake_up(&channel->intent_req_ack);
atomic_inc(&channel->intent_req_completed);
wake_up(&channel->intent_req_comp);
/* cancel pending rx_done work */
kthread_cancel_work_sync(&channel->intent_work);
@ -504,8 +512,8 @@ static void qcom_glink_handle_intent_req_ack(struct qcom_glink *glink,
}
channel->intent_req_result = granted;
atomic_inc(&channel->intent_req_comp);
wake_up(&channel->intent_req_event);
atomic_inc(&channel->intent_req_acked);
wake_up(&channel->intent_req_ack);
CH_INFO(channel, "\n");
}
@ -1144,6 +1152,9 @@ static void qcom_glink_handle_intent(struct qcom_glink *glink,
dev_err(glink->dev, "failed to store remote intent\n");
}
atomic_inc(&channel->intent_req_completed);
wake_up(&channel->intent_req_comp);
kfree(msg);
qcom_glink_rx_advance(glink, ALIGN(msglen, 8));
}
@ -1537,7 +1548,8 @@ static int qcom_glink_request_intent(struct qcom_glink *glink,
mutex_lock(&channel->intent_req_lock);
atomic_set(&channel->intent_req_comp, 0);
atomic_set(&channel->intent_req_acked, 0);
atomic_set(&channel->intent_req_completed, 0);
cmd.id = RPM_CMD_RX_INTENT_REQ;
cmd.cid = channel->lcid;
@ -1549,11 +1561,11 @@ static int qcom_glink_request_intent(struct qcom_glink *glink,
if (ret)
goto unlock;
ret = wait_event_timeout(channel->intent_req_event,
atomic_read(&channel->intent_req_comp) ||
ret = wait_event_timeout(channel->intent_req_ack,
atomic_read(&channel->intent_req_acked) ||
atomic_read(&glink->in_reset), 10 * HZ);
if (!ret) {
dev_err(glink->dev, "intent request timed out\n");
dev_err(glink->dev, "intent request ack timed out\n");
ret = -ETIMEDOUT;
} else if (atomic_read(&glink->in_reset)) {
CH_INFO(channel, "ssr detected\n");
@ -1614,6 +1626,25 @@ static int __qcom_glink_send(struct glink_channel *channel,
ret = qcom_glink_request_intent(glink, channel, len);
if (ret < 0)
return ret;
/*Wait for intents to arrive*/
ret = wait_event_timeout(channel->intent_req_comp,
atomic_read(&channel->intent_req_completed) ||
atomic_read(&glink->in_reset), 10 * HZ);
if (!ret) {
dev_err(glink->dev,
"intent request completion timed out\n");
ret = -ETIMEDOUT;
} else if (atomic_read(&glink->in_reset)) {
CH_INFO(channel, "ssr detected\n");
ret = -ECONNRESET;
} else {
ret = channel->intent_req_result ? 0 : -ECANCELED;
}
if (ret < 0)
return ret;
}
iid = intent->id;
@ -2041,7 +2072,8 @@ static void qcom_glink_notif_reset(void *data)
spin_lock_irqsave(&glink->idr_lock, flags);
idr_for_each_entry(&glink->lcids, channel, cid) {
wake_up(&channel->intent_req_event);
wake_up(&channel->intent_req_ack);
wake_up(&channel->intent_req_comp);
}
spin_unlock_irqrestore(&glink->idr_lock, flags);
}