Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * SPDX-License-Identifier: MIT
0003  *
0004  * Copyright © 2018 Intel Corporation
0005  */
0006 #include "gt/intel_gpu_commands.h"
0007 #include "gt/intel_gt.h"
0008 
0009 #include "gem/i915_gem_internal.h"
0010 #include "gem/selftests/igt_gem_utils.h"
0011 
0012 #include "igt_spinner.h"
0013 
0014 int igt_spinner_init(struct igt_spinner *spin, struct intel_gt *gt)
0015 {
0016     int err;
0017 
0018     memset(spin, 0, sizeof(*spin));
0019     spin->gt = gt;
0020 
0021     spin->hws = i915_gem_object_create_internal(gt->i915, PAGE_SIZE);
0022     if (IS_ERR(spin->hws)) {
0023         err = PTR_ERR(spin->hws);
0024         goto err;
0025     }
0026     i915_gem_object_set_cache_coherency(spin->hws, I915_CACHE_LLC);
0027 
0028     spin->obj = i915_gem_object_create_internal(gt->i915, PAGE_SIZE);
0029     if (IS_ERR(spin->obj)) {
0030         err = PTR_ERR(spin->obj);
0031         goto err_hws;
0032     }
0033 
0034     return 0;
0035 
0036 err_hws:
0037     i915_gem_object_put(spin->hws);
0038 err:
0039     return err;
0040 }
0041 
0042 static void *igt_spinner_pin_obj(struct intel_context *ce,
0043                  struct i915_gem_ww_ctx *ww,
0044                  struct drm_i915_gem_object *obj,
0045                  unsigned int mode, struct i915_vma **vma)
0046 {
0047     void *vaddr;
0048     int ret;
0049 
0050     *vma = i915_vma_instance(obj, ce->vm, NULL);
0051     if (IS_ERR(*vma))
0052         return ERR_CAST(*vma);
0053 
0054     ret = i915_gem_object_lock(obj, ww);
0055     if (ret)
0056         return ERR_PTR(ret);
0057 
0058     vaddr = i915_gem_object_pin_map(obj, mode);
0059 
0060     if (!ww)
0061         i915_gem_object_unlock(obj);
0062 
0063     if (IS_ERR(vaddr))
0064         return vaddr;
0065 
0066     if (ww)
0067         ret = i915_vma_pin_ww(*vma, ww, 0, 0, PIN_USER);
0068     else
0069         ret = i915_vma_pin(*vma, 0, 0, PIN_USER);
0070 
0071     if (ret) {
0072         i915_gem_object_unpin_map(obj);
0073         return ERR_PTR(ret);
0074     }
0075 
0076     return vaddr;
0077 }
0078 
0079 int igt_spinner_pin(struct igt_spinner *spin,
0080             struct intel_context *ce,
0081             struct i915_gem_ww_ctx *ww)
0082 {
0083     void *vaddr;
0084 
0085     if (spin->ce && WARN_ON(spin->ce != ce))
0086         return -ENODEV;
0087     spin->ce = ce;
0088 
0089     if (!spin->seqno) {
0090         vaddr = igt_spinner_pin_obj(ce, ww, spin->hws, I915_MAP_WB, &spin->hws_vma);
0091         if (IS_ERR(vaddr))
0092             return PTR_ERR(vaddr);
0093 
0094         spin->seqno = memset(vaddr, 0xff, PAGE_SIZE);
0095     }
0096 
0097     if (!spin->batch) {
0098         unsigned int mode;
0099 
0100         mode = i915_coherent_map_type(spin->gt->i915, spin->obj, false);
0101         vaddr = igt_spinner_pin_obj(ce, ww, spin->obj, mode, &spin->batch_vma);
0102         if (IS_ERR(vaddr))
0103             return PTR_ERR(vaddr);
0104 
0105         spin->batch = vaddr;
0106     }
0107 
0108     return 0;
0109 }
0110 
0111 static unsigned int seqno_offset(u64 fence)
0112 {
0113     return offset_in_page(sizeof(u32) * fence);
0114 }
0115 
0116 static u64 hws_address(const struct i915_vma *hws,
0117                const struct i915_request *rq)
0118 {
0119     return hws->node.start + seqno_offset(rq->fence.context);
0120 }
0121 
0122 static int move_to_active(struct i915_vma *vma,
0123               struct i915_request *rq,
0124               unsigned int flags)
0125 {
0126     int err;
0127 
0128     i915_vma_lock(vma);
0129     err = i915_request_await_object(rq, vma->obj,
0130                     flags & EXEC_OBJECT_WRITE);
0131     if (err == 0)
0132         err = i915_vma_move_to_active(vma, rq, flags);
0133     i915_vma_unlock(vma);
0134 
0135     return err;
0136 }
0137 
0138 struct i915_request *
0139 igt_spinner_create_request(struct igt_spinner *spin,
0140                struct intel_context *ce,
0141                u32 arbitration_command)
0142 {
0143     struct intel_engine_cs *engine = ce->engine;
0144     struct i915_request *rq = NULL;
0145     struct i915_vma *hws, *vma;
0146     unsigned int flags;
0147     u32 *batch;
0148     int err;
0149 
0150     GEM_BUG_ON(spin->gt != ce->vm->gt);
0151 
0152     if (!intel_engine_can_store_dword(ce->engine))
0153         return ERR_PTR(-ENODEV);
0154 
0155     if (!spin->batch) {
0156         err = igt_spinner_pin(spin, ce, NULL);
0157         if (err)
0158             return ERR_PTR(err);
0159     }
0160 
0161     hws = spin->hws_vma;
0162     vma = spin->batch_vma;
0163 
0164     rq = intel_context_create_request(ce);
0165     if (IS_ERR(rq))
0166         return ERR_CAST(rq);
0167 
0168     err = move_to_active(vma, rq, 0);
0169     if (err)
0170         goto cancel_rq;
0171 
0172     err = move_to_active(hws, rq, 0);
0173     if (err)
0174         goto cancel_rq;
0175 
0176     batch = spin->batch;
0177 
0178     if (GRAPHICS_VER(rq->engine->i915) >= 8) {
0179         *batch++ = MI_STORE_DWORD_IMM_GEN4;
0180         *batch++ = lower_32_bits(hws_address(hws, rq));
0181         *batch++ = upper_32_bits(hws_address(hws, rq));
0182     } else if (GRAPHICS_VER(rq->engine->i915) >= 6) {
0183         *batch++ = MI_STORE_DWORD_IMM_GEN4;
0184         *batch++ = 0;
0185         *batch++ = hws_address(hws, rq);
0186     } else if (GRAPHICS_VER(rq->engine->i915) >= 4) {
0187         *batch++ = MI_STORE_DWORD_IMM_GEN4 | MI_USE_GGTT;
0188         *batch++ = 0;
0189         *batch++ = hws_address(hws, rq);
0190     } else {
0191         *batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;
0192         *batch++ = hws_address(hws, rq);
0193     }
0194     *batch++ = rq->fence.seqno;
0195 
0196     *batch++ = arbitration_command;
0197 
0198     if (GRAPHICS_VER(rq->engine->i915) >= 8)
0199         *batch++ = MI_BATCH_BUFFER_START | BIT(8) | 1;
0200     else if (IS_HASWELL(rq->engine->i915))
0201         *batch++ = MI_BATCH_BUFFER_START | MI_BATCH_PPGTT_HSW;
0202     else if (GRAPHICS_VER(rq->engine->i915) >= 6)
0203         *batch++ = MI_BATCH_BUFFER_START;
0204     else
0205         *batch++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT;
0206     *batch++ = lower_32_bits(vma->node.start);
0207     *batch++ = upper_32_bits(vma->node.start);
0208 
0209     *batch++ = MI_BATCH_BUFFER_END; /* not reached */
0210 
0211     intel_gt_chipset_flush(engine->gt);
0212 
0213     if (engine->emit_init_breadcrumb) {
0214         err = engine->emit_init_breadcrumb(rq);
0215         if (err)
0216             goto cancel_rq;
0217     }
0218 
0219     flags = 0;
0220     if (GRAPHICS_VER(rq->engine->i915) <= 5)
0221         flags |= I915_DISPATCH_SECURE;
0222     err = engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, flags);
0223 
0224 cancel_rq:
0225     if (err) {
0226         i915_request_set_error_once(rq, err);
0227         i915_request_add(rq);
0228     }
0229     return err ? ERR_PTR(err) : rq;
0230 }
0231 
0232 static u32
0233 hws_seqno(const struct igt_spinner *spin, const struct i915_request *rq)
0234 {
0235     u32 *seqno = spin->seqno + seqno_offset(rq->fence.context);
0236 
0237     return READ_ONCE(*seqno);
0238 }
0239 
0240 void igt_spinner_end(struct igt_spinner *spin)
0241 {
0242     if (!spin->batch)
0243         return;
0244 
0245     *spin->batch = MI_BATCH_BUFFER_END;
0246     intel_gt_chipset_flush(spin->gt);
0247 }
0248 
0249 void igt_spinner_fini(struct igt_spinner *spin)
0250 {
0251     igt_spinner_end(spin);
0252 
0253     if (spin->batch) {
0254         i915_vma_unpin(spin->batch_vma);
0255         i915_gem_object_unpin_map(spin->obj);
0256     }
0257     i915_gem_object_put(spin->obj);
0258 
0259     if (spin->seqno) {
0260         i915_vma_unpin(spin->hws_vma);
0261         i915_gem_object_unpin_map(spin->hws);
0262     }
0263     i915_gem_object_put(spin->hws);
0264 }
0265 
0266 bool igt_wait_for_spinner(struct igt_spinner *spin, struct i915_request *rq)
0267 {
0268     if (i915_request_is_ready(rq))
0269         intel_engine_flush_submission(rq->engine);
0270 
0271     return !(wait_for_us(i915_seqno_passed(hws_seqno(spin, rq),
0272                            rq->fence.seqno),
0273                  100) &&
0274          wait_for(i915_seqno_passed(hws_seqno(spin, rq),
0275                         rq->fence.seqno),
0276               50));
0277 }