diff mbox

[v12,7/8] RFC: drm/i915: expose chipset/driver properties through query uAPI

Message ID 20180129163146.20251-8-lionel.g.landwerlin@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Lionel Landwerlin Jan. 29, 2018, 4:31 p.m. UTC
The purpose of this is to give the ability to userspace to query a
bunch of properties in 1 ioctl rather than a series of successive
GETPARAM ioctl().

This loosely divides the properties in 2 groups, one being hardware
focused and the other being rather driver features.

The structures defined in the uAPI can be extended only by adding new
fields. If userspace uses an old version of the structures, the kernel
will only copy data up to the size requested by userspace. In the case
userspace has an newer version of the struct than what the kernel can
provide, any field tag with a more recent version than what returned
by the kernel should be ignored.

This change leaves out some of the GETPARAMs :

  - EU/slice/subslice: those are already covered by topology structs
  - engines queries: those might be addressed in another patch/series
  - some deprecated fields which always return ENODEV

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
---
 drivers/gpu/drm/i915/i915_query.c | 135 ++++++++++++++++++++++++++++++++++++++
 drivers/gpu/drm/i915/i915_query.h |   5 ++
 include/uapi/drm/i915_drm.h       |  76 +++++++++++++++++++++
 3 files changed, 216 insertions(+)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
index ff87ec8a321a..3770a0e49dad 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -132,11 +132,146 @@  static int query_eu_info(struct drm_i915_private *dev_priv,
 			       sseu->eu_mask, data_length);
 }
 
+void i915_query_fill_chipset_info(struct drm_i915_private *dev_priv,
+				  struct drm_i915_query_chipset_info *chipset_info)
+{
+	struct pci_dev *pdev = dev_priv->drm.pdev;
+
+	memset(chipset_info, 0, sizeof(*chipset_info));
+	chipset_info->version = 1;
+
+	chipset_info->chipset_id = pdev->device;
+	chipset_info->chipset_revision = pdev->revision;
+	chipset_info->num_fences_available = dev_priv->num_fence_regs;
+	chipset_info->cs_timestamp_frequency =
+		1000ULL * INTEL_INFO(dev_priv)->cs_timestamp_frequency_khz;
+	chipset_info->has_llc = HAS_LLC(dev_priv);
+	chipset_info->has_overlay = dev_priv->overlay ? 1 : 0;
+	chipset_info->has_semaphores = HAS_LEGACY_SEMAPHORES(dev_priv);
+	chipset_info->has_writethrough = HAS_WT(dev_priv);
+}
+
+static int query_chipset_info(struct drm_i915_private *dev_priv,
+			      struct drm_i915_query_item *query_item)
+{
+	struct drm_i915_query_chipset_info chipset_info;
+
+	if (query_item->flags != 0)
+		return -EINVAL;
+
+	if (query_item->length == 0) {
+		query_item->length = sizeof(chipset_info);
+		return 0;
+	}
+
+	i915_query_fill_chipset_info(dev_priv, &chipset_info);
+
+	/*
+	 * Only copy request user size as it depends upon the version of the
+	 * struct used by userspace.
+	 */
+	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr),
+			 &chipset_info, query_item->length))
+		return -EFAULT;
+
+	return 0;
+}
+
+void i915_query_fill_driver_info(struct drm_i915_private *dev_priv,
+				 struct drm_i915_query_driver_info *driver_info)
+{
+	memset(driver_info, 0, sizeof(*driver_info));
+	driver_info->version = 1;
+
+	/* Remember to bump this if the version changes! */
+	driver_info->mmap_version = 1;
+
+	/* For the time being all of these are always true;
+	 * if some supported hardware does not have one of these
+	 * features this value needs to be provided from
+	 * INTEL_INFO(), a feature macro, or similar.
+	 */
+	driver_info->has_coherent_phys_gtt = 1;
+	driver_info->has_coherent_rings = 1;
+	driver_info->has_exec_async = 1;
+	driver_info->has_exec_batch_first = 1;
+	driver_info->has_exec_capture = 1;
+	driver_info->has_exec_fence = 1;
+	driver_info->has_exec_fence_array = 1;
+	driver_info->has_exec_handle_lut = 1;
+	driver_info->has_exec_no_reloc = 1;
+	driver_info->has_exec_softpin = 1;
+	driver_info->has_execbuf2 = 1;
+	driver_info->has_gem = 1;
+	driver_info->has_gen7_sol_reset = 1;
+	driver_info->has_pageflipping = 1;
+	driver_info->has_pinned_batches = 1;
+	driver_info->has_prime_vmap_flush = 1;
+	driver_info->has_relaxed_delta = 1;
+	driver_info->has_relaxed_fencing = 1;
+	driver_info->has_wait_timeout = 1;
+
+	driver_info->has_aliasing_ppgtt = USES_PPGTT(dev_priv);
+
+	driver_info->has_context_isolation =
+		intel_engines_has_context_isolation(dev_priv);
+
+	driver_info->has_gpu_reset = i915_modparams.enable_hangcheck &&
+		intel_has_gpu_reset(dev_priv);
+	if (driver_info->has_gpu_reset && intel_has_reset_engine(dev_priv))
+		driver_info->has_gpu_reset = 2;
+
+	driver_info->has_resource_streamer = HAS_RESOURCE_STREAMER(dev_priv);
+
+	driver_info->has_scheduler = 0;
+	if (dev_priv->engine[RCS] && dev_priv->engine[RCS]->schedule) {
+		driver_info->has_scheduler |= I915_SCHEDULER_CAP_ENABLED;
+		driver_info->has_scheduler |= I915_SCHEDULER_CAP_PRIORITY;
+		if (HAS_LOGICAL_RING_PREEMPTION(dev_priv))
+			driver_info->has_scheduler |= I915_SCHEDULER_CAP_PREEMPTION;
+	}
+
+	driver_info->has_secure_batches = capable(CAP_SYS_ADMIN);
+
+	driver_info->cmd_parser_version = i915_cmd_parser_get_version(dev_priv);
+
+	driver_info->mmap_gtt_version = i915_gem_mmap_gtt_version();
+}
+
+
+static int query_driver_info(struct drm_i915_private *dev_priv,
+			     struct drm_i915_query_item *query_item)
+{
+	struct drm_i915_query_driver_info driver_info;
+
+	if (query_item->flags != 0)
+		return -EINVAL;
+
+	if (query_item->length == 0) {
+		query_item->length = sizeof(driver_info);
+		return 0;
+	}
+
+	i915_query_fill_driver_info(dev_priv, &driver_info);
+
+	/*
+	 * Only copy request user size as it depends upon the version of the
+	 * struct used by userspace.
+	 */
+	if (copy_to_user(u64_to_user_ptr(query_item->data_ptr),
+			 &driver_info, query_item->length))
+		return -EFAULT;
+
+	return 0;
+}
+
 static int (* const i915_query_funcs[])(struct drm_i915_private *dev_priv,
 					struct drm_i915_query_item *query_item) = {
 	query_slice_info,
 	query_subslice_info,
 	query_eu_info,
+	query_chipset_info,
+	query_driver_info,
 };
 
 int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
