diff options
| author | Steven Cahail <scahail@codeaurora.org> | 2015-12-03 13:23:30 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 21:13:25 -0700 |
| commit | ea74beeae9c5d82213b7faf94464a850aa550810 (patch) | |
| tree | 1f1af5714918531068bdf9c30fde73033e6505de | |
| parent | 945d3d962ca4b188afb56a93e9fbec7f52f51002 (diff) | |
soc: qcom: glink: Add RX intent request timeout to G-Link channels
During glink_tx(), G-Link can wait for an unlimited amount of time for
the remote side to queue an RX intent. In some cases, e.g. SSR, the wait
must be restricted to a short time, but in the current implementation,
glink_tx() can continue to block indefinitely.
Add a configurable timeout value to the G-Link channel context, which is
set in the channel open configuration. If the value is set to 0, treat
it as an infinite timeout. This allows a timeout to be put in place by
the client for sensitive cases such as SSR where a very limited amount of
time can be spent waiting for an intent.
Change-Id: I1e480fac286d285f871fe3059de7ae761fc4581e
Signed-off-by: Steven Cahail <scahail@codeaurora.org>
| -rw-r--r-- | drivers/soc/qcom/glink.c | 46 | ||||
| -rw-r--r-- | include/soc/qcom/glink.h | 21 |
2 files changed, 48 insertions, 19 deletions
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c index d09412bbead5..0af0d67d3789 100644 --- a/drivers/soc/qcom/glink.c +++ b/drivers/soc/qcom/glink.c @@ -159,14 +159,16 @@ struct glink_core_xprt_ctx { * @notify_rx_tracer_pkt: Receive notification for tracer packet * @notify_remote_rx_intent: Receive notification for remote-queued RX intent * - * @transport_ptr: Transport this channel uses - * @lcid: Local channel ID - * @rcid: Remote channel ID - * @local_open_state: Local channel state - * @remote_opened: Remote channel state (opened or closed) - * @int_req_ack: Remote side intent request ACK state - * @int_req_ack_complete: Intent tracking completion - received remote ACK - * @int_req_complete: Intent tracking completion - received intent + * @transport_ptr: Transport this channel uses + * @lcid: Local channel ID + * @rcid: Remote channel ID + * @local_open_state: Local channel state + * @remote_opened: Remote channel state (opened or closed) + * @int_req_ack: Remote side intent request ACK state + * @int_req_ack_complete: Intent tracking completion - received remote ACK + * @int_req_complete: Intent tracking completion - received intent + * @rx_intent_req_timeout_jiffies: Timeout for requesting an RX intent, in + * jiffies; if set to 0, timeout is infinite * * @local_rx_intent_lst_lock_lhc1: RX intent list lock * @local_rx_intent_list: Active RX Intents queued by client @@ -244,6 +246,7 @@ struct channel_ctx { bool int_req_ack; struct completion int_req_ack_complete; struct completion int_req_complete; + unsigned long rx_intent_req_timeout_jiffies; spinlock_t local_rx_intent_lst_lock_lhc1; struct list_head local_rx_intent_list; @@ -2401,6 +2404,8 @@ void *glink_open(const struct glink_open_config *cfg) /* initialize port structure */ ctx->user_priv = cfg->priv; + ctx->rx_intent_req_timeout_jiffies = + msecs_to_jiffies(cfg->rx_intent_req_timeout_ms); ctx->notify_rx = cfg->notify_rx; ctx->notify_tx_done = cfg->notify_tx_done; ctx->notify_state = cfg->notify_state; @@ -2421,6 +2426,9 @@ void *glink_open(const struct glink_open_config *cfg) if (!ctx->notify_tx_abort) ctx->notify_tx_abort = glink_dummy_notify_tx_abort; + if (!ctx->rx_intent_req_timeout_jiffies) + ctx->rx_intent_req_timeout_jiffies = MAX_SCHEDULE_TIMEOUT; + ctx->local_xprt_req = best_id; ctx->no_migrate = cfg->transport && !(cfg->options & GLINK_OPT_INITIAL_XPORT); @@ -2712,7 +2720,16 @@ static int glink_tx_common(void *handle, void *pkt_priv, } /* wait for the remote intent req ack */ - wait_for_completion(&ctx->int_req_ack_complete); + if (!wait_for_completion_timeout( + &ctx->int_req_ack_complete, + ctx->rx_intent_req_timeout_jiffies)) { + GLINK_ERR_CH(ctx, + "%s: Intent request ack with size: %zu not granted for lcid\n", + __func__, size); + rwref_put(&ctx->ch_state_lhc0); + return -ETIMEDOUT; + } + if (!ctx->int_req_ack) { GLINK_ERR_CH(ctx, "%s: Intent Request with size: %zu %s", @@ -2723,7 +2740,16 @@ static int glink_tx_common(void *handle, void *pkt_priv, } /* wait for the rx_intent from remote side */ - wait_for_completion(&ctx->int_req_complete); + if (!wait_for_completion_timeout( + &ctx->int_req_complete, + ctx->rx_intent_req_timeout_jiffies)) { + GLINK_ERR_CH(ctx, + "%s: Intent request with size: %zu not granted for lcid\n", + __func__, size); + rwref_put(&ctx->ch_state_lhc0); + return -ETIMEDOUT; + } + reinit_completion(&ctx->int_req_complete); ch_st = ctx->local_open_state; if (ch_st == GLINK_CHANNEL_CLOSING || diff --git a/include/soc/qcom/glink.h b/include/soc/qcom/glink.h index 970ee2bf31a9..fedca64ec9a2 100644 --- a/include/soc/qcom/glink.h +++ b/include/soc/qcom/glink.h @@ -43,15 +43,17 @@ enum { /** * Open configuration. * - * priv: Private data passed into user callbacks - * options: Open option flags - * notify_rx: Receive notification function (required) - * notify_tx_done: Transmit-done notification function (required) - * notify_state: State-change notification (required) - * notify_rx_intent_req: Receive intent request (optional) - * notify_rxv: Receive notification function for vector buffers (required if - * notify_rx is not provided) - * notify_sig: Signal-change notification (optional) + * priv: Private data passed into user callbacks + * options: Open option flags + * rx_intent_req_timeout_ms: Timeout for requesting an RX intent, in + * milliseconds; if set to 0, timeout is infinite + * notify_rx: Receive notification function (required) + * notify_tx_done: Transmit-done notification function (required) + * notify_state: State-change notification (required) + * notify_rx_intent_req: Receive intent request (optional) + * notify_rxv: Receive notification function for vector buffers + * (required if notify_rx is not provided) + * notify_sig: Signal-change notification (optional) * notify_rx_tracer_pkt: Receive notification for tracer packet * notify_remote_rx_intent: Receive notification for remote-queued RX intent * @@ -67,6 +69,7 @@ struct glink_open_config { const char *transport; const char *edge; const char *name; + unsigned int rx_intent_req_timeout_ms; void (*notify_rx)(void *handle, const void *priv, const void *pkt_priv, const void *ptr, size_t size); |
