Lockdep: registering non-static key message displayed in tegra_nvhdcp_off

Below lockdep warning is appearing when CONFIG_LOCKDEP along with couple of other kernel debug options are turned on.

[    4.055788] INFO: trying to register non-static key.
[    4.055803] the code is fine but needs lockdep annotation.
[    4.055816] turning off the locking correctness validator.
[    4.055835] CPU: 0 PID: 4 Comm: kworker/0:0 Tainted: G        W       4.9.140-rt94-r32.4.2-tegra-RedHawk-7.5.3-r599-nvidia-import-r32. #2
[    4.055848] Hardware name: NVIDIA Jetson Xavier NX Developer Kit (DT)
[    4.055887] Workqueue: events tegra_hdmi_hpd_worker
[    4.055900] Call trace:
[    4.055931] [<ffffff800808bfd0>] dump_backtrace+0x0/0x1b0
[    4.055946] [<ffffff800808c2bc>] show_stack+0x24/0x30
[    4.055953] [<ffffff8008443a00>] dump_stack+0x88/0xb0
[    4.055961] [<ffffff8008147474>] register_lock_class+0x394/0x5f0
[    4.055966] [<ffffff80081486ac>] __lock_acquire.isra.12+0x6c/0xa10
[    4.055971] [<ffffff800814949c>] lock_acquire+0xf4/0x238
[    4.055976] [<ffffff80080fac44>] flush_work+0x44/0x2a0
[    4.055981] [<ffffff80080fc720>] __cancel_work_timer+0xa0/0x188
[    4.055986] [<ffffff80080fc85c>] cancel_delayed_work_sync+0x24/0x30
[    4.055993] [<ffffff80085f484c>] tegra_nvhdcp_off+0x5c/0x70
[    4.055998] [<ffffff80085fa60c>] tegra_nvhdcp_set_plug+0x44/0xb8
[    4.056008] [<ffffff8008666a44>] tegra_dc_hdmi_disable+0x25c/0x270
[    4.056014] [<ffffff80085cabb8>] _tegra_dc_controller_disable+0xa0/0x640
[    4.056019] [<ffffff80085cb19c>] _tegra_dc_disable+0x44/0xd0
[    4.056023] [<ffffff80085cb89c>] tegra_dc_disable_irq_ops+0x2e4/0x360
[    4.056028] [<ffffff80085ce234>] tegra_dc_disable+0x2c/0x60
[    4.056034] [<ffffff80086c4abc>] tegra_fb_blank+0x6c/0x218
[    4.056041] [<ffffff8008509d48>] fb_blank+0x60/0xc0
[    4.056053] [<ffffff80086c5980>] tegra_fbcon_set_fb_mode+0x40/0xa0
[    4.056058] [<ffffff80086c5b64>] tegra_fb_update_monspecs+0x184/0x318
[    4.056065] [<ffffff800865e2f8>] tegra_hdmi_hotplug_notify+0x70/0xd0
[    4.056068] [<ffffff800865ff34>] tegra_hdmi_edid_eld_setup+0x1b4/0x240
[    4.056073] [<ffffff8008662520>] tegra_hdmi_hpd_worker+0x160/0x360
[    4.056080] [<ffffff80080fb56c>] process_one_work+0x2cc/0x710
[    4.056086] [<ffffff80080fba0c>] worker_thread+0x5c/0x480
[    4.056093] [<ffffff8008102ca4>] kthread+0xf4/0xf8
[    4.056098] [<ffffff8008083320>] ret_from_fork+0x10/0x30

The tegra_nvhdcp_off() tries to cancel_delayed_work_sync() which may or may not be initialized. The worker function is either nvhdcp_downstream_worker() or nvhdcp2_downstream_worker() initialized using INIT_DELAYED_WORK() in tegra_nvhdcp_on().

I have got a workaround in place but dunno if there’s a better approach to this. My patch is as below:

Index: nx/nvidia/drivers/video/tegra/dc/hdcp/hdmihdcp.c
===================================================================
--- nx.orig/nvidia/drivers/video/tegra/dc/hdcp/hdmihdcp.c
+++ nx/nvidia/drivers/video/tegra/dc/hdcp/hdmihdcp.c
@@ -2203,6 +2203,9 @@ static int tegra_nvhdcp_on(struct tegra_
 		}
 		queue_delayed_work(nvhdcp->downstream_wq, &nvhdcp->work,
 				msecs_to_jiffies(delay));
+		mutex_lock(&nvhdcp->lock);
+		nvhdcp->worker_started = 1;
+		mutex_unlock(&nvhdcp->lock);
 	}
 	return 0;
 }
@@ -2214,7 +2217,12 @@ static int tegra_nvhdcp_off(struct tegra
 	nvhdcp_set_plugged(nvhdcp, false);
 	mutex_unlock(&nvhdcp->lock);
 	wake_up_interruptible(&wq_worker);
-	cancel_delayed_work_sync(&nvhdcp->work);
+	if (nvhdcp->worker_started) {
+		mutex_lock(&nvhdcp->lock);
+		nvhdcp->worker_started = 0;
+		mutex_unlock(&nvhdcp->lock);
+		cancel_delayed_work_sync(&nvhdcp->work);
+	}
 	return 0;
 }
 
Index: nx/nvidia/drivers/video/tegra/dc/hdcp/hdmihdcp.h
===================================================================
--- nx.orig/nvidia/drivers/video/tegra/dc/hdcp/hdmihdcp.h
+++ nx/nvidia/drivers/video/tegra/dc/hdcp/hdmihdcp.h
@@ -57,6 +57,7 @@ struct tegra_nvhdcp {
 	bool				plugged; /* true if hotplug detected */
 	atomic_t			policy; /* set policy */
 	enum tegra_nvhdcp_state		state; /* STATE_xxx */
+	int				worker_started; /* CCUR: check if worker started */
 	struct i2c_client		*client;
 	struct i2c_board_info		info;
 	int				bus;

I think I may be able to use couple other conditions to decide whether to call cancel_delayed_work_sync(&nvhdcp->work);, but I was not sure about. Those conditions would be:

  1. nvhdcp->state == STATE_LINK_VERIFY —> Not sure if this is set only if the worker thread is set.
  2. nvhdcp->hdcp22 —> This value is set only when we are about to initialize the work, but the values that it
    is set to are HDCP22_PROTOCOL(1) or HDCP1X_PROTOCOL (0), so that means no
    matter what the initial value of nvhdcp->hdcp22’s is HDCP1X_PROTOCOL. This
    may be a desired way, hence didn’t touch it to use values like 2 and 1, resp.

Please let me know if there’s another and a better solution for this.

Hi,

We don’t support hdcp on any of jetson platforms now.
I would let other forum user to share their experience.

Hello @WayneWWW,

Thanks for the reply but I am confused here.

Concurrent’s RedHawk kernel uses the same config options (and later adds our own) as L4T kernel. I see that CONFIG_TEGRA_HDMIHDCP is enabled in all the Jetson platforms’ config in JetPack 4.4 i.e. L4T R32.4.3. This config option depends on CONFIG_TEGRA_HDMI2_0 which is also enabled.

Now, if no jetson platform supports HDCP then it should be disabled (=n) by NVIDIA and also, we will disable it in our kernels. This is not a requirement for RedHawk.