Lines Matching +full:ext +full:- +full:clk +full:- +full:freq +full:- +full:hz

1 // SPDX-License-Identifier: MIT
3 * Copyright © 2023-2024 Intel Corporation
119 return tail >= head ? tail - head : in xe_oa_circ_diff()
120 tail + stream->oa_buffer.circ_size - head; in xe_oa_circ_diff()
125 return ptr + n >= stream->oa_buffer.circ_size ? in xe_oa_circ_incr()
126 ptr + n - stream->oa_buffer.circ_size : ptr + n; in xe_oa_circ_incr()
134 kfree(oa_config->regs); in xe_oa_config_release()
144 kref_put(&oa_config->ref, xe_oa_config_release); in xe_oa_config_put()
149 return kref_get_unless_zero(&oa_config->ref) ? oa_config : NULL; in xe_oa_config_get()
157 oa_config = idr_find(&oa->metrics_idr, metrics_set); in xe_oa_get_oa_config()
167 xe_oa_config_put(oa_bo->oa_config); in free_oa_config_bo()
168 xe_bb_free(oa_bo->bb, NULL); in free_oa_config_bo()
174 return &stream->hwe->oa_unit->regs; in __oa_regs()
179 return xe_mmio_read32(stream->gt, __oa_regs(stream)->oa_tail_ptr) & in xe_oa_hw_tail_read()
184 ((__s)->oa_buffer.format->header == HDR_64_BIT)
216 u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo); in xe_oa_buffer_check_unlocked()
217 int report_size = stream->oa_buffer.format->size; in xe_oa_buffer_check_unlocked()
223 spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags); in xe_oa_buffer_check_unlocked()
226 hw_tail -= gtt_offset; in xe_oa_buffer_check_unlocked()
233 partial_report_size = xe_oa_circ_diff(stream, hw_tail, stream->oa_buffer.tail); in xe_oa_buffer_check_unlocked()
249 while (xe_oa_circ_diff(stream, tail, stream->oa_buffer.tail) >= report_size) { in xe_oa_buffer_check_unlocked()
250 void *report = stream->oa_buffer.vaddr + tail; in xe_oa_buffer_check_unlocked()
259 drm_dbg(&stream->oa->xe->drm, in xe_oa_buffer_check_unlocked()
261 stream->oa_buffer.head, tail, hw_tail); in xe_oa_buffer_check_unlocked()
263 stream->oa_buffer.tail = tail; in xe_oa_buffer_check_unlocked()
265 pollin = xe_oa_circ_diff(stream, stream->oa_buffer.tail, in xe_oa_buffer_check_unlocked()
266 stream->oa_buffer.head) >= report_size; in xe_oa_buffer_check_unlocked()
268 spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); in xe_oa_buffer_check_unlocked()
279 stream->pollin = true; in xe_oa_poll_check_timer_cb()
280 wake_up(&stream->poll_wq); in xe_oa_poll_check_timer_cb()
283 hrtimer_forward_now(hrtimer, ns_to_ktime(stream->poll_period_ns)); in xe_oa_poll_check_timer_cb()
291 int report_size = stream->oa_buffer.format->size; in xe_oa_append_report()
295 if ((count - *offset) < report_size) in xe_oa_append_report()
296 return -ENOSPC; in xe_oa_append_report()
300 oa_buf_end = stream->oa_buffer.vaddr + stream->oa_buffer.circ_size; in xe_oa_append_report()
301 report_size_partial = oa_buf_end - report; in xe_oa_append_report()
305 return -EFAULT; in xe_oa_append_report()
308 if (copy_to_user(buf, stream->oa_buffer.vaddr, in xe_oa_append_report()
309 report_size - report_size_partial)) in xe_oa_append_report()
310 return -EFAULT; in xe_oa_append_report()
312 return -EFAULT; in xe_oa_append_report()
323 int report_size = stream->oa_buffer.format->size; in xe_oa_append_reports()
324 u8 *oa_buf_base = stream->oa_buffer.vaddr; in xe_oa_append_reports()
325 u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo); in xe_oa_append_reports()
331 spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags); in xe_oa_append_reports()
332 head = stream->oa_buffer.head; in xe_oa_append_reports()
333 tail = stream->oa_buffer.tail; in xe_oa_append_reports()
334 spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); in xe_oa_append_reports()
336 xe_assert(stream->oa->xe, in xe_oa_append_reports()
337 head < stream->oa_buffer.circ_size && tail < stream->oa_buffer.circ_size); in xe_oa_append_reports()
347 if (!(stream->oa_buffer.circ_size % report_size)) { in xe_oa_append_reports()
352 u8 *oa_buf_end = stream->oa_buffer.vaddr + stream->oa_buffer.circ_size; in xe_oa_append_reports()
353 u32 part = oa_buf_end - report; in xe_oa_append_reports()
360 memset(oa_buf_base, 0, report_size - part); in xe_oa_append_reports()
366 struct xe_reg oaheadptr = __oa_regs(stream)->oa_head_ptr; in xe_oa_append_reports()
368 spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags); in xe_oa_append_reports()
369 xe_mmio_write32(stream->gt, oaheadptr, in xe_oa_append_reports()
371 stream->oa_buffer.head = head; in xe_oa_append_reports()
372 spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); in xe_oa_append_reports()
380 u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo); in xe_oa_init_oa_buffer()
384 spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags); in xe_oa_init_oa_buffer()
386 xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_status, 0); in xe_oa_init_oa_buffer()
387 xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_head_ptr, in xe_oa_init_oa_buffer()
389 stream->oa_buffer.head = 0; in xe_oa_init_oa_buffer()
394 xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_buffer, oa_buf); in xe_oa_init_oa_buffer()
395 xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_tail_ptr, in xe_oa_init_oa_buffer()
399 stream->oa_buffer.tail = 0; in xe_oa_init_oa_buffer()
401 spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags); in xe_oa_init_oa_buffer()
404 memset(stream->oa_buffer.vaddr, 0, stream->oa_buffer.bo->size); in xe_oa_init_oa_buffer()
409 return ((format->counter_select << (ffs(counter_sel_mask) - 1)) & counter_sel_mask) | in __format_to_oactrl()
410 REG_FIELD_PREP(OA_OACONTROL_REPORT_BC_MASK, format->bc_report) | in __format_to_oactrl()
411 REG_FIELD_PREP(OA_OACONTROL_COUNTER_SIZE_MASK, format->counter_size); in __format_to_oactrl()
418 if (stream->hwe->class != XE_ENGINE_CLASS_COMPUTE) in __oa_ccs_select()
421 val = REG_FIELD_PREP(OAG_OACONTROL_OA_CCS_SELECT_MASK, stream->hwe->instance); in __oa_ccs_select()
422 xe_assert(stream->oa->xe, in __oa_ccs_select()
423 REG_FIELD_GET(OAG_OACONTROL_OA_CCS_SELECT_MASK, val) == stream->hwe->instance); in __oa_ccs_select()
429 const struct xe_oa_format *format = stream->oa_buffer.format; in xe_oa_enable()
434 * BSpec: 46822: Bit 0. Even if stream->sample is 0, for OAR to function, the OA in xe_oa_enable()
440 val = __format_to_oactrl(format, regs->oa_ctrl_counter_select_mask) | in xe_oa_enable()
443 if (GRAPHICS_VER(stream->oa->xe) >= 20 && in xe_oa_enable()
444 stream->hwe->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG) in xe_oa_enable()
447 xe_mmio_write32(stream->gt, regs->oa_ctrl, val); in xe_oa_enable()
452 xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_ctrl, 0); in xe_oa_disable()
453 if (xe_mmio_wait32(stream->gt, __oa_regs(stream)->oa_ctrl, in xe_oa_disable()
455 drm_err(&stream->oa->xe->drm, in xe_oa_disable()
458 if (GRAPHICS_VERx100(stream->oa->xe) <= 1270 && GRAPHICS_VERx100(stream->oa->xe) != 1260) { in xe_oa_disable()
460 xe_mmio_write32(stream->gt, OA_TLB_INV_CR, 1); in xe_oa_disable()
461 if (xe_mmio_wait32(stream->gt, OA_TLB_INV_CR, 1, 0, 50000, NULL, false)) in xe_oa_disable()
462 drm_err(&stream->oa->xe->drm, in xe_oa_disable()
470 if (!stream->periodic) in xe_oa_wait_unlocked()
471 return -EINVAL; in xe_oa_wait_unlocked()
473 return wait_event_interruptible(stream->poll_wq, in xe_oa_wait_unlocked()
483 /* Only clear our bits to avoid side-effects */ in __xe_oa_read()
484 stream->oa_status = xe_mmio_rmw32(stream->gt, __oa_regs(stream)->oa_status, in __xe_oa_read()
487 * Signal to userspace that there is non-zero OA status to read via in __xe_oa_read()
490 if (stream->oa_status & OASTATUS_RELEVANT_BITS) in __xe_oa_read()
491 return -EIO; in __xe_oa_read()
499 struct xe_oa_stream *stream = file->private_data; in xe_oa_read()
504 if (!stream->enabled || !stream->sample) in xe_oa_read()
505 return -EINVAL; in xe_oa_read()
507 if (!(file->f_flags & O_NONBLOCK)) { in xe_oa_read()
513 mutex_lock(&stream->stream_lock); in xe_oa_read()
515 mutex_unlock(&stream->stream_lock); in xe_oa_read()
518 mutex_lock(&stream->stream_lock); in xe_oa_read()
520 mutex_unlock(&stream->stream_lock); in xe_oa_read()
525 * before unblocking. The exception to this is if __xe_oa_read returns -ENOSPC, in xe_oa_read()
529 * Also in case of -EIO, we have already waited for data before returning in xe_oa_read()
530 * -EIO, so need to wait again in xe_oa_read()
532 if (ret != -ENOSPC && ret != -EIO) in xe_oa_read()
533 stream->pollin = false; in xe_oa_read()
535 /* Possible values for ret are 0, -EFAULT, -ENOSPC, -EIO, -EINVAL, ... */ in xe_oa_read()
536 return offset ?: (ret ?: -EAGAIN); in xe_oa_read()
544 poll_wait(file, &stream->poll_wq, wait); in xe_oa_poll_locked()
552 if (stream->pollin) in xe_oa_poll_locked()
560 struct xe_oa_stream *stream = file->private_data; in xe_oa_poll()
563 mutex_lock(&stream->stream_lock); in xe_oa_poll()
565 mutex_unlock(&stream->stream_lock); in xe_oa_poll()
577 /* Kernel configuration is issued on stream->k_exec_q, not stream->exec_q */ in xe_oa_submit_bb()
578 job = xe_bb_create_job(stream->k_exec_q, bb); in xe_oa_submit_bb()
585 fence = dma_fence_get(&job->drm.s_fence->finished); in xe_oa_submit_bb()
588 timeout = dma_fence_wait_timeout(fence, false, HZ); in xe_oa_submit_bb()
593 err = -ETIME; in xe_oa_submit_bb()
606 u32 n_lri = min_t(u32, n_regs - i, in write_cs_mi_lri()
609 bb->cs[bb->len++] = MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(n_lri); in write_cs_mi_lri()
611 bb->cs[bb->len++] = reg_data[i].addr.addr; in write_cs_mi_lri()
612 bb->cs[bb->len++] = reg_data[i].value; in write_cs_mi_lri()
630 xe_bo_unpin_map_no_vm(stream->oa_buffer.bo); in xe_oa_free_oa_buffer()
637 xe_oa_config_put(stream->oa_config); in xe_oa_free_configs()
638 llist_for_each_entry_safe(oa_bo, tmp, stream->oa_config_bos.first, node) in xe_oa_free_configs()
645 u32 offset = xe_bo_ggtt_addr(lrc->bo); in xe_oa_store_flex()
648 bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_GGTT | MI_SDI_NUM_DW(1); in xe_oa_store_flex()
649 bb->cs[bb->len++] = offset + flex->offset * sizeof(u32); in xe_oa_store_flex()
650 bb->cs[bb->len++] = 0; in xe_oa_store_flex()
651 bb->cs[bb->len++] = flex->value; in xe_oa_store_flex()
653 } while (flex++, --count); in xe_oa_store_flex()
662 bb = xe_bb_new(stream->gt, 4 * count, false); in xe_oa_modify_ctx_image()
681 bb = xe_bb_new(stream->gt, 3, false); in xe_oa_load_with_lri()
697 const struct xe_oa_format *format = stream->oa_buffer.format; in xe_oa_configure_oar_context()
698 struct xe_lrc *lrc = stream->exec_q->lrc[0]; in xe_oa_configure_oar_context()
705 OACTXCONTROL(stream->hwe->mmio_base), in xe_oa_configure_oar_context()
706 stream->oa->ctx_oactxctrl_offset[stream->hwe->class] + 1, in xe_oa_configure_oar_context()
710 RING_CONTEXT_CONTROL(stream->hwe->mmio_base), in xe_oa_configure_oar_context()
719 err = xe_oa_modify_ctx_image(stream, stream->exec_q->lrc[0], in xe_oa_configure_oar_context()
730 const struct xe_oa_format *format = stream->oa_buffer.format; in xe_oa_configure_oac_context()
731 struct xe_lrc *lrc = stream->exec_q->lrc[0]; in xe_oa_configure_oac_context()
737 OACTXCONTROL(stream->hwe->mmio_base), in xe_oa_configure_oac_context()
738 stream->oa->ctx_oactxctrl_offset[stream->hwe->class] + 1, in xe_oa_configure_oac_context()
742 RING_CONTEXT_CONTROL(stream->hwe->mmio_base), in xe_oa_configure_oac_context()
752 xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_ctrl, __oa_ccs_select(stream)); in xe_oa_configure_oac_context()
755 err = xe_oa_modify_ctx_image(stream, stream->exec_q->lrc[0], in xe_oa_configure_oac_context()
766 switch (stream->hwe->class) { in xe_oa_configure_oa_context()
782 enable && stream && stream->sample ? in oag_configure_mmio_trigger()
794 if (stream->oa->xe->info.platform == XE_DG2) { in xe_oa_disable_metric_set()
795 xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN, in xe_oa_disable_metric_set()
797 xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN2, in xe_oa_disable_metric_set()
801 xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_debug, in xe_oa_disable_metric_set()
805 if (stream->exec_q) in xe_oa_disable_metric_set()
809 xe_mmio_rmw32(stream->gt, RPM_CONFIG1, GT_NOA_ENABLE, 0); in xe_oa_disable_metric_set()
812 (HAS_OA_BPC_REPORTING(stream->oa->xe) ? SQCNT1_OABPC : 0); in xe_oa_disable_metric_set()
815 xe_mmio_rmw32(stream->gt, XELPMP_SQCNT1, sqcnt1, 0); in xe_oa_disable_metric_set()
820 struct xe_oa_unit *u = stream->hwe->oa_unit; in xe_oa_stream_destroy()
821 struct xe_gt *gt = stream->hwe->gt; in xe_oa_stream_destroy()
823 if (WARN_ON(stream != u->exclusive_stream)) in xe_oa_stream_destroy()
826 WRITE_ONCE(u->exclusive_stream, NULL); in xe_oa_stream_destroy()
828 mutex_destroy(&stream->stream_lock); in xe_oa_stream_destroy()
831 xe_exec_queue_put(stream->k_exec_q); in xe_oa_stream_destroy()
836 xe_pm_runtime_put(stream->oa->xe); in xe_oa_stream_destroy()
839 if (stream->override_gucrc) in xe_oa_stream_destroy()
840 xe_gt_WARN_ON(gt, xe_guc_pc_unset_gucrc_mode(&gt->uc.guc.pc)); in xe_oa_stream_destroy()
852 bo = xe_bo_create_pin_map(stream->oa->xe, stream->gt->tile, NULL, in xe_oa_alloc_oa_buffer()
858 stream->oa_buffer.bo = bo; in xe_oa_alloc_oa_buffer()
860 xe_assert(stream->oa->xe, bo->vmap.is_iomem == 0); in xe_oa_alloc_oa_buffer()
861 stream->oa_buffer.vaddr = bo->vmap.vaddr; in xe_oa_alloc_oa_buffer()
874 return ERR_PTR(-ENOMEM); in __xe_oa_alloc_config_buffer()
876 config_length = num_lri_dwords(oa_config->regs_len); in __xe_oa_alloc_config_buffer()
879 bb = xe_bb_new(stream->gt, config_length, false); in __xe_oa_alloc_config_buffer()
883 write_cs_mi_lri(bb, oa_config->regs, oa_config->regs_len); in __xe_oa_alloc_config_buffer()
885 oa_bo->bb = bb; in __xe_oa_alloc_config_buffer()
886 oa_bo->oa_config = xe_oa_config_get(oa_config); in __xe_oa_alloc_config_buffer()
887 llist_add(&oa_bo->node, &stream->oa_config_bos); in __xe_oa_alloc_config_buffer()
901 llist_for_each_entry(oa_bo, stream->oa_config_bos.first, node) { in xe_oa_alloc_config_buffer()
902 if (oa_bo->oa_config == oa_config && in xe_oa_alloc_config_buffer()
903 memcmp(oa_bo->oa_config->uuid, oa_config->uuid, in xe_oa_alloc_config_buffer()
904 sizeof(oa_config->uuid)) == 0) in xe_oa_alloc_config_buffer()
925 err = xe_oa_submit_bb(stream, oa_bo->bb); in xe_oa_emit_oa_config()
937 stream->sample ? in oag_report_ctx_switches()
951 if (stream->oa->xe->info.platform == XE_DG2) { in xe_oa_enable_metric_set()
952 xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN, in xe_oa_enable_metric_set()
954 xe_gt_mcr_multicast_write(stream->gt, ROW_CHICKEN2, in xe_oa_enable_metric_set()
958 /* Disable clk ratio reports */ in xe_oa_enable_metric_set()
962 if (GRAPHICS_VER(stream->oa->xe) >= 20) in xe_oa_enable_metric_set()
969 xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_debug, in xe_oa_enable_metric_set()
974 xe_mmio_write32(stream->gt, __oa_regs(stream)->oa_ctx_ctrl, stream->periodic ? in xe_oa_enable_metric_set()
978 stream->period_exponent)) : 0); in xe_oa_enable_metric_set()
986 (HAS_OA_BPC_REPORTING(stream->oa->xe) ? SQCNT1_OABPC : 0); in xe_oa_enable_metric_set()
988 xe_mmio_rmw32(stream->gt, XELPMP_SQCNT1, 0, sqcnt1); in xe_oa_enable_metric_set()
991 if (stream->exec_q) { in xe_oa_enable_metric_set()
997 return xe_oa_emit_oa_config(stream, stream->oa_config); in xe_oa_enable_metric_set()
1002 stream->pollin = false; in xe_oa_stream_enable()
1006 if (stream->sample) in xe_oa_stream_enable()
1007 hrtimer_start(&stream->poll_check_timer, in xe_oa_stream_enable()
1008 ns_to_ktime(stream->poll_period_ns), in xe_oa_stream_enable()
1016 if (stream->sample) in xe_oa_stream_disable()
1017 hrtimer_cancel(&stream->poll_check_timer); in xe_oa_stream_disable()
1022 struct xe_exec_queue *q = stream->exec_q; in xe_oa_enable_preempt_timeslice()
1026 ret1 = q->ops->set_timeslice(q, stream->hwe->eclass->sched_props.timeslice_us); in xe_oa_enable_preempt_timeslice()
1027 ret2 = q->ops->set_preempt_timeout(q, stream->hwe->eclass->sched_props.preempt_timeout_us); in xe_oa_enable_preempt_timeslice()
1032 drm_dbg(&stream->oa->xe->drm, "%s failed ret1 %d ret2 %d\n", __func__, ret1, ret2); in xe_oa_enable_preempt_timeslice()
1038 struct xe_exec_queue *q = stream->exec_q; in xe_oa_disable_preempt_timeslice()
1042 ret = q->ops->set_timeslice(q, 0); in xe_oa_disable_preempt_timeslice()
1046 ret = q->ops->set_preempt_timeout(q, 0); in xe_oa_disable_preempt_timeslice()
1053 drm_dbg(&stream->oa->xe->drm, "%s failed %d\n", __func__, ret); in xe_oa_disable_preempt_timeslice()
1059 if (stream->enabled) in xe_oa_enable_locked()
1062 if (stream->no_preempt) { in xe_oa_enable_locked()
1071 stream->enabled = true; in xe_oa_enable_locked()
1079 if (!stream->enabled) in xe_oa_disable_locked()
1084 if (stream->no_preempt) in xe_oa_disable_locked()
1087 stream->enabled = false; in xe_oa_disable_locked()
1093 struct drm_xe_ext_set_property ext; in xe_oa_config_locked() local
1094 long ret = stream->oa_config->id; in xe_oa_config_locked()
1098 err = __copy_from_user(&ext, u64_to_user_ptr(arg), sizeof(ext)); in xe_oa_config_locked()
1099 if (XE_IOCTL_DBG(stream->oa->xe, err)) in xe_oa_config_locked()
1100 return -EFAULT; in xe_oa_config_locked()
1102 if (XE_IOCTL_DBG(stream->oa->xe, ext.pad) || in xe_oa_config_locked()
1103 XE_IOCTL_DBG(stream->oa->xe, ext.base.name != DRM_XE_OA_EXTENSION_SET_PROPERTY) || in xe_oa_config_locked()
1104 XE_IOCTL_DBG(stream->oa->xe, ext.base.next_extension) || in xe_oa_config_locked()
1105 XE_IOCTL_DBG(stream->oa->xe, ext.property != DRM_XE_OA_PROPERTY_OA_METRIC_SET)) in xe_oa_config_locked()
1106 return -EINVAL; in xe_oa_config_locked()
1108 config = xe_oa_get_oa_config(stream->oa, ext.value); in xe_oa_config_locked()
1110 return -ENODEV; in xe_oa_config_locked()
1112 if (config != stream->oa_config) { in xe_oa_config_locked()
1115 config = xchg(&stream->oa_config, config); in xe_oa_config_locked()
1131 if (stream->oa_status & OASTATUS_REPORT_LOST) in xe_oa_status_locked()
1133 if (stream->oa_status & OASTATUS_BUFFER_OVERFLOW) in xe_oa_status_locked()
1135 if (stream->oa_status & OASTATUS_COUNTER_OVERFLOW) in xe_oa_status_locked()
1137 if (stream->oa_status & OASTATUS_MMIO_TRG_Q_FULL) in xe_oa_status_locked()
1141 return -EFAULT; in xe_oa_status_locked()
1152 return -EFAULT; in xe_oa_info_locked()
1174 return -EINVAL; in xe_oa_ioctl_locked()
1181 struct xe_oa_stream *stream = file->private_data; in xe_oa_ioctl()
1184 mutex_lock(&stream->stream_lock); in xe_oa_ioctl()
1186 mutex_unlock(&stream->stream_lock); in xe_oa_ioctl()
1193 if (stream->enabled) in xe_oa_destroy_locked()
1198 if (stream->exec_q) in xe_oa_destroy_locked()
1199 xe_exec_queue_put(stream->exec_q); in xe_oa_destroy_locked()
1206 struct xe_oa_stream *stream = file->private_data; in xe_oa_release()
1207 struct xe_gt *gt = stream->gt; in xe_oa_release()
1210 mutex_lock(&gt->oa.gt_lock); in xe_oa_release()
1212 mutex_unlock(&gt->oa.gt_lock); in xe_oa_release()
1216 drm_dev_put(&gt_to_xe(gt)->drm); in xe_oa_release()
1223 struct xe_oa_stream *stream = file->private_data; in xe_oa_mmap()
1224 struct xe_bo *bo = stream->oa_buffer.bo; in xe_oa_mmap()
1225 unsigned long start = vma->vm_start; in xe_oa_mmap()
1229 drm_dbg(&stream->oa->xe->drm, "Insufficient privilege to map OA buffer\n"); in xe_oa_mmap()
1230 return -EACCES; in xe_oa_mmap()
1234 if (vma->vm_end - vma->vm_start != XE_OA_BUFFER_SIZE) { in xe_oa_mmap()
1235 drm_dbg(&stream->oa->xe->drm, "Wrong mmap size, must be OA buffer size\n"); in xe_oa_mmap()
1236 return -EINVAL; in xe_oa_mmap()
1243 if (vma->vm_flags & (VM_WRITE | VM_EXEC | VM_SHARED | VM_MAYSHARE)) { in xe_oa_mmap()
1244 drm_dbg(&stream->oa->xe->drm, "mmap must be read only\n"); in xe_oa_mmap()
1245 return -EINVAL; in xe_oa_mmap()
1250 xe_assert(stream->oa->xe, bo->ttm.ttm->num_pages == vma_pages(vma)); in xe_oa_mmap()
1251 for (i = 0; i < bo->ttm.ttm->num_pages; i++) { in xe_oa_mmap()
1252 ret = remap_pfn_range(vma, start, page_to_pfn(bo->ttm.ttm->pages[i]), in xe_oa_mmap()
1253 PAGE_SIZE, vma->vm_page_prot); in xe_oa_mmap()
1274 return hwe->class == XE_ENGINE_CLASS_RENDER || in engine_supports_mi_query()
1275 hwe->class == XE_ENGINE_CLASS_COMPUTE; in engine_supports_mi_query()
1301 struct xe_lrc *lrc = stream->exec_q->lrc[0]; in xe_oa_context_image_offset()
1302 u32 len = (xe_gt_lrc_size(stream->gt, stream->hwe->class) + in xe_oa_context_image_offset()
1303 lrc->ring.size) / sizeof(u32); in xe_oa_context_image_offset()
1305 u32 *state = (u32 *)lrc->bo->vmap.vaddr; in xe_oa_context_image_offset()
1307 if (drm_WARN_ON(&stream->oa->xe->drm, !state)) in xe_oa_context_image_offset()
1313 * We expect reg-value pairs in MI_LRI command, so in xe_oa_context_image_offset()
1316 drm_WARN_ON(&stream->oa->xe->drm, in xe_oa_context_image_offset()
1331 struct xe_reg reg = OACTXCONTROL(stream->hwe->mmio_base); in xe_oa_set_ctx_ctrl_offset()
1332 u32 offset = stream->oa->ctx_oactxctrl_offset[stream->hwe->class]; in xe_oa_set_ctx_ctrl_offset()
1339 stream->oa->ctx_oactxctrl_offset[stream->hwe->class] = offset; in xe_oa_set_ctx_ctrl_offset()
1341 drm_dbg(&stream->oa->xe->drm, "%s oa ctx control at 0x%08x dword offset\n", in xe_oa_set_ctx_ctrl_offset()
1342 stream->hwe->name, offset); in xe_oa_set_ctx_ctrl_offset()
1344 return offset && offset != U32_MAX ? 0 : -ENODEV; in xe_oa_set_ctx_ctrl_offset()
1350 struct xe_oa_unit *u = param->hwe->oa_unit; in xe_oa_stream_init()
1351 struct xe_gt *gt = param->hwe->gt; in xe_oa_stream_init()
1354 stream->exec_q = param->exec_q; in xe_oa_stream_init()
1355 stream->poll_period_ns = DEFAULT_POLL_PERIOD_NS; in xe_oa_stream_init()
1356 stream->hwe = param->hwe; in xe_oa_stream_init()
1357 stream->gt = stream->hwe->gt; in xe_oa_stream_init()
1358 stream->oa_buffer.format = &stream->oa->oa_formats[param->oa_format]; in xe_oa_stream_init()
1360 stream->sample = param->sample; in xe_oa_stream_init()
1361 stream->periodic = param->period_exponent > 0; in xe_oa_stream_init()
1362 stream->period_exponent = param->period_exponent; in xe_oa_stream_init()
1363 stream->no_preempt = param->no_preempt; in xe_oa_stream_init()
1367 * of buffer, making the OA buffer effectively a non-power-of-2 size circular in xe_oa_stream_init()
1370 if (GRAPHICS_VER(stream->oa->xe) >= 20 && in xe_oa_stream_init()
1371 stream->hwe->oa_unit->type == DRM_XE_OA_UNIT_TYPE_OAG && stream->sample) in xe_oa_stream_init()
1372 stream->oa_buffer.circ_size = in xe_oa_stream_init()
1373 XE_OA_BUFFER_SIZE - XE_OA_BUFFER_SIZE % stream->oa_buffer.format->size; in xe_oa_stream_init()
1375 stream->oa_buffer.circ_size = XE_OA_BUFFER_SIZE; in xe_oa_stream_init()
1377 if (stream->exec_q && engine_supports_mi_query(stream->hwe)) { in xe_oa_stream_init()
1381 drm_err(&stream->oa->xe->drm, in xe_oa_stream_init()
1383 stream->hwe->name); in xe_oa_stream_init()
1388 stream->oa_config = xe_oa_get_oa_config(stream->oa, param->metric_set); in xe_oa_stream_init()
1389 if (!stream->oa_config) { in xe_oa_stream_init()
1390 drm_dbg(&stream->oa->xe->drm, "Invalid OA config id=%i\n", param->metric_set); in xe_oa_stream_init()
1391 ret = -EINVAL; in xe_oa_stream_init()
1401 if (stream->oa->xe->info.platform == XE_PVC) { in xe_oa_stream_init()
1402 ret = xe_guc_pc_override_gucrc_mode(&gt->uc.guc.pc, in xe_oa_stream_init()
1407 stream->override_gucrc = true; in xe_oa_stream_init()
1411 xe_pm_runtime_get(stream->oa->xe); in xe_oa_stream_init()
1418 stream->k_exec_q = xe_exec_queue_create(stream->oa->xe, NULL, in xe_oa_stream_init()
1419 BIT(stream->hwe->logical_instance), 1, in xe_oa_stream_init()
1420 stream->hwe, EXEC_QUEUE_FLAG_KERNEL, 0); in xe_oa_stream_init()
1421 if (IS_ERR(stream->k_exec_q)) { in xe_oa_stream_init()
1422 ret = PTR_ERR(stream->k_exec_q); in xe_oa_stream_init()
1423 drm_err(&stream->oa->xe->drm, "gt%d, hwe %s, xe_exec_queue_create failed=%d", in xe_oa_stream_init()
1424 stream->gt->info.id, stream->hwe->name, ret); in xe_oa_stream_init()
1430 drm_dbg(&stream->oa->xe->drm, "Unable to enable metric set\n"); in xe_oa_stream_init()
1434 drm_dbg(&stream->oa->xe->drm, "opening stream oa config uuid=%s\n", in xe_oa_stream_init()
1435 stream->oa_config->uuid); in xe_oa_stream_init()
1437 WRITE_ONCE(u->exclusive_stream, stream); in xe_oa_stream_init()
1439 hrtimer_init(&stream->poll_check_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); in xe_oa_stream_init()
1440 stream->poll_check_timer.function = xe_oa_poll_check_timer_cb; in xe_oa_stream_init()
1441 init_waitqueue_head(&stream->poll_wq); in xe_oa_stream_init()
1443 spin_lock_init(&stream->oa_buffer.ptr_lock); in xe_oa_stream_init()
1444 mutex_init(&stream->stream_lock); in xe_oa_stream_init()
1450 xe_exec_queue_put(stream->k_exec_q); in xe_oa_stream_init()
1455 xe_pm_runtime_put(stream->oa->xe); in xe_oa_stream_init()
1456 if (stream->override_gucrc) in xe_oa_stream_init()
1457 xe_gt_WARN_ON(gt, xe_guc_pc_unset_gucrc_mode(&gt->uc.guc.pc)); in xe_oa_stream_init()
1472 if (param->hwe->oa_unit->exclusive_stream) { in xe_oa_stream_open_ioctl_locked()
1473 drm_dbg(&oa->xe->drm, "OA unit already in use\n"); in xe_oa_stream_open_ioctl_locked()
1474 ret = -EBUSY; in xe_oa_stream_open_ioctl_locked()
1480 ret = -ENOMEM; in xe_oa_stream_open_ioctl_locked()
1484 stream->oa = oa; in xe_oa_stream_open_ioctl_locked()
1489 if (!param->disabled) { in xe_oa_stream_open_ioctl_locked()
1502 drm_dev_get(&stream->oa->xe->drm); in xe_oa_stream_open_ioctl_locked()
1506 if (!param->disabled) in xe_oa_stream_open_ioctl_locked()
1517 * xe_oa_timestamp_frequency - Return OA timestamp frequency
1533 switch (gt_to_xe(gt)->info.platform) { in xe_oa_timestamp_frequency()
1542 return gt->info.reference_clock << (3 - shift); in xe_oa_timestamp_frequency()
1545 return gt->info.reference_clock; in xe_oa_timestamp_frequency()
1554 return div_u64(nom + den - 1, den); in oa_exponent_to_ns()
1559 switch (hwe->oa_unit->type) { in engine_supports_oa_format()
1578 for_each_set_bit(idx, oa->format_mask, __XE_OA_FORMAT_MAX) { in decode_oa_format()
1579 const struct xe_oa_format *f = &oa->oa_formats[idx]; in decode_oa_format()
1581 if (counter_size == f->counter_size && bc_report == f->bc_report && in decode_oa_format()
1582 type == f->type && counter_sel == f->counter_select) { in decode_oa_format()
1588 return -EINVAL; in decode_oa_format()
1592 * xe_oa_unit_id - Return OA unit ID for a hardware engine
1599 return hwe->oa_unit && hwe->oa_unit->num_engines ? in xe_oa_unit_id()
1600 hwe->oa_unit->oa_unit_id : U16_MAX; in xe_oa_unit_id()
1608 if (param->exec_q) { in xe_oa_assign_hwe()
1610 param->hwe = xe_gt_hw_engine(param->exec_q->gt, param->exec_q->class, in xe_oa_assign_hwe()
1611 param->engine_instance, true); in xe_oa_assign_hwe()
1617 for_each_gt(gt, oa->xe, i) { in xe_oa_assign_hwe()
1619 if (xe_oa_unit_id(hwe) == param->oa_unit_id) { in xe_oa_assign_hwe()
1620 param->hwe = hwe; in xe_oa_assign_hwe()
1627 if (!param->hwe || xe_oa_unit_id(param->hwe) != param->oa_unit_id) { in xe_oa_assign_hwe()
1628 drm_dbg(&oa->xe->drm, "Unable to find hwe (%d, %d) for OA unit ID %d\n", in xe_oa_assign_hwe()
1629 param->exec_q ? param->exec_q->class : -1, in xe_oa_assign_hwe()
1630 param->engine_instance, param->oa_unit_id); in xe_oa_assign_hwe()
1631 ret = -EINVAL; in xe_oa_assign_hwe()
1640 if (value >= oa->oa_unit_ids) { in xe_oa_set_prop_oa_unit_id()
1641 drm_dbg(&oa->xe->drm, "OA unit ID out of range %lld\n", value); in xe_oa_set_prop_oa_unit_id()
1642 return -EINVAL; in xe_oa_set_prop_oa_unit_id()
1644 param->oa_unit_id = value; in xe_oa_set_prop_oa_unit_id()
1651 param->sample = value; in xe_oa_set_prop_sample_oa()
1658 param->metric_set = value; in xe_oa_set_prop_metric_set()
1665 int ret = decode_oa_format(oa, value, &param->oa_format); in xe_oa_set_prop_oa_format()
1668 drm_dbg(&oa->xe->drm, "Unsupported OA report format %#llx\n", value); in xe_oa_set_prop_oa_format()
1680 drm_dbg(&oa->xe->drm, "OA timer exponent too high (> %u)\n", OA_EXPONENT_MAX); in xe_oa_set_prop_oa_exponent()
1681 return -EINVAL; in xe_oa_set_prop_oa_exponent()
1683 param->period_exponent = value; in xe_oa_set_prop_oa_exponent()
1690 param->disabled = value; in xe_oa_set_prop_disabled()
1697 param->exec_queue_id = value; in xe_oa_set_prop_exec_queue_id()
1704 param->engine_instance = value; in xe_oa_set_prop_engine_instance()
1711 param->no_preempt = value; in xe_oa_set_no_preempt()
1733 struct drm_xe_ext_set_property ext; in xe_oa_user_ext_set_property() local
1737 err = __copy_from_user(&ext, address, sizeof(ext)); in xe_oa_user_ext_set_property()
1738 if (XE_IOCTL_DBG(oa->xe, err)) in xe_oa_user_ext_set_property()
1739 return -EFAULT; in xe_oa_user_ext_set_property()
1741 if (XE_IOCTL_DBG(oa->xe, ext.property >= ARRAY_SIZE(xe_oa_set_property_funcs)) || in xe_oa_user_ext_set_property()
1742 XE_IOCTL_DBG(oa->xe, ext.pad)) in xe_oa_user_ext_set_property()
1743 return -EINVAL; in xe_oa_user_ext_set_property()
1745 idx = array_index_nospec(ext.property, ARRAY_SIZE(xe_oa_set_property_funcs)); in xe_oa_user_ext_set_property()
1746 return xe_oa_set_property_funcs[idx](oa, ext.value, param); in xe_oa_user_ext_set_property()
1760 struct drm_xe_user_extension ext; in xe_oa_user_extensions() local
1764 if (XE_IOCTL_DBG(oa->xe, ext_number >= MAX_USER_EXTENSIONS)) in xe_oa_user_extensions()
1765 return -E2BIG; in xe_oa_user_extensions()
1767 err = __copy_from_user(&ext, address, sizeof(ext)); in xe_oa_user_extensions()
1768 if (XE_IOCTL_DBG(oa->xe, err)) in xe_oa_user_extensions()
1769 return -EFAULT; in xe_oa_user_extensions()
1771 if (XE_IOCTL_DBG(oa->xe, ext.pad) || in xe_oa_user_extensions()
1772 XE_IOCTL_DBG(oa->xe, ext.name >= ARRAY_SIZE(xe_oa_user_extension_funcs))) in xe_oa_user_extensions()
1773 return -EINVAL; in xe_oa_user_extensions()
1775 idx = array_index_nospec(ext.name, ARRAY_SIZE(xe_oa_user_extension_funcs)); in xe_oa_user_extensions()
1777 if (XE_IOCTL_DBG(oa->xe, err)) in xe_oa_user_extensions()
1780 if (ext.next_extension) in xe_oa_user_extensions()
1781 return xe_oa_user_extensions(oa, ext.next_extension, ++ext_number, param); in xe_oa_user_extensions()
1787 * xe_oa_stream_open_ioctl - Opens an OA stream
1799 struct xe_oa *oa = &xe->oa; in xe_oa_stream_open_ioctl()
1806 if (!oa->xe) { in xe_oa_stream_open_ioctl()
1807 drm_dbg(&xe->drm, "xe oa interface not available for this system\n"); in xe_oa_stream_open_ioctl()
1808 return -ENODEV; in xe_oa_stream_open_ioctl()
1817 if (XE_IOCTL_DBG(oa->xe, !param.exec_q)) in xe_oa_stream_open_ioctl()
1818 return -ENOENT; in xe_oa_stream_open_ioctl()
1820 if (param.exec_q->width > 1) in xe_oa_stream_open_ioctl()
1821 drm_dbg(&oa->xe->drm, "exec_q->width > 1, programming only exec_q->lrc[0]\n"); in xe_oa_stream_open_ioctl()
1833 drm_dbg(&oa->xe->drm, "Preemption disable without exec_q!\n"); in xe_oa_stream_open_ioctl()
1834 ret = -EINVAL; in xe_oa_stream_open_ioctl()
1841 drm_dbg(&oa->xe->drm, "Insufficient privileges to open xe OA stream\n"); in xe_oa_stream_open_ioctl()
1842 ret = -EACCES; in xe_oa_stream_open_ioctl()
1847 drm_dbg(&oa->xe->drm, "Only OA report sampling supported\n"); in xe_oa_stream_open_ioctl()
1848 ret = -EINVAL; in xe_oa_stream_open_ioctl()
1856 f = &oa->oa_formats[param.oa_format]; in xe_oa_stream_open_ioctl()
1857 if (!param.oa_format || !f->size || in xe_oa_stream_open_ioctl()
1858 !engine_supports_oa_format(param.hwe, f->type)) { in xe_oa_stream_open_ioctl()
1859 drm_dbg(&oa->xe->drm, "Invalid OA format %d type %d size %d for class %d\n", in xe_oa_stream_open_ioctl()
1860 param.oa_format, f->type, f->size, param.hwe->class); in xe_oa_stream_open_ioctl()
1861 ret = -EINVAL; in xe_oa_stream_open_ioctl()
1870 drm_dbg(&oa->xe->drm, "OA_EXPONENT specified without SAMPLE_OA\n"); in xe_oa_stream_open_ioctl()
1871 ret = -EINVAL; in xe_oa_stream_open_ioctl()
1874 oa_period = oa_exponent_to_ns(param.hwe->gt, param.period_exponent); in xe_oa_stream_open_ioctl()
1876 drm_dbg(&oa->xe->drm, "Using periodic sampling freq %lld Hz\n", oa_freq_hz); in xe_oa_stream_open_ioctl()
1879 mutex_lock(&param.hwe->gt->oa.gt_lock); in xe_oa_stream_open_ioctl()
1881 mutex_unlock(&param.hwe->gt->oa.gt_lock); in xe_oa_stream_open_ioctl()
1910 while (table->start && table->end) { in xe_oa_reg_in_range_table()
1911 if (addr >= table->start && addr <= table->end) in xe_oa_reg_in_range_table()
1922 { .start = 0xdd00, .end = 0xdd48 }, /* OAG_LCE0_0 - OAA_LENABLE_REG */
1928 { .start = 0xd900, .end = 0xd91c }, /* OAG_OASTARTTRIG[1-8] */
1929 { .start = 0xd920, .end = 0xd93c }, /* OAG_OAREPORTTRIG1[1-8] */
1930 { .start = 0xd940, .end = 0xd97c }, /* OAG_CEC[0-7][0-1] */
1931 { .start = 0xdc00, .end = 0xdc3c }, /* OAG_SCEC[0-7][0-1] */
1938 { .start = 0x393000, .end = 0x39301c }, /* OAM_STARTTRIG1[1-8] */
1939 { .start = 0x393020, .end = 0x39303c }, /* OAM_REPORTTRIG1[1-8] */
1940 { .start = 0x393040, .end = 0x39307c }, /* OAM_CEC[0-7][0-1] */
1941 { .start = 0x393200, .end = 0x39323C }, /* MPES[0-7] */
1946 { .start = 0x393200, .end = 0x39323C }, /* MPES_0_MPES_SAG - MPES_7_UPPER_MPES_SAG */
1947 { .start = 0x394200, .end = 0x39423C }, /* MPES_0_MPES_SCMI0 - MPES_7_UPPER_MPES_SCMI0 */
1948 { .start = 0x394A00, .end = 0x394A3C }, /* MPES_0_MPES_SCMI1 - MPES_7_UPPER_MPES_SCMI1 */
1957 (GRAPHICS_VER(oa->xe) >= 20 && in xe_oa_is_valid_b_counter_addr()
1962 { .start = 0x0d00, .end = 0x0d04 }, /* RPM_CONFIG[0-1] */
1963 { .start = 0x0d0c, .end = 0x0d2c }, /* NOA_CONFIG[0-8] */
1971 { .start = 0x0d00, .end = 0x0d04 }, /* RPM_CONFIG[0-1] */
1972 { .start = 0x0d0c, .end = 0x0d2c }, /* NOA_CONFIG[0-8] */
1985 { .start = 0x13000, .end = 0x137FC }, /* PES_0_PESL0 - PES_63_UPPER_PESL3 */
1991 if (GRAPHICS_VER(oa->xe) >= 20) in xe_oa_is_valid_mux_addr()
1993 else if (GRAPHICS_VERx100(oa->xe) >= 1270) in xe_oa_is_valid_mux_addr()
2016 return ERR_PTR(-ENOMEM); in xe_oa_alloc_regs()
2026 drm_dbg(&oa->xe->drm, "Invalid oa_reg address: %X\n", addr); in xe_oa_alloc_regs()
2027 err = -EINVAL; in xe_oa_alloc_regs()
2055 return sysfs_emit(buf, "%d\n", oa_config->id); in show_dynamic_id()
2061 sysfs_attr_init(&oa_config->sysfs_metric_id.attr); in create_dynamic_oa_sysfs_entry()
2062 oa_config->sysfs_metric_id.attr.name = "id"; in create_dynamic_oa_sysfs_entry()
2063 oa_config->sysfs_metric_id.attr.mode = 0444; in create_dynamic_oa_sysfs_entry()
2064 oa_config->sysfs_metric_id.show = show_dynamic_id; in create_dynamic_oa_sysfs_entry()
2065 oa_config->sysfs_metric_id.store = NULL; in create_dynamic_oa_sysfs_entry()
2067 oa_config->attrs[0] = &oa_config->sysfs_metric_id.attr; in create_dynamic_oa_sysfs_entry()
2068 oa_config->attrs[1] = NULL; in create_dynamic_oa_sysfs_entry()
2070 oa_config->sysfs_metric.name = oa_config->uuid; in create_dynamic_oa_sysfs_entry()
2071 oa_config->sysfs_metric.attrs = oa_config->attrs; in create_dynamic_oa_sysfs_entry()
2073 return sysfs_create_group(oa->metrics_kobj, &oa_config->sysfs_metric); in create_dynamic_oa_sysfs_entry()
2077 * xe_oa_add_config_ioctl - Adds one OA config
2089 struct xe_oa *oa = &xe->oa; in xe_oa_add_config_ioctl()
2096 if (!oa->xe) { in xe_oa_add_config_ioctl()
2097 drm_dbg(&xe->drm, "xe oa interface not available for this system\n"); in xe_oa_add_config_ioctl()
2098 return -ENODEV; in xe_oa_add_config_ioctl()
2102 drm_dbg(&oa->xe->drm, "Insufficient privileges to add xe OA config\n"); in xe_oa_add_config_ioctl()
2103 return -EACCES; in xe_oa_add_config_ioctl()
2107 if (XE_IOCTL_DBG(oa->xe, err)) in xe_oa_add_config_ioctl()
2108 return -EFAULT; in xe_oa_add_config_ioctl()
2110 if (XE_IOCTL_DBG(oa->xe, arg->extensions) || in xe_oa_add_config_ioctl()
2111 XE_IOCTL_DBG(oa->xe, !arg->regs_ptr) || in xe_oa_add_config_ioctl()
2112 XE_IOCTL_DBG(oa->xe, !arg->n_regs)) in xe_oa_add_config_ioctl()
2113 return -EINVAL; in xe_oa_add_config_ioctl()
2117 return -ENOMEM; in xe_oa_add_config_ioctl()
2119 oa_config->oa = oa; in xe_oa_add_config_ioctl()
2120 kref_init(&oa_config->ref); in xe_oa_add_config_ioctl()
2122 if (!uuid_is_valid(arg->uuid)) { in xe_oa_add_config_ioctl()
2123 drm_dbg(&oa->xe->drm, "Invalid uuid format for OA config\n"); in xe_oa_add_config_ioctl()
2124 err = -EINVAL; in xe_oa_add_config_ioctl()
2128 /* Last character in oa_config->uuid will be 0 because oa_config is kzalloc */ in xe_oa_add_config_ioctl()
2129 memcpy(oa_config->uuid, arg->uuid, sizeof(arg->uuid)); in xe_oa_add_config_ioctl()
2131 oa_config->regs_len = arg->n_regs; in xe_oa_add_config_ioctl()
2133 u64_to_user_ptr(arg->regs_ptr), in xe_oa_add_config_ioctl()
2134 arg->n_regs); in xe_oa_add_config_ioctl()
2136 drm_dbg(&oa->xe->drm, "Failed to create OA config for mux_regs\n"); in xe_oa_add_config_ioctl()
2140 oa_config->regs = regs; in xe_oa_add_config_ioctl()
2142 err = mutex_lock_interruptible(&oa->metrics_lock); in xe_oa_add_config_ioctl()
2147 idr_for_each_entry(&oa->metrics_idr, tmp, id) { in xe_oa_add_config_ioctl()
2148 if (!strcmp(tmp->uuid, oa_config->uuid)) { in xe_oa_add_config_ioctl()
2149 drm_dbg(&oa->xe->drm, "OA config already exists with this uuid\n"); in xe_oa_add_config_ioctl()
2150 err = -EADDRINUSE; in xe_oa_add_config_ioctl()
2157 drm_dbg(&oa->xe->drm, "Failed to create sysfs entry for OA config\n"); in xe_oa_add_config_ioctl()
2161 oa_config->id = idr_alloc(&oa->metrics_idr, oa_config, 1, 0, GFP_KERNEL); in xe_oa_add_config_ioctl()
2162 if (oa_config->id < 0) { in xe_oa_add_config_ioctl()
2163 drm_dbg(&oa->xe->drm, "Failed to create sysfs entry for OA config\n"); in xe_oa_add_config_ioctl()
2164 err = oa_config->id; in xe_oa_add_config_ioctl()
2168 mutex_unlock(&oa->metrics_lock); in xe_oa_add_config_ioctl()
2170 drm_dbg(&oa->xe->drm, "Added config %s id=%i\n", oa_config->uuid, oa_config->id); in xe_oa_add_config_ioctl()
2172 return oa_config->id; in xe_oa_add_config_ioctl()
2175 mutex_unlock(&oa->metrics_lock); in xe_oa_add_config_ioctl()
2178 drm_dbg(&oa->xe->drm, "Failed to add new OA config\n"); in xe_oa_add_config_ioctl()
2183 * xe_oa_remove_config_ioctl - Removes one OA config
2191 struct xe_oa *oa = &xe->oa; in xe_oa_remove_config_ioctl()
2196 if (!oa->xe) { in xe_oa_remove_config_ioctl()
2197 drm_dbg(&xe->drm, "xe oa interface not available for this system\n"); in xe_oa_remove_config_ioctl()
2198 return -ENODEV; in xe_oa_remove_config_ioctl()
2202 drm_dbg(&oa->xe->drm, "Insufficient privileges to remove xe OA config\n"); in xe_oa_remove_config_ioctl()
2203 return -EACCES; in xe_oa_remove_config_ioctl()
2207 if (XE_IOCTL_DBG(oa->xe, ret)) in xe_oa_remove_config_ioctl()
2210 ret = mutex_lock_interruptible(&oa->metrics_lock); in xe_oa_remove_config_ioctl()
2214 oa_config = idr_find(&oa->metrics_idr, arg); in xe_oa_remove_config_ioctl()
2216 drm_dbg(&oa->xe->drm, "Failed to remove unknown OA config\n"); in xe_oa_remove_config_ioctl()
2217 ret = -ENOENT; in xe_oa_remove_config_ioctl()
2221 WARN_ON(arg != oa_config->id); in xe_oa_remove_config_ioctl()
2223 sysfs_remove_group(oa->metrics_kobj, &oa_config->sysfs_metric); in xe_oa_remove_config_ioctl()
2224 idr_remove(&oa->metrics_idr, arg); in xe_oa_remove_config_ioctl()
2226 mutex_unlock(&oa->metrics_lock); in xe_oa_remove_config_ioctl()
2228 drm_dbg(&oa->xe->drm, "Removed config %s id=%i\n", oa_config->uuid, oa_config->id); in xe_oa_remove_config_ioctl()
2235 mutex_unlock(&oa->metrics_lock); in xe_oa_remove_config_ioctl()
2240 * xe_oa_register - Xe OA registration
2247 struct xe_oa *oa = &xe->oa; in xe_oa_register()
2249 if (!oa->xe) in xe_oa_register()
2252 oa->metrics_kobj = kobject_create_and_add("metrics", in xe_oa_register()
2253 &xe->drm.primary->kdev->kobj); in xe_oa_register()
2257 * xe_oa_unregister - Xe OA de-registration
2262 struct xe_oa *oa = &xe->oa; in xe_oa_unregister()
2264 if (!oa->metrics_kobj) in xe_oa_unregister()
2267 kobject_put(oa->metrics_kobj); in xe_oa_unregister()
2268 oa->metrics_kobj = NULL; in xe_oa_unregister()
2278 if (GRAPHICS_VERx100(gt_to_xe(hwe->gt)) >= 1270) { in __hwe_oam_unit()
2283 xe_gt_WARN_ON(hwe->gt, hwe->gt->info.type != XE_GT_TYPE_MEDIA); in __hwe_oam_unit()
2293 switch (hwe->class) { in __hwe_oa_unit()
2340 int i, num_units = gt->oa.num_oa_units; in __xe_oa_init_oa_units()
2343 struct xe_oa_unit *u = &gt->oa.oa_unit[i]; in __xe_oa_init_oa_units()
2345 if (gt->info.type != XE_GT_TYPE_MEDIA) { in __xe_oa_init_oa_units()
2346 u->regs = __oag_regs(); in __xe_oa_init_oa_units()
2347 u->type = DRM_XE_OA_UNIT_TYPE_OAG; in __xe_oa_init_oa_units()
2349 u->regs = __oam_regs(mtl_oa_base[i]); in __xe_oa_init_oa_units()
2350 u->type = DRM_XE_OA_UNIT_TYPE_OAM; in __xe_oa_init_oa_units()
2354 xe_mmio_write32(gt, u->regs.oa_debug, in __xe_oa_init_oa_units()
2358 u->oa_unit_id = gt_to_xe(gt)->oa.oa_unit_ids++; in __xe_oa_init_oa_units()
2369 u = drmm_kcalloc(&gt_to_xe(gt)->drm, num_oa_units, sizeof(*u), GFP_KERNEL); in xe_oa_init_gt()
2371 return -ENOMEM; in xe_oa_init_gt()
2376 hwe->oa_unit = NULL; in xe_oa_init_gt()
2379 hwe->oa_unit = &u[index]; in xe_oa_init_gt()
2387 gt->oa.num_oa_units = num_oa_units; in xe_oa_init_gt()
2388 gt->oa.oa_unit = u; in xe_oa_init_gt()
2392 drmm_mutex_init(&gt_to_xe(gt)->drm, &gt->oa.gt_lock); in xe_oa_init_gt()
2402 for_each_gt(gt, oa->xe, i) { in xe_oa_init_oa_units()
2413 __set_bit(format, oa->format_mask); in oa_format_add()
2418 if (GRAPHICS_VER(oa->xe) >= 20) { in xe_oa_init_supported_formats()
2431 } else if (GRAPHICS_VERx100(oa->xe) >= 1270) { in xe_oa_init_supported_formats()
2439 } else if (GRAPHICS_VERx100(oa->xe) >= 1255) { in xe_oa_init_supported_formats()
2447 xe_assert(oa->xe, GRAPHICS_VER(oa->xe) >= 12); in xe_oa_init_supported_formats()
2456 * xe_oa_init - OA initialization during device probe
2463 struct xe_oa *oa = &xe->oa; in xe_oa_init()
2473 oa->xe = xe; in xe_oa_init()
2474 oa->oa_formats = oa_formats; in xe_oa_init()
2476 drmm_mutex_init(&oa->xe->drm, &oa->metrics_lock); in xe_oa_init()
2477 idr_init_base(&oa->metrics_idr, 1); in xe_oa_init()
2481 drm_err(&xe->drm, "OA initialization failed (%pe)\n", ERR_PTR(ret)); in xe_oa_init()
2488 oa->xe = NULL; in xe_oa_init()
2499 * xe_oa_fini - OA de-initialization during device remove
2504 struct xe_oa *oa = &xe->oa; in xe_oa_fini()
2506 if (!oa->xe) in xe_oa_fini()
2509 idr_for_each(&oa->metrics_idr, destroy_config, oa); in xe_oa_fini()
2510 idr_destroy(&oa->metrics_idr); in xe_oa_fini()
2512 oa->xe = NULL; in xe_oa_fini()