msm: mdss: hdmi: proper state validation and buffer handling
Validate current hdcp lib state before starting new hdcp session. Double buffer the sink message and protect its access with mutex to handle fast re-authentication requests. Change-Id: I039b1a0c818a2e66eef583afb15420ce8587a75c Signed-off-by: Ajay Singh Parmar <aparmar@codeaurora.org>
This commit is contained in:
parent
10ab09906b
commit
9fc3e2178c
2 changed files with 146 additions and 27 deletions
|
@ -337,6 +337,7 @@ struct hdcp_lib_handle {
|
||||||
void *client_ctx;
|
void *client_ctx;
|
||||||
struct hdcp_client_ops *client_ops;
|
struct hdcp_client_ops *client_ops;
|
||||||
struct mutex hdcp_lock;
|
struct mutex hdcp_lock;
|
||||||
|
struct mutex msg_lock;
|
||||||
struct mutex wakeup_mutex;
|
struct mutex wakeup_mutex;
|
||||||
enum hdcp_state hdcp_state;
|
enum hdcp_state hdcp_state;
|
||||||
enum hdcp_lib_wakeup_cmd wakeup_cmd;
|
enum hdcp_lib_wakeup_cmd wakeup_cmd;
|
||||||
|
@ -755,6 +756,77 @@ exit:
|
||||||
return supported;
|
return supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hdcp_lib_check_worker_status(struct hdcp_lib_handle *handle)
|
||||||
|
{
|
||||||
|
if (!list_empty(&handle->init.node))
|
||||||
|
pr_debug("init work queued\n");
|
||||||
|
|
||||||
|
if (handle->worker.current_work == &handle->init)
|
||||||
|
pr_debug("init work executing\n");
|
||||||
|
|
||||||
|
if (!list_empty(&handle->msg_sent.node))
|
||||||
|
pr_debug("msg_sent work queued\n");
|
||||||
|
|
||||||
|
if (handle->worker.current_work == &handle->msg_sent)
|
||||||
|
pr_debug("msg_sent work executing\n");
|
||||||
|
|
||||||
|
if (!list_empty(&handle->msg_recvd.node))
|
||||||
|
pr_debug("msg_recvd work queued\n");
|
||||||
|
|
||||||
|
if (handle->worker.current_work == &handle->msg_recvd)
|
||||||
|
pr_debug("msg_recvd work executing\n");
|
||||||
|
|
||||||
|
if (!list_empty(&handle->timeout.node))
|
||||||
|
pr_debug("timeout work queued\n");
|
||||||
|
|
||||||
|
if (handle->worker.current_work == &handle->timeout)
|
||||||
|
pr_debug("timeout work executing\n");
|
||||||
|
|
||||||
|
if (!list_empty(&handle->clean.node))
|
||||||
|
pr_debug("clean work queued\n");
|
||||||
|
|
||||||
|
if (handle->worker.current_work == &handle->clean)
|
||||||
|
pr_debug("clean work executing\n");
|
||||||
|
|
||||||
|
if (!list_empty(&handle->topology.node))
|
||||||
|
pr_debug("topology work queued\n");
|
||||||
|
|
||||||
|
if (handle->worker.current_work == &handle->topology)
|
||||||
|
pr_debug("topology work executing\n");
|
||||||
|
|
||||||
|
if (!list_empty(&handle->stream.node))
|
||||||
|
pr_debug("stream work queued\n");
|
||||||
|
|
||||||
|
if (handle->worker.current_work == &handle->stream)
|
||||||
|
pr_debug("stream work executing\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hdcp_lib_check_valid_state(struct hdcp_lib_handle *handle)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_START) {
|
||||||
|
if (!list_empty(&handle->worker.work_list)) {
|
||||||
|
hdcp_lib_check_worker_status(handle);
|
||||||
|
rc = -EBUSY;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (atomic_read(&handle->hdcp_off)) {
|
||||||
|
pr_warn("hdcp2.2 session tearing down\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) {
|
||||||
|
pr_err("hdcp 2.2 app not loaded\n");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exit:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
|
static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
|
||||||
{
|
{
|
||||||
struct hdcp_lib_handle *handle;
|
struct hdcp_lib_handle *handle;
|
||||||
|
@ -770,22 +842,29 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
|
||||||
mutex_lock(&handle->wakeup_mutex);
|
mutex_lock(&handle->wakeup_mutex);
|
||||||
|
|
||||||
handle->wakeup_cmd = data->cmd;
|
handle->wakeup_cmd = data->cmd;
|
||||||
|
pr_debug("%s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd));
|
||||||
|
|
||||||
pr_debug("cmd: %s\n", hdcp_lib_cmd_to_str(handle->wakeup_cmd));
|
rc = hdcp_lib_check_valid_state(handle);
|
||||||
|
if (rc)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
mutex_lock(&handle->msg_lock);
|
||||||
if (data->recvd_msg_len) {
|
if (data->recvd_msg_len) {
|
||||||
handle->last_msg_recvd_len = data->recvd_msg_len;
|
kzfree(handle->last_msg_recvd_buf);
|
||||||
|
|
||||||
|
handle->last_msg_recvd_len = data->recvd_msg_len;
|
||||||
handle->last_msg_recvd_buf = kzalloc(data->recvd_msg_len,
|
handle->last_msg_recvd_buf = kzalloc(data->recvd_msg_len,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!handle->last_msg_recvd_buf) {
|
if (!handle->last_msg_recvd_buf) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
|
mutex_unlock(&handle->msg_lock);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(handle->last_msg_recvd_buf, data->recvd_msg_buf,
|
memcpy(handle->last_msg_recvd_buf, data->recvd_msg_buf,
|
||||||
data->recvd_msg_len);
|
data->recvd_msg_len);
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&handle->msg_lock);
|
||||||
|
|
||||||
if (!completion_done(&handle->topo_wait))
|
if (!completion_done(&handle->topo_wait))
|
||||||
complete_all(&handle->topo_wait);
|
complete_all(&handle->topo_wait);
|
||||||
|
@ -807,32 +886,27 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
|
||||||
case HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS:
|
case HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS:
|
||||||
handle->last_msg_sent = handle->listener_buf[0];
|
handle->last_msg_sent = handle->listener_buf[0];
|
||||||
|
|
||||||
if (!atomic_read(&handle->hdcp_off))
|
queue_kthread_work(&handle->worker, &handle->msg_sent);
|
||||||
queue_kthread_work(&handle->worker, &handle->msg_sent);
|
|
||||||
break;
|
break;
|
||||||
case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED:
|
case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED:
|
||||||
case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED:
|
case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED:
|
||||||
if (!atomic_read(&handle->hdcp_off))
|
queue_kthread_work(&handle->worker, &handle->clean);
|
||||||
queue_kthread_work(&handle->worker, &handle->clean);
|
|
||||||
break;
|
break;
|
||||||
case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS:
|
case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS:
|
||||||
if (!atomic_read(&handle->hdcp_off))
|
queue_kthread_work(&handle->worker, &handle->msg_recvd);
|
||||||
queue_kthread_work(&handle->worker, &handle->msg_recvd);
|
|
||||||
break;
|
break;
|
||||||
case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT:
|
case HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT:
|
||||||
if (!atomic_read(&handle->hdcp_off))
|
queue_kthread_work(&handle->worker, &handle->timeout);
|
||||||
queue_kthread_work(&handle->worker, &handle->timeout);
|
|
||||||
break;
|
break;
|
||||||
case HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE:
|
case HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE:
|
||||||
if (!atomic_read(&handle->hdcp_off))
|
queue_kthread_work(&handle->worker, &handle->stream);
|
||||||
queue_kthread_work(&handle->worker, &handle->stream);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
|
pr_err("invalid wakeup command %d\n", handle->wakeup_cmd);
|
||||||
}
|
}
|
||||||
exit:
|
exit:
|
||||||
mutex_unlock(&handle->wakeup_mutex);
|
mutex_unlock(&handle->wakeup_mutex);
|
||||||
return 0;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hdcp_lib_msg_sent_work(struct kthread_work *work)
|
static void hdcp_lib_msg_sent_work(struct kthread_work *work)
|
||||||
|
@ -926,7 +1000,6 @@ exit:
|
||||||
|
|
||||||
if (rc && !atomic_read(&handle->hdcp_off))
|
if (rc && !atomic_read(&handle->hdcp_off))
|
||||||
queue_kthread_work(&handle->worker, &handle->clean);
|
queue_kthread_work(&handle->worker, &handle->clean);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hdcp_lib_manage_timeout_work(struct kthread_work *work)
|
static void hdcp_lib_manage_timeout_work(struct kthread_work *work)
|
||||||
|
@ -1044,18 +1117,29 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&handle->hdcp_lock);
|
mutex_lock(&handle->hdcp_lock);
|
||||||
|
|
||||||
msg = handle->last_msg_recvd_buf;
|
|
||||||
msglen = handle->last_msg_recvd_len;
|
|
||||||
|
|
||||||
cdata.context = handle->client_ctx;
|
cdata.context = handle->client_ctx;
|
||||||
|
|
||||||
|
mutex_lock(&handle->msg_lock);
|
||||||
|
msglen = handle->last_msg_recvd_len;
|
||||||
|
|
||||||
if (msglen <= 0) {
|
if (msglen <= 0) {
|
||||||
pr_err("invalid msg len\n");
|
pr_err("invalid msg len\n");
|
||||||
|
mutex_unlock(&handle->msg_lock);
|
||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msg = kzalloc(msglen, GFP_KERNEL);
|
||||||
|
if (!msg) {
|
||||||
|
mutex_unlock(&handle->msg_lock);
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(msg, handle->last_msg_recvd_buf, msglen);
|
||||||
|
|
||||||
|
mutex_unlock(&handle->msg_lock);
|
||||||
|
|
||||||
pr_debug("msg received: %s from sink\n",
|
pr_debug("msg received: %s from sink\n",
|
||||||
hdcp_lib_message_name((int)msg[0]));
|
hdcp_lib_message_name((int)msg[0]));
|
||||||
|
|
||||||
|
@ -1140,7 +1224,7 @@ static void hdcp_lib_msg_recvd_work(struct kthread_work *work)
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
kzfree(handle->last_msg_recvd_buf);
|
kzfree(msg);
|
||||||
mutex_unlock(&handle->hdcp_lock);
|
mutex_unlock(&handle->hdcp_lock);
|
||||||
|
|
||||||
hdcp_lib_wakeup_client(handle, &cdata);
|
hdcp_lib_wakeup_client(handle, &cdata);
|
||||||
|
@ -1160,7 +1244,6 @@ static void hdcp_lib_topology_work(struct kthread_work *work)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
reinit_completion(&handle->topo_wait);
|
reinit_completion(&handle->topo_wait);
|
||||||
timeout = wait_for_completion_timeout(&handle->topo_wait, HZ * 3);
|
timeout = wait_for_completion_timeout(&handle->topo_wait, HZ * 3);
|
||||||
if (!timeout) {
|
if (!timeout) {
|
||||||
|
@ -1185,6 +1268,9 @@ bool hdcp1_check_if_supported_load_app(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pr_debug("hdcp1 app %s loaded\n",
|
||||||
|
hdcp1_supported ? "successfully" : "not");
|
||||||
|
|
||||||
return hdcp1_supported;
|
return hdcp1_supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1274,6 +1360,7 @@ int hdcp_library_register(void **pphdcpcontext,
|
||||||
atomic_set(&handle->hdcp_off, 0);
|
atomic_set(&handle->hdcp_off, 0);
|
||||||
|
|
||||||
mutex_init(&handle->hdcp_lock);
|
mutex_init(&handle->hdcp_lock);
|
||||||
|
mutex_init(&handle->msg_lock);
|
||||||
mutex_init(&handle->wakeup_mutex);
|
mutex_init(&handle->wakeup_mutex);
|
||||||
|
|
||||||
init_kthread_worker(&handle->worker);
|
init_kthread_worker(&handle->worker);
|
||||||
|
@ -1326,6 +1413,7 @@ void hdcp_library_deregister(void *phdcpcontext)
|
||||||
kthread_stop(handle->thread);
|
kthread_stop(handle->thread);
|
||||||
|
|
||||||
kzfree(handle->qseecom_handle);
|
kzfree(handle->qseecom_handle);
|
||||||
|
kzfree(handle->last_msg_recvd_buf);
|
||||||
|
|
||||||
mutex_destroy(&handle->hdcp_lock);
|
mutex_destroy(&handle->hdcp_lock);
|
||||||
mutex_destroy(&handle->wakeup_mutex);
|
mutex_destroy(&handle->wakeup_mutex);
|
||||||
|
|
|
@ -56,6 +56,7 @@ struct hdmi_hdcp2p2_ctrl {
|
||||||
enum hdmi_hdcp2p2_sink_status sink_status; /* Is sink connected */
|
enum hdmi_hdcp2p2_sink_status sink_status; /* Is sink connected */
|
||||||
struct hdmi_hdcp_init_data init_data; /* Feature data from HDMI drv */
|
struct hdmi_hdcp_init_data init_data; /* Feature data from HDMI drv */
|
||||||
struct mutex mutex; /* mutex to protect access to ctrl */
|
struct mutex mutex; /* mutex to protect access to ctrl */
|
||||||
|
struct mutex msg_lock; /* mutex to protect access to msg buffer */
|
||||||
struct mutex wakeup_mutex; /* mutex to protect access to wakeup call*/
|
struct mutex wakeup_mutex; /* mutex to protect access to wakeup call*/
|
||||||
struct hdmi_hdcp_ops *ops;
|
struct hdmi_hdcp_ops *ops;
|
||||||
void *lib_ctx; /* Handle to HDCP 2.2 Trustzone library */
|
void *lib_ctx; /* Handle to HDCP 2.2 Trustzone library */
|
||||||
|
@ -99,18 +100,24 @@ static int hdmi_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data)
|
||||||
ctrl->wakeup_cmd = data->cmd;
|
ctrl->wakeup_cmd = data->cmd;
|
||||||
ctrl->timeout = data->timeout;
|
ctrl->timeout = data->timeout;
|
||||||
|
|
||||||
if (data->send_msg_len) {
|
mutex_lock(&ctrl->msg_lock);
|
||||||
|
if (data->send_msg_len) {
|
||||||
ctrl->send_msg_len = data->send_msg_len;
|
ctrl->send_msg_len = data->send_msg_len;
|
||||||
|
|
||||||
|
kzfree(ctrl->send_msg_buf);
|
||||||
|
|
||||||
ctrl->send_msg_buf = kzalloc(
|
ctrl->send_msg_buf = kzalloc(
|
||||||
data->send_msg_len, GFP_KERNEL);
|
data->send_msg_len, GFP_KERNEL);
|
||||||
|
|
||||||
if (!ctrl->send_msg_buf)
|
if (!ctrl->send_msg_buf) {
|
||||||
|
mutex_unlock(&ctrl->msg_lock);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(ctrl->send_msg_buf, data->send_msg_buf,
|
memcpy(ctrl->send_msg_buf, data->send_msg_buf,
|
||||||
ctrl->send_msg_len);
|
ctrl->send_msg_len);
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&ctrl->msg_lock);
|
||||||
|
|
||||||
switch (ctrl->wakeup_cmd) {
|
switch (ctrl->wakeup_cmd) {
|
||||||
case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE:
|
case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE:
|
||||||
|
@ -137,7 +144,7 @@ exit:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void hdmi_hdcp2p2_wakeup_lib(struct hdmi_hdcp2p2_ctrl *ctrl,
|
static inline int hdmi_hdcp2p2_wakeup_lib(struct hdmi_hdcp2p2_ctrl *ctrl,
|
||||||
struct hdcp_lib_wakeup_data *data)
|
struct hdcp_lib_wakeup_data *data)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
@ -149,6 +156,8 @@ static inline void hdmi_hdcp2p2_wakeup_lib(struct hdmi_hdcp2p2_ctrl *ctrl,
|
||||||
pr_err("error sending %s to lib\n",
|
pr_err("error sending %s to lib\n",
|
||||||
hdcp_lib_cmd_to_str(data->cmd));
|
hdcp_lib_cmd_to_str(data->cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hdmi_hdcp2p2_reset(struct hdmi_hdcp2p2_ctrl *ctrl)
|
static void hdmi_hdcp2p2_reset(struct hdmi_hdcp2p2_ctrl *ctrl)
|
||||||
|
@ -461,6 +470,8 @@ static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work)
|
||||||
struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
|
struct hdmi_hdcp2p2_ctrl *ctrl = container_of(work,
|
||||||
struct hdmi_hdcp2p2_ctrl, send_msg);
|
struct hdmi_hdcp2p2_ctrl, send_msg);
|
||||||
struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
|
struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
|
||||||
|
char *msg;
|
||||||
|
uint32_t msglen;
|
||||||
|
|
||||||
if (!ctrl) {
|
if (!ctrl) {
|
||||||
pr_err("invalid input\n");
|
pr_err("invalid input\n");
|
||||||
|
@ -476,9 +487,25 @@ static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work)
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&ctrl->msg_lock);
|
||||||
|
msglen = ctrl->send_msg_len;
|
||||||
|
|
||||||
|
if (!msglen) {
|
||||||
|
mutex_unlock(&ctrl->msg_lock);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = kzalloc(msglen, GFP_KERNEL);
|
||||||
|
if (!msg) {
|
||||||
|
mutex_unlock(&ctrl->msg_lock);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(msg, ctrl->send_msg_buf, msglen);
|
||||||
|
mutex_unlock(&ctrl->msg_lock);
|
||||||
|
|
||||||
/* Forward the message to the sink */
|
/* Forward the message to the sink */
|
||||||
rc = hdmi_hdcp2p2_ddc_write_message(ctrl,
|
rc = hdmi_hdcp2p2_ddc_write_message(ctrl, msg, (size_t)msglen);
|
||||||
ctrl->send_msg_buf, (size_t)ctrl->send_msg_len);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("Error sending msg to sink %d\n", rc);
|
pr_err("Error sending msg to sink %d\n", rc);
|
||||||
cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED;
|
cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED;
|
||||||
|
@ -486,7 +513,7 @@ static void hdmi_hdcp2p2_send_msg_work(struct kthread_work *work)
|
||||||
cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS;
|
cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS;
|
||||||
}
|
}
|
||||||
exit:
|
exit:
|
||||||
kzfree(ctrl->send_msg_buf);
|
kzfree(msg);
|
||||||
mutex_unlock(&ctrl->mutex);
|
mutex_unlock(&ctrl->mutex);
|
||||||
|
|
||||||
hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata);
|
hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata);
|
||||||
|
@ -755,7 +782,8 @@ static void hdmi_hdcp2p2_auth_work(struct kthread_work *work)
|
||||||
|
|
||||||
mutex_unlock(&ctrl->mutex);
|
mutex_unlock(&ctrl->mutex);
|
||||||
|
|
||||||
hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata);
|
if (hdmi_hdcp2p2_wakeup_lib(ctrl, &cdata))
|
||||||
|
hdmi_hdcp2p2_auth_failed(ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hdmi_hdcp2p2_deinit(void *input)
|
void hdmi_hdcp2p2_deinit(void *input)
|
||||||
|
@ -778,6 +806,8 @@ void hdmi_hdcp2p2_deinit(void *input)
|
||||||
&hdmi_hdcp2p2_fs_attr_group);
|
&hdmi_hdcp2p2_fs_attr_group);
|
||||||
|
|
||||||
mutex_destroy(&ctrl->mutex);
|
mutex_destroy(&ctrl->mutex);
|
||||||
|
mutex_destroy(&ctrl->msg_lock);
|
||||||
|
mutex_destroy(&ctrl->wakeup_mutex);
|
||||||
kfree(ctrl);
|
kfree(ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -832,6 +862,7 @@ void *hdmi_hdcp2p2_init(struct hdmi_hdcp_init_data *init_data)
|
||||||
|
|
||||||
ctrl->ops = &ops;
|
ctrl->ops = &ops;
|
||||||
mutex_init(&ctrl->mutex);
|
mutex_init(&ctrl->mutex);
|
||||||
|
mutex_init(&ctrl->msg_lock);
|
||||||
mutex_init(&ctrl->wakeup_mutex);
|
mutex_init(&ctrl->wakeup_mutex);
|
||||||
|
|
||||||
rc = hdcp_library_register(&ctrl->lib_ctx,
|
rc = hdcp_library_register(&ctrl->lib_ctx,
|
||||||
|
|
Loading…
Add table
Reference in a new issue