aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3444-drm-amdkfd-add-debug-notification.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3444-drm-amdkfd-add-debug-notification.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3444-drm-amdkfd-add-debug-notification.patch577
1 files changed, 577 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3444-drm-amdkfd-add-debug-notification.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3444-drm-amdkfd-add-debug-notification.patch
new file mode 100644
index 00000000..69b42ac6
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/3444-drm-amdkfd-add-debug-notification.patch
@@ -0,0 +1,577 @@
+From 149171bf2e15568cb3d7169d6e4c6dbd5fbaa8cb Mon Sep 17 00:00:00 2001
+From: Jonathan Kim <jonathan.kim@amd.com>
+Date: Thu, 9 May 2019 20:49:29 -0400
+Subject: [PATCH 3444/4256] drm/amdkfd: add debug notification
+
+User space adds trace to process. Ring buffer entry is flagged by IH and
+process info is sent to debug event handler by kernel. Kernel updates queue
+debug event status as pending event by doorbell id and updates fifo data
+accessible by user space after kernel sends wake signal on polling fd. Fifo
+data records debug event history as fifo string where 't' is trap and 'v'
+is vm fault.
+
+User space can query pending events by target queue id or find the first
+queue with a pending event. User space also has option of clearing pending
+event status on target (or first found) queue. Kernel will report queried
+pending event type (trap or vm fault) and suspend status of queue.
+
+Change-Id: Ied5b7c21306638c8cfdaac8d8b9bae342b235b47
+Signed-off-by: Jonathan Kim <jonathan.kim@amd.com>
+---
+ drivers/gpu/drm/amd/amdkfd/Makefile | 3 +-
+ drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 18 ++
+ drivers/gpu/drm/amd/amdkfd/kfd_debug_events.c | 285 ++++++++++++++++++
+ drivers/gpu/drm/amd/amdkfd/kfd_debug_events.h | 40 +++
+ .../gpu/drm/amd/amdkfd/kfd_int_process_v9.c | 27 +-
+ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 11 +
+ include/uapi/linux/kfd_ioctl.h | 21 +-
+ 7 files changed, 396 insertions(+), 9 deletions(-)
+ create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_debug_events.c
+ create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_debug_events.h
+
+diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile
+index dad236a68a25..aa951107a895 100644
+--- a/drivers/gpu/drm/amd/amdkfd/Makefile
++++ b/drivers/gpu/drm/amd/amdkfd/Makefile
+@@ -59,7 +59,8 @@ AMDKFD_FILES := $(AMDKFD_PATH)/kfd_module.o \
+ $(AMDKFD_PATH)/kfd_rdma.o \
+ $(AMDKFD_PATH)/kfd_peerdirect.o \
+ $(AMDKFD_PATH)/kfd_ipc.o \
+- $(AMDKFD_PATH)/kfd_trace.o
++ $(AMDKFD_PATH)/kfd_trace.o \
++ $(AMDKFD_PATH)/kfd_debug_events.o
+
+ ifneq ($(CONFIG_AMD_IOMMU_V2),)
+ AMDKFD_FILES += $(AMDKFD_PATH)/kfd_iommu.o
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+index e96aa4eaaa66..44a9803f26f3 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+@@ -42,6 +42,7 @@
+ #include "kfd_priv.h"
+ #include "kfd_device_queue_manager.h"
+ #include "kfd_dbgmgr.h"
++#include "kfd_debug_events.h"
+ #include "kfd_ipc.h"
+ #include "kfd_trace.h"
+
+@@ -2736,6 +2737,18 @@ static int kfd_ioctl_dbg_set_debug_trap(struct file *filep,
+ r = dev->kfd2kgd->enable_debug_trap(dev->kgd,
+ pdd->trap_debug_wave_launch_mode,
+ dev->vm_info.last_vmid_kfd);
++ if (r)
++ break;
++
++ r = kfd_dbg_ev_enable(pdd);
++ if (r >= 0) {
++ args->data3 = r;
++ r = 0;
++ } else {
++ pdd->debug_trap_enabled = false;
++ dev->kfd2kgd->disable_debug_trap(dev->kgd);
++ }
++
+ break;
+ default:
+ pr_err("Invalid trap enable option: %i\n",
+@@ -2783,6 +2796,11 @@ static int kfd_ioctl_dbg_set_debug_trap(struct file *filep,
+ if (r)
+ goto unlock_out;
+ break;
++ case KFD_IOC_DBG_TRAP_QUERY_DEBUG_EVENT:
++ r = kfd_dbg_ev_query_debug_event(pdd, &args->data1,
++ args->data2,
++ &args->data3);
++ break;
+ default:
+ pr_err("Invalid option: %i\n", debug_trap_action);
+ r = -EINVAL;
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debug_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_debug_events.c
+new file mode 100644
+index 000000000000..210cccdeed81
+--- /dev/null
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug_events.c
+@@ -0,0 +1,285 @@
++/*
++ * Copyright 2019 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.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#include <linux/kfifo.h>
++#include <linux/poll.h>
++#include <linux/wait.h>
++#include <linux/anon_inodes.h>
++#include <uapi/linux/kfd_ioctl.h>
++#include "kfd_debug_events.h"
++#include "kfd_priv.h"
++#include "kfd_topology.h"
++
++/* poll and read functions */
++static __poll_t kfd_dbg_ev_poll(struct file *, struct poll_table_struct *);
++static ssize_t kfd_dbg_ev_read(struct file *, char __user *, size_t, loff_t *);
++static int kfd_dbg_ev_release(struct inode *, struct file *);
++
++/* fd name */
++static const char kfd_dbg_name[] = "kfd_debug";
++
++/* fops for polling, read and ioctl */
++static const struct file_operations kfd_dbg_ev_fops = {
++ .owner = THIS_MODULE,
++ .poll = kfd_dbg_ev_poll,
++ .read = kfd_dbg_ev_read,
++ .release = kfd_dbg_ev_release
++};
++
++/* poll on wait queue of file */
++static __poll_t kfd_dbg_ev_poll(struct file *filep,
++ struct poll_table_struct *wait)
++{
++
++ struct kfd_debug_process_device *dpd = filep->private_data;
++
++ __poll_t mask = 0;
++
++ /* pending event have been queue'd via interrupt */
++ poll_wait(filep, &dpd->wait_queue, wait);
++ mask |= !kfifo_is_empty(&dpd->fifo) ? POLLIN | POLLRDNORM : mask;
++
++ return mask;
++}
++
++/* read based on wait entries and return types found */
++static ssize_t kfd_dbg_ev_read(struct file *filep, char __user *user,
++ size_t size, loff_t *offset)
++{
++ int ret, copied;
++ struct kfd_debug_process_device *dpd = filep->private_data;
++
++ ret = kfifo_to_user(&dpd->fifo, user, size, &copied);
++
++ if (ret) {
++ pr_debug("KFD DEBUG EVENT: Failed to read poll fd (%i)\n", ret);
++ return ret;
++ }
++
++ return copied;
++}
++
++static int kfd_dbg_ev_release(struct inode *inode, struct file *filep)
++{
++ struct kfd_debug_process_device *dpd = filep->private_data;
++
++ kfifo_free(&dpd->fifo);
++
++ return 0;
++}
++
++/* query pending events and return queue_id, event_type and is_suspended */
++#define KFD_DBG_EV_SET_SUSPEND_STATE(x, s) \
++ ((x) = (s) ? (x) | KFD_DBG_EV_STATUS_SUSPENDED : \
++ (x) & ~KFD_DBG_EV_STATUS_SUSPENDED)
++
++#define KFD_DBG_EV_SET_EVENT_TYPE(x, e) \
++ ((x) = ((x) & ~(KFD_DBG_EV_STATUS_TRAP \
++ | KFD_DBG_EV_STATUS_VMFAULT)) | (e))
++
++int kfd_dbg_ev_query_debug_event(struct kfd_process_device *pdd,
++ unsigned int *queue_id,
++ unsigned int flags,
++ uint32_t *event_status)
++{
++ struct process_queue_manager *pqm;
++ struct process_queue_node *pqn;
++ struct queue *q;
++ int ret = 0;
++
++ if (!pdd || !pdd->process)
++ return -ENODATA;
++
++ /* lock process events to update event queues */
++ mutex_lock(&pdd->process->event_mutex);
++ pqm = &pdd->process->pqm;
++
++ if (*queue_id != KFD_INVALID_QUEUEID) {
++ q = pqm_get_user_queue(pqm, *queue_id);
++
++ if (!q) {
++ ret = -EINVAL;
++ goto out;
++ }
++
++ KFD_DBG_EV_SET_EVENT_TYPE(*event_status,
++ q->properties.debug_event_type);
++ KFD_DBG_EV_SET_SUSPEND_STATE(*event_status,
++ q->properties.is_suspended);
++ if (flags & KFD_DBG_EV_FLAG_CLEAR_STATUS)
++ q->properties.debug_event_type = 0;
++ goto out;
++
++ } else {
++ list_for_each_entry(pqn, &pqm->queues, process_queue_list) {
++ if (pqn->q &&
++ (pqn->q->properties.debug_event_type
++ == KFD_DBG_EV_STATUS_TRAP
++ || pqn->q->properties.debug_event_type
++ == KFD_DBG_EV_STATUS_VMFAULT)) {
++ *queue_id = pqn->q->properties.queue_id;
++ KFD_DBG_EV_SET_EVENT_TYPE(*event_status,
++ pqn->q->properties.debug_event_type);
++ KFD_DBG_EV_SET_SUSPEND_STATE(*event_status,
++ pqn->q->properties.is_suspended);
++ if (flags & KFD_DBG_EV_FLAG_CLEAR_STATUS)
++ pqn->q->properties.debug_event_type
++ = 0;
++ goto out;
++ }
++ }
++ ret = -EAGAIN;
++ }
++
++out:
++ mutex_unlock(&pdd->process->event_mutex);
++ return ret;
++}
++
++/* create event queue struct associated with process per device */
++static int kfd_create_event_queue(struct kfd_process_device *pdd)
++{
++ struct process_queue_manager *pqm;
++ struct process_queue_node *pqn;
++ struct kfd_topology_device *tdev;
++ int ret;
++
++ if (!pdd || !pdd->process)
++ return -ESRCH;
++
++ tdev = kfd_topology_device_by_id(pdd->dev->id);
++
++ pdd->dpd.max_debug_events = tdev->node_props.simd_count
++ * tdev->node_props.max_waves_per_simd;
++
++ ret = kfifo_alloc(&pdd->dpd.fifo, pdd->dpd.max_debug_events,
++ GFP_KERNEL);
++
++ if (ret)
++ return ret;
++
++ init_waitqueue_head(&pdd->dpd.wait_queue);
++
++ pqm = &pdd->process->pqm;
++
++ /* to reset queue pending status - TBD need init in queue creation */
++ list_for_each_entry(pqn, &pqm->queues, process_queue_list) {
++ if (pqn->q->device == pdd->dev)
++ pqn->q->properties.debug_event_type = 0;
++ }
++
++ return ret;
++}
++
++/* update process device, write to kfifo and wake up wait queue */
++static void kfd_dbg_ev_update_event_queue(struct kfd_process_device *pdd,
++ unsigned int doorbell_id,
++ bool is_vmfault)
++{
++ struct process_queue_manager *pqm;
++ struct process_queue_node *pqn;
++ char fifo_output;
++
++ if (!pdd->debug_trap_enabled)
++ return;
++
++ pqm = &pdd->process->pqm;
++
++ /* iterate through each queue */
++ list_for_each_entry(pqn, &pqm->queues,
++ process_queue_list) {
++
++ if (!pqn->q)
++ continue;
++
++ if (pqn->q->device != pdd->dev)
++ continue;
++
++ if (pqn->q->doorbell_id != doorbell_id && !is_vmfault)
++ continue;
++
++ pqn->q->properties.debug_event_type |=
++ is_vmfault ? KFD_DBG_EV_STATUS_VMFAULT :
++ KFD_DBG_EV_STATUS_TRAP;
++
++ fifo_output = is_vmfault ? 'v' : 't';
++
++ kfifo_in(&pdd->dpd.fifo, &fifo_output, 1);
++
++ wake_up_all(&pdd->dpd.wait_queue);
++
++ if (!is_vmfault)
++ break;
++ }
++}
++
++/* set pending event queue entry from ring entry */
++void kfd_set_dbg_ev_from_interrupt(struct kfd_dev *dev,
++ unsigned int pasid,
++ uint32_t doorbell_id,
++ bool is_vmfault)
++{
++ struct kfd_process *p;
++ struct kfd_process_device *pdd;
++
++ p = kfd_lookup_process_by_pasid(pasid);
++
++ if (!p)
++ return;
++
++ pdd = kfd_get_process_device_data(dev, p);
++
++ if (!pdd) {
++ kfd_unref_process(p);
++ return;
++ }
++
++ mutex_lock(&p->event_mutex);
++
++ kfd_dbg_ev_update_event_queue(pdd, doorbell_id, is_vmfault);
++
++ mutex_unlock(&p->event_mutex);
++
++ kfd_unref_process(p);
++}
++
++/* enable debug and return file pointer struct */
++int kfd_dbg_ev_enable(struct kfd_process_device *pdd)
++{
++ int ret;
++
++ if (!pdd || !pdd->process)
++ return -ESRCH;
++
++ mutex_lock(&pdd->process->event_mutex);
++
++ ret = kfd_create_event_queue(pdd);
++
++ mutex_unlock(&pdd->process->event_mutex);
++
++ if (ret)
++ return ret;
++
++ return anon_inode_getfd(kfd_dbg_name, &kfd_dbg_ev_fops,
++ (void *)&pdd->dpd, 0);
++}
++
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_debug_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_debug_events.h
+new file mode 100644
+index 000000000000..5b035a4321c6
+--- /dev/null
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_debug_events.h
+@@ -0,0 +1,40 @@
++/*
++ * Copyright 2019 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.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
++ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
++ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
++ * OTHER DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef KFD_DEBUG_EVENTS_H_INCLUDED
++#define KFD_DEBUG_EVENTS_H_INCLUDED
++
++#include "kfd_priv.h"
++
++int kfd_dbg_ev_query_debug_event(struct kfd_process_device *pdd,
++ unsigned int *queue_id,
++ unsigned int flags,
++ uint32_t *event_status);
++
++void kfd_set_dbg_ev_from_interrupt(struct kfd_dev *dev,
++ unsigned int pasid,
++ uint32_t doorbell_id,
++ bool is_vmfault);
++
++int kfd_dbg_ev_enable(struct kfd_process_device *pdd);
++
++#endif
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
+index 3ef67d2e0d9f..ab8a695c4a3c 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
+@@ -22,9 +22,13 @@
+
+ #include "kfd_priv.h"
+ #include "kfd_events.h"
++#include "kfd_debug_events.h"
+ #include "soc15_int.h"
+ #include "kfd_device_queue_manager.h"
+
++#define KFD_CONTEXT_ID_DEBUG_TRAP_MASK 0x000080
++#define KFD_CONTEXT_ID_DEBUG_DOORBELL_MASK 0x0003ff
++
+ static bool event_interrupt_isr_v9(struct kfd_dev *dev,
+ const uint32_t *ih_ring_entry,
+ uint32_t *patched_ihre,
+@@ -88,21 +92,29 @@ static void event_interrupt_wq_v9(struct kfd_dev *dev,
+ const uint32_t *ih_ring_entry)
+ {
+ uint16_t source_id, client_id, pasid, vmid;
+- uint32_t context_id;
++ uint32_t context_id0, context_id1;
+
+ source_id = SOC15_SOURCE_ID_FROM_IH_ENTRY(ih_ring_entry);
+ client_id = SOC15_CLIENT_ID_FROM_IH_ENTRY(ih_ring_entry);
+ pasid = SOC15_PASID_FROM_IH_ENTRY(ih_ring_entry);
+ vmid = SOC15_VMID_FROM_IH_ENTRY(ih_ring_entry);
+- context_id = SOC15_CONTEXT_ID0_FROM_IH_ENTRY(ih_ring_entry);
++ context_id0 = SOC15_CONTEXT_ID0_FROM_IH_ENTRY(ih_ring_entry);
++ context_id1 = SOC15_CONTEXT_ID1_FROM_IH_ENTRY(ih_ring_entry);
+
+ if (source_id == SOC15_INTSRC_CP_END_OF_PIPE)
+- kfd_signal_event_interrupt(pasid, context_id, 32);
++ kfd_signal_event_interrupt(pasid, context_id0, 32);
+ else if (source_id == SOC15_INTSRC_SDMA_TRAP)
+- kfd_signal_event_interrupt(pasid, context_id & 0xfffffff, 28);
+- else if (source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG)
+- kfd_signal_event_interrupt(pasid, context_id & 0xffffff, 24);
+- else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE)
++ kfd_signal_event_interrupt(pasid, context_id0 & 0xfffffff, 28);
++ else if (source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG) {
++ if (context_id1 & KFD_CONTEXT_ID_DEBUG_TRAP_MASK) {
++ kfd_set_dbg_ev_from_interrupt(dev, pasid,
++ context_id0 &
++ KFD_CONTEXT_ID_DEBUG_DOORBELL_MASK,
++ false);
++ } else
++ kfd_signal_event_interrupt(pasid,
++ context_id0 & 0xffffff, 24);
++ } else if (source_id == SOC15_INTSRC_CP_BAD_OPCODE)
+ kfd_signal_hw_exception_event(pasid);
+ else if (client_id == SOC15_IH_CLIENTID_VMC ||
+ client_id == SOC15_IH_CLIENTID_VMC1 ||
+@@ -118,6 +130,7 @@ static void event_interrupt_wq_v9(struct kfd_dev *dev,
+ info.prot_read = ring_id & 0x10;
+ info.prot_write = ring_id & 0x20;
+
++ kfd_set_dbg_ev_from_interrupt(dev, pasid, -1, true);
+ kfd_process_vm_fault(dev->dqm, pasid);
+ kfd_signal_vm_fault_event(dev, pasid, &info);
+ }
+diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+index 40c2b0d5a954..73aa6a3330eb 100644
+--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
++++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+@@ -510,6 +510,7 @@ struct queue_properties {
+ /* Relevant for CU */
+ uint32_t cu_mask_count; /* Must be a multiple of 32 */
+ uint32_t *cu_mask;
++ unsigned int debug_event_type;
+ };
+
+ #define QUEUE_IS_ACTIVE(q) ((q).queue_size > 0 && \
+@@ -696,6 +697,13 @@ enum kfd_pdd_bound {
+ PDD_BOUND_SUSPENDED,
+ };
+
++struct kfd_debug_process_device {
++ struct kfifo fifo;
++ wait_queue_head_t wait_queue;
++ int max_debug_events;
++};
++
++
+ /* Data that is per-process-per device. */
+ struct kfd_process_device {
+ /*
+@@ -710,6 +718,9 @@ struct kfd_process_device {
+ /* The process that owns this kfd_process_device. */
+ struct kfd_process *process;
+
++ /* per-process-per device debug event info */
++ struct kfd_debug_process_device dpd;
++
+ /* per-process-per device QCM data structure */
+ struct qcm_process_device qpd;
+
+diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h
+index 8c2862565444..617c07047d55 100644
+--- a/include/uapi/linux/kfd_ioctl.h
++++ b/include/uapi/linux/kfd_ioctl.h
+@@ -187,11 +187,19 @@ struct kfd_ioctl_dbg_wave_control_args {
+ __u32 buf_size_in_bytes; /*including gpu_id and buf_size */
+ };
+
++/* mapping event types to API spec */
++#define KFD_DBG_EV_STATUS_TRAP 1
++#define KFD_DBG_EV_STATUS_VMFAULT 2
++#define KFD_DBG_EV_STATUS_SUSPENDED 4
++#define KFD_DBG_EV_FLAG_CLEAR_STATUS 1
++
++#define KFD_INVALID_QUEUEID 0xffffffff
++
+ /* KFD_IOC_DBG_TRAP_ENABLE:
+ * ptr: unused
+ * data1: 0=disable, 1=enable
+ * data2: queue ID (for future use)
+- * data3: unused
++ * data3: return value for fd
+ */
+ #define KFD_IOC_DBG_TRAP_ENABLE 0
+
+@@ -235,6 +243,14 @@ struct kfd_ioctl_dbg_wave_control_args {
+ */
+ #define KFD_IOC_DBG_TRAP_NODE_RESUME 5
+
++/* KFD_IOC_DBG_TRAP_QUERY_DEBUG_EVENT:
++ * ptr: unused
++ * data1: queue id (IN/OUT)
++ * data2: flags (IN)
++ * data3: suspend[2:2], event type [1:0] (OUT)
++ */
++#define KFD_IOC_DBG_TRAP_QUERY_DEBUG_EVENT 6
++
+ struct kfd_ioctl_dbg_trap_args {
+ __u64 ptr; /* to KFD -- used for pointer arguments: queue arrays */
+ __u32 pid; /* to KFD */
+@@ -657,6 +673,9 @@ struct kfd_ioctl_cross_memory_copy_args {
+ #define AMDKFD_IOC_IPC_EXPORT_HANDLE \
+ AMDKFD_IOWR(0x20, struct kfd_ioctl_ipc_export_handle_args)
+
++#define AMDKFD_IOC_DBG_TRAP \
++ AMDKFD_IOWR(0x21, struct kfd_ioctl_dbg_trap_args)
++
+ #define AMDKFD_IOC_CROSS_MEMORY_COPY \
+ AMDKFD_IOWR(0x22, struct kfd_ioctl_cross_memory_copy_args)
+
+--
+2.17.1
+