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:
-
nvhdcp->state == STATE_LINK_VERIFY
—> Not sure if this is set only if the worker thread is set. -
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.