summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/xe/xe_query.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/xe/xe_query.c')
-rw-r--r--drivers/gpu/drm/xe/xe_query.c91
1 files changed, 89 insertions, 2 deletions
diff --git a/drivers/gpu/drm/xe/xe_query.c b/drivers/gpu/drm/xe/xe_query.c
index df407d73e5f5..73ef6e4c2dc9 100644
--- a/drivers/gpu/drm/xe/xe_query.c
+++ b/drivers/gpu/drm/xe/xe_query.c
@@ -16,6 +16,7 @@
#include "xe_bo.h"
#include "xe_device.h"
#include "xe_exec_queue.h"
+#include "xe_force_wake.h"
#include "xe_ggtt.h"
#include "xe_gt.h"
#include "xe_guc_hwconfig.h"
@@ -454,9 +455,10 @@ static int query_hwconfig(struct xe_device *xe,
static size_t calc_topo_query_size(struct xe_device *xe)
{
return xe->info.gt_count *
- (3 * sizeof(struct drm_xe_query_topology_mask) +
+ (4 * sizeof(struct drm_xe_query_topology_mask) +
sizeof_field(struct xe_gt, fuse_topo.g_dss_mask) +
sizeof_field(struct xe_gt, fuse_topo.c_dss_mask) +
+ sizeof_field(struct xe_gt, fuse_topo.l3_bank_mask) +
sizeof_field(struct xe_gt, fuse_topo.eu_mask_per_dss));
}
@@ -510,7 +512,15 @@ static int query_gt_topology(struct xe_device *xe,
if (err)
return err;
- topo.type = DRM_XE_TOPO_EU_PER_DSS;
+ topo.type = DRM_XE_TOPO_L3_BANK;
+ err = copy_mask(&query_ptr, &topo, gt->fuse_topo.l3_bank_mask,
+ sizeof(gt->fuse_topo.l3_bank_mask));
+ if (err)
+ return err;
+
+ topo.type = gt->fuse_topo.eu_type == XE_GT_EU_TYPE_SIMD16 ?
+ DRM_XE_TOPO_SIMD16_EU_PER_DSS :
+ DRM_XE_TOPO_EU_PER_DSS;
err = copy_mask(&query_ptr, &topo,
gt->fuse_topo.eu_mask_per_dss,
sizeof(gt->fuse_topo.eu_mask_per_dss));
@@ -594,6 +604,82 @@ query_uc_fw_version(struct xe_device *xe, struct drm_xe_device_query *query)
return 0;
}
+static size_t calc_oa_unit_query_size(struct xe_device *xe)
+{
+ size_t size = sizeof(struct drm_xe_query_oa_units);
+ struct xe_gt *gt;
+ int i, id;
+
+ for_each_gt(gt, xe, id) {
+ for (i = 0; i < gt->oa.num_oa_units; i++) {
+ size += sizeof(struct drm_xe_oa_unit);
+ size += gt->oa.oa_unit[i].num_engines *
+ sizeof(struct drm_xe_engine_class_instance);
+ }
+ }
+
+ return size;
+}
+
+static int query_oa_units(struct xe_device *xe,
+ struct drm_xe_device_query *query)
+{
+ void __user *query_ptr = u64_to_user_ptr(query->data);
+ size_t size = calc_oa_unit_query_size(xe);
+ struct drm_xe_query_oa_units *qoa;
+ enum xe_hw_engine_id hwe_id;
+ struct drm_xe_oa_unit *du;
+ struct xe_hw_engine *hwe;
+ struct xe_oa_unit *u;
+ int gt_id, i, j, ret;
+ struct xe_gt *gt;
+ u8 *pdu;
+
+ if (query->size == 0) {
+ query->size = size;
+ return 0;
+ } else if (XE_IOCTL_DBG(xe, query->size != size)) {
+ return -EINVAL;
+ }
+
+ qoa = kzalloc(size, GFP_KERNEL);
+ if (!qoa)
+ return -ENOMEM;
+
+ pdu = (u8 *)&qoa->oa_units[0];
+ for_each_gt(gt, xe, gt_id) {
+ for (i = 0; i < gt->oa.num_oa_units; i++) {
+ u = &gt->oa.oa_unit[i];
+ du = (struct drm_xe_oa_unit *)pdu;
+
+ du->oa_unit_id = u->oa_unit_id;
+ du->oa_unit_type = u->type;
+ du->oa_timestamp_freq = xe_oa_timestamp_frequency(gt);
+ du->capabilities = DRM_XE_OA_CAPS_BASE;
+
+ j = 0;
+ for_each_hw_engine(hwe, gt, hwe_id) {
+ if (!xe_hw_engine_is_reserved(hwe) &&
+ xe_oa_unit_id(hwe) == u->oa_unit_id) {
+ du->eci[j].engine_class =
+ xe_to_user_engine_class[hwe->class];
+ du->eci[j].engine_instance = hwe->logical_instance;
+ du->eci[j].gt_id = gt->info.id;
+ j++;
+ }
+ }
+ du->num_engines = j;
+ pdu += sizeof(*du) + j * sizeof(du->eci[0]);
+ qoa->num_oa_units++;
+ }
+ }
+
+ ret = copy_to_user(query_ptr, qoa, size);
+ kfree(qoa);
+
+ return ret ? -EFAULT : 0;
+}
+
static int (* const xe_query_funcs[])(struct xe_device *xe,
struct drm_xe_device_query *query) = {
query_engines,
@@ -604,6 +690,7 @@ static int (* const xe_query_funcs[])(struct xe_device *xe,
query_gt_topology,
query_engine_cycles,
query_uc_fw_version,
+ query_oa_units,
};
int xe_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)