From patchwork Wed Sep 5 14:25:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 10588987 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B4AAF112B for ; Wed, 5 Sep 2018 14:25:58 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9D8972821F for ; Wed, 5 Sep 2018 14:25:58 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 91CAD29D9E; Wed, 5 Sep 2018 14:25:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 090B32821F for ; Wed, 5 Sep 2018 14:25:56 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8C8106E4C1; Wed, 5 Sep 2018 14:25:54 +0000 (UTC) X-Original-To: Intel-gfx@lists.freedesktop.org Delivered-To: Intel-gfx@lists.freedesktop.org Received: from mail-wm0-x230.google.com (mail-wm0-x230.google.com [IPv6:2a00:1450:400c:c09::230]) by gabe.freedesktop.org (Postfix) with ESMTPS id 876386E4C5 for ; Wed, 5 Sep 2018 14:25:52 +0000 (UTC) Received: by mail-wm0-x230.google.com with SMTP id t25-v6so7938115wmi.3 for ; Wed, 05 Sep 2018 07:25:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=v/ceBYfgCFg1hq1bxwt/X/hVji0oQXKOFikrnU2xVmk=; b=LN0Gxzfd+bu+0z8vrDvsADWuqmsM1xCSjMzzBCECbvkZgDvosaMbDvSteeoRMhuhZ7 VohH0fFF1pwJQWt5UAypHQgA9RAq1jFy7PVYMhgfEuMwbcByLts+vsEv2oMHy/4ndOdZ 3lTJW4G8tgyvl+c0mFwy7e5DorkrIHLlpgf7BOVuaP5/f9japNGRUqjGZy0uC4a74wzL HqcJnaoqAxEtwl6CClHnNjWx5IoI5Dig5CurA+vxkJcR0Ia6km+y4txYp2nzxVQRYCMi 1T6tztp5nBYfPRao+n82gxOK19vyYs12qTPOhWyMvFbko6UwnCTpeDYU5KlcOrvrnRUr DxYQ== X-Gm-Message-State: APzg51C706DLCFk+j+qxu/ecOHRz+RoFnTFc+AGLgfC68rJFpHznZb6Y OndiicpNVvb8Jd5fOM8dBCo0dA== X-Google-Smtp-Source: ANB0VdacXymH3//H7IJ5PoyWWIJLtDX5P88kUiRdkXn+yBKEr4BBaqbZ9rF5OwOW/17T8qeBhftOLw== X-Received: by 2002:a1c:dac9:: with SMTP id r192-v6mr378056wmg.141.1536157550654; Wed, 05 Sep 2018 07:25:50 -0700 (PDT) Received: from localhost.localdomain ([95.144.165.37]) by smtp.gmail.com with ESMTPSA id z13sm2289763wrw.19.2018.09.05.07.25.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Sep 2018 07:25:50 -0700 (PDT) From: Tvrtko Ursulin X-Google-Original-From: Tvrtko Ursulin To: igt-dev@lists.freedesktop.org Date: Wed, 5 Sep 2018 15:25:43 +0100 Message-Id: <20180905142544.3381-2-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180905142544.3381-1-tvrtko.ursulin@linux.intel.com> References: <20180905142544.3381-1-tvrtko.ursulin@linux.intel.com> Subject: [Intel-gfx] [PATH i-g-t 1/2] headers: bump X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Intel-gfx@lists.freedesktop.org MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP From: Lionel Landwerlin --- include/drm-uapi/amdgpu_drm.h | 23 ++ include/drm-uapi/drm.h | 7 + include/drm-uapi/drm_mode.h | 22 +- include/drm-uapi/etnaviv_drm.h | 6 + include/drm-uapi/exynos_drm.h | 240 ++++++++++++++++ include/drm-uapi/i915_drm.h | 43 +++ include/drm-uapi/msm_drm.h | 2 + include/drm-uapi/tegra_drm.h | 492 ++++++++++++++++++++++++++++++++- include/drm-uapi/vc4_drm.h | 13 +- include/drm-uapi/virtgpu_drm.h | 1 + 10 files changed, 833 insertions(+), 16 deletions(-) diff --git a/include/drm-uapi/amdgpu_drm.h b/include/drm-uapi/amdgpu_drm.h index 1816bd8200d1..78b4dd89fcb4 100644 --- a/include/drm-uapi/amdgpu_drm.h +++ b/include/drm-uapi/amdgpu_drm.h @@ -78,6 +78,12 @@ extern "C" { #define AMDGPU_GEM_DOMAIN_GDS 0x8 #define AMDGPU_GEM_DOMAIN_GWS 0x10 #define AMDGPU_GEM_DOMAIN_OA 0x20 +#define AMDGPU_GEM_DOMAIN_MASK (AMDGPU_GEM_DOMAIN_CPU | \ + AMDGPU_GEM_DOMAIN_GTT | \ + AMDGPU_GEM_DOMAIN_VRAM | \ + AMDGPU_GEM_DOMAIN_GDS | \ + AMDGPU_GEM_DOMAIN_GWS | \ + AMDGPU_GEM_DOMAIN_OA) /* Flag that CPU access will be required for the case of VRAM domain */ #define AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED (1 << 0) @@ -95,6 +101,10 @@ extern "C" { #define AMDGPU_GEM_CREATE_VM_ALWAYS_VALID (1 << 6) /* Flag that BO sharing will be explicitly synchronized */ #define AMDGPU_GEM_CREATE_EXPLICIT_SYNC (1 << 7) +/* Flag that indicates allocating MQD gart on GFX9, where the mtype + * for the second page onward should be set to NC. + */ +#define AMDGPU_GEM_CREATE_MQD_GFX9 (1 << 8) struct drm_amdgpu_gem_create_in { /** the requested memory size */ @@ -520,6 +530,10 @@ union drm_amdgpu_cs { /* Preempt flag, IB should set Pre_enb bit if PREEMPT flag detected */ #define AMDGPU_IB_FLAG_PREEMPT (1<<2) +/* The IB fence should do the L2 writeback but not invalidate any shader + * caches (L2/vL1/sL1/I$). */ +#define AMDGPU_IB_FLAG_TC_WB_NOT_INVALIDATE (1 << 3) + struct drm_amdgpu_cs_chunk_ib { __u32 _pad; /** AMDGPU_IB_FLAG_* */ @@ -618,6 +632,14 @@ struct drm_amdgpu_cs_chunk_data { #define AMDGPU_INFO_FW_SOS 0x0c /* Subquery id: Query PSP ASD firmware version */ #define AMDGPU_INFO_FW_ASD 0x0d + /* Subquery id: Query VCN firmware version */ + #define AMDGPU_INFO_FW_VCN 0x0e + /* Subquery id: Query GFX RLC SRLC firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_CNTL 0x0f + /* Subquery id: Query GFX RLC SRLG firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_GPM_MEM 0x10 + /* Subquery id: Query GFX RLC SRLS firmware version */ + #define AMDGPU_INFO_FW_GFX_RLC_RESTORE_LIST_SRM_MEM 0x11 /* number of bytes moved for TTM migration */ #define AMDGPU_INFO_NUM_BYTES_MOVED 0x0f /* the used VRAM size */ @@ -806,6 +828,7 @@ struct drm_amdgpu_info_firmware { #define AMDGPU_VRAM_TYPE_GDDR5 5 #define AMDGPU_VRAM_TYPE_HBM 6 #define AMDGPU_VRAM_TYPE_DDR3 7 +#define AMDGPU_VRAM_TYPE_DDR4 8 struct drm_amdgpu_info_device { /** PCI Device ID */ diff --git a/include/drm-uapi/drm.h b/include/drm-uapi/drm.h index f0bd91de0cf9..778a97fcfe63 100644 --- a/include/drm-uapi/drm.h +++ b/include/drm-uapi/drm.h @@ -674,6 +674,13 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_ATOMIC 3 +/** + * DRM_CLIENT_CAP_ASPECT_RATIO + * + * If set to 1, the DRM core will provide aspect ratio information in modes. + */ +#define DRM_CLIENT_CAP_ASPECT_RATIO 4 + /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability; diff --git a/include/drm-uapi/drm_mode.h b/include/drm-uapi/drm_mode.h index 2c575794fb52..971c016b368c 100644 --- a/include/drm-uapi/drm_mode.h +++ b/include/drm-uapi/drm_mode.h @@ -93,6 +93,15 @@ extern "C" { #define DRM_MODE_PICTURE_ASPECT_NONE 0 #define DRM_MODE_PICTURE_ASPECT_4_3 1 #define DRM_MODE_PICTURE_ASPECT_16_9 2 +#define DRM_MODE_PICTURE_ASPECT_64_27 3 +#define DRM_MODE_PICTURE_ASPECT_256_135 4 + +/* Content type options */ +#define DRM_MODE_CONTENT_TYPE_NO_DATA 0 +#define DRM_MODE_CONTENT_TYPE_GRAPHICS 1 +#define DRM_MODE_CONTENT_TYPE_PHOTO 2 +#define DRM_MODE_CONTENT_TYPE_CINEMA 3 +#define DRM_MODE_CONTENT_TYPE_GAME 4 /* Aspect ratio flag bitmask (4 bits 22:19) */ #define DRM_MODE_FLAG_PIC_AR_MASK (0x0F<<19) @@ -102,6 +111,10 @@ extern "C" { (DRM_MODE_PICTURE_ASPECT_4_3<<19) #define DRM_MODE_FLAG_PIC_AR_16_9 \ (DRM_MODE_PICTURE_ASPECT_16_9<<19) +#define DRM_MODE_FLAG_PIC_AR_64_27 \ + (DRM_MODE_PICTURE_ASPECT_64_27<<19) +#define DRM_MODE_FLAG_PIC_AR_256_135 \ + (DRM_MODE_PICTURE_ASPECT_256_135<<19) #define DRM_MODE_FLAG_ALL (DRM_MODE_FLAG_PHSYNC | \ DRM_MODE_FLAG_NHSYNC | \ @@ -363,7 +376,7 @@ struct drm_mode_get_connector { __u32 pad; }; -#define DRM_MODE_PROP_PENDING (1<<0) +#define DRM_MODE_PROP_PENDING (1<<0) /* deprecated, do not use */ #define DRM_MODE_PROP_RANGE (1<<1) #define DRM_MODE_PROP_IMMUTABLE (1<<2) #define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */ @@ -598,8 +611,11 @@ struct drm_mode_crtc_lut { }; struct drm_color_ctm { - /* Conversion matrix in S31.32 format. */ - __s64 matrix[9]; + /* + * Conversion matrix in S31.32 sign-magnitude + * (not two's complement!) format. + */ + __u64 matrix[9]; }; struct drm_color_lut { diff --git a/include/drm-uapi/etnaviv_drm.h b/include/drm-uapi/etnaviv_drm.h index e9b997a0ef27..0d5c49dc478c 100644 --- a/include/drm-uapi/etnaviv_drm.h +++ b/include/drm-uapi/etnaviv_drm.h @@ -55,6 +55,12 @@ struct drm_etnaviv_timespec { #define ETNAVIV_PARAM_GPU_FEATURES_4 0x07 #define ETNAVIV_PARAM_GPU_FEATURES_5 0x08 #define ETNAVIV_PARAM_GPU_FEATURES_6 0x09 +#define ETNAVIV_PARAM_GPU_FEATURES_7 0x0a +#define ETNAVIV_PARAM_GPU_FEATURES_8 0x0b +#define ETNAVIV_PARAM_GPU_FEATURES_9 0x0c +#define ETNAVIV_PARAM_GPU_FEATURES_10 0x0d +#define ETNAVIV_PARAM_GPU_FEATURES_11 0x0e +#define ETNAVIV_PARAM_GPU_FEATURES_12 0x0f #define ETNAVIV_PARAM_GPU_STREAM_COUNT 0x10 #define ETNAVIV_PARAM_GPU_REGISTER_MAX 0x11 diff --git a/include/drm-uapi/exynos_drm.h b/include/drm-uapi/exynos_drm.h index a00116b5cc5c..7414cfd76419 100644 --- a/include/drm-uapi/exynos_drm.h +++ b/include/drm-uapi/exynos_drm.h @@ -135,6 +135,219 @@ struct drm_exynos_g2d_exec { __u64 async; }; +/* Exynos DRM IPP v2 API */ + +/** + * Enumerate available IPP hardware modules. + * + * @count_ipps: size of ipp_id array / number of ipp modules (set by driver) + * @reserved: padding + * @ipp_id_ptr: pointer to ipp_id array or NULL + */ +struct drm_exynos_ioctl_ipp_get_res { + __u32 count_ipps; + __u32 reserved; + __u64 ipp_id_ptr; +}; + +enum drm_exynos_ipp_format_type { + DRM_EXYNOS_IPP_FORMAT_SOURCE = 0x01, + DRM_EXYNOS_IPP_FORMAT_DESTINATION = 0x02, +}; + +struct drm_exynos_ipp_format { + __u32 fourcc; + __u32 type; + __u64 modifier; +}; + +enum drm_exynos_ipp_capability { + DRM_EXYNOS_IPP_CAP_CROP = 0x01, + DRM_EXYNOS_IPP_CAP_ROTATE = 0x02, + DRM_EXYNOS_IPP_CAP_SCALE = 0x04, + DRM_EXYNOS_IPP_CAP_CONVERT = 0x08, +}; + +/** + * Get IPP hardware capabilities and supported image formats. + * + * @ipp_id: id of IPP module to query + * @capabilities: bitmask of drm_exynos_ipp_capability (set by driver) + * @reserved: padding + * @formats_count: size of formats array (in entries) / number of filled + * formats (set by driver) + * @formats_ptr: pointer to formats array or NULL + */ +struct drm_exynos_ioctl_ipp_get_caps { + __u32 ipp_id; + __u32 capabilities; + __u32 reserved; + __u32 formats_count; + __u64 formats_ptr; +}; + +enum drm_exynos_ipp_limit_type { + /* size (horizontal/vertial) limits, in pixels (min, max, alignment) */ + DRM_EXYNOS_IPP_LIMIT_TYPE_SIZE = 0x0001, + /* scale ratio (horizonta/vertial), 16.16 fixed point (min, max) */ + DRM_EXYNOS_IPP_LIMIT_TYPE_SCALE = 0x0002, + + /* image buffer area */ + DRM_EXYNOS_IPP_LIMIT_SIZE_BUFFER = 0x0001 << 16, + /* src/dst rectangle area */ + DRM_EXYNOS_IPP_LIMIT_SIZE_AREA = 0x0002 << 16, + /* src/dst rectangle area when rotation enabled */ + DRM_EXYNOS_IPP_LIMIT_SIZE_ROTATED = 0x0003 << 16, + + DRM_EXYNOS_IPP_LIMIT_TYPE_MASK = 0x000f, + DRM_EXYNOS_IPP_LIMIT_SIZE_MASK = 0x000f << 16, +}; + +struct drm_exynos_ipp_limit_val { + __u32 min; + __u32 max; + __u32 align; + __u32 reserved; +}; + +/** + * IPP module limitation. + * + * @type: limit type (see drm_exynos_ipp_limit_type enum) + * @reserved: padding + * @h: horizontal limits + * @v: vertical limits + */ +struct drm_exynos_ipp_limit { + __u32 type; + __u32 reserved; + struct drm_exynos_ipp_limit_val h; + struct drm_exynos_ipp_limit_val v; +}; + +/** + * Get IPP limits for given image format. + * + * @ipp_id: id of IPP module to query + * @fourcc: image format code (see DRM_FORMAT_* in drm_fourcc.h) + * @modifier: image format modifier (see DRM_FORMAT_MOD_* in drm_fourcc.h) + * @type: source/destination identifier (drm_exynos_ipp_format_flag enum) + * @limits_count: size of limits array (in entries) / number of filled entries + * (set by driver) + * @limits_ptr: pointer to limits array or NULL + */ +struct drm_exynos_ioctl_ipp_get_limits { + __u32 ipp_id; + __u32 fourcc; + __u64 modifier; + __u32 type; + __u32 limits_count; + __u64 limits_ptr; +}; + +enum drm_exynos_ipp_task_id { + /* buffer described by struct drm_exynos_ipp_task_buffer */ + DRM_EXYNOS_IPP_TASK_BUFFER = 0x0001, + /* rectangle described by struct drm_exynos_ipp_task_rect */ + DRM_EXYNOS_IPP_TASK_RECTANGLE = 0x0002, + /* transformation described by struct drm_exynos_ipp_task_transform */ + DRM_EXYNOS_IPP_TASK_TRANSFORM = 0x0003, + /* alpha configuration described by struct drm_exynos_ipp_task_alpha */ + DRM_EXYNOS_IPP_TASK_ALPHA = 0x0004, + + /* source image data (for buffer and rectangle chunks) */ + DRM_EXYNOS_IPP_TASK_TYPE_SOURCE = 0x0001 << 16, + /* destination image data (for buffer and rectangle chunks) */ + DRM_EXYNOS_IPP_TASK_TYPE_DESTINATION = 0x0002 << 16, +}; + +/** + * Memory buffer with image data. + * + * @id: must be DRM_EXYNOS_IPP_TASK_BUFFER + * other parameters are same as for AddFB2 generic DRM ioctl + */ +struct drm_exynos_ipp_task_buffer { + __u32 id; + __u32 fourcc; + __u32 width, height; + __u32 gem_id[4]; + __u32 offset[4]; + __u32 pitch[4]; + __u64 modifier; +}; + +/** + * Rectangle for processing. + * + * @id: must be DRM_EXYNOS_IPP_TASK_RECTANGLE + * @reserved: padding + * @x,@y: left corner in pixels + * @w,@h: width/height in pixels + */ +struct drm_exynos_ipp_task_rect { + __u32 id; + __u32 reserved; + __u32 x; + __u32 y; + __u32 w; + __u32 h; +}; + +/** + * Image tranformation description. + * + * @id: must be DRM_EXYNOS_IPP_TASK_TRANSFORM + * @rotation: DRM_MODE_ROTATE_* and DRM_MODE_REFLECT_* values + */ +struct drm_exynos_ipp_task_transform { + __u32 id; + __u32 rotation; +}; + +/** + * Image global alpha configuration for formats without alpha values. + * + * @id: must be DRM_EXYNOS_IPP_TASK_ALPHA + * @value: global alpha value (0-255) + */ +struct drm_exynos_ipp_task_alpha { + __u32 id; + __u32 value; +}; + +enum drm_exynos_ipp_flag { + /* generate DRM event after processing */ + DRM_EXYNOS_IPP_FLAG_EVENT = 0x01, + /* dry run, only check task parameters */ + DRM_EXYNOS_IPP_FLAG_TEST_ONLY = 0x02, + /* non-blocking processing */ + DRM_EXYNOS_IPP_FLAG_NONBLOCK = 0x04, +}; + +#define DRM_EXYNOS_IPP_FLAGS (DRM_EXYNOS_IPP_FLAG_EVENT |\ + DRM_EXYNOS_IPP_FLAG_TEST_ONLY | DRM_EXYNOS_IPP_FLAG_NONBLOCK) + +/** + * Perform image processing described by array of drm_exynos_ipp_task_* + * structures (parameters array). + * + * @ipp_id: id of IPP module to run the task + * @flags: bitmask of drm_exynos_ipp_flag values + * @reserved: padding + * @params_size: size of parameters array (in bytes) + * @params_ptr: pointer to parameters array or NULL + * @user_data: (optional) data for drm event + */ +struct drm_exynos_ioctl_ipp_commit { + __u32 ipp_id; + __u32 flags; + __u32 reserved; + __u32 params_size; + __u64 params_ptr; + __u64 user_data; +}; + #define DRM_EXYNOS_GEM_CREATE 0x00 #define DRM_EXYNOS_GEM_MAP 0x01 /* Reserved 0x03 ~ 0x05 for exynos specific gem ioctl */ @@ -147,6 +360,11 @@ struct drm_exynos_g2d_exec { #define DRM_EXYNOS_G2D_EXEC 0x22 /* Reserved 0x30 ~ 0x33 for obsolete Exynos IPP ioctls */ +/* IPP - Image Post Processing */ +#define DRM_EXYNOS_IPP_GET_RESOURCES 0x40 +#define DRM_EXYNOS_IPP_GET_CAPS 0x41 +#define DRM_EXYNOS_IPP_GET_LIMITS 0x42 +#define DRM_EXYNOS_IPP_COMMIT 0x43 #define DRM_IOCTL_EXYNOS_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + \ DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create) @@ -165,8 +383,20 @@ struct drm_exynos_g2d_exec { #define DRM_IOCTL_EXYNOS_G2D_EXEC DRM_IOWR(DRM_COMMAND_BASE + \ DRM_EXYNOS_G2D_EXEC, struct drm_exynos_g2d_exec) +#define DRM_IOCTL_EXYNOS_IPP_GET_RESOURCES DRM_IOWR(DRM_COMMAND_BASE + \ + DRM_EXYNOS_IPP_GET_RESOURCES, \ + struct drm_exynos_ioctl_ipp_get_res) +#define DRM_IOCTL_EXYNOS_IPP_GET_CAPS DRM_IOWR(DRM_COMMAND_BASE + \ + DRM_EXYNOS_IPP_GET_CAPS, struct drm_exynos_ioctl_ipp_get_caps) +#define DRM_IOCTL_EXYNOS_IPP_GET_LIMITS DRM_IOWR(DRM_COMMAND_BASE + \ + DRM_EXYNOS_IPP_GET_LIMITS, \ + struct drm_exynos_ioctl_ipp_get_limits) +#define DRM_IOCTL_EXYNOS_IPP_COMMIT DRM_IOWR(DRM_COMMAND_BASE + \ + DRM_EXYNOS_IPP_COMMIT, struct drm_exynos_ioctl_ipp_commit) + /* EXYNOS specific events */ #define DRM_EXYNOS_G2D_EVENT 0x80000000 +#define DRM_EXYNOS_IPP_EVENT 0x80000002 struct drm_exynos_g2d_event { struct drm_event base; @@ -177,6 +407,16 @@ struct drm_exynos_g2d_event { __u32 reserved; }; +struct drm_exynos_ipp_event { + struct drm_event base; + __u64 user_data; + __u32 tv_sec; + __u32 tv_usec; + __u32 ipp_id; + __u32 sequence; + __u64 reserved; +}; + #if defined(__cplusplus) } #endif diff --git a/include/drm-uapi/i915_drm.h b/include/drm-uapi/i915_drm.h index 16e452aa12d4..ab80759a2b9b 100644 --- a/include/drm-uapi/i915_drm.h +++ b/include/drm-uapi/i915_drm.h @@ -1456,9 +1456,52 @@ struct drm_i915_gem_context_param { #define I915_CONTEXT_MAX_USER_PRIORITY 1023 /* inclusive */ #define I915_CONTEXT_DEFAULT_PRIORITY 0 #define I915_CONTEXT_MIN_USER_PRIORITY -1023 /* inclusive */ + /* + * When using the following param, value should be a pointer to + * drm_i915_gem_context_param_sseu. + */ +#define I915_CONTEXT_PARAM_SSEU 0x7 __u64 value; }; +struct drm_i915_gem_context_param_sseu { + /* + * Engine class & instance to be configured or queried. + */ + __u16 class; + __u16 instance; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 rsvd1; + + /* + * Mask of slices to enable for the context. Valid values are a subset + * of the bitmask value returned for I915_PARAM_SLICE_MASK. + */ + __u64 slice_mask; + + /* + * Mask of subslices to enable for the context. Valid values are a + * subset of the bitmask value return by I915_PARAM_SUBSLICE_MASK. + */ + __u64 subslice_mask; + + /* + * Minimum/Maximum number of EUs to enable per subslice for the + * context. min_eus_per_subslice must be inferior or equal to + * max_eus_per_subslice. + */ + __u16 min_eus_per_subslice; + __u16 max_eus_per_subslice; + + /* + * Unused for now. Must be cleared to zero. + */ + __u32 rsvd2; +}; + enum drm_i915_oa_format { I915_OA_FORMAT_A13 = 1, /* HSW only */ I915_OA_FORMAT_A29, /* HSW only */ diff --git a/include/drm-uapi/msm_drm.h b/include/drm-uapi/msm_drm.h index bbbaffad772d..c06d0a5bdd80 100644 --- a/include/drm-uapi/msm_drm.h +++ b/include/drm-uapi/msm_drm.h @@ -201,10 +201,12 @@ struct drm_msm_gem_submit_bo { #define MSM_SUBMIT_NO_IMPLICIT 0x80000000 /* disable implicit sync */ #define MSM_SUBMIT_FENCE_FD_IN 0x40000000 /* enable input fence_fd */ #define MSM_SUBMIT_FENCE_FD_OUT 0x20000000 /* enable output fence_fd */ +#define MSM_SUBMIT_SUDO 0x10000000 /* run submitted cmds from RB */ #define MSM_SUBMIT_FLAGS ( \ MSM_SUBMIT_NO_IMPLICIT | \ MSM_SUBMIT_FENCE_FD_IN | \ MSM_SUBMIT_FENCE_FD_OUT | \ + MSM_SUBMIT_SUDO | \ 0) /* Each cmdstream submit consists of a table of buffers involved, and diff --git a/include/drm-uapi/tegra_drm.h b/include/drm-uapi/tegra_drm.h index 12f9bf848db1..6c07919c04e9 100644 --- a/include/drm-uapi/tegra_drm.h +++ b/include/drm-uapi/tegra_drm.h @@ -32,143 +32,615 @@ extern "C" { #define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) #define DRM_TEGRA_GEM_CREATE_BOTTOM_UP (1 << 1) +/** + * struct drm_tegra_gem_create - parameters for the GEM object creation IOCTL + */ struct drm_tegra_gem_create { + /** + * @size: + * + * The size, in bytes, of the buffer object to be created. + */ __u64 size; + + /** + * @flags: + * + * A bitmask of flags that influence the creation of GEM objects: + * + * DRM_TEGRA_GEM_CREATE_TILED + * Use the 16x16 tiling format for this buffer. + * + * DRM_TEGRA_GEM_CREATE_BOTTOM_UP + * The buffer has a bottom-up layout. + */ __u32 flags; + + /** + * @handle: + * + * The handle of the created GEM object. Set by the kernel upon + * successful completion of the IOCTL. + */ __u32 handle; }; +/** + * struct drm_tegra_gem_mmap - parameters for the GEM mmap IOCTL + */ struct drm_tegra_gem_mmap { + /** + * @handle: + * + * Handle of the GEM object to obtain an mmap offset for. + */ __u32 handle; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; + + /** + * @offset: + * + * The mmap offset for the given GEM object. Set by the kernel upon + * successful completion of the IOCTL. + */ __u64 offset; }; +/** + * struct drm_tegra_syncpt_read - parameters for the read syncpoint IOCTL + */ struct drm_tegra_syncpt_read { + /** + * @id: + * + * ID of the syncpoint to read the current value from. + */ __u32 id; + + /** + * @value: + * + * The current syncpoint value. Set by the kernel upon successful + * completion of the IOCTL. + */ __u32 value; }; +/** + * struct drm_tegra_syncpt_incr - parameters for the increment syncpoint IOCTL + */ struct drm_tegra_syncpt_incr { + /** + * @id: + * + * ID of the syncpoint to increment. + */ __u32 id; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; }; +/** + * struct drm_tegra_syncpt_wait - parameters for the wait syncpoint IOCTL + */ struct drm_tegra_syncpt_wait { + /** + * @id: + * + * ID of the syncpoint to wait on. + */ __u32 id; + + /** + * @thresh: + * + * Threshold value for which to wait. + */ __u32 thresh; + + /** + * @timeout: + * + * Timeout, in milliseconds, to wait. + */ __u32 timeout; + + /** + * @value: + * + * The new syncpoint value after the wait. Set by the kernel upon + * successful completion of the IOCTL. + */ __u32 value; }; #define DRM_TEGRA_NO_TIMEOUT (0xffffffff) +/** + * struct drm_tegra_open_channel - parameters for the open channel IOCTL + */ struct drm_tegra_open_channel { + /** + * @client: + * + * The client ID for this channel. + */ __u32 client; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; + + /** + * @context: + * + * The application context of this channel. Set by the kernel upon + * successful completion of the IOCTL. This context needs to be passed + * to the DRM_TEGRA_CHANNEL_CLOSE or the DRM_TEGRA_SUBMIT IOCTLs. + */ __u64 context; }; +/** + * struct drm_tegra_close_channel - parameters for the close channel IOCTL + */ struct drm_tegra_close_channel { + /** + * @context: + * + * The application context of this channel. This is obtained from the + * DRM_TEGRA_OPEN_CHANNEL IOCTL. + */ __u64 context; }; +/** + * struct drm_tegra_get_syncpt - parameters for the get syncpoint IOCTL + */ struct drm_tegra_get_syncpt { + /** + * @context: + * + * The application context identifying the channel for which to obtain + * the syncpoint ID. + */ __u64 context; + + /** + * @index: + * + * Index of the client syncpoint for which to obtain the ID. + */ __u32 index; + + /** + * @id: + * + * The ID of the given syncpoint. Set by the kernel upon successful + * completion of the IOCTL. + */ __u32 id; }; +/** + * struct drm_tegra_get_syncpt_base - parameters for the get wait base IOCTL + */ struct drm_tegra_get_syncpt_base { + /** + * @context: + * + * The application context identifying for which channel to obtain the + * wait base. + */ __u64 context; + + /** + * @syncpt: + * + * ID of the syncpoint for which to obtain the wait base. + */ __u32 syncpt; + + /** + * @id: + * + * The ID of the wait base corresponding to the client syncpoint. Set + * by the kernel upon successful completion of the IOCTL. + */ __u32 id; }; +/** + * struct drm_tegra_syncpt - syncpoint increment operation + */ struct drm_tegra_syncpt { + /** + * @id: + * + * ID of the syncpoint to operate on. + */ __u32 id; + + /** + * @incrs: + * + * Number of increments to perform for the syncpoint. + */ __u32 incrs; }; +/** + * struct drm_tegra_cmdbuf - structure describing a command buffer + */ struct drm_tegra_cmdbuf { + /** + * @handle: + * + * Handle to a GEM object containing the command buffer. + */ __u32 handle; + + /** + * @offset: + * + * Offset, in bytes, into the GEM object identified by @handle at + * which the command buffer starts. + */ __u32 offset; + + /** + * @words: + * + * Number of 32-bit words in this command buffer. + */ __u32 words; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; }; +/** + * struct drm_tegra_reloc - GEM object relocation structure + */ struct drm_tegra_reloc { struct { + /** + * @cmdbuf.handle: + * + * Handle to the GEM object containing the command buffer for + * which to perform this GEM object relocation. + */ __u32 handle; + + /** + * @cmdbuf.offset: + * + * Offset, in bytes, into the command buffer at which to + * insert the relocated address. + */ __u32 offset; } cmdbuf; struct { + /** + * @target.handle: + * + * Handle to the GEM object to be relocated. + */ __u32 handle; + + /** + * @target.offset: + * + * Offset, in bytes, into the target GEM object at which the + * relocated data starts. + */ __u32 offset; } target; + + /** + * @shift: + * + * The number of bits by which to shift relocated addresses. + */ __u32 shift; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; }; +/** + * struct drm_tegra_waitchk - wait check structure + */ struct drm_tegra_waitchk { + /** + * @handle: + * + * Handle to the GEM object containing a command stream on which to + * perform the wait check. + */ __u32 handle; + + /** + * @offset: + * + * Offset, in bytes, of the location in the command stream to perform + * the wait check on. + */ __u32 offset; + + /** + * @syncpt: + * + * ID of the syncpoint to wait check. + */ __u32 syncpt; + + /** + * @thresh: + * + * Threshold value for which to check. + */ __u32 thresh; }; +/** + * struct drm_tegra_submit - job submission structure + */ struct drm_tegra_submit { + /** + * @context: + * + * The application context identifying the channel to use for the + * execution of this job. + */ __u64 context; + + /** + * @num_syncpts: + * + * The number of syncpoints operated on by this job. This defines the + * length of the array pointed to by @syncpts. + */ __u32 num_syncpts; + + /** + * @num_cmdbufs: + * + * The number of command buffers to execute as part of this job. This + * defines the length of the array pointed to by @cmdbufs. + */ __u32 num_cmdbufs; + + /** + * @num_relocs: + * + * The number of relocations to perform before executing this job. + * This defines the length of the array pointed to by @relocs. + */ __u32 num_relocs; + + /** + * @num_waitchks: + * + * The number of wait checks to perform as part of this job. This + * defines the length of the array pointed to by @waitchks. + */ __u32 num_waitchks; + + /** + * @waitchk_mask: + * + * Bitmask of valid wait checks. + */ __u32 waitchk_mask; + + /** + * @timeout: + * + * Timeout, in milliseconds, before this job is cancelled. + */ __u32 timeout; + + /** + * @syncpts: + * + * A pointer to an array of &struct drm_tegra_syncpt structures that + * specify the syncpoint operations performed as part of this job. + * The number of elements in the array must be equal to the value + * given by @num_syncpts. + */ __u64 syncpts; + + /** + * @cmdbufs: + * + * A pointer to an array of &struct drm_tegra_cmdbuf structures that + * define the command buffers to execute as part of this job. The + * number of elements in the array must be equal to the value given + * by @num_syncpts. + */ __u64 cmdbufs; + + /** + * @relocs: + * + * A pointer to an array of &struct drm_tegra_reloc structures that + * specify the relocations that need to be performed before executing + * this job. The number of elements in the array must be equal to the + * value given by @num_relocs. + */ __u64 relocs; + + /** + * @waitchks: + * + * A pointer to an array of &struct drm_tegra_waitchk structures that + * specify the wait checks to be performed while executing this job. + * The number of elements in the array must be equal to the value + * given by @num_waitchks. + */ __u64 waitchks; - __u32 fence; /* Return value */ - __u32 reserved[5]; /* future expansion */ + /** + * @fence: + * + * The threshold of the syncpoint associated with this job after it + * has been completed. Set by the kernel upon successful completion of + * the IOCTL. This can be used with the DRM_TEGRA_SYNCPT_WAIT IOCTL to + * wait for this job to be finished. + */ + __u32 fence; + + /** + * @reserved: + * + * This field is reserved for future use. Must be 0. + */ + __u32 reserved[5]; }; #define DRM_TEGRA_GEM_TILING_MODE_PITCH 0 #define DRM_TEGRA_GEM_TILING_MODE_TILED 1 #define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2 +/** + * struct drm_tegra_gem_set_tiling - parameters for the set tiling IOCTL + */ struct drm_tegra_gem_set_tiling { - /* input */ + /** + * @handle: + * + * Handle to the GEM object for which to set the tiling parameters. + */ __u32 handle; + + /** + * @mode: + * + * The tiling mode to set. Must be one of: + * + * DRM_TEGRA_GEM_TILING_MODE_PITCH + * pitch linear format + * + * DRM_TEGRA_GEM_TILING_MODE_TILED + * 16x16 tiling format + * + * DRM_TEGRA_GEM_TILING_MODE_BLOCK + * 16Bx2 tiling format + */ __u32 mode; + + /** + * @value: + * + * The value to set for the tiling mode parameter. + */ __u32 value; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; }; +/** + * struct drm_tegra_gem_get_tiling - parameters for the get tiling IOCTL + */ struct drm_tegra_gem_get_tiling { - /* input */ + /** + * @handle: + * + * Handle to the GEM object for which to query the tiling parameters. + */ __u32 handle; - /* output */ + + /** + * @mode: + * + * The tiling mode currently associated with the GEM object. Set by + * the kernel upon successful completion of the IOCTL. + */ __u32 mode; + + /** + * @value: + * + * The tiling mode parameter currently associated with the GEM object. + * Set by the kernel upon successful completion of the IOCTL. + */ __u32 value; + + /** + * @pad: + * + * Structure padding that may be used in the future. Must be 0. + */ __u32 pad; }; #define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0) #define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP) +/** + * struct drm_tegra_gem_set_flags - parameters for the set flags IOCTL + */ struct drm_tegra_gem_set_flags { - /* input */ + /** + * @handle: + * + * Handle to the GEM object for which to set the flags. + */ __u32 handle; - /* output */ + + /** + * @flags: + * + * The flags to set for the GEM object. + */ __u32 flags; }; +/** + * struct drm_tegra_gem_get_flags - parameters for the get flags IOCTL + */ struct drm_tegra_gem_get_flags { - /* input */ + /** + * @handle: + * + * Handle to the GEM object for which to query the flags. + */ __u32 handle; - /* output */ + + /** + * @flags: + * + * The flags currently associated with the GEM object. Set by the + * kernel upon successful completion of the IOCTL. + */ __u32 flags; }; @@ -193,7 +665,7 @@ struct drm_tegra_gem_get_flags { #define DRM_IOCTL_TEGRA_SYNCPT_INCR DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_INCR, struct drm_tegra_syncpt_incr) #define DRM_IOCTL_TEGRA_SYNCPT_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SYNCPT_WAIT, struct drm_tegra_syncpt_wait) #define DRM_IOCTL_TEGRA_OPEN_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_OPEN_CHANNEL, struct drm_tegra_open_channel) -#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_open_channel) +#define DRM_IOCTL_TEGRA_CLOSE_CHANNEL DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_CLOSE_CHANNEL, struct drm_tegra_close_channel) #define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) #define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) #define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) diff --git a/include/drm-uapi/vc4_drm.h b/include/drm-uapi/vc4_drm.h index 4117117b4204..31f50de39acb 100644 --- a/include/drm-uapi/vc4_drm.h +++ b/include/drm-uapi/vc4_drm.h @@ -183,10 +183,17 @@ struct drm_vc4_submit_cl { /* ID of the perfmon to attach to this job. 0 means no perfmon. */ __u32 perfmonid; - /* Unused field to align this struct on 64 bits. Must be set to 0. - * If one ever needs to add an u32 field to this struct, this field - * can be used. + /* Syncobj handle to wait on. If set, processing of this render job + * will not start until the syncobj is signaled. 0 means ignore. */ + __u32 in_sync; + + /* Syncobj handle to export fence to. If set, the fence in the syncobj + * will be replaced with a fence that signals upon completion of this + * render job. 0 means ignore. + */ + __u32 out_sync; + __u32 pad2; }; diff --git a/include/drm-uapi/virtgpu_drm.h b/include/drm-uapi/virtgpu_drm.h index 91a31ffed828..9a781f0611df 100644 --- a/include/drm-uapi/virtgpu_drm.h +++ b/include/drm-uapi/virtgpu_drm.h @@ -63,6 +63,7 @@ struct drm_virtgpu_execbuffer { }; #define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */ +#define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2 /* do we have the capset fix */ struct drm_virtgpu_getparam { __u64 param; From patchwork Wed Sep 5 14:25:44 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 10588989 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1A1A5112B for ; Wed, 5 Sep 2018 14:26:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 02EBE2821F for ; Wed, 5 Sep 2018 14:26:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EAD08286BD; Wed, 5 Sep 2018 14:25:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 6129928417 for ; Wed, 5 Sep 2018 14:25:58 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 984106E4C6; Wed, 5 Sep 2018 14:25:56 +0000 (UTC) X-Original-To: Intel-gfx@lists.freedesktop.org Delivered-To: Intel-gfx@lists.freedesktop.org Received: from mail-wr1-x444.google.com (mail-wr1-x444.google.com [IPv6:2a00:1450:4864:20::444]) by gabe.freedesktop.org (Postfix) with ESMTPS id 805F46E4C5 for ; Wed, 5 Sep 2018 14:25:53 +0000 (UTC) Received: by mail-wr1-x444.google.com with SMTP id 20-v6so7859486wrb.12 for ; Wed, 05 Sep 2018 07:25:53 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bsjhfx/H5OYBO9Sig9fOqj7nHnW9yrP+K/ypGbE/HXk=; b=KVEPHcg6fbFxBAhmA0lhJ7LkGPKqIvPpiAU/xZxA41defaci2VViPzkhZQ1NQMgOeK W83MJI5VFazG1OLc2UwiNF1QrfXOAXZXpRBEZFmh/V6HruLqonz+90+JtVW+SgkSToGF FveaFe+ExXFp0dVqDB17gDLrXxbWKCiUXDE6OTmMlHoeseY1n+3RAEePs7451iq/WxLM 45JXEarkBVzQKva+iYMahvaCBDMaIBevWZ/cuzxxw8eeozymvzk+TcVw63GUSOlG6rA4 slsf4ko8W4yoRCggdLiXBgzHOmnrPY8ul7soiRe7aLJLKN9qB5MS3mXJwDNdq44msiGN Iy8Q== X-Gm-Message-State: APzg51CDkhy/fstbr5VG+9sVOdGcSftEnwiS28kkYLddFe79ZiTXKM7D 0DmyLdNrat0xMwuoWqLMyQxctA== X-Google-Smtp-Source: ANB0VdbDa4Q+d2D/t2Jw2QEY9EKGNdgqq/J4CCqnIBn11Ce3mKyIqYdFb1tnZtg2ab7s1EaDaQ8nhA== X-Received: by 2002:adf:b112:: with SMTP id l18-v6mr27998597wra.101.1536157551564; Wed, 05 Sep 2018 07:25:51 -0700 (PDT) Received: from localhost.localdomain ([95.144.165.37]) by smtp.gmail.com with ESMTPSA id z13sm2289763wrw.19.2018.09.05.07.25.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 05 Sep 2018 07:25:51 -0700 (PDT) From: Tvrtko Ursulin X-Google-Original-From: Tvrtko Ursulin To: igt-dev@lists.freedesktop.org Date: Wed, 5 Sep 2018 15:25:44 +0100 Message-Id: <20180905142544.3381-3-tvrtko.ursulin@linux.intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180905142544.3381-1-tvrtko.ursulin@linux.intel.com> References: <20180905142544.3381-1-tvrtko.ursulin@linux.intel.com> MIME-Version: 1.0 Subject: [Intel-gfx] [PATH i-g-t 2/2] tests: add slice power programming test X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Intel-gfx@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP From: Lionel Landwerlin Verifies that the kernel programs slices correctly based by reading the value of PWR_CLK_STATE register or MI_SET_PREDICATE on platforms before Cannonlake. v2: Add subslice tests (Lionel) Use MI_SET_PREDICATE for further verification when available (Lionel) v3: Rename to gem_ctx_rpcs (Lionel) v4: Update kernel API (Lionel) Add 0 value test (Lionel) Exercise invalid values (Lionel) v5: Add perf tests (Lionel) v6: Add new sysfs entry tests (Lionel) v7: Test rsvd fields Update for kernel series changes v8: Drop test_no_sseu_support() test (Kelvin) Drop drm_intel_*() apis (Chris) v9: by Chris: Drop all do_ioctl/do_ioctl_err() Use gem_context_[gs]et_param() Use gem_read() instead of mapping memory by Lionel: Test dynamic sseu on/off more Tvrtko Ursulin: v10: * Various style tweaks and refactorings. * New test coverage. Signed-off-by: Lionel Landwerlin Signed-off-by: Tvrtko Ursulin --- tests/Makefile.am | 1 + tests/Makefile.sources | 1 + tests/gem_ctx_param.c | 4 +- tests/gem_ctx_sseu.c | 1040 ++++++++++++++++++++++++++++++++++++++++ tests/meson.build | 7 + 5 files changed, 1052 insertions(+), 1 deletion(-) create mode 100644 tests/gem_ctx_sseu.c diff --git a/tests/Makefile.am b/tests/Makefile.am index ee5a7c5e83b8..6b67bd2cc17a 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -107,6 +107,7 @@ gem_close_race_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) gem_close_race_LDADD = $(LDADD) -lpthread gem_ctx_thrash_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) gem_ctx_thrash_LDADD = $(LDADD) -lpthread +gem_ctx_sseu_LDADD = $(LDADD) $(top_builddir)/lib/libigt_perf.la gem_exec_parallel_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) gem_exec_parallel_LDADD = $(LDADD) -lpthread gem_fence_thrash_CFLAGS = $(AM_CFLAGS) $(THREAD_CFLAGS) diff --git a/tests/Makefile.sources b/tests/Makefile.sources index c84933f1d971..f8f2c8d67d72 100644 --- a/tests/Makefile.sources +++ b/tests/Makefile.sources @@ -56,6 +56,7 @@ TESTS_progs = \ gem_ctx_exec \ gem_ctx_isolation \ gem_ctx_param \ + gem_ctx_sseu \ gem_ctx_switch \ gem_ctx_thrash \ gem_double_irq_loop \ diff --git a/tests/gem_ctx_param.c b/tests/gem_ctx_param.c index c46fd709b0d7..af1afeaa2f2f 100644 --- a/tests/gem_ctx_param.c +++ b/tests/gem_ctx_param.c @@ -294,11 +294,13 @@ igt_main set_priority(fd); } + /* I915_CONTEXT_PARAM_SSEU tests are located in gem_ctx_sseu.c */ + /* NOTE: This testcase intentionally tests for the next free parameter * to catch ABI extensions. Don't "fix" this testcase without adding all * the tests for the new param first. */ - arg.param = I915_CONTEXT_PARAM_PRIORITY + 1; + arg.param = I915_CONTEXT_PARAM_SSEU + 1; igt_subtest("invalid-param-get") { arg.ctx_id = ctx; diff --git a/tests/gem_ctx_sseu.c b/tests/gem_ctx_sseu.c new file mode 100644 index 000000000000..1f816818e3de --- /dev/null +++ b/tests/gem_ctx_sseu.c @@ -0,0 +1,1040 @@ +/* + * Copyright © 2017-2018 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + * Authors: + * Lionel Landwerlin + * + */ + +#include "igt.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "igt_dummyload.h" +#include "igt_perf.h" +#include "igt_sysfs.h" +#include "ioctl_wrappers.h" + +IGT_TEST_DESCRIPTION("Test context render powergating programming."); + +#define MI_STORE_REGISTER_MEM (0x24 << 23) + +#define MI_SET_PREDICATE (0x1 << 23) +#define MI_SET_PREDICATE_NOOP_NEVER (0) +#define MI_SET_PREDICATE_NOOP_RESULT2_CLEAR (1) +#define MI_SET_PREDICATE_NOOP_RESULT2_SET (2) +#define MI_SET_PREDICATE_NOOP_RESULT_CLEAR (3) +#define MI_SET_PREDICATE_NOOP_RESULT_SET (4) +#define MI_SET_PREDICATE_1_SLICES (5) +#define MI_SET_PREDICATE_2_SLICES (6) +#define MI_SET_PREDICATE_3_SLICES (7) + +#define GEN8_R_PWR_CLK_STATE 0x20C8 +#define GEN8_RPCS_ENABLE (1 << 31) +#define GEN8_RPCS_S_CNT_ENABLE (1 << 18) +#define GEN8_RPCS_S_CNT_SHIFT 15 +#define GEN8_RPCS_S_CNT_MASK (0x7 << GEN8_RPCS_S_CNT_SHIFT) +#define GEN11_RPCS_S_CNT_SHIFT 12 +#define GEN11_RPCS_S_CNT_MASK (0x3f << GEN11_RPCS_S_CNT_SHIFT) +#define GEN8_RPCS_SS_CNT_ENABLE (1 << 11) +#define GEN8_RPCS_SS_CNT_SHIFT 8 +#define GEN8_RPCS_SS_CNT_MASK (0x7 << GEN8_RPCS_SS_CNT_SHIFT) +#define GEN8_RPCS_EU_MAX_SHIFT 4 +#define GEN8_RPCS_EU_MAX_MASK (0xf << GEN8_RPCS_EU_MAX_SHIFT) +#define GEN8_RPCS_EU_MIN_SHIFT 0 +#define GEN8_RPCS_EU_MIN_MASK (0xf << GEN8_RPCS_EU_MIN_SHIFT) + +#define RCS_TIMESTAMP (0x2000 + 0x358) + +static unsigned int __intel_gen__, __intel_devid__; +static uint64_t __slice_mask__, __subslice_mask__; +static unsigned int __slice_count__, __subslice_count__; + +static uint64_t mask_minus_one(uint64_t mask) +{ + unsigned int i; + + for (i = 0; i < (sizeof(mask) * 8 - 1); i++) { + if ((1ULL << i) & mask) + return mask & ~(1ULL << i); + } + + igt_assert(0); + return 0; +} + +static uint64_t mask_plus_one(uint64_t mask) +{ + unsigned int i; + + for (i = 0; i < (sizeof(mask) * 8 - 1); i++) { + if (((1ULL << i) & mask) == 0) + return mask | (1ULL << i); + } + + igt_assert(0); + return 0; +} + +static uint64_t mask_minus(uint64_t mask, int n) +{ + unsigned int i; + + for (i = 0; i < n; i++) + mask = mask_minus_one(mask); + + return mask; +} + +static uint64_t mask_plus(uint64_t mask, int n) +{ + unsigned int i; + + for (i = 0; i < n; i++) + mask = mask_plus_one(mask); + + return mask; +} + +static uint32_t * +fill_relocation(uint32_t *batch, + struct drm_i915_gem_relocation_entry *reloc, + uint32_t gem_handle, uint32_t delta, /* in bytes */ + uint32_t offset, /* in dwords */ + uint32_t read_domains, uint32_t write_domains) +{ + reloc->target_handle = gem_handle; + reloc->delta = delta; + reloc->offset = offset * sizeof(uint32_t); + reloc->presumed_offset = 0; + reloc->read_domains = read_domains; + reloc->write_domain = write_domains; + + *batch++ = delta; + *batch++ = 0; + + return batch; +} + + +static uint32_t +read_rpcs_reg(int fd, uint32_t ctx, uint32_t expected_slices, igt_spin_t *spin) +{ + struct drm_i915_gem_execbuffer2 execbuf = { }; + struct drm_i915_gem_relocation_entry relocs[2]; + struct drm_i915_gem_exec_object2 obj[2]; + uint32_t *batch, *b, data[2]; + unsigned int n_relocs = 0; + uint32_t rpcs; + + memset(obj, 0, sizeof(obj)); + obj[0].handle = gem_create(fd, 4096); + obj[1].handle = gem_create(fd, 4096); + + batch = b = + gem_mmap__cpu(fd, obj[1].handle, 0, 4096, PROT_READ | PROT_WRITE); + + if (expected_slices != 0 && __intel_gen__ < 10) + *b++ = MI_SET_PREDICATE | (1 - 1) | + (MI_SET_PREDICATE_1_SLICES + expected_slices - 1); + + *b++ = MI_STORE_REGISTER_MEM | (4 - 2); + *b++ = RCS_TIMESTAMP; + b = fill_relocation(b, &relocs[n_relocs++], obj[0].handle, + 0, b - batch, + I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); + + *b++ = MI_STORE_REGISTER_MEM | (4 - 2); + *b++ = GEN8_R_PWR_CLK_STATE; + b = fill_relocation(b, &relocs[n_relocs++], obj[0].handle, + 4, b - batch, + I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); + + if (expected_slices != 0 && __intel_gen__ < 10) + *b++ = MI_SET_PREDICATE | (1 - 1) | MI_SET_PREDICATE_NOOP_NEVER; + + *b++ = MI_BATCH_BUFFER_END; + + gem_munmap(batch, 4096); + + obj[1].relocation_count = n_relocs; + obj[1].relocs_ptr = to_user_pointer(relocs); + + execbuf.buffers_ptr = to_user_pointer(obj); + execbuf.buffer_count = ARRAY_SIZE(obj); + i915_execbuffer2_set_context_id(execbuf, ctx); + + gem_execbuf(fd, &execbuf); + + if (spin) + igt_spin_batch_end(spin); + + gem_read(fd, obj[0].handle, 0, data, sizeof(data)); + + rpcs = data[1]; + + igt_debug("rcs_timestamp=0x%x rpcs=0x%x\n", data[0], data[1]); + + gem_close(fd, obj[0].handle); + gem_close(fd, obj[1].handle); + + return rpcs; +} + +typedef uint32_t (*read_slice_count_f)(int fd, uint32_t ctx, uint32_t expected, + igt_spin_t *spin); + +static read_slice_count_f __read_slice_count; + +static uint32_t +read_slice_count(int fd, uint32_t ctx, uint32_t expected_slice_count) +{ + return __read_slice_count(fd, ctx, expected_slice_count, NULL); +} + +static uint32_t +gen8_read_slice_count(int fd, uint32_t ctx, uint32_t expected_slice_count, + igt_spin_t *spin) +{ + return (read_rpcs_reg(fd, ctx, expected_slice_count, spin) & + GEN8_RPCS_S_CNT_MASK) >> GEN8_RPCS_S_CNT_SHIFT; +} + +static uint32_t +gen11_read_slice_count(int fd, uint32_t ctx, uint32_t expected_slice_count, + igt_spin_t *spin) +{ + return (read_rpcs_reg(fd, ctx, expected_slice_count, spin) & + GEN11_RPCS_S_CNT_MASK) >> GEN11_RPCS_S_CNT_SHIFT; +} + +static uint32_t +read_subslice_count(int fd, uint32_t ctx) +{ + return (read_rpcs_reg(fd, ctx, 0, NULL) & GEN8_RPCS_SS_CNT_MASK) >> + GEN8_RPCS_SS_CNT_SHIFT; +} + +static bool +kernel_has_per_context_sseu_support(int fd) +{ + struct drm_i915_gem_context_param_sseu sseu = { }; + struct drm_i915_gem_context_param arg = + { .param = I915_CONTEXT_PARAM_SSEU, + .value = to_user_pointer(&sseu) }; + + return __gem_context_get_param(fd, &arg) == 0; +} + +static void +context_get_sseu_masks(int fd, uint32_t ctx, + uint64_t *slice_mask, + uint64_t *subslice_mask) +{ + struct drm_i915_gem_context_param_sseu sseu = { }; + struct drm_i915_gem_context_param arg = + { .param = I915_CONTEXT_PARAM_SSEU, + .ctx_id = ctx, + .size = sizeof(sseu), + .value = to_user_pointer(&sseu) }; + + gem_context_get_param(fd, &arg); + + if (slice_mask) + *slice_mask = sseu.slice_mask; + + if (subslice_mask) + *subslice_mask = sseu.subslice_mask; +} + +static void +context_set_slice_mask(int fd, uint32_t ctx, uint64_t slice_mask) +{ + struct drm_i915_gem_context_param_sseu sseu = { }; + struct drm_i915_gem_context_param arg = + { .param = I915_CONTEXT_PARAM_SSEU, + .ctx_id = ctx, + .size = sizeof(sseu), + .value = to_user_pointer(&sseu) }; + + gem_context_get_param(fd, &arg); + sseu.slice_mask = slice_mask; + gem_context_set_param(fd, &arg); +} + +static void +context_set_subslice_mask(int fd, uint32_t ctx, uint64_t subslice_mask) +{ + struct drm_i915_gem_context_param_sseu sseu = { }; + struct drm_i915_gem_context_param arg = + { .param = I915_CONTEXT_PARAM_SSEU, + .ctx_id = ctx, + .size = sizeof(sseu), + .value = to_user_pointer(&sseu) }; + + gem_context_get_param(fd, &arg); + sseu.subslice_mask = subslice_mask; + gem_context_set_param(fd, &arg); +} + +/* + * Verify that we can program the slice count. + */ +static void +test_slice_pg(int fd, uint32_t pg_slice_count) +{ + uint64_t pg_slice_mask = mask_minus(__slice_mask__, pg_slice_count); + unsigned int slice_count = __slice_count__ - pg_slice_count; + uint64_t slice_mask; + uint32_t ctx; + + igt_assert_eq(slice_count, __builtin_popcount(pg_slice_mask)); + + ctx = gem_context_create(fd); + context_set_slice_mask(fd, ctx, pg_slice_mask); + context_get_sseu_masks(fd, ctx, &slice_mask, NULL); + igt_assert_eq(pg_slice_mask, slice_mask); + + /* + * Test false positives with predicates (only available on + * before Gen10). + */ + if (__intel_gen__ < 10) + igt_assert_eq(read_slice_count(fd, ctx, __slice_count__), 0); + + igt_assert_eq(read_slice_count(fd, ctx, 0), slice_count); + + gem_context_destroy(fd, ctx); +} + +/* + * Verify that we can program the subslice count. + */ +static void +test_subslice_pg(int fd, int pg_subslice_count) +{ + uint64_t pg_subslice_mask = + mask_minus(__subslice_mask__, pg_subslice_count); + unsigned int subslice_count = __subslice_count__ - pg_subslice_count; + uint64_t subslice_mask; + uint32_t ctx; + + igt_assert_eq(subslice_count, __builtin_popcount(pg_subslice_mask)); + + ctx = gem_context_create(fd); + context_set_subslice_mask(fd, ctx, pg_subslice_mask); + context_get_sseu_masks(fd, ctx, NULL, &subslice_mask); + igt_assert_eq(pg_subslice_mask, subslice_mask); + + igt_assert_eq(read_subslice_count(fd, ctx), subslice_count); + + gem_context_destroy(fd, ctx); +} + +static bool has_engine(int fd, unsigned int class, unsigned int instance) +{ + int pmu = perf_i915_open(I915_PMU_ENGINE_BUSY(class, instance)); + + if (pmu >= 0) + close(pmu); + + return pmu >= 0; +} + +static bool +engine_supports_sseu(int fd, unsigned int class, unsigned int instance) +{ + return __intel_gen__ >= 8 && + class == I915_ENGINE_CLASS_RENDER && instance == 0 ? + true : false; +} + +/* + * Verify that invalid engines are rejected and valid ones are accepted. + */ +static void test_engines(int fd) +{ + struct drm_i915_gem_context_param_sseu sseu = { }; + struct drm_i915_gem_context_param arg = + { .param = I915_CONTEXT_PARAM_SSEU, + .ctx_id = gem_context_create(fd), + .size = sizeof(sseu), + .value = to_user_pointer(&sseu) }; + unsigned int class, instance; + int last_with_engines; + + /* get_param */ + + sseu.instance = -1; /* Assumed invalid. */ + igt_assert_eq(__gem_context_get_param(fd, &arg), -EINVAL); + + sseu.class = I915_ENGINE_CLASS_INVALID; /* Both invalid. */ + igt_assert_eq(__gem_context_get_param(fd, &arg), -EINVAL); + + sseu.instance = 0; /* Class invalid. */ + igt_assert_eq(__gem_context_get_param(fd, &arg), -EINVAL); + sseu.class = I915_ENGINE_CLASS_RENDER; + + last_with_engines = -1; + for (class = 0; class < ~0; class++) { + for (instance = 0; instance < ~0; instance++) { + int ret; + + sseu.class = class; + sseu.instance = instance; + + ret = __gem_context_get_param(fd, &arg); + + if (has_engine(fd, class, instance)) { + igt_assert_eq(ret, 0); + last_with_engines = class; + } else { + igt_assert_eq(ret, -EINVAL); + if (instance > 8) /* Skip over some instance holes. */ + break; + } + } + + if (class - last_with_engines > 8) /* Skip over some class holes. */ + break; + } + + /* + * Get some proper values before trying to reprogram them onto + * an invalid engine. + */ + sseu.class = 0; + sseu.instance = 0; + gem_context_get_param(fd, &arg); + + /* set_param */ + + sseu.instance = -1; /* Assumed invalid. */ + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + + sseu.class = I915_ENGINE_CLASS_INVALID; /* Both invalid. */ + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + + sseu.instance = 0; /* Class invalid. */ + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + + last_with_engines = -1; + for (class = 0; class < ~0; class++) { + for (instance = 0; instance < ~0; instance++) { + int ret; + + sseu.class = class; + sseu.instance = instance; + + ret = __gem_context_set_param(fd, &arg); + + if (has_engine(fd, class, instance)) { + if (engine_supports_sseu(fd, class, instance)) + igt_assert_eq(ret, 0); + else + igt_assert_eq(ret, -ENODEV); + + last_with_engines = class; + } else { + igt_assert_eq(ret, -EINVAL); + if (instance > 8) /* Skip over some instance holes. */ + break; + } + } + + if (class - last_with_engines > 8) /* Skip over some class holes. */ + break; + } + + gem_context_destroy(fd, arg.ctx_id); +} + +/* + * Verify that invalid arguments are rejected. + */ +static void +test_invalid_args(int fd) +{ + struct drm_i915_gem_context_param_sseu default_sseu = { }; + struct drm_i915_gem_context_param_sseu sseu = { }; + struct drm_i915_gem_context_param arg = + { .param = I915_CONTEXT_PARAM_SSEU, + .ctx_id = gem_context_create(fd), + }; + unsigned int sz; + + /* get param */ + + /* Invalid size. */ + arg.size = 1; + igt_assert_eq(__gem_context_get_param(fd, &arg), -EINVAL); + + /* Query size. */ + arg.size = 0; + igt_assert_eq(__gem_context_get_param(fd, &arg), 0); + sz = arg.size; + + /* Bad pointer. */ + igt_assert_eq(__gem_context_get_param(fd, &arg), -EFAULT); + arg.value = to_user_pointer(&sseu); + + /* Fetch the device defaults. */ + arg.value = to_user_pointer(&default_sseu); + gem_context_get_param(fd, &arg); + + /* set param */ + + /* Invalid sizes. */ + arg.size = 1; + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + + arg.size = 0; + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + arg.size = sz; + + /* Bad pointer. */ + arg.value = 0; + igt_assert_eq(__gem_context_set_param(fd, &arg), -EFAULT); + arg.value = to_user_pointer(&sseu); + + gem_context_destroy(fd, arg.ctx_id); +} + +/* + * Verify that invalid SSEU values are rejected. + */ +static void +test_invalid_sseu(int fd) +{ + struct drm_i915_gem_context_param_sseu default_sseu = { }; + struct drm_i915_gem_context_param_sseu sseu = { }; + struct drm_i915_gem_context_param arg = + { .param = I915_CONTEXT_PARAM_SSEU, + .ctx_id = gem_context_create(fd), + .size = sizeof(sseu), + }; + unsigned int i; + + /* Fetch the device defaults. */ + arg.value = to_user_pointer(&default_sseu); + gem_context_get_param(fd, &arg); + + arg.value = to_user_pointer(&sseu); + + /* Try all slice masks known to be invalid. */ + sseu = default_sseu; + for (i = 1; i <= (8 - __slice_count__); i++) { + sseu.slice_mask = mask_plus(__slice_mask__, i); + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + } + + /* 0 slices. */ + sseu.slice_mask = 0; + igt_assert_eq(-EINVAL, __gem_context_set_param(fd, &arg)); + + /* Try all subslice masks known to be invalid. */ + sseu = default_sseu; + for (i = 1; i <= (8 - __subslice_count__); i++) { + sseu.subslice_mask = mask_plus(__subslice_mask__, i); + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + } + + /* 0 subslices. */ + sseu.subslice_mask = 0; + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + + /* Try number of EUs superior to the max available. */ + sseu = default_sseu; + sseu.min_eus_per_subslice = default_sseu.max_eus_per_subslice + 1; + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + + sseu = default_sseu; + sseu.max_eus_per_subslice = default_sseu.max_eus_per_subslice + 1; + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + + /* Try to program 0 max EUs. */ + sseu = default_sseu; + sseu.max_eus_per_subslice = 0; + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + + /* Min > max */ + sseu = default_sseu; + sseu.min_eus_per_subslice = sseu.max_eus_per_subslice; + sseu.max_eus_per_subslice = 1; + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + + if (__intel_gen__ != 11) + goto out; + + /* Subset of subslices but slice mask greater than one. */ + if (__slice_count__ > 1) { + sseu = default_sseu; + sseu.subslice_mask = mask_minus_one(sseu.subslice_mask); + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + } + + /* Odd subslices above four. */ + sseu = default_sseu; + sseu.slice_mask = 0x1; + sseu.subslice_mask = mask_minus_one(sseu.subslice_mask); + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + + /* More than half subslices with one slice. */ + sseu = default_sseu; + sseu.slice_mask = 0x1; + sseu.subslice_mask = mask_minus(sseu.subslice_mask, + __subslice_count__ / 2 - 1); + igt_assert_eq(__gem_context_set_param(fd, &arg), -EINVAL); + +out: + gem_context_destroy(fd, arg.ctx_id); +} + +/* Verify that the kernel returns a correct error value on Gen < 8. */ +static void +init_contexts(int fd, uint32_t *ctx, unsigned int num, + uint64_t mask0, uint64_t mask1) +{ + unsigned int i; + + igt_assert_eq(num, 2); + + for (i = 0; i < num; i++) + ctx[i] = gem_context_create(fd); + + context_set_slice_mask(fd, ctx[0], mask0); + context_set_slice_mask(fd, ctx[1], mask1); +} + +/* + * Verify that powergating settings are put on hold while i915/perf is + * active. + */ +static void +test_perf_oa(int fd) +{ + uint64_t properties[] = { + /* Include OA reports in samples */ + DRM_I915_PERF_PROP_SAMPLE_OA, true, + + /* OA unit configuration */ + DRM_I915_PERF_PROP_OA_METRICS_SET, 1, /* test metric */ + DRM_I915_PERF_PROP_OA_FORMAT, I915_OA_FORMAT_A32u40_A4u32_B8_C8, + DRM_I915_PERF_PROP_OA_EXPONENT, 20, + }; + struct drm_i915_perf_open_param param = { + .flags = I915_PERF_FLAG_FD_CLOEXEC | + I915_PERF_FLAG_FD_NONBLOCK, + .num_properties = ARRAY_SIZE(properties) / 2, + .properties_ptr = to_user_pointer(properties), + }; + uint64_t pg_slice_mask = mask_minus_one(__slice_mask__); + unsigned int slice_count = __slice_count__ - 1; + uint32_t ctx[2]; + unsigned int i; + int perf_fd; + + init_contexts(fd, ctx, ARRAY_SIZE(ctx), __slice_mask__, pg_slice_mask); + + /* + * Test false positives with predicates (only available on + * before Gen10). + */ + if (__intel_gen__ < 10) + igt_assert_eq(read_slice_count(fd, ctx[1], __slice_count__), + 0); + + igt_assert_eq(read_slice_count(fd, ctx[0], 0), __slice_count__); + igt_assert_eq(read_slice_count(fd, ctx[1], 0), slice_count); + + /* + * Now open i915/perf and verify that all contexts have been + * reconfigured to the device's default. + */ + perf_fd = igt_ioctl(fd, DRM_IOCTL_I915_PERF_OPEN, ¶m); + igt_assert_fd(perf_fd); + + if (__intel_gen__ != 11) { + if (__intel_gen__ < 10) + igt_assert_eq(read_slice_count(fd, ctx[1], slice_count), + 0); + + igt_assert_eq(read_slice_count(fd, ctx[0], 0), __slice_count__); + igt_assert_eq(read_slice_count(fd, ctx[1], 0), __slice_count__); + } else { + igt_assert_eq(read_slice_count(fd, ctx[0], 0), 1); + igt_assert_eq(read_slice_count(fd, ctx[1], 0), 1); + igt_assert_eq(read_subslice_count(fd, ctx[0]), + __subslice_count__ / 2); + igt_assert_eq(read_subslice_count(fd, ctx[1]), + __subslice_count__ / 2); + } + + close(perf_fd); + + /* + * After closing the perf stream, configurations should be + * back to the programmed values. + */ + if (__intel_gen__ < 10) + igt_assert_eq(read_slice_count(fd, ctx[1], __slice_count__), 0); + igt_assert_eq(read_slice_count(fd, ctx[0], 0), __slice_count__); + igt_assert_eq(read_slice_count(fd, ctx[1], 0), slice_count); + + for (i = 0; i < ARRAY_SIZE(ctx); i++) + gem_context_destroy(fd, ctx[i]); + + /* + * Open i915/perf first and verify that all contexts created + * afterward are configured to the device's default. + */ + perf_fd = igt_ioctl(fd, DRM_IOCTL_I915_PERF_OPEN, ¶m); + igt_assert_fd(perf_fd); + + init_contexts(fd, ctx, ARRAY_SIZE(ctx), __slice_mask__, pg_slice_mask); + + /* + * Check the device's default values, despite setting + * otherwise. + */ + if (__intel_gen__ != 11) { + if (__intel_gen__ < 10) + igt_assert_eq(read_slice_count(fd, ctx[1], + slice_count), 0); + + igt_assert_eq(read_slice_count(fd, ctx[0], 0), __slice_count__); + igt_assert_eq(read_slice_count(fd, ctx[1], 0), __slice_count__); + } else { + igt_assert_eq(read_slice_count(fd, ctx[0], 0), 1); + igt_assert_eq(read_slice_count(fd, ctx[1], 0), 1); + igt_assert_eq(read_subslice_count(fd, ctx[0]), + __subslice_count__ / 2); + igt_assert_eq(read_subslice_count(fd, ctx[1]), + __subslice_count__ / 2); + } + + close(perf_fd); + + /* + * After closing the perf stream, configurations should be + * back to the programmed values. + */ + if (__intel_gen__ < 10) + igt_assert_eq(read_slice_count(fd, ctx[1], __slice_count__), + 0); + + igt_assert_eq(read_slice_count(fd, ctx[0], 0), __slice_count__); + igt_assert_eq(read_slice_count(fd, ctx[1], 0), slice_count); + + for (i = 0; i < ARRAY_SIZE(ctx); i++) + gem_context_destroy(fd, ctx[i]); +} + +static igt_spin_t * __spin_poll(int fd, uint32_t ctx, unsigned long flags) +{ + struct igt_spin_factory opts = { + .ctx = ctx, + .engine = flags, + }; + + if (gem_can_store_dword(fd, flags)) + opts.flags |= IGT_SPIN_POLL_RUN; + + return __igt_spin_batch_factory(fd, &opts); +} + +static unsigned long __spin_wait(int fd, igt_spin_t *spin) +{ + struct timespec start = { }; + + igt_nsec_elapsed(&start); + + if (spin->running) { + unsigned long timeout = 0; + + while (!READ_ONCE(*spin->running)) { + unsigned long t = igt_nsec_elapsed(&start); + + if ((t - timeout) > 250e6) { + timeout = t; + igt_warn("Spinner not running after %.2fms\n", + (double)t / 1e6); + } + } + } else { + igt_debug("__spin_wait - usleep mode\n"); + usleep(500e3); /* Better than nothing! */ + } + + return igt_nsec_elapsed(&start); +} + +static igt_spin_t * __spin_sync(int fd, uint32_t ctx, unsigned long flags) +{ + igt_spin_t *spin = __spin_poll(fd, ctx, flags); + + __spin_wait(fd, spin); + + return spin; +} + +static uint32_t +read_slice_count_busy(int fd, uint32_t context, uint32_t expected, + igt_spin_t *spin) +{ + return __read_slice_count(fd, context, expected, spin); +} + +#define TEST_IDLE (1) +#define TEST_BUSY (2) + +/* + * Test context re-configuration with either idle or busy contexts. + */ +static void +test_dynamic(int fd, unsigned int flags) +{ + uint64_t pg_slice_mask = mask_minus_one(__slice_mask__); + unsigned int pg_slice_count = __slice_count__ - 1; + struct drm_i915_gem_context_param_sseu sseu = { }; + struct drm_i915_gem_context_param arg = + { .param = I915_CONTEXT_PARAM_SSEU, + .ctx_id = gem_context_create(fd), + .size = sizeof(sseu), + .value = to_user_pointer(&sseu) }; + igt_spin_t *spin = NULL; + + gem_context_get_param(fd, &arg); + + /* First set the default mask */ + if (flags & TEST_BUSY) + spin = __spin_sync(fd, arg.ctx_id, I915_EXEC_RENDER); + + sseu.slice_mask = __slice_mask__; + gem_context_set_param(fd, &arg); + + igt_assert_eq(read_slice_count_busy(fd, arg.ctx_id, 0, spin), + __slice_count__); + igt_assert_eq(read_slice_count(fd, 0, 0), __slice_count__); + + if (spin) { + igt_spin_batch_free(fd, spin); + spin = NULL; + } + + if (flags & TEST_IDLE) + igt_drop_caches_set(fd, DROP_RETIRE | DROP_IDLE | DROP_ACTIVE); + + /* Then set a powergated configuration */ + if (flags & TEST_BUSY) + spin = __spin_sync(fd, arg.ctx_id, I915_EXEC_RENDER); + + sseu.slice_mask = pg_slice_mask; + gem_context_set_param(fd, &arg); + + igt_assert_eq(read_slice_count_busy(fd, arg.ctx_id, 0, spin), + pg_slice_count); + igt_assert_eq(read_slice_count(fd, 0, 0), __slice_count__); + + if (spin) { + igt_spin_batch_free(fd, spin); + spin = NULL; + } + + if (flags & TEST_IDLE) + igt_drop_caches_set(fd, DROP_RETIRE | DROP_IDLE | DROP_ACTIVE); + + /* Put the device's default back again */ + if (flags & TEST_BUSY) + spin = __spin_sync(fd, arg.ctx_id, I915_EXEC_RENDER); + + sseu.slice_mask = __slice_mask__; + gem_context_set_param(fd, &arg); + + igt_assert_eq(read_slice_count_busy(fd, arg.ctx_id, 0, spin), + __slice_count__); + igt_assert_eq(read_slice_count(fd, 0, 0), __slice_count__); + + if (spin) { + igt_spin_batch_free(fd, spin); + spin = NULL; + } + + if (flags & TEST_IDLE) + igt_drop_caches_set(fd, DROP_RETIRE | DROP_IDLE | DROP_ACTIVE); + + /* One last powergated config for the road... */ + if (flags & TEST_BUSY) + spin = __spin_sync(fd, arg.ctx_id, I915_EXEC_RENDER); + + sseu.slice_mask = pg_slice_mask; + gem_context_set_param(fd, &arg); + + igt_assert_eq(read_slice_count_busy(fd, arg.ctx_id, 0, spin), + pg_slice_count); + igt_assert_eq(read_slice_count(fd, 0, 0), __slice_count__); + + if (spin) { + igt_spin_batch_free(fd, spin); + spin = NULL; + } + + gem_context_destroy(fd, arg.ctx_id); +} + +static void test_unsupported_device(int fd) +{ + struct drm_i915_gem_context_param_sseu sseu = { }; + struct drm_i915_gem_context_param arg = + { .param = I915_CONTEXT_PARAM_SSEU, + .ctx_id = gem_context_create(fd), + .size = sizeof(sseu), + .value = to_user_pointer(&sseu) }; + + igt_assert_eq(__gem_context_set_param(fd, &arg), -ENODEV); + + gem_context_destroy(fd, arg.ctx_id); +} + +static bool +platform_has_per_context_sseu_support(void) +{ + return __intel_gen__ >= 8; +} + +igt_main +{ + unsigned int max_slices = 3, max_subslices = 3; + unsigned int i; + int fd; + + igt_fixture { + fd = drm_open_driver(DRIVER_INTEL); + igt_require_gem(fd); + + __intel_devid__ = intel_get_drm_devid(fd); + __intel_gen__ = intel_gen(__intel_devid__); + + igt_require(kernel_has_per_context_sseu_support(fd)); + + if (__intel_gen__ >= 11) + __read_slice_count = gen11_read_slice_count; + else + __read_slice_count = gen8_read_slice_count; + } + + igt_subtest_group { + igt_fixture { + igt_require(!platform_has_per_context_sseu_support()); + } + + igt_subtest("unsupported-device") + test_unsupported_device(fd); + } + + igt_subtest_group { + igt_fixture { + drm_i915_getparam_t gp; + + igt_require(platform_has_per_context_sseu_support()); + + gp.param = I915_PARAM_SLICE_MASK; + gp.value = (int *) &__slice_mask__; + do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); + __slice_count__ = __builtin_popcount(__slice_mask__); + + gp.param = I915_PARAM_SUBSLICE_MASK; + gp.value = (int *) &__subslice_mask__; + do_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); + __subslice_count__ = + __builtin_popcount(__subslice_mask__); + } + + igt_subtest("invalid-args") + test_invalid_args(fd); + + igt_subtest("invalid-sseu") + test_invalid_sseu(fd); + + igt_subtest("engines") + test_engines(fd); + + for (i = 1; i < max_slices; i++) { + igt_subtest_f("slice-pg-%i", i) { + igt_require(__slice_count__ > i); + + test_slice_pg(fd, i); + } + } + + for (i = 1; i < max_subslices; i++) { + igt_subtest_f("subslice-pg-%i", i) { + igt_require(__subslice_count__ >= 2); + + /* + * Only available on some Atom platforms and + * Gen10+. + */ + igt_require(IS_BROXTON(__intel_devid__) || + IS_GEMINILAKE(__intel_devid__) || + __intel_gen__ >= 10); + + test_subslice_pg(fd, i); + } + } + + igt_subtest("sseu-perf-oa") { + igt_require(__slice_count__ > 1); + + test_perf_oa(fd); + } + + igt_subtest("dynamic") { + igt_require(__slice_count__ > 1); + + test_dynamic(fd, 0); + } + + igt_subtest("dynamic-busy") { + igt_require(__slice_count__ > 1); + + test_dynamic(fd, TEST_BUSY); + } + + igt_subtest("dynamic-idle") { + igt_require(__slice_count__ > 1); + + test_dynamic(fd, TEST_IDLE); + } + } + + igt_fixture { + close(fd); + } +} diff --git a/tests/meson.build b/tests/meson.build index 17deb945ec95..9319fa4e19b4 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -249,6 +249,13 @@ foreach prog : test_progs install : true) endforeach +test_executables += executable('gem_ctx_sseu', 'gem_ctx_sseu.c', + dependencies : test_deps + [ lib_igt_perf ], + install_dir : libexecdir, + install_rpath : libexecdir_rpathdir, + install : true) +test_progs += 'gem_ctx_sseu' + test_executables += executable('gem_eio', 'gem_eio.c', dependencies : test_deps + [ realtime ], install_dir : libexecdir,