diff --git a/drivers/gpu/drm/i915/i915_query.h b/drivers/gpu/drm/i915/i915_query.h
index 4550e8f21459..30cb8c892aab 100644
--- a/drivers/gpu/drm/i915/i915_query.h
+++ b/drivers/gpu/drm/i915/i915_query.h
@@ -30,4 +30,9 @@  struct drm_file;
 
 int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
 
+void i915_query_fill_chipset_info(struct drm_i915_private *dev_priv,
+				  struct drm_i915_query_chipset_info *chipset_info);
+void i915_query_fill_driver_info(struct drm_i915_private *dev_priv,
+				 struct drm_i915_query_driver_info *driver_info);
+
 #endif
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 7ae8e9aa0206..d1f8b48df336 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1621,6 +1621,8 @@  struct drm_i915_query_item {
 #define DRM_I915_QUERY_SLICE_INFO	0x01
 #define DRM_I915_QUERY_SUBSLICE_INFO	0x02
 #define DRM_I915_QUERY_EU_INFO		0x03
+#define DRM_I915_QUERY_CHIPSET_INFO	0x04
+#define DRM_I915_QUERY_DRIVER_INFO	0x05
 
 	/*
 	 * When set to zero by userspace, this is filled with the size of the
@@ -1725,6 +1727,80 @@  struct drm_i915_query_eu_info {
 	__u8 data[];
 };
 
+/*
+ * Data written by the kernel with query DRM_I915_QUERY_CHIPSET_INFO.
+ *
+ * This structure is versioned, only allowing new fields to be added at the
+ * end of the structure.
+ *
+ * If a user queries this information with a newer version of the struct than
+ * what the kernel supports, it should not rely on fields in versions above
+ * the version number returned by the kernel, as they will contain invalid
+ * data.
+ */
+struct drm_i915_query_chipset_info {
+	__u32 version;
+
+	/* Version 1 */
+	__u32 chipset_id;
+	__u32 chipset_revision;
+
+	__u32 num_fences_available;
+
+	__u64 cs_timestamp_frequency;
+
+	__u8 has_llc;
+	__u8 has_overlay;
+	__u8 has_semaphores;
+	__u8 has_writethrough;
+};
+
+/*
+ * Data written by the kernel with query DRM_I915_QUERY_DRIVER_INFO.
+ *
+ * This structure is versioned, only allowing new fields to be added at the
+ * end of the structure.
+ *
+ * If a user queries this information with a newer version of the struct than
+ * what the kernel supports, it should not rely on fields in versions above
+ * the version number returned by the kernel, as they will contain invalid
+ * data.
+ */
+struct drm_i915_query_driver_info {
+	__u32 version;
+
+	/* Version 1 */
+	__u32 cmd_parser_version;
+	__u32 mmap_version;
+	__u32 mmap_gtt_version;
+
+	__u8 has_aliasing_ppgtt;
+	__u8 has_coherent_phys_gtt;
+	__u8 has_coherent_rings;
+	__u8 has_context_isolation;
+	__u8 has_exec_async;
+	__u8 has_exec_batch_first;
+	__u8 has_exec_capture;
+	__u8 has_exec_fence;
+	__u8 has_exec_fence_array;
+	__u8 has_exec_handle_lut;
+	__u8 has_exec_no_reloc;
+	__u8 has_exec_softpin;
+	__u8 has_execbuf2;
+	__u8 has_gem;
+	__u8 has_gen7_sol_reset;
+	__u8 has_gpu_reset;
+	__u8 has_pageflipping;
+	__u8 has_pinned_batches;
+	__u8 has_prime_vmap_flush;
+	__u8 has_relaxed_delta;
+	__u8 has_relaxed_fencing;
+	__u8 has_resource_streamer;
+	__u8 has_scheduler;
+	__u8 has_secure_batches;
+	__u8 has_wait_timeout;
+};
+
 #if defined(__cplusplus)
 }
 #endif