diff --git a/msm/dp/dp_hdcp2p2.c b/msm/dp/dp_hdcp2p2.c index b87cfee526..bc2a254139 100644 --- a/msm/dp/dp_hdcp2p2.c +++ b/msm/dp/dp_hdcp2p2.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #include @@ -44,7 +44,8 @@ struct dp_hdcp2p2_ctrl { struct hdcp2_buffer response; struct hdcp2_buffer request; uint32_t total_message_length; - uint32_t timeout; + uint32_t transaction_delay; + uint32_t transaction_timeout; struct sde_hdcp_2x_msg_part msg_part[HDCP_MAX_MESSAGE_PARTS]; u8 sink_rx_status; u8 rx_status; @@ -108,7 +109,6 @@ static int dp_hdcp2p2_copy_buf(struct dp_hdcp2p2_ctrl *ctrl, mutex_lock(&ctrl->msg_lock); - ctrl->timeout = data->timeout; num_messages = data->message_data->num_messages; ctrl->total_message_length = 0; /* Total length of all messages */ @@ -132,6 +132,9 @@ static int dp_hdcp2p2_copy_buf(struct dp_hdcp2p2_ctrl *ctrl, ctrl->request.data = data->buf; ctrl->request.length = ctrl->total_message_length; + ctrl->transaction_delay = data->transaction_delay; + ctrl->transaction_timeout = data->transaction_timeout; + mutex_unlock(&ctrl->msg_lock); return 0; @@ -170,7 +173,6 @@ static void dp_hdcp2p2_set_interrupts(struct dp_hdcp2p2_ctrl *ctrl, bool enable) static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) { struct dp_hdcp2p2_ctrl *ctrl; - u32 const default_timeout_us = 500; if (!data) { DP_ERR("invalid input\n"); @@ -183,11 +185,6 @@ static int dp_hdcp2p2_wakeup(struct hdcp_transport_wakeup_data *data) return -EINVAL; } - if (data->timeout) - ctrl->timeout = (data->timeout) * 2; - else - ctrl->timeout = default_timeout_us; - if (dp_hdcp2p2_copy_buf(ctrl, data)) goto exit; @@ -364,6 +361,8 @@ static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl) int rc = 0, max_size = 16, read_size = 0, bytes_read = 0; int size = ctrl->request.length, offset = ctrl->msg_part->offset; u8 *buf = ctrl->request.data; + s64 diff_ms; + ktime_t start_read, finish_read; if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE || atomic_read(&ctrl->auth_state) == HDCP_STATE_AUTH_FAIL) { @@ -380,6 +379,7 @@ static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl) DP_DEBUG("offset(0x%x), size(%d)\n", offset, size); + start_read = ktime_get(); do { read_size = min(size, max_size); @@ -396,7 +396,14 @@ static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl) offset += read_size; size -= read_size; } while (size > 0); + finish_read = ktime_get(); + diff_ms = ktime_ms_delta(finish_read, start_read); + if (ctrl->transaction_timeout && diff_ms > ctrl->transaction_timeout) { + DP_ERR("HDCP read timeout exceeded (%dms > %dms)\n", diff_ms, + ctrl->transaction_timeout); + rc = -ETIMEDOUT; + } exit: return rc; } @@ -485,7 +492,7 @@ static void dp_hdcp2p2_send_msg(struct dp_hdcp2p2_ctrl *ctrl) rc = dp_hdcp2p2_aux_write_message(ctrl, ctrl->response.data, ctrl->response.length, ctrl->msg_part->offset, - ctrl->timeout); + ctrl->transaction_delay); if (rc) { DP_ERR("Error sending msg to sink %d\n", rc); mutex_unlock(&ctrl->msg_lock); @@ -493,7 +500,7 @@ static void dp_hdcp2p2_send_msg(struct dp_hdcp2p2_ctrl *ctrl) } cdata.cmd = HDCP_2X_CMD_MSG_SEND_SUCCESS; - cdata.timeout = ctrl->timeout; + cdata.timeout = ctrl->transaction_delay; mutex_unlock(&ctrl->msg_lock); exit: @@ -519,7 +526,7 @@ static int dp_hdcp2p2_get_msg_from_sink(struct dp_hdcp2p2_ctrl *ctrl) } cdata.total_message_length = ctrl->total_message_length; - cdata.timeout = ctrl->timeout; + cdata.timeout = ctrl->transaction_delay; exit: if (rc == -ETIMEDOUT) cdata.cmd = HDCP_2X_CMD_MSG_RECV_TIMEOUT; @@ -544,6 +551,9 @@ static void dp_hdcp2p2_recv_msg(struct dp_hdcp2p2_ctrl *ctrl) return; } + if (ctrl->transaction_delay) + msleep(ctrl->transaction_delay); + dp_hdcp2p2_get_msg_from_sink(ctrl); } diff --git a/msm/sde_hdcp_2x.c b/msm/sde_hdcp_2x.c index a3bc7b6185..28cf474b3a 100644 --- a/msm/sde_hdcp_2x.c +++ b/msm/sde_hdcp_2x.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "[sde-hdcp-2x] %s: " fmt, __func__ @@ -42,6 +42,9 @@ #define REAUTH_REQ BIT(3) #define LINK_INTEGRITY_FAILURE BIT(4) +/* Temporary define to override wrong TZ value */ +#define AKE_SEND_CERT_MSG_DELAY 100 + struct sde_hdcp_2x_ctrl { DECLARE_KFIFO(cmd_q, enum sde_hdcp_2x_wakeup_cmd, 8); wait_queue_head_t wait_q; @@ -100,49 +103,49 @@ static const struct sde_hdcp_2x_msg_data hdcp_msg_lookup[HDCP2P2_MAX_MESSAGES] = { [AKE_INIT] = { 2, { {"rtx", 0x69000, 8}, {"TxCaps", 0x69008, 3} }, - 0 }, + 0, 0 }, [AKE_SEND_CERT] = { 3, { {"cert-rx", 0x6900B, 522}, {"rrx", 0x69215, 8}, {"RxCaps", 0x6921D, 3} }, - 0 }, + 0, 110 }, [AKE_NO_STORED_KM] = { 1, { {"Ekpub_km", 0x69220, 128} }, - 0 }, + 0, 0 }, [AKE_STORED_KM] = { 2, { {"Ekh_km", 0x692A0, 16}, {"m", 0x692B0, 16} }, - 0 }, + 0, 0 }, [AKE_SEND_H_PRIME] = { 1, { {"H'", 0x692C0, 32} }, - (1 << 1) }, + (1 << 1), 7 }, [AKE_SEND_PAIRING_INFO] = { 1, { {"Ekh_km", 0x692E0, 16} }, - (1 << 2) }, + (1 << 2), 5 }, [LC_INIT] = { 1, { {"rn", 0x692F0, 8} }, - 0 }, + 0, 0 }, [LC_SEND_L_PRIME] = { 1, { {"L'", 0x692F8, 32} }, - 0 }, + 0, 0 }, [SKE_SEND_EKS] = { 2, { {"Edkey_ks", 0x69318, 16}, {"riv", 0x69328, 8} }, - 0 }, + 0, 0 }, [SKE_SEND_TYPE_ID] = { 1, { {"type", 0x69494, 1} }, - 0 }, + 0, 0 }, [REP_SEND_RECV_ID_LIST] = { 4, { {"RxInfo", 0x69330, 2}, {"seq_num_V", 0x69332, 3}, {"V'", 0x69335, 16}, {"ridlist", 0x69345, 155} }, - (1 << 0) }, + (1 << 0), 0 }, [REP_SEND_ACK] = { 1, { {"V", 0x693E0, 16} }, - 0 }, + 0, 0 }, [REP_STREAM_MANAGE] = { 3, { {"seq_num_M", 0x693F0, 3}, {"k", 0x693F3, 2}, {"streamID_Type", 0x693F5, 126} }, - 0 }, + 0, 0 }, [REP_STREAM_READY] = { 1, { {"M'", 0x69473, 32} }, - 0 }, + 0, 7 }, }; static int sde_hdcp_2x_get_next_message(struct sde_hdcp_2x_ctrl *hdcp, @@ -247,6 +250,29 @@ static void sde_hdcp_2x_wait_for_response(struct sde_hdcp_2x_ctrl *hdcp) hdcp->wait_timeout_ms = 0; } +static void sde_hdcp_2x_adjust_transaction_params( + struct sde_hdcp_2x_ctrl *hdcp, + struct hdcp_transport_wakeup_data *data) +{ + switch (hdcp->last_msg) { + case AKE_SEND_CERT: + data->transaction_delay = AKE_SEND_CERT_MSG_DELAY; + break; + case REP_STREAM_READY: + break; + default: + data->transaction_delay = 0; + break; + } + + data->transaction_timeout = + hdcp_msg_lookup[hdcp->last_msg].transaction_timeout; + + pr_debug("%s: transaction delay: %ums, transaction timeout: %ums\n", + sde_hdcp_2x_message_name(hdcp->last_msg), + data->transaction_delay, data->transaction_timeout); +} + static void sde_hdcp_2x_wakeup_client(struct sde_hdcp_2x_ctrl *hdcp, struct hdcp_transport_wakeup_data *data) { @@ -271,6 +297,8 @@ static void sde_hdcp_2x_wakeup_client(struct sde_hdcp_2x_ctrl *hdcp, data->message_data = &hdcp_msg_lookup[hdcp->last_msg]; } + sde_hdcp_2x_adjust_transaction_params(hdcp, data); + rc = hdcp->client_ops->wakeup(data); if (rc) pr_err("error sending %s to client\n", @@ -285,7 +313,7 @@ static inline void sde_hdcp_2x_send_message(struct sde_hdcp_2x_ctrl *hdcp) HDCP_TRANSPORT_CMD_SEND_MESSAGE }; cdata.context = hdcp->client_data; - cdata.timeout = hdcp->app_data.timeout; + cdata.transaction_delay = hdcp->app_data.timeout; cdata.buf_len = hdcp->app_data.response.length; /* ignore the first byte as it contains the message id */ @@ -436,7 +464,7 @@ static void sde_hdcp_2x_initialize_command(struct sde_hdcp_2x_ctrl *hdcp, struct hdcp_transport_wakeup_data *cdata) { cdata->cmd = cmd; - cdata->timeout = hdcp->timeout_left; + cdata->transaction_delay = hdcp->timeout_left; cdata->buf = hdcp->app_data.request.data + 1; } @@ -492,7 +520,7 @@ static void sde_hdcp_2x_msg_sent(struct sde_hdcp_2x_ctrl *hdcp) break; default: cdata.cmd = HDCP_TRANSPORT_CMD_RECV_MESSAGE; - cdata.timeout = hdcp->timeout_left; + cdata.transaction_delay = hdcp->app_data.timeout; cdata.buf = hdcp->app_data.request.data + 1; } @@ -593,7 +621,7 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) if (msg[0] == AKE_SEND_H_PRIME && hdcp->no_stored_km) { cdata.cmd = HDCP_TRANSPORT_CMD_RECV_MESSAGE; - cdata.timeout = hdcp->app_data.timeout; + cdata.transaction_delay = hdcp->app_data.timeout; cdata.buf = hdcp->app_data.request.data + 1; goto exit; } @@ -653,7 +681,7 @@ static void sde_hdcp_2x_msg_recvd(struct sde_hdcp_2x_ctrl *hdcp) cdata.cmd = HDCP_TRANSPORT_CMD_SEND_MESSAGE; cdata.buf = hdcp->app_data.response.data + 1; cdata.buf_len = hdcp->app_data.response.length; - cdata.timeout = hdcp->app_data.timeout; + cdata.transaction_delay = hdcp->app_data.timeout; } exit: sde_hdcp_2x_wakeup_client(hdcp, &cdata); diff --git a/msm/sde_hdcp_2x.h b/msm/sde_hdcp_2x.h index 4669564dec..a8c459c7fa 100644 --- a/msm/sde_hdcp_2x.h +++ b/msm/sde_hdcp_2x.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. */ #ifndef __SDE_HDCP_2X_H__ @@ -114,32 +114,37 @@ struct sde_hdcp_2x_msg_part { /** * struct sde_hdcp_2x_msg_data - HDCP 2.2 message containing one or more parts - * @num_messages: total number of parts in a full message - * @messages: array containing num_messages parts - * @rx_status: value of rx_status register + * @num_messages: total number of parts in a full message + * @messages: array containing num_messages parts + * @rx_status: value of rx_status register + * @transaction_timeout: maximum duration to read/write message from/to sink */ struct sde_hdcp_2x_msg_data { uint32_t num_messages; struct sde_hdcp_2x_msg_part messages[HDCP_MAX_MESSAGE_PARTS]; uint8_t rx_status; + uint32_t transaction_timeout; }; /** * struct hdcp_transport_wakeup_data - data sent to display transport layer - * @cmd: command type - * @context: void pointer to the display transport layer - * @send_msg_buf: buffer containing message to be sent to sink - * @send_msg_len: length of the message to be sent to sink - * @timeout: timeout value for timed transactions - * @abort_mask: mask used to determine whether HDCP link is valid - * @message_data: a pointer to the message description + * @cmd: command type + * @context: void pointer to the display transport layer + * @send_msg_buf: buffer containing message to be sent to sink + * @send_msg_len: length of the message to be sent to sink + * @timeout: timeout value for timed transactions + * @abort_mask: mask used to determine whether HDCP link is valid + * @message_data: a pointer to the message description + * @transaction_delay: amount of time to delay before performing transaction + * @transaction_timeout: maximum duration to read/write message from/to sink */ struct hdcp_transport_wakeup_data { enum hdcp_transport_wakeup_cmd cmd; void *context; unsigned char *buf; u32 buf_len; - u32 timeout; + u32 transaction_delay; + u32 transaction_timeout; u8 abort_mask; const struct sde_hdcp_2x_msg_data *message_data; };