Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2022 Intel Corporation
4 */
5
6#include "xe_bb.h"
7
8#include "instructions/xe_mi_commands.h"
9#include "xe_assert.h"
10#include "xe_device.h"
11#include "xe_exec_queue_types.h"
12#include "xe_gt.h"
13#include "xe_hw_fence.h"
14#include "xe_sa.h"
15#include "xe_sched_job.h"
16#include "xe_vm_types.h"
17
18static int bb_prefetch(struct xe_gt *gt)
19{
20 struct xe_device *xe = gt_to_xe(gt);
21
22 if (GRAPHICS_VERx100(xe) >= 1250 && xe_gt_is_main_type(gt))
23 /*
24 * RCS and CCS require 1K, although other engines would be
25 * okay with 512.
26 */
27 return SZ_1K;
28 else
29 return SZ_512;
30}
31
32struct xe_bb *xe_bb_new(struct xe_gt *gt, u32 dwords, bool usm)
33{
34 struct xe_tile *tile = gt_to_tile(gt);
35 struct xe_bb *bb = kmalloc(sizeof(*bb), GFP_KERNEL);
36 int err;
37
38 if (!bb)
39 return ERR_PTR(-ENOMEM);
40
41 /*
42 * We need to allocate space for the requested number of dwords,
43 * one additional MI_BATCH_BUFFER_END dword, and additional buffer
44 * space to accommodate the platform-specific hardware prefetch
45 * requirements.
46 */
47 bb->bo = xe_sa_bo_new(!usm ? tile->mem.kernel_bb_pool : gt->usm.bb_pool,
48 4 * (dwords + 1) + bb_prefetch(gt));
49 if (IS_ERR(bb->bo)) {
50 err = PTR_ERR(bb->bo);
51 goto err;
52 }
53
54 bb->cs = xe_sa_bo_cpu_addr(bb->bo);
55 bb->len = 0;
56
57 return bb;
58err:
59 kfree(bb);
60 return ERR_PTR(err);
61}
62
63struct xe_bb *xe_bb_ccs_new(struct xe_gt *gt, u32 dwords,
64 enum xe_sriov_vf_ccs_rw_ctxs ctx_id)
65{
66 struct xe_bb *bb = kmalloc(sizeof(*bb), GFP_KERNEL);
67 struct xe_device *xe = gt_to_xe(gt);
68 struct xe_sa_manager *bb_pool;
69 int err;
70
71 if (!bb)
72 return ERR_PTR(-ENOMEM);
73 /*
74 * We need to allocate space for the requested number of dwords &
75 * one additional MI_BATCH_BUFFER_END dword. Since the whole SA
76 * is submitted to HW, we need to make sure that the last instruction
77 * is not over written when the last chunk of SA is allocated for BB.
78 * So, this extra DW acts as a guard here.
79 */
80
81 bb_pool = xe->sriov.vf.ccs.contexts[ctx_id].mem.ccs_bb_pool;
82 bb->bo = xe_sa_bo_new(bb_pool, 4 * (dwords + 1));
83
84 if (IS_ERR(bb->bo)) {
85 err = PTR_ERR(bb->bo);
86 goto err;
87 }
88
89 bb->cs = xe_sa_bo_cpu_addr(bb->bo);
90 bb->len = 0;
91
92 return bb;
93err:
94 kfree(bb);
95 return ERR_PTR(err);
96}
97
98static struct xe_sched_job *
99__xe_bb_create_job(struct xe_exec_queue *q, struct xe_bb *bb, u64 *addr)
100{
101 u32 size = drm_suballoc_size(bb->bo);
102
103 if (bb->len == 0 || bb->cs[bb->len - 1] != MI_BATCH_BUFFER_END)
104 bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
105
106 xe_gt_assert(q->gt, bb->len * 4 + bb_prefetch(q->gt) <= size);
107
108 xe_sa_bo_flush_write(bb->bo);
109
110 return xe_sched_job_create(q, addr);
111}
112
113struct xe_sched_job *xe_bb_create_migration_job(struct xe_exec_queue *q,
114 struct xe_bb *bb,
115 u64 batch_base_ofs,
116 u32 second_idx)
117{
118 u64 addr[2] = {
119 batch_base_ofs + drm_suballoc_soffset(bb->bo),
120 batch_base_ofs + drm_suballoc_soffset(bb->bo) +
121 4 * second_idx,
122 };
123
124 xe_gt_assert(q->gt, second_idx <= bb->len);
125 xe_gt_assert(q->gt, xe_sched_job_is_migration(q));
126 xe_gt_assert(q->gt, q->width == 1);
127
128 return __xe_bb_create_job(q, bb, addr);
129}
130
131struct xe_sched_job *xe_bb_create_job(struct xe_exec_queue *q,
132 struct xe_bb *bb)
133{
134 u64 addr = xe_sa_bo_gpu_addr(bb->bo);
135
136 xe_gt_assert(q->gt, !xe_sched_job_is_migration(q));
137 xe_gt_assert(q->gt, q->width == 1);
138 return __xe_bb_create_job(q, bb, &addr);
139}
140
141void xe_bb_free(struct xe_bb *bb, struct dma_fence *fence)
142{
143 if (!bb)
144 return;
145
146 xe_sa_bo_free(bb->bo, fence);
147 kfree(bb);
148}