Merge "msm: hdcp: add response timeout and new messages for sink"

This commit is contained in:
Linux Build Service Account 2016-12-01 09:23:50 -08:00 committed by Gerrit - the friendly Code Review server
commit c2cbb11bf9

View file

@ -65,7 +65,8 @@
#define REPEATER_AUTH_SEND_ACK_MESSAGE_ID 15
#define REPEATER_AUTH_STREAM_MANAGE_MESSAGE_ID 16
#define REPEATER_AUTH_STREAM_READY_MESSAGE_ID 17
#define HDCP2P2_MAX_MESSAGES 18
#define SKE_SEND_TYPE_ID 18
#define HDCP2P2_MAX_MESSAGES 19
#define HDCP1_SET_KEY_MESSAGE_ID 202
#define HDCP1_SET_ENC_MESSAGE_ID 205
@ -94,7 +95,7 @@
* minimum wait as per standard is 200 ms. keep it 300 ms
* to be on safe side.
*/
#define SLEEP_SET_HW_KEY_MS 300
#define SLEEP_SET_HW_KEY_MS 220
#define QSEECOM_ALIGN_SIZE 0x40
#define QSEECOM_ALIGN_MASK (QSEECOM_ALIGN_SIZE - 1)
@ -187,6 +188,9 @@ static const struct hdcp_msg_data hdcp_msg_lookup[HDCP2P2_MAX_MESSAGES] = {
[SKE_SEND_EKS_MESSAGE_ID] = { 2,
{ {"Edkey_ks", 0x69318, 16}, {"riv", 0x69328, 8} },
0 },
[SKE_SEND_TYPE_ID] = { 1,
{ {"type", 0x69494, 1} },
0 },
[REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID] = { 4,
{ {"RxInfo", 0x69330, 2}, {"seq_num_V", 0x69332, 3},
{"V'", 0x69335, 16}, {"ridlist", 0x69345, 155} },
@ -499,8 +503,10 @@ struct hdcp_lib_handle {
uint32_t tz_ctxhandle;
uint32_t hdcp_timeout;
uint32_t timeout_left;
uint32_t wait_timeout;
bool no_stored_km_flag;
bool feature_supported;
bool authenticated;
void *client_ctx;
struct hdcp_client_ops *client_ops;
struct mutex msg_lock;
@ -521,7 +527,7 @@ struct hdcp_lib_handle {
enum hdcp_device_type device_type;
struct task_struct *thread;
struct completion topo_wait;
struct completion poll_wait;
struct kthread_worker worker;
struct kthread_work wk_init;
@ -529,7 +535,7 @@ struct hdcp_lib_handle {
struct kthread_work wk_msg_recvd;
struct kthread_work wk_timeout;
struct kthread_work wk_clean;
struct kthread_work wk_topology;
struct kthread_work wk_wait;
struct kthread_work wk_stream;
int (*hdcp_app_init)(struct hdcp_lib_handle *handle);
@ -574,6 +580,7 @@ static const char *hdcp_lib_message_name(int msg_id)
{15, "REPEATER_AUTH_SEND_ACK"},
{16, "REPEATER_AUTH_STREAM_MANAGE"},
{17, "REPEATER_AUTH_STREAM_READY"},
{18, "SKE_SEND_TYPE_ID"},
};
int i;
@ -612,8 +619,14 @@ static int hdcp_lib_get_next_message(struct hdcp_lib_handle *handle,
case LC_SEND_L_PRIME_MESSAGE_ID:
return SKE_SEND_EKS_MESSAGE_ID;
case SKE_SEND_EKS_MESSAGE_ID:
if (!handle->repeater_flag)
return SKE_SEND_TYPE_ID;
case SKE_SEND_TYPE_ID:
case REPEATER_AUTH_STREAM_READY_MESSAGE_ID:
case REPEATER_AUTH_SEND_ACK_MESSAGE_ID:
if (!handle->repeater_flag)
return INVALID_MESSAGE_ID;
if (data->cmd == HDMI_HDCP_WKUP_CMD_SEND_MESSAGE)
return REPEATER_AUTH_STREAM_MANAGE_MESSAGE_ID;
else
@ -628,6 +641,33 @@ static int hdcp_lib_get_next_message(struct hdcp_lib_handle *handle,
}
}
static void hdcp_lib_wait_for_response(struct hdcp_lib_handle *handle,
struct hdmi_hdcp_wakeup_data *data)
{
switch (handle->last_msg) {
case AKE_SEND_H_PRIME_MESSAGE_ID:
if (handle->no_stored_km_flag)
handle->wait_timeout = HZ;
else
handle->wait_timeout = HZ / 4;
break;
case AKE_SEND_PAIRING_INFO_MESSAGE_ID:
handle->wait_timeout = HZ / 4;
break;
case REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID:
if (!handle->authenticated)
handle->wait_timeout = HZ * 3;
else
handle->wait_timeout = 0;
break;
default:
handle->wait_timeout = 0;
}
if (handle->wait_timeout)
queue_kthread_work(&handle->worker, &handle->wk_wait);
}
static void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle,
struct hdmi_hdcp_wakeup_data *data)
{
@ -639,43 +679,42 @@ static void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle,
data->abort_mask = REAUTH_REQ | LINK_INTEGRITY_FAILURE;
if (data->cmd == HDMI_HDCP_WKUP_CMD_SEND_MESSAGE ||
data->cmd == HDMI_HDCP_WKUP_CMD_RECV_MESSAGE ||
data->cmd == HDMI_HDCP_WKUP_CMD_LINK_POLL) {
if (data->cmd == HDMI_HDCP_WKUP_CMD_RECV_MESSAGE ||
data->cmd == HDMI_HDCP_WKUP_CMD_LINK_POLL)
handle->last_msg = hdcp_lib_get_next_message(handle, data);
if (handle->last_msg != INVALID_MESSAGE_ID &&
data->cmd != HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS &&
data->cmd != HDMI_HDCP_WKUP_CMD_STATUS_FAILED) {
u32 msg_num, rx_status;
const struct hdcp_msg_part *msg;
pr_debug("lib->client: %s (%s)\n",
hdmi_hdcp_cmd_to_str(data->cmd),
hdcp_lib_message_name(handle->last_msg));
if (handle->last_msg > INVALID_MESSAGE_ID &&
handle->last_msg < HDCP2P2_MAX_MESSAGES) {
u32 msg_num, rx_status;
const struct hdcp_msg_part *msg;
data->message_data = &hdcp_msg_lookup[handle->last_msg];
data->message_data = &hdcp_msg_lookup[handle->last_msg];
msg_num = data->message_data->num_messages;
msg = data->message_data->messages;
rx_status = data->message_data->rx_status;
msg_num = data->message_data->num_messages;
msg = data->message_data->messages;
rx_status = data->message_data->rx_status;
pr_debug("%10s | %6s | %4s\n", "name", "offset", "len");
pr_debug("rxstatus 0x%x\n", rx_status);
pr_debug("%10s | %6s | %4s\n", "name", "offset", "len");
for (i = 0; i < msg_num; i++)
pr_debug("%10s | %6x | %4d\n",
msg[i].name, msg[i].offset,
msg[i].length);
}
for (i = 0; i < msg_num; i++)
pr_debug("%10s | %6x | %4d\n",
msg[i].name, msg[i].offset,
msg[i].length);
} else {
pr_debug("lib->client: %s\n",
hdmi_hdcp_cmd_to_str(data->cmd));
pr_debug("lib->client: %s\n", hdmi_hdcp_cmd_to_str(data->cmd));
}
rc = handle->client_ops->wakeup(data);
if (rc)
pr_err("error sending %s to client\n",
hdmi_hdcp_cmd_to_str(data->cmd));
hdcp_lib_wait_for_response(handle, data);
}
static inline void hdcp_lib_send_message(struct hdcp_lib_handle *handle)
@ -1286,6 +1325,8 @@ static int hdcp_lib_txmtr_init_legacy(struct hdcp_lib_handle *handle)
hdcp_lib_message_name((int)rsp_buf->message[0]),
jiffies_to_msecs(jiffies));
handle->last_msg = (int)rsp_buf->message[0];
/* send the response to HDMI driver */
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
memcpy(handle->listener_buf, (unsigned char *)rsp_buf->message,
@ -1404,6 +1445,8 @@ static int hdcp_lib_start_auth(struct hdcp_lib_handle *handle)
hdcp_lib_message_name((int)rsp_buf->message[0]),
jiffies_to_msecs(jiffies));
handle->last_msg = (int)rsp_buf->message[0];
/* send the response to HDMI driver */
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
memcpy(handle->listener_buf, (unsigned char *)rsp_buf->message,
@ -1470,6 +1513,8 @@ static void hdcp_lib_stream(struct hdcp_lib_handle *handle)
pr_debug("message received from TZ: %s\n",
hdcp_lib_message_name((int)rsp_buf->msg[0]));
handle->last_msg = (int)rsp_buf->msg[0];
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
memcpy(handle->listener_buf, (unsigned char *)rsp_buf->msg,
rsp_buf->msglen);
@ -1550,11 +1595,11 @@ static void hdcp_lib_check_worker_status(struct hdcp_lib_handle *handle)
if (handle->worker.current_work == &handle->wk_clean)
pr_debug("clean work executing\n");
if (!list_empty(&handle->wk_topology.node))
pr_debug("topology work queued\n");
if (!list_empty(&handle->wk_wait.node))
pr_debug("wait work queued\n");
if (handle->worker.current_work == &handle->wk_topology)
pr_debug("topology work executing\n");
if (handle->worker.current_work == &handle->wk_wait)
pr_debug("wait work executing\n");
if (!list_empty(&handle->wk_stream.node))
pr_debug("stream work queued\n");
@ -1613,7 +1658,7 @@ static void hdcp_lib_update_exec_type(void *ctx, bool tethered)
mutex_unlock(&handle->wakeup_mutex);
}
static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
static int hdcp_lib_wakeup_thread(struct hdcp_lib_wakeup_data *data)
{
struct hdcp_lib_handle *handle;
int rc = 0;
@ -1630,8 +1675,9 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
handle->wakeup_cmd = data->cmd;
handle->timeout_left = data->timeout;
pr_debug("client->lib: %s\n",
hdcp_lib_cmd_to_str(handle->wakeup_cmd));
pr_debug("client->lib: %s (%s)\n",
hdcp_lib_cmd_to_str(data->cmd),
hdcp_lib_message_name(handle->last_msg));
rc = hdcp_lib_check_valid_state(handle);
if (rc)
@ -1655,8 +1701,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
}
mutex_unlock(&handle->msg_lock);
if (!completion_done(&handle->topo_wait))
complete_all(&handle->topo_wait);
if (!completion_done(&handle->poll_wait))
complete_all(&handle->poll_wait);
switch (handle->wakeup_cmd) {
case HDCP_LIB_WKUP_CMD_START:
@ -1719,22 +1765,30 @@ static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle)
cdata.context = handle->client_ctx;
switch (handle->last_msg_sent) {
case SKE_SEND_EKS_MESSAGE_ID:
if (handle->repeater_flag) {
if (!atomic_read(&handle->hdcp_off))
queue_kthread_work(&handle->worker,
&handle->wk_topology);
}
case SKE_SEND_TYPE_ID:
if (!hdcp_lib_enable_encryption(handle)) {
handle->authenticated = true;
cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS;
hdcp_lib_wakeup_client(handle, &cdata);
}
/* poll for link check */
cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL;
break;
case SKE_SEND_EKS_MESSAGE_ID:
if (handle->repeater_flag) {
/* poll for link check */
cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL;
} else {
if (!atomic_read(&handle->hdcp_off))
HDCP_LIB_EXECUTE(clean);
memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE);
handle->listener_buf[0] = SKE_SEND_TYPE_ID;
handle->msglen = 2;
cdata.cmd = HDMI_HDCP_WKUP_CMD_SEND_MESSAGE;
cdata.send_msg_buf = handle->listener_buf;
cdata.send_msg_len = handle->msglen;
handle->last_msg = hdcp_lib_get_next_message(handle,
&cdata);
}
break;
case REPEATER_AUTH_SEND_ACK_MESSAGE_ID:
@ -1915,6 +1969,8 @@ static void hdcp_lib_clean(struct hdcp_lib_handle *handle)
return;
}
handle->authenticated = false;
hdcp_lib_txmtr_deinit(handle);
if (!handle->legacy_app)
hdcp_lib_session_deinit(handle);
@ -2040,6 +2096,13 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle)
(rc == 0) && (rsp_buf->status == 0)) {
pr_debug("Got Auth_Stream_Ready, nothing sent to rx\n");
if (!hdcp_lib_enable_encryption(handle)) {
handle->authenticated = true;
cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS;
hdcp_lib_wakeup_client(handle, &cdata);
}
cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL;
goto exit;
}
@ -2057,6 +2120,8 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle)
hdcp_lib_message_name((int)rsp_buf->msg[0]),
jiffies_to_msecs(jiffies));
handle->last_msg = (int)rsp_buf->msg[0];
/* set the flag if response is AKE_No_Stored_km */
if (((int)rsp_buf->msg[0] == AKE_NO_STORED_KM_MESSAGE_ID)) {
pr_debug("Setting no_stored_km_flag\n");
@ -2101,12 +2166,11 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
hdcp_lib_msg_recvd(handle);
}
static void hdcp_lib_topology_work(struct kthread_work *work)
static void hdcp_lib_wait_work(struct kthread_work *work)
{
u32 timeout;
struct hdcp_lib_handle *handle = container_of(work,
struct hdcp_lib_handle,
wk_topology);
struct hdcp_lib_handle, wk_wait);
if (!handle) {
pr_err("invalid input\n");
@ -2123,14 +2187,17 @@ static void hdcp_lib_topology_work(struct kthread_work *work)
return;
}
reinit_completion(&handle->topo_wait);
timeout = wait_for_completion_timeout(&handle->topo_wait, HZ * 3);
reinit_completion(&handle->poll_wait);
timeout = wait_for_completion_timeout(&handle->poll_wait,
handle->wait_timeout);
if (!timeout) {
pr_err("topology receiver id list timeout\n");
pr_err("wait timeout\n");
if (!atomic_read(&handle->hdcp_off))
HDCP_LIB_EXECUTE(clean);
}
handle->wait_timeout = 0;
}
bool hdcp1_check_if_supported_load_app(void)
@ -2266,7 +2333,7 @@ int hdcp_library_register(struct hdcp_register_data *data)
/* populate ops to be called by client */
data->txmtr_ops->feature_supported = hdcp_lib_client_feature_supported;
data->txmtr_ops->wakeup = hdcp_lib_wakeup;
data->txmtr_ops->wakeup = hdcp_lib_wakeup_thread;
data->txmtr_ops->update_exec_type = hdcp_lib_update_exec_type;
handle = kzalloc(sizeof(*handle), GFP_KERNEL);
@ -2296,10 +2363,10 @@ int hdcp_library_register(struct hdcp_register_data *data)
init_kthread_work(&handle->wk_msg_recvd, hdcp_lib_msg_recvd_work);
init_kthread_work(&handle->wk_timeout, hdcp_lib_manage_timeout_work);
init_kthread_work(&handle->wk_clean, hdcp_lib_cleanup_work);
init_kthread_work(&handle->wk_topology, hdcp_lib_topology_work);
init_kthread_work(&handle->wk_wait, hdcp_lib_wait_work);
init_kthread_work(&handle->wk_stream, hdcp_lib_query_stream_work);
init_completion(&handle->topo_wait);
init_completion(&handle->poll_wait);
handle->listener_buf = kzalloc(MAX_TX_MESSAGE_SIZE, GFP_KERNEL);
if (!(handle->listener_buf)) {