public inbox for igt-dev@lists.freedesktop.org
 help / color / mirror / Atom feed
From: Ville Syrjala <ville.syrjala@linux.intel.com>
To: igt-dev@lists.freedesktop.org
Subject: [PATCH i-g-t 15/17] tests/kms: Pass crtc_index to kmstest_get_vblank()
Date: Fri, 27 Feb 2026 10:06:51 +0200	[thread overview]
Message-ID: <20260227080653.30389-16-ville.syrjala@linux.intel.com> (raw)
In-Reply-To: <20260227080653.30389-1-ville.syrjala@linux.intel.com>

From: Ville Syrjälä <ville.syrjala@linux.intel.com>

kmstest_get_vblank() is supposed to take the crtc_index
rather than the pipe. Make it so.

 #include "scripts/iterators.cocci"

@@
typedef igt_crtc_t;
igt_crtc_t *CRTC;
expression FD;
@@
kmstest_get_vblank(FD,
-	CRTC->pipe
+ 	CRTC->crtc_index
	,...)

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 tests/drm_read.c          |   4 +-
 tests/kms_cursor_legacy.c | 105 ++++++++++++++++++++++++++------------
 tests/kms_plane.c         |   5 +-
 tests/kms_rotation_crc.c  |   4 +-
 4 files changed, 80 insertions(+), 38 deletions(-)

diff --git a/tests/drm_read.c b/tests/drm_read.c
index 23b9ebe0faa3..2823238f6668 100644
--- a/tests/drm_read.c
+++ b/tests/drm_read.c
@@ -79,7 +79,7 @@ static void assert_empty(int fd)
 
 static void generate_event(int fd, igt_crtc_t *crtc)
 {
-	igt_assert(kmstest_get_vblank(fd, crtc->pipe, DRM_VBLANK_EVENT));
+	igt_assert(kmstest_get_vblank(fd, crtc->crtc_index, DRM_VBLANK_EVENT));
 }
 
 static void wait_for_event(int fd)
@@ -305,7 +305,7 @@ int igt_main()
 		}
 
 		igt_display_commit2(&display, display.is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
-		igt_require(kmstest_get_vblank(fd, crtc->pipe, 0));
+		igt_require(kmstest_get_vblank(fd, crtc->crtc_index, 0));
 	}
 
 	igt_subtest("invalid-buffer")
diff --git a/tests/kms_cursor_legacy.c b/tests/kms_cursor_legacy.c
index 3d5b8b851383..5cbb97676dea 100644
--- a/tests/kms_cursor_legacy.c
+++ b/tests/kms_cursor_legacy.c
@@ -778,10 +778,13 @@ static void basic_flip_cursor(igt_display_t *display,
 	igt_display_commit2(display, display->is_atomic ? COMMIT_ATOMIC : COMMIT_LEGACY);
 
 	/* Quick sanity check that we can update a cursor in a single vblank */
-	vblank_start = kmstest_get_vblank(display->drm_fd, crtc->pipe, DRM_VBLANK_NEXTONMISS);
-	igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start);
+	vblank_start = kmstest_get_vblank(display->drm_fd, crtc->crtc_index,
+					  DRM_VBLANK_NEXTONMISS);
+	igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+		      vblank_start);
 	do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
