From: Matthew Auld <matthew.auld@intel.com>
To: Smitha Balasubramanyam <smitha.balasubramanyam@intel.com>,
igt-dev@lists.freedesktop.org, zbigniew.kempczynski@intel.com
Subject: Re: [PATCH v2 3/3] tests/intel/xe_ccs : Add CCS corruption neg test for VM_BIND decomp
Date: Mon, 15 Jun 2026 18:05:12 +0100 [thread overview]
Message-ID: <baae1a9a-f704-4590-8ef8-826244dd0486@intel.com> (raw)
In-Reply-To: <20260615123109.2286386-4-smitha.balasubramanyam@intel.com>
On 15/06/2026 13:31, Smitha Balasubramanyam wrote:
> Add a negative test covering VM_BIND decompression verification
> with corrupted CCS metadata.
> > The test also exercises suspend and resume handling during the
> corruption scenario.
What is meant by corrupted CCS here? Is this userspace corrupting
something? If so, why does the kernel care? Can you give some more
details here please?
>
> Signed-off-by: Smitha Balasubramanyam <smitha.balasubramanyam@intel.com>
> ---
> tests/intel/xe_ccs.c | 345 +++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 345 insertions(+)
>
> diff --git a/tests/intel/xe_ccs.c b/tests/intel/xe_ccs.c
> index 9a4fa36e1..bcf7655bd 100644
> --- a/tests/intel/xe_ccs.c
> +++ b/tests/intel/xe_ccs.c
> @@ -75,6 +75,13 @@
> * SUBTEST: vm-bind-decompress-uapi-bad-params-fault-mode
> * Description: UAPI negative test attempt VM_BIND with a combination of
> * invalid params - fault mode
> + *
> + * SUBTEST: vm-bind-decompress-ccs-corruption
> + * Description: Functional negative test — attempt VM_BIND after corrupting the CCS data;
> + * verify that decompression fails (data differs from original).
> + *
> + * SUBTEST: vm-bind-decompress-ccs-corruption-suspend-resume
> + * Description: Validate VM_BIND with DECOMPRESS flag with corrupted CCS with suspend/resume (S0)
> */
>
> IGT_TEST_DESCRIPTION("Exercise gen12 blitter with and without flatccs compression on Xe");
> @@ -113,6 +120,7 @@ struct test_config {
> bool vm_bind_fault_mode_decompress;
> bool vm_bind_decompress_uapi_bad_params;
> bool vm_bind_decompress_uapi_bad_params_fault_mode;
> + bool vm_bind_decompress_ccs_corruption;
> int width_increment;
> int width_steps;
> int overwrite_width;
> @@ -1175,6 +1183,307 @@ static void vm_bind_decompress_uapi_bad_params_fault_mode(int xe,
> vm_bind_decomp_test_cleanup(xe, ahnd, &allocated_resources);
> }
>
> +/* Functional negative test that validates VM_BIND Decompress with CCS corruption.
> + * It compresses src -> mid1/mid2, extracts CCS, corrupts mid1 CCS, writes back,
> + * reissues VM_BIND with DECOMPRESS for both and verifies mid1 != src and mid2 == src.
> + */
> +static void vm_bind_decompress_ccs_corruption(int xe,
> + intel_ctx_t *ctx,
> + u64 ahnd,
> + u32 region1,
> + u32 region2,
> + u32 width,
> + u32 height,
> + const struct test_config *config)
> +{
> + struct drm_xe_gem_mmap_offset mmap_offset = {};
> + struct blt_copy_data blt = {};
> + struct blt_block_copy_data_ext ext = {};
> + struct blt_ctrl_surf_copy_data surf = {};
> + struct vm_bind_decomp_setup_resources allocated_resources = {};
> + struct blt_copy_object *src, *mid1, *mid2;
> + const u32 bpp = 32;
> + enum blt_compression_type comp_type = COMPRESSION_TYPE_3D;
> + u64 bb_size = xe_bb_size(xe, SZ_4K);
> + u64 size = (u64)width * height * 4;
> + u32 comp_pat = intel_get_pat_idx_uc_comp(xe);
> + u32 ccs1, ccs2;
> + uint32_t *ccsmap1 = NULL, *ccsmap2 = NULL;
> + uint64_t ccssize = 0;
> + uint64_t ccs_bo_size = 0;
> + uint32_t *ccscopy = NULL;
> + int result;
> + void *mapped_mid1 = MAP_FAILED;
> + void *mapped_mid2 = MAP_FAILED;
> +
> + /* Use vm_bind_decomp_test_setup to create a src (uncompressed) and a first
> + * compressed object (mid1). The helper also creates a VM and BB
> + * used for subsequent ctrl-surface operations.
> + */
> + result = vm_bind_decomp_test_setup(xe, ctx, ahnd, region1, region2, width,
> + height, T_LINEAR, config, true, false,
> + &allocated_resources);
> + igt_assert_eq(result, 0);
> +
> + /* Reuse helper-created objects */
> + src = allocated_resources.src_obj;
> + mid1 = allocated_resources.comp_obj;
> +
> + print_buffer_data(src->ptr, min_t(size_t, 64, size), "ORIGINAL", 4);
> + print_buffer_data(mid1->ptr, min_t(size_t, 64, size),
> + "SURFACE1_COMPRESSED", 4);
> +
> + /* Compute CCS sizes now that mid1 is valid */
> + ccssize = mid1->size / CCS_RATIO(xe);
> + ccs_bo_size = ALIGN(ccssize, xe_get_default_alignment(xe));
> + ccscopy = malloc(ccssize);
> +
> + /* Create a second compressed object (mid2) and compress src->mid2 */
> + /* Init blit + batch */
> + blt_copy_init(xe, &blt);
> + mid2 = blt_create_object(&blt, region2, width, height,
> + bpp, intel_get_uc_mocs_index(xe), T_LINEAR,
> + COMPRESSION_ENABLED, comp_type, true);
> + igt_assert(mid2);
> +
> + /* Use the BB provided by the helper */
> + blt_set_batch(&blt.bb, allocated_resources.bb, bb_size, allocated_resources.region_src);
> + blt.color_depth = CD_32bit;
> + blt.print_bb = param.print_bb;
> + blt_set_copy_object(&blt.src, src);
> + blt_set_copy_object(&blt.dst, mid2);
> + blt_set_object_ext(&ext.src, 0, width, height, SURFACE_TYPE_2D);
> + blt_set_object_ext(&ext.dst, param.compression_format, width, height, SURFACE_TYPE_2D);
> +
> + blt_block_copy(xe, ctx, NULL, ahnd, &blt, &ext);
> + intel_ctx_xe_sync(ctx, true);
> +
> + /* Verify compression occurred when platform supports it */
> + if (blt_platform_has_flat_ccs_enabled(xe)) {
> + bool is_compressed = blt_surface_is_compressed(xe, ctx, NULL, ahnd, mid2);
> +
> + if (!is_compressed) {
> + vm_bind_decomp_test_cleanup(xe, ahnd, &allocated_resources);
> + igt_assert_f(false, "Surface compression failed - "
> + " cannot test decompression\n");
> + }
> + }
> +
> + print_buffer_data(mid2->ptr, min_t(size_t, 64, size),
> + "SURFACE2_COMPRESSED", 4);
> +
> + ccs1 = xe_bo_create_caching(xe, 0, ccs_bo_size, system_memory(xe), 0,
> + __xe_default_cpu_caching(xe,
> + system_memory(xe), 0));
> + ccs2 = xe_bo_create_caching(xe, 0, ccs_bo_size, system_memory(xe), 0,
> + __xe_default_cpu_caching(xe,
> + system_memory(xe), 0));
> + blt_ctrl_surf_copy_init(xe, &surf);
> + surf.print_bb = param.print_bb;
> +
> + /* mid1 -> ccs1 */
> + blt_set_ctrl_surf_object(&surf.src, mid1->handle, mid1->region,
> + mid1->size, intel_get_uc_mocs_index(xe),
> + comp_pat, BLT_INDIRECT_ACCESS);
> + blt_set_ctrl_surf_object(&surf.dst, ccs1, system_memory(xe), ccssize,
> + 0, DEFAULT_PAT_INDEX, DIRECT_ACCESS);
> + blt_set_batch(&surf.bb, allocated_resources.bb, bb_size, allocated_resources.region_src);
> +
> + blt_ctrl_surf_copy(xe, ctx, NULL, ahnd, &surf);
> + intel_ctx_xe_sync(ctx, true);
> +
> + /* mid2 -> ccs2 */
> + blt_set_ctrl_surf_object(&surf.src, mid2->handle, mid2->region,
> + mid2->size, intel_get_uc_mocs_index(xe),
> + comp_pat, BLT_INDIRECT_ACCESS);
> + blt_set_ctrl_surf_object(&surf.dst, ccs2, system_memory(xe), ccssize,
> + 0, DEFAULT_PAT_INDEX, DIRECT_ACCESS);
> + blt_set_batch(&surf.bb, allocated_resources.bb, bb_size, allocated_resources.region_src);
> + blt_ctrl_surf_copy(xe, ctx, NULL, ahnd, &surf);
> + intel_ctx_xe_sync(ctx, true);
> + igt_info("\nExtracted CCS for both compressed surfaces\n");
> + igt_info("Proceeds to corrupt surface1 CCS and preserve surface2 CCS\n");
> +
> + /* --- Map, corrupt mid1's CCS, then write corrupted CCS back into mid1 --- */
> + /* Map ccs1 (the corrupted copy) */
> + ccsmap1 = xe_bo_map(xe, ccs1, ccssize);
> + // Verifying mapping
> + igt_assert(ccsmap1 != MAP_FAILED);
> +
> + igt_assert(ccscopy);
> + memcpy(ccscopy, ccsmap1, ccssize);
> +
> + /* Corrupt the CCS content (example corruption) */
> + for (size_t i = 0; i < ccssize / sizeof(uint32_t); i++)
> + ccsmap1[i] = (uint32_t)i ^ 0xdeadbeefu;
> +
> + /* Ensure GPU sees the change by writing it back via ctrl-surf-copy:
> + * ccs1 -> mid1 (DIRECT_ACCESS -> BLT_INDIRECT_ACCESS)
> + */
> + munmap(ccsmap1, ccssize); /* unmap before submitting */
> + blt_set_ctrl_surf_object(&surf.src, ccs1, system_memory(xe), ccssize,
> + 0, DEFAULT_PAT_INDEX, DIRECT_ACCESS);
> + blt_set_ctrl_surf_object(&surf.dst, mid1->handle, mid1->region,
> + mid1->size, intel_get_uc_mocs_index(xe),
> + comp_pat, BLT_INDIRECT_ACCESS);
> + blt_set_batch(&surf.bb, allocated_resources.bb, bb_size, allocated_resources.region_src);
> + blt_ctrl_surf_copy(xe, ctx, NULL, ahnd, &surf);
> + intel_ctx_xe_sync(ctx, true);
> +
> + /* --- Write clean/unaltered CCS back to mid2 (optional, restoration) --- */
> + ccsmap2 = xe_bo_map(xe, ccs2, ccssize);
> + igt_assert(ccsmap2 != MAP_FAILED);
> + munmap(ccsmap2, ccssize);
> + blt_set_ctrl_surf_object(&surf.src, ccs2, system_memory(xe), ccssize,
> + 0, DEFAULT_PAT_INDEX, DIRECT_ACCESS);
> + blt_set_ctrl_surf_object(&surf.dst, mid2->handle, mid2->region,
> + mid2->size, intel_get_uc_mocs_index(xe),
> + comp_pat, BLT_INDIRECT_ACCESS);
> + blt_set_batch(&surf.bb, allocated_resources.bb, bb_size, allocated_resources.region_src);
> + blt_ctrl_surf_copy(xe, ctx, NULL, ahnd, &surf);
> + intel_ctx_xe_sync(ctx, true);
> + igt_info("Applied corrupted CCS to surface1 and restored clean CCS to surface2\n");
> +
> + /* --- Suspend/Resume test (optional) --- */
> + if (config->suspend_resume) {
> + char *ccs1_before = NULL, *ccs2_before = NULL;
> + char *ccs1_after = NULL, *ccs2_after = NULL;
> + void *map;
> +
> + igt_info("Test Case has invoked a suspend-resume\n");
> +
> + /* Compute checksums of CCS BOs before suspend */
> + map = xe_bo_map(xe, ccs1, ccssize);
> + igt_assert(map != MAP_FAILED);
> + ccs1_before = g_compute_checksum_for_data(G_CHECKSUM_SHA1, map, ccssize);
> + munmap(map, ccssize);
> +
> + map = xe_bo_map(xe, ccs2, ccssize);
> + igt_assert(map != MAP_FAILED);
> + ccs2_before = g_compute_checksum_for_data(G_CHECKSUM_SHA1, map, ccssize);
> + munmap(map, ccssize);
> +
> + /* Ensure all GPU work is visible, then suspend/resume */
> + intel_ctx_xe_sync(ctx, true);
> + igt_info("Suspending system to test CCS persistence across S0 suspend/resume\n");
> + igt_system_suspend_autoresume(SUSPEND_STATE_FREEZE, SUSPEND_TEST_NONE);
> + igt_info("System resume complete — continuing VM_BIND tests\n");
> +
> + /* Re-read CCS BOs after resume and compute checksums */
> + map = xe_bo_map(xe, ccs1, ccssize);
> + igt_assert(map != MAP_FAILED);
> + ccs1_after = g_compute_checksum_for_data(G_CHECKSUM_SHA1, map, ccssize);
> + munmap(map, ccssize);
> +
> + map = xe_bo_map(xe, ccs2, ccssize);
> + igt_assert(map != MAP_FAILED);
> + ccs2_after = g_compute_checksum_for_data(G_CHECKSUM_SHA1, map, ccssize);
> + munmap(map, ccssize);
> +
> + /* Expectations:
> + * - ccs1 (corrupted) should remain changed across suspend/resume
> + * - ccs2 (clean) should remain unchanged across suspend/resume
> + */
> + if (ccs1_before && ccs1_after && !strcmp(ccs1_before, ccs1_after))
> + igt_info("CCS1 (corrupted) persisted with same checksum (expected)\n");
> + else if (ccs1_before && ccs1_after)
> + igt_warn("CCS1 checksum changed across suspend/resume (unexpected)\n");
> +
> + if (ccs2_before && ccs2_after && strcmp(ccs2_before, ccs2_after) == 0)
> + igt_info("CCS2 (clean) persisted with identical checksum (expected)\n");
> + else
> + igt_warn("CCS2 checksum changed across suspend/resume (unexpected)\n");
> +
> + g_free(ccs1_before);
> + g_free(ccs1_after);
> + g_free(ccs2_before);
> + g_free(ccs2_after);
> + }
> +
> + /* Cleanup */
> + free(ccscopy);
> + /* ccsmap1 was unmapped before writeback; avoid double unmap here */
> + gem_close(xe, ccs1);
> + gem_close(xe, ccs2);
> + put_offset(ahnd, ccs1);
> + put_offset(ahnd, ccs2);
> + igt_debug("Cleaned up CCS BOs\n");
> +
> + /* Bind both mid1 and mid2 initially compressed */
> + result = __xe_vm_bind(xe, allocated_resources.vm, 0, mid1->handle, 0,
> + allocated_resources.vm_map_addr,
> + allocated_resources.map_size,
> + DRM_XE_VM_BIND_OP_MAP, 0, NULL, 0, 0,
> + comp_pat, 0);
> + igt_assert_eq(result, 0);
> + result = __xe_vm_bind(xe, allocated_resources.vm, 0, mid2->handle, 0,
> + allocated_resources.vm_map_addr +
> + allocated_resources.map_size,
> + allocated_resources.map_size,
> + DRM_XE_VM_BIND_OP_MAP, 0, NULL, 0, 0,
> + comp_pat, 0);
> + igt_assert_eq(result, 0);
> + /* Update mappings to request DECOMPRESS (UC PAT) */
> + result = __xe_vm_bind(xe, allocated_resources.vm, 0, mid1->handle, 0,
> + allocated_resources.vm_map_addr,
> + allocated_resources.map_size,
> + DRM_XE_VM_BIND_OP_MAP,
> + DRM_XE_VM_BIND_FLAG_DECOMPRESS, NULL, 0, 0,
> + allocated_resources.uncompressed_pat, 0);
> + igt_assert_eq(result, 0);
> + result = __xe_vm_bind(xe, allocated_resources.vm, 0, mid2->handle, 0,
> + allocated_resources.vm_map_addr +
> + allocated_resources.map_size,
> + allocated_resources.map_size,
> + DRM_XE_VM_BIND_OP_MAP,
> + DRM_XE_VM_BIND_FLAG_DECOMPRESS, NULL, 0, 0,
> + allocated_resources.uncompressed_pat, 0);
> + igt_assert_eq(result, 0);
> +
> + /* Map both for CPU access and compare */
> + mmap_offset.handle = mid1->handle;
> + mmap_offset.flags = 0;
> + result = igt_ioctl(xe, DRM_IOCTL_XE_GEM_MMAP_OFFSET, &mmap_offset);
> +
> + igt_assert_eq(result, 0);
> + mapped_mid1 = mmap(NULL, size, PROT_READ, MAP_SHARED, xe, mmap_offset.offset);
> + igt_assert(mapped_mid1 != MAP_FAILED);
> +
> + mmap_offset.handle = mid2->handle;
> + mmap_offset.flags = 0;
> + result = igt_ioctl(xe, DRM_IOCTL_XE_GEM_MMAP_OFFSET, &mmap_offset);
> + igt_assert_eq(result, 0);
> + mapped_mid2 = mmap(NULL, size, PROT_READ, MAP_SHARED, xe, mmap_offset.offset);
> + igt_assert(mapped_mid2 != MAP_FAILED);
> + igt_info("Issued VM_BIND with DECOMPRESS for both surfaces and now verifying each surface against the original data\n");
> + if (memcmp(mapped_mid1, src->ptr, size) == 0)
> + igt_assert_f(false, "mid1 decompressed matches src "
> + "(expected mismatch due to CCS corruption)");
> + igt_info("VM_BIND decompression did not recover original data for corrupted surface (mid1), as expected\n");
> +
> + print_buffer_data(mapped_mid1, min_t(size_t, 64, size),
> + "MID1_CORRUPTED", 4);
> + print_buffer_data(src->ptr, min_t(size_t, 64, size), "SRC", 4);
> +
> + if (memcmp(mapped_mid2, src->ptr, size) != 0)
> + igt_assert_f(false, "Decompressed MID2 does not match src "
> + "(expected match for clean CCS)");
> + igt_info("VM_BIND decompression successful for clean surface (mid2)\n");
> +
> + print_buffer_data(mapped_mid2, min_t(size_t, 64, size),
> + "MID2_DECOMPRESSED", 4);
> + print_buffer_data(src->ptr, min_t(size_t, 64, size), "SRC", 4);
> +
> + igt_info("CCS corruption decompression test completed successfully\n");
> + munmap(mapped_mid1, size);
> + munmap(mapped_mid2, size);
> +
> + put_offset(ahnd, mid2->handle);
> + blt_destroy_object(xe, mid2);
> +
> + vm_bind_decomp_test_cleanup(xe, ahnd, &allocated_resources);
> +}
> +
> struct blt_copy3_data {
> int xe;
> struct blt_copy_object src;
> @@ -2089,6 +2398,12 @@ static void single_copy(int xe, const struct test_config *config,
> ctx, ahnd, region1, region2,
> width, height, tiling, config);
> put_ahnd(ahnd);
> + } else if (config->vm_bind_decompress_ccs_corruption) {
> + ahnd = intel_allocator_open(xe, vm, INTEL_ALLOCATOR_RELOC);
> + vm_bind_decompress_ccs_corruption(xe, ctx, ahnd,
> + region1, region2, width,
> + height, config);
> + put_ahnd(ahnd);
> } else {
> copyfns[copy_function].copyfn(xe, ctx,
> region1, region2,
> @@ -2419,6 +2734,36 @@ int igt_main_args("bf:pst:W:H:", NULL, help_str, opt_handler, NULL)
> single_copy(xe, &config, region1, region2, width, height, tiling, BLOCK_COPY);
> }
>
> + igt_describe("Validate VM_BIND with DECOMPRESS flag with corrupted CCS");
> + igt_subtest("vm-bind-decompress-ccs-corruption") {
> + struct test_config config = { .compression = true,
> + .vm_bind_decompress_ccs_corruption = true,
> + .suspend_resume = false };
> + u32 region1 = system_memory(xe);
> + u32 region2 = vram_if_possible(xe, 0);
> + int tiling = T_LINEAR;
> + int width = param.width;
> + int height = param.height;
> +
> + single_copy(xe, &config, region1, region2, width, height, tiling, BLOCK_COPY);
> + }
> +
> + igt_describe("Validate VM_BIND with DECOMPRESS flag "
> + "with corrupted CCS with suspend/resume");
> + igt_subtest("vm-bind-decompress-ccs-corruption-suspend-resume") {
> + struct test_config config = { .compression = true,
> + .vm_bind_decompress_ccs_corruption = true,
> + .suspend_resume = true };
> + u32 region1 = system_memory(xe);
> + u32 region2 = vram_if_possible(xe, 0);
> + int tiling = T_LINEAR;
> + int width = param.width;
> + int height = param.height;
> +
> + single_copy(xe, &config, region1, region2, width, height, tiling,
> + BLOCK_COPY);
> + }
> +
> igt_fixture() {
> xe_device_put(xe);
> close(xe);
next prev parent reply other threads:[~2026-06-15 17:05 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-27 5:42 [PATCH 0/3] Negative tests for VM_BIND decompression Smitha Balasubramanyam
2026-05-27 5:42 ` [PATCH 1/3] tests/intel/xe_ccs : Add helpers and Negative test for VM_Bind Decomp Smitha Balasubramanyam
2026-05-27 5:42 ` [PATCH 2/3] tests/intel/xe_ccs: Add fault-mode helper and VM_BIND decomp neg test Smitha Balasubramanyam
2026-05-27 5:42 ` [PATCH 3/3] tests/intel/xe_ccs : Add CCS corruption neg test for VM_BIND decomp Smitha Balasubramanyam
2026-05-27 6:40 ` ✓ Xe.CI.BAT: success for Negative tests for VM_BIND decompression Patchwork
2026-05-27 6:42 ` ✓ i915.CI.BAT: " Patchwork
2026-05-27 8:39 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-05-27 13:21 ` ✓ i915.CI.Full: success " Patchwork
2026-06-15 12:31 ` [PATCH v2 0/3] " Smitha Balasubramanyam
2026-06-15 12:31 ` [PATCH v2 1/3] tests/intel/xe_ccs : Add helpers and Negative test for VM_Bind Decomp Smitha Balasubramanyam
2026-06-15 17:02 ` Matthew Auld
2026-06-15 17:06 ` Matthew Auld
2026-06-22 5:24 ` Balasubramanyam, Smitha
2026-06-22 14:50 ` Matthew Auld
2026-06-15 12:31 ` [PATCH v2 2/3] tests/intel/xe_ccs: Add fault-mode helper and VM_BIND decomp neg test Smitha Balasubramanyam
2026-06-15 12:31 ` [PATCH v2 3/3] tests/intel/xe_ccs : Add CCS corruption neg test for VM_BIND decomp Smitha Balasubramanyam
2026-06-15 17:05 ` Matthew Auld [this message]
2026-06-22 6:08 ` Balasubramanyam, Smitha
2026-06-22 15:21 ` Matthew Auld
-- strict thread matches above, loose matches on Subject: below --
2026-04-20 4:57 [PATCH 0/2] Negative tests for VM_BIND decompression Smitha Balasubramanyam
2026-05-25 11:40 ` [PATCH v2 0/3] " Smitha Balasubramanyam
2026-05-25 11:40 ` [PATCH v2 3/3] tests/intel/xe_ccs : Add CCS corruption neg test for VM_BIND decomp Smitha Balasubramanyam
2026-05-25 12:15 ` [PATCH v2 0/3] Negative tests for VM_BIND decompression Smitha Balasubramanyam
2026-05-25 12:15 ` [PATCH v2 3/3] tests/intel/xe_ccs : Add CCS corruption neg test for VM_BIND decomp Smitha Balasubramanyam
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=baae1a9a-f704-4590-8ef8-826244dd0486@intel.com \
--to=matthew.auld@intel.com \
--cc=igt-dev@lists.freedesktop.org \
--cc=smitha.balasubramanyam@intel.com \
--cc=zbigniew.kempczynski@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox