[PATCH v5 19/24] amdkfd: Add interrupt handling module

2014-11-08 Thread Oded Gabbay
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

2014-11-08 Thread Oded Gabbay
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
+ *