-	igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start);
+	igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+		      vblank_start);
 
 	for (i = 0; i < 25; i++) {
 		bool miss;
@@ -796,7 +799,9 @@ static void basic_flip_cursor(igt_display_t *display,
 					    .dependency = fb_info.gem_handle);
 
 		/* Start with a synchronous query to align with the vblank */
-		vblank_start = kmstest_get_vblank(display->drm_fd, crtc->pipe, DRM_VBLANK_NEXTONMISS);
+		vblank_start = kmstest_get_vblank(display->drm_fd,
+						  crtc->crtc_index,
+						  DRM_VBLANK_NEXTONMISS);
 
 		switch (order) {
 		case FLIP_BEFORE_CURSOR:
@@ -810,7 +815,8 @@ static void basic_flip_cursor(igt_display_t *display,
 				break;
 			}
 
-			delta = kmstest_get_vblank(display->drm_fd, crtc->pipe, 0) - vblank_start;
+			delta = kmstest_get_vblank(display->drm_fd,
+						   crtc->crtc_index, 0) - vblank_start;
 			miss = delta != 0;
 
 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
@@ -819,7 +825,8 @@ static void basic_flip_cursor(igt_display_t *display,
 		case FLIP_AFTER_CURSOR:
 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
 
-			delta = kmstest_get_vblank(display->drm_fd, crtc->pipe, 0) - vblank_start;
+			delta = kmstest_get_vblank(display->drm_fd,
+						   crtc->crtc_index, 0) - vblank_start;
 			miss = delta != 0;
 
 			switch (mode) {
@@ -833,7 +840,8 @@ static void basic_flip_cursor(igt_display_t *display,
 			}
 		}
 
-		delta = kmstest_get_vblank(display->drm_fd, crtc->pipe, 0) - vblank_start;
+		delta = kmstest_get_vblank(display->drm_fd, crtc->crtc_index,
+					   0) - vblank_start;
 
 		if (spin) {
 			struct pollfd pfd = { display->drm_fd, POLLIN };
@@ -857,7 +865,8 @@ static void basic_flip_cursor(igt_display_t *display,
 		if (miss1)
 			continue;
 
-		delta = kmstest_get_vblank(display->drm_fd, crtc->pipe, 0) - vblank_start;
+		delta = kmstest_get_vblank(display->drm_fd, crtc->crtc_index,
+					   0) - vblank_start;
 
 		if (!mode_requires_extra_vblank(mode))
 			miss2 += delta != 1;
@@ -893,13 +902,16 @@ get_cursor_updates_per_vblank(igt_display_t *display, igt_crtc_t *crtc,
 	int target;
 
 	for (target = 65536; target; target /= 2) {
-		unsigned vblank_start = kmstest_get_vblank(display->drm_fd, crtc->pipe, DRM_VBLANK_NEXTONMISS);
+		unsigned vblank_start = kmstest_get_vblank(display->drm_fd,
+							   crtc->crtc_index,
+							   DRM_VBLANK_NEXTONMISS);
 
-		igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start);
+		igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+			      vblank_start);
 
 		for (int n = 0; n < target; n++)
 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, arg);
-		if (kmstest_get_vblank(display->drm_fd, crtc->pipe, 0) == vblank_start)
+		if (kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0) == vblank_start)
 			break;
 	}
 
@@ -953,11 +965,14 @@ static void flip_vs_cursor(igt_display_t *display, enum flip_test mode, int nloo
 	else
 		target = 1;
 
-	vblank_start = kmstest_get_vblank(display->drm_fd, crtc->pipe, DRM_VBLANK_NEXTONMISS);
-	igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start);
+	vblank_start = kmstest_get_vblank(display->drm_fd, crtc->crtc_index,
+					  DRM_VBLANK_NEXTONMISS);
+	igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+		      vblank_start);
 	for (int n = 0; n < target; n++)
 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[0]);
-	igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start);
+	igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+		      vblank_start);
 
 	/*
 	 * There are variations caused by using cpu frequency changing. To
@@ -995,7 +1010,9 @@ static void flip_vs_cursor(igt_display_t *display, enum flip_test mode, int nloo
 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
 
 		/* Start with a synchronous query to align with the vblank */
-		vblank_start = kmstest_get_vblank(display->drm_fd, crtc->pipe, DRM_VBLANK_NEXTONMISS);
+		vblank_start = kmstest_get_vblank(display->drm_fd,
+						  crtc->crtc_index,
+						  DRM_VBLANK_NEXTONMISS);
 		switch (mode) {
 		default:
 			flip_nonblocking(display, crtc, mode >= flip_test_atomic, &fb_info, NULL);
@@ -1007,25 +1024,31 @@ static void flip_vs_cursor(igt_display_t *display, enum flip_test mode, int nloo
 		}
 
 		/* The nonblocking flip should not have delayed us */
-		igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start);
+		igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+			      vblank_start);
 		for (int n = 0; n < target; n++)
 			do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[nloops & 1]);
 
 		/* Nor should it have delayed the following cursor update */
 		if (!cursor_slowpath(display, mode))
