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 <leo.ding@rock-chips.com>
This commit is contained in:
Ding Wei
2021-10-19 10:11:58 +08:00
committed by Tao Huang
parent 85546e9ff7
commit 4e57d971b6

View File

@@ -20,6 +20,7 @@
#include <linux/kref.h>
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#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;
}