diff options
author | Christian König <christian.koenig@amd.com> | 2018-11-02 09:46:24 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2018-11-05 15:49:38 -0500 |
commit | 2383a767c0ca06f96534456d8313909017c6c8d0 (patch) | |
tree | c0c2a8f05d40d1b7ad112f8654847acf86b28413 | |
parent | f6cffc0d4d3c20bd5c9b3c825448016d7388b43a (diff) |
drm/amdkfd: fix interrupt spin lock
Vega10 has multiple interrupt rings, so this can be called from multiple
calles at the same time resulting in:
[ 71.779334] ================================
[ 71.779406] WARNING: inconsistent lock state
[ 71.779478] 4.19.0-rc1+ #44 Tainted: G W
[ 71.779565] --------------------------------
[ 71.779637] inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage.
[ 71.779740] kworker/6:1/120 [HC0[0]:SC0[0]:HE1:SE1] takes:
[ 71.779832] 00000000ad761971 (&(&kfd->interrupt_lock)->rlock){?...},
at: kgd2kfd_interrupt+0x75/0x100 [amdgpu]
[ 71.780058] {IN-HARDIRQ-W} state was registered at:
[ 71.780115] _raw_spin_lock+0x2c/0x40
[ 71.780180] kgd2kfd_interrupt+0x75/0x100 [amdgpu]
[ 71.780248] amdgpu_irq_callback+0x6c/0x150 [amdgpu]
[ 71.780315] amdgpu_ih_process+0x88/0x100 [amdgpu]
[ 71.780380] amdgpu_irq_handler+0x20/0x40 [amdgpu]
[ 71.780409] __handle_irq_event_percpu+0x49/0x2a0
[ 71.780436] handle_irq_event_percpu+0x30/0x70
[ 71.780461] handle_irq_event+0x37/0x60
[ 71.780484] handle_edge_irq+0x83/0x1b0
[ 71.780506] handle_irq+0x1f/0x30
[ 71.780526] do_IRQ+0x53/0x110
[ 71.780544] ret_from_intr+0x0/0x22
[ 71.780566] cpuidle_enter_state+0xaa/0x330
[ 71.780591] do_idle+0x203/0x280
[ 71.780610] cpu_startup_entry+0x6f/0x80
[ 71.780634] start_secondary+0x1b0/0x200
[ 71.780657] secondary_startup_64+0xa4/0xb0
Fix this by always using irq save spin locks.
Signed-off-by: Christian König <christian.koenig@amd.com>
Acked-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_device.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index d7e0f41f8edc..c004647c8cb4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c | |||
@@ -682,6 +682,7 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) | |||
682 | { | 682 | { |
683 | uint32_t patched_ihre[KFD_MAX_RING_ENTRY_SIZE]; | 683 | uint32_t patched_ihre[KFD_MAX_RING_ENTRY_SIZE]; |
684 | bool is_patched = false; | 684 | bool is_patched = false; |
685 | unsigned long flags; | ||
685 | 686 | ||
686 | if (!kfd->init_complete) | 687 | if (!kfd->init_complete) |
687 | return; | 688 | return; |
@@ -691,7 +692,7 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) | |||
691 | return; | 692 | return; |
692 | } | 693 | } |
693 | 694 | ||
694 | spin_lock(&kfd->interrupt_lock); | 695 | spin_lock_irqsave(&kfd->interrupt_lock, flags); |
695 | 696 | ||
696 | if (kfd->interrupts_active | 697 | if (kfd->interrupts_active |
697 | && interrupt_is_wanted(kfd, ih_ring_entry, | 698 | && interrupt_is_wanted(kfd, ih_ring_entry, |
@@ -700,7 +701,7 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) | |||
700 | is_patched ? patched_ihre : ih_ring_entry)) | 701 | is_patched ? patched_ihre : ih_ring_entry)) |
701 | queue_work(kfd->ih_wq, &kfd->interrupt_work); | 702 | queue_work(kfd->ih_wq, &kfd->interrupt_work); |
702 | 703 | ||
703 | spin_unlock(&kfd->interrupt_lock); | 704 | spin_unlock_irqrestore(&kfd->interrupt_lock, flags); |
704 | } | 705 | } |
705 | 706 | ||
706 | int kgd2kfd_quiesce_mm(struct mm_struct *mm) | 707 | int kgd2kfd_quiesce_mm(struct mm_struct *mm) |