[Intel-xe] [PATCH 09/10] drm/xe/oa: Read file_operation
Umesh Nerlige Ramappa
umesh.nerlige.ramappa at intel.com
Wed Aug 23 19:46:45 UTC 2023
On Mon, Aug 07, 2023 at 06:31:58PM -0700, Ashutosh Dixit wrote:
>Finally implement the OA stream read file_operation which was the only fop
>missing in the previous commit. Both blocking and non-blocking reads are
>supported. The read copies OA perf data from the OA buffer to the user
>buffer provided as part of read system call.
>
>Signed-off-by: Ashutosh Dixit <ashutosh.dixit at intel.com>
>---
> drivers/gpu/drm/xe/xe_oa.c | 359 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 359 insertions(+)
>
>diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c
>index c97180997427e..fcbb352f36a48 100644
>--- a/drivers/gpu/drm/xe/xe_oa.c
>+++ b/drivers/gpu/drm/xe/xe_oa.c
>@@ -146,6 +146,29 @@ static u64 oa_report_id(struct xe_oa_stream *stream, void *report)
> return oa_report_header_64bit(stream) ? *(u64 *)report : *(u32 *)report;
> }
>
>+#define OAREPORT_REASON_MASK_EXTENDED GENMASK(25, 19)
>+#define OAREPORT_REASON_TIMER BIT(0)
>+#define OAREPORT_REASON_CTX_SWITCH BIT(3)
>+#define OAREPORT_REASON_CLK_RATIO BIT(5)
>+
>+static u64 oa_report_reason(struct xe_oa_stream *stream, void *report)
>+{
>+ return FIELD_GET(OAREPORT_REASON_MASK_EXTENDED, oa_report_id(stream, report));
>+}
>+
>+static void oa_report_id_clear(struct xe_oa_stream *stream, u32 *report)
>+{
>+ if (oa_report_header_64bit(stream))
>+ *(u64 *)report = 0;
>+ else
>+ *report = 0;
>+}
>+
>+static bool oa_report_ctx_invalid(struct xe_oa_stream *stream, void
>*report)
>+{
>+ return false;
>+}
I think I had posted an updated patch for i915. The context valid bit is
applicable to gen12 as well, so we should implement the context id
valid/invalid helper.
>+
> static u64 oa_timestamp(struct xe_oa_stream *stream, void *report)
> {
> return oa_report_header_64bit(stream) ?
>@@ -153,6 +176,29 @@ static u64 oa_timestamp(struct xe_oa_stream *stream, void *report)
> *((u32 *)report + 1);
> }
>
>+static void oa_timestamp_clear(struct xe_oa_stream *stream, u32 *report)
>+{
>+ if (oa_report_header_64bit(stream))
>+ *(u64 *)&report[2] = 0;
>+ else
>+ report[1] = 0;
>+}
>+
>+static u32 oa_context_id(struct xe_oa_stream *stream, u32 *report)
>+{
>+ u32 ctx_id = oa_report_header_64bit(stream) ? report[4] : report[2];
>+
>+ return ctx_id & stream->specific_ctx_id_mask;
>+}
>+
>+static void oa_context_id_squash(struct xe_oa_stream *stream, u32 *report)
>+{
>+ if (oa_report_header_64bit(stream))
>+ report[4] = INVALID_CTX_ID;
>+ else
>+ report[2] = INVALID_CTX_ID;
>+}
>+
> static bool xe_oa_buffer_check_unlocked(struct xe_oa_stream *stream)
> {
> u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo);
>@@ -234,6 +280,199 @@ static enum hrtimer_restart xe_oa_poll_check_timer_cb(struct hrtimer *hrtimer)
> return HRTIMER_RESTART;
> }
>
>+static int xe_oa_append_status(struct xe_oa_stream *stream, char __user *buf,
>+ size_t count, size_t *offset,
>+ enum drm_xe_oa_record_type type)
>+{
>+ struct drm_xe_oa_record_header header = { type, 0, sizeof(header) };
>+
>+ if ((count - *offset) < header.size)
>+ return -ENOSPC;
>+
>+ if (copy_to_user(buf + *offset, &header, sizeof(header)))
>+ return -EFAULT;
>+
>+ *offset += header.size;
>+
>+ return 0;
>+}
>+
>+static int xe_oa_append_sample(struct xe_oa_stream *stream, char __user *buf,
>+ size_t count, size_t *offset, const u8 *report)
>+{
>+ int report_size = stream->oa_buffer.format->size;
>+ struct drm_xe_oa_record_header header;
>+ int report_size_partial;
>+ u8 *oa_buf_end;
>+
>+ header.type = DRM_XE_OA_RECORD_SAMPLE;
>+ header.pad = 0;
>+ header.size = stream->sample_size;
>+
>+ if ((count - *offset) < header.size)
>+ return -ENOSPC;
>+
>+ buf += *offset;
>+ if (copy_to_user(buf, &header, sizeof(header)))
>+ return -EFAULT;
>+ buf += sizeof(header);
>+
>+ oa_buf_end = stream->oa_buffer.vaddr + OA_BUFFER_SIZE;
>+ report_size_partial = oa_buf_end - report;
>+
>+ if (report_size_partial < report_size) {
>+ if (copy_to_user(buf, report, report_size_partial))
>+ return -EFAULT;
>+ buf += report_size_partial;
>+
>+ if (copy_to_user(buf, stream->oa_buffer.vaddr,
>+ report_size - report_size_partial))
>+ return -EFAULT;
>+ } else if (copy_to_user(buf, report, report_size)) {
>+ return -EFAULT;
>+ }
>+
>+ *offset += header.size;
>+
>+ return 0;
>+}
>+
>+static int xe_oa_append_reports(struct xe_oa_stream *stream, char __user *buf,
>+ size_t count, size_t *offset)
>+{
>+ int report_size = stream->oa_buffer.format->size;
>+ u8 *oa_buf_base = stream->oa_buffer.vaddr;
>+ u32 gtt_offset = xe_bo_ggtt_addr(stream->oa_buffer.bo);
>+ u32 mask = (OA_BUFFER_SIZE - 1);
>+ size_t start_offset = *offset;
>+ unsigned long flags;
>+ u32 head, tail;
>+ int ret = 0;
>+
>+ if (drm_WARN_ON(&stream->oa->xe->drm, !stream->enabled))
>+ return -EIO;
>+
>+ spin_lock_irqsave(&stream->oa_buffer.ptr_lock, flags);
>+
>+ head = stream->oa_buffer.head;
>+ tail = stream->oa_buffer.tail;
>+
>+ spin_unlock_irqrestore(&stream->oa_buffer.ptr_lock, flags);
>+
>+ /* An out of bounds or misaligned head or tail pointer implies a driver bug */
>+ if (drm_WARN_ONCE(&stream->oa->xe->drm,
>+ head > OA_BUFFER_SIZE || tail > OA_BUFFER_SIZE,
>+ "Inconsistent OA buffer pointers: head = %u, tail = %u\n",
>+ head, tail))
>+ return -EIO;
>+
>+ for (/* none */; OA_TAKEN(tail, head); head = (head + report_size) & mask) {
We can drop the 'none' comment.
Umesh
More information about the Intel-xe
mailing list