[PATCH v5 19/24] amdkfd: Add interrupt handling module
From: Andrew Lewycky This patch adds the interrupt handling module, in kfd_interrupt.c, and its related members in different data structures to the amdkfd driver. The amdkfd interrupt module maintains an internal interrupt ring per amdkfd device. The internal interrupt ring contains interrupts that needs further handling. The extra handling is deferred to a later time through a workqueue. There's no acknowledgment for the interrupts we use. The hardware simply queues a new interrupt each time without waiting. The fixed-size internal queue means that it's possible for us to lose interrupts because we have no back-pressure to the hardware. v3: Move amdkfd from drm/radeon/ to drm/amd/ Change device init Made sure spin lock is taken only if init is complete Moved bool field to the end of the structure Signed-off-by: Andrew Lewycky Signed-off-by: Oded Gabbay --- drivers/gpu/drm/amd/amdkfd/Makefile| 3 +- drivers/gpu/drm/amd/amdkfd/kfd_device.c| 23 +++- drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c | 176 + drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 21 +++- 4 files changed, 218 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile index 307a309..be6246d 100644 --- a/drivers/gpu/drm/amd/amdkfd/Makefile +++ b/drivers/gpu/drm/amd/amdkfd/Makefile @@ -8,6 +8,7 @@ amdkfd-y:= kfd_module.o kfd_device.o kfd_chardev.o kfd_topology.o \ kfd_pasid.o kfd_doorbell.o kfd_flat_memory.o \ kfd_process.o kfd_queue.o kfd_mqd_manager.o \ kfd_kernel_queue.o kfd_packet_manager.o \ - kfd_process_queue_manager.o kfd_device_queue_manager.o + kfd_process_queue_manager.o kfd_device_queue_manager.o \ + kfd_interrupt.o obj-$(CONFIG_HSA_AMD) += amdkfd.o diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index bdf3e94..9beb6f7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -31,6 +31,7 @@ static const struct kfd_device_info kaveri_device_info = { .max_pasid_bits = 16, + .ih_ring_entry_size = 4 * sizeof(uint32_t), .mqd_size_aligned = MQD_SIZE_ALIGNED }; @@ -191,6 +192,13 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, goto kfd_topology_add_device_error; } + if (kfd_interrupt_init(kfd)) { + dev_err(kfd_device, + "Error initializing interrupts for device (%x:%x)\n", + kfd->pdev->vendor, kfd->pdev->device); + goto kfd_interrupt_error; + } + if (!device_iommu_pasid_init(kfd)) { dev_err(kfd_device, "Error initializing iommuv2 for device (%x:%x)\n", @@ -229,6 +237,8 @@ dqm_start_error: device_queue_manager_error: amd_iommu_free_device(kfd->pdev); device_iommu_pasid_error: + kfd_interrupt_exit(kfd); +kfd_interrupt_error: kfd_topology_remove_device(kfd); kfd_topology_add_device_error: kfd2kgd->fini_sa_manager(kfd->kgd); @@ -244,6 +254,7 @@ void kgd2kfd_device_exit(struct kfd_dev *kfd) if (kfd->init_complete) { device_queue_manager_uninit(kfd->dqm); amd_iommu_free_device(kfd->pdev); + kfd_interrupt_exit(kfd); kfd_topology_remove_device(kfd); } @@ -281,6 +292,16 @@ int kgd2kfd_resume(struct kfd_dev *kfd) return 0; } -void kgd2kfd_interrupt(struct kfd_dev *dev, const void *ih_ring_entry) +/* This is called directly from KGD at ISR. */ +void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) { + if (kfd->init_complete) { + spin_lock(>interrupt_lock); + + if (kfd->interrupts_active + && enqueue_ih_ring_entry(kfd, ih_ring_entry)) + schedule_work(>interrupt_work); + + spin_unlock(>interrupt_lock); + } } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c new file mode 100644 index 000..5b99909 --- /dev/null +++ b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c @@ -0,0 +1,176 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. +
[PATCH v5 19/24] amdkfd: Add interrupt handling module
From: Andrew Lewycky andrew.lewy...@amd.com This patch adds the interrupt handling module, in kfd_interrupt.c, and its related members in different data structures to the amdkfd driver. The amdkfd interrupt module maintains an internal interrupt ring per amdkfd device. The internal interrupt ring contains interrupts that needs further handling. The extra handling is deferred to a later time through a workqueue. There's no acknowledgment for the interrupts we use. The hardware simply queues a new interrupt each time without waiting. The fixed-size internal queue means that it's possible for us to lose interrupts because we have no back-pressure to the hardware. v3: Move amdkfd from drm/radeon/ to drm/amd/ Change device init Made sure spin lock is taken only if init is complete Moved bool field to the end of the structure Signed-off-by: Andrew Lewycky andrew.lewy...@amd.com Signed-off-by: Oded Gabbay oded.gab...@amd.com --- drivers/gpu/drm/amd/amdkfd/Makefile| 3 +- drivers/gpu/drm/amd/amdkfd/kfd_device.c| 23 +++- drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c | 176 + drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 21 +++- 4 files changed, 218 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile index 307a309..be6246d 100644 --- a/drivers/gpu/drm/amd/amdkfd/Makefile +++ b/drivers/gpu/drm/amd/amdkfd/Makefile @@ -8,6 +8,7 @@ amdkfd-y:= kfd_module.o kfd_device.o kfd_chardev.o kfd_topology.o \ kfd_pasid.o kfd_doorbell.o kfd_flat_memory.o \ kfd_process.o kfd_queue.o kfd_mqd_manager.o \ kfd_kernel_queue.o kfd_packet_manager.o \ - kfd_process_queue_manager.o kfd_device_queue_manager.o + kfd_process_queue_manager.o kfd_device_queue_manager.o \ + kfd_interrupt.o obj-$(CONFIG_HSA_AMD) += amdkfd.o diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index bdf3e94..9beb6f7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -31,6 +31,7 @@ static const struct kfd_device_info kaveri_device_info = { .max_pasid_bits = 16, + .ih_ring_entry_size = 4 * sizeof(uint32_t), .mqd_size_aligned = MQD_SIZE_ALIGNED }; @@ -191,6 +192,13 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, goto kfd_topology_add_device_error; } + if (kfd_interrupt_init(kfd)) { + dev_err(kfd_device, + Error initializing interrupts for device (%x:%x)\n, + kfd-pdev-vendor, kfd-pdev-device); + goto kfd_interrupt_error; + } + if (!device_iommu_pasid_init(kfd)) { dev_err(kfd_device, Error initializing iommuv2 for device (%x:%x)\n, @@ -229,6 +237,8 @@ dqm_start_error: device_queue_manager_error: amd_iommu_free_device(kfd-pdev); device_iommu_pasid_error: + kfd_interrupt_exit(kfd); +kfd_interrupt_error: kfd_topology_remove_device(kfd); kfd_topology_add_device_error: kfd2kgd-fini_sa_manager(kfd-kgd); @@ -244,6 +254,7 @@ void kgd2kfd_device_exit(struct kfd_dev *kfd) if (kfd-init_complete) { device_queue_manager_uninit(kfd-dqm); amd_iommu_free_device(kfd-pdev); + kfd_interrupt_exit(kfd); kfd_topology_remove_device(kfd); } @@ -281,6 +292,16 @@ int kgd2kfd_resume(struct kfd_dev *kfd) return 0; } -void kgd2kfd_interrupt(struct kfd_dev *dev, const void *ih_ring_entry) +/* This is called directly from KGD at ISR. */ +void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) { + if (kfd-init_complete) { + spin_lock(kfd-interrupt_lock); + + if (kfd-interrupts_active +enqueue_ih_ring_entry(kfd, ih_ring_entry)) + schedule_work(kfd-interrupt_work); + + spin_unlock(kfd-interrupt_lock); + } } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c new file mode 100644 index 000..5b99909 --- /dev/null +++ b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c @@ -0,0 +1,176 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the Software), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + *