summaryrefslogtreecommitdiff
path: root/drivers/video/tegra/dc
diff options
context:
space:
mode:
authorMatt Wagner <mwagner@nvidia.com>2012-08-02 15:49:50 -0700
committerLokesh Pathak <lpathak@nvidia.com>2012-08-09 08:29:46 -0700
commita7eb6356009a8e7423a200b49654a883117f282f (patch)
tree1d90c82b3149a129080b2f0ced5b1705d3682f8b /drivers/video/tegra/dc
parent57716f1d1f8381ff50874cb81c326e203909b4f3 (diff)
video: tegra: hdcp: Fix Locking Issue
Locking in nvhdcp was set up in such a way that we couldn't change the state of the HDMI plug while negotiating the HDCP connection. Another lock was added that is only taken when the state of the plug or hdcp session are changed. This enables correct failure if the plug is removed during negotiation. Bug 1024031 Reviewed-on: http://git-master/r/120546 (cherry picked from commit 51f746421b73f8f378bd7908b35fd6c79687e239) Change-Id: Id9a9b09f2cd03a1b51e7334391f35fc076a1e1dd Signed-off-by: Matt Wagner <mwagner@nvidia.com> Reviewed-on: http://git-master/r/121399 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Jon Mayo <jmayo@nvidia.com>
Diffstat (limited to 'drivers/video/tegra/dc')
-rw-r--r--drivers/video/tegra/dc/nvhdcp.c28
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);