drm/radeon: Add init interrupt kfd->kgd interface
Subsystems (3)
PATCH 1/9 drm/radeon: Add init interrupt kfd->kgd interface
This patch adds a new interface function to the kfd->kgd interface. The function is kgd_init_interrupts() and its function is to initialize a pipe's interrupts.
The function currently enables the timestamp interrupt and the bad opcode interrupt.
--- drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 2 ++ drivers/gpu/drm/radeon/cik_reg.h | 2 ++ drivers/gpu/drm/radeon/cikd.h | 1 + drivers/gpu/drm/radeon/radeon_kfd.c | 21 ++++++++++++++++++++- 4 files changed, 25 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/include/kgd_kfd_interface.h +2 -0
@@ -144,6 +144,8 @@ struct kfd2kgd_calls {int (*init_pipeline)(struct kgd_dev *kgd,uint32_t pipe_id,uint32_t hpd_size,uint64_t hpd_gpu_addr); +int (*init_interrupts)(struct kgd_dev *kgd,uint32_t pipe_id); +int (*hqd_load)(struct kgd_dev *kgd,void *mqd,uint32_t pipe_id,uint32_t queue_id,uint32_t __user *wptr);
drivers/gpu/drm/radeon/cik_reg.h +2 -0
@@ -149,6 +149,8 @@#define KFD_CIK_SDMA_QUEUE_OFFSET 0x200 +#define CPC_INT_CNTL 0xC2D0 +#define CP_HQD_IQ_RPTR 0xC970u#define AQL_ENABLE (1U << 0)#define SDMA0_RLC0_RB_CNTL 0xD400u
drivers/gpu/drm/radeon/cikd.h +1 -0
@@ -1335,6 +1335,7 @@# define CNTX_EMPTY_INT_ENABLE (1 << 20)# define PRIV_INSTR_INT_ENABLE (1 << 22)# define PRIV_REG_INT_ENABLE (1 << 23) +# define OPCODE_ERROR_INT_ENABLE (1 << 24)# define TIME_STAMP_INT_ENABLE (1 << 26)# define CP_RINGID2_INT_ENABLE (1 << 29)# define CP_RINGID1_INT_ENABLE (1 << 30)
drivers/gpu/drm/radeon/radeon_kfd.c +20 -1
@@ -66,7 +66,7 @@ static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid,static int kgd_init_pipeline (struct kgd_dev *kgd,uint32_t pipe_id,uint32_t hpd_size,uint64_t hpd_gpu_addr); - +static int kgd_init_interrupts (struct kgd_dev *kgd,uint32_t pipe_id);static int kgd_hqd_load (struct kgd_dev *kgd,void *mqd,uint32_t pipe_id,uint32_t queue_id,uint32_t __user *wptr);static int kgd_hqd_sdma_load (struct kgd_dev *kgd,void *mqd);
@@ -89,6 +89,7 @@ static const struct kfd2kgd_calls kfd2kgd = { .program_sh_mem_settings = kgd_program_sh_mem_settings, .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, .init_pipeline = kgd_init_pipeline, + .init_interrupts = kgd_init_interrupts, .hqd_load = kgd_hqd_load, .hqd_sdma_load = kgd_hqd_sdma_load, .hqd_is_occupied = kgd_hqd_is_occupied,
@@ -407,6 +408,24 @@ static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id,return 0 ; } +static int kgd_init_interrupts (struct kgd_dev *kgd,uint32_t pipe_id) +{ +uint32_t mec; +uint32_t pipe; + + mec = (pipe_id /CIK_PIPE_PER_MEC ) +1 ; + pipe = (pipe_id %CIK_PIPE_PER_MEC ); + +lock_srbm (kgd, mec, pipe,0 ,0 ); + +write_register (kgd,CPC_INT_CNTL , +TIME_STAMP_INT_ENABLE |OPCODE_ERROR_INT_ENABLE ); + +unlock_srbm (kgd); + +return 0 ; +} +static inline uint32_t get_sdma_base_addr (struct cik_sdma_rlc_registers *m) {uint32_t retval;
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 2/9 drm/amdkfd: Add interrupt handling module
From: Andrew Lewycky <[email protected]>
This patch adds the interrupt handling module, 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.
However, only interrupts that are "wanted" by amdkfd, are copied into the amdkfd s/w interrupt ring, in order to minimize the chances for overflow of the ring.
--- drivers/gpu/drm/amd/amdkfd/Makefile | 1 + drivers/gpu/drm/amd/amdkfd/kfd_device.c | 22 ++- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 15 ++ drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c | 181 +++++++++++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 17 ++ 5 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c
drivers/gpu/drm/amd/amdkfd/Makefile +1 -0
@@ -12,5 +12,6 @@ amdkfd-y := kfd_module.o kfd_device.o kfd_chardev.o kfd_topology.o \ kfd_kernel_queue_vi.o kfd_packet_manager.o \ kfd_process_queue_manager.o kfd_device_queue_manager.o \ kfd_device_queue_manager_cik.o kfd_device_queue_manager_vi.o \ + kfd_interrupt.o obj-$(CONFIG_HSA_AMD) += amdkfd.o
drivers/gpu/drm/amd/amdkfd/kfd_device.c +21 -1
@@ -235,6 +235,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",
@@ -273,6 +280,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:kfd_gtt_sa_fini (kfd);
@@ -290,6 +299,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);kfd_gtt_sa_fini (kfd); kfd->kfd2kgd->free_gtt_mem (kfd->kgd, kfd->gtt_mem);
@@ -333,7 +343,17 @@ int kgd2kfd_resume(struct kfd_dev *kfd)/* This is called directly from KGD at ISR. */ void kgd2kfd_interrupt (struct kfd_dev *kfd,const void *ih_ring_entry) { -/* Process interrupts / schedule work as necessary */ +if (!kfd->init_complete) +return ; + +spin_lock (&kfd->interrupt_lock); + +if (kfd->interrupts_active + &&interrupt_is_wanted (kfd, ih_ring_entry) + &&enqueue_ih_ring_entry (kfd, ih_ring_entry)) +schedule_work (&kfd->interrupt_work); + +spin_unlock (&kfd->interrupt_lock); } static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size,
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +15 -0
@@ -522,6 +522,17 @@ int init_pipelines(struct device_queue_manager *dqm,return 0 ; } +static void init_interrupts (struct device_queue_manager *dqm) +{ +unsigned int i; + +BUG_ON (dqm ==NULL ); + +for (i =0 ; i <get_pipes_num (dqm) ; i++) + dqm->dev->kfd2kgd->init_interrupts (dqm->dev->kgd, + i +get_first_pipe (dqm)); +} +static int init_scheduler (struct device_queue_manager *dqm) {int retval;
@@ -581,6 +592,7 @@ static void uninitialize_nocpsch(struct device_queue_manager *dqm)static int start_nocpsch (struct device_queue_manager *dqm) { +init_interrupts (dqm);return 0 ; }
@@ -750,6 +762,9 @@ static int start_cpsch(struct device_queue_manager *dqm) dqm->fence_addr = dqm->fence_mem->cpu_ptr; dqm->fence_gpu_addr = dqm->fence_mem->gpu_addr; + +init_interrupts (dqm); +list_for_each_entry (node, &dqm->queues, list)if (node->qpd->pqm->process && dqm->dev) kfd_bind_process_to_device(dqm->dev,
drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c new file +181 -0
181 lines not on this page · raw message
drivers/gpu/drm/amd/amdkfd/kfd_priv.h +17 -0
@@ -161,10 +161,23 @@ struct kfd_dev {unsigned int gtt_sa_chunk_size;unsigned int gtt_sa_num_of_chunks; +/* Interrupts */ +void *interrupt_ring; +size_t interrupt_ring_size; +atomic_t interrupt_ring_rptr; +atomic_t interrupt_ring_wptr; +struct work_struct interrupt_work; +spinlock_t interrupt_lock; +/* QCM Device instance */ struct device_queue_manager *dqm;bool init_complete; +/* +* Interrupts of interest to KFD are copied +* from the HW ring into a SW ring. +*/ +bool interrupts_active; };/* KGD2KFD callbacks */
@@ -555,7 +568,11 @@ struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev);struct kfd_dev *kfd_topology_enum_kfd_devices (uint8_t idx);/* Interrupts */ +int kfd_interrupt_init (struct kfd_dev *dev); +void kfd_interrupt_exit (struct kfd_dev *dev);void kgd2kfd_interrupt (struct kfd_dev *kfd,const void *ih_ring_entry); +bool enqueue_ih_ring_entry (struct kfd_dev *kfd,const void *ih_ring_entry); +bool interrupt_is_wanted (struct kfd_dev *dev,const uint32_t *ih_ring_entry);/* Power Management */ void kgd2kfd_suspend (struct kfd_dev *kfd);
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 3/9 drm/amdkfd: add events IOCTL set definitions
In reply to Oded GabbayFrom: Andrew Lewycky <[email protected]>
- AMDKFD_IOC_CREATE_EVENT:
Creates a new event of a specified type
- AMDKFD_IOC_DESTROY_EVENT:
Destroys an existing event
- AMDKFD_IOC_SET_EVENT:
Signal an existing event
- AMDKFD_IOC_RESET_EVENT:
Reset an existing event
- AMDKFD_IOC_WAIT_EVENTS:
Wait on event(s) until they are signaled
--- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 45 +++++++++++++++ include/uapi/linux/kfd_ioctl.h | 94 +++++++++++++++++++++++++++++++- 2 files changed, 137 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +45 -0
@@ -514,6 +514,36 @@ static int kfd_ioctl_get_process_apertures(struct file *filp,return 0 ; } +static int kfd_ioctl_create_event (struct file *filp,struct kfd_process *p, +void *data) +{ +return -ENODEV ; +} + +static int kfd_ioctl_destroy_event (struct file *filp,struct kfd_process *p, +void *data) +{ +return -ENODEV ; +} + +static int kfd_ioctl_set_event (struct file *filp,struct kfd_process *p, +void *data) +{ +return -ENODEV ; +} + +static int kfd_ioctl_reset_event (struct file *filp,struct kfd_process *p, +void *data) +{ +return -ENODEV ; +} + +static int kfd_ioctl_wait_events (struct file *filp,struct kfd_process *p, +void *data) +{ +return -ENODEV ; +} +#define AMDKFD_IOCTL_DEF (ioctl, _func, _flags) \ [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, .cmd_drv = 0, .name = #ioctl}
@@ -539,6 +569,21 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = {AMDKFD_IOCTL_DEF (AMDKFD_IOC_UPDATE_QUEUE , kfd_ioctl_update_queue,0 ), + +AMDKFD_IOCTL_DEF (AMDKFD_IOC_CREATE_EVENT , + kfd_ioctl_create_event,0 ), + +AMDKFD_IOCTL_DEF (AMDKFD_IOC_DESTROY_EVENT , + kfd_ioctl_destroy_event,0 ), + +AMDKFD_IOCTL_DEF (AMDKFD_IOC_SET_EVENT , + kfd_ioctl_set_event,0 ), + +AMDKFD_IOCTL_DEF (AMDKFD_IOC_RESET_EVENT , + kfd_ioctl_reset_event,0 ), + +AMDKFD_IOCTL_DEF (AMDKFD_IOC_WAIT_EVENTS , + kfd_ioctl_wait_events, 0), };#define AMDKFD_CORE_IOCTL_COUNT ARRAY_SIZE(amdkfd_ioctls)
include/uapi/linux/kfd_ioctl.h +92 -2
112 lines not on this page · raw message
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 4/9 drm/amdkfd: Add the events module
In reply to Oded GabbayFrom: Andrew Lewycky <[email protected]>
This patch adds the events module (kfd_events.c) and the interrupt handler module for Kaveri (cik_event_interrupt.c).
The patch updates the interrupt_is_wanted(), so that it now calls the interrupt isr function specific for the device that received the interrupt. That function (implemented in cik_event_interrupt.c) returns whether this interrupt is of interest to us or not.
The patch also updates the interrupt_wq(), so that it now calls the device's specific wq function, which checks the interrupt source and tries to signal relevant events.
There is a limitation of 256 events per process, in order for the search for SQ interrupts to be a direct lookup. In the future, this limitation will be lifted.
--- drivers/gpu/drm/amd/amdkfd/Makefile | 2 +- drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c | 57 ++ drivers/gpu/drm/amd/amdkfd/cik_int.h | 54 ++ drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 16 +- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 1 + drivers/gpu/drm/amd/amdkfd/kfd_events.c | 775 +++++++++++++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_events.h | 76 +++ drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c | 11 +- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 48 ++ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 24 + 10 files changed, 1059 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c create mode 100644 drivers/gpu/drm/amd/amdkfd/cik_int.h create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_events.c create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_events.h
drivers/gpu/drm/amd/amdkfd/Makefile +1 -1
@@ -12,6 +12,6 @@ amdkfd-y := kfd_module.o kfd_device.o kfd_chardev.o kfd_topology.o \ kfd_kernel_queue_vi.o kfd_packet_manager.o \ kfd_process_queue_manager.o kfd_device_queue_manager.o \ kfd_device_queue_manager_cik.o kfd_device_queue_manager_vi.o \ - kfd_interrupt.o + kfd_interrupt.o kfd_events.o cik_event_interrupt.o obj-$(CONFIG_HSA_AMD) += amdkfd.o
drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c new file +57 -0
57 lines not on this page · raw message
drivers/gpu/drm/amd/amdkfd/cik_int.h new file +54 -0
54 lines not on this page · raw message
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +14 -2
@@ -289,8 +289,10 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, args->queue_id = queue_id; +/* Return gpu_id as doorbell offset for mmap usage */ - args->doorbell_offset = args->gpu_id <<PAGE_SHIFT ; + args->doorbell_offset = (KFD_MMAP_DOORBELL_MASK | args->gpu_id); + args->doorbell_offset <<=PAGE_SHIFT ;mutex_unlock (&p->mutex);
@@ -684,5 +686,15 @@ static int kfd_mmap(struct file *filp, struct vm_area_struct *vma)if (IS_ERR (process))return PTR_ERR (process); -return kfd_doorbell_mmap (process, vma); +if ((vma->vm_pgoff &KFD_MMAP_DOORBELL_MASK ) == +KFD_MMAP_DOORBELL_MASK ) { + vma->vm_pgoff = vma->vm_pgoff ^KFD_MMAP_DOORBELL_MASK ; +return kfd_doorbell_mmap (process, vma); + }else if ((vma->vm_pgoff &KFD_MMAP_EVENTS_MASK ) == +KFD_MMAP_EVENTS_MASK ) { + vma->vm_pgoff = vma->vm_pgoff ^KFD_MMAP_EVENTS_MASK ; +return radeon_kfd_event_mmap (process, vma); + } + +return -EFAULT ; }
drivers/gpu/drm/amd/amdkfd/kfd_device.c +1 -0
@@ -34,6 +34,7 @@ static const struct kfd_device_info kaveri_device_info = { .asic_family = CHIP_KAVERI, .max_pasid_bits = 16, .ih_ring_entry_size = 4 * sizeof(uint32_t), + .event_interrupt_class = &event_interrupt_class_cik, .mqd_size_aligned = MQD_SIZE_ALIGNED };
drivers/gpu/drm/amd/amdkfd/kfd_events.c new file +775 -0
775 lines not on this page · raw message
drivers/gpu/drm/amd/amdkfd/kfd_events.h new file +76 -0
76 lines not on this page · raw message
drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c +9 -2
@@ -172,10 +172,17 @@ static void interrupt_wq(struct work_struct *work) sizeof(uint32_t))];while (dequeue_ih_ring_entry (dev, ih_ring_entry)) - ; + dev->device_info->event_interrupt_class->interrupt_wq (dev, + ih_ring_entry); }bool interrupt_is_wanted (struct kfd_dev *dev,const uint32_t *ih_ring_entry) { -return false; +/* integer and bitwise OR so there is no boolean short-circuiting */ +unsigned wanted =0 ; + + wanted |= dev->device_info->event_interrupt_class->interrupt_isr (dev, + ih_ring_entry); + +return wanted !=0 ; }
drivers/gpu/drm/amd/amdkfd/kfd_priv.h +48 -0
78 lines not on this page · raw message
drivers/gpu/drm/amd/amdkfd/kfd_process.c +24 -0
@@ -178,6 +178,8 @@ static void kfd_process_wq_release(struct work_struct *work)kfree (pdd); } +kfd_event_free_process (p); +kfd_pasid_free (p->pasid);mutex_unlock (&p->mutex);
@@ -289,6 +291,8 @@ static struct kfd_process *create_process(const struct task_struct *thread)INIT_LIST_HEAD (&process->per_device_data); +kfd_event_init_process (process); + err =pqm_init (&process->pqm, process);if (err !=0 ) goto err_process_pqm_init;
@@ -431,3 +435,23 @@ bool kfd_has_process_device_data(struct kfd_process *p) {return !(list_empty (&p->per_device_data)); } + +/* This returns with process->mutex locked. */ +struct kfd_process *kfd_lookup_process_by_pasid (unsigned int pasid) +{ +struct kfd_process *p; +unsigned int temp; + +int idx =srcu_read_lock (&kfd_processes_srcu); + +hash_for_each_rcu (kfd_processes_table, temp, p, kfd_processes) { +if (p->pasid == pasid) { +mutex_lock (&p->mutex); +break ; + } + } + +srcu_read_unlock (&kfd_processes_srcu, idx); + +return p; +}
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 5/9 drm/amdkfd: Add memory exception handling
In reply to Oded GabbayFrom: Alexey Skidanov <[email protected]>
This patch adds Peripheral Page Request (PPR) failure processing and reporting.
Bad address or pointer to a system memory block with inappropriate read/write permission cause such PPR failure during a user queue processing. PPR request handling is done by IOMMU driver notifying AMDKFD module on PPR failure.
The process triggering a PPR failure will be notified by appropriate event or SIGTERM signal will be sent to it.
--- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 29 ++++++ drivers/gpu/drm/amd/amdkfd/kfd_events.c | 154 ++++++++++++++++++++++++++++++-- drivers/gpu/drm/amd/amdkfd/kfd_events.h | 7 ++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 5 +- 4 files changed, 186 insertions(+), 9 deletions(-)
drivers/gpu/drm/amd/amdkfd/kfd_device.c +29 -0
@@ -182,6 +182,32 @@ static void iommu_pasid_shutdown_callback(struct pci_dev *pdev, int pasid)kfd_unbind_process_from_device (dev, pasid); } +/* +* This function called by IOMMU driver on PPR failure +*/ +static int iommu_invalid_ppr_cb (struct pci_dev *pdev,int pasid, +unsigned long address,u16 flags) +{ +struct kfd_dev *dev; + +dev_warn (kfd_device, +"Invalid PPR device %x:%x.%x pasid %d address 0x%lX flags 0x%X" , +PCI_BUS_NUM (pdev->devfn), +PCI_SLOT (pdev->devfn), +PCI_FUNC (pdev->devfn), + pasid, + address, + flags); + + dev =kfd_device_by_pci_dev (pdev); +BUG_ON (dev ==NULL ); + +kfd_signal_iommu_event (dev, pasid, address, + flags &PPR_FAULT_WRITE , flags &PPR_FAULT_EXEC ); + +return AMD_IOMMU_INV_PRI_RSP_INVALID ; +} +bool kgd2kfd_device_init (struct kfd_dev *kfd,const struct kgd2kfd_shared_resources *gpu_resources) {
@@ -251,6 +277,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, }amd_iommu_set_invalidate_ctx_cb (kfd->pdev, iommu_pasid_shutdown_callback); +amd_iommu_set_invalid_ppr_cb (kfd->pdev, iommu_invalid_ppr_cb); kfd->dqm =device_queue_manager_init (kfd);if (!kfd->dqm) {
@@ -316,6 +343,7 @@ void kgd2kfd_suspend(struct kfd_dev *kfd)if (kfd->init_complete) { kfd->dqm->ops.stop (kfd->dqm);amd_iommu_set_invalidate_ctx_cb (kfd->pdev,NULL ); +amd_iommu_set_invalid_ppr_cb (kfd->pdev,NULL );amd_iommu_free_device (kfd->pdev); } }
@@ -335,6 +363,7 @@ int kgd2kfd_resume(struct kfd_dev *kfd)return -ENXIO ;amd_iommu_set_invalidate_ctx_cb (kfd->pdev, iommu_pasid_shutdown_callback); +amd_iommu_set_invalid_ppr_cb (kfd->pdev, iommu_invalid_ppr_cb); kfd->dqm->ops.start (kfd->dqm); }
drivers/gpu/drm/amd/amdkfd/kfd_events.c +146 -8
211 lines not on this page · raw message
drivers/gpu/drm/amd/amdkfd/kfd_events.h +7 -0
@@ -28,6 +28,7 @@#include <linux/types.h> #include <linux/list.h> #include "kfd_priv.h" +#include <uapi/linux/kfd_ioctl.h> #define KFD_EVENT_ID_NONSIGNAL_MASK 0x80000000U#define KFD_FIRST_NONSIGNAL_EVENT_ID KFD_EVENT_ID_NONSIGNAL_MASK
@@ -61,6 +62,11 @@ struct kfd_event {struct signal_page *signal_page;unsigned int signal_slot_index;uint64_t __user *user_signal_address; + +/* type specific data */ +union { +struct kfd_hsa_memory_exception_data memory_exception_data; + }; };#define KFD_EVENT_TIMEOUT_IMMEDIATE 0
@@ -69,6 +75,7 @@ struct kfd_event {/* Matching HSA_EVENTTYPE */ #define KFD_EVENT_TYPE_SIGNAL 0#define KFD_EVENT_TYPE_DEBUG 5 +#define KFD_EVENT_TYPE_MEMORY 8extern void kfd_signal_event_interrupt (unsigned int pasid,uint32_t partial_id,uint32_t valid_id_bits);
drivers/gpu/drm/amd/amdkfd/kfd_priv.h +4 -1
@@ -694,11 +694,14 @@ void kfd_event_free_process(struct kfd_process *p);int radeon_kfd_event_mmap (struct kfd_process *process,struct vm_area_struct *vma);int kfd_wait_on_events (struct kfd_process *p, -uint32_t num_events,const uint32_t __user *event_ids, +uint32_t num_events,void __user *data,bool all,uint32_t user_timeout_ms,enum kfd_event_wait_result *wait_result);void kfd_signal_event_interrupt (unsigned int pasid,uint32_t partial_id,uint32_t valid_id_bits); +void kfd_signal_iommu_event (struct kfd_dev *dev, +unsigned int pasid,unsigned long address, +bool is_write_requested,bool is_execute_requested);int kfd_set_event (struct kfd_process *p,uint32_t event_id);int kfd_reset_event (struct kfd_process *p,uint32_t event_id); int kfd_event_create(struct file *devkfd, struct kfd_process *p,
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 6/9 drm/amdkfd: Add bad opcode exception handling
In reply to Oded GabbayFrom: Alexey Skidanov <[email protected]>
--- drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c | 5 ++++- drivers/gpu/drm/amd/amdkfd/cik_int.h | 1 + drivers/gpu/drm/amd/amdkfd/kfd_events.c | 21 +++++++++++++++++++++ drivers/gpu/drm/amd/amdkfd/kfd_events.h | 1 + drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 2 ++ 5 files changed, 29 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c +4 -1
@@ -33,7 +33,8 @@ static bool cik_event_interrupt_isr(struct kfd_dev *dev,/* Do not process in ISR, just request it to be forwarded to WQ. */ return (ihre->pasid !=0 ) && (ihre->source_id ==CIK_INTSRC_CP_END_OF_PIPE || - ihre->source_id ==CIK_INTSRC_SQ_INTERRUPT_MSG ); + ihre->source_id ==CIK_INTSRC_SQ_INTERRUPT_MSG || + ihre->source_id ==CIK_INTSRC_CP_BAD_OPCODE ); } static void cik_event_interrupt_wq(struct kfd_dev *dev,
@@ -49,6 +50,8 @@ static void cik_event_interrupt_wq(struct kfd_dev *dev,kfd_signal_event_interrupt (ihre->pasid,0 ,0 ); else if (ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG) kfd_signal_event_interrupt(ihre->pasid, ihre->data & 0xFF, 8); + else if (ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE) + kfd_signal_hw_exception_event(ihre->pasid); }const struct kfd_event_interrupt_class event_interrupt_class_cik = {
drivers/gpu/drm/amd/amdkfd/cik_int.h +1 -0
@@ -48,6 +48,7 @@ struct cik_ih_ring_entry {#define CIK_INTSRC_DEQUEUE_COMPLETE 0xC6#define CIK_INTSRC_CP_END_OF_PIPE 0xB5 +#define CIK_INTSRC_CP_BAD_OPCODE 0xB7#define CIK_INTSRC_SQ_INTERRUPT_MSG 0xEF#endif
drivers/gpu/drm/amd/amdkfd/kfd_events.c +21 -0
@@ -911,3 +911,24 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid,mutex_unlock (&p->event_mutex);mutex_unlock (&p->mutex); } + +void kfd_signal_hw_exception_event (unsigned int pasid) +{ +/* +* Because we are called from arbitrary context (workqueue) as opposed +* to process context, kfd_process could attempt to exit while we are +* running so the lookup function returns a locked process. +*/ +struct kfd_process *p =kfd_lookup_process_by_pasid (pasid); + +if (!p) +return ;/* Presumably process exited. */ + +mutex_lock (&p->event_mutex); + +/* Lookup events by type and signal them */ +lookup_events_by_type_and_signal (p,KFD_EVENT_TYPE_HW_EXCEPTION ,NULL ); + +mutex_unlock (&p->event_mutex); +mutex_unlock (&p->mutex); +}
drivers/gpu/drm/amd/amdkfd/kfd_events.h +1 -0
@@ -74,6 +74,7 @@ struct kfd_event {/* Matching HSA_EVENTTYPE */ #define KFD_EVENT_TYPE_SIGNAL 0 +#define KFD_EVENT_TYPE_HW_EXCEPTION 3#define KFD_EVENT_TYPE_DEBUG 5#define KFD_EVENT_TYPE_MEMORY 8
drivers/gpu/drm/amd/amdkfd/kfd_priv.h +2 -0
@@ -682,6 +682,7 @@ phys_addr_t kfd_get_process_doorbells(struct kfd_dev *dev,/* Events */ extern const struct kfd_event_interrupt_class event_interrupt_class_cik; +extern const struct kfd_device_global_init_class device_global_init_class_cik;enum kfd_event_wait_result {KFD_WAIT_COMPLETE ,
@@ -702,6 +703,7 @@ void kfd_signal_event_interrupt(unsigned int pasid, uint32_t partial_id,void kfd_signal_iommu_event (struct kfd_dev *dev,unsigned int pasid,unsigned long address,bool is_write_requested,bool is_execute_requested); +void kfd_signal_hw_exception_event (unsigned int pasid);int kfd_set_event (struct kfd_process *p,uint32_t event_id);int kfd_reset_event (struct kfd_process *p,uint32_t event_id); int kfd_event_create(struct file *devkfd, struct kfd_process *p,
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 7/9 drm/amdkfd: Add module parameter of send_sigterm
In reply to Oded GabbayThis patch adds a new kernel module parameter to amdkfd, called send_sigterm.
This parameter specifies whether amdkfd should send the SIGTERM signal to an HSA process, when the following conditions occur:
1. The GPU triggers an exception regarding a kernel that was issued by this process.
2. The HSA process isn't waiting on an event that handles this exception.
The default behavior is not to send a SIGTERM and suffice with a dmesg error print.
--- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 12 +++++++++--- drivers/gpu/drm/amd/amdkfd/kfd_module.c | 5 +++++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 6 ++++++ 3 files changed, 20 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/amdkfd/kfd_events.c +9 -3
@@ -847,10 +847,16 @@ static void lookup_events_by_type_and_signal(struct kfd_process *p,/* Send SIGTERM no event of type "type" has been found*/ if (send_signal) { -dev_warn (kfd_device, -"Sending SIGTERM to HSA Process with PID %d " , +if (send_sigterm) { +dev_warn (kfd_device, +"Sending SIGTERM to HSA Process with PID %d " , + p->lead_thread->pid); +send_sig (SIGTERM , p->lead_thread,0 ); + }else { +dev_err (kfd_device, +"HSA Process (PID %d) got unhandled exception" , p->lead_thread->pid); -send_sig (SIGTERM , p->lead_thread,0 ); + } } }
drivers/gpu/drm/amd/amdkfd/kfd_module.c +5 -0
@@ -54,6 +54,11 @@ module_param(max_num_of_queues_per_device, int, 0444);MODULE_PARM_DESC (max_num_of_queues_per_device,"Maximum number of supported queues per device (1 = Minimum, 4096 = default)" ); +int send_sigterm; +module_param (send_sigterm, int,0444 ); +MODULE_PARM_DESC (send_sigterm, +"Send sigterm to HSA process on unhandled exception (0 = disable, 1 = enable)" ); +bool kgd2kfd_init (unsigned interface_version,const struct kgd2kfd_calls **g2f) {/*
drivers/gpu/drm/amd/amdkfd/kfd_priv.h +6 -0
@@ -74,6 +74,12 @@ extern int max_num_of_queues_per_device;/* Kernel module parameter to specify the scheduling policy */ extern int sched_policy; +/* +* Kernel module parameter to specify whether to send sigterm to HSA process on +* unhandled exception +*/ +extern int send_sigterm; +/** * enum kfd_sched_policy *
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 8/9 drm/amdkfd: Implement events IOCTLs
In reply to Oded GabbayFrom: Andrew Lewycky <[email protected]>
--- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 36 +++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-)
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +31 -5
@@ -519,31 +519,57 @@ static int kfd_ioctl_get_process_apertures(struct file *filp,static int kfd_ioctl_create_event (struct file *filp,struct kfd_process *p,void *data) { -return -ENODEV ; +struct kfd_ioctl_create_event_args *args = data; +int err; + + err =kfd_event_create (filp, p, args->event_type, + args->auto_reset !=0 , args->node_id, + &args->event_id, &args->event_trigger_data, + &args->event_page_offset, + &args->event_slot_index); + +return err; }static int kfd_ioctl_destroy_event (struct file *filp,struct kfd_process *p,void *data) { -return -ENODEV ; +struct kfd_ioctl_destroy_event_args *args = data; + +return kfd_event_destroy (p, args->event_id); }static int kfd_ioctl_set_event (struct file *filp,struct kfd_process *p,void *data) { -return -ENODEV ; +struct kfd_ioctl_set_event_args *args = data; + +return kfd_set_event (p, args->event_id); }static int kfd_ioctl_reset_event (struct file *filp,struct kfd_process *p,void *data) { -return -ENODEV ; +struct kfd_ioctl_reset_event_args *args = data; + +return kfd_reset_event (p, args->event_id); }static int kfd_ioctl_wait_events (struct file *filp,struct kfd_process *p,void *data) { -return -ENODEV ; +struct kfd_ioctl_wait_events_args *args = data; +enum kfd_event_wait_result wait_result; +int err; + + err =kfd_wait_on_events (p, args->num_events, + (void __user *)args->events_ptr, + (args->wait_for_all !=0 ), + args->timeout, &wait_result); + + args->wait_result = wait_result; + +return err; }#define AMDKFD_IOCTL_DEF (ioctl, _func, _flags) \
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
PATCH 9/9 drm/amdkfd: change driver version to 0.7.2
In reply to Oded Gabbay--- drivers/gpu/drm/amd/amdkfd/kfd_module.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdkfd/kfd_module.c +2 -2
@@ -29,10 +29,10 @@#define KFD_DRIVER_AUTHOR "AMD Inc. and others"#define KFD_DRIVER_DESC "Standalone HSA driver for AMD's GPUs" -#define KFD_DRIVER_DATE "20150122" +#define KFD_DRIVER_DATE "20150421"#define KFD_DRIVER_MAJOR 0#define KFD_DRIVER_MINOR 7 -#define KFD_DRIVER_PATCHLEVEL 1 +#define KFD_DRIVER_PATCHLEVEL 2static const struct kgd2kfd_calls kgd2kfd = { .exit = kgd2kfd_exit,
Signature · 6 lines
1.9.1 _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel