@@ -43,6 +43,8 @@
#include <linux/atomic.h>
#include <linux/dma-resv.h>
+#include "ttm_trace.h"
+
static void ttm_bo_global_kobj_release(struct kobject *kobj);
/**
@@ -143,6 +145,8 @@ static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo,
if (mem->placement & TTM_PL_FLAG_NO_EVICT)
return;
+ trace_ttm_bo_add_mem_to_lru(bo, mem);
+
man = ttm_manager_type(bdev, mem->mem_type);
list_add_tail(&bo->lru, &man->lru[bo->priority]);
@@ -167,6 +171,8 @@ static void ttm_bo_del_from_lru(struct ttm_buffer_object *bo)
notify = true;
}
+ trace_ttm_bo_del_from_lru(bo, notify);
+
if (notify && bdev->driver->del_from_lru_notify)
bdev->driver->del_from_lru_notify(bo);
}
@@ -299,6 +305,8 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo,
}
}
+ trace_ttm_bo_move_mem(bo, mem, evict);
+
if (bdev->driver->move_notify)
bdev->driver->move_notify(bo, evict, mem);
@@ -542,6 +550,8 @@ static void ttm_bo_release(struct kref *kref)
size_t acc_size = bo->acc_size;
int ret;
+ trace_ttm_bo_release(bo);
+
if (!bo->deleted) {
ret = ttm_bo_individualize_resv(bo);
if (ret) {
@@ -668,6 +678,8 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo,
ttm_resource_free(bo, &evict_mem);
goto out;
}
+
+ trace_ttm_bo_evict(bo, &evict_mem);
bo->evicted = true;
out:
return ret;
@@ -1151,6 +1163,8 @@ int ttm_bo_validate(struct ttm_buffer_object *bo,
dma_resv_assert_held(bo->base.resv);
+ trace_ttm_bo_validate(bo);
+
/*
* Remove the backing store if no placement is given.
*/
@@ -1263,6 +1277,8 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev,
}
atomic_inc(&ttm_bo_glob.bo_count);
+ trace_ttm_bo_init_reserved(bo, size);
+
/*
* For ttm_bo_type_device buffers, allocate
* address space from the device.
@@ -1487,6 +1503,8 @@ int ttm_bo_device_release(struct ttm_bo_device *bdev)
if (!ret)
ttm_bo_global_release();
+ trace_ttm_bo_device_release(bdev);
+
return ret;
}
EXPORT_SYMBOL(ttm_bo_device_release);
@@ -1537,6 +1555,8 @@ int ttm_bo_device_init(struct ttm_bo_device *bdev,
list_add_tail(&bdev->device_list, &glob->device_list);
mutex_unlock(&ttm_global_mutex);
+ trace_ttm_bo_device_init(bdev);
+
return 0;
}
EXPORT_SYMBOL(ttm_bo_device_init);
@@ -1580,6 +1600,8 @@ int ttm_bo_wait(struct ttm_buffer_object *bo,
timeout = dma_resv_wait_timeout_rcu(bo->base.resv, true,
interruptible, timeout);
+
+ trace_ttm_bo_wait(bo, interruptible, timeout);
if (timeout < 0)
return timeout;
@@ -1670,6 +1692,7 @@ int ttm_bo_swapout(struct ttm_bo_global *glob, struct ttm_operation_ctx *ctx)
* anyone tries to access a ttm page.
*/
+ trace_ttm_bo_swapout(bo, i);
if (bo->bdev->driver->swap_notify)
bo->bdev->driver->swap_notify(bo);
@@ -35,6 +35,9 @@
#include <drm/ttm/ttm_module.h>
#include <drm/drm_sysfs.h>
+#define CREATE_TRACE_POINTS
+#include "ttm_trace.h"
+
static DECLARE_WAIT_QUEUE_HEAD(exit_q);
static atomic_t device_released;
new file mode 100644
@@ -0,0 +1,321 @@
+/*
+ * Copyright 2021 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.
+ *
+ * Authors: Kevin Wang
+ */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ttm
+
+#if !defined(_TRACE_TTM_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_TTM_H_
+
+#include <drm/ttm/ttm_bo_api.h>
+#include <drm/ttm/ttm_bo_driver.h>
+#include <drm/ttm/ttm_placement.h>
+#include <drm/ttm/ttm_module.h>
+#include <drm/ttm/ttm_page_alloc.h>
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#define TTM_PLACEMENT_FLAGS_TRACE \
+ { TTM_PL_FLAG_SYSTEM, "SYSTEM" },\
+ { TTM_PL_FLAG_TT, "TT" },\
+ { TTM_PL_FLAG_VRAM, "VRAM" },\
+ { TTM_PL_FLAG_PRIV, "PRIV" },\
+ { TTM_PL_FLAG_CACHED, "CACHED" },\
+ { TTM_PL_FLAG_UNCACHED, "UNCACHED" },\
+ { TTM_PL_FLAG_WC, "WC" },\
+ { TTM_PL_FLAG_CONTIGUOUS, "CONTIGUOUS" },\
+ { TTM_PL_FLAG_NO_EVICT, "NO_EVICT" },\
+ { TTM_PL_FLAG_TOPDOWN, "TOPDOWN" }
+
+#define __show_ttm_pl_flags(flags, mask) \
+ (flags & mask) ? __print_flags(flags, "|", \
+ TTM_PLACEMENT_FLAGS_TRACE \
+ ) : "none"
+
+#define show_ttm_pl_flags(flags) \
+ __show_ttm_pl_flags(flags, ~0UL)
+
+#define show_ttm_pl_mem_flags(flags) \
+ __show_ttm_pl_flags(flags, TTM_PL_MASK_MEM)
+
+
+TRACE_EVENT(ttm_bo_add_mem_to_lru,
+ TP_PROTO(struct ttm_buffer_object *bo, struct ttm_resource *res),
+ TP_ARGS(bo, res),
+ TP_STRUCT__entry(
+ __field(struct ttm_buffer_object *, bo)
+ __field(unsigned long, size)
+ __field(uint32_t, placement)
+ __field(enum ttm_bo_type, bo_type)
+ __field(uint32_t, mem_type)
+ ),
+
+ TP_fast_assign(
+ __entry->bo = bo;
+ __entry->bo_type = bo->type;
+ __entry->size = bo->mem.size;
+ __entry->placement = res->placement;
+ __entry->mem_type = res->mem_type;
+ ),
+
+ TP_printk("bo:%p, size=%lx, bo_type=%d, mtype=%d, placement=%s(%x)",
+ __entry->bo, __entry->size, __entry->bo_type, __entry->mem_type,
+ show_ttm_pl_flags(__entry->placement), __entry->placement)
+);
+
+TRACE_EVENT(ttm_bo_del_from_lru,
+ TP_PROTO(struct ttm_buffer_object *bo, bool notify),
+ TP_ARGS(bo, notify),
+ TP_STRUCT__entry(
+ __field(struct ttm_buffer_object *, bo)
+ __field(unsigned long, size)
+ __field(uint32_t, placement)
+ __field(enum ttm_bo_type, bo_type)
+ __field(uint32_t, mem_type)
+ __field(bool, notify)
+ ),
+
+ TP_fast_assign(
+ __entry->bo = bo;
+ __entry->bo_type = bo->type;
+ __entry->size = bo->mem.size;
+ __entry->placement = bo->mem.placement;
+ __entry->mem_type = bo->mem.mem_type;
+ __entry->notify = notify;
+ ),
+
+ TP_printk("bo:%p, size=%lx, bo_type=%d, mtype=%d, placement=%s(%x), notify=%s",
+ __entry->bo, __entry->size, __entry->bo_type, __entry->mem_type,
+ show_ttm_pl_flags(__entry->placement), __entry->placement,
+ __entry->notify ? "true" : "false")
+);
+
+TRACE_EVENT(ttm_bo_move_mem,
+ TP_PROTO(struct ttm_buffer_object *bo, struct ttm_resource *res, bool evict),
+ TP_ARGS(bo, res, evict),
+ TP_STRUCT__entry(
+ __field(struct ttm_buffer_object *, bo)
+ __field(unsigned long, start)
+ __field(unsigned long, size)
+ __field(uint32_t, old_placement)
+ __field(uint32_t, new_placement)
+ __field(uint32_t, old_mem_type)
+ __field(uint32_t, new_mem_type)
+ __field(bool, evict)
+ ),
+
+ TP_fast_assign(
+ __entry->bo = bo;
+ __entry->start = res->start;
+ __entry->size = res->size;
+ __entry->old_placement = bo->mem.placement;
+ __entry->new_placement = res->placement;
+ __entry->old_mem_type = bo->mem.mem_type;
+ __entry->new_mem_type = res->mem_type;
+ __entry->evict = evict;
+ ),
+
+ TP_printk("bo:%p, start=%lx, size=%lx, mtype: %d -> %d, placement: %s(%x) -> %s(%x), evict=%s",
+ __entry->bo, __entry->start, __entry->size,
+ __entry->old_mem_type, __entry->new_mem_type,
+ show_ttm_pl_flags(__entry->old_placement), __entry->old_placement,
+ show_ttm_pl_flags(__entry->new_placement), __entry->new_placement,
+ __entry->evict ? "true" : "false")
+);
+
+TRACE_EVENT(ttm_bo_wait,
+ TP_PROTO(struct ttm_buffer_object *bo, bool interruptible, long timeout),
+ TP_ARGS(bo, interruptible, timeout),
+ TP_STRUCT__entry(
+ __field(struct ttm_buffer_object *, bo)
+ __field(bool, interruptible)
+ __field(long, timeout)
+ ),
+
+ TP_fast_assign(
+ __entry->bo = bo;
+ __entry->interruptible = interruptible;
+ __entry->timeout = timeout;
+ ),
+
+ TP_printk("bo:%p, interruptible=%s, timeout=%ld", __entry->bo,
+ __entry->interruptible ? "true" : "false", __entry->timeout)
+);
+
+TRACE_EVENT(ttm_bo_evict,
+ TP_PROTO(struct ttm_buffer_object *bo, struct ttm_resource *res),
+ TP_ARGS(bo, res),
+ TP_STRUCT__entry(
+ __field(struct ttm_buffer_object *, bo)
+ __field(enum ttm_bo_type, bo_type)
+ __field(unsigned long, size)
+ __field(uint32_t, old_placement)
+ __field(uint32_t, new_placement)
+ __field(uint32_t, old_mem_type)
+ __field(uint32_t, new_mem_type)
+ ),
+
+ TP_fast_assign(
+ __entry->bo = bo;
+ __entry->bo_type = bo->type;
+ __entry->size = res->size;
+ __entry->old_placement = bo->mem.placement;
+ __entry->new_placement = res->placement;
+ __entry->old_mem_type = bo->mem.mem_type;
+ __entry->new_mem_type = res->mem_type;
+ ),
+
+ TP_printk("bo:%p, size=%lx, bo_type=%d, mtype: %d -> %d, placement: %s(%x) -> %s(%x)",
+ __entry->bo, __entry->size, __entry->bo_type,
+ __entry->old_mem_type, __entry->new_mem_type,
+ show_ttm_pl_flags(__entry->old_placement), __entry->old_placement,
+ show_ttm_pl_flags(__entry->new_placement), __entry->new_placement)
+
+);
+
+TRACE_EVENT(ttm_bo_swapout,
+ TP_PROTO(struct ttm_buffer_object *bo, int priority),
+ TP_ARGS(bo, priority),
+ TP_STRUCT__entry(
+ __field(struct ttm_buffer_object *, bo)
+ __field(enum ttm_bo_type, bo_type)
+ __field(unsigned long, size)
+ __field(uint32_t, placement)
+ __field(uint32_t, mem_type)
+ __field(int, priority)
+ ),
+
+ TP_fast_assign(
+ __entry->bo = bo;
+ __entry->priority = priority;
+ __entry->bo_type = bo->type;
+ __entry->size = bo->mem.size;
+ __entry->placement = bo->mem.placement;
+ __entry->mem_type = bo->mem.mem_type;
+ ),
+
+ TP_printk("bo:%p, size=%lx, bo_type=%d, mtype=%d, placement=%s(%x), prio=%d",
+ __entry->bo, __entry->size, __entry->bo_type, __entry->mem_type,
+ show_ttm_pl_flags(__entry->placement), __entry->placement,
+ __entry->priority)
+);
+
+TRACE_EVENT(ttm_bo_device_init,
+ TP_PROTO(struct ttm_bo_device *bdev),
+ TP_ARGS(bdev),
+ TP_STRUCT__entry(
+ __field(struct ttm_bo_device *, bdev)
+ __field(struct ttm_bo_driver *, driver)
+ __field(bool, need_dma32)
+ ),
+
+ TP_fast_assign(
+ __entry->bdev = bdev;
+ __entry->driver = bdev->driver;
+ __entry->need_dma32 = bdev->need_dma32;
+ ),
+
+ TP_printk("bdev:%p, driver=%p, need_dma32=%s", __entry->bdev, __entry->driver,
+ __entry->need_dma32 ? "true" : "false")
+);
+
+TRACE_EVENT(ttm_bo_device_release,
+ TP_PROTO(struct ttm_bo_device *bdev),
+ TP_ARGS(bdev),
+ TP_STRUCT__entry(
+ __field(struct ttm_bo_device *, bdev)
+ ),
+
+ TP_fast_assign(
+ __entry->bdev = bdev;
+ ),
+
+ TP_printk("bdev:%p", __entry->bdev)
+);
+
+TRACE_EVENT(ttm_bo_init_reserved,
+ TP_PROTO(struct ttm_buffer_object *bo, unsigned long size),
+ TP_ARGS(bo, size),
+ TP_STRUCT__entry(
+ __field(struct ttm_bo_device *, bdev)
+ __field(struct ttm_buffer_object *, bo)
+ __field(enum ttm_bo_type, bo_type)
+ __field(uint32_t, page_alignment)
+ __field(uint32_t, placement)
+ __field(unsigned long, size)
+ __field(size_t, acc_size)
+ ),
+
+ TP_fast_assign(
+ __entry->bo = bo;
+ __entry->bdev = bo->bdev;
+ __entry->bo_type = bo->type;
+ __entry->placement = bo->mem.placement;
+ __entry->page_alignment = bo->mem.page_alignment;
+ __entry->size = size;
+ __entry->acc_size = bo->acc_size;
+ ),
+
+ TP_printk("bo:%p, bdev=%p, bo_type=%d, %s(%x) size=%lx, accsize=%lx, alignment=%d",
+ __entry->bo, __entry->bdev, __entry->bo_type,
+ show_ttm_pl_flags(__entry->placement), __entry->placement,
+ __entry->size, __entry->acc_size, __entry->page_alignment)
+);
+
+TRACE_EVENT(ttm_bo_validate,
+ TP_PROTO(struct ttm_buffer_object *bo),
+ TP_ARGS(bo),
+ TP_STRUCT__entry(
+ __field(struct ttm_buffer_object *, bo)
+ ),
+
+ TP_fast_assign(
+ __entry->bo = bo;
+ ),
+
+ TP_printk("bo:%p", __entry->bo)
+);
+
+TRACE_EVENT(ttm_bo_release,
+ TP_PROTO(struct ttm_buffer_object *bo),
+ TP_ARGS(bo),
+ TP_STRUCT__entry(
+ __field(struct ttm_buffer_object *, bo)
+ ),
+
+ TP_fast_assign(
+ __entry->bo = bo;
+ ),
+
+ TP_printk("bo:%p", __entry->bo)
+);
+
+#endif
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH ../../drivers/gpu/drm/ttm
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE ttm_trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
add ttm bo related trace event support trace events: ttm:ttm_bo_add_mem_to_lru ttm:ttm_bo_del_from_lru ttm:ttm_bo_move_mem ttm:ttm_bo_wait ttm:ttm_bo_evict ttm:ttm_bo_swapout ttm:ttm_bo_device_init ttm:ttm_bo_device_release ttm:ttm_bo_init_reserved ttm:ttm_bo_validate ttm:ttm_bo_release Signed-off-by: Kevin Wang <kevin1.wang@amd.com> --- drivers/gpu/drm/ttm/ttm_bo.c | 23 +++ drivers/gpu/drm/ttm/ttm_module.c | 3 + drivers/gpu/drm/ttm/ttm_trace.h | 321 +++++++++++++++++++++++++++++++ 3 files changed, 347 insertions(+) create mode 100644 drivers/gpu/drm/ttm/ttm_trace.h