mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
video: rockchip: mpp: Use spinlock for queue->running_lock
reason: mpp_iommu_handle is called by irq for iommu, thus it cannot use mutex which might case sleep, thus use spinlock instead. Call trace: [ 71.047958 ] Call trace: [ 71.047974 ] dump_backtrace+0x0/0x160 [ 71.047988 ] show_stack+0x14/0x1c [ 71.048003 ] dump_stack+0xd0/0x120 [ 71.048018 ] ___might_sleep+0x1f4/0x204 [ 71.048032 ] __might_sleep+0x4c/0x80 [ 71.048045 ] __mutex_lock_common+0x60/0x1028 [ 71.048057 ] mutex_lock_nested+0x28/0x30 [ 71.048073 ] mpp_iommu_handle+0x44/0x1c8 [ 71.048088 ] report_iommu_fault+0x3c/0x198 [ 71.048102 ] rk_iommu_irq+0x2a4/0x3bc [ 71.048117 ] __handle_irq_event_percpu+0x114/0x3c4 [ 71.048131 ] handle_irq_event+0x5c/0xd0 [ 71.048143 ] handle_fasteoi_irq+0x124/0x220 [ 71.048156 ] __handle_domain_irq+0x9c/0xf4 [ 71.048169 ] gic_handle_irq+0x108/0x180 [ 71.048181 ] el1_irq+0xec/0x1a0 [ 71.048194 ] _raw_spin_unlock_irqrestore+0x3c/0x78 [ 71.048209 ] vop2_crtc_atomic_flush+0x1c78/0x202c [ 71.048223 ] drm_atomic_helper_commit_planes+0x1a4/0x210 [ 71.048238 ] rockchip_atomic_commit_complete+0x1a4/0x390 [ 71.048252 ] rockchip_drm_atomic_commit+0x22c/0x24c [ 71.048266 ] drm_mode_atomic_ioctl+0xa18/0xddc [ 71.048280 ] drm_ioctl+0x2d8/0x46c [ 71.048296 ] do_vfs_ioctl+0x4dc/0x794 [ 71.048308 ] __arm64_sys_ioctl+0x70/0x98 [ 71.048322 ] el0_svc_common+0xa0/0x18c [ 71.048335 ] el0_svc_handler+0x28/0x60 [ 71.048348 ] el0_svc+0x8/0xc Change-Id: Ie8e79995ec4bebf4ccbb509a57306541de861754 Signed-off-by: Ding Wei <leo.ding@rock-chips.com>
This commit is contained in:
@@ -138,11 +138,12 @@ mpp_taskqueue_get_pending_task(struct mpp_taskqueue *queue)
|
||||
static bool
|
||||
mpp_taskqueue_is_running(struct mpp_taskqueue *queue)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool flag;
|
||||
|
||||
mutex_lock(&queue->running_lock);
|
||||
spin_lock_irqsave(&queue->running_lock, flags);
|
||||
flag = !list_empty(&queue->running_list);
|
||||
mutex_unlock(&queue->running_lock);
|
||||
spin_unlock_irqrestore(&queue->running_lock, flags);
|
||||
|
||||
return flag;
|
||||
}
|
||||
@@ -151,10 +152,13 @@ static int
|
||||
mpp_taskqueue_pending_to_run(struct mpp_taskqueue *queue,
|
||||
struct mpp_task *task)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
mutex_lock(&queue->pending_lock);
|
||||
mutex_lock(&queue->running_lock);
|
||||
spin_lock_irqsave(&queue->running_lock, flags);
|
||||
list_move_tail(&task->queue_link, &queue->running_list);
|
||||
mutex_unlock(&queue->running_lock);
|
||||
spin_unlock_irqrestore(&queue->running_lock, flags);
|
||||
|
||||
mutex_unlock(&queue->pending_lock);
|
||||
|
||||
return 0;
|
||||
@@ -163,13 +167,14 @@ mpp_taskqueue_pending_to_run(struct mpp_taskqueue *queue,
|
||||
static struct mpp_task *
|
||||
mpp_taskqueue_get_running_task(struct mpp_taskqueue *queue)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct mpp_task *task = NULL;
|
||||
|
||||
mutex_lock(&queue->running_lock);
|
||||
spin_lock_irqsave(&queue->running_lock, flags);
|
||||
task = list_first_entry_or_null(&queue->running_list,
|
||||
struct mpp_task,
|
||||
queue_link);
|
||||
mutex_unlock(&queue->running_lock);
|
||||
spin_unlock_irqrestore(&queue->running_lock, flags);
|
||||
|
||||
return task;
|
||||
}
|
||||
@@ -178,12 +183,14 @@ static int
|
||||
mpp_taskqueue_pop_running(struct mpp_taskqueue *queue,
|
||||
struct mpp_task *task)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (!task->session || !task->session->mpp)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&queue->running_lock);
|
||||
spin_lock_irqsave(&queue->running_lock, flags);
|
||||
list_del_init(&task->queue_link);
|
||||
mutex_unlock(&queue->running_lock);
|
||||
spin_unlock_irqrestore(&queue->running_lock, flags);
|
||||
kref_put(&task->ref, mpp_free_task);
|
||||
|
||||
return 0;
|
||||
@@ -932,7 +939,7 @@ struct mpp_taskqueue *mpp_taskqueue_init(struct device *dev)
|
||||
|
||||
mutex_init(&queue->session_lock);
|
||||
mutex_init(&queue->pending_lock);
|
||||
mutex_init(&queue->running_lock);
|
||||
spin_lock_init(&queue->running_lock);
|
||||
mutex_init(&queue->mmu_lock);
|
||||
mutex_init(&queue->dev_lock);
|
||||
INIT_LIST_HEAD(&queue->session_attach);
|
||||
|
||||
@@ -430,7 +430,7 @@ struct mpp_taskqueue {
|
||||
struct mutex pending_lock;
|
||||
struct list_head pending_list;
|
||||
/* lock for running list */
|
||||
struct mutex running_lock;
|
||||
spinlock_t running_lock;
|
||||
struct list_head running_list;
|
||||
|
||||
/* point to MPP Service */
|
||||
|
||||
@@ -853,12 +853,13 @@ fail:
|
||||
static void *rkvdec_prepare_with_reset(struct mpp_dev *mpp,
|
||||
struct mpp_task *mpp_task)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct mpp_task *out_task = NULL;
|
||||
struct rkvdec_dev *dec = to_rkvdec_dev(mpp);
|
||||
|
||||
mutex_lock(&mpp->queue->running_lock);
|
||||
spin_lock_irqsave(&mpp->queue->running_lock, flags);
|
||||
out_task = list_empty(&mpp->queue->running_list) ? mpp_task : NULL;
|
||||
mutex_unlock(&mpp->queue->running_lock);
|
||||
spin_unlock_irqrestore(&mpp->queue->running_lock, flags);
|
||||
|
||||
if (out_task && !dec->had_reset) {
|
||||
struct rkvdec_task *task = to_rkvdec_task(out_task);
|
||||
|
||||
Reference in New Issue
Block a user