All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: Jani Nikula <jani.nikula@intel.com>
Cc: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: Re: [PATCH 01/12] drm/edid: use struct edid * in drm_do_get_edid()
Date: Wed, 30 Mar 2022 19:50:29 +0300	[thread overview]
Message-ID: <YkSKVRi8g+jGeeSd@intel.com> (raw)
In-Reply-To: <87lewrbe0n.fsf@intel.com>

On Wed, Mar 30, 2022 at 07:28:56PM +0300, Jani Nikula wrote:
> On Wed, 30 Mar 2022, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > On Wed, Mar 30, 2022 at 06:16:17PM +0300, Jani Nikula wrote:
> >> On Wed, 30 Mar 2022, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> >> > On Tue, Mar 29, 2022 at 09:42:08PM +0300, Jani Nikula wrote:
> >> >> Mixing u8 * and struct edid * is confusing, switch to the latter.
> >> >> 
> >> >> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> >> >> ---
> >> >>  drivers/gpu/drm/drm_edid.c | 31 +++++++++++++++----------------
> >> >>  1 file changed, 15 insertions(+), 16 deletions(-)
> >> >> 
> >> >> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> >> >> index d79b06f7f34c..0650b9217aa2 100644
> >> >> --- a/drivers/gpu/drm/drm_edid.c
> >> >> +++ b/drivers/gpu/drm/drm_edid.c
> >> >> @@ -1991,29 +1991,28 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
> >> >>  	void *data)
> >> >>  {
> >> >>  	int i, j = 0, valid_extensions = 0;
> >> >> -	u8 *edid, *new;
> >> >> -	struct edid *override;
> >> >> +	struct edid *edid, *new, *override;
> >> >>  
> >> >>  	override = drm_get_override_edid(connector);
> >> >>  	if (override)
> >> >>  		return override;
> >> >>  
> >> >> -	edid = (u8 *)drm_do_get_edid_base_block(connector, get_edid_block, data);
> >> >> +	edid = drm_do_get_edid_base_block(connector, get_edid_block, data);
> >> >>  	if (!edid)
> >> >>  		return NULL;
> >> >>  
> >> >>  	/* if there's no extensions or no connector, we're done */
> >> >> -	valid_extensions = edid[0x7e];
> >> >> +	valid_extensions = edid->extensions;
> >> >>  	if (valid_extensions == 0)
> >> >> -		return (struct edid *)edid;
> >> >> +		return edid;
> >> >>  
> >> >>  	new = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
> >> >>  	if (!new)
> >> >>  		goto out;
> >> >>  	edid = new;
> >> >>  
> >> >> -	for (j = 1; j <= edid[0x7e]; j++) {
> >> >> -		u8 *block = edid + j * EDID_LENGTH;
> >> >> +	for (j = 1; j <= edid->extensions; j++) {
> >> >> +		void *block = edid + j;
> >> >>  
> >> >>  		for (i = 0; i < 4; i++) {
> >> >>  			if (get_edid_block(data, block, j, EDID_LENGTH))
> >> >> @@ -2026,13 +2025,13 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
> >> >>  			valid_extensions--;
> >> >>  	}
> >> >>  
> >> >> -	if (valid_extensions != edid[0x7e]) {
> >> >> -		u8 *base;
> >> >> +	if (valid_extensions != edid->extensions) {
> >> >> +		struct edid *base;
> >> >
> >> > This one points to extension blocks too so using 
> >> > struct edid doesn't seem entirely appropriate.
> >> 
> >> So I've gone back and forth with this. I think I want to get rid of u8*
> >> no matter what, because it always requires casting. I've used void* here
> >> and there to allow mixed use, internally in drm_edid.c while
> >> transitioning, and in public interfaces due to usage all over the place.
> >> 
> >> OTOH I don't much like arithmetics on void*. It's a gcc extension.
> >> 
> >> struct edid * is useful for e.g. ->checksum and arithmetics. In many
> >> places I've named it struct edid *block to distinguish. We could have a
> >> struct edid_block too, which could have ->tag and ->checksum members,
> >> for example, but then it would require casting or a function for "safe"
> >> typecasting.
> >> 
> >> I've also gone back and forth with the helpers for getting a pointer to
> >> a block. For usage like this, kind of need both const and non-const
> >> versions. And, with the plans I have for future, I'm not sure I want to
> >> promote any EDID parsing outside of drm_edid.c, so maybe they should be
> >> static.
> >> 
> >> Undecided. C is a bit clunky here.
> >> 
> >> >
> >> >>  
> >> >> -		connector_bad_edid(connector, edid, edid[0x7e] + 1);
> >> >> +		connector_bad_edid(connector, (u8 *)edid, edid->extensions + 1);
> >> >>  
> >> >> -		edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
> >> >> -		edid[0x7e] = valid_extensions;
> >> >> +		edid->checksum += edid->extensions - valid_extensions;
> >> >> +		edid->extensions = valid_extensions;
> >> >>  
> >> >>  		new = kmalloc_array(valid_extensions + 1, EDID_LENGTH,
> >> >>  				    GFP_KERNEL);
> >> >> @@ -2040,21 +2039,21 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
> >> >>  			goto out;
> >> >>  
> >> >>  		base = new;
> >> >> -		for (i = 0; i <= edid[0x7e]; i++) {
> >> >> -			u8 *block = edid + i * EDID_LENGTH;
> >> >> +		for (i = 0; i <= edid->extensions; i++) {
> >> >> +			void *block = edid + i;
> >> >
> >> > Hmm. This code seems very broken to me. We read each block
> >> > into its expected offset based on the original base block extension
> >> > count, but here we only iterate up to the new ext block count. So
> >> > if we had eg. a 4 block EDID where block 2 is busted, we set 
> >> > the new ext count to 2, copy over blocks 0 and 1, skip block 2,
> >> > and then terminate the loop. So instead of copying block 3 from
> >> > the orignal EDID into block 2 of the new EDID, we leave the
> >> > original garbage block 2 in place.
> >> 
> >> Ugh. I end up fixing this in the series, in "drm/edid: split out invalid
> >> block filtering to a separate function", but I don't mention it
> >> anywhere.
> >> 
> >> Looks like it's been broken for 5+ years since commit 14544d0937bf
> >> ("drm/edid: Only print the bad edid when aborting").
> >> 
> >> Which really makes you wonder about the usefulness of trying to "fix"
> >> the EDID by skipping extension blocks. It was added in commit
> >> 0ea75e23356f ("DRM: ignore invalid EDID extensions").
> >> 
> >> > Also this memcpy() business seems entirely poinless in the sense
> >> > that we could just read each ext block into the final offset
> >> > directly AFAICS.
> >> 
> >> This is how it was before commit 14544d0937bf.
> >
> > Hmm. This is actually even a bit worse than I though since it
> > looks like we can leak uninitialized stuff from kmalloc_array().
> > I originally thought it was a krealloc()+memmove() but that is
> > not the case.
> >
> >> I guess the point is if
> >> we decide the EDID is garbage, we want to print the original EDID, once,
> >> not something we've already changed. I also kind of like the idea of
> >> hiding the broken EDID path magic in a separate function.
> >
> > I'm wondering we should just stop with this bad block filtering
> > entirely? Just let the block be all zeroes/crap if that is really
> > what we got from the sink. And we could still skip known broken
> > blocks during parsing to avoid getting too confused I guess.
> 
> I think by far the most common extension count must be 1. Especially
> with older displays I think anything beyond 256 bytes is virtually
> non-existent. Agreed?

More than one extension block is certainly pretty rare.

edid-decode has a few with 3 (base + CTA + DispID), and my
edid.tv dump seems to have two with 4 blocks (one has base +
CTA + 2 DispID blocks, the other has base + block map +
2 CTA blocks).

> 
> With that, going from 1 to 0 extensions, it actually works by
> coincidence, no leaks, no uninitialized stuff. (Looks like maybe any
> scenario where it's the last N extensions that are invalid works just
> fine, and it's the broken extensions in the middle that make this go
> haywire.)
> 
> So maybe it's not so scary after all. I could fix that bit first, and
> then proceed with the rest of the series.

I'd fix this up front so we don't end having to backport the whole
thing if/when some security scan gizmo stumbles on this.

> I'm a bit hesitant to make big
> functional changes now, like stopping the filtering entirely, because
> it's not just drm_edid.c parsing the returned EDIDs, parsing is all over
> the place.

Sure. Just threw it out there as a future idea.

> And on that note, my idea (also for HF-EEODB, my end goal) is to move
> towards an opaque struct drm_edid, which is 1) generated and parsed
> exclusively within drm_edid.c, nowhere else, 2) always valid to be
> passed to drm_edid.c (i.e. always be able to handle what we've
> generated, whatever that is). If you want the benefits of HF-EEODB or
> new DisplayID 2.0 features or whatever, you switch your driver to struct
> drm_edid. But you can keep rolling with the legacy struct edid crap ad
> infinitum.

Hopefully we can shame enough people to fix their stuff eventually :P
But yeah, trying to fix it all right now is a bit much.

-- 
Ville Syrjälä
Intel

WARNING: multiple messages have this Message-ID (diff)
From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: Jani Nikula <jani.nikula@intel.com>
Cc: intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: Re: [Intel-gfx] [PATCH 01/12] drm/edid: use struct edid * in drm_do_get_edid()
Date: Wed, 30 Mar 2022 19:50:29 +0300	[thread overview]
Message-ID: <YkSKVRi8g+jGeeSd@intel.com> (raw)
In-Reply-To: <87lewrbe0n.fsf@intel.com>

On Wed, Mar 30, 2022 at 07:28:56PM +0300, Jani Nikula wrote:
> On Wed, 30 Mar 2022, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> > On Wed, Mar 30, 2022 at 06:16:17PM +0300, Jani Nikula wrote:
> >> On Wed, 30 Mar 2022, Ville Syrjälä <ville.syrjala@linux.intel.com> wrote:
> >> > On Tue, Mar 29, 2022 at 09:42:08PM +0300, Jani Nikula wrote:
> >> >> Mixing u8 * and struct edid * is confusing, switch to the latter.
> >> >> 
> >> >> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
> >> >> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> >> >> ---
> >> >>  drivers/gpu/drm/drm_edid.c | 31 +++++++++++++++----------------
> >> >>  1 file changed, 15 insertions(+), 16 deletions(-)
> >> >> 
> >> >> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> >> >> index d79b06f7f34c..0650b9217aa2 100644
> >> >> --- a/drivers/gpu/drm/drm_edid.c
> >> >> +++ b/drivers/gpu/drm/drm_edid.c
> >> >> @@ -1991,29 +1991,28 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
> >> >>  	void *data)
> >> >>  {
> >> >>  	int i, j = 0, valid_extensions = 0;
> >> >> -	u8 *edid, *new;
> >> >> -	struct edid *override;
> >> >> +	struct edid *edid, *new, *override;
> >> >>  
> >> >>  	override = drm_get_override_edid(connector);
> >> >>  	if (override)
> >> >>  		return override;
> >> >>  
> >> >> -	edid = (u8 *)drm_do_get_edid_base_block(connector, get_edid_block, data);
> >> >> +	edid = drm_do_get_edid_base_block(connector, get_edid_block, data);
> >> >>  	if (!edid)
> >> >>  		return NULL;
> >> >>  
> >> >>  	/* if there's no extensions or no connector, we're done */
> >> >> -	valid_extensions = edid[0x7e];
> >> >> +	valid_extensions = edid->extensions;
> >> >>  	if (valid_extensions == 0)
> >> >> -		return (struct edid *)edid;
> >> >> +		return edid;
> >> >>  
> >> >>  	new = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
> >> >>  	if (!new)
> >> >>  		goto out;
> >> >>  	edid = new;
> >> >>  
> >> >> -	for (j = 1; j <= edid[0x7e]; j++) {
> >> >> -		u8 *block = edid + j * EDID_LENGTH;
> >> >> +	for (j = 1; j <= edid->extensions; j++) {
> >> >> +		void *block = edid + j;
> >> >>  
> >> >>  		for (i = 0; i < 4; i++) {
> >> >>  			if (get_edid_block(data, block, j, EDID_LENGTH))
> >> >> @@ -2026,13 +2025,13 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
> >> >>  			valid_extensions--;
> >> >>  	}
> >> >>  
> >> >> -	if (valid_extensions != edid[0x7e]) {
> >> >> -		u8 *base;
> >> >> +	if (valid_extensions != edid->extensions) {
> >> >> +		struct edid *base;
> >> >
> >> > This one points to extension blocks too so using 
> >> > struct edid doesn't seem entirely appropriate.
> >> 
> >> So I've gone back and forth with this. I think I want to get rid of u8*
> >> no matter what, because it always requires casting. I've used void* here
> >> and there to allow mixed use, internally in drm_edid.c while
> >> transitioning, and in public interfaces due to usage all over the place.
> >> 
> >> OTOH I don't much like arithmetics on void*. It's a gcc extension.
> >> 
> >> struct edid * is useful for e.g. ->checksum and arithmetics. In many
> >> places I've named it struct edid *block to distinguish. We could have a
> >> struct edid_block too, which could have ->tag and ->checksum members,
> >> for example, but then it would require casting or a function for "safe"
> >> typecasting.
> >> 
> >> I've also gone back and forth with the helpers for getting a pointer to
> >> a block. For usage like this, kind of need both const and non-const
> >> versions. And, with the plans I have for future, I'm not sure I want to
> >> promote any EDID parsing outside of drm_edid.c, so maybe they should be
> >> static.
> >> 
> >> Undecided. C is a bit clunky here.
> >> 
> >> >
> >> >>  
> >> >> -		connector_bad_edid(connector, edid, edid[0x7e] + 1);
> >> >> +		connector_bad_edid(connector, (u8 *)edid, edid->extensions + 1);
> >> >>  
> >> >> -		edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
> >> >> -		edid[0x7e] = valid_extensions;
> >> >> +		edid->checksum += edid->extensions - valid_extensions;
> >> >> +		edid->extensions = valid_extensions;
> >> >>  
> >> >>  		new = kmalloc_array(valid_extensions + 1, EDID_LENGTH,
> >> >>  				    GFP_KERNEL);
> >> >> @@ -2040,21 +2039,21 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
> >> >>  			goto out;
> >> >>  
> >> >>  		base = new;
> >> >> -		for (i = 0; i <= edid[0x7e]; i++) {
> >> >> -			u8 *block = edid + i * EDID_LENGTH;
> >> >> +		for (i = 0; i <= edid->extensions; i++) {
> >> >> +			void *block = edid + i;
> >> >
> >> > Hmm. This code seems very broken to me. We read each block
> >> > into its expected offset based on the original base block extension
> >> > count, but here we only iterate up to the new ext block count. So
> >> > if we had eg. a 4 block EDID where block 2 is busted, we set 
> >> > the new ext count to 2, copy over blocks 0 and 1, skip block 2,
> >> > and then terminate the loop. So instead of copying block 3 from
> >> > the orignal EDID into block 2 of the new EDID, we leave the
> >> > original garbage block 2 in place.
> >> 
> >> Ugh. I end up fixing this in the series, in "drm/edid: split out invalid
> >> block filtering to a separate function", but I don't mention it
> >> anywhere.
> >> 
> >> Looks like it's been broken for 5+ years since commit 14544d0937bf
> >> ("drm/edid: Only print the bad edid when aborting").
> >> 
> >> Which really makes you wonder about the usefulness of trying to "fix"
> >> the EDID by skipping extension blocks. It was added in commit
> >> 0ea75e23356f ("DRM: ignore invalid EDID extensions").
> >> 
> >> > Also this memcpy() business seems entirely poinless in the sense
> >> > that we could just read each ext block into the final offset
> >> > directly AFAICS.
> >> 
> >> This is how it was before commit 14544d0937bf.
> >
> > Hmm. This is actually even a bit worse than I though since it
> > looks like we can leak uninitialized stuff from kmalloc_array().
> > I originally thought it was a krealloc()+memmove() but that is
> > not the case.
> >
> >> I guess the point is if
> >> we decide the EDID is garbage, we want to print the original EDID, once,
> >> not something we've already changed. I also kind of like the idea of
> >> hiding the broken EDID path magic in a separate function.
> >
> > I'm wondering we should just stop with this bad block filtering
> > entirely? Just let the block be all zeroes/crap if that is really
> > what we got from the sink. And we could still skip known broken
> > blocks during parsing to avoid getting too confused I guess.
> 
> I think by far the most common extension count must be 1. Especially
> with older displays I think anything beyond 256 bytes is virtually
> non-existent. Agreed?

More than one extension block is certainly pretty rare.

edid-decode has a few with 3 (base + CTA + DispID), and my
edid.tv dump seems to have two with 4 blocks (one has base +
CTA + 2 DispID blocks, the other has base + block map +
2 CTA blocks).

> 
> With that, going from 1 to 0 extensions, it actually works by
> coincidence, no leaks, no uninitialized stuff. (Looks like maybe any
> scenario where it's the last N extensions that are invalid works just
> fine, and it's the broken extensions in the middle that make this go
> haywire.)
> 
> So maybe it's not so scary after all. I could fix that bit first, and
> then proceed with the rest of the series.

I'd fix this up front so we don't end having to backport the whole
thing if/when some security scan gizmo stumbles on this.

> I'm a bit hesitant to make big
> functional changes now, like stopping the filtering entirely, because
> it's not just drm_edid.c parsing the returned EDIDs, parsing is all over
> the place.

Sure. Just threw it out there as a future idea.

> And on that note, my idea (also for HF-EEODB, my end goal) is to move
> towards an opaque struct drm_edid, which is 1) generated and parsed
> exclusively within drm_edid.c, nowhere else, 2) always valid to be
> passed to drm_edid.c (i.e. always be able to handle what we've
> generated, whatever that is). If you want the benefits of HF-EEODB or
> new DisplayID 2.0 features or whatever, you switch your driver to struct
> drm_edid. But you can keep rolling with the legacy struct edid crap ad
> infinitum.

Hopefully we can shame enough people to fix their stuff eventually :P
But yeah, trying to fix it all right now is a bit much.

-- 
Ville Syrjälä
Intel

  reply	other threads:[~2022-03-30 16:50 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-29 18:42 [PATCH 00/12] drm/edid: cleanup and refactoring around validity checks Jani Nikula
2022-03-29 18:42 ` [Intel-gfx] " Jani Nikula
2022-03-29 18:42 ` [PATCH 01/12] drm/edid: use struct edid * in drm_do_get_edid() Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-30 13:05   ` Ville Syrjälä
2022-03-30 13:05     ` [Intel-gfx] " Ville Syrjälä
2022-03-30 15:16     ` Jani Nikula
2022-03-30 15:16       ` [Intel-gfx] " Jani Nikula
2022-03-30 15:39       ` Ville Syrjälä
2022-03-30 15:39         ` [Intel-gfx] " Ville Syrjälä
2022-03-30 16:28         ` Jani Nikula
2022-03-30 16:28           ` [Intel-gfx] " Jani Nikula
2022-03-30 16:50           ` Ville Syrjälä [this message]
2022-03-30 16:50             ` Ville Syrjälä
2022-03-30 17:09             ` Jani Nikula
2022-03-30 21:01       ` Jani Nikula
2022-03-30 21:01         ` [Intel-gfx] " Jani Nikula
2022-03-31 18:46     ` Jani Nikula
2022-03-31 18:46       ` [Intel-gfx] " Jani Nikula
2022-03-29 18:42 ` [PATCH 02/12] drm/edid: clean up EDID block checksum functions Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-29 18:42 ` [PATCH 03/12] drm/edid: add edid_block_tag() helper to get the EDID extension tag Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-29 18:42 ` [PATCH 04/12] drm/edid: make drm_edid_header_is_valid() accept void pointer Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-29 18:42 ` [PATCH 05/12] drm/edid: clean up edid_is_zero() Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-29 18:42 ` [PATCH 06/12] drm/edid: split out edid_header_fix() Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-29 18:42 ` [PATCH 07/12] drm/edid: split drm_edid_block_valid() to check and act parts Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-31 14:54   ` Ville Syrjälä
2022-03-31 14:54     ` [Intel-gfx] " Ville Syrjälä
2022-03-31 15:54     ` Jani Nikula
2022-03-31 15:54       ` [Intel-gfx] " Jani Nikula
2022-03-31 16:49     ` Jani Nikula
2022-03-31 16:49       ` [Intel-gfx] " Jani Nikula
2022-03-31 16:58       ` Ville Syrjälä
2022-03-31 16:58         ` [Intel-gfx] " Ville Syrjälä
2022-03-29 18:42 ` [PATCH 08/12] drm/edid: use a better variable name for EDID block read retries Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-31 14:55   ` Ville Syrjälä
2022-03-31 14:55     ` [Intel-gfx] " Ville Syrjälä
2022-03-29 18:42 ` [PATCH 09/12] drm/edid: simplify block check when filtering invalid blocks Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-29 18:42 ` [PATCH 10/12] drm/edid: split out invalid block filtering to a separate function Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-29 18:42 ` [PATCH 11/12] drm/edid: track invalid blocks in drm_do_get_edid() Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-29 18:42 ` [PATCH 12/12] drm/edid: reduce magic when updating the EDID block checksum Jani Nikula
2022-03-29 18:42   ` [Intel-gfx] " Jani Nikula
2022-03-31 14:59   ` Ville Syrjälä
2022-03-31 14:59     ` [Intel-gfx] " Ville Syrjälä
2022-03-29 19:33 ` [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/edid: cleanup and refactoring around validity checks Patchwork
2022-03-29 19:37 ` [Intel-gfx] ✗ Fi.CI.DOCS: " Patchwork
2022-03-29 20:09 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2022-03-29 21:26 ` [Intel-gfx] ✓ Fi.CI.IGT: " Patchwork
2022-03-31 17:07 ` [PATCH 00/12] " Ville Syrjälä
2022-03-31 17:07   ` [Intel-gfx] " Ville Syrjälä

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=YkSKVRi8g+jGeeSd@intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jani.nikula@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.