diff options
Diffstat (limited to 'drivers/video/tegra')
-rw-r--r-- | drivers/video/tegra/dc/nvhdcp.c | 28 |
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/video/tegra/dc/nvhdcp.c b/drivers/video/tegra/dc/nvhdcp.c index 3566e2bd33b5..b509a6c78499 100644 --- a/drivers/video/tegra/dc/nvhdcp.c +++ b/drivers/video/tegra/dc/nvhdcp.c @@ -78,6 +78,7 @@ struct tegra_nvhdcp { struct tegra_dc_hdmi_data *hdmi; struct workqueue_struct *downstream_wq; struct mutex lock; + struct mutex state_lock; struct miscdevice miscdev; char name[12]; unsigned id; @@ -980,7 +981,9 @@ static void nvhdcp_downstream_worker(struct work_struct *work) nvhdcp_vdbg("CRYPT enabled\n"); + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_LINK_VERIFY; + mutex_unlock(&nvhdcp->state_lock); nvhdcp_info("link verified!\n"); while (1) { @@ -1007,30 +1010,39 @@ failure: if(nvhdcp->fail_count > 5) { nvhdcp_err("nvhdcp failure - too many failures, giving up!\n"); } else { - nvhdcp_err("nvhdcp failure - renegotiating in 1 second\n"); - if (!nvhdcp_is_plugged(nvhdcp)) + if (!nvhdcp_is_plugged(nvhdcp)) { + nvhdcp_err("nvhdcp failure\n"); goto lost_hdmi; + } + nvhdcp_err("nvhdcp failure - renegotiating in 1 second\n"); queue_delayed_work(nvhdcp->downstream_wq, &nvhdcp->work, msecs_to_jiffies(1000)); } lost_hdmi: + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_UNAUTHENTICATED; + mutex_unlock(&nvhdcp->state_lock); hdcp_ctrl_run(hdmi, 0); err: mutex_unlock(&nvhdcp->lock); return; disable: + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_OFF; nvhdcp_set_plugged(nvhdcp, false); + mutex_unlock(&nvhdcp->state_lock); mutex_unlock(&nvhdcp->lock); return; } static int tegra_nvhdcp_on(struct tegra_nvhdcp *nvhdcp) { + mutex_lock(&nvhdcp->state_lock); + nvhdcp_set_plugged(nvhdcp, true); nvhdcp->state = STATE_UNAUTHENTICATED; + mutex_unlock(&nvhdcp->state_lock); if (nvhdcp_is_plugged(nvhdcp)) { nvhdcp->fail_count = 0; queue_delayed_work(nvhdcp->downstream_wq, &nvhdcp->work, @@ -1041,10 +1053,10 @@ static int tegra_nvhdcp_on(struct tegra_nvhdcp *nvhdcp) static int tegra_nvhdcp_off(struct tegra_nvhdcp *nvhdcp) { - mutex_lock(&nvhdcp->lock); + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_OFF; nvhdcp_set_plugged(nvhdcp, false); - mutex_unlock(&nvhdcp->lock); + mutex_unlock(&nvhdcp->state_lock); wake_up_interruptible(&wq_worker); flush_workqueue(nvhdcp->downstream_wq); return 0; @@ -1055,7 +1067,6 @@ void tegra_nvhdcp_set_plug(struct tegra_nvhdcp *nvhdcp, bool hpd) nvhdcp_debug("hdmi hotplug detected (hpd = %d)\n", hpd); if (hpd) { - nvhdcp_set_plugged(nvhdcp, true); tegra_nvhdcp_on(nvhdcp); } else { tegra_nvhdcp_off(nvhdcp); @@ -1080,9 +1091,9 @@ int tegra_nvhdcp_set_policy(struct tegra_nvhdcp *nvhdcp, int pol) static int tegra_nvhdcp_renegotiate(struct tegra_nvhdcp *nvhdcp) { - mutex_lock(&nvhdcp->lock); + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_RENEGOTIATE; - mutex_unlock(&nvhdcp->lock); + mutex_unlock(&nvhdcp->state_lock); tegra_nvhdcp_on(nvhdcp); return 0; } @@ -1201,6 +1212,7 @@ struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_dc_hdmi_data *hdmi, snprintf(nvhdcp->name, sizeof(nvhdcp->name), "nvhdcp%u", id); nvhdcp->hdmi = hdmi; mutex_init(&nvhdcp->lock); + mutex_init(&nvhdcp->state_lock); strlcpy(nvhdcp->info.type, nvhdcp->name, sizeof(nvhdcp->info.type)); nvhdcp->bus = bus; @@ -1224,7 +1236,9 @@ struct tegra_nvhdcp *tegra_nvhdcp_create(struct tegra_dc_hdmi_data *hdmi, goto free_nvhdcp; } + mutex_lock(&nvhdcp->state_lock); nvhdcp->state = STATE_UNAUTHENTICATED; + mutex_unlock(&nvhdcp->state_lock); nvhdcp->downstream_wq = create_singlethread_workqueue(nvhdcp->name); INIT_DELAYED_WORK(&nvhdcp->work, nvhdcp_downstream_worker); |