1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright(c) 2024 Intel Corporation. 4 */ 5 6 #include "xe_pxp_submit.h" 7 8 #include <uapi/drm/xe_drm.h> 9 10 #include "xe_device_types.h" 11 #include "xe_bo.h" 12 #include "xe_exec_queue.h" 13 #include "xe_gsc_submit.h" 14 #include "xe_gt.h" 15 #include "xe_pxp_types.h" 16 #include "xe_vm.h" 17 18 /* 19 * The VCS is used for kernel-owned GGTT submissions to issue key termination. 20 * Terminations are serialized, so we only need a single queue and a single 21 * batch. 22 */ 23 static int allocate_vcs_execution_resources(struct xe_pxp *pxp) 24 { 25 struct xe_gt *gt = pxp->gt; 26 struct xe_device *xe = pxp->xe; 27 struct xe_tile *tile = gt_to_tile(gt); 28 struct xe_hw_engine *hwe; 29 struct xe_exec_queue *q; 30 struct xe_bo *bo; 31 int err; 32 33 hwe = xe_gt_hw_engine(gt, XE_ENGINE_CLASS_VIDEO_DECODE, 0, true); 34 if (!hwe) 35 return -ENODEV; 36 37 q = xe_exec_queue_create(xe, NULL, BIT(hwe->logical_instance), 1, hwe, 38 EXEC_QUEUE_FLAG_KERNEL | EXEC_QUEUE_FLAG_PERMANENT, 0); 39 if (IS_ERR(q)) 40 return PTR_ERR(q); 41 42 /* 43 * Each termination is 16 DWORDS, so 4K is enough to contain a 44 * termination for each sessions. 45 */ 46 bo = xe_bo_create_pin_map(xe, tile, 0, SZ_4K, ttm_bo_type_kernel, 47 XE_BO_FLAG_SYSTEM | XE_BO_FLAG_PINNED | XE_BO_FLAG_GGTT); 48 if (IS_ERR(bo)) { 49 err = PTR_ERR(bo); 50 goto out_queue; 51 } 52 53 pxp->vcs_exec.q = q; 54 pxp->vcs_exec.bo = bo; 55 56 return 0; 57 58 out_queue: 59 xe_exec_queue_put(q); 60 return err; 61 } 62 63 static void destroy_vcs_execution_resources(struct xe_pxp *pxp) 64 { 65 if (pxp->vcs_exec.bo) 66 xe_bo_unpin_map_no_vm(pxp->vcs_exec.bo); 67 68 if (pxp->vcs_exec.q) 69 xe_exec_queue_put(pxp->vcs_exec.q); 70 } 71 72 #define PXP_BB_SIZE XE_PAGE_SIZE 73 static int allocate_gsc_client_resources(struct xe_gt *gt, 74 struct xe_pxp_gsc_client_resources *gsc_res, 75 size_t inout_size) 76 { 77 struct xe_tile *tile = gt_to_tile(gt); 78 struct xe_device *xe = tile_to_xe(tile); 79 struct xe_hw_engine *hwe; 80 struct xe_vm *vm; 81 struct xe_bo *bo; 82 struct xe_exec_queue *q; 83 struct dma_fence *fence; 84 long timeout; 85 int err = 0; 86 87 hwe = xe_gt_hw_engine(gt, XE_ENGINE_CLASS_OTHER, 0, true); 88 89 /* we shouldn't reach here if the GSC engine is not available */ 90 xe_assert(xe, hwe); 91 92 /* PXP instructions must be issued from PPGTT */ 93 vm = xe_vm_create(xe, XE_VM_FLAG_GSC); 94 if (IS_ERR(vm)) 95 return PTR_ERR(vm); 96 97 /* We allocate a single object for the batch and the in/out memory */ 98 xe_vm_lock(vm, false); 99 bo = xe_bo_create_pin_map(xe, tile, vm, PXP_BB_SIZE + inout_size * 2, 100 ttm_bo_type_kernel, 101 XE_BO_FLAG_SYSTEM | XE_BO_FLAG_PINNED | XE_BO_FLAG_NEEDS_UC); 102 xe_vm_unlock(vm); 103 if (IS_ERR(bo)) { 104 err = PTR_ERR(bo); 105 goto vm_out; 106 } 107 108 fence = xe_vm_bind_kernel_bo(vm, bo, NULL, 0, XE_CACHE_WB); 109 if (IS_ERR(fence)) { 110 err = PTR_ERR(fence); 111 goto bo_out; 112 } 113 114 timeout = dma_fence_wait_timeout(fence, false, HZ); 115 dma_fence_put(fence); 116 if (timeout <= 0) { 117 err = timeout ?: -ETIME; 118 goto bo_out; 119 } 120 121 q = xe_exec_queue_create(xe, vm, BIT(hwe->logical_instance), 1, hwe, 122 EXEC_QUEUE_FLAG_KERNEL | 123 EXEC_QUEUE_FLAG_PERMANENT, 0); 124 if (IS_ERR(q)) { 125 err = PTR_ERR(q); 126 goto bo_out; 127 } 128 129 gsc_res->vm = vm; 130 gsc_res->bo = bo; 131 gsc_res->inout_size = inout_size; 132 gsc_res->batch = IOSYS_MAP_INIT_OFFSET(&bo->vmap, 0); 133 gsc_res->msg_in = IOSYS_MAP_INIT_OFFSET(&bo->vmap, PXP_BB_SIZE); 134 gsc_res->msg_out = IOSYS_MAP_INIT_OFFSET(&bo->vmap, PXP_BB_SIZE + inout_size); 135 gsc_res->q = q; 136 137 /* initialize host-session-handle (for all Xe-to-gsc-firmware PXP cmds) */ 138 gsc_res->host_session_handle = xe_gsc_create_host_session_id(); 139 140 return 0; 141 142 bo_out: 143 xe_bo_unpin_map_no_vm(bo); 144 vm_out: 145 xe_vm_close_and_put(vm); 146 147 return err; 148 } 149 150 static void destroy_gsc_client_resources(struct xe_pxp_gsc_client_resources *gsc_res) 151 { 152 if (!gsc_res->q) 153 return; 154 155 xe_exec_queue_put(gsc_res->q); 156 xe_bo_unpin_map_no_vm(gsc_res->bo); 157 xe_vm_close_and_put(gsc_res->vm); 158 } 159 160 /** 161 * xe_pxp_allocate_execution_resources - Allocate PXP submission objects 162 * @pxp: the xe_pxp structure 163 * 164 * Allocates exec_queues objects for VCS and GSCCS submission. The GSCCS 165 * submissions are done via PPGTT, so this function allocates a VM for it and 166 * maps the object into it. 167 * 168 * Returns 0 if the allocation and mapping is successful, an errno value 169 * otherwise. 170 */ 171 int xe_pxp_allocate_execution_resources(struct xe_pxp *pxp) 172 { 173 int err; 174 175 err = allocate_vcs_execution_resources(pxp); 176 if (err) 177 return err; 178 179 /* 180 * PXP commands can require a lot of BO space (see PXP_MAX_PACKET_SIZE), 181 * but we currently only support a subset of commands that are small 182 * (< 20 dwords), so a single page is enough for now. 183 */ 184 err = allocate_gsc_client_resources(pxp->gt, &pxp->gsc_res, XE_PAGE_SIZE); 185 if (err) 186 goto destroy_vcs_context; 187 188 return 0; 189 190 destroy_vcs_context: 191 destroy_vcs_execution_resources(pxp); 192 return err; 193 } 194 195 void xe_pxp_destroy_execution_resources(struct xe_pxp *pxp) 196 { 197 destroy_gsc_client_resources(&pxp->gsc_res); 198 destroy_vcs_execution_resources(pxp); 199 } 200