1 // SPDX-License-Identifier: MIT
3 * Copyright © 2019 Intel Corporation
7 #include "gt/intel_context.h"
8 #include "gt/intel_engine_pm.h"
9 #include "gt/intel_engine_pool.h"
10 #include "i915_gem_client_blt.h"
11 #include "i915_gem_object_blt.h"
15 struct drm_i915_gem_object
*obj
;
16 struct sg_table
*pages
;
17 struct i915_page_sizes page_sizes
;
20 static int vma_set_pages(struct i915_vma
*vma
)
22 struct i915_sleeve
*sleeve
= vma
->private;
24 vma
->pages
= sleeve
->pages
;
25 vma
->page_sizes
= sleeve
->page_sizes
;
30 static void vma_clear_pages(struct i915_vma
*vma
)
32 GEM_BUG_ON(!vma
->pages
);
36 static int vma_bind(struct i915_vma
*vma
,
37 enum i915_cache_level cache_level
,
40 return vma
->vm
->vma_ops
.bind_vma(vma
, cache_level
, flags
);
43 static void vma_unbind(struct i915_vma
*vma
)
45 vma
->vm
->vma_ops
.unbind_vma(vma
);
48 static const struct i915_vma_ops proxy_vma_ops
= {
49 .set_pages
= vma_set_pages
,
50 .clear_pages
= vma_clear_pages
,
52 .unbind_vma
= vma_unbind
,
55 static struct i915_sleeve
*create_sleeve(struct i915_address_space
*vm
,
56 struct drm_i915_gem_object
*obj
,
57 struct sg_table
*pages
,
58 struct i915_page_sizes
*page_sizes
)
60 struct i915_sleeve
*sleeve
;
64 sleeve
= kzalloc(sizeof(*sleeve
), GFP_KERNEL
);
66 return ERR_PTR(-ENOMEM
);
68 vma
= i915_vma_instance(obj
, vm
, NULL
);
74 vma
->private = sleeve
;
75 vma
->ops
= &proxy_vma_ops
;
78 sleeve
->pages
= pages
;
79 sleeve
->page_sizes
= *page_sizes
;
88 static void destroy_sleeve(struct i915_sleeve
*sleeve
)
93 struct clear_pages_work
{
95 struct dma_fence_cb cb
;
96 struct i915_sw_fence wait
;
97 struct work_struct work
;
98 struct irq_work irq_work
;
99 struct i915_sleeve
*sleeve
;
100 struct intel_context
*ce
;
104 static const char *clear_pages_work_driver_name(struct dma_fence
*fence
)
109 static const char *clear_pages_work_timeline_name(struct dma_fence
*fence
)
114 static void clear_pages_work_release(struct dma_fence
*fence
)
116 struct clear_pages_work
*w
= container_of(fence
, typeof(*w
), dma
);
118 destroy_sleeve(w
->sleeve
);
120 i915_sw_fence_fini(&w
->wait
);
122 BUILD_BUG_ON(offsetof(typeof(*w
), dma
));
123 dma_fence_free(&w
->dma
);
126 static const struct dma_fence_ops clear_pages_work_ops
= {
127 .get_driver_name
= clear_pages_work_driver_name
,
128 .get_timeline_name
= clear_pages_work_timeline_name
,
129 .release
= clear_pages_work_release
,
132 static void clear_pages_signal_irq_worker(struct irq_work
*work
)
134 struct clear_pages_work
*w
= container_of(work
, typeof(*w
), irq_work
);
136 dma_fence_signal(&w
->dma
);
137 dma_fence_put(&w
->dma
);
140 static void clear_pages_dma_fence_cb(struct dma_fence
*fence
,
141 struct dma_fence_cb
*cb
)
143 struct clear_pages_work
*w
= container_of(cb
, typeof(*w
), cb
);
146 dma_fence_set_error(&w
->dma
, fence
->error
);
149 * Push the signalling of the fence into yet another worker to avoid
150 * the nightmare locking around the fence spinlock.
152 irq_work_queue(&w
->irq_work
);
155 static void clear_pages_worker(struct work_struct
*work
)
157 struct clear_pages_work
*w
= container_of(work
, typeof(*w
), work
);
158 struct drm_i915_gem_object
*obj
= w
->sleeve
->vma
->obj
;
159 struct i915_vma
*vma
= w
->sleeve
->vma
;
160 struct i915_request
*rq
;
161 struct i915_vma
*batch
;
162 int err
= w
->dma
.error
;
167 if (obj
->cache_dirty
) {
168 if (i915_gem_object_has_struct_page(obj
))
169 drm_clflush_sg(w
->sleeve
->pages
);
170 obj
->cache_dirty
= false;
172 obj
->read_domains
= I915_GEM_GPU_DOMAINS
;
173 obj
->write_domain
= 0;
175 err
= i915_vma_pin(vma
, 0, 0, PIN_USER
);
179 batch
= intel_emit_vma_fill_blt(w
->ce
, vma
, w
->value
);
181 err
= PTR_ERR(batch
);
185 rq
= intel_context_create_request(w
->ce
);
191 /* There's no way the fence has signalled */
192 if (dma_fence_add_callback(&rq
->fence
, &w
->cb
,
193 clear_pages_dma_fence_cb
))
196 err
= intel_emit_vma_mark_active(batch
, rq
);
200 if (w
->ce
->engine
->emit_init_breadcrumb
) {
201 err
= w
->ce
->engine
->emit_init_breadcrumb(rq
);
207 * w->dma is already exported via (vma|obj)->resv we need only
208 * keep track of the GPU activity within this vma/request, and
209 * propagate the signal from the request to w->dma.
211 err
= __i915_vma_move_to_active(vma
, rq
);
215 err
= w
->ce
->engine
->emit_bb_start(rq
,
216 batch
->node
.start
, batch
->node
.size
,
220 i915_request_skip(rq
, err
);
224 i915_request_add(rq
);
226 intel_emit_vma_release(w
->ce
, batch
);
231 dma_fence_set_error(&w
->dma
, err
);
232 dma_fence_signal(&w
->dma
);
233 dma_fence_put(&w
->dma
);
237 static int __i915_sw_fence_call
238 clear_pages_work_notify(struct i915_sw_fence
*fence
,
239 enum i915_sw_fence_notify state
)
241 struct clear_pages_work
*w
= container_of(fence
, typeof(*w
), wait
);
245 schedule_work(&w
->work
);
249 dma_fence_put(&w
->dma
);
256 static DEFINE_SPINLOCK(fence_lock
);
258 /* XXX: better name please */
259 int i915_gem_schedule_fill_pages_blt(struct drm_i915_gem_object
*obj
,
260 struct intel_context
*ce
,
261 struct sg_table
*pages
,
262 struct i915_page_sizes
*page_sizes
,
265 struct clear_pages_work
*work
;
266 struct i915_sleeve
*sleeve
;
269 sleeve
= create_sleeve(ce
->vm
, obj
, pages
, page_sizes
);
271 return PTR_ERR(sleeve
);
273 work
= kmalloc(sizeof(*work
), GFP_KERNEL
);
275 destroy_sleeve(sleeve
);
280 work
->sleeve
= sleeve
;
283 INIT_WORK(&work
->work
, clear_pages_worker
);
285 init_irq_work(&work
->irq_work
, clear_pages_signal_irq_worker
);
287 dma_fence_init(&work
->dma
, &clear_pages_work_ops
, &fence_lock
, 0, 0);
288 i915_sw_fence_init(&work
->wait
, clear_pages_work_notify
);
290 i915_gem_object_lock(obj
);
291 err
= i915_sw_fence_await_reservation(&work
->wait
,
292 obj
->base
.resv
, NULL
,
293 true, I915_FENCE_TIMEOUT
,
296 dma_fence_set_error(&work
->dma
, err
);
298 dma_resv_add_excl_fence(obj
->base
.resv
, &work
->dma
);
301 i915_gem_object_unlock(obj
);
303 dma_fence_get(&work
->dma
);
304 i915_sw_fence_commit(&work
->wait
);
309 #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
310 #include "selftests/i915_gem_client_blt.c"