From: Taehee Yoo <ap420073@gmail.com>
To: "Alex Deucher" <alexander.deucher@amd.com>,
"Alexei Starovoitov" <ast@kernel.org>,
amd-gfx@lists.freedesktop.org,
"Andrew Lunn" <andrew+netdev@lunn.ch>,
"Andrii Nakryiko" <andrii@kernel.org>,
"Bill Wendling" <morbo@google.com>,
bpf@vger.kernel.org, "Christian König" <christian.koenig@amd.com>,
"Daniel Borkmann" <daniel@iogearbox.net>,
"David Airlie" <airlied@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
"Donald Hunter" <donald.hunter@gmail.com>,
dri-devel@lists.freedesktop.org,
"Eduard Zingerman" <eddyz87@gmail.com>,
"Emil Tsalapatis" <emil@etsalapatis.com>,
"Eric Dumazet" <edumazet@google.com>,
"Felix Kuehling" <Felix.Kuehling@amd.com>,
"Hoyeon Lee" <hoyeon.rhee@gmail.com>,
"Ilias Apalodimas" <ilias.apalodimas@linaro.org>,
"Jakub Kicinski" <kuba@kernel.org>,
"Jesper Dangaard Brouer" <hawk@kernel.org>,
"Jiri Olsa" <jolsa@kernel.org>,
"John Fastabend" <john.fastabend@gmail.com>,
"Justin Stitt" <justinstitt@google.com>,
"Kees Cook" <kees@kernel.org>,
"Kumar Kartikeya Dwivedi" <memxor@gmail.com>,
"Leon Romanovsky" <leon@kernel.org>,
linaro-mm-sig@lists.linaro.org, linux-hardening@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-media@vger.kernel.org, linux-rdma@vger.kernel.org,
llvm@lists.linux.dev, "Mark Bloch" <mbloch@nvidia.com>,
"Martin KaFai Lau" <martin.lau@linux.dev>,
"Michael Chan" <michael.chan@broadcom.com>,
"Nathan Chancellor" <nathan@kernel.org>,
netdev@vger.kernel.org,
"Nick Desaulniers" <ndesaulniers@google.com>,
"Paolo Abeni" <pabeni@redhat.com>,
"Pavan Chebbi" <pavan.chebbi@broadcom.com>,
"Saeed Mahameed" <saeedm@nvidia.com>,
"Shuah Khan" <shuah@kernel.org>,
"Simona Vetter" <simona@ffwll.ch>,
"Simon Horman" <horms@kernel.org>, "Song Liu" <song@kernel.org>,
"Stanislav Fomichev" <sdf@fomichev.me>,
"Sumit Semwal" <sumit.semwal@linaro.org>,
"Taehee Yoo" <ap420073@gmail.com>,
"Tariq Toukan" <tariqt@nvidia.com>,
"Yonghong Song" <yonghong.song@linux.dev>
Subject: [RFC PATCH net-next 06/13] drm/amdkfd: prepare kfd core for the knod provider
Date: Sun, 19 Jul 2026 17:58:50 +0000 [thread overview]
Message-ID: <20260719175857.4071636-7-ap420073@gmail.com> (raw)
In-Reply-To: <20260719175857.4071636-1-ap420073@gmail.com>
Expose the kfd internals the knod provider needs to build and run GPU
queues on behalf of the kernel: kernel-side event waiting, GPUVM
allocation for VRAM/GTT, doorbell access, and the HSA queue/packet
layout (kfd_hsa.h). No functional change for existing user-mode
queue users; the provider itself is added in a following patch.
Signed-off-by: Taehee Yoo <ap420073@gmail.com>
(cherry picked from commit 7d2c7cbfbb2a4a80052b5793841f6a229271973d)
---
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 13 +-
.../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 65 +++
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 +
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 117 ++---
drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c | 20 +-
drivers/gpu/drm/amd/amdkfd/kfd_events.c | 112 ++++-
drivers/gpu/drm/amd/amdkfd/kfd_events.h | 4 +
drivers/gpu/drm/amd/amdkfd/kfd_hsa.h | 451 ++++++++++++++++++
drivers/gpu/drm/amd/amdkfd/kfd_module.c | 1 +
drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 34 ++
drivers/gpu/drm/amd/amdkfd/kfd_process.c | 26 +-
11 files changed, 778 insertions(+), 68 deletions(-)
create mode 100644 drivers/gpu/drm/amd/amdkfd/kfd_hsa.h
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index e443a7277299..cf906b32eacb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -328,6 +328,8 @@ int amdgpu_amdkfd_gpuvm_sync_memory(
struct amdgpu_device *adev, struct kgd_mem *mem, bool intr);
int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
void **kptr, uint64_t *size);
+int amdgpu_amdkfd_gpuvm_map_vram_bo_to_kernel(struct kgd_mem *mem,
+ void **kptr, uint64_t *size);
void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct kgd_mem *mem);
int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_bo *bo, struct amdgpu_bo **bo_gart);
@@ -446,7 +448,6 @@ bool kgd2kfd_vmfault_fast_path(struct amdgpu_device *adev, struct amdgpu_iv_entr
bool retry_fault);
void kgd2kfd_lock_kfd(void);
void kgd2kfd_teardown_processes(struct amdgpu_device *adev);
-
#else
static inline int kgd2kfd_init(void)
{
@@ -576,5 +577,15 @@ static inline void kgd2kfd_teardown_processes(struct amdgpu_device *adev)
{
}
+#endif
+
+#if defined(CONFIG_HSA_AMD_KNOD)
+int knod_init(struct amdgpu_device *adev);
+void knod_fini(struct amdgpu_device *adev);
+void knod_exit(void);
+#else
+static inline int knod_init(struct amdgpu_device *adev) { return 0; }
+static inline void knod_fini(struct amdgpu_device *adev) { }
+static inline void knod_exit(void) { }
#endif
#endif /* AMDGPU_AMDKFD_H_INCLUDED */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 35fe2c974699..79fd0ce7fc24 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -2336,6 +2336,71 @@ int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct kgd_mem *mem,
return ret;
}
+/** amdgpu_amdkfd_gpuvm_map_vram_bo_to_kernel() - Map a VRAM BO for kernel CPU access
+ *
+ * @mem: Buffer object to be mapped for CPU access
+ * @kptr[out]: pointer in kernel CPU address space
+ * @size[out]: size of the buffer
+ *
+ * Pins the BO and maps it for kernel CPU access. The eviction fence is removed
+ * from the BO, since pinned BOs cannot be evicted. The bo must remain on the
+ * validate_list, so the GPU mapping can be restored after a page table was
+ * evicted.
+ *
+ * Return: 0 on success, error code on failure
+ */
+int amdgpu_amdkfd_gpuvm_map_vram_bo_to_kernel(struct kgd_mem *mem,
+ void **kptr, uint64_t *size)
+{
+ int ret;
+ struct amdgpu_bo *bo = mem->bo;
+
+ if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) {
+ pr_err("userptr can't be mapped to kernel\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(&mem->process_info->lock);
+
+ ret = amdgpu_bo_reserve(bo, true);
+ if (ret) {
+ pr_err("Failed to reserve bo. ret %d\n", ret);
+ goto bo_reserve_failed;
+ }
+
+ ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_VRAM);
+ if (ret) {
+ pr_err("Failed to pin bo. ret %d\n", ret);
+ goto pin_failed;
+ }
+
+ ret = amdgpu_bo_kmap(bo, kptr);
+ if (ret) {
+ pr_err("Failed to map bo to kernel. ret %d\n", ret);
+ goto kmap_failed;
+ }
+
+ amdgpu_amdkfd_remove_eviction_fence(
+ bo, mem->process_info->eviction_fence);
+
+ if (size)
+ *size = amdgpu_bo_size(bo);
+
+ amdgpu_bo_unreserve(bo);
+
+ mutex_unlock(&mem->process_info->lock);
+ return 0;
+
+kmap_failed:
+ amdgpu_bo_unpin(bo);
+pin_failed:
+ amdgpu_bo_unreserve(bo);
+bo_reserve_failed:
+ mutex_unlock(&mem->process_info->lock);
+
+ return ret;
+}
+
/** amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel() - Unmap a GTT BO for kernel CPU access
*
* @mem: Buffer object to be unmapped for CPU access
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 4c0c77eafbd1..aa974929d22a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -2480,6 +2480,8 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
drm_client_setup(adev_to_drm(adev), format);
}
+ knod_init(adev);
+
ret = amdgpu_debugfs_init(adev);
if (ret)
DRM_ERROR("Creating debugfs files failed (%d).\n", ret);
@@ -2540,6 +2542,7 @@ amdgpu_pci_remove(struct pci_dev *pdev)
struct drm_device *dev = pci_get_drvdata(pdev);
struct amdgpu_device *adev = drm_to_adev(dev);
+ knod_fini(adev);
amdgpu_ras_eeprom_check_and_recover(adev);
amdgpu_xcp_dev_unplug(adev);
amdgpu_gmc_prepare_nps_mode_change(adev);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index c7edebd2fd8a..7879a6ffaa76 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -335,32 +335,27 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties,
return 0;
}
-static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
- void *data)
+/*
+ * Create a queue from a kernel-filled queue_properties. @q_properties is
+ * owned by the caller and must already be populated (the ioctl handler does
+ * this from user args via set_queue_properties_from_user(); in-kernel callers
+ * fill it directly). On success *@queue_id_out and *@doorbell_offset_out are
+ * set.
+ */
+int kfd_create_queue(struct kfd_process *p, struct queue_properties *q_properties,
+ u32 gpu_id, u32 *queue_id_out, u64 *doorbell_offset_out)
{
- struct kfd_ioctl_create_queue_args *args = data;
struct kfd_node *dev;
int err = 0;
unsigned int queue_id;
struct kfd_process_device *pdd;
- struct queue_properties q_properties;
uint32_t doorbell_offset_in_process = 0;
- memset(&q_properties, 0, sizeof(struct queue_properties));
-
- pr_debug("Creating queue ioctl\n");
-
- err = set_queue_properties_from_user(&q_properties, args);
- if (err)
- return err;
-
- pr_debug("Looking for gpu id 0x%x\n", args->gpu_id);
-
mutex_lock(&p->mutex);
- pdd = kfd_process_device_data_by_id(p, args->gpu_id);
+ pdd = kfd_process_device_data_by_id(p, gpu_id);
if (!pdd) {
- pr_debug("Could not find gpu id 0x%x\n", args->gpu_id);
+ pr_debug("Could not find gpu id 0x%x\n", gpu_id);
err = -EINVAL;
goto err_pdd;
}
@@ -372,14 +367,14 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
goto err_bind_process;
}
- if (q_properties.type == KFD_QUEUE_TYPE_SDMA_BY_ENG_ID) {
+ if (q_properties->type == KFD_QUEUE_TYPE_SDMA_BY_ENG_ID) {
int max_sdma_eng_id = kfd_get_num_sdma_engines(dev) +
kfd_get_num_xgmi_sdma_engines(dev) - 1;
- if (q_properties.sdma_engine_id > max_sdma_eng_id) {
+ if (q_properties->sdma_engine_id > max_sdma_eng_id) {
err = -EINVAL;
pr_err("sdma_engine_id %i exceeds maximum id of %i\n",
- q_properties.sdma_engine_id, max_sdma_eng_id);
+ q_properties->sdma_engine_id, max_sdma_eng_id);
goto err_sdma_engine_id;
}
}
@@ -392,7 +387,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
}
}
- err = kfd_queue_acquire_buffers(pdd, &q_properties);
+ err = kfd_queue_acquire_buffers(pdd, q_properties);
if (err) {
pr_debug("failed to acquire user queue buffers\n");
goto err_acquire_queue_buf;
@@ -402,42 +397,32 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
p->lead_thread->pid,
dev->id);
- err = pqm_create_queue(&p->pqm, dev, &q_properties, &queue_id,
+ err = pqm_create_queue(&p->pqm, dev, q_properties, &queue_id,
NULL, NULL, NULL, &doorbell_offset_in_process);
if (err != 0)
goto err_create_queue;
- args->queue_id = queue_id;
-
+ *queue_id_out = queue_id;
/* Return gpu_id as doorbell offset for mmap usage */
- args->doorbell_offset = KFD_MMAP_TYPE_DOORBELL;
- args->doorbell_offset |= KFD_MMAP_GPU_ID(args->gpu_id);
+ *doorbell_offset_out = KFD_MMAP_TYPE_DOORBELL;
+ *doorbell_offset_out |= KFD_MMAP_GPU_ID(gpu_id);
if (KFD_IS_SOC15(dev))
/* On SOC15 ASICs, include the doorbell offset within the
* process doorbell frame, which is 2 pages.
*/
- args->doorbell_offset |= doorbell_offset_in_process;
+ *doorbell_offset_out |= doorbell_offset_in_process;
mutex_unlock(&p->mutex);
- pr_debug("Queue id %d was created successfully\n", args->queue_id);
-
- pr_debug("Ring buffer address == 0x%016llX\n",
- args->ring_base_address);
-
- pr_debug("Read ptr address == 0x%016llX\n",
- args->read_pointer_address);
-
- pr_debug("Write ptr address == 0x%016llX\n",
- args->write_pointer_address);
+ pr_debug("Queue id %d was created successfully\n", queue_id);
kfd_dbg_ev_raise(KFD_EC_MASK(EC_QUEUE_NEW), p, dev, queue_id, false, NULL, 0);
return 0;
err_create_queue:
- kfd_queue_unref_bo_vas(pdd, &q_properties);
- kfd_queue_release_buffers(pdd, &q_properties);
+ kfd_queue_unref_bo_vas(pdd, q_properties);
+ kfd_queue_release_buffers(pdd, q_properties);
err_acquire_queue_buf:
err_sdma_engine_id:
err_bind_process:
@@ -446,6 +431,23 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
return err;
}
+static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p,
+ void *data)
+{
+ struct kfd_ioctl_create_queue_args *args = data;
+ struct queue_properties q_properties;
+ int err;
+
+ memset(&q_properties, 0, sizeof(q_properties));
+
+ err = set_queue_properties_from_user(&q_properties, args);
+ if (err)
+ return err;
+
+ return kfd_create_queue(p, &q_properties, args->gpu_id,
+ &args->queue_id, &args->doorbell_offset);
+}
+
static int kfd_ioctl_destroy_queue(struct file *filp, struct kfd_process *p,
void *data)
{
@@ -643,7 +645,7 @@ static int kfd_ioctl_set_memory_policy(struct file *filep,
return err;
}
-static int kfd_ioctl_set_trap_handler(struct file *filep,
+int kfd_ioctl_set_trap_handler(struct file *filep,
struct kfd_process *p, void *data)
{
struct kfd_ioctl_set_trap_handler_args *args = data;
@@ -726,7 +728,7 @@ static int kfd_ioctl_get_clock_counters(struct file *filep,
static int kfd_ioctl_get_process_apertures(struct file *filp,
- struct kfd_process *p, void *data)
+ struct kfd_process *p, void *data)
{
struct kfd_ioctl_get_process_apertures_args *args = data;
struct kfd_process_device_apertures *pAperture;
@@ -859,7 +861,7 @@ static int kfd_ioctl_get_process_apertures_new(struct file *filp,
}
static int kfd_ioctl_create_event(struct file *filp, struct kfd_process *p,
- void *data)
+ void *data)
{
struct kfd_ioctl_create_event_args *args = data;
int err;
@@ -894,24 +896,24 @@ static int kfd_ioctl_destroy_event(struct file *filp, struct kfd_process *p,
return kfd_event_destroy(p, args->event_id);
}
-static int kfd_ioctl_set_event(struct file *filp, struct kfd_process *p,
- void *data)
+int kfd_ioctl_set_event(struct file *filp, struct kfd_process *p,
+ void *data)
{
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)
+int kfd_ioctl_reset_event(struct file *filp, struct kfd_process *p,
+ void *data)
{
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)
+int kfd_ioctl_wait_events(struct file *filp, struct kfd_process *p,
+ void *data)
{
struct kfd_ioctl_wait_events_args *args = data;
@@ -920,8 +922,9 @@ static int kfd_ioctl_wait_events(struct file *filp, struct kfd_process *p,
(args->wait_for_all != 0),
&args->timeout, &args->wait_result);
}
-static int kfd_ioctl_set_scratch_backing_va(struct file *filep,
- struct kfd_process *p, void *data)
+
+int kfd_ioctl_set_scratch_backing_va(struct file *filep,
+ struct kfd_process *p, void *data)
{
struct kfd_ioctl_set_scratch_backing_va_args *args = data;
struct kfd_process_device *pdd;
@@ -1003,8 +1006,8 @@ static int kfd_ioctl_get_tile_config(struct file *filep,
return 0;
}
-static int kfd_ioctl_acquire_vm(struct file *filep, struct kfd_process *p,
- void *data)
+int kfd_ioctl_acquire_vm(struct file *filep, struct kfd_process *p,
+ void *data)
{
struct kfd_ioctl_acquire_vm_args *args = data;
struct kfd_process_device *pdd;
@@ -1078,8 +1081,8 @@ static int kfd_ioctl_get_available_memory(struct file *filep,
return 0;
}
-static int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
- struct kfd_process *p, void *data)
+int kfd_ioctl_alloc_memory_of_gpu(struct file *filep,
+ struct kfd_process *p, void *data)
{
struct kfd_ioctl_alloc_memory_of_gpu_args *args = data;
struct kfd_process_device *pdd;
@@ -1279,8 +1282,8 @@ static int kfd_ioctl_free_memory_of_gpu(struct file *filep,
return ret;
}
-static int kfd_ioctl_map_memory_to_gpu(struct file *filep,
- struct kfd_process *p, void *data)
+int kfd_ioctl_map_memory_to_gpu(struct file *filep,
+ struct kfd_process *p, void *data)
{
struct kfd_ioctl_map_memory_to_gpu_args *args = data;
struct kfd_process_device *pdd, *peer_pdd;
@@ -1624,8 +1627,8 @@ static int kfd_ioctl_import_dmabuf(struct file *filep,
return r;
}
-static int kfd_ioctl_export_dmabuf(struct file *filep,
- struct kfd_process *p, void *data)
+int kfd_ioctl_export_dmabuf(struct file *filep,
+ struct kfd_process *p, void *data)
{
struct kfd_ioctl_export_dmabuf_args *args = data;
struct kfd_process_device *pdd;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
index fdcf7f2d1b5b..78b7e956f590 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c
@@ -145,10 +145,28 @@ int kfd_doorbell_mmap(struct kfd_node *dev, struct kfd_process *process,
vma->vm_page_prot);
}
+void __iomem *kfd_kernel_doorbell_mmap(struct kfd_node *dev,
+ struct kfd_process *process)
+{
+ phys_addr_t address;
+ struct kfd_process_device *pdd;
+
+ pdd = kfd_get_process_device_data(dev, process);
+ if (!pdd)
+ return NULL;
+
+ /* Calculate physical address of doorbell */
+ address = kfd_get_process_doorbells(pdd);
+ if (!address)
+ return NULL;
+
+ return ioremap(address, kfd_doorbell_process_slice(dev->kfd));
+}
+
/* get kernel iomem pointer for a doorbell */
void __iomem *kfd_get_kernel_doorbell(struct kfd_dev *kfd,
- unsigned int *doorbell_off)
+ unsigned int *doorbell_off)
{
u32 inx;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
index 81900b49d9d5..91ef4c61a8bc 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
@@ -326,7 +326,7 @@ static bool event_can_be_cpu_signaled(const struct kfd_event *ev)
return ev->type == KFD_EVENT_TYPE_SIGNAL;
}
-static int kfd_event_page_set(struct kfd_process *p, void *kernel_address,
+int kfd_event_page_set(struct kfd_process *p, void *kernel_address,
uint64_t size, uint64_t user_handle)
{
struct kfd_signal_page *page;
@@ -1068,6 +1068,116 @@ int kfd_wait_on_events(struct kfd_process *p,
return ret;
}
+int kfd_wait_on_events_kernel(struct kfd_process *p,
+ uint32_t num_events, void __user *data,
+ bool all, uint32_t *user_timeout_ms,
+ uint32_t *wait_result)
+{
+ struct kfd_event_data *events = (struct kfd_event_data *) data;
+ uint32_t i;
+ int ret = 0;
+
+ struct kfd_event_waiter *event_waiters = NULL;
+ long timeout = user_timeout_to_jiffies(*user_timeout_ms);
+
+ event_waiters = alloc_event_waiters(num_events);
+ if (!event_waiters) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* Use p->event_mutex here to protect against concurrent creation and
+ * destruction of events while we initialize event_waiters.
+ */
+ mutex_lock(&p->event_mutex);
+
+ for (i = 0; i < num_events; i++) {
+ struct kfd_event_data event_data;
+
+ memcpy(&event_data, &events[i], sizeof(struct kfd_event_data));
+ ret = init_event_waiter(p, &event_waiters[i], &event_data);
+ if (ret)
+ goto out_unlock;
+ }
+
+ /* Check condition once. */
+ *wait_result = test_event_condition(all, num_events, event_waiters);
+ if (*wait_result == KFD_IOC_WAIT_RESULT_COMPLETE) {
+ ret = copy_signaled_event_data(num_events,
+ event_waiters, events);
+ goto out_unlock;
+ } else if (WARN_ON(*wait_result == KFD_IOC_WAIT_RESULT_FAIL)) {
+ /* This should not happen. Events shouldn't be
+ * destroyed while we're holding the event_mutex
+ */
+ goto out_unlock;
+ }
+
+ mutex_unlock(&p->event_mutex);
+
+ while (true) {
+ if (fatal_signal_pending(current)) {
+ ret = -EINTR;
+ break;
+ }
+
+ if (signal_pending(current)) {
+ ret = -ERESTARTSYS;
+ if (*user_timeout_ms != KFD_EVENT_TIMEOUT_IMMEDIATE &&
+ *user_timeout_ms != KFD_EVENT_TIMEOUT_INFINITE)
+ *user_timeout_ms = jiffies_to_msecs(
+ max(0l, timeout-1));
+ break;
+ }
+
+ /* Set task state to interruptible sleep before
+ * checking wake-up conditions. A concurrent wake-up
+ * will put the task back into runnable state. In that
+ * case schedule_timeout will not put the task to
+ * sleep and we'll get a chance to re-check the
+ * updated conditions almost immediately. Otherwise,
+ * this race condition would lead to a soft hang or a
+ * very long sleep.
+ */
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ *wait_result = test_event_condition(all, num_events,
+ event_waiters);
+ if (*wait_result != KFD_IOC_WAIT_RESULT_TIMEOUT)
+ break;
+
+ if (timeout <= 0)
+ break;
+
+ timeout = schedule_timeout(timeout);
+ }
+ __set_current_state(TASK_RUNNING);
+
+ mutex_lock(&p->event_mutex);
+ /* copy_signaled_event_data may sleep. So this has to happen
+ * after the task state is set back to RUNNING.
+ *
+ * The event may also have been destroyed after signaling. So
+ * copy_signaled_event_data also must confirm that the event
+ * still exists. Therefore this must be under the p->event_mutex
+ * which is also held when events are destroyed.
+ */
+ if (!ret && *wait_result == KFD_IOC_WAIT_RESULT_COMPLETE)
+ ret = copy_signaled_event_data(num_events,
+ event_waiters, events);
+
+out_unlock:
+ free_waiters(num_events, event_waiters, ret == -ERESTARTSYS);
+ mutex_unlock(&p->event_mutex);
+out:
+ if (ret)
+ *wait_result = KFD_IOC_WAIT_RESULT_FAIL;
+ else if (*wait_result == KFD_IOC_WAIT_RESULT_FAIL)
+ ret = -EIO;
+
+ return ret;
+}
+
int kfd_event_mmap(struct kfd_process *p, struct vm_area_struct *vma)
{
unsigned long pfn;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_events.h
index 1dc21c13833b..aa6ead122084 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.h
@@ -87,5 +87,9 @@ struct kfd_event {
extern void kfd_signal_event_interrupt(u32 pasid, uint32_t partial_id,
uint32_t valid_id_bits,
bool signal_mailbox_updated);
+int kfd_wait_on_events_kernel(struct kfd_process *p,
+ uint32_t num_events, void __user *data,
+ bool all, uint32_t *user_timeout_ms,
+ uint32_t *wait_result);
#endif
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_hsa.h b/drivers/gpu/drm/amd/amdkfd/kfd_hsa.h
new file mode 100644
index 000000000000..794688c615f0
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_hsa.h
@@ -0,0 +1,451 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef KFD_HSA_CODE_H_
+#define KFD_HSA_CODE_H_
+
+struct amd_queue_properties {
+ u32 enable_trap_handler:1,
+ is_ptr64:1,
+ enable_trap_handler_debug_sgprs:1,
+ enable_profiling:1,
+ use_scratch_once:1,
+ reserved1:27;
+};
+
+enum hsa_packet_type {
+ /*
+ * Vendor-specific packet.
+ */
+ HSA_PACKET_TYPE_VENDOR_SPECIFIC = 0,
+ /*
+ * The packet has been processed in the past, but has not been reassigned to
+ * the packet processor. A packet processor must not process a packet of this
+ * type. All queues support this packet type.
+ */
+ HSA_PACKET_TYPE_INVALID = 1,
+ /*
+ * Packet used by agents for dispatching jobs to kernel agents. Not all
+ * queues support packets of this type (see ::hsa_queue_feature_t).
+ */
+ HSA_PACKET_TYPE_KERNEL_DISPATCH = 2,
+ /*
+ * Packet used by agents to delay processing of subsequent packets, and to
+ * express complex dependencies between multiple packets. All queues support
+ * this packet type.
+ */
+ HSA_PACKET_TYPE_BARRIER_AND = 3,
+ /*
+ * Packet used by agents for dispatching jobs to agents. Not all
+ * queues support packets of this type (see ::hsa_queue_feature_t).
+ */
+ HSA_PACKET_TYPE_AGENT_DISPATCH = 4,
+ /*
+ * Packet used by agents to delay processing of subsequent packets, and to
+ * express complex dependencies between multiple packets. All queues support
+ * this packet type.
+ */
+ HSA_PACKET_TYPE_BARRIER_OR = 5
+};
+
+enum hsa_packet_header {
+ /*
+ * Packet type. The value of this sub-field must be one of
+ * ::hsa_packet_type_t. If the type is ::HSA_PACKET_TYPE_VENDOR_SPECIFIC, the
+ * packet layout is vendor-specific.
+ */
+ HSA_PACKET_HEADER_TYPE = 0,
+ /*
+ * Barrier bit. If the barrier bit is set, the processing of the current
+ * packet only launches when all preceding packets (within the same queue) are
+ * complete.
+ */
+ HSA_PACKET_HEADER_BARRIER = 8,
+ /*
+ * Acquire fence scope. The value of this sub-field determines the scope and
+ * type of the memory fence operation applied before the packet enters the
+ * active phase. An acquire fence ensures that any subsequent global segment
+ * or image loads by any unit of execution that belongs to a dispatch that has
+ * not yet entered the active phase on any queue of the same kernel agent,
+ * sees any data previously released at the scopes specified by the acquire
+ * fence. The value of this sub-field must be one of ::hsa_fence_scope_t.
+ */
+ HSA_PACKET_HEADER_ACQUIRE_FENCE_SCOPE = 9,
+ /*
+ * Release fence scope, The value of this sub-field determines the scope and
+ * type of the memory fence operation applied after kernel completion but
+ * before the packet is completed. A release fence makes any global segment or
+ * image data that was stored by any unit of execution that belonged to a
+ * dispatch that has completed the active phase on any queue of the same
+ * kernel agent visible in all the scopes specified by the release fence. The
+ * value of this sub-field must be one of ::hsa_fence_scope_t.
+ */
+ HSA_PACKET_HEADER_RELEASE_FENCE_SCOPE = 11
+};
+
+struct code_properties {
+ /* 4-sgprs */
+ u16 enable_sgpr_private_segment_buffer:1,
+ /* 2-sgprs */
+ enable_sgpr_dispatch_ptr:1,
+ /* 2-sgprs */
+ enable_sgpr_queue_ptr:1,
+ /* 2-sgprs */
+ enable_sgpr_kernarg_segment_ptr:1,
+ /* 2-sgprs */
+ enable_sgpr_dispatch_id:1,
+ /* 2-sgprs */
+ enable_sgpr_flat_scratch_init:1,
+ /* 2-sgprs */
+ enable_sgpr_private_segment_size:1,
+ reserved0:3,
+ enable_wavefront_size32:1, // gfx10+
+ uses_dynamic_stack:1,
+ reserved1:4;
+};
+
+struct compute_pgm_rsrc1 {
+ u32 granulated_workitem_vgpr_count:6,
+ granulated_wavefront_sgpr_count:4,
+ priority:2,
+ float_round_mode_32:2,
+ float_round_mode_16_64:2,
+ float_denorm_mode_32:2,
+ float_denorm_mode_16_64:2,
+ priv:1,
+ enable_dx10_clamp:1,
+ debug_mode:1,
+ enable_ieee_mode:1,
+ bulky:1,
+ cdbg_user:1,
+ fp16_ovfl:1, /* gfx9+ */
+ reserved0:2,
+ wgp_mode:1, /* gfx10+ */
+ mem_ordered:1, /* gfx10+ */
+ fwd_progress:1; /* gfx10+ */
+};
+
+struct compute_pgm_rsrc2 {
+ /* 1-sgprs
+ * enable_sgpr_private_segment_wavefront_offset
+ */
+ u32 enable_private_segment:1,
+ /* More or equal to enable_sgpr_*.
+ * Exceed 16 will be ignored.
+ */
+ user_sgpr_count:5,
+ enable_trap_handler:1,
+ /* 1-sgpr */
+ enable_sgpr_workgroup_id_x:1,
+ /* 1-sgpr */
+ enable_sgpr_workgroup_id_y:1,
+ /* 1-sgpr */
+ enable_sgpr_workgroup_id_z:1,
+ /* 1-sgpr */
+ enable_sgpr_workgroup_info:1,
+ enable_vgpr_workitem_id:2,
+ enable_exception_address_watch:1,
+ enable_exception_memory:1,
+ granulated_lds_size:9,
+ enable_exception_ieee_754_fp_invalid_operation:1,
+ enable_exception_fp_denormal_source:1,
+ enable_exception_ieee_754_fp_division_by_zero:1,
+ enable_exception_ieee_754_fp_overflow:1,
+ enable_exception_ieee_754_fp_underflow:1,
+ enable_exception_ieee_754_fp_inexact:1,
+ enable_exception_int_divide_by_zero:1,
+ reserved0:1;
+};
+
+struct compute_pgm_rsrc3 {
+ u32 accum_offset:6,
+ reserved0:10,
+ tg_split:1,
+ reserved1:15;
+};
+
+struct kernel_descriptor {
+ u32 group_segment_fixed_size;
+ u32 private_segment_fixed_size;
+ u32 kernarg_size;
+ u8 reserved0[4];
+ s64 kernel_code_entry_byte_offset;
+ u8 reserved1[20];
+ struct compute_pgm_rsrc3 compute_pgm_rsrc3; /* GFX10+ and GFX90A+ */
+ struct compute_pgm_rsrc1 compute_pgm_rsrc1;
+ struct compute_pgm_rsrc2 compute_pgm_rsrc2;
+ struct code_properties code_properties;
+ u8 reserved2[6];
+};
+
+enum hsa_queue_type {
+ HSA_QUEUE_TYPE_MULTI = 0,
+ HSA_QUEUE_TYPE_SINGLE = 1
+};
+
+enum hsa_queue_feature {
+ HSA_QUEUE_FEATURE_KERNEL_DISPATCH = 1,
+ HSA_QUEUE_FEATURE_AGENT_DISPATCH = 2
+};
+
+struct hsa_kernel_dispatch_packet {
+ u16 header;
+ u16 setup;
+ u16 workgroup_size_x;
+ u16 workgroup_size_y;
+ u16 workgroup_size_z;
+ u16 reserved0;
+ u32 grid_size_x;
+ u32 grid_size_y;
+ u32 grid_size_z;
+ u32 private_segment_size;
+ u32 group_segment_size;
+ u64 kernel_object;
+ void *kernarg_address;
+ u64 reserved2;
+ u64 completion_signal;
+};
+
+enum amd_signal_kind {
+ AMD_SIGNAL_KIND_INVALID = 0,
+ AMD_SIGNAL_KIND_USER = 1,
+ AMD_SIGNAL_KIND_DOORBELL = -1,
+ AMD_SIGNAL_KIND_LEGACY_DOORBELL = -2
+};
+
+/* An AMD Signal object must always be 64 byte aligned to ensure it cannot
+ * span a page boundary. This is required by CP microcode which optimizes
+ * access to the structure by only doing a single SUA (System Uniform Address)
+ * translation when accessing signal fields. This optimization is used in GFX8.
+ */
+struct amd_signal {
+ u64 kind;
+ union {
+ volatile s64 value;
+ volatile u32 *legacy_hardware_doorbell_ptr;
+ volatile u64 *hardware_doorbell_ptr;
+ };
+ /* For AMD_SIGNAL_KIND_USER: mailbox address for event notification
+ * in Signal operations.
+ */
+ u64 event_mailbox_ptr;
+ /* For AMD_SIGNAL_KIND_USER: event id for event notification in Signal
+ * operations.
+ */
+ u32 event_id;
+ u32 reserved1;
+ /* Start of the AQL packet timestamp, when profiled. */
+ u64 start_ts;
+ /* End of the AQL packet timestamp, when profiled. */
+ u64 end_ts;
+ union {
+ /* For AMD_SIGNAL_KIND_*DOORBELL: the address of the associated
+ * amd_queue, otherwise reserved and must be 0.
+ */
+ void *queue_ptr;
+ u64 reserved2;
+ };
+ u32 reserved3[2];
+} __aligned(64);
+
+struct hsa_queue {
+ u32 type;
+
+ u32 features;
+
+ void *base_address;
+ /*
+ * Signal object used by the application to indicate the ID of a packet that
+ * is ready to be processed. The HSA runtime manages the doorbell signal. If
+ * the application tries to replace or destroy this signal, the behavior is
+ * undefined.
+ *
+ * If @a type is ::HSA_QUEUE_TYPE_SINGLE, the doorbell signal value must be
+ * updated in a monotonically increasing fashion. If @a type is
+ * ::HSA_QUEUE_TYPE_MULTI, the doorbell signal value can be updated with any
+ * value.
+ */
+ u64 doorbell_signal;
+
+ /*
+ * Maximum number of packets the queue can hold. Must be a power of 2.
+ */
+ u32 size;
+ /* Reserved. Must be 0. */
+ u32 reserved1;
+ /*
+ * Queue identifier, which is unique over the lifetime of the application.
+ */
+ u64 id;
+
+};
+
+enum hsa_fence_scope {
+ HSA_FENCE_SCOPE_NONE = 0,
+ HSA_FENCE_SCOPE_AGENT = 1,
+ HSA_FENCE_SCOPE_SYSTEM = 2
+};
+
+struct amd_queue {
+ struct hsa_queue hsa_queue;
+ u32 reserved1[4];
+ volatile u64 write_dispatch_id;
+ u32 group_segment_aperture_base_hi;
+ u32 private_segment_aperture_base_hi;
+ u32 max_cu_id;
+ u32 max_wave_id;
+ volatile u64 max_legacy_doorbell_dispatch_id_plus_1;
+ volatile u32 legacy_doorbell_lock;
+ u32 reserved2[9];
+ volatile u64 read_dispatch_id;
+ u32 read_dispatch_id_field_base_byte_offset;
+ u32 compute_tmpring_size;
+ u32 scratch_resource_descriptor[4];
+ u64 scratch_backing_memory_location;
+ u64 scratch_backing_memory_byte_size;
+ u32 scratch_wave64_lane_byte_size;
+ struct amd_queue_properties queue_properties;
+ u32 reserved3[2];
+ u64 queue_inactive_signal;
+ u32 reserved4[14];
+} __aligned(64);
+
+struct hsa_sync_var {
+ union {
+ /* pointer to user mode data */
+ void *user_data;
+ /* 64bit compatibility of value */
+ u64 user_data_ptr_value;
+ };
+ u64 SyncVarSize;
+};
+
+enum hsa_event_type {
+ /* user-mode generated GPU signal */
+ HSA_EVENTTYPE_SIGNAL = 0,
+ /* HSA node change (attach/detach) */
+ HSA_EVENTTYPE_NODECHANGE = 1,
+ /* HSA device state change( start/stop ) */
+ HSA_EVENTTYPE_DEVICESTATECHANGE = 2,
+ /* GPU shader exception event */
+ HSA_EVENTTYPE_HW_EXCEPTION = 3,
+ /* GPU SYSCALL with parameter info */
+ HSA_EVENTTYPE_SYSTEM_EVENT = 4,
+ /* GPU signal for debugging */
+ HSA_EVENTTYPE_DEBUG_EVENT = 5,
+ /* GPU signal for profiling */
+ HSA_EVENTTYPE_PROFILE_EVENT = 6,
+ /* GPU signal queue idle state (EOP pm4) */
+ HSA_EVENTTYPE_QUEUE_EVENT = 7,
+ /* GPU signal for signaling memory access faults and memory subsystem issues */
+ HSA_EVENTTYPE_MEMORY = 8,
+ /* ... */
+ HSA_EVENTTYPE_MAXID,
+ HSA_EVENTTYPE_TYPE_SIZE = 0xffffffff
+};
+
+enum hsa_eventtype_nodechange_flags {
+ HSA_EVENTTYPE_NODECHANGE_ADD = 0,
+ HSA_EVENTTYPE_NODECHANGE_REMOVE = 1,
+ HSA_EVENTTYPE_NODECHANGE_SIZE = 0xffffffff
+};
+
+struct hsa_node_change {
+ /* HSA node added/removed on the platform */
+ enum hsa_eventtype_nodechange_flags flags;
+};
+
+enum hsa_device {
+ HSA_DEVICE_CPU = 0,
+ HSA_DEVICE_GPU = 1,
+ MAX_HSA_DEVICE = 2
+};
+
+enum hsa_eventtype_devicestatechange_flags {
+ /* device started (and available) */
+ HSA_EVENTTYPE_DEVICESTATUSCHANGE_START = 0,
+ /* device stopped (i.e. unavailable) */
+ HSA_EVENTTYPE_DEVICESTATUSCHANGE_STOP = 1,
+ HSA_EVENTTYPE_DEVICESTATUSCHANGE_SIZE = 0xffffffff
+};
+
+struct hsa_device_state_change {
+ /* F-NUMA node that contains the device */
+ u32 node_id;
+ /* device type: GPU or CPU */
+ enum hsa_device device;
+ /* event flags */
+ enum hsa_eventtype_devicestatechange_flags flags;
+};
+
+struct hsa_access_attribute_failure {
+ /* Page not present or supervisor privilege */
+ unsigned int not_present:1;
+ /* Write access to a read-only page */
+ unsigned int readonly:1;
+ /* Execute access to a page marked NX */
+ unsigned int no_execute:1;
+ /* Host access only */
+ unsigned int gpu_access:1;
+ /* RAS ECC failure (notification of DRAM ECC - non-recoverable -
+ * error, if supported by HW)
+ */
+ unsigned int ecc:1;
+ /* Can't determine the exact fault address */
+ unsigned int imprecise:1;
+ /* Indicates RAS errors or other errors causing the access to GPU to fail
+ * 0 = no RAS error,
+ * 1 = ECC_SRAM,
+ * 2 = Link_SYNFLOOD (poison),
+ * 3 = GPU hang (not attributable to a specific cause), other values reserved
+ */
+ unsigned int error_type:3;
+ /* must be 0 */
+ unsigned int Reserved:23;
+};
+
+enum hsa_eventid_memory_flags {
+ /* access fault, recoverable after page adjustment */
+ HSA_EVENTID_MEMORY_RECOVERABLE = 0,
+ /* memory access requires process context destruction, unrecoverable */
+ HSA_EVENTID_MEMORY_FATAL_PROCESS = 1,
+ /* memory access requires all GPU VA context destruction, unrecoverable */
+ HSA_EVENTID_MEMORY_FATAL_VM = 2,
+};
+
+struct hsa_memory_access_fault {
+ /* H-NUMA node that contains the device where the memory access occurred */
+ u32 node_id;
+ /* virtual address this occurred on */
+ u64 virtual_address;
+ /* failure attribute */
+ struct hsa_access_attribute_failure failure;
+ /* event flags */
+ enum hsa_eventid_memory_flags flags;
+};
+
+struct hsa_event_data {
+ enum hsa_event_type event_type;
+
+ union {
+ /* return data associated with HSA_EVENTTYPE_SIGNAL and other events */
+ struct hsa_sync_var sync_var;
+ /* data associated with HSA_EVENTTYPE_NODE_CHANGE */
+ struct hsa_node_change node_change_state;
+ /* data associated with HSA_EVENTTYPE_DEVICE_STATE_CHANGE */
+ struct hsa_device_state_change device_state;
+ /* data associated with HSA_EVENTTYPE_MEMORY */
+ struct hsa_memory_access_fault memory_access_fault;
+ };
+
+ // the following data entries are internal to the KFD & thunk itself.
+
+ u64 hw_data1; // internal thunk store for Event data (OsEventHandle)
+ u64 hw_data2; // internal thunk store for Event data (HWAddress)
+ u32 hw_data3; // internal thunk store for Event data (HWData)
+};
+
+struct hsa_event {
+ u32 event_id;
+ struct hsa_event_data event_data;
+};
+
+#endif /* KFD_HSA_CODE_H_ */
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_module.c b/drivers/gpu/drm/amd/amdkfd/kfd_module.c
index 33aa23450b3f..2a2405db5b9c 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_module.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_module.c
@@ -77,6 +77,7 @@ static int kfd_init(void)
static void kfd_exit(void)
{
+ knod_exit();
kfd_cleanup_processes();
kfd_process_destroy_wq();
kfd_debugfs_fini();
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index acd0e41e744c..4f5d4b0bfa89 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -1069,6 +1069,7 @@ bool kfd_dev_is_large_bar(struct kfd_node *dev);
struct kfd_process *create_process(const struct task_struct *thread, bool primary);
int kfd_process_create_wq(void);
void kfd_process_destroy_wq(void);
+void kfd_process_flush_wq(void);
void kfd_cleanup_processes(void);
struct kfd_process *kfd_create_process(struct task_struct *thread);
int kfd_create_process_sysfs(struct kfd_process *process);
@@ -1536,6 +1537,9 @@ void kfd_signal_hw_exception_event(u32 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_kmap_event_page(struct kfd_process *p, uint64_t event_page_offset);
+int kfd_event_page_set(struct kfd_process *p, void *kernel_address,
+ uint64_t size, uint64_t user_handle);
+
int kfd_event_create(struct file *devkfd, struct kfd_process *p,
uint32_t event_type, bool auto_reset, uint32_t node_id,
@@ -1641,3 +1645,33 @@ static inline void kfd_debugfs_remove_process(struct kfd_process *p) {}
#endif
#endif
+
+int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd,
+ uint64_t gpu_va, uint32_t size,
+ uint32_t flags, struct kgd_mem **mem, void **kptr);
+void kfd_process_free_gpuvm(struct kgd_mem *mem,
+ struct kfd_process_device *pdd, void **kptr);
+int kfd_create_queue(struct kfd_process *p, struct queue_properties *q_properties,
+ u32 gpu_id, u32 *queue_id_out, u64 *doorbell_offset_out);
+int kfd_ioctl_set_event(struct file *filp, struct kfd_process *p,
+ void *data);
+int kfd_ioctl_reset_event(struct file *filp, struct kfd_process *p,
+ void *data);
+int kfd_ioctl_wait_events(struct file *filp, struct kfd_process *p, void *data);
+
+int kfd_ioctl_set_trap_handler(struct file *filep,
+ struct kfd_process *p, void *data);
+int kfd_ioctl_set_scratch_backing_va(struct file *filep,
+ struct kfd_process *p, void *data);
+
+
+int kfd_ioctl_acquire_vm(struct file *filep, struct kfd_process *p, void *data);
+int kfd_ioctl_map_memory_to_gpu(struct file *filep, struct kfd_process *p,
+ void *data);
+int kfd_ioctl_alloc_memory_of_gpu(struct file *filep, struct kfd_process *p,
+ void *data);
+int kfd_ioctl_export_dmabuf(struct file *filep,
+ struct kfd_process *p, void *data);
+
+void __iomem *kfd_kernel_doorbell_mmap(struct kfd_node *dev,
+ struct kfd_process *process);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index ca71fa726e32..3c9268241800 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -715,8 +715,14 @@ void kfd_process_destroy_wq(void)
}
}
-static void kfd_process_free_gpuvm(struct kgd_mem *mem,
- struct kfd_process_device *pdd, void **kptr)
+void kfd_process_flush_wq(void)
+{
+ if (kfd_process_wq)
+ flush_workqueue(kfd_process_wq);
+}
+
+void kfd_process_free_gpuvm(struct kgd_mem *mem,
+ struct kfd_process_device *pdd, void **kptr)
{
struct kfd_node *dev = pdd->dev;
@@ -736,9 +742,9 @@ static void kfd_process_free_gpuvm(struct kgd_mem *mem,
* to avoid concurrency. Because of that exclusiveness, we do
* not need to take p->mutex.
*/
-static int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd,
- uint64_t gpu_va, uint32_t size,
- uint32_t flags, struct kgd_mem **mem, void **kptr)
+int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd,
+ uint64_t gpu_va, uint32_t size,
+ uint32_t flags, struct kgd_mem **mem, void **kptr)
{
struct kfd_node *kdev = pdd->dev;
int err;
@@ -761,10 +767,14 @@ static int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd,
}
if (kptr) {
- err = amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(
- (struct kgd_mem *)*mem, kptr, NULL);
+ if (flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM)
+ err = amdgpu_amdkfd_gpuvm_map_vram_bo_to_kernel(
+ (struct kgd_mem *)*mem, kptr, NULL);
+ else
+ err = amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(
+ (struct kgd_mem *)*mem, kptr, NULL);
if (err) {
- pr_debug("Map GTT BO to kernel failed\n");
+ pr_debug("Map BO to kernel failed\n");
goto sync_memory_failed;
}
}
--
2.43.0
next prev parent reply other threads:[~2026-07-19 18:00 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-19 17:58 [RFC PATCH net-next 00/13] net: knod: in-kernel network offload device Taehee Yoo
2026-07-19 17:58 ` [RFC PATCH net-next 01/13] net: knod: add uapi and core headers Taehee Yoo
2026-07-19 17:58 ` [RFC PATCH net-next 02/13] net: devmem: extend memory provider for knod Taehee Yoo
2026-07-20 19:43 ` Mina Almasry
2026-07-19 17:58 ` [RFC PATCH net-next 03/13] net: core: add XDP_MODE_HW offload hook " Taehee Yoo
2026-07-19 17:58 ` [RFC PATCH net-next 04/13] net: knod: add offload device core and control plane Taehee Yoo
2026-07-19 17:58 ` [RFC PATCH net-next 05/13] bpf: offload: allow PERCPU_ARRAY maps for offloaded programs Taehee Yoo
2026-07-19 17:58 ` Taehee Yoo [this message]
2026-07-19 17:58 ` [RFC PATCH net-next 07/13] drm/amdkfd: add knod provider core Taehee Yoo
2026-07-19 17:58 ` [RFC PATCH net-next 08/13] drm/amdkfd: add GPU instruction emitter and disassembler Taehee Yoo
2026-07-20 20:05 ` Natalie Vock
2026-07-20 20:53 ` Andrew Lunn
2026-07-19 17:58 ` [RFC PATCH net-next 09/13] drm/amdkfd: add BPF-to-GPU JIT offload Taehee Yoo
2026-07-19 17:58 ` [RFC PATCH net-next 10/13] net/mlx5e: add knod XDP offload support Taehee Yoo
2026-07-19 17:58 ` [RFC PATCH net-next 11/13] bnxt_en: " Taehee Yoo
2026-07-19 17:58 ` [RFC PATCH net-next 12/13] selftests: drivers/net: add knod tests Taehee Yoo
2026-07-19 17:58 ` [RFC PATCH net-next 13/13] drm/amdkfd: add IPsec full-packet offload Taehee Yoo
2026-07-20 19:18 ` [RFC PATCH net-next 00/13] net: knod: in-kernel network offload device Mina Almasry
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260719175857.4071636-7-ap420073@gmail.com \
--to=ap420073@gmail.com \
--cc=Felix.Kuehling@amd.com \
--cc=airlied@gmail.com \
--cc=alexander.deucher@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=andrew+netdev@lunn.ch \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=christian.koenig@amd.com \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=donald.hunter@gmail.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=eddyz87@gmail.com \
--cc=edumazet@google.com \
--cc=emil@etsalapatis.com \
--cc=hawk@kernel.org \
--cc=horms@kernel.org \
--cc=hoyeon.rhee@gmail.com \
--cc=ilias.apalodimas@linaro.org \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=justinstitt@google.com \
--cc=kees@kernel.org \
--cc=kuba@kernel.org \
--cc=leon@kernel.org \
--cc=linaro-mm-sig@lists.linaro.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-media@vger.kernel.org \
--cc=linux-rdma@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=martin.lau@linux.dev \
--cc=mbloch@nvidia.com \
--cc=memxor@gmail.com \
--cc=michael.chan@broadcom.com \
--cc=morbo@google.com \
--cc=nathan@kernel.org \
--cc=ndesaulniers@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pavan.chebbi@broadcom.com \
--cc=saeedm@nvidia.com \
--cc=sdf@fomichev.me \
--cc=shuah@kernel.org \
--cc=simona@ffwll.ch \
--cc=song@kernel.org \
--cc=sumit.semwal@linaro.org \
--cc=tariqt@nvidia.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox