aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdkfd
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-26 13:18:51 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-26 13:18:51 -0700
commit099bfbfc7fbbe22356c02f0caf709ac32e1126ea (patch)
treec2dfe2f9445255d866e9203cff9e9f865ef93513 /drivers/gpu/drm/amd/amdkfd
parent22165fa79814e71e7a5974b3c37a5028ed16c8f9 (diff)
parentc5fd936e992dd2829167d2adc63e151675ca6898 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "This is the main drm pull request for v4.2. I've one other new driver from freescale on my radar, it's been posted and reviewed, I'd just like to get someone to give it a last look, so maybe I'll send it or maybe I'll leave it. There is no major nouveau changes in here, Ben was working on something big, and we agreed it was a bit late, there wasn't anything else he considered urgent to merge. There might be another msm pull for some bits that are waiting on arm-soc, I'll see how we time it. This touches some "of" stuff, acks are in place except for the fixes to the build in various configs,t hat I just applied. Summary: New drivers: - virtio-gpu: KMS only pieces of driver for virtio-gpu in qemu. This is just the first part of this driver, enough to run unaccelerated userspace on. As qemu merges more we'll start adding the 3D features for the virgl 3d work. - amdgpu: a new driver from AMD to driver their newer GPUs. (VI+) It contains a new cleaner userspace API, and is a clean break from radeon moving forward, that AMD are going to concentrate on. It also contains a set of register headers auto generated from AMD internal database. core: - atomic modesetting API completed, enabled by default now. - Add support for mode_id blob to atomic ioctl to complete interface. - bunch of Displayport MST fixes - lots of misc fixes. panel: - new simple panels - fix some long-standing build issues with bridge drivers radeon: - VCE1 support - add a GPU reset counter for userspace - lots of fixes. amdkfd: - H/W debugger support module - static user-mode queues - support killing all the waves when a process terminates - use standard DECLARE_BITMAP i915: - Add Broxton support - S3, rotation support for Skylake - RPS booting tuning - CPT modeset sequence fixes - ns2501 dither support - enable cmd parser on haswell - cdclk handling fixes - gen8 dynamic pte allocation - lots of atomic conversion work exynos: - Add atomic modesetting support - Add iommu support - Consolidate drm driver initialization - and MIC, DECON and MIPI-DSI support for exynos5433 omapdrm: - atomic modesetting support (fixes lots of things in rewrite) tegra: - DP aux transaction fixes - iommu support fix msm: - adreno a306 support - various dsi bits - various 64-bit fixes - NV12MT support rcar-du: - atomic and misc fixes sti: - fix HDMI timing complaince tilcdc: - use drm component API to access tda998x driver - fix module unloading qxl: - stability fixes" * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (872 commits) drm/nouveau: Pause between setting gpu to D3hot and cutting the power drm/dp/mst: close deadlock in connector destruction. drm: Always enable atomic API drm/vgem: Set unique to "vgem" of: fix a build error to of_graph_get_endpoint_by_regs function drm/dp/mst: take lock around looking up the branch device on hpd irq drm/dp/mst: make sure mst_primary mstb is valid in work function of: add EXPORT_SYMBOL for of_graph_get_endpoint_by_regs ARM: dts: rename the clock of MIPI DSI 'pll_clk' to 'sclk_mipi' drm/atomic: Don't set crtc_state->enable manually drm/exynos: dsi: do not set TE GPIO direction by input drm/exynos: dsi: add support for MIC driver as a bridge drm/exynos: dsi: add support for Exynos5433 drm/exynos: dsi: make use of array for clock access drm/exynos: dsi: make use of driver data for static values drm/exynos: dsi: add macros for register access drm/exynos: dsi: rename pll_clk to sclk_clk drm/exynos: mic: add MIC driver of: add helper for getting endpoint node of specific identifiers drm/exynos: add Exynos5433 decon driver ...
Diffstat (limited to 'drivers/gpu/drm/amd/amdkfd')
-rw-r--r--drivers/gpu/drm/amd/amdkfd/Makefile2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c66
-rw-r--r--drivers/gpu/drm/amd/amdkfd/cik_int.h41
-rw-r--r--drivers/gpu/drm/amd/amdkfd/cik_regs.h177
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_chardev.c395
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c886
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.h193
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.c168
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_dbgmgr.h294
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device.c60
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c82
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h27
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c18
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c10
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_doorbell.c15
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_events.c969
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_events.h84
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c188
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c5
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_module.c9
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c46
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers.h6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_diq.h290
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_priv.h99
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c49
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c18
26 files changed, 3969 insertions, 228 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/Makefile b/drivers/gpu/drm/amd/amdkfd/Makefile
index 0f4960148126..28551153ec6d 100644
--- a/drivers/gpu/drm/amd/amdkfd/Makefile
+++ b/drivers/gpu/drm/amd/amdkfd/Makefile
@@ -12,5 +12,7 @@ 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_events.o cik_event_interrupt.o \
+ kfd_dbgdev.o kfd_dbgmgr.o
obj-$(CONFIG_HSA_AMD) += amdkfd.o
diff --git a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
new file mode 100644
index 000000000000..211fc48697fa
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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 "kfd_priv.h"
+#include "kfd_events.h"
+#include "cik_int.h"
+
+static bool cik_event_interrupt_isr(struct kfd_dev *dev,
+ const uint32_t *ih_ring_entry)
+{
+ unsigned int pasid;
+ const struct cik_ih_ring_entry *ihre =
+ (const struct cik_ih_ring_entry *)ih_ring_entry;
+
+ pasid = (ihre->ring_id & 0xffff0000) >> 16;
+
+ /* Do not process in ISR, just request it to be forwarded to WQ. */
+ return (pasid != 0) &&
+ (ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE ||
+ 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,
+ const uint32_t *ih_ring_entry)
+{
+ unsigned int pasid;
+ const struct cik_ih_ring_entry *ihre =
+ (const struct cik_ih_ring_entry *)ih_ring_entry;
+
+ pasid = (ihre->ring_id & 0xffff0000) >> 16;
+
+ if (pasid == 0)
+ return;
+
+ if (ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE)
+ kfd_signal_event_interrupt(pasid, 0, 0);
+ else if (ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG)
+ kfd_signal_event_interrupt(pasid, ihre->data & 0xFF, 8);
+ else if (ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE)
+ kfd_signal_hw_exception_event(pasid);
+}
+
+const struct kfd_event_interrupt_class event_interrupt_class_cik = {
+ .interrupt_isr = cik_event_interrupt_isr,
+ .interrupt_wq = cik_event_interrupt_wq,
+};
diff --git a/drivers/gpu/drm/amd/amdkfd/cik_int.h b/drivers/gpu/drm/amd/amdkfd/cik_int.h
new file mode 100644
index 000000000000..79a16d24c1b8
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdkfd/cik_int.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2014 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * 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 HSA_RADEON_CIK_INT_H_INCLUDED
+#define HSA_RADEON_CIK_INT_H_INCLUDED
+
+#include <linux/types.h>
+
+struct cik_ih_ring_entry {
+ uint32_t source_id;
+ uint32_t data;
+ uint32_t ring_id;
+ uint32_t reserved;
+};
+
+#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
+
diff --git a/drivers/gpu/drm/amd/amdkfd/cik_regs.h b/drivers/gpu/drm/amd/amdkfd/cik_regs.h
index 01ff332fabd4..183be5b8414f 100644
--- a/drivers/gpu/drm/amd/amdkfd/cik_regs.h
+++ b/drivers/gpu/drm/amd/amdkfd/cik_regs.h
@@ -23,33 +23,11 @@
#ifndef CIK_REGS_H
#define CIK_REGS_H
-#define IH_VMID_0_LUT 0x3D40u
-
-#define BIF_DOORBELL_CNTL 0x530Cu
-
-#define SRBM_GFX_CNTL 0xE44
-#define PIPEID(x) ((x) << 0)
-#define MEID(x) ((x) << 2)
-#define VMID(x) ((x) << 4)
-#define QUEUEID(x) ((x) << 8)
-
-#define SQ_CONFIG 0x8C00
-
-#define SH_MEM_BASES 0x8C28
/* if PTR32, these are the bases for scratch and lds */
#define PRIVATE_BASE(x) ((x) << 0) /* scratch */
#define SHARED_BASE(x) ((x) << 16) /* LDS */
-#define SH_MEM_APE1_BASE 0x8C2C
-/* if PTR32, this is the base location of GPUVM */
-#define SH_MEM_APE1_LIMIT 0x8C30
-/* if PTR32, this is the upper limit of GPUVM */
-#define SH_MEM_CONFIG 0x8C34
#define PTR32 (1 << 0)
-#define PRIVATE_ATC (1 << 1)
#define ALIGNMENT_MODE(x) ((x) << 2)
-#define SH_MEM_ALIGNMENT_MODE_DWORD 0
-#define SH_MEM_ALIGNMENT_MODE_DWORD_STRICT 1
-#define SH_MEM_ALIGNMENT_MODE_STRICT 2
#define SH_MEM_ALIGNMENT_MODE_UNALIGNED 3
#define DEFAULT_MTYPE(x) ((x) << 4)
#define APE1_MTYPE(x) ((x) << 7)
@@ -58,137 +36,34 @@
#define MTYPE_CACHED 0
#define MTYPE_NONCACHED 3
-
-#define SH_STATIC_MEM_CONFIG 0x9604u
-
-#define TC_CFG_L1_LOAD_POLICY0 0xAC68
-#define TC_CFG_L1_LOAD_POLICY1 0xAC6C
-#define TC_CFG_L1_STORE_POLICY 0xAC70
-#define TC_CFG_L2_LOAD_POLICY0 0xAC74
-#define TC_CFG_L2_LOAD_POLICY1 0xAC78
-#define TC_CFG_L2_STORE_POLICY0 0xAC7C
-#define TC_CFG_L2_STORE_POLICY1 0xAC80
-#define TC_CFG_L2_ATOMIC_POLICY 0xAC84
-#define TC_CFG_L1_VOLATILE 0xAC88
-#define TC_CFG_L2_VOLATILE 0xAC8C
-
-#define CP_PQ_WPTR_POLL_CNTL 0xC20C
-#define WPTR_POLL_EN (1 << 31)
-
-#define CPC_INT_CNTL 0xC2D0
-#define CP_ME1_PIPE0_INT_CNTL 0xC214
-#define CP_ME1_PIPE1_INT_CNTL 0xC218
-#define CP_ME1_PIPE2_INT_CNTL 0xC21C
-#define CP_ME1_PIPE3_INT_CNTL 0xC220
-#define CP_ME2_PIPE0_INT_CNTL 0xC224
-#define CP_ME2_PIPE1_INT_CNTL 0xC228
-#define CP_ME2_PIPE2_INT_CNTL 0xC22C
-#define CP_ME2_PIPE3_INT_CNTL 0xC230
-#define DEQUEUE_REQUEST_INT_ENABLE (1 << 13)
-#define WRM_POLL_TIMEOUT_INT_ENABLE (1 << 17)
-#define PRIV_REG_INT_ENABLE (1 << 23)
-#define TIME_STAMP_INT_ENABLE (1 << 26)
-#define GENERIC2_INT_ENABLE (1 << 29)
-#define GENERIC1_INT_ENABLE (1 << 30)
-#define GENERIC0_INT_ENABLE (1 << 31)
-#define CP_ME1_PIPE0_INT_STATUS 0xC214
-#define CP_ME1_PIPE1_INT_STATUS 0xC218
-#define CP_ME1_PIPE2_INT_STATUS 0xC21C
-#define CP_ME1_PIPE3_INT_STATUS 0xC220
-#define CP_ME2_PIPE0_INT_STATUS 0xC224
-#define CP_ME2_PIPE1_INT_STATUS 0xC228
-#define CP_ME2_PIPE2_INT_STATUS 0xC22C
-#define CP_ME2_PIPE3_INT_STATUS 0xC230
-#define DEQUEUE_REQUEST_INT_STATUS (1 << 13)
-#define WRM_POLL_TIMEOUT_INT_STATUS (1 << 17)
-#define PRIV_REG_INT_STATUS (1 << 23)
-#define TIME_STAMP_INT_STATUS (1 << 26)
-#define GENERIC2_INT_STATUS (1 << 29)
-#define GENERIC1_INT_STATUS (1 << 30)
-#define GENERIC0_INT_STATUS (1 << 31)
-
-#define CP_HPD_EOP_BASE_ADDR 0xC904
-#define CP_HPD_EOP_BASE_ADDR_HI 0xC908
-#define CP_HPD_EOP_VMID 0xC90C
-#define CP_HPD_EOP_CONTROL 0xC910
-#define EOP_SIZE(x) ((x) << 0)
-#define EOP_SIZE_MASK (0x3f << 0)
-#define CP_MQD_BASE_ADDR 0xC914
-#define CP_MQD_BASE_ADDR_HI 0xC918
-#define CP_HQD_ACTIVE 0xC91C
-#define CP_HQD_VMID 0xC920
-
-#define CP_HQD_PERSISTENT_STATE 0xC924u
#define DEFAULT_CP_HQD_PERSISTENT_STATE (0x33U << 8)
#define PRELOAD_REQ (1 << 0)
-#define CP_HQD_PIPE_PRIORITY 0xC928u
-#define CP_HQD_QUEUE_PRIORITY 0xC92Cu
-#define CP_HQD_QUANTUM 0xC930u
+#define MQD_CONTROL_PRIV_STATE_EN (1U << 8)
+
+#define DEFAULT_MIN_IB_AVAIL_SIZE (3U << 20)
+
+#define IB_ATC_EN (1U << 23)
+
#define QUANTUM_EN 1U
#define QUANTUM_SCALE_1MS (1U << 4)
#define QUANTUM_DURATION(x) ((x) << 8)
-#define CP_HQD_PQ_BASE 0xC934
-#define CP_HQD_PQ_BASE_HI 0xC938
-#define CP_HQD_PQ_RPTR 0xC93C
-#define CP_HQD_PQ_RPTR_REPORT_ADDR 0xC940
-#define CP_HQD_PQ_RPTR_REPORT_ADDR_HI 0xC944
-#define CP_HQD_PQ_WPTR_POLL_ADDR 0xC948
-#define CP_HQD_PQ_WPTR_POLL_ADDR_HI 0xC94C
-#define CP_HQD_PQ_DOORBELL_CONTROL 0xC950
-#define DOORBELL_OFFSET(x) ((x) << 2)
-#define DOORBELL_OFFSET_MASK (0x1fffff << 2)
-#define DOORBELL_SOURCE (1 << 28)
-#define DOORBELL_SCHD_HIT (1 << 29)
-#define DOORBELL_EN (1 << 30)
-#define DOORBELL_HIT (1 << 31)
-#define CP_HQD_PQ_WPTR 0xC954
-#define CP_HQD_PQ_CONTROL 0xC958
-#define QUEUE_SIZE(x) ((x) << 0)
-#define QUEUE_SIZE_MASK (0x3f << 0)
#define RPTR_BLOCK_SIZE(x) ((x) << 8)
-#define RPTR_BLOCK_SIZE_MASK (0x3f << 8)
#define MIN_AVAIL_SIZE(x) ((x) << 20)
-#define PQ_ATC_EN (1 << 23)
-#define PQ_VOLATILE (1 << 26)
-#define NO_UPDATE_RPTR (1 << 27)
-#define UNORD_DISPATCH (1 << 28)
-#define ROQ_PQ_IB_FLIP (1 << 29)
-#define PRIV_STATE (1 << 30)
-#define KMD_QUEUE (1 << 31)
-
#define DEFAULT_RPTR_BLOCK_SIZE RPTR_BLOCK_SIZE(5)
#define DEFAULT_MIN_AVAIL_SIZE MIN_AVAIL_SIZE(3)
-#define CP_HQD_IB_BASE_ADDR 0xC95Cu
-#define CP_HQD_IB_BASE_ADDR_HI 0xC960u
-#define CP_HQD_IB_RPTR 0xC964u
-#define CP_HQD_IB_CONTROL 0xC968u
-#define IB_ATC_EN (1U << 23)
-#define DEFAULT_MIN_IB_AVAIL_SIZE (3U << 20)
-
-#define AQL_ENABLE 1
-
-#define CP_HQD_DEQUEUE_REQUEST 0xC974
-#define DEQUEUE_REQUEST_DRAIN 1
-#define DEQUEUE_REQUEST_RESET 2
-#define DEQUEUE_INT (1U << 8)
+#define PQ_ATC_EN (1 << 23)
+#define NO_UPDATE_RPTR (1 << 27)
-#define CP_HQD_SEMA_CMD 0xC97Cu
-#define CP_HQD_MSG_TYPE 0xC980u
-#define CP_HQD_ATOMIC0_PREOP_LO 0xC984u
-#define CP_HQD_ATOMIC0_PREOP_HI 0xC988u
-#define CP_HQD_ATOMIC1_PREOP_LO 0xC98Cu
-#define CP_HQD_ATOMIC1_PREOP_HI 0xC990u
-#define CP_HQD_HQ_SCHEDULER0 0xC994u
-#define CP_HQD_HQ_SCHEDULER1 0xC998u
+#define DOORBELL_OFFSET(x) ((x) << 2)
+#define DOORBELL_EN (1 << 30)
+#define PRIV_STATE (1 << 30)
+#define KMD_QUEUE (1 << 31)
-#define CP_MQD_CONTROL 0xC99C
-#define MQD_VMID(x) ((x) << 0)
-#define MQD_VMID_MASK (0xf << 0)
-#define MQD_CONTROL_PRIV_STATE_EN (1U << 8)
+#define AQL_ENABLE 1
#define SDMA_RB_VMID(x) (x << 24)
#define SDMA_RB_ENABLE (1 << 0)
@@ -202,33 +77,7 @@
#define SDMA_VA_SHARED_BASE(x) (x << 8)
#define GRBM_GFX_INDEX 0x30800
-#define INSTANCE_INDEX(x) ((x) << 0)
-#define SH_INDEX(x) ((x) << 8)
-#define SE_INDEX(x) ((x) << 16)
-#define SH_BROADCAST_WRITES (1 << 29)
-#define INSTANCE_BROADCAST_WRITES (1 << 30)
-#define SE_BROADCAST_WRITES (1 << 31)
-
-#define SQC_CACHES 0x30d20
-#define SQC_POLICY 0x8C38u
-#define SQC_VOLATILE 0x8C3Cu
-#define CP_PERFMON_CNTL 0x36020
-
-#define ATC_VMID0_PASID_MAPPING 0x339Cu
-#define ATC_VMID_PASID_MAPPING_UPDATE_STATUS 0x3398u
#define ATC_VMID_PASID_MAPPING_VALID (1U << 31)
-#define ATC_VM_APERTURE0_CNTL 0x3310u
-#define ATS_ACCESS_MODE_NEVER 0
-#define ATS_ACCESS_MODE_ALWAYS 1
-
-#define ATC_VM_APERTURE0_CNTL2 0x3318u
-#define ATC_VM_APERTURE0_HIGH_ADDR 0x3308u
-#define ATC_VM_APERTURE0_LOW_ADDR 0x3300u
-#define ATC_VM_APERTURE1_CNTL 0x3314u
-#define ATC_VM_APERTURE1_CNTL2 0x331Cu
-#define ATC_VM_APERTURE1_HIGH_ADDR 0x330Cu
-#define ATC_VM_APERTURE1_LOW_ADDR 0x3304u
-
#endif
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
index 19a4fba46e4e..c991973019d0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
@@ -35,6 +35,7 @@
#include <asm/processor.h>
#include "kfd_priv.h"
#include "kfd_device_queue_manager.h"
+#include "kfd_dbgmgr.h"
static long kfd_ioctl(struct file *, unsigned int, unsigned long);
static int kfd_open(struct inode *, struct file *);
@@ -289,8 +290,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);
@@ -430,6 +433,301 @@ out:
return err;
}
+static int kfd_ioctl_dbg_register(struct file *filep,
+ struct kfd_process *p, void *data)
+{
+ struct kfd_ioctl_dbg_register_args *args = data;
+ struct kfd_dev *dev;
+ struct kfd_dbgmgr *dbgmgr_ptr;
+ struct kfd_process_device *pdd;
+ bool create_ok;
+ long status = 0;
+
+ dev = kfd_device_by_id(args->gpu_id);
+ if (dev == NULL)
+ return -EINVAL;
+
+ if (dev->device_info->asic_family == CHIP_CARRIZO) {
+ pr_debug("kfd_ioctl_dbg_register not supported on CZ\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(kfd_get_dbgmgr_mutex());
+ mutex_lock(&p->mutex);
+
+ /*
+ * make sure that we have pdd, if this the first queue created for
+ * this process
+ */
+ pdd = kfd_bind_process_to_device(dev, p);
+ if (IS_ERR(pdd)) {
+ mutex_unlock(&p->mutex);
+ mutex_unlock(kfd_get_dbgmgr_mutex());
+ return PTR_ERR(pdd);
+ }
+
+ if (dev->dbgmgr == NULL) {
+ /* In case of a legal call, we have no dbgmgr yet */
+ create_ok = kfd_dbgmgr_create(&dbgmgr_ptr, dev);
+ if (create_ok) {
+ status = kfd_dbgmgr_register(dbgmgr_ptr, p);
+ if (status != 0)
+ kfd_dbgmgr_destroy(dbgmgr_ptr);
+ else
+ dev->dbgmgr = dbgmgr_ptr;
+ }
+ } else {
+ pr_debug("debugger already registered\n");
+ status = -EINVAL;
+ }
+
+ mutex_unlock(&p->mutex);
+ mutex_unlock(kfd_get_dbgmgr_mutex());
+
+ return status;
+}
+
+static int kfd_ioctl_dbg_unrgesiter(struct file *filep,
+ struct kfd_process *p, void *data)
+{
+ struct kfd_ioctl_dbg_unregister_args *args = data;
+ struct kfd_dev *dev;
+ long status;
+
+ dev = kfd_device_by_id(args->gpu_id);
+ if (dev == NULL)
+ return -EINVAL;
+
+ if (dev->device_info->asic_family == CHIP_CARRIZO) {
+ pr_debug("kfd_ioctl_dbg_unrgesiter not supported on CZ\n");
+ return -EINVAL;
+ }
+
+ mutex_lock(kfd_get_dbgmgr_mutex());
+
+ status = kfd_dbgmgr_unregister(dev->dbgmgr, p);
+ if (status == 0) {
+ kfd_dbgmgr_destroy(dev->dbgmgr);
+ dev->dbgmgr = NULL;
+ }
+
+ mutex_unlock(kfd_get_dbgmgr_mutex());
+
+ return status;
+}
+
+/*
+ * Parse and generate variable size data structure for address watch.
+ * Total size of the buffer and # watch points is limited in order
+ * to prevent kernel abuse. (no bearing to the much smaller HW limitation
+ * which is enforced by dbgdev module)
+ * please also note that the watch address itself are not "copied from user",
+ * since it be set into the HW in user mode values.
+ *
+ */
+static int kfd_ioctl_dbg_address_watch(struct file *filep,
+ struct kfd_process *p, void *data)
+{
+ struct kfd_ioctl_dbg_address_watch_args *args = data;
+ struct kfd_dev *dev;
+ struct dbg_address_watch_info aw_info;
+ unsigned char *args_buff;
+ long status;
+ void __user *cmd_from_user;
+ uint64_t watch_mask_value = 0;
+ unsigned int args_idx = 0;
+
+ memset((void *) &aw_info, 0, sizeof(struct dbg_address_watch_info));
+
+ dev = kfd_device_by_id(args->gpu_id);
+ if (dev == NULL)
+ return -EINVAL;
+
+ if (dev->device_info->asic_family == CHIP_CARRIZO) {
+ pr_debug("kfd_ioctl_dbg_wave_control not supported on CZ\n");
+ return -EINVAL;
+ }
+
+ cmd_from_user = (void __user *) args->content_ptr;
+
+ /* Validate arguments */
+
+ if ((args->buf_size_in_bytes > MAX_ALLOWED_AW_BUFF_SIZE) ||
+ (args->buf_size_in_bytes <= sizeof(*args) + sizeof(int) * 2) ||
+ (cmd_from_user == NULL))
+ return -EINVAL;
+
+ /* this is the actual buffer to work with */
+
+ args_buff = kmalloc(args->buf_size_in_bytes -
+ sizeof(*args), GFP_KERNEL);
+ if (args_buff == NULL)
+ return -ENOMEM;
+
+ status = copy_from_user(args_buff, cmd_from_user,
+ args->buf_size_in_bytes - sizeof(*args));
+
+ if (status != 0) {
+ pr_debug("Failed to copy address watch user data\n");
+ kfree(args_buff);
+ return -EINVAL;
+ }
+
+ aw_info.process = p;
+
+ aw_info.num_watch_points = *((uint32_t *)(&args_buff[args_idx]));
+ args_idx += sizeof(aw_info.num_watch_points);
+
+ aw_info.watch_mode = (enum HSA_DBG_WATCH_MODE *) &args_buff[args_idx];
+ args_idx += sizeof(enum HSA_DBG_WATCH_MODE) * aw_info.num_watch_points;
+
+ /*
+ * set watch address base pointer to point on the array base
+ * within args_buff
+ */
+ aw_info.watch_address = (uint64_t *) &args_buff[args_idx];
+
+ /* skip over the addresses buffer */
+ args_idx += sizeof(aw_info.watch_address) * aw_info.num_watch_points;
+
+ if (args_idx >= args->buf_size_in_bytes - sizeof(*args)) {
+ kfree(args_buff);
+ return -EINVAL;
+ }
+
+ watch_mask_value = (uint64_t) args_buff[args_idx];
+
+ if (watch_mask_value > 0) {
+ /*
+ * There is an array of masks.
+ * set watch mask base pointer to point on the array base
+ * within args_buff
+ */
+ aw_info.watch_mask = (uint64_t *) &args_buff[args_idx];
+
+ /* skip over the masks buffer */
+ args_idx += sizeof(aw_info.watch_mask) *
+ aw_info.num_watch_points;
+ } else {
+ /* just the NULL mask, set to NULL and skip over it */
+ aw_info.watch_mask = NULL;
+ args_idx += sizeof(aw_info.watch_mask);
+ }
+
+ if (args_idx >= args->buf_size_in_bytes - sizeof(args)) {
+ kfree(args_buff);
+ return -EINVAL;
+ }
+
+ /* Currently HSA Event is not supported for DBG */
+ aw_info.watch_event = NULL;
+
+ mutex_lock(kfd_get_dbgmgr_mutex());
+
+ status = kfd_dbgmgr_address_watch(dev->dbgmgr, &aw_info);
+
+ mutex_unlock(kfd_get_dbgmgr_mutex());
+
+ kfree(args_buff);
+
+ return status;
+}
+
+/* Parse and generate fixed size data structure for wave control */
+static int kfd_ioctl_dbg_wave_control(struct file *filep,
+ struct kfd_process *p, void *data)
+{
+ struct kfd_ioctl_dbg_wave_control_args *args = data;
+ struct kfd_dev *dev;
+ struct dbg_wave_control_info wac_info;
+ unsigned char *args_buff;
+ uint32_t computed_buff_size;
+ long status;
+ void __user *cmd_from_user;
+ unsigned int args_idx = 0;
+
+ memset((void *) &wac_info, 0, sizeof(struct dbg_wave_control_info));
+
+ /* we use compact form, independent of the packing attribute value */
+ computed_buff_size = sizeof(*args) +
+ sizeof(wac_info.mode) +
+ sizeof(wac_info.operand) +
+ sizeof(wac_info.dbgWave_msg.DbgWaveMsg) +
+ sizeof(wac_info.dbgWave_msg.MemoryVA) +
+ sizeof(wac_info.trapId);
+
+ dev = kfd_device_by_id(args->gpu_id);
+ if (dev == NULL)
+ return -EINVAL;
+
+ if (dev->device_info->asic_family == CHIP_CARRIZO) {
+ pr_debug("kfd_ioctl_dbg_wave_control not supported on CZ\n");
+ return -EINVAL;
+ }
+
+ /* input size must match the computed "compact" size */
+ if (args->buf_size_in_bytes != computed_buff_size) {
+ pr_debug("size mismatch, computed : actual %u : %u\n",
+ args->buf_size_in_bytes, computed_buff_size);
+ return -EINVAL;
+ }
+
+ cmd_from_user = (void __user *) args->content_ptr;
+
+ if (cmd_from_user == NULL)
+ return -EINVAL;
+
+ /* this is the actual buffer to work with */
+
+ args_buff = kmalloc(args->buf_size_in_bytes - sizeof(*args),
+ GFP_KERNEL);
+
+ if (args_buff == NULL)
+ return -ENOMEM;
+
+ /* Now copy the entire buffer from user */
+ status = copy_from_user(args_buff, cmd_from_user,
+ args->buf_size_in_bytes - sizeof(*args));
+ if (status != 0) {
+ pr_debug("Failed to copy wave control user data\n");
+ kfree(args_buff);
+ return -EINVAL;
+ }
+
+ /* move ptr to the start of the "pay-load" area */
+ wac_info.process = p;
+
+ wac_info.operand = *((enum HSA_DBG_WAVEOP *)(&args_buff[args_idx]));
+ args_idx += sizeof(wac_info.operand);
+
+ wac_info.mode = *((enum HSA_DBG_WAVEMODE *)(&args_buff[args_idx]));
+ args_idx += sizeof(wac_info.mode);
+
+ wac_info.trapId = *((uint32_t *)(&args_buff[args_idx]));
+ args_idx += sizeof(wac_info.trapId);
+
+ wac_info.dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2.Value =
+ *((uint32_t *)(&args_buff[args_idx]));
+ wac_info.dbgWave_msg.MemoryVA = NULL;
+
+ mutex_lock(kfd_get_dbgmgr_mutex());
+
+ pr_debug("Calling dbg manager process %p, operand %u, mode %u, trapId %u, message %u\n",
+ wac_info.process, wac_info.operand,
+ wac_info.mode, wac_info.trapId,
+ wac_info.dbgWave_msg.DbgWaveMsg.WaveMsgInfoGen2.Value);
+
+ status = kfd_dbgmgr_wave_control(dev->dbgmgr, &wac_info);
+
+ pr_debug("Returned status of dbg manager is %ld\n", status);
+
+ mutex_unlock(kfd_get_dbgmgr_mutex());
+
+ kfree(args_buff);
+
+ return status;
+}
+
static int kfd_ioctl_get_clock_counters(struct file *filep,
struct kfd_process *p, void *data)
{
@@ -514,6 +812,62 @@ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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);