-			igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start);
+			igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+				      vblank_start);
 		else if (mode_requires_extra_vblank(mode))
-			igt_assert_lte(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start + 2);
+			igt_assert_lte(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+				       vblank_start + 2);
 		else
-			igt_assert_lte(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start + 1);
+			igt_assert_lte(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+				       vblank_start + 1);
 
 		igt_set_timeout(1, "Stuck page flip");
 		igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
 
 		if (!mode_requires_extra_vblank(mode))
-			igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start + 1);
+			igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+				      vblank_start + 1);
 		else
-			igt_assert_lte(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start + 2);
+			igt_assert_lte(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+				       vblank_start + 2);
 
 		igt_reset_timeout();
 	} while (nloops--);
@@ -1234,7 +1257,9 @@ static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool
 		 * Try a page flip on crtc 1, if we succeed pump page flips and
 		 * modesets interleaved, else do a single atomic commit with both.
 		 */
-		vblank_start = kmstest_get_vblank(display->drm_fd, crtc->pipe, DRM_VBLANK_NEXTONMISS);
+		vblank_start = kmstest_get_vblank(display->drm_fd,
+						  crtc->crtc_index,
+						  DRM_VBLANK_NEXTONMISS);
 		igt_plane_set_fb(plane, &fb_info);
 		ret = igt_display_try_commit_atomic(display, flags, (void*)(ptrdiff_t)vblank_start);
 		igt_assert(!ret || ret == -EBUSY);
@@ -1266,10 +1291,14 @@ static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool
 			goto done;
 		}
 	} else {
-		vblank_start = kmstest_get_vblank(display->drm_fd, crtc->pipe, DRM_VBLANK_NEXTONMISS);
+		vblank_start = kmstest_get_vblank(display->drm_fd,
+						  crtc->crtc_index,
+						  DRM_VBLANK_NEXTONMISS);
 		flip_nonblocking(display, crtc, atomic, &fb_info, (void*)(ptrdiff_t)vblank_start);
 
-		vblank_start = kmstest_get_vblank(display->drm_fd, crtc2->pipe, DRM_VBLANK_NEXTONMISS);
+		vblank_start = kmstest_get_vblank(display->drm_fd,
+						  crtc2->crtc_index,
+						  DRM_VBLANK_NEXTONMISS);
 		flip_nonblocking(display, crtc2, atomic, &fb2_info, (void*)(ptrdiff_t)vblank_start);
 	}
 
@@ -1294,7 +1323,9 @@ static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool
 		}
 
 		if (vbl.crtc_id == crtc->crtc_id) {
-			vblank_start = kmstest_get_vblank(display->drm_fd, crtc->pipe, DRM_VBLANK_NEXTONMISS);
+			vblank_start = kmstest_get_vblank(display->drm_fd,
+							  crtc->crtc_index,
+							  DRM_VBLANK_NEXTONMISS);
 			flip_nonblocking(display, crtc, atomic, &fb_info, (void*)(ptrdiff_t)vblank_start);
 		} else {
 			igt_assert(vbl.crtc_id == crtc2->crtc_id);
@@ -1302,7 +1333,9 @@ static void two_screens_flip_vs_cursor(igt_display_t *display, int nloops, bool
 			nloops--;
 
 			if (!modeset) {
-				vblank_start = kmstest_get_vblank(display->drm_fd, crtc2->pipe, DRM_VBLANK_NEXTONMISS);
+				vblank_start = kmstest_get_vblank(display->drm_fd,
+								  crtc2->crtc_index,
+								  DRM_VBLANK_NEXTONMISS);
 				flip_nonblocking(display, crtc2, atomic, &fb2_info, (void*)(ptrdiff_t)vblank_start);
 			} else {
 				igt_output_set_crtc(output2,
@@ -1625,18 +1658,22 @@ static void flip_vs_cursor_crc(igt_display_t *display, bool atomic)
 
 	/* Disable cursor, and immediately queue a flip. Check if resulting crc is correct. */
 	for (int i = 1; i >= 0; i--) {
-		vblank_start = kmstest_get_vblank(display->drm_fd, crtc->pipe, DRM_VBLANK_NEXTONMISS);
+		vblank_start = kmstest_get_vblank(display->drm_fd,
+						  crtc->crtc_index,
+						  DRM_VBLANK_NEXTONMISS);
 
 		flip_nonblocking(display, crtc, atomic, &fb_info, NULL);
 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i]);
 
-		igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start);
+		igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+			      vblank_start);
 
 		igt_set_timeout(1, "Stuck page flip");
 		igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
 		igt_reset_timeout();
 
-		igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start + 1);
+		igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+			      vblank_start + 1);
 
 		igt_pipe_crc_collect_crc(pipe_crc, &crcs[2]);
 
