mirror of
https://github.com/torvalds/linux.git
synced 2026-07-31 19:47:08 +02:00
rpmsg: glink: wait for intent request completion
Wait for actul intent allocation to complete before again requesting for same intent. Currently on getting intent request ack glink looks for allocated intent and if it is not found it again requests. In some cases remote host may delay allocation of intents but acknowledge it immediately, in such cases glink will keep on requesting same intent repeatedly. Now added code to wait for actual intent allocation to complete and timeout if it is not allocated within 10 sec. Change-Id: I346eb207422450cbeedc94e6451c6491bbf58bf0 Signed-off-by: Deepak Kumar Singh <deesin@codeaurora.org>
This commit is contained in:
parent
ca10e48d38
commit
1332236bd1
|
|
@ -158,8 +158,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
|
||||
*/
|
||||
struct glink_channel {
|
||||
struct rpmsg_endpoint ept;
|
||||
|
|
@ -191,8 +193,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;
|
||||
};
|
||||
|
||||
#define to_glink_channel(_ept) container_of(_ept, struct glink_channel, ept)
|
||||
|
|
@ -237,8 +241,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);
|
||||
INIT_WORK(&channel->intent_work, qcom_glink_rx_done_work);
|
||||
|
|
@ -260,9 +266,11 @@ static void qcom_glink_channel_release(struct kref *ref)
|
|||
int iid;
|
||||
|
||||
channel->intent_req_result = false;
|
||||
atomic_inc(&channel->intent_req_comp);
|
||||
atomic_inc(&channel->intent_req_acked);
|
||||
wake_up(&channel->intent_req_ack);
|
||||
atomic_inc(&channel->intent_req_completed);
|
||||
wake_up(&channel->intent_req_comp);
|
||||
|
||||
wake_up(&channel->intent_req_event);
|
||||
/* cancel pending rx_done work */
|
||||
cancel_work_sync(&channel->intent_work);
|
||||
|
||||
|
|
@ -437,8 +445,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1049,6 +1057,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));
|
||||
}
|
||||
|
|
@ -1352,7 +1363,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;
|
||||
|
|
@ -1362,11 +1374,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)) {
|
||||
ret = -ECONNRESET;
|
||||
|
|
@ -1426,6 +1438,24 @@ 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)) {
|
||||
ret = -ECONNRESET;
|
||||
} else {
|
||||
ret = channel->intent_req_result ? 0 : -ECANCELED;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
iid = intent->id;
|
||||
|
|
@ -1910,7 +1940,8 @@ void qcom_glink_native_remove(struct qcom_glink *glink)
|
|||
/* Signal all threads to cancel tx */
|
||||
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);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user