disp: msm: hdcp: abort queued tasks while processing PM suspend
During suspend, there might be a chance that lib auth work is queued but not yet started. So during pm cycle it might start execution before host_init which can lead to noc error while accessing dp_aux registers. To prevent that set abort flag to abort lib auth work and set interrupts before host_deinit. Change-Id: Ie2c3ac9b0846644d3c2b37f410c341659b030c16 Signed-off-by: Rajat Gupta <rajatgu@codeaurora.org> Signed-off-by: Tatenda Chipeperekwa <tatendac@codeaurora.org>
This commit is contained in:

committed by
Tatenda Chipeperekwa

parent
54365213d1
commit
0e1496c718
@@ -513,6 +513,22 @@ static void dp_display_hdcp_process_state(struct dp_display_private *dp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dp_display_abort_hdcp(struct dp_display_private *dp,
|
||||||
|
bool abort)
|
||||||
|
{
|
||||||
|
u8 i = HDCP_VERSION_2P2;
|
||||||
|
struct dp_hdcp_dev *dev = NULL;
|
||||||
|
|
||||||
|
while (i) {
|
||||||
|
dev = &dp->hdcp.dev[i];
|
||||||
|
i >>= 1;
|
||||||
|
if (!(dp->hdcp.source_cap & dev->ver))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dev->ops->abort(dev->fd, abort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void dp_display_hdcp_cb_work(struct work_struct *work)
|
static void dp_display_hdcp_cb_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct dp_display_private *dp;
|
struct dp_display_private *dp;
|
||||||
@@ -894,6 +910,7 @@ static void dp_display_host_init(struct dp_display_private *dp)
|
|||||||
dp->hpd->host_init(dp->hpd, &dp->catalog->hpd);
|
dp->hpd->host_init(dp->hpd, &dp->catalog->hpd);
|
||||||
dp->ctrl->init(dp->ctrl, flip, reset);
|
dp->ctrl->init(dp->ctrl, flip, reset);
|
||||||
enable_irq(dp->irq);
|
enable_irq(dp->irq);
|
||||||
|
dp_display_abort_hdcp(dp, false);
|
||||||
|
|
||||||
dp_display_state_add(DP_STATE_INITIALIZED);
|
dp_display_state_add(DP_STATE_INITIALIZED);
|
||||||
|
|
||||||
@@ -971,6 +988,7 @@ static void dp_display_host_deinit(struct dp_display_private *dp)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dp_display_abort_hdcp(dp, true);
|
||||||
dp->ctrl->deinit(dp->ctrl);
|
dp->ctrl->deinit(dp->ctrl);
|
||||||
dp->hpd->host_deinit(dp->hpd, &dp->catalog->hpd);
|
dp->hpd->host_deinit(dp->hpd, &dp->catalog->hpd);
|
||||||
dp->power->deinit(dp->power);
|
dp->power->deinit(dp->power);
|
||||||
|
@@ -31,6 +31,7 @@ struct dp_hdcp2p2_ctrl {
|
|||||||
DECLARE_KFIFO(cmd_q, enum hdcp_transport_wakeup_cmd, 8);
|
DECLARE_KFIFO(cmd_q, enum hdcp_transport_wakeup_cmd, 8);
|
||||||
wait_queue_head_t wait_q;
|
wait_queue_head_t wait_q;
|
||||||
atomic_t auth_state;
|
atomic_t auth_state;
|
||||||
|
atomic_t abort;
|
||||||
enum dp_hdcp2p2_sink_status sink_status; /* Is sink connected */
|
enum dp_hdcp2p2_sink_status sink_status; /* Is sink connected */
|
||||||
struct dp_hdcp2p2_interrupts *intr;
|
struct dp_hdcp2p2_interrupts *intr;
|
||||||
struct sde_hdcp_init_data init_data;
|
struct sde_hdcp_init_data init_data;
|
||||||
@@ -151,6 +152,9 @@ static void dp_hdcp2p2_set_interrupts(struct dp_hdcp2p2_ctrl *ctrl, bool enable)
|
|||||||
void __iomem *base = ctrl->init_data.dp_ahb->base;
|
void __iomem *base = ctrl->init_data.dp_ahb->base;
|
||||||
struct dp_hdcp2p2_interrupts *intr = ctrl->intr;
|
struct dp_hdcp2p2_interrupts *intr = ctrl->intr;
|
||||||
|
|
||||||
|
if (atomic_read(&ctrl->abort))
|
||||||
|
return;
|
||||||
|
|
||||||
while (intr && intr->reg) {
|
while (intr && intr->reg) {
|
||||||
struct dp_hdcp2p2_int_set *int_set = intr->int_set;
|
struct dp_hdcp2p2_int_set *int_set = intr->int_set;
|
||||||
u32 interrupts = 0;
|
u32 interrupts = 0;
|
||||||
@@ -882,6 +886,13 @@ static int dp_hdcp2p2_main(void *data)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dp_hdcp2p2_abort(void *input, bool abort)
|
||||||
|
{
|
||||||
|
struct dp_hdcp2p2_ctrl *ctrl = input;
|
||||||
|
|
||||||
|
atomic_set(&ctrl->abort, abort);
|
||||||
|
}
|
||||||
|
|
||||||
void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data)
|
void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
@@ -896,6 +907,7 @@ void *sde_dp_hdcp2p2_init(struct sde_hdcp_init_data *init_data)
|
|||||||
.set_mode = dp_hdcp2p2_register,
|
.set_mode = dp_hdcp2p2_register,
|
||||||
.on = dp_hdcp2p2_on,
|
.on = dp_hdcp2p2_on,
|
||||||
.off = dp_hdcp2p2_off,
|
.off = dp_hdcp2p2_off,
|
||||||
|
.abort = dp_hdcp2p2_abort,
|
||||||
.cp_irq = dp_hdcp2p2_cp_irq,
|
.cp_irq = dp_hdcp2p2_cp_irq,
|
||||||
.register_streams = dp_hdcp2p2_register_streams,
|
.register_streams = dp_hdcp2p2_register_streams,
|
||||||
.deregister_streams = dp_hdcp2p2_deregister_streams,
|
.deregister_streams = dp_hdcp2p2_deregister_streams,
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012, 2014-2019, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2012, 2014-2020, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SDE_HDCP_H__
|
#ifndef __SDE_HDCP_H__
|
||||||
@@ -81,6 +81,7 @@ struct sde_hdcp_ops {
|
|||||||
bool (*feature_supported)(void *input);
|
bool (*feature_supported)(void *input);
|
||||||
void (*force_encryption)(void *input, bool enable);
|
void (*force_encryption)(void *input, bool enable);
|
||||||
bool (*sink_support)(void *input);
|
bool (*sink_support)(void *input);
|
||||||
|
void (*abort)(void *input, bool abort);
|
||||||
int (*set_mode)(void *input, bool mst_enabled);
|
int (*set_mode)(void *input, bool mst_enabled);
|
||||||
int (*on)(void *input);
|
int (*on)(void *input);
|
||||||
void (*off)(void *hdcp_ctrl);
|
void (*off)(void *hdcp_ctrl);
|
||||||
|
@@ -207,6 +207,7 @@ struct sde_hdcp_1x {
|
|||||||
bool reauth;
|
bool reauth;
|
||||||
bool ksv_ready;
|
bool ksv_ready;
|
||||||
bool force_encryption;
|
bool force_encryption;
|
||||||
|
atomic_t abort;
|
||||||
enum sde_hdcp_state hdcp_state;
|
enum sde_hdcp_state hdcp_state;
|
||||||
struct HDCP_V2V1_MSG_TOPOLOGY current_tp;
|
struct HDCP_V2V1_MSG_TOPOLOGY current_tp;
|
||||||
struct delayed_work hdcp_auth_work;
|
struct delayed_work hdcp_auth_work;
|
||||||
@@ -1040,7 +1041,7 @@ static void sde_hdcp_1x_update_auth_status(struct sde_hdcp_1x *hdcp)
|
|||||||
|
|
||||||
static void sde_hdcp_1x_auth_work(struct work_struct *work)
|
static void sde_hdcp_1x_auth_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc = 0;
|
||||||
struct delayed_work *dw = to_delayed_work(work);
|
struct delayed_work *dw = to_delayed_work(work);
|
||||||
struct sde_hdcp_1x *hdcp = container_of(dw,
|
struct sde_hdcp_1x *hdcp = container_of(dw,
|
||||||
struct sde_hdcp_1x, hdcp_auth_work);
|
struct sde_hdcp_1x, hdcp_auth_work);
|
||||||
@@ -1056,6 +1057,9 @@ static void sde_hdcp_1x_auth_work(struct work_struct *work)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (atomic_read(&hdcp->abort))
|
||||||
|
goto end;
|
||||||
|
|
||||||
hdcp->sink_r0_ready = false;
|
hdcp->sink_r0_ready = false;
|
||||||
hdcp->reauth = false;
|
hdcp->reauth = false;
|
||||||
hdcp->ksv_ready = false;
|
hdcp->ksv_ready = false;
|
||||||
@@ -1484,6 +1488,15 @@ irq_not_handled:
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sde_hdcp_1x_abort(void *data, bool abort)
|
||||||
|
{
|
||||||
|
struct sde_hdcp_1x *hdcp = data;
|
||||||
|
|
||||||
|
atomic_set(&hdcp->abort, abort);
|
||||||
|
cancel_delayed_work_sync(&hdcp->hdcp_auth_work);
|
||||||
|
flush_workqueue(hdcp->workq);
|
||||||
|
}
|
||||||
|
|
||||||
void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data)
|
void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data)
|
||||||
{
|
{
|
||||||
struct sde_hdcp_1x *hdcp = NULL;
|
struct sde_hdcp_1x *hdcp = NULL;
|
||||||
@@ -1496,6 +1509,7 @@ void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data)
|
|||||||
.feature_supported = sde_hdcp_1x_feature_supported,
|
.feature_supported = sde_hdcp_1x_feature_supported,
|
||||||
.force_encryption = sde_hdcp_1x_force_encryption,
|
.force_encryption = sde_hdcp_1x_force_encryption,
|
||||||
.sink_support = sde_hdcp_1x_sink_support,
|
.sink_support = sde_hdcp_1x_sink_support,
|
||||||
|
.abort = sde_hdcp_1x_abort,
|
||||||
.off = sde_hdcp_1x_off
|
.off = sde_hdcp_1x_off
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user