xref: /linux/drivers/gpu/drm/xe/xe_bb.c (revision 08516de501fae647fb29bf3b62718de56cc24014)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2022 Intel Corporation
4  */
5 
6 #include "xe_bb.h"
7 
8 #include "regs/xe_gpu_commands.h"
9 #include "xe_device.h"
10 #include "xe_engine_types.h"
11 #include "xe_gt.h"
12 #include "xe_hw_fence.h"
13 #include "xe_sa.h"
14 #include "xe_sched_job.h"
15 #include "xe_vm_types.h"
16 
17 static int bb_prefetch(struct xe_gt *gt)
18 {
19 	struct xe_device *xe = gt_to_xe(gt);
20 
21 	if (GRAPHICS_VERx100(xe) >= 1250 && !xe_gt_is_media_type(gt))
22 		/*
23 		 * RCS and CCS require 1K, although other engines would be
24 		 * okay with 512.
25 		 */
26 		return SZ_1K;
27 	else
28 		return SZ_512;
29 }
30 
31 struct xe_bb *xe_bb_new(struct xe_gt *gt, u32 dwords, bool usm)
32 {
33 	struct xe_tile *tile = gt_to_tile(gt);
34 	struct xe_bb *bb = kmalloc(sizeof(*bb), GFP_KERNEL);
35 	int err;
36 
37 	if (!bb)
38 		return ERR_PTR(-ENOMEM);
39 
40 	/*
41 	 * We need to allocate space for the requested number of dwords,
42 	 * one additional MI_BATCH_BUFFER_END dword, and additional buffer
43 	 * space to accomodate the platform-specific hardware prefetch
44 	 * requirements.
45 	 */
46 	bb->bo = xe_sa_bo_new(!usm ? tile->mem.kernel_bb_pool : gt->usm.bb_pool,
47 			      4 * (dwords + 1) + bb_prefetch(gt));
48 	if (IS_ERR(bb->bo)) {
49 		err = PTR_ERR(bb->bo);
50 		goto err;
51 	}
52 
53 	bb->cs = xe_sa_bo_cpu_addr(bb->bo);
54 	bb->len = 0;
55 
56 	return bb;
57 err:
58 	kfree(bb);
59 	return ERR_PTR(err);
60 }
61 
62 static struct xe_sched_job *
63 __xe_bb_create_job(struct xe_engine *kernel_eng, struct xe_bb *bb, u64 *addr)
64 {
65 	u32 size = drm_suballoc_size(bb->bo);
66 
67 	bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
68 
69 	WARN_ON(bb->len * 4 + bb_prefetch(kernel_eng->gt) > size);
70 
71 	xe_sa_bo_flush_write(bb->bo);
72 
73 	return xe_sched_job_create(kernel_eng, addr);
74 }
75 
76 struct xe_sched_job *xe_bb_create_wa_job(struct xe_engine *wa_eng,
77 					 struct xe_bb *bb, u64 batch_base_ofs)
78 {
79 	u64 addr = batch_base_ofs + drm_suballoc_soffset(bb->bo);
80 
81 	XE_BUG_ON(!(wa_eng->vm->flags & XE_VM_FLAG_MIGRATION));
82 
83 	return __xe_bb_create_job(wa_eng, bb, &addr);
84 }
85 
86 struct xe_sched_job *xe_bb_create_migration_job(struct xe_engine *kernel_eng,
87 						struct xe_bb *bb,
88 						u64 batch_base_ofs,
89 						u32 second_idx)
90 {
91 	u64 addr[2] = {
92 		batch_base_ofs + drm_suballoc_soffset(bb->bo),
93 		batch_base_ofs + drm_suballoc_soffset(bb->bo) +
94 		4 * second_idx,
95 	};
96 
97 	BUG_ON(second_idx > bb->len);
98 	BUG_ON(!(kernel_eng->vm->flags & XE_VM_FLAG_MIGRATION));
99 
100 	return __xe_bb_create_job(kernel_eng, bb, addr);
101 }
102 
103 struct xe_sched_job *xe_bb_create_job(struct xe_engine *kernel_eng,
104 				      struct xe_bb *bb)
105 {
106 	u64 addr = xe_sa_bo_gpu_addr(bb->bo);
107 
108 	BUG_ON(kernel_eng->vm && kernel_eng->vm->flags & XE_VM_FLAG_MIGRATION);
109 	return __xe_bb_create_job(kernel_eng, bb, &addr);
110 }
111 
112 void xe_bb_free(struct xe_bb *bb, struct dma_fence *fence)
113 {
114 	if (!bb)
115 		return;
116 
117 	xe_sa_bo_free(bb->bo, fence);
118 	kfree(bb);
119 }
120