]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm/xe/oa/uapi: Expose media OA units
authorAshutosh Dixit <ashutosh.dixit@intel.com>
Fri, 6 Jun 2025 19:26:13 +0000 (12:26 -0700)
committerAshutosh Dixit <ashutosh.dixit@intel.com>
Tue, 17 Jun 2025 18:31:50 +0000 (11:31 -0700)
On Xe2+ platforms, media engines are attached to "SCMI" OA media (OAM)
units. One or more SCMI OAM units might be present on a platform. In
addition there is another OAM unit for global events, called
OAM-SAG. Performance metrics for media workloads can be obtained from these
OAM units, similar to OAG.

Expose these OAM units for userspace to use. OAM-SAG is exposed as an OA
unit without any attached engines.

Bspec: 70819, 67103, 63844, 72572, 74476, 61284

v2: Fix xe_gt_WARN_ON in __hwe_oam_unit for < 12.7 platforms
v3: Return XE_OA_UNIT_INVALID for < 12.7 to indicate no OAM units
v4: Move xe_oa_print_oa_units() to separate patch
v5: Introduce DRM_XE_OA_UNIT_TYPE_OAM_SAG
v6: Introduce DRM_XE_OA_CAPS_OAM

Signed-off-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Reviewed-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Link: https://lore.kernel.org/r/20250606192618.4133817-2-ashutosh.dixit@intel.com
drivers/gpu/drm/xe/xe_oa.c
drivers/gpu/drm/xe/xe_query.c
include/uapi/drm/xe_drm.h

index fb842fa0552e5c253dc7141c9d1377cfba30ff49..0de0d5a18df745d2b7693ab65ef1055fc833bff3 100644 (file)
 #define DEFAULT_POLL_PERIOD_NS (NSEC_PER_SEC / DEFAULT_POLL_FREQUENCY_HZ)
 #define XE_OA_UNIT_INVALID U32_MAX
 
