From 01cb3026c647fecaf22449ed25548c590cd5c1c8 Mon Sep 17 00:00:00 2001 From: Ajay Singh Parmar Date: Thu, 20 Oct 2016 17:13:19 -0700 Subject: [PATCH] msm: mdss: hdcp2p2: fix deadlock during re-authentication Fix the dead lock happening during re-authentication where threads were waiting for each other during clearing the last session and starting a new one. Change-Id: Ife18adde8349acb92b22e228d0bbc18edbf2c90e Signed-off-by: Ajay Singh Parmar --- drivers/misc/hdcp.c | 89 ++++++++++++----- drivers/video/fbdev/msm/mdss_dp.c | 63 +++++++----- drivers/video/fbdev/msm/mdss_dp.h | 2 + drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c | 114 ++++++---------------- drivers/video/fbdev/msm/mdss_hdcp.h | 1 + include/linux/hdcp_qseecom.h | 3 + 6 files changed, 141 insertions(+), 131 deletions(-) diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c index 76add503b6b8..8b7c16e9175d 100644 --- a/drivers/misc/hdcp.c +++ b/drivers/misc/hdcp.c @@ -616,32 +616,53 @@ static int hdcp_lib_get_next_message(struct hdcp_lib_handle *handle, } } -static inline void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle, - struct hdmi_hdcp_wakeup_data *data) +static void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle, + struct hdmi_hdcp_wakeup_data *data) { - int rc = 0; + int rc = 0, i; - if (handle && handle->client_ops && handle->client_ops->wakeup && - data && (data->cmd != HDMI_HDCP_WKUP_CMD_INVALID)) { - data->abort_mask = REAUTH_REQ | LINK_INTEGRITY_FAILURE; + if (!handle || !handle->client_ops || !handle->client_ops->wakeup || + !data || (data->cmd == HDMI_HDCP_WKUP_CMD_INVALID)) + return; - 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) { - handle->last_msg = - hdcp_lib_get_next_message(handle, data); + data->abort_mask = REAUTH_REQ | LINK_INTEGRITY_FAILURE; - if (handle->last_msg > INVALID_MESSAGE_ID && - handle->last_msg < HDCP2P2_MAX_MESSAGES) - data->message_data = - &hdcp_msg_lookup[handle->last_msg]; + 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) { + handle->last_msg = hdcp_lib_get_next_message(handle, data); + + 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]; + + msg_num = data->message_data->num_messages; + msg = data->message_data->messages; + rx_status = data->message_data->rx_status; + + pr_debug("rxstatus 0x%x\n", rx_status); + pr_debug("%6s | %4s\n", "offset", "len"); + + for (i = 0; i < msg_num; i++) + pr_debug("%6x | %4d\n", + msg[i].offset, msg[i].length); } - - rc = handle->client_ops->wakeup(data); - if (rc) - pr_err("error sending %s to client\n", - hdmi_hdcp_cmd_to_str(data->cmd)); + } else { + 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)); } static inline void hdcp_lib_send_message(struct hdcp_lib_handle *handle) @@ -1486,6 +1507,7 @@ static int hdcp_lib_check_valid_state(struct hdcp_lib_handle *handle) if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_START) { if (!list_empty(&handle->worker.work_list)) { + pr_debug("error: queue not empty\n"); rc = -EBUSY; goto exit; } @@ -1543,9 +1565,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) handle->wakeup_cmd = data->cmd; handle->timeout_left = data->timeout; - pr_debug("%s, timeout left: %dms, tethered %d\n", - hdcp_lib_cmd_to_str(handle->wakeup_cmd), - handle->timeout_left, handle->tethered); + pr_debug("client->lib: %s\n", + hdcp_lib_cmd_to_str(handle->wakeup_cmd)); rc = hdcp_lib_check_valid_state(handle); if (rc) @@ -1599,6 +1620,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) break; case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED: case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED: + case HDCP_LIB_WKUP_CMD_LINK_FAILED: + handle->hdcp_state |= HDCP_STATE_ERROR; HDCP_LIB_EXECUTE(clean); break; case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS: @@ -1825,7 +1848,7 @@ static void hdcp_lib_clean(struct hdcp_lib_handle *handle) if (!handle) { pr_err("invalid input\n"); return; - }; + } hdcp_lib_txmtr_deinit(handle); if (!handle->legacy_app) @@ -1859,6 +1882,7 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) struct hdcp_rcvd_msg_rsp *rsp_buf; uint32_t msglen; char *msg = NULL; + char msg_name[50]; uint32_t message_id_bytes = 0; if (!handle || !handle->qseecom_handle || @@ -1907,8 +1931,11 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) mutex_unlock(&handle->msg_lock); - pr_debug("msg received: %s from sink\n", - hdcp_lib_message_name((int)msg[0])); + snprintf(msg_name, sizeof(msg_name), "%s: ", + hdcp_lib_message_name((int)msg[0])); + + print_hex_dump(KERN_DEBUG, msg_name, + DUMP_PREFIX_NONE, 16, 1, msg, msglen, false); /* send the message to QSEECOM */ req_buf = (struct hdcp_rcvd_msg_req *)(handle->qseecom_handle->sbuf); @@ -2026,6 +2053,16 @@ static void hdcp_lib_topology_work(struct kthread_work *work) return; } + if (atomic_read(&handle->hdcp_off)) { + pr_debug("invalid state: hdcp off\n"); + return; + } + + if (handle->hdcp_state & HDCP_STATE_ERROR) { + pr_debug("invalid state: hdcp error\n"); + return; + } + reinit_completion(&handle->topo_wait); timeout = wait_for_completion_timeout(&handle->topo_wait, HZ * 3); if (!timeout) { diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c index dea326a2fc76..dbaf3247e8bb 100644 --- a/drivers/video/fbdev/msm/mdss_dp.c +++ b/drivers/video/fbdev/msm/mdss_dp.c @@ -1620,22 +1620,18 @@ end: return rc; } -static void mdss_dp_hdcp_cb(void *ptr, enum hdcp_states status) +static void mdss_dp_hdcp_cb_work(struct work_struct *work) { - struct mdss_dp_drv_pdata *dp = ptr; + struct mdss_dp_drv_pdata *dp; + struct delayed_work *dw = to_delayed_work(work); struct hdcp_ops *ops; int rc = 0; - if (!dp) { - pr_debug("invalid input\n"); - return; - } + dp = container_of(dw, struct mdss_dp_drv_pdata, hdcp_cb_work); ops = dp->hdcp.ops; - mutex_lock(&dp->train_mutex); - - switch (status) { + switch (dp->hdcp_status) { case HDCP_STATE_AUTHENTICATED: pr_debug("hdcp authenticated\n"); dp->hdcp.auth_state = true; @@ -1658,8 +1654,20 @@ static void mdss_dp_hdcp_cb(void *ptr, enum hdcp_states status) default: break; } +} - mutex_unlock(&dp->train_mutex); +static void mdss_dp_hdcp_cb(void *ptr, enum hdcp_states status) +{ + struct mdss_dp_drv_pdata *dp = ptr; + + if (!dp) { + pr_err("invalid input\n"); + return; + } + + dp->hdcp_status = status; + + queue_delayed_work(dp->workq, &dp->hdcp_cb_work, HZ/4); } static int mdss_dp_hdcp_init(struct mdss_panel_data *pdata) @@ -1888,6 +1896,13 @@ static void mdss_dp_update_hdcp_info(struct mdss_dp_drv_pdata *dp) dp->hdcp.ops = ops; } +static inline bool dp_is_hdcp_enabled(struct mdss_dp_drv_pdata *dp_drv) +{ + return dp_drv->hdcp.feature_enabled && + (dp_drv->hdcp.hdcp1_present || dp_drv->hdcp.hdcp2_present) && + dp_drv->hdcp.ops; +} + static int mdss_dp_event_handler(struct mdss_panel_data *pdata, int event, void *arg) { @@ -1919,8 +1934,10 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata, rc = mdss_dp_off(pdata); break; case MDSS_EVENT_BLANK: - if (dp->hdcp.ops && dp->hdcp.ops->off) + if (dp_is_hdcp_enabled(dp) && dp->hdcp.ops->off) { + flush_delayed_work(&dp->hdcp_cb_work); dp->hdcp.ops->off(dp->hdcp.data); + } mdss_dp_mainlink_push_idle(pdata); break; @@ -2197,6 +2214,11 @@ irqreturn_t dp_isr(int irq, void *ptr) dp_aux_native_handler(dp, isr1); } + if (dp->hdcp.ops && dp->hdcp.ops->isr) { + if (dp->hdcp.ops->isr(dp->hdcp.data)) + pr_err("dp_hdcp_isr failed\n"); + } + return IRQ_HANDLED; } @@ -2211,6 +2233,7 @@ static int mdss_dp_event_setup(struct mdss_dp_drv_pdata *dp) } INIT_WORK(&dp->work, mdss_dp_event_work); + INIT_DELAYED_WORK(&dp->hdcp_cb_work, mdss_dp_hdcp_cb_work); return 0; } @@ -2434,8 +2457,6 @@ static void mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp) { int ret = 0; - pr_debug("enter: HPD IRQ High\n"); - dp->hpd_irq_on = true; mdss_dp_aux_parse_sink_status_field(dp); @@ -2523,6 +2544,12 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, dp_drv->alt_mode.dp_status.hpd_irq; if (dp_drv->alt_mode.dp_status.hpd_irq) { + pr_debug("Attention: hpd_irq high\n"); + + if (dp_drv->power_on && dp_drv->hdcp.ops && + dp_drv->hdcp.ops->cp_irq) + dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data); + mdss_dp_process_hpd_irq_high(dp_drv); break; } @@ -2552,9 +2579,6 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd, else dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE); - if (dp_drv->alt_mode.dp_status.hpd_irq && dp_drv->power_on && - dp_drv->hdcp.ops && dp_drv->hdcp.ops->isr) - dp_drv->hdcp.ops->isr(dp_drv->hdcp.data); break; case DP_VDM_STATUS: dp_drv->alt_mode.dp_status.response = *vdos; @@ -2770,13 +2794,6 @@ void *mdss_dp_get_hdcp_data(struct device *dev) return dp_drv->hdcp.data; } -static inline bool dp_is_hdcp_enabled(struct mdss_dp_drv_pdata *dp_drv) -{ - return dp_drv->hdcp.feature_enabled && - (dp_drv->hdcp.hdcp1_present || dp_drv->hdcp.hdcp2_present) && - dp_drv->hdcp.ops; -} - static inline bool dp_is_stream_shareable(struct mdss_dp_drv_pdata *dp_drv) { bool ret = 0; diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h index 0d4e8da90da5..cfacbfa1d413 100644 --- a/drivers/video/fbdev/msm/mdss_dp.h +++ b/drivers/video/fbdev/msm/mdss_dp.h @@ -484,6 +484,7 @@ struct mdss_dp_drv_pdata { /* event */ struct workqueue_struct *workq; struct work_struct work; + struct delayed_work hdcp_cb_work; u32 current_event; spinlock_t event_lock; spinlock_t lock; @@ -494,6 +495,7 @@ struct mdss_dp_drv_pdata { u32 vic; u32 new_vic; int fb_node; + int hdcp_status; struct dpcd_test_request test_data; struct dpcd_sink_count sink_count; diff --git a/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c b/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c index 3891806b09bb..a5146437978b 100644 --- a/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c +++ b/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c @@ -53,7 +53,6 @@ struct dp_hdcp2p2_ctrl { struct kthread_work send_msg; struct kthread_work recv_msg; struct kthread_work link; - struct kthread_work poll; char *msg_buf; uint32_t send_msg_len; /* length of all parameters in msg */ uint32_t timeout; @@ -67,26 +66,6 @@ struct dp_hdcp2p2_ctrl { bool polling; }; -static inline char *dp_hdcp_cmd_to_str(uint32_t cmd) -{ - switch (cmd) { - case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE: - return "HDMI_HDCP_WKUP_CMD_SEND_MESSAGE"; - case HDMI_HDCP_WKUP_CMD_RECV_MESSAGE: - return "HDMI_HDCP_WKUP_CMD_RECV_MESSAGE"; - case HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS: - return "HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS"; - case HDMI_HDCP_WKUP_CMD_STATUS_FAILED: - return "DP_HDCP_WKUP_CMD_STATUS_FAIL"; - case HDMI_HDCP_WKUP_CMD_LINK_POLL: - return "HDMI_HDCP_WKUP_CMD_LINK_POLL"; - case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: - return "HDMI_HDCP_WKUP_CMD_AUTHENTICATE"; - default: - return "???"; - } -} - static inline bool dp_hdcp2p2_is_valid_state(struct dp_hdcp2p2_ctrl *ctrl) { if (ctrl->wakeup_cmd == HDMI_HDCP_WKUP_CMD_AUTHENTICATE) @@ -193,7 +172,7 @@ static int dp_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) queue_kthread_work(&ctrl->worker, &ctrl->status); break; case HDMI_HDCP_WKUP_CMD_LINK_POLL: - queue_kthread_work(&ctrl->worker, &ctrl->poll); + ctrl->polling = true; break; case HDMI_HDCP_WKUP_CMD_AUTHENTICATE: queue_kthread_work(&ctrl->worker, &ctrl->auth); @@ -203,10 +182,11 @@ static int dp_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data) } exit: mutex_unlock(&ctrl->wakeup_mutex); + return 0; } -static inline int dp_hdcp2p2_wakeup_lib(struct dp_hdcp2p2_ctrl *ctrl, +static inline void dp_hdcp2p2_wakeup_lib(struct dp_hdcp2p2_ctrl *ctrl, struct hdcp_lib_wakeup_data *data) { int rc = 0; @@ -218,8 +198,6 @@ static inline int dp_hdcp2p2_wakeup_lib(struct dp_hdcp2p2_ctrl *ctrl, pr_err("error sending %s to lib\n", hdcp_lib_cmd_to_str(data->cmd)); } - - return rc; } static void dp_hdcp2p2_reset(struct dp_hdcp2p2_ctrl *ctrl) @@ -339,8 +317,6 @@ static void dp_hdcp2p2_auth_failed(struct dp_hdcp2p2_ctrl *ctrl) return; } - atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL); - /* notify DP about HDCP failure */ ctrl->init_data.notify_status(ctrl->init_data.cb_data, HDCP_STATE_AUTH_FAIL); @@ -349,8 +325,7 @@ static void dp_hdcp2p2_auth_failed(struct dp_hdcp2p2_ctrl *ctrl) static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl, u8 *buf, int size, int offset, u32 timeout) { - int rc, max_size = 16, read_size, len = size; - u8 *buf_start = buf; + int rc, max_size = 16, read_size; if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { pr_err("hdcp is off\n"); @@ -378,8 +353,6 @@ static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl, size -= read_size; } while (size > 0); - print_hex_dump(KERN_DEBUG, "hdcp2p2: ", DUMP_PREFIX_NONE, - 16, 1, buf_start, len, false); return rc; } @@ -550,7 +523,6 @@ exit: static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work) { - int rc = 0; struct hdcp_lib_wakeup_data cdata = { HDCP_LIB_WKUP_CMD_INVALID }; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, recv_msg); @@ -559,44 +531,24 @@ static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work) if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) { pr_err("hdcp is off\n"); - goto exit; + return; } - if (ctrl->sink_rx_status & ctrl->abort_mask) { - pr_err("reauth or Link fail triggered by sink\n"); + if (ctrl->rx_status) { + if (!ctrl->cp_irq_done) { + pr_debug("waiting for CP_IRQ\n"); + ctrl->polling = true; + return; + } - ctrl->sink_rx_status = 0; - rc = -ENOLINK; - cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; - - goto exit; - } - - if (ctrl->rx_status && !ctrl->sink_rx_status) { - pr_debug("Recv msg for RxStatus, but no CP_IRQ yet\n"); - ctrl->polling = true; - goto exit; + if (ctrl->rx_status & ctrl->sink_rx_status) { + ctrl->cp_irq_done = false; + ctrl->sink_rx_status = 0; + ctrl->rx_status = 0; + } } dp_hdcp2p2_get_msg_from_sink(ctrl); - - return; -exit: - if (rc) - dp_hdcp2p2_wakeup_lib(ctrl, &cdata); -} - -static void dp_hdcp2p2_poll_work(struct kthread_work *work) -{ - struct dp_hdcp2p2_ctrl *ctrl = container_of(work, - struct dp_hdcp2p2_ctrl, poll); - - if (ctrl->cp_irq_done) { - ctrl->cp_irq_done = false; - dp_hdcp2p2_get_msg_from_sink(ctrl); - } else { - ctrl->polling = true; - } } static void dp_hdcp2p2_auth_status_work(struct kthread_work *work) @@ -645,44 +597,45 @@ static void dp_hdcp2p2_link_work(struct kthread_work *work) if (rc) { pr_err("failed to read rx status\n"); - cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; + cdata.cmd = HDCP_LIB_WKUP_CMD_LINK_FAILED; + atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL); goto exit; } if (ctrl->sink_rx_status & ctrl->abort_mask) { - pr_err("reauth or Link fail triggered by sink\n"); + if (ctrl->sink_rx_status & BIT(3)) + pr_err("reauth_req set by sink\n"); + + if (ctrl->sink_rx_status & BIT(4)) + pr_err("link failure reported by sink\n"); ctrl->sink_rx_status = 0; ctrl->rx_status = 0; rc = -ENOLINK; - cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; + + cdata.cmd = HDCP_LIB_WKUP_CMD_LINK_FAILED; + atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL); goto exit; } - /* if polling, get message from sink else let polling start */ if (ctrl->polling && (ctrl->sink_rx_status & ctrl->rx_status)) { ctrl->sink_rx_status = 0; ctrl->rx_status = 0; - rc = dp_hdcp2p2_get_msg_from_sink(ctrl); + dp_hdcp2p2_get_msg_from_sink(ctrl); ctrl->polling = false; } else { ctrl->cp_irq_done = true; } exit: - dp_hdcp2p2_wakeup_lib(ctrl, &cdata); - - if (rc) { - dp_hdcp2p2_auth_failed(ctrl); - return; - } + if (rc) + dp_hdcp2p2_wakeup_lib(ctrl, &cdata); } static void dp_hdcp2p2_auth_work(struct kthread_work *work) { - int rc = 0; struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID}; struct dp_hdcp2p2_ctrl *ctrl = container_of(work, struct dp_hdcp2p2_ctrl, auth); @@ -694,12 +647,10 @@ static void dp_hdcp2p2_auth_work(struct kthread_work *work) else cdata.cmd = HDCP_LIB_WKUP_CMD_STOP; - rc = dp_hdcp2p2_wakeup_lib(ctrl, &cdata); - if (rc) - dp_hdcp2p2_auth_failed(ctrl); + dp_hdcp2p2_wakeup_lib(ctrl, &cdata); } -static int dp_hdcp2p2_isr(void *input) +static int dp_hdcp2p2_cp_irq(void *input) { struct dp_hdcp2p2_ctrl *ctrl = input; @@ -748,7 +699,7 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data) .authenticate = dp_hdcp2p2_authenticate, .feature_supported = dp_hdcp2p2_feature_supported, .off = dp_hdcp2p2_off, - .isr = dp_hdcp2p2_isr + .cp_irq = dp_hdcp2p2_cp_irq, }; static struct hdcp_client_ops client_ops = { @@ -806,7 +757,6 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data) init_kthread_work(&ctrl->recv_msg, dp_hdcp2p2_recv_msg_work); init_kthread_work(&ctrl->status, dp_hdcp2p2_auth_status_work); init_kthread_work(&ctrl->link, dp_hdcp2p2_link_work); - init_kthread_work(&ctrl->poll, dp_hdcp2p2_poll_work); ctrl->thread = kthread_run(kthread_worker_fn, &ctrl->worker, "dp_hdcp2p2"); diff --git a/drivers/video/fbdev/msm/mdss_hdcp.h b/drivers/video/fbdev/msm/mdss_hdcp.h index d373d22384e8..6e347a867366 100644 --- a/drivers/video/fbdev/msm/mdss_hdcp.h +++ b/drivers/video/fbdev/msm/mdss_hdcp.h @@ -55,6 +55,7 @@ struct hdcp_init_data { struct hdcp_ops { int (*isr)(void *ptr); + int (*cp_irq)(void *ptr); int (*reauthenticate)(void *input); int (*authenticate)(void *hdcp_ctrl); bool (*feature_supported)(void *input); diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h index f66264bc935a..6ad79378737e 100644 --- a/include/linux/hdcp_qseecom.h +++ b/include/linux/hdcp_qseecom.h @@ -26,6 +26,7 @@ enum hdcp_lib_wakeup_cmd { HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED, HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT, HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE, + HDCP_LIB_WKUP_CMD_LINK_FAILED, }; enum hdmi_hdcp_wakeup_cmd { @@ -106,6 +107,8 @@ static inline char *hdcp_lib_cmd_to_str(uint32_t cmd) return "HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT"; case HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE: return "HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE"; + case HDCP_LIB_WKUP_CMD_LINK_FAILED: + return "HDCP_LIB_WKUP_CMD_LINK_FAILED"; default: return "???"; }