@@ -1730,12 +1767,15 @@ static void flip_vs_cursor_busy_crc(igt_display_t *display, bool atomic)
 				    .dependency = fb_info[1].gem_handle,
 				    .dependency_size = fb_info[1].size);
 
-		vblank_start = kmstest_get_vblank(display->drm_fd, crtc->pipe, DRM_VBLANK_NEXTONMISS);
+		vblank_start = kmstest_get_vblank(display->drm_fd,
+						  crtc->crtc_index,
+						  DRM_VBLANK_NEXTONMISS);
 
 		flip_nonblocking(display, crtc, atomic, &fb_info[1], NULL);
 		do_ioctl(display->drm_fd, DRM_IOCTL_MODE_CURSOR, &arg[i]);
 
-		igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->pipe, 0), vblank_start);
+		igt_assert_eq(kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0),
+			      vblank_start);
 
 		igt_pipe_crc_get_current(display->drm_fd, pipe_crc, &test_crc);
 
@@ -1745,7 +1785,8 @@ static void flip_vs_cursor_busy_crc(igt_display_t *display, bool atomic)
 		igt_ignore_warn(read(display->drm_fd, &vbl, sizeof(vbl)));
 		igt_reset_timeout();
 
-		igt_assert_lte(vblank_start + 1, kmstest_get_vblank(display->drm_fd, crtc->pipe, 0));
+		igt_assert_lte(vblank_start + 1,
+			       kmstest_get_vblank(display->drm_fd, crtc->crtc_index, 0));
 
 		igt_plane_set_fb(plane_primary, &fb_info[0]);
 		igt_display_commit2(display, COMMIT_UNIVERSAL);
diff --git a/tests/kms_plane.c b/tests/kms_plane.c
index 15924f550ebf..cdb7884fdfe2 100644
--- a/tests/kms_plane.c
+++ b/tests/kms_plane.c
@@ -834,7 +834,7 @@ restart_round:
 			 */
 			if (i >= 1)
 				vblank[i - 1] = kmstest_get_vblank(data->drm_fd,
-								   crtc->pipe,
+								   crtc->crtc_index,
 								   0) + 1;
 
 			/*
@@ -871,7 +871,8 @@ restart_round:
 		 * The last crc is available earliest one
 		 * frame after the last flip latched.
 		 */
-		vblank[i - 1] = kmstest_get_vblank(data->drm_fd, crtc->pipe,
+		vblank[i - 1] = kmstest_get_vblank(data->drm_fd,
+						   crtc->crtc_index,
 						   0) + 1;
 	}
 
diff --git a/tests/kms_rotation_crc.c b/tests/kms_rotation_crc.c
index 0d3e17a32593..cf0ca78287c1 100644
--- a/tests/kms_rotation_crc.c
+++ b/tests/kms_rotation_crc.c
@@ -1023,7 +1023,7 @@ static void test_multi_plane_rotation(data_t *data, igt_crtc_t *crtc)
 
 							igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
 							flipsw = kmstest_get_vblank(data->gfx_fd,
-										    crtc->pipe,
+										    crtc->crtc_index,
 										    0) + 1;
 							have_crc = false;
 						}
