summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorAjay Singh Parmar <aparmar@codeaurora.org>2015-10-01 13:24:06 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:46:20 -0700
commit38fdd3f630696356da2575fe8f0ea51cecd95b5c (patch)
tree8d9eea7c7a9274d0eb9b218df9c6cad5597648e7 /drivers/misc
parente8591b7730777af87c1ea2b6d7742118c2531bf3 (diff)
msm: mdss: hdmi: cleanup wakeup calls
Do not lock in wakeup functions as it may block current thread. Wakeup can trigger a callback looking to acquire same lock. Also rename the wakeup command names to properly identify client and lib commands. Change-Id: I28411714d2d7f0104364726fc5ce0593e5ccff91 Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/hdcp.c202
1 files changed, 98 insertions, 104 deletions
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c
index 3acfb3e272cf..7319d51114b0 100644
--- a/drivers/misc/hdcp.c
+++ b/drivers/misc/hdcp.c
@@ -85,7 +85,11 @@
#define MAX_RCVR_IDS_ALLOWED_IN_LIST 31
#define MAX_RCVR_ID_LIST_SIZE \
(RCVR_ID_SIZE*MAX_RCVR_IDS_ALLOWED_IN_LIST)
-#define SLEEP_SET_HW_KEY_MS 200
+/*
+ * 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 QSEECOM_ALIGN_SIZE 0x40
@@ -387,60 +391,30 @@ static const char *hdcp_lib_message_name(int msg_id)
return "UNKNOWN";
}
-static inline int hdcp_lib_report_error(struct hdcp_lib_handle *handle)
+static inline void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle,
+ struct hdmi_hdcp_wakeup_data *data)
{
- int rc = -EINVAL;
+ int rc = 0;
- if (handle->client_ops->wakeup) {
- rc = handle->client_ops->wakeup(
- handle->client_ctx, HDMI_HDCP_STATUS_FAIL,
- 0, 0, 0);
+ if (handle && handle->client_ops && handle->client_ops->wakeup &&
+ data && (data->cmd != HDMI_HDCP_WKUP_CMD_INVALID)) {
+ rc = handle->client_ops->wakeup(data);
if (rc)
- pr_err("error: report error\n");
- } else {
- pr_err("error: client ops wakeup not defined\n");
+ pr_err("error sending %s to client\n",
+ hdmi_hdcp_cmd_to_str(data->cmd));
}
-
- return rc;
}
-static inline int hdcp_lib_recv_message(struct hdcp_lib_handle *handle)
+static inline void hdcp_lib_send_message(struct hdcp_lib_handle *handle)
{
- int rc = -EINVAL;
-
- if (handle->client_ops->wakeup) {
- rc = handle->client_ops->wakeup(
- handle->client_ctx, HDMI_HDCP_RECV_MESSAGE,
- 0, 0, handle->hdcp_timeout);
- if (rc)
- pr_err("error receiving message from client\n");
- } else {
- pr_err("error: client ops wakeup not defined\n");
- }
-
- return rc;
-}
+ struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_SEND_MESSAGE};
-static inline int hdcp_lib_send_message(struct hdcp_lib_handle *handle)
-{
- int rc = -EINVAL;
-
- pr_debug("send msg: %s to sink\n",
- hdcp_lib_message_name((int)handle->listener_buf[0]));
-
- if (handle->client_ops->wakeup) {
- rc = handle->client_ops->wakeup(
- handle->client_ctx, HDMI_HDCP_SEND_MESSAGE,
- handle->listener_buf, handle->msglen, 0);
- if (!rc)
- handle->last_msg_sent = (int)handle->listener_buf[0];
- else
- pr_err("error sending message to client\n");
- } else {
- pr_err("error: client ops wakeup not defined\n");
- }
+ cdata.context = handle->client_ctx;
+ cdata.send_msg_buf = handle->listener_buf;
+ cdata.send_msg_len = handle->msglen;
+ cdata.timeout = handle->hdcp_timeout;
- return rc;
+ hdcp_lib_wakeup_client(handle, &cdata);
}
static int hdcp_lib_enable_encryption(struct hdcp_lib_handle *handle)
@@ -450,7 +424,7 @@ static int hdcp_lib_enable_encryption(struct hdcp_lib_handle *handle)
struct hdcp_set_hw_key_rsp *rsp_buf;
/*
- * wait for 200ms before enabling encryption
+ * wait at least 200ms before enabling encryption
* as per hdcp2p2 sepcifications.
*/
msleep(SLEEP_SET_HW_KEY_MS);
@@ -781,43 +755,38 @@ exit:
return supported;
}
-static int hdcp_lib_wakeup(void *phdcpcontext,
- enum hdcp_lib_wakeup_cmd cmd, char *msg, uint32_t msglen)
+static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
{
- struct hdcp_lib_handle *handle = phdcpcontext;
+ struct hdcp_lib_handle *handle;
int rc = 0;
- if (!handle)
+ if (!data)
return -EINVAL;
- mutex_lock(&handle->hdcp_lock);
- handle->wakeup_cmd = cmd;
- mutex_unlock(&handle->hdcp_lock);
-
- if (handle->wakeup_cmd == HDCP_WKUP_CMD_STOP) {
- atomic_set(&handle->hdcp_off_pending, 1);
- flush_kthread_worker(&handle->worker);
- atomic_set(&handle->hdcp_off_pending, 0);
- }
+ handle = data->context;
+ if (!handle)
+ return -EINVAL;
- mutex_lock(&handle->hdcp_lock);
+ handle->wakeup_cmd = data->cmd;
- pr_debug("wakeup_cmd: %s\n", hdcp_cmd_to_str(handle->wakeup_cmd));
+ pr_debug("wakeup_cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd));
- if (msglen) {
- handle->last_msg_recvd_len = msglen;
+ if (data->recvd_msg_len) {
+ handle->last_msg_recvd_len = data->recvd_msg_len;
- handle->last_msg_recvd_buf = kzalloc(msglen, GFP_KERNEL);
+ handle->last_msg_recvd_buf = kzalloc(data->recvd_msg_len,
+ GFP_KERNEL);
if (!handle->last_msg_recvd_buf) {
rc = -ENOMEM;
goto exit;
}
- memcpy(handle->last_msg_recvd_buf, msg, msglen);
+ memcpy(handle->last_msg_recvd_buf, data->recvd_msg_buf,
+ data->recvd_msg_len);
}
switch (handle->wakeup_cmd) {
- case HDCP_WKUP_CMD_START:
+ case HDCP_LIB_WKUP_CMD_START:
handle->no_stored_km_flag = 0;
handle->repeater_flag = 0;
handle->hdcp_state = HDCP_STATE_INIT;
@@ -825,24 +794,26 @@ static int hdcp_lib_wakeup(void *phdcpcontext,
if (!atomic_read(&handle->hdcp_off_pending))
queue_kthread_work(&handle->worker, &handle->init);
break;
- case HDCP_WKUP_CMD_STOP:
- /* wait for any work being executed */
+ case HDCP_LIB_WKUP_CMD_STOP:
+ atomic_set(&handle->hdcp_off_pending, 1);
queue_kthread_work(&handle->worker, &handle->clean);
break;
- case HDCP_WKUP_CMD_MSG_SEND_SUCCESS:
+ case HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS:
+ handle->last_msg_sent = handle->listener_buf[0];
+
if (!atomic_read(&handle->hdcp_off_pending))
queue_kthread_work(&handle->worker, &handle->msg_sent);
break;
- case HDCP_WKUP_CMD_MSG_SEND_FAILED:
- case HDCP_WKUP_CMD_MSG_RECV_FAILED:
+ case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED:
+ case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED:
if (!atomic_read(&handle->hdcp_off_pending))
queue_kthread_work(&handle->worker, &handle->clean);
break;
- case HDCP_WKUP_CMD_MSG_RECV_SUCCESS:
+ case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS:
if (!atomic_read(&handle->hdcp_off_pending))
queue_kthread_work(&handle->worker, &handle->msg_recvd);
break;
- case HDCP_WKUP_CMD_MSG_RECV_TIMEOUT:
+ case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT:
if (!atomic_read(&handle->hdcp_off_pending))
queue_kthread_work(&handle->worker, &handle->timeout);
break;
@@ -850,7 +821,6 @@ static int hdcp_lib_wakeup(void *phdcpcontext,
pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
}
exit:
- mutex_unlock(&handle->hdcp_lock);
return 0;
}
@@ -858,6 +828,7 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work)
{
struct hdcp_lib_handle *handle = container_of(work,
struct hdcp_lib_handle, msg_sent);
+ struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID};
if (!handle) {
pr_err("invalid handle\n");
@@ -866,15 +837,17 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work)
mutex_lock(&handle->hdcp_lock);
- if (handle->wakeup_cmd == HDCP_WKUP_CMD_MSG_SEND_SUCCESS) {
+ cdata.context = handle->client_ctx;
+
+ if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS) {
if (handle->last_msg_sent == SKE_SEND_EKS_MESSAGE_ID) {
if (!hdcp_lib_enable_encryption(handle))
- handle->client_ops->wakeup(
- handle->client_ctx,
- HDMI_HDCP_STATUS_SUCCESS,
- 0, 0, 0);
+ cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS;
+ else
+ cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_FAILED;
} else {
- hdcp_lib_recv_message(handle);
+ cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE;
+ cdata.timeout = handle->hdcp_timeout;
}
} else {
pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
@@ -882,12 +855,14 @@ static void hdcp_lib_msg_sent_work(struct kthread_work *work)
mutex_unlock(&handle->hdcp_lock);
+ hdcp_lib_wakeup_client(handle, &cdata);
return;
}
static void hdcp_lib_init_work(struct kthread_work *work)
{
int rc = 0;
+ bool send_msg = false;
struct hdcp_lib_handle *handle = container_of(work,
struct hdcp_lib_handle, init);
@@ -898,7 +873,7 @@ static void hdcp_lib_init_work(struct kthread_work *work)
mutex_lock(&handle->hdcp_lock);
- if (handle->wakeup_cmd == HDCP_WKUP_CMD_START) {
+ if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_START) {
rc = hdcp_lib_library_load(handle);
if (rc)
goto exit;
@@ -907,10 +882,8 @@ static void hdcp_lib_init_work(struct kthread_work *work)
if (rc)
goto exit;
- rc = hdcp_lib_send_message(handle);
- if (rc)
- goto exit;
- } else if (handle->wakeup_cmd == HDCP_WKUP_CMD_STOP) {
+ send_msg = true;
+ } else if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_STOP) {
rc = hdcp_lib_txmtr_deinit(handle);
if (rc)
goto exit;
@@ -922,16 +895,20 @@ static void hdcp_lib_init_work(struct kthread_work *work)
pr_err("invalid wakeup cmd: %d\n", handle->wakeup_cmd);
}
exit:
+ mutex_unlock(&handle->hdcp_lock);
+
+ if (send_msg)
+ hdcp_lib_send_message(handle);
+
if (rc && !atomic_read(&handle->hdcp_off_pending))
queue_kthread_work(&handle->worker, &handle->clean);
-
- mutex_unlock(&handle->hdcp_lock);
return;
}
static void hdcp_lib_manage_timeout_work(struct kthread_work *work)
{
int rc = 0;
+ bool send_msg = false;
struct hdcp_send_timeout_req *req_buf;
struct hdcp_send_timeout_rsp *rsp_buf;
struct hdcp_lib_handle *handle = container_of(work,
@@ -986,20 +963,24 @@ static void hdcp_lib_manage_timeout_work(struct kthread_work *work)
handle->hdcp_timeout = rsp_buf->timeout;
handle->msglen = rsp_buf->msglen;
- hdcp_lib_send_message(handle);
+ send_msg = true;
}
}
error:
+ mutex_unlock(&handle->hdcp_lock);
+
+ if (send_msg)
+ hdcp_lib_send_message(handle);
+
if (rc && !atomic_read(&handle->hdcp_off_pending))
queue_kthread_work(&handle->worker, &handle->clean);
-
- mutex_unlock(&handle->hdcp_lock);
}
static void hdcp_lib_cleanup_work(struct kthread_work *work)
{
struct hdcp_lib_handle *handle = container_of(work,
struct hdcp_lib_handle, clean);
+ struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID};
if (!handle) {
pr_err("invalid input\n");
@@ -1008,18 +989,18 @@ static void hdcp_lib_cleanup_work(struct kthread_work *work)
mutex_lock(&handle->hdcp_lock);
- if (atomic_read(&handle->hdcp_off_pending)) {
- pr_err("hdcp off underway\n");
- goto exit;
- }
+ cdata.context = handle->client_ctx;
+ cdata.cmd = HDMI_HDCP_WKUP_CMD_STATUS_FAILED;
hdcp_lib_txmtr_deinit(handle);
hdcp_lib_library_unload(handle);
- if (handle->wakeup_cmd != HDCP_WKUP_CMD_STOP)
- hdcp_lib_report_error(handle);
-exit:
mutex_unlock(&handle->hdcp_lock);
+
+ if (atomic_read(&handle->hdcp_off_pending))
+ atomic_set(&handle->hdcp_off_pending, 0);
+ else
+ hdcp_lib_wakeup_client(handle, &cdata);
}
static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
@@ -1031,6 +1012,7 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
char *msg;
struct hdcp_lib_handle *handle = container_of(work,
struct hdcp_lib_handle, msg_recvd);
+ struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID};
if (!handle) {
pr_err("invalid handle\n");
@@ -1042,8 +1024,10 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
msg = handle->last_msg_recvd_buf;
msglen = handle->last_msg_recvd_len;
+ cdata.context = handle->client_ctx;
+
if (msglen <= 0) {
- pr_err("invalid msg\n");
+ pr_err("invalid msg len\n");
rc = -EINVAL;
goto exit;
}
@@ -1074,7 +1058,11 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
/* get next message from sink if we receive H PRIME on no store km */
if ((msg[0] == AKE_SEND_H_PRIME_MESSAGE_ID) &&
handle->no_stored_km_flag) {
- hdcp_lib_recv_message(handle);
+ handle->hdcp_timeout = rsp_buf->timeout;
+
+ cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE;
+ cdata.timeout = handle->hdcp_timeout;
+
goto exit;
}
@@ -1120,15 +1108,21 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
handle->hdcp_timeout = rsp_buf->timeout;
handle->msglen = rsp_buf->msglen;
- if (!atomic_read(&handle->hdcp_off_pending))
- hdcp_lib_send_message(handle);
+ if (!atomic_read(&handle->hdcp_off_pending)) {
+ cdata.cmd = HDMI_HDCP_WKUP_CMD_SEND_MESSAGE;
+ cdata.send_msg_buf = handle->listener_buf;
+ cdata.send_msg_len = handle->msglen;
+ cdata.timeout = handle->hdcp_timeout;
+ }
+
exit:
kzfree(handle->last_msg_recvd_buf);
+ mutex_unlock(&handle->hdcp_lock);
+
+ hdcp_lib_wakeup_client(handle, &cdata);
if (rc && !atomic_read(&handle->hdcp_off_pending))
queue_kthread_work(&handle->worker, &handle->clean);
-
- mutex_unlock(&handle->hdcp_lock);
}
/* APIs exposed to all clients */