From 4e57d971b6cfd48750e2a1a3cb31313726f4c057 Mon Sep 17 00:00:00 2001 From: Ding Wei Date: Tue, 19 Oct 2021 10:11:58 +0800 Subject: [PATCH] video: rockchip: mpp: rcu_read_lock/unlock -> device_links_read_lock/unlock reason: 1. might_sleep is called by pm_runtime_xx, thus, it cannot covered by rcu_read_lock/unlock which is atomic context. 2. it need use device_links_read_lock/unlock when meets dev->links.suppliers. relative call trace: [ 1804.810833 ] mpp_rkvdec2 fdf80200.rkvdec: resetting... [ 1804.811030 ] BUG: sleeping function called from invalid context at drivers/base/power/runtime.c:1005 [ 1804.811090 ] in_atomic(): 0, irqs_disabled(): 0, pid: 3043, name: [ 1804.811149 ] CPU: 2 PID: 3043 Comm: rkvdec Tainted: G W 4.19.206 #215 [ 1804.811192 ] Hardware name: Rockchip RK3566 EVB1 DDR4 V10 Board (DT) [ 1804.811236 ] Call trace: [ 1804.811316 ] dump_backtrace+0x0/0x178 [ 1804.811366 ] show_stack+0x14/0x20 [ 1804.811421 ] dump_stack+0x94/0xb4 [ 1804.811474 ] ___might_sleep+0xf0/0x118 [ 1804.811505 ] __might_sleep+0x50/0x88 [ 1804.811535 ] __pm_runtime_idle+0x9c/0xa0 [ 1804.811681 ] mpp_iommu_refresh+0x54/0xd0 [rk_vcodec] [ 1804.811789 ] rkvdec2_link_reset+0xac/0x128 [rk_vcodec] [ 1804.811873 ] rkvdec2_link_isr+0xe4/0x6d0 [rk_vcodec] [ 1804.811995 ] rkvdec2_link_worker+0xc0/0xb08 [rk_vcodec] [ 1804.812053 ] kthread_worker_fn+0xe8/0x1f8 [ 1804.812099 ] kthread+0x138/0x168 [ 1804.812130 ] ret_from_fork+0x10/0x18 [ 1804.812243 ] mpp_rkvdec2 fdf80200.rkvdec: reset done Change-Id: Id8453483b021a092e298736640e725a8e48c862b Signed-off-by: Ding Wei --- drivers/video/rockchip/mpp/mpp_iommu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/video/rockchip/mpp/mpp_iommu.c b/drivers/video/rockchip/mpp/mpp_iommu.c index 4f50641e34f5..2e035aa5f8af 100644 --- a/drivers/video/rockchip/mpp/mpp_iommu.c +++ b/drivers/video/rockchip/mpp/mpp_iommu.c @@ -20,6 +20,7 @@ #include #include #include +#include "../../../base/base.h" #include "mpp_debug.h" #include "mpp_iommu.h" @@ -459,12 +460,12 @@ int mpp_iommu_remove(struct mpp_iommu_info *info) int mpp_iommu_refresh(struct mpp_iommu_info *info, struct device *dev) { - int i; + int idx, i; int usage_count; struct device_link *link; struct device *iommu_dev = &info->pdev->dev; - rcu_read_lock(); + idx = device_links_read_lock(); usage_count = atomic_read(&iommu_dev->power.usage_count); list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) { @@ -477,7 +478,7 @@ int mpp_iommu_refresh(struct mpp_iommu_info *info, struct device *dev) pm_runtime_get_sync(link->supplier); } - rcu_read_unlock(); + device_links_read_unlock(idx); return 0; }