+enum xe_oam_unit_type {
+       XE_OAM_UNIT_SAG,
+       XE_OAM_UNIT_SCMI_0,
+       XE_OAM_UNIT_SCMI_1,
+};
+
 enum xe_oa_submit_deps {
        XE_OA_SUBMIT_NO_DEPS,
        XE_OA_SUBMIT_ADD_DEPS,
@@ -1881,6 +1887,7 @@ static bool engine_supports_oa_format(const struct xe_hw_engine *hwe, int type)
                return type == DRM_XE_OA_FMT_TYPE_OAG || type == DRM_XE_OA_FMT_TYPE_OAR ||
                        type == DRM_XE_OA_FMT_TYPE_OAC || type == DRM_XE_OA_FMT_TYPE_PEC;
        case DRM_XE_OA_UNIT_TYPE_OAM:
+       case DRM_XE_OA_UNIT_TYPE_OAM_SAG:
                return type == DRM_XE_OA_FMT_TYPE_OAM || type == DRM_XE_OA_FMT_TYPE_OAM_MPEC;
        default:
                return false;
@@ -2448,20 +2455,38 @@ int xe_oa_register(struct xe_device *xe)
 
 static u32 num_oa_units_per_gt(struct xe_gt *gt)
 {
-       return 1;
+       if (!xe_gt_is_media_type(gt) || GRAPHICS_VER(gt_to_xe(gt)) < 20)
+               return 1;
+       else if (!IS_DGFX(gt_to_xe(gt)))
+               return XE_OAM_UNIT_SCMI_0 + 1; /* SAG + SCMI_0 */
+       else
+               return XE_OAM_UNIT_SCMI_1 + 1; /* SAG + SCMI_0 + SCMI_1 */
 }
 
 static u32 __hwe_oam_unit(struct xe_hw_engine *hwe)
 {
-       if (GRAPHICS_VERx100(gt_to_xe(hwe->gt)) >= 1270) {
-               /*
-                * There's 1 SAMEDIA gt and 1 OAM per SAMEDIA gt. All media slices
-                * within the gt use the same OAM. All MTL/LNL SKUs list 1 SA MEDIA
-                */
-               xe_gt_WARN_ON(hwe->gt, hwe->gt->info.type != XE_GT_TYPE_MEDIA);
+       if (GRAPHICS_VERx100(gt_to_xe(hwe->gt)) < 1270)
+               return XE_OA_UNIT_INVALID;
 
+       xe_gt_WARN_ON(hwe->gt, !xe_gt_is_media_type(hwe->gt));
+
+       if (GRAPHICS_VER(gt_to_xe(hwe->gt)) < 20)
                return 0;
-       }
+       /*
+        * XE_OAM_UNIT_SAG has only GSCCS attached to it, but only on some platforms. Also
+        * GSCCS cannot be used to submit batches to program the OAM unit. Therefore we don't
+        * assign an OA unit to GSCCS. This means that XE_OAM_UNIT_SAG is exposed as an OA
+        * unit without attached engines. Fused off engines can also result in oa_unit's with
+        * num_engines == 0. OA streams can be opened on all OA units.
+        */
+       else if (hwe->engine_id == XE_HW_ENGINE_GSCCS0)
+               return XE_OA_UNIT_INVALID;
+       else if (!IS_DGFX(gt_to_xe(hwe->gt)))
+               return XE_OAM_UNIT_SCMI_0;
+       else if (hwe->class == XE_ENGINE_CLASS_VIDEO_DECODE)
+               return (hwe->instance / 2 & 0x1) + 1;
+       else if (hwe->class == XE_ENGINE_CLASS_VIDEO_ENHANCE)
+               return (hwe->instance & 0x1) + 1;
 
        return XE_OA_UNIT_INVALID;
 }
@@ -2475,6 +2500,7 @@ static u32 __hwe_oa_unit(struct xe_hw_engine *hwe)
 
        case XE_ENGINE_CLASS_VIDEO_DECODE:
        case XE_ENGINE_CLASS_VIDEO_ENHANCE:
+       case XE_ENGINE_CLASS_OTHER:
                return __hwe_oam_unit(hwe);
 
        default:
@@ -2514,18 +2540,25 @@ static struct xe_oa_regs __oag_regs(void)
 
 static void __xe_oa_init_oa_units(struct xe_gt *gt)
 {
-       const u32 mtl_oa_base[] = { 0x13000 };
+       /* Actual address is MEDIA_GT_GSI_OFFSET + oam_base_addr[i] */
+       const u32 oam_base_addr[] = {
+               [XE_OAM_UNIT_SAG]    = 0x13000,
+               [XE_OAM_UNIT_SCMI_0] = 0x14000,
+               [XE_OAM_UNIT_SCMI_1] = 0x14800,
+       };
        int i, num_units = gt->oa.num_oa_units;
 
        for (i = 0; i < num_units; i++) {
                struct xe_oa_unit *u = &gt->oa.oa_unit[i];
 
-               if (gt->info.type != XE_GT_TYPE_MEDIA) {
+               if (!xe_gt_is_media_type(gt)) {
                        u->regs = __oag_regs();
                        u->type = DRM_XE_OA_UNIT_TYPE_OAG;
-               } else if (GRAPHICS_VERx100(gt_to_xe(gt)) >= 1270) {
-                       u->regs = __oam_regs(mtl_oa_base[i]);
-                       u->type = DRM_XE_OA_UNIT_TYPE_OAM;
+               } else {
+                       xe_gt_assert(gt, GRAPHICS_VERx100(gt_to_xe(gt)) >= 1270);
+                       u->regs = __oam_regs(oam_base_addr[i]);
+                       u->type = i == XE_OAM_UNIT_SAG && GRAPHICS_VER(gt_to_xe(gt)) >= 20 ?
+                               DRM_XE_OA_UNIT_TYPE_OAM_SAG : DRM_XE_OA_UNIT_TYPE_OAM;
                }
 
                xe_mmio_write32(&gt->mmio, u->regs.oa_ctrl, 0);
@@ -2560,10 +2593,6 @@ static int xe_oa_init_gt(struct xe_gt *gt)
                }
        }
 
-       /*
-        * Fused off engines can result in oa_unit's with num_engines == 0. These units
-        * will appear in OA unit query, but no OA streams can be opened on them.
-        */
        gt->oa.num_oa_units = num_oa_units;
        gt->oa.oa_unit = u;
 
@@ -2579,6 +2608,11 @@ static int xe_oa_init_oa_units(struct xe_oa *oa)
        struct xe_gt *gt;
        int i, ret;
 
+       /* Needed for OAM implementation here */
+       BUILD_BUG_ON(XE_OAM_UNIT_SAG != 0);
+       BUILD_BUG_ON(XE_OAM_UNIT_SCMI_0 != 1);
+       BUILD_BUG_ON(XE_OAM_UNIT_SCMI_1 != 2);
+
        for_each_gt(gt, oa->xe, i) {
                ret = xe_oa_init_gt(gt);
                if (ret)
index 2dbf4066d86ff225eee002d352e1233c8d9519b9..e8e1743dcb1e06cbd77752d03ca7876a52ea7ee7 100644 (file)
@@ -683,8 +683,8 @@ static int query_oa_units(struct xe_device *xe,
                        du->oa_timestamp_freq = xe_oa_timestamp_frequency(gt);
                        du->capabilities = DRM_XE_OA_CAPS_BASE | DRM_XE_OA_CAPS_SYNCS |
                                           DRM_XE_OA_CAPS_OA_BUFFER_SIZE |
-                                          DRM_XE_OA_CAPS_WAIT_NUM_REPORTS;
-
+                                          DRM_XE_OA_CAPS_WAIT_NUM_REPORTS |
+                                          DRM_XE_OA_CAPS_OAM;
                        j = 0;
                        for_each_hw_engine(hwe, gt, hwe_id) {
                                if (!xe_hw_engine_is_reserved(hwe) &&
index 6a702ba7817c38778cfea3506d682e22821623d4..8e8bbdec8c5ca4c33be8907a557b764ea5eaa83c 100644 (file)
@@ -1617,6 +1617,9 @@ enum drm_xe_oa_unit_type {
 
        /** @DRM_XE_OA_UNIT_TYPE_OAM: OAM OA unit */
        DRM_XE_OA_UNIT_TYPE_OAM,
+
+       /** @DRM_XE_OA_UNIT_TYPE_OAM_SAG: OAM_SAG OA unit */
+       DRM_XE_OA_UNIT_TYPE_OAM_SAG,
 };
 
 /**
@@ -1638,6 +1641,7 @@ struct drm_xe_oa_unit {
 #define DRM_XE_OA_CAPS_SYNCS           (1 << 1)
 #define DRM_XE_OA_CAPS_OA_BUFFER_SIZE  (1 << 2)
 #define DRM_XE_OA_CAPS_WAIT_NUM_REPORTS        (1 << 3)
+#define DRM_XE_OA_CAPS_OAM             (1 << 4)
 
        /** @oa_timestamp_freq: OA timestamp freq */
        __u64 oa_timestamp_freq;