@@ -1038,7 +1038,7 @@ static void test_multi_plane_rotation(data_t *data, igt_crtc_t *crtc)
 
 						igt_display_commit_atomic(display, DRM_MODE_ATOMIC_ALLOW_MODESET, NULL);
 						fliphw = kmstest_get_vblank(data->gfx_fd,
-									    crtc->pipe,
+									    crtc->crtc_index,
 									    0) + 1;
 
 						if (!have_crc) {
-- 
2.52.0


  parent reply	other threads:[~2026-02-27  8:08 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-27  8:06 [PATCH i-g-t 00/17] lib/kms: Finish the igt_crtc_t API refactoring Ville Syrjala
2026-02-27  8:06 ` [PATCH i-g-t 01/17] lib/kms: Replace igt_pipe_has_valid_output() with igt_crtc_has_valid_output() Ville Syrjala
2026-02-27 10:42   ` Jani Nikula
2026-02-27  8:06 ` [PATCH i-g-t 02/17] lib/kms: Replace igt_display_require_output_on_pipe() with igt_display_require_output_on_crtc() Ville Syrjala
2026-02-27 10:50   ` Jani Nikula
2026-02-27  8:06 ` [PATCH i-g-t 03/17] lib/kms: Replace igt_get_single_output_for_pipe() with igt_get_single_output_for_crtc() Ville Syrjala
2026-02-27 10:22   ` Jani Nikula
2026-02-27  8:06 ` [PATCH i-g-t 04/17] lib/kms: Make the igt_*_bpc_*() interfaces more abstract Ville Syrjala
2026-02-27  8:06 ` [PATCH i-g-t 05/17] tests/kms: Use igt_crtc_name() Ville Syrjala
2026-02-27  8:06 ` [PATCH i-g-t 06/17] tests/kms: Clean up crtc->pipe comparions Ville Syrjala
2026-02-27 10:51   ` Jani Nikula
2026-02-27  8:06 ` [PATCH i-g-t 07/17] tests/vmwgfx/vmw_prime: Replace igt_pipe_crc_new() with igt_crtc_crc_new() Ville Syrjala
2026-02-27  8:06 ` [PATCH i-g-t 08/17] lib/kms: Prefer "crtc" over "pipe" in function names Ville Syrjala
2026-02-27  8:06 ` [PATCH i-g-t 09/17] tests/kms_color*: " Ville Syrjala
2026-02-27  8:06 ` [PATCH i-g-t 10/17] tests/kms: " Ville Syrjala
2026-02-27  8:06 ` [PATCH i-g-t 11/17] tests/kms_tiled_display: Remove mention of PIPE_NONE Ville Syrjala
2026-02-27  8:06 ` [PATCH i-g-t 12/17] tests/kms: Remove hand rolled get_vblank() stuff Ville Syrjala
2026-02-27  8:06 ` [PATCH i-g-t 13/17] lib/kms: Fix kmstest_get_vblank() docs Ville Syrjala
2026-02-27  8:06 ` [PATCH i-g-t 14/17] tests/kms: Pass crtc_index to kmstest_get_vbl_flag() Ville Syrjala
2026-02-27  8:06 ` Ville Syrjala [this message]
2026-02-27  8:06 ` [PATCH i-g-t 16/17] lib/kms: Introduce igt_crtc_get_vbl_flag() Ville Syrjala
2026-02-27  8:06 ` [PATCH i-g-t 17/17] lib/kms: Introduce igt_crtc_get_vblank() Ville Syrjala
2026-02-27 10:55 ` [PATCH i-g-t 00/17] lib/kms: Finish the igt_crtc_t API refactoring Jani Nikula
2026-02-27 14:14 ` ✗ i915.CI.BAT: failure for " Patchwork
2026-02-27 14:24 ` ✓ Xe.CI.BAT: success " Patchwork
2026-02-27 23:28 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-03-04  5:58 ` ✓ Xe.CI.BAT: success for lib/kms: Finish the igt_crtc_t API refactoring (rev2) Patchwork
2026-03-04  6:19 ` ✓ i915.CI.BAT: " Patchwork
2026-03-05  5:01 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-03-05  8:15 ` ✗ i915.CI.Full: " Patchwork

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=20260227080653.30389-16-ville.syrjala@linux.intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=igt-dev@lists.freedesktop.org \
    /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