Lines Matching +full:enforce +full:- +full:video +full:- +full:mode

1 // SPDX-License-Identifier: MIT
3 * Copyright © 2023-2024 Intel Corporation
139 return tail >= head ? tail - head : in xe_oa_circ_diff()
140 tail + stream->oa_buffer.circ_size - head; in xe_oa_circ_diff()
145 return ptr + n >= stream->oa_buffer.circ_size ? in xe_oa_circ_incr()
146 ptr + n - stream->oa_buffer.circ_size : ptr + n; in xe_oa_circ_incr()
154 kfree(oa_config->regs); in xe_oa_config_release()
164 kref_put(&oa_config->ref, xe_oa_config_release); in xe_oa_config_put()
169 return kref_get_unless_zero(&oa_config->ref) ? oa_config : NULL; in xe_oa_config_get()
177 oa_config = idr_find(&oa->metrics_idr, metrics_set); in xe_oa_get_oa_config()
187 xe_oa_config_put(oa_bo->oa_config); in free_oa_config_bo()
188 xe_bb_free(oa_bo->bb, last_fence); in free_oa_config_bo()
194 return &stream->hwe->oa_unit->regs; in __oa_regs()
199 return xe_mmio_read32(&stream->gt->mmio, __oa_regs(stream)->oa_tail_ptr) & in xe_oa_hw_tail_read()
204 ((__s)->oa_buffer.format->header == HDR_64_BIT)
236 u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo); in xe_oa_buffer_check_unlocked()
237 int report_size = stream->oa_buffer.format->size; in xe_oa_buffer_check_unlocked()
243 spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags); in xe_oa_buffer_check_unlocked()
246 hw_tail -= gtt_offset; in xe_oa_buffer_check_unlocked()
253 partial_report_size = xe_oa_circ_diff(stream, hw_tail, stream->oa_buffer.tail); in xe_oa_buffer_check_unlocked()
269 while (xe_oa_circ_diff(stream, tail, stream->oa_buffer.tail) >= report_size) { in xe_oa_buffer_check_unlocked()
270 void *report = stream->oa_buffer.vaddr + tail; in xe_oa_buffer_check_unlocked()
279 drm_dbg(&stream->oa->xe->drm, in xe_oa_buffer_check_unlocked()
281 stream->oa_buffer.head, tail, hw_tail); in xe_oa_buffer_check_unlocked()
283 stream->oa_buffer.tail = tail; in xe_oa_buffer_check_unlocked()
285 pollin = xe_oa_circ_diff(stream, stream->oa_buffer.tail, in xe_oa_buffer_check_unlocked()
286 stream->oa_buffer.head) >= report_size; in xe_oa_buffer_check_unlocked()
288 spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); in xe_oa_buffer_check_unlocked()
299 stream->pollin = true; in xe_oa_poll_check_timer_cb()
300 wake_up(&stream->poll_wq); in xe_oa_poll_check_timer_cb()
303 hrtimer_forward_now(hrtimer, ns_to_ktime(stream->poll_period_ns)); in xe_oa_poll_check_timer_cb()
311 int report_size = stream->oa_buffer.format->size; in xe_oa_append_report()
315 if ((count - *offset) < report_size) in xe_oa_append_report()
316 return -ENOSPC; in xe_oa_append_report()
320 oa_buf_end = stream->oa_buffer.vaddr + stream->oa_buffer.circ_size; in xe_oa_append_report()
321 report_size_partial = oa_buf_end - report; in xe_oa_append_report()
325 return -EFAULT; in xe_oa_append_report()
328 if (copy_to_user(buf, stream->oa_buffer.vaddr, in xe_oa_append_report()
329 report_size - report_size_partial)) in xe_oa_append_report()
330 return -EFAULT; in xe_oa_append_report()
332 return -EFAULT; in xe_oa_append_report()
343 int report_size = stream->oa_buffer.format->size; in xe_oa_append_reports()
344 u8 *oa_buf_base = stream->oa_buffer.vaddr; in xe_oa_append_reports()
345 u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo); in xe_oa_append_reports()
351 spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags); in xe_oa_append_reports()
352 head = stream->oa_buffer.head; in xe_oa_append_reports()
353 tail = stream->oa_buffer.tail; in xe_oa_append_reports()
354 spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); in xe_oa_append_reports()
356 xe_assert(stream->oa->xe, in xe_oa_append_reports()
357 head < stream->oa_buffer.circ_size && tail < stream->oa_buffer.circ_size); in xe_oa_append_reports()
367 if (!(stream->oa_buffer.circ_size % report_size)) { in xe_oa_append_reports()
372 u8 *oa_buf_end = stream->oa_buffer.vaddr + stream->oa_buffer.circ_size; in xe_oa_append_reports()
373 u32 part = oa_buf_end - report; in xe_oa_append_reports()
380 memset(oa_buf_base, 0, report_size - part); in xe_oa_append_reports()
386 struct xe_reg oaheadptr = __oa_regs(stream)->oa_head_ptr; in xe_oa_append_reports()
388 spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags); in xe_oa_append_reports()
389 xe_mmio_write32(&stream->gt->mmio, oaheadptr, in xe_oa_append_reports()
391 stream->oa_buffer.head = head; in xe_oa_append_reports()
392 spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); in xe_oa_append_reports()
400 struct xe_mmio *mmio = &stream->gt->mmio; in xe_oa_init_oa_buffer()
401 u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo); in xe_oa_init_oa_buffer()
405 spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags); in xe_oa_init_oa_buffer()
407 xe_mmio_write32(mmio, __oa_regs(stream)->oa_status, 0); in xe_oa_init_oa_buffer()
408 xe_mmio_write32(mmio, __oa_regs(stream)->oa_head_ptr, in xe_oa_init_oa_buffer()
410 stream->oa_buffer.head = 0; in xe_oa_init_oa_buffer()
415 xe_mmio_write32(mmio, __oa_regs(stream)->oa_buffer, oa_buf); in xe_oa_init_oa_buffer()
416 xe_mmio_write32(mmio, __oa_regs(stream)->oa_tail_ptr, in xe_oa_init_oa_buffer()
420 stream->oa_buffer.tail = 0; in xe_oa_init_oa_buffer()
422 spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); in xe_oa_init_oa_buffer()
425 memset(stream->oa_buffer.vaddr, 0, stream->oa_buffer.bo->size); in xe_oa_init_oa_buffer()
430 return ((format->counter_select << (ffs(counter_sel_mask) - 1)) & counter_sel_mask) | in __format_to_oactrl()
431 REG_FIELD_PREP(OA_OACONTROL_REPORT_BC_MASK, format->bc_report) | in __format_to_oactrl()
432 REG_FIELD_PREP(OA_OACONTROL_COUNTER_SIZE_MASK, format->counter_size); in __format_to_oactrl()
439 if (stream->hwe->class != XE_ENGINE_CLASS_COMPUTE) in __oa_ccs_select()
442 val = REG_FIELD_PREP(OAG_OACONTROL_OA_CCS_SELECT_MASK, stream->hwe->instance); in __oa_ccs_select()
443 xe_assert(stream->oa->xe, in __oa_ccs_select()
444 REG_FIELD_GET(OAG_OACONTROL_OA_CCS_SELECT_MASK, val) == stream->hwe->instance); in __oa_ccs_select()
450 const struct xe_oa_format *format = stream->oa_buffer.format; in xe_oa_enable()
455 * BSpec: 46822: Bit 0. Even if stream->sample is 0, for OAR to function, the OA in xe_oa_enable()
461 val = __format_to_oactrl(format, regs->oa_ctrl_counter_select_mask) | in xe_oa_enable()
464 if (GRAPHICS_VER(stream->oa->xe) >= 20 && in xe_oa_enable()
465 stream->hwe->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG) in xe_oa_enable()
468 xe_mmio_write32(&stream->gt->mmio, regs->oa_ctrl, val); in xe_oa_enable()
473 struct xe_mmio *mmio = &stream->gt->mmio; in xe_oa_disable()
475 xe_mmio_write32(mmio, __oa_regs(stream)->oa_ctrl, 0); in xe_oa_disable()
476 if (xe_mmio_wait32(mmio, __oa_regs(stream)->oa_ctrl, in xe_oa_disable()
478 drm_err(&stream->oa->xe->drm, in xe_oa_disable()
481 if (GRAPHICS_VERx100(stream->oa->xe) <= 1270 && GRAPHICS_VERx100(stream->oa->xe) != 1260) { in xe_oa_disable()
485 drm_err(&stream->oa->xe->drm, in xe_oa_disable()
493 if (!stream->periodic) in xe_oa_wait_unlocked()
494 return -EINVAL; in xe_oa_wait_unlocked()
496 return wait_event_interruptible(stream->poll_wq, in xe_oa_wait_unlocked()
506 /* Only clear our bits to avoid side-effects */ in __xe_oa_read()
507 stream->oa_status = xe_mmio_rmw32(&stream->gt->mmio, __oa_regs(stream)->oa_status, in __xe_oa_read()
510 * Signal to userspace that there is non-zero OA status to read via in __xe_oa_read()
513 if (stream->oa_status & OASTATUS_RELEVANT_BITS) in __xe_oa_read()
514 return -EIO; in __xe_oa_read()
522 struct xe_oa_stream *stream = file->private_data; in xe_oa_read()
527 if (!stream->enabled || !stream->sample) in xe_oa_read()
528 return -EINVAL; in xe_oa_read()
530 if (!(file->f_flags & O_NONBLOCK)) { in xe_oa_read()
536 mutex_lock(&stream->stream_lock); in xe_oa_read()
538 mutex_unlock(&stream->stream_lock); in xe_oa_read()
541 mutex_lock(&stream->stream_lock); in xe_oa_read()
543 mutex_unlock(&stream->stream_lock); in xe_oa_read()
548 * before unblocking. The exception to this is if __xe_oa_read returns -ENOSPC, in xe_oa_read()
552 * Also in case of -EIO, we have already waited for data before returning in xe_oa_read()
553 * -EIO, so need to wait again in xe_oa_read()
555 if (ret != -ENOSPC && ret != -EIO) in xe_oa_read()
556 stream->pollin = false; in xe_oa_read()
558 /* Possible values for ret are 0, -EFAULT, -ENOSPC, -EIO, -EINVAL, ... */ in xe_oa_read()
559 return offset ?: (ret ?: -EAGAIN); in xe_oa_read()
567 poll_wait(file, &stream->poll_wq, wait); in xe_oa_poll_locked()
575 if (stream->pollin) in xe_oa_poll_locked()
583 struct xe_oa_stream *stream = file->private_data; in xe_oa_poll()
586 mutex_lock(&stream->stream_lock); in xe_oa_poll()
588 mutex_unlock(&stream->stream_lock); in xe_oa_poll()
595 if (q->vm) { in xe_oa_lock_vma()
596 down_read(&q->vm->lock); in xe_oa_lock_vma()
597 xe_vm_lock(q->vm, false); in xe_oa_lock_vma()
603 if (q->vm) { in xe_oa_unlock_vma()
604 xe_vm_unlock(q->vm); in xe_oa_unlock_vma()
605 up_read(&q->vm->lock); in xe_oa_unlock_vma()
612 struct xe_exec_queue *q = stream->exec_q ?: stream->k_exec_q; in xe_oa_submit_bb()
624 job->ggtt = true; in xe_oa_submit_bb()
627 for (int i = 0; i < stream->num_syncs && !err; i++) in xe_oa_submit_bb()
628 err = xe_sync_entry_add_deps(&stream->syncs[i], job); in xe_oa_submit_bb()
630 drm_dbg(&stream->oa->xe->drm, "xe_sync_entry_add_deps err %d\n", err); in xe_oa_submit_bb()
636 fence = dma_fence_get(&job->drm.s_fence->finished); in xe_oa_submit_bb()
657 u32 n_lri = min_t(u32, n_regs - i, in write_cs_mi_lri()
660 bb->cs[bb->len++] = MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(n_lri); in write_cs_mi_lri()
662 bb->cs[bb->len++] = reg_data[i].addr.addr; in write_cs_mi_lri()
663 bb->cs[bb->len++] = reg_data[i].value; in write_cs_mi_lri()
681 xe_bo_unpin_map_no_vm(stream->oa_buffer.bo); in xe_oa_free_oa_buffer()
688 xe_oa_config_put(stream->oa_config); in xe_oa_free_configs()
689 llist_for_each_entry_safe(oa_bo, tmp, stream->oa_config_bos.first, node) in xe_oa_free_configs()
690 free_oa_config_bo(oa_bo, stream->last_fence); in xe_oa_free_configs()
691 dma_fence_put(stream->last_fence); in xe_oa_free_configs()
700 bb = xe_bb_new(stream->gt, 2 * count + 1, false); in xe_oa_load_with_lri()
725 const struct xe_oa_format *format = stream->oa_buffer.format; in xe_oa_configure_oar_context()
731 OACTXCONTROL(stream->hwe->mmio_base), in xe_oa_configure_oar_context()
739 RING_CONTEXT_CONTROL(stream->hwe->mmio_base), in xe_oa_configure_oar_context()
750 const struct xe_oa_format *format = stream->oa_buffer.format; in xe_oa_configure_oac_context()
755 OACTXCONTROL(stream->hwe->mmio_base), in xe_oa_configure_oac_context()
763 RING_CONTEXT_CONTROL(stream->hwe->mmio_base), in xe_oa_configure_oac_context()
771 xe_mmio_write32(&stream->gt->mmio, __oa_regs(stream)->oa_ctrl, in xe_oa_configure_oac_context()
779 switch (stream->hwe->class) { in xe_oa_configure_oa_context()
785 /* Video engines do not support MI_REPORT_PERF_COUNT */ in xe_oa_configure_oa_context()
795 enable && stream && stream->sample ? in oag_configure_mmio_trigger()
801 struct xe_mmio *mmio = &stream->gt->mmio; in xe_oa_disable_metric_set()
808 if (stream->oa->xe->info.platform == XE_DG2) { in xe_oa_disable_metric_set()
809 xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN, in xe_oa_disable_metric_set()
811 xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN2, in xe_oa_disable_metric_set()
815 xe_mmio_write32(mmio, __oa_regs(stream)->oa_debug, in xe_oa_disable_metric_set()
819 if (stream->exec_q) in xe_oa_disable_metric_set()
826 (HAS_OA_BPC_REPORTING(stream->oa->xe) ? SQCNT1_OABPC : 0); in xe_oa_disable_metric_set()
834 struct xe_oa_unit *u = stream->hwe->oa_unit; in xe_oa_stream_destroy()
835 struct xe_gt *gt = stream->hwe->gt; in xe_oa_stream_destroy()
837 if (WARN_ON(stream != u->exclusive_stream)) in xe_oa_stream_destroy()
840 WRITE_ONCE(u->exclusive_stream, NULL); in xe_oa_stream_destroy()
842 mutex_destroy(&stream->stream_lock); in xe_oa_stream_destroy()
845 xe_exec_queue_put(stream->k_exec_q); in xe_oa_stream_destroy()
850 xe_pm_runtime_put(stream->oa->xe); in xe_oa_stream_destroy()
852 /* Wa_1509372804:pvc: Unset the override of GUCRC mode to enable rc6 */ in xe_oa_stream_destroy()
853 if (stream->override_gucrc) in xe_oa_stream_destroy()
854 xe_gt_WARN_ON(gt, xe_guc_pc_unset_gucrc_mode(&gt->uc.guc.pc)); in xe_oa_stream_destroy()
857 xe_file_put(stream->xef); in xe_oa_stream_destroy()
867 bo = xe_bo_create_pin_map(stream->oa->xe, stream->gt->tile, NULL, in xe_oa_alloc_oa_buffer()
873 stream->oa_buffer.bo = bo; in xe_oa_alloc_oa_buffer()
875 xe_assert(stream->oa->xe, bo->vmap.is_iomem == 0); in xe_oa_alloc_oa_buffer()
876 stream->oa_buffer.vaddr = bo->vmap.vaddr; in xe_oa_alloc_oa_buffer()
889 return ERR_PTR(-ENOMEM); in __xe_oa_alloc_config_buffer()
891 config_length = num_lri_dwords(oa_config->regs_len); in __xe_oa_alloc_config_buffer()
894 bb = xe_bb_new(stream->gt, config_length, false); in __xe_oa_alloc_config_buffer()
898 write_cs_mi_lri(bb, oa_config->regs, oa_config->regs_len); in __xe_oa_alloc_config_buffer()
900 oa_bo->bb = bb; in __xe_oa_alloc_config_buffer()
901 oa_bo->oa_config = xe_oa_config_get(oa_config); in __xe_oa_alloc_config_buffer()
902 llist_add(&oa_bo->node, &stream->oa_config_bos); in __xe_oa_alloc_config_buffer()
916 llist_for_each_entry(oa_bo, stream->oa_config_bos.first, node) { in xe_oa_alloc_config_buffer()
917 if (oa_bo->oa_config == oa_config && in xe_oa_alloc_config_buffer()
918 memcmp(oa_bo->oa_config->uuid, oa_config->uuid, in xe_oa_alloc_config_buffer()
919 sizeof(oa_config->uuid)) == 0) in xe_oa_alloc_config_buffer()
930 dma_fence_put(stream->last_fence); in xe_oa_update_last_fence()
931 stream->last_fence = dma_fence_get(fence); in xe_oa_update_last_fence()
939 dma_fence_signal(&ofence->base); in xe_oa_fence_work_fn()
940 dma_fence_put(&ofence->base); in xe_oa_fence_work_fn()
950 INIT_DELAYED_WORK(&ofence->work, xe_oa_fence_work_fn); in xe_oa_config_cb()
951 queue_delayed_work(system_unbound_wq, &ofence->work, in xe_oa_config_cb()
981 err = -ENOMEM; in xe_oa_emit_oa_config()
992 fence = xe_oa_submit_bb(stream, XE_OA_SUBMIT_ADD_DEPS, oa_bo->bb); in xe_oa_emit_oa_config()
999 spin_lock_init(&ofence->lock); in xe_oa_emit_oa_config()
1000 dma_fence_init(&ofence->base, &xe_oa_fence_ops, &ofence->lock, 0, 0); in xe_oa_emit_oa_config()
1002 for (i = 0; i < stream->num_syncs; i++) { in xe_oa_emit_oa_config()
1003 if (stream->syncs[i].flags & DRM_XE_SYNC_FLAG_SIGNAL) in xe_oa_emit_oa_config()
1005 xe_sync_entry_signal(&stream->syncs[i], &ofence->base); in xe_oa_emit_oa_config()
1010 dma_fence_get(&ofence->base); in xe_oa_emit_oa_config()
1015 /* Add job fence callback to schedule work to signal ofence->base */ in xe_oa_emit_oa_config()
1016 err = dma_fence_add_callback(fence, &ofence->cb, xe_oa_config_cb); in xe_oa_emit_oa_config()
1017 xe_gt_assert(stream->gt, !err || err == -ENOENT); in xe_oa_emit_oa_config()
1018 if (err == -ENOENT) in xe_oa_emit_oa_config()
1019 xe_oa_config_cb(fence, &ofence->cb); in xe_oa_emit_oa_config()
1023 dma_fence_wait(&ofence->base, false); in xe_oa_emit_oa_config()
1024 dma_fence_put(&ofence->base); in xe_oa_emit_oa_config()
1028 for (i = 0; i < stream->num_syncs; i++) in xe_oa_emit_oa_config()
1029 xe_sync_entry_cleanup(&stream->syncs[i]); in xe_oa_emit_oa_config()
1030 kfree(stream->syncs); in xe_oa_emit_oa_config()
1042 stream->sample ? in oag_report_ctx_switches()
1048 struct xe_mmio *mmio = &stream->gt->mmio; in xe_oa_enable_metric_set()
1057 if (stream->oa->xe->info.platform == XE_DG2) { in xe_oa_enable_metric_set()
1058 xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN, in xe_oa_enable_metric_set()
1060 xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN2, in xe_oa_enable_metric_set()
1068 if (GRAPHICS_VER(stream->oa->xe) >= 20) in xe_oa_enable_metric_set()
1075 xe_mmio_write32(mmio, __oa_regs(stream)->oa_debug, in xe_oa_enable_metric_set()
1080 xe_mmio_write32(mmio, __oa_regs(stream)->oa_ctx_ctrl, stream->periodic ? in xe_oa_enable_metric_set()
1084 stream->period_exponent)) : 0); in xe_oa_enable_metric_set()
1092 (HAS_OA_BPC_REPORTING(stream->oa->xe) ? SQCNT1_OABPC : 0); in xe_oa_enable_metric_set()
1097 if (stream->exec_q) { in xe_oa_enable_metric_set()
1103 return xe_oa_emit_oa_config(stream, stream->oa_config); in xe_oa_enable_metric_set()
1114 for_each_set_bit(idx, oa->format_mask, __XE_OA_FORMAT_MAX) { in decode_oa_format()
1115 const struct xe_oa_format *f = &oa->oa_formats[idx]; in decode_oa_format()
1117 if (counter_size == f->counter_size && bc_report == f->bc_report && in decode_oa_format()
1118 type == f->type && counter_sel == f->counter_select) { in decode_oa_format()
1124 return -EINVAL; in decode_oa_format()
1130 if (value >= oa->oa_unit_ids) { in xe_oa_set_prop_oa_unit_id()
1131 drm_dbg(&oa->xe->drm, "OA unit ID out of range %lld\n", value); in xe_oa_set_prop_oa_unit_id()
1132 return -EINVAL; in xe_oa_set_prop_oa_unit_id()
1134 param->oa_unit_id = value; in xe_oa_set_prop_oa_unit_id()
1141 param->sample = value; in xe_oa_set_prop_sample_oa()
1148 param->metric_set = value; in xe_oa_set_prop_metric_set()
1155 int ret = decode_oa_format(oa, value, &param->oa_format); in xe_oa_set_prop_oa_format()
1158 drm_dbg(&oa->xe->drm, "Unsupported OA report format %#llx\n", value); in xe_oa_set_prop_oa_format()
1170 drm_dbg(&oa->xe->drm, "OA timer exponent too high (> %u)\n", OA_EXPONENT_MAX); in xe_oa_set_prop_oa_exponent()
1171 return -EINVAL; in xe_oa_set_prop_oa_exponent()
1173 param->period_exponent = value; in xe_oa_set_prop_oa_exponent()
1180 param->disabled = value; in xe_oa_set_prop_disabled()
1187 param->exec_queue_id = value; in xe_oa_set_prop_exec_queue_id()
1194 param->engine_instance = value; in xe_oa_set_prop_engine_instance()
1201 param->no_preempt = value; in xe_oa_set_no_preempt()
1208 param->num_syncs = value; in xe_oa_set_prop_num_syncs()
1215 param->syncs_user = u64_to_user_ptr(value); in xe_oa_set_prop_syncs_user()
1222 return -EINVAL; in xe_oa_set_prop_ret_inval()
1264 if (XE_IOCTL_DBG(oa->xe, err)) in xe_oa_user_ext_set_property()
1265 return -EFAULT; in xe_oa_user_ext_set_property()
1270 if (XE_IOCTL_DBG(oa->xe, ext.property >= ARRAY_SIZE(xe_oa_set_property_funcs_open)) || in xe_oa_user_ext_set_property()
1271 XE_IOCTL_DBG(oa->xe, ext.pad)) in xe_oa_user_ext_set_property()
1272 return -EINVAL; in xe_oa_user_ext_set_property()
1297 if (XE_IOCTL_DBG(oa->xe, ext_number >= MAX_USER_EXTENSIONS)) in xe_oa_user_extensions()
1298 return -E2BIG; in xe_oa_user_extensions()
1301 if (XE_IOCTL_DBG(oa->xe, err)) in xe_oa_user_extensions()
1302 return -EFAULT; in xe_oa_user_extensions()
1304 if (XE_IOCTL_DBG(oa->xe, ext.pad) || in xe_oa_user_extensions()
1305 XE_IOCTL_DBG(oa->xe, ext.name >= ARRAY_SIZE(xe_oa_user_extension_funcs))) in xe_oa_user_extensions()
1306 return -EINVAL; in xe_oa_user_extensions()
1310 if (XE_IOCTL_DBG(oa->xe, err)) in xe_oa_user_extensions()
1323 if (param->num_syncs && !param->syncs_user) { in xe_oa_parse_syncs()
1324 drm_dbg(&oa->xe->drm, "num_syncs specified without sync array\n"); in xe_oa_parse_syncs()
1325 ret = -EINVAL; in xe_oa_parse_syncs()
1329 if (param->num_syncs) { in xe_oa_parse_syncs()
1330 param->syncs = kcalloc(param->num_syncs, sizeof(*param->syncs), GFP_KERNEL); in xe_oa_parse_syncs()
1331 if (!param->syncs) { in xe_oa_parse_syncs()
1332 ret = -ENOMEM; in xe_oa_parse_syncs()
1337 for (num_syncs = 0; num_syncs < param->num_syncs; num_syncs++) { in xe_oa_parse_syncs()
1338 ret = xe_sync_entry_parse(oa->xe, param->xef, &param->syncs[num_syncs], in xe_oa_parse_syncs()
1339 &param->syncs_user[num_syncs], 0); in xe_oa_parse_syncs()
1343 if (xe_sync_is_ufence(&param->syncs[num_syncs])) in xe_oa_parse_syncs()
1347 if (XE_IOCTL_DBG(oa->xe, num_ufence > 1)) { in xe_oa_parse_syncs()
1348 ret = -EINVAL; in xe_oa_parse_syncs()
1355 while (num_syncs--) in xe_oa_parse_syncs()
1356 xe_sync_entry_cleanup(&param->syncs[num_syncs]); in xe_oa_parse_syncs()
1357 kfree(param->syncs); in xe_oa_parse_syncs()
1364 stream->pollin = false; in xe_oa_stream_enable()
1368 if (stream->sample) in xe_oa_stream_enable()
1369 hrtimer_start(&stream->poll_check_timer, in xe_oa_stream_enable()
1370 ns_to_ktime(stream->poll_period_ns), in xe_oa_stream_enable()
1378 if (stream->sample) in xe_oa_stream_disable()
1379 hrtimer_cancel(&stream->poll_check_timer); in xe_oa_stream_disable()
1384 struct xe_exec_queue *q = stream->exec_q; in xe_oa_enable_preempt_timeslice()
1388 ret1 = q->ops->set_timeslice(q, stream->hwe->eclass->sched_props.timeslice_us); in xe_oa_enable_preempt_timeslice()
1389 ret2 = q->ops->set_preempt_timeout(q, stream->hwe->eclass->sched_props.preempt_timeout_us); in xe_oa_enable_preempt_timeslice()
1394 drm_dbg(&stream->oa->xe->drm, "%s failed ret1 %d ret2 %d\n", __func__, ret1, ret2); in xe_oa_enable_preempt_timeslice()
1400 struct xe_exec_queue *q = stream->exec_q; in xe_oa_disable_preempt_timeslice()
1404 ret = q->ops->set_timeslice(q, 0); in xe_oa_disable_preempt_timeslice()
1408 ret = q->ops->set_preempt_timeout(q, 0); in xe_oa_disable_preempt_timeslice()
1415 drm_dbg(&stream->oa->xe->drm, "%s failed %d\n", __func__, ret); in xe_oa_disable_preempt_timeslice()
1421 if (stream->enabled) in xe_oa_enable_locked()
1424 if (stream->no_preempt) { in xe_oa_enable_locked()
1433 stream->enabled = true; in xe_oa_enable_locked()
1441 if (!stream->enabled) in xe_oa_disable_locked()
1446 if (stream->no_preempt) in xe_oa_disable_locked()
1449 stream->enabled = false; in xe_oa_disable_locked()
1456 long ret = stream->oa_config->id; in xe_oa_config_locked()
1460 err = xe_oa_user_extensions(stream->oa, XE_OA_USER_EXTN_FROM_CONFIG, arg, 0, &param); in xe_oa_config_locked()
1464 config = xe_oa_get_oa_config(stream->oa, param.metric_set); in xe_oa_config_locked()
1466 return -ENODEV; in xe_oa_config_locked()
1468 param.xef = stream->xef; in xe_oa_config_locked()
1469 err = xe_oa_parse_syncs(stream->oa, &param); in xe_oa_config_locked()
1473 stream->num_syncs = param.num_syncs; in xe_oa_config_locked()
1474 stream->syncs = param.syncs; in xe_oa_config_locked()
1478 config = xchg(&stream->oa_config, config); in xe_oa_config_locked()
1479 drm_dbg(&stream->oa->xe->drm, "changed to oa config uuid=%s\n", in xe_oa_config_locked()
1480 stream->oa_config->uuid); in xe_oa_config_locked()
1495 if (stream->oa_status & OASTATUS_REPORT_LOST) in xe_oa_status_locked()
1497 if (stream->oa_status & OASTATUS_BUFFER_OVERFLOW) in xe_oa_status_locked()
1499 if (stream->oa_status & OASTATUS_COUNTER_OVERFLOW) in xe_oa_status_locked()
1501 if (stream->oa_status & OASTATUS_MMIO_TRG_Q_FULL) in xe_oa_status_locked()
1505 return -EFAULT; in xe_oa_status_locked()
1516 return -EFAULT; in xe_oa_info_locked()
1538 return -EINVAL; in xe_oa_ioctl_locked()
1545 struct xe_oa_stream *stream = file->private_data; in xe_oa_ioctl()
1548 mutex_lock(&stream->stream_lock); in xe_oa_ioctl()
1550 mutex_unlock(&stream->stream_lock); in xe_oa_ioctl()
1557 if (stream->enabled) in xe_oa_destroy_locked()
1562 if (stream->exec_q) in xe_oa_destroy_locked()
1563 xe_exec_queue_put(stream->exec_q); in xe_oa_destroy_locked()
1570 struct xe_oa_stream *stream = file->private_data; in xe_oa_release()
1571 struct xe_gt *gt = stream->gt; in xe_oa_release()
1574 mutex_lock(&gt->oa.gt_lock); in xe_oa_release()
1576 mutex_unlock(&gt->oa.gt_lock); in xe_oa_release()
1580 drm_dev_put(&gt_to_xe(gt)->drm); in xe_oa_release()
1587 struct xe_oa_stream *stream = file->private_data; in xe_oa_mmap()
1588 struct xe_bo *bo = stream->oa_buffer.bo; in xe_oa_mmap()
1589 unsigned long start = vma->vm_start; in xe_oa_mmap()
1593 drm_dbg(&stream->oa->xe->drm, "Insufficient privilege to map OA buffer\n"); in xe_oa_mmap()
1594 return -EACCES; in xe_oa_mmap()
1598 if (vma->vm_end - vma->vm_start != XE_OA_BUFFER_SIZE) { in xe_oa_mmap()
1599 drm_dbg(&stream->oa->xe->drm, "Wrong mmap size, must be OA buffer size\n"); in xe_oa_mmap()
1600 return -EINVAL; in xe_oa_mmap()
1604 * Only support VM_READ, enforce MAP_PRIVATE by checking for in xe_oa_mmap()
1607 if (vma->vm_flags & (VM_WRITE | VM_EXEC | VM_SHARED | VM_MAYSHARE)) { in xe_oa_mmap()
1608 drm_dbg(&stream->oa->xe->drm, "mmap must be read only\n"); in xe_oa_mmap()
1609 return -EINVAL; in xe_oa_mmap()
1614 xe_assert(stream->oa->xe, bo->ttm.ttm->num_pages == vma_pages(vma)); in xe_oa_mmap()
1615 for (i = 0; i < bo->ttm.ttm->num_pages; i++) { in xe_oa_mmap()
1616 ret = remap_pfn_range(vma, start, page_to_pfn(bo->ttm.ttm->pages[i]), in xe_oa_mmap()
1617 PAGE_SIZE, vma->vm_page_prot); in xe_oa_mmap()
1638 return hwe->class == XE_ENGINE_CLASS_RENDER || in engine_supports_mi_query()
1639 hwe->class == XE_ENGINE_CLASS_COMPUTE; in engine_supports_mi_query()
1665 struct xe_lrc *lrc = stream->exec_q->lrc[0]; in xe_oa_context_image_offset()
1666 u32 len = (xe_gt_lrc_size(stream->gt, stream->hwe->class) + in xe_oa_context_image_offset()
1667 lrc->ring.size) / sizeof(u32); in xe_oa_context_image_offset()
1669 u32 *state = (u32 *)lrc->bo->vmap.vaddr; in xe_oa_context_image_offset()
1671 if (drm_WARN_ON(&stream->oa->xe->drm, !state)) in xe_oa_context_image_offset()
1677 * We expect reg-value pairs in MI_LRI command, so in xe_oa_context_image_offset()
1680 drm_WARN_ON(&stream->oa->xe->drm, in xe_oa_context_image_offset()
1695 struct xe_reg reg = OACTXCONTROL(stream->hwe->mmio_base); in xe_oa_set_ctx_ctrl_offset()
1696 u32 offset = stream->oa->ctx_oactxctrl_offset[stream->hwe->class]; in xe_oa_set_ctx_ctrl_offset()
1703 stream->oa->ctx_oactxctrl_offset[stream->hwe->class] = offset; in xe_oa_set_ctx_ctrl_offset()
1705 drm_dbg(&stream->oa->xe->drm, "%s oa ctx control at 0x%08x dword offset\n", in xe_oa_set_ctx_ctrl_offset()
1706 stream->hwe->name, offset); in xe_oa_set_ctx_ctrl_offset()
1708 return offset && offset != U32_MAX ? 0 : -ENODEV; in xe_oa_set_ctx_ctrl_offset()
1714 struct xe_oa_unit *u = param->hwe->oa_unit; in xe_oa_stream_init()
1715 struct xe_gt *gt = param->hwe->gt; in xe_oa_stream_init()
1719 stream->exec_q = param->exec_q; in xe_oa_stream_init()
1720 stream->poll_period_ns = DEFAULT_POLL_PERIOD_NS; in xe_oa_stream_init()
1721 stream->hwe = param->hwe; in xe_oa_stream_init()
1722 stream->gt = stream->hwe->gt; in xe_oa_stream_init()
1723 stream->oa_buffer.format = &stream->oa->oa_formats[param->oa_format]; in xe_oa_stream_init()
1725 stream->sample = param->sample; in xe_oa_stream_init()
1726 stream->periodic = param->period_exponent > 0; in xe_oa_stream_init()
1727 stream->period_exponent = param->period_exponent; in xe_oa_stream_init()
1728 stream->no_preempt = param->no_preempt; in xe_oa_stream_init()
1730 stream->xef = xe_file_get(param->xef); in xe_oa_stream_init()
1731 stream->num_syncs = param->num_syncs; in xe_oa_stream_init()
1732 stream->syncs = param->syncs; in xe_oa_stream_init()
1735 * For Xe2+, when overrun mode is enabled, there are no partial reports at the end in xe_oa_stream_init()
1736 * of buffer, making the OA buffer effectively a non-power-of-2 size circular in xe_oa_stream_init()
1739 if (GRAPHICS_VER(stream->oa->xe) >= 20 && in xe_oa_stream_init()
1740 stream->hwe->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG && stream->sample) in xe_oa_stream_init()
1741 stream->oa_buffer.circ_size = in xe_oa_stream_init()
1742 XE_OA_BUFFER_SIZE - XE_OA_BUFFER_SIZE % stream->oa_buffer.format->size; in xe_oa_stream_init()
1744 stream->oa_buffer.circ_size = XE_OA_BUFFER_SIZE; in xe_oa_stream_init()
1746 if (stream->exec_q && engine_supports_mi_query(stream->hwe)) { in xe_oa_stream_init()
1750 drm_err(&stream->oa->xe->drm, in xe_oa_stream_init()
1752 stream->hwe->name); in xe_oa_stream_init()
1757 stream->oa_config = xe_oa_get_oa_config(stream->oa, param->metric_set); in xe_oa_stream_init()
1758 if (!stream->oa_config) { in xe_oa_stream_init()
1759 drm_dbg(&stream->oa->xe->drm, "Invalid OA config id=%i\n", param->metric_set); in xe_oa_stream_init()
1760 ret = -EINVAL; in xe_oa_stream_init()
1768 * state. Prevent this by overriding GUCRC mode. in xe_oa_stream_init()
1770 if (stream->oa->xe->info.platform == XE_PVC) { in xe_oa_stream_init()
1771 ret = xe_guc_pc_override_gucrc_mode(&gt->uc.guc.pc, in xe_oa_stream_init()
1776 stream->override_gucrc = true; in xe_oa_stream_init()
1780 xe_pm_runtime_get(stream->oa->xe); in xe_oa_stream_init()
1783 ret = -ETIMEDOUT; in xe_oa_stream_init()
1791 stream->k_exec_q = xe_exec_queue_create(stream->oa->xe, NULL, in xe_oa_stream_init()
1792 BIT(stream->hwe->logical_instance), 1, in xe_oa_stream_init()
1793 stream->hwe, EXEC_QUEUE_FLAG_KERNEL, 0); in xe_oa_stream_init()
1794 if (IS_ERR(stream->k_exec_q)) { in xe_oa_stream_init()
1795 ret = PTR_ERR(stream->k_exec_q); in xe_oa_stream_init()
1796 drm_err(&stream->oa->xe->drm, "gt%d, hwe %s, xe_exec_queue_create failed=%d", in xe_oa_stream_init()
1797 stream->gt->info.id, stream->hwe->name, ret); in xe_oa_stream_init()
1803 drm_dbg(&stream->oa->xe->drm, "Unable to enable metric set\n"); in xe_oa_stream_init()
1807 drm_dbg(&stream->oa->xe->drm, "opening stream oa config uuid=%s\n", in xe_oa_stream_init()
1808 stream->oa_config->uuid); in xe_oa_stream_init()
1810 WRITE_ONCE(u->exclusive_stream, stream); in xe_oa_stream_init()
1812 hrtimer_init(&stream->poll_check_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); in xe_oa_stream_init()
1813 stream->poll_check_timer.function = xe_oa_poll_check_timer_cb; in xe_oa_stream_init()
1814 init_waitqueue_head(&stream->poll_wq); in xe_oa_stream_init()
1816 spin_lock_init(&stream->oa_buffer.ptr_lock); in xe_oa_stream_init()
1817 mutex_init(&stream->stream_lock); in xe_oa_stream_init()
1823 xe_exec_queue_put(stream->k_exec_q); in xe_oa_stream_init()
1828 xe_pm_runtime_put(stream->oa->xe); in xe_oa_stream_init()
1829 if (stream->override_gucrc) in xe_oa_stream_init()
1830 xe_gt_WARN_ON(gt, xe_guc_pc_unset_gucrc_mode(&gt->uc.guc.pc)); in xe_oa_stream_init()
1834 xe_file_put(stream->xef); in xe_oa_stream_init()
1846 if (param->hwe->oa_unit->exclusive_stream) { in xe_oa_stream_open_ioctl_locked()
1847 drm_dbg(&oa->xe->drm, "OA unit already in use\n"); in xe_oa_stream_open_ioctl_locked()
1848 ret = -EBUSY; in xe_oa_stream_open_ioctl_locked()
1854 ret = -ENOMEM; in xe_oa_stream_open_ioctl_locked()
1858 stream->oa = oa; in xe_oa_stream_open_ioctl_locked()
1863 if (!param->disabled) { in xe_oa_stream_open_ioctl_locked()
1876 drm_dev_get(&stream->oa->xe->drm); in xe_oa_stream_open_ioctl_locked()
1880 if (!param->disabled) in xe_oa_stream_open_ioctl_locked()
1891 * xe_oa_timestamp_frequency - Return OA timestamp frequency
1907 switch (gt_to_xe(gt)->info.platform) { in xe_oa_timestamp_frequency()
1912 reg = xe_mmio_read32(&gt->mmio, RPM_CONFIG0); in xe_oa_timestamp_frequency()
1916 return gt->info.reference_clock << (3 - shift); in xe_oa_timestamp_frequency()
1919 return gt->info.reference_clock; in xe_oa_timestamp_frequency()
1928 return div_u64(nom + den - 1, den); in oa_exponent_to_ns()
1933 switch (hwe->oa_unit->type) { in engine_supports_oa_format()
1945 * xe_oa_unit_id - Return OA unit ID for a hardware engine
1952 return hwe->oa_unit && hwe->oa_unit->num_engines ? in xe_oa_unit_id()
1953 hwe->oa_unit->oa_unit_id : U16_MAX; in xe_oa_unit_id()
1961 if (param->exec_q) { in xe_oa_assign_hwe()
1963 param->hwe = xe_gt_hw_engine(param->exec_q->gt, param->exec_q->class, in xe_oa_assign_hwe()
1964 param->engine_instance, true); in xe_oa_assign_hwe()
1970 for_each_gt(gt, oa->xe, i) { in xe_oa_assign_hwe()
1972 if (xe_oa_unit_id(hwe) == param->oa_unit_id) { in xe_oa_assign_hwe()
1973 param->hwe = hwe; in xe_oa_assign_hwe()
1980 if (!param->hwe || xe_oa_unit_id(param->hwe) != param->oa_unit_id) { in xe_oa_assign_hwe()
1981 drm_dbg(&oa->xe->drm, "Unable to find hwe (%d, %d) for OA unit ID %d\n", in xe_oa_assign_hwe()
1982 param->exec_q ? param->exec_q->class : -1, in xe_oa_assign_hwe()
1983 param->engine_instance, param->oa_unit_id); in xe_oa_assign_hwe()
1984 ret = -EINVAL; in xe_oa_assign_hwe()
1991 * xe_oa_stream_open_ioctl - Opens an OA stream
2003 struct xe_oa *oa = &xe->oa; in xe_oa_stream_open_ioctl()
2010 if (!oa->xe) { in xe_oa_stream_open_ioctl()
2011 drm_dbg(&xe->drm, "xe oa interface not available for this system\n"); in xe_oa_stream_open_ioctl()
2012 return -ENODEV; in xe_oa_stream_open_ioctl()
2022 if (XE_IOCTL_DBG(oa->xe, !param.exec_q)) in xe_oa_stream_open_ioctl()
2023 return -ENOENT; in xe_oa_stream_open_ioctl()
2025 if (XE_IOCTL_DBG(oa->xe, param.exec_q->width > 1)) in xe_oa_stream_open_ioctl()
2026 return -EOPNOTSUPP; in xe_oa_stream_open_ioctl()
2038 drm_dbg(&oa->xe->drm, "Preemption disable without exec_q!\n"); in xe_oa_stream_open_ioctl()
2039 ret = -EINVAL; in xe_oa_stream_open_ioctl()
2046 drm_dbg(&oa->xe->drm, "Insufficient privileges to open xe OA stream\n"); in xe_oa_stream_open_ioctl()
2047 ret = -EACCES; in xe_oa_stream_open_ioctl()
2052 drm_dbg(&oa->xe->drm, "Only OA report sampling supported\n"); in xe_oa_stream_open_ioctl()
2053 ret = -EINVAL; in xe_oa_stream_open_ioctl()
2061 f = &oa->oa_formats[param.oa_format]; in xe_oa_stream_open_ioctl()
2062 if (!param.oa_format || !f->size || in xe_oa_stream_open_ioctl()
2063 !engine_supports_oa_format(param.hwe, f->type)) { in xe_oa_stream_open_ioctl()
2064 drm_dbg(&oa->xe->drm, "Invalid OA format %d type %d size %d for class %d\n", in xe_oa_stream_open_ioctl()
2065 param.oa_format, f->type, f->size, param.hwe->class); in xe_oa_stream_open_ioctl()
2066 ret = -EINVAL; in xe_oa_stream_open_ioctl()
2075 drm_dbg(&oa->xe->drm, "OA_EXPONENT specified without SAMPLE_OA\n"); in xe_oa_stream_open_ioctl()
2076 ret = -EINVAL; in xe_oa_stream_open_ioctl()
2079 oa_period = oa_exponent_to_ns(param.hwe->gt, param.period_exponent); in xe_oa_stream_open_ioctl()
2081 drm_dbg(&oa->xe->drm, "Using periodic sampling freq %lld Hz\n", oa_freq_hz); in xe_oa_stream_open_ioctl()
2088 mutex_lock(&param.hwe->gt->oa.gt_lock); in xe_oa_stream_open_ioctl()
2090 mutex_unlock(&param.hwe->gt->oa.gt_lock); in xe_oa_stream_open_ioctl()
2097 while (param.num_syncs--) in xe_oa_stream_open_ioctl()
2128 while (table->start && table->end) { in xe_oa_reg_in_range_table()
2129 if (addr >= table->start && addr <= table->end) in xe_oa_reg_in_range_table()
2140 { .start = 0xdd00, .end = 0xdd48 }, /* OAG_LCE0_0 - OAA_LENABLE_REG */
2146 { .start = 0xd900, .end = 0xd91c }, /* OAG_OASTARTTRIG[1-8] */
2147 { .start = 0xd920, .end = 0xd93c }, /* OAG_OAREPORTTRIG1[1-8] */
2148 { .start = 0xd940, .end = 0xd97c }, /* OAG_CEC[0-7][0-1] */
2149 { .start = 0xdc00, .end = 0xdc3c }, /* OAG_SCEC[0-7][0-1] */
2156 { .start = 0x393000, .end = 0x39301c }, /* OAM_STARTTRIG1[1-8] */
2157 { .start = 0x393020, .end = 0x39303c }, /* OAM_REPORTTRIG1[1-8] */
2158 { .start = 0x393040, .end = 0x39307c }, /* OAM_CEC[0-7][0-1] */
2159 { .start = 0x393200, .end = 0x39323C }, /* MPES[0-7] */
2164 { .start = 0x393200, .end = 0x39323C }, /* MPES_0_MPES_SAG - MPES_7_UPPER_MPES_SAG */
2165 { .start = 0x394200, .end = 0x39423C }, /* MPES_0_MPES_SCMI0 - MPES_7_UPPER_MPES_SCMI0 */
2166 { .start = 0x394A00, .end = 0x394A3C }, /* MPES_0_MPES_SCMI1 - MPES_7_UPPER_MPES_SCMI1 */
2175 (GRAPHICS_VER(oa->xe) >= 20 && in xe_oa_is_valid_b_counter_addr()
2180 { .start = 0x0d00, .end = 0x0d04 }, /* RPM_CONFIG[0-1] */
2181 { .start = 0x0d0c, .end = 0x0d2c }, /* NOA_CONFIG[0-8] */
2189 { .start = 0x0d00, .end = 0x0d04 }, /* RPM_CONFIG[0-1] */
2190 { .start = 0x0d0c, .end = 0x0d2c }, /* NOA_CONFIG[0-8] */
2203 { .start = 0x13000, .end = 0x137FC }, /* PES_0_PESL0 - PES_63_UPPER_PESL3 */
2209 if (GRAPHICS_VER(oa->xe) >= 20) in xe_oa_is_valid_mux_addr()
2211 else if (GRAPHICS_VERx100(oa->xe) >= 1270) in xe_oa_is_valid_mux_addr()
2234 return ERR_PTR(-ENOMEM); in xe_oa_alloc_regs()
2244 drm_dbg(&oa->xe->drm, "Invalid oa_reg address: %X\n", addr); in xe_oa_alloc_regs()
2245 err = -EINVAL; in xe_oa_alloc_regs()
2273 return sysfs_emit(buf, "%d\n", oa_config->id); in show_dynamic_id()
2279 sysfs_attr_init(&oa_config->sysfs_metric_id.attr); in create_dynamic_oa_sysfs_entry()
2280 oa_config->sysfs_metric_id.attr.name = "id"; in create_dynamic_oa_sysfs_entry()
2281 oa_config->sysfs_metric_id.attr.mode = 0444; in create_dynamic_oa_sysfs_entry()
2282 oa_config->sysfs_metric_id.show = show_dynamic_id; in create_dynamic_oa_sysfs_entry()
2283 oa_config->sysfs_metric_id.store = NULL; in create_dynamic_oa_sysfs_entry()
2285 oa_config->attrs[0] = &oa_config->sysfs_metric_id.attr; in create_dynamic_oa_sysfs_entry()
2286 oa_config->attrs[1] = NULL; in create_dynamic_oa_sysfs_entry()
2288 oa_config->sysfs_metric.name = oa_config->uuid; in create_dynamic_oa_sysfs_entry()
2289 oa_config->sysfs_metric.attrs = oa_config->attrs; in create_dynamic_oa_sysfs_entry()
2291 return sysfs_create_group(oa->metrics_kobj, &oa_config->sysfs_metric); in create_dynamic_oa_sysfs_entry()
2295 * xe_oa_add_config_ioctl - Adds one OA config
2307 struct xe_oa *oa = &xe->oa; in xe_oa_add_config_ioctl()
2314 if (!oa->xe) { in xe_oa_add_config_ioctl()
2315 drm_dbg(&xe->drm, "xe oa interface not available for this system\n"); in xe_oa_add_config_ioctl()
2316 return -ENODEV; in xe_oa_add_config_ioctl()
2320 drm_dbg(&oa->xe->drm, "Insufficient privileges to add xe OA config\n"); in xe_oa_add_config_ioctl()
2321 return -EACCES; in xe_oa_add_config_ioctl()
2325 if (XE_IOCTL_DBG(oa->xe, err)) in xe_oa_add_config_ioctl()
2326 return -EFAULT; in xe_oa_add_config_ioctl()
2328 if (XE_IOCTL_DBG(oa->xe, arg->extensions) || in xe_oa_add_config_ioctl()
2329 XE_IOCTL_DBG(oa->xe, !arg->regs_ptr) || in xe_oa_add_config_ioctl()
2330 XE_IOCTL_DBG(oa->xe, !arg->n_regs)) in xe_oa_add_config_ioctl()
2331 return -EINVAL; in xe_oa_add_config_ioctl()
2335 return -ENOMEM; in xe_oa_add_config_ioctl()
2337 oa_config->oa = oa; in xe_oa_add_config_ioctl()
2338 kref_init(&oa_config->ref); in xe_oa_add_config_ioctl()
2340 if (!uuid_is_valid(arg->uuid)) { in xe_oa_add_config_ioctl()
2341 drm_dbg(&oa->xe->drm, "Invalid uuid format for OA config\n"); in xe_oa_add_config_ioctl()
2342 err = -EINVAL; in xe_oa_add_config_ioctl()
2346 /* Last character in oa_config->uuid will be 0 because oa_config is kzalloc */ in xe_oa_add_config_ioctl()
2347 memcpy(oa_config->uuid, arg->uuid, sizeof(arg->uuid)); in xe_oa_add_config_ioctl()
2349 oa_config->regs_len = arg->n_regs; in xe_oa_add_config_ioctl()
2351 u64_to_user_ptr(arg->regs_ptr), in xe_oa_add_config_ioctl()
2352 arg->n_regs); in xe_oa_add_config_ioctl()
2354 drm_dbg(&oa->xe->drm, "Failed to create OA config for mux_regs\n"); in xe_oa_add_config_ioctl()
2358 oa_config->regs = regs; in xe_oa_add_config_ioctl()
2360 err = mutex_lock_interruptible(&oa->metrics_lock); in xe_oa_add_config_ioctl()
2365 idr_for_each_entry(&oa->metrics_idr, tmp, id) { in xe_oa_add_config_ioctl()
2366 if (!strcmp(tmp->uuid, oa_config->uuid)) { in xe_oa_add_config_ioctl()
2367 drm_dbg(&oa->xe->drm, "OA config already exists with this uuid\n"); in xe_oa_add_config_ioctl()
2368 err = -EADDRINUSE; in xe_oa_add_config_ioctl()
2375 drm_dbg(&oa->xe->drm, "Failed to create sysfs entry for OA config\n"); in xe_oa_add_config_ioctl()
2379 oa_config->id = idr_alloc(&oa->metrics_idr, oa_config, 1, 0, GFP_KERNEL); in xe_oa_add_config_ioctl()
2380 if (oa_config->id < 0) { in xe_oa_add_config_ioctl()
2381 drm_dbg(&oa->xe->drm, "Failed to create sysfs entry for OA config\n"); in xe_oa_add_config_ioctl()
2382 err = oa_config->id; in xe_oa_add_config_ioctl()
2386 mutex_unlock(&oa->metrics_lock); in xe_oa_add_config_ioctl()
2388 drm_dbg(&oa->xe->drm, "Added config %s id=%i\n", oa_config->uuid, oa_config->id); in xe_oa_add_config_ioctl()
2390 return oa_config->id; in xe_oa_add_config_ioctl()
2393 mutex_unlock(&oa->metrics_lock); in xe_oa_add_config_ioctl()
2396 drm_dbg(&oa->xe->drm, "Failed to add new OA config\n"); in xe_oa_add_config_ioctl()
2401 * xe_oa_remove_config_ioctl - Removes one OA config
2409 struct xe_oa *oa = &xe->oa; in xe_oa_remove_config_ioctl()
2414 if (!oa->xe) { in xe_oa_remove_config_ioctl()
2415 drm_dbg(&xe->drm, "xe oa interface not available for this system\n"); in xe_oa_remove_config_ioctl()
2416 return -ENODEV; in xe_oa_remove_config_ioctl()
2420 drm_dbg(&oa->xe->drm, "Insufficient privileges to remove xe OA config\n"); in xe_oa_remove_config_ioctl()
2421 return -EACCES; in xe_oa_remove_config_ioctl()
2425 if (XE_IOCTL_DBG(oa->xe, ret)) in xe_oa_remove_config_ioctl()
2428 ret = mutex_lock_interruptible(&oa->metrics_lock); in xe_oa_remove_config_ioctl()
2432 oa_config = idr_find(&oa->metrics_idr, arg); in xe_oa_remove_config_ioctl()
2434 drm_dbg(&oa->xe->drm, "Failed to remove unknown OA config\n"); in xe_oa_remove_config_ioctl()
2435 ret = -ENOENT; in xe_oa_remove_config_ioctl()
2439 WARN_ON(arg != oa_config->id); in xe_oa_remove_config_ioctl()
2441 sysfs_remove_group(oa->metrics_kobj, &oa_config->sysfs_metric); in xe_oa_remove_config_ioctl()
2442 idr_remove(&oa->metrics_idr, arg); in xe_oa_remove_config_ioctl()
2444 mutex_unlock(&oa->metrics_lock); in xe_oa_remove_config_ioctl()
2446 drm_dbg(&oa->xe->drm, "Removed config %s id=%i\n", oa_config->uuid, oa_config->id); in xe_oa_remove_config_ioctl()
2453 mutex_unlock(&oa->metrics_lock); in xe_oa_remove_config_ioctl()
2458 * xe_oa_register - Xe OA registration
2465 struct xe_oa *oa = &xe->oa; in xe_oa_register()
2467 if (!oa->xe) in xe_oa_register()
2470 oa->metrics_kobj = kobject_create_and_add("metrics", in xe_oa_register()
2471 &xe->drm.primary->kdev->kobj); in xe_oa_register()
2475 * xe_oa_unregister - Xe OA de-registration
2480 struct xe_oa *oa = &xe->oa; in xe_oa_unregister()
2482 if (!oa->metrics_kobj) in xe_oa_unregister()
2485 kobject_put(oa->metrics_kobj); in xe_oa_unregister()
2486 oa->metrics_kobj = NULL; in xe_oa_unregister()
2496 if (GRAPHICS_VERx100(gt_to_xe(hwe->gt)) >= 1270) { in __hwe_oam_unit()
2501 xe_gt_WARN_ON(hwe->gt, hwe->gt->info.type != XE_GT_TYPE_MEDIA); in __hwe_oam_unit()
2511 switch (hwe->class) { in __hwe_oa_unit()
2558 int i, num_units = gt->oa.num_oa_units; in __xe_oa_init_oa_units()
2561 struct xe_oa_unit *u = &gt->oa.oa_unit[i]; in __xe_oa_init_oa_units()
2563 if (gt->info.type != XE_GT_TYPE_MEDIA) { in __xe_oa_init_oa_units()
2564 u->regs = __oag_regs(); in __xe_oa_init_oa_units()
2565 u->type = DRM_XE_OA_UNIT_TYPE_OAG; in __xe_oa_init_oa_units()
2567 u->regs = __oam_regs(mtl_oa_base[i]); in __xe_oa_init_oa_units()
2568 u->type = DRM_XE_OA_UNIT_TYPE_OAM; in __xe_oa_init_oa_units()
2572 xe_mmio_write32(&gt->mmio, u->regs.oa_debug, in __xe_oa_init_oa_units()
2576 u->oa_unit_id = gt_to_xe(gt)->oa.oa_unit_ids++; in __xe_oa_init_oa_units()
2587 u = drmm_kcalloc(&gt_to_xe(gt)->drm, num_oa_units, sizeof(*u), GFP_KERNEL); in xe_oa_init_gt()
2589 return -ENOMEM; in xe_oa_init_gt()
2594 hwe->oa_unit = NULL; in xe_oa_init_gt()
2597 hwe->oa_unit = &u[index]; in xe_oa_init_gt()
2605 gt->oa.num_oa_units = num_oa_units; in xe_oa_init_gt()
2606 gt->oa.oa_unit = u; in xe_oa_init_gt()
2610 drmm_mutex_init(&gt_to_xe(gt)->drm, &gt->oa.gt_lock); in xe_oa_init_gt()
2620 for_each_gt(gt, oa->xe, i) { in xe_oa_init_oa_units()
2631 __set_bit(format, oa->format_mask); in oa_format_add()
2636 if (GRAPHICS_VER(oa->xe) >= 20) { in xe_oa_init_supported_formats()
2649 } else if (GRAPHICS_VERx100(oa->xe) >= 1270) { in xe_oa_init_supported_formats()
2657 } else if (GRAPHICS_VERx100(oa->xe) >= 1255) { in xe_oa_init_supported_formats()
2665 xe_assert(oa->xe, GRAPHICS_VER(oa->xe) >= 12); in xe_oa_init_supported_formats()
2674 * xe_oa_init - OA initialization during device probe
2681 struct xe_oa *oa = &xe->oa; in xe_oa_init()
2691 oa->xe = xe; in xe_oa_init()
2692 oa->oa_formats = oa_formats; in xe_oa_init()
2694 drmm_mutex_init(&oa->xe->drm, &oa->metrics_lock); in xe_oa_init()
2695 idr_init_base(&oa->metrics_idr, 1); in xe_oa_init()
2699 drm_err(&xe->drm, "OA initialization failed (%pe)\n", ERR_PTR(ret)); in xe_oa_init()
2706 oa->xe = NULL; in xe_oa_init()
2717 * xe_oa_fini - OA de-initialization during device remove
2722 struct xe_oa *oa = &xe->oa; in xe_oa_fini()
2724 if (!oa->xe) in xe_oa_fini()
2727 idr_for_each(&oa->metrics_idr, destroy_config, oa); in xe_oa_fini()
2728 idr_destroy(&oa->metrics_idr); in xe_oa_fini()
2730 oa->xe = NULL; in xe_oa_fini()