All of lore.kernel.org
 help / color / mirror / Atom feed
From: <sunpeng.li-5C7GfCeVMHo@public.gmane.org>
To: amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org
Cc: David Francis <David.Francis-5C7GfCeVMHo@public.gmane.org>
Subject: [PATCH 05/20] drm/amd/display: Call into DC once per multiplane flip
Date: Tue, 22 Jan 2019 13:28:51 -0500	[thread overview]
Message-ID: <1548181746-23783-6-git-send-email-sunpeng.li@amd.com> (raw)
In-Reply-To: <1548181746-23783-1-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>

From: David Francis <David.Francis@amd.com>

[Why]
amdgpu_dm_commit_planes was performing multi-plane
flips incorrectly:

It waited for vblank once per flipped plane

It prepared flip ISR and acquired the corresponding vblank ref
once per plane, although it closed ISR and put the ref once
per crtc

It called into dc once per flipped plane, duplicating some work

[How]
Wait for vblank, get vblank ref, prepare flip ISR, and call into
DC only once, and only if there is a pageflip

Make freesync continue to update planes even if vrr information
has already been changed

Signed-off-by: David Francis <David.Francis@amd.com>
Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 335 ++++++++++------------
 1 file changed, 154 insertions(+), 181 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index db060da..818a2a1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -4691,12 +4691,12 @@ static void update_freesync_state_on_stream(
 		TRANSFER_FUNC_UNKNOWN,
 		&vrr_infopacket);
 
-	new_crtc_state->freesync_timing_changed =
+	new_crtc_state->freesync_timing_changed |=
 		(memcmp(&new_crtc_state->vrr_params.adjust,
 			&vrr_params.adjust,
 			sizeof(vrr_params.adjust)) != 0);
 
-	new_crtc_state->freesync_vrr_info_changed =
+	new_crtc_state->freesync_vrr_info_changed |=
 		(memcmp(&new_crtc_state->vrr_infopacket,
 			&vrr_infopacket,
 			sizeof(vrr_infopacket)) != 0);
@@ -4721,156 +4721,6 @@ static void update_freesync_state_on_stream(
 }
 
 /*
- * Executes flip
- *
- * Waits on all BO's fences and for proper vblank count
- */
-static void amdgpu_dm_do_flip(struct drm_crtc *crtc,
-			      struct drm_framebuffer *fb,
-			      uint32_t target,
-			      struct dc_state *state)
-{
-	unsigned long flags;
-	uint64_t timestamp_ns;
-	uint32_t target_vblank;
-	int r, vpos, hpos;
-	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
-	struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb);
-	struct amdgpu_bo *abo = gem_to_amdgpu_bo(fb->obj[0]);
-	struct amdgpu_device *adev = crtc->dev->dev_private;
-	bool async_flip = (crtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
-	struct dc_flip_addrs addr = { {0} };
-	/* TODO eliminate or rename surface_update */
-	struct dc_surface_update surface_updates[1] = { {0} };
-	struct dc_stream_update stream_update = {0};
-	struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state);
-	struct dc_stream_status *stream_status;
-	struct dc_plane_state *surface;
-	uint64_t tiling_flags, dcc_address;
-
-
-	/* Prepare wait for target vblank early - before the fence-waits */
-	target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) +
-			amdgpu_get_vblank_counter_kms(crtc->dev, acrtc->crtc_id);
-
-	/*
-	 * TODO This might fail and hence better not used, wait
-	 * explicitly on fences instead
-	 * and in general should be called for
-	 * blocking commit to as per framework helpers
-	 */
-	r = amdgpu_bo_reserve(abo, true);
-	if (unlikely(r != 0)) {
-		DRM_ERROR("failed to reserve buffer before flip\n");
-		WARN_ON(1);
-	}
-
-	/* Wait for all fences on this FB */
-	WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, false,
-								    MAX_SCHEDULE_TIMEOUT) < 0);
-
-	amdgpu_bo_get_tiling_flags(abo, &tiling_flags);
-
-	amdgpu_bo_unreserve(abo);
-
-	/*
-	 * Wait until we're out of the vertical blank period before the one
-	 * targeted by the flip
-	 */
-	while ((acrtc->enabled &&
-		(amdgpu_display_get_crtc_scanoutpos(adev->ddev, acrtc->crtc_id,
-						    0, &vpos, &hpos, NULL,
-						    NULL, &crtc->hwmode)
-		 & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) ==
-		(DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) &&
-		(int)(target_vblank -
-		  amdgpu_get_vblank_counter_kms(adev->ddev, acrtc->crtc_id)) > 0)) {
-		usleep_range(1000, 1100);
-	}
-
-	/* Flip */
-	spin_lock_irqsave(&crtc->dev->event_lock, flags);
-
-	WARN_ON(acrtc->pflip_status != AMDGPU_FLIP_NONE);
-	WARN_ON(!acrtc_state->stream);
-
-	addr.address.grph.addr.low_part = lower_32_bits(afb->address);
-	addr.address.grph.addr.high_part = upper_32_bits(afb->address);
-
-	dcc_address = get_dcc_address(afb->address, tiling_flags);
-	addr.address.grph.meta_addr.low_part = lower_32_bits(dcc_address);
-	addr.address.grph.meta_addr.high_part = upper_32_bits(dcc_address);
-
-	addr.flip_immediate = async_flip;
-
-	timestamp_ns = ktime_get_ns();
-	addr.flip_timestamp_in_us = div_u64(timestamp_ns, 1000);
-
-
-	if (acrtc->base.state->event)
-		prepare_flip_isr(acrtc);
-
-	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-
-	stream_status = dc_stream_get_status(acrtc_state->stream);
-	if (!stream_status) {
-		DRM_ERROR("No stream status for CRTC: id=%d\n",
-			acrtc->crtc_id);
-		return;
-	}
-
-	surface = stream_status->plane_states[0];
-	surface_updates->surface = surface;
-
-	if (!surface) {
-		DRM_ERROR("No surface for CRTC: id=%d\n",
-			acrtc->crtc_id);
-		return;
-	}
-	surface_updates->flip_addr = &addr;
-
-	if (acrtc_state->stream) {
-		update_freesync_state_on_stream(
-			&adev->dm,
-			acrtc_state,
-			acrtc_state->stream,
-			surface,
-			addr.flip_timestamp_in_us);
-
-		if (acrtc_state->freesync_timing_changed)
-			stream_update.adjust =
-				&acrtc_state->stream->adjust;
-
-		if (acrtc_state->freesync_vrr_info_changed)
-			stream_update.vrr_infopacket =
-				&acrtc_state->stream->vrr_infopacket;
-	}
-
-	/* Update surface timing information. */
-	surface->time.time_elapsed_in_us[surface->time.index] =
-		addr.flip_timestamp_in_us - surface->time.prev_update_time_in_us;
-	surface->time.prev_update_time_in_us = addr.flip_timestamp_in_us;
-	surface->time.index++;
-	if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX)
-		surface->time.index = 0;
-
-	mutex_lock(&adev->dm.dc_lock);
-
-	dc_commit_updates_for_stream(adev->dm.dc,
-					     surface_updates,
-					     1,
-					     acrtc_state->stream,
-					     &stream_update,
-					     state);
-	mutex_unlock(&adev->dm.dc_lock);
-
-	DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n",
-			 __func__,
-			 addr.address.grph.addr.high_part,
-			 addr.address.grph.addr.low_part);
-}
-
-/*
  * TODO this whole function needs to go
  *
  * dc_surface_update is needlessly complex. See if we can just replace this
@@ -4976,10 +4826,10 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 				    struct drm_crtc *pcrtc,
 				    bool *wait_for_vblank)
 {
-	uint32_t i;
+	uint32_t i, r;
+	uint64_t timestamp_ns;
 	struct drm_plane *plane;
 	struct drm_plane_state *old_plane_state, *new_plane_state;
-	struct dc_stream_state *dc_stream_attach;
 	struct dc_plane_state *plane_states_constructed[MAX_SURFACES];
 	struct amdgpu_crtc *acrtc_attach = to_amdgpu_crtc(pcrtc);
 	struct drm_crtc_state *new_pcrtc_state =
@@ -4987,8 +4837,23 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 	struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state);
 	struct dm_crtc_state *dm_old_crtc_state =
 			to_dm_crtc_state(drm_atomic_get_old_crtc_state(state, pcrtc));
-	int planes_count = 0;
+	int flip_count = 0, planes_count = 0, vpos, hpos;
 	unsigned long flags;
+	struct amdgpu_bo *abo;
+	uint64_t tiling_flags, dcc_address;
+	struct dc_stream_status *stream_status;
+	uint32_t target, target_vblank;
+
+	struct {
+		struct dc_surface_update surface_updates[MAX_SURFACES];
+		struct dc_flip_addrs flip_addrs[MAX_SURFACES];
+		struct dc_stream_update stream_update;
+	} *flip;
+
+	flip = kzalloc(sizeof(*flip), GFP_KERNEL);
+
+	if (!flip)
+		dm_error("Failed to allocate update bundles\n");
 
 	/* update planes when needed */
 	for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
@@ -4998,8 +4863,10 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 		struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(fb);
 		struct amdgpu_framebuffer *old_afb = to_amdgpu_framebuffer(old_plane_state->fb);
 		bool pflip_needed;
+		struct dc_plane_state *surface;
 		struct dm_plane_state *dm_new_plane_state = to_dm_plane_state(new_plane_state);
 
+
 		if (plane->type == DRM_PLANE_TYPE_CURSOR) {
 			handle_cursor_update(plane, old_plane_state);
 			continue;
@@ -5015,44 +4882,150 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 		pflip_needed = old_plane_state->fb &&
 			(old_plane_state->fb != new_plane_state->fb || afb->address != old_afb->address);
 
-		spin_lock_irqsave(&crtc->dev->event_lock, flags);
-		if (acrtc_attach->pflip_status != AMDGPU_FLIP_NONE) {
-			DRM_ERROR("%s: acrtc %d, already busy\n",
-				  __func__,
-				  acrtc_attach->crtc_id);
-			/* In commit tail framework this cannot happen */
-			WARN_ON(1);
-		}
-		spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-
 		if (!pflip_needed || plane->type == DRM_PLANE_TYPE_OVERLAY) {
 			WARN_ON(!dm_new_plane_state->dc_state);
 
 			plane_states_constructed[planes_count] = dm_new_plane_state->dc_state;
 
-			dc_stream_attach = acrtc_state->stream;
 			planes_count++;
 
 		} else if (new_crtc_state->planes_changed) {
-			/* Assume even ONE crtc with immediate flip means
+			/*
+			 * Assume even ONE crtc with immediate flip means
 			 * entire can't wait for VBLANK
 			 * TODO Check if it's correct
 			 */
-			*wait_for_vblank =
-					new_pcrtc_state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ?
-				false : true;
-
-			/* TODO: Needs rework for multiplane flip */
-			if (plane->type == DRM_PLANE_TYPE_PRIMARY)
-				drm_crtc_vblank_get(crtc);
-
-			amdgpu_dm_do_flip(
-				crtc,
-				fb,
-				(uint32_t)drm_crtc_vblank_count(crtc) + *wait_for_vblank,
-				dc_state);
+			if (new_pcrtc_state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC)
+				*wait_for_vblank = false;
+
+			/*
+			 * TODO This might fail and hence better not used, wait
+			 * explicitly on fences instead
+			 * and in general should be called for
+			 * blocking commit to as per framework helpers
+			 */
+			abo = gem_to_amdgpu_bo(fb->obj[0]);
+			r = amdgpu_bo_reserve(abo, true);
+			if (unlikely(r != 0)) {
+				DRM_ERROR("failed to reserve buffer before flip\n");
+				WARN_ON(1);
+			}
+
+			/* Wait for all fences on this FB */
+			WARN_ON(reservation_object_wait_timeout_rcu(abo->tbo.resv, true, false,
+										    MAX_SCHEDULE_TIMEOUT) < 0);
+
+			amdgpu_bo_get_tiling_flags(abo, &tiling_flags);
+
+			amdgpu_bo_unreserve(abo);
+
+			flip->flip_addrs[flip_count].address.grph.addr.low_part = lower_32_bits(afb->address);
+			flip->flip_addrs[flip_count].address.grph.addr.high_part = upper_32_bits(afb->address);
+
+			dcc_address = get_dcc_address(afb->address, tiling_flags);
+			flip->flip_addrs[flip_count].address.grph.meta_addr.low_part = lower_32_bits(dcc_address);
+			flip->flip_addrs[flip_count].address.grph.meta_addr.high_part = upper_32_bits(dcc_address);
+
+			flip->flip_addrs[flip_count].flip_immediate =
+					(crtc->state->pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;
+
+			timestamp_ns = ktime_get_ns();
+			flip->flip_addrs[flip_count].flip_timestamp_in_us = div_u64(timestamp_ns, 1000);
+			flip->surface_updates[flip_count].flip_addr = &flip->flip_addrs[flip_count];
+
+			stream_status = dc_stream_get_status(acrtc_state->stream);
+			if (!stream_status) {
+				DRM_ERROR("No stream status for CRTC: id=%d\n",
+						acrtc_attach->crtc_id);
+				continue;
+			}
+
+			surface = stream_status->plane_states[0];
+			flip->surface_updates[flip_count].surface = surface;
+			if (!flip->surface_updates[flip_count].surface) {
+				DRM_ERROR("No surface for CRTC: id=%d\n",
+						acrtc_attach->crtc_id);
+				continue;
+			}
+
+			if (acrtc_state->stream)
+				update_freesync_state_on_stream(
+					dm,
+					acrtc_state,
+					acrtc_state->stream,
+					surface,
+					flip->flip_addrs[flip_count].flip_timestamp_in_us);
+
+			/* Update surface timing information. */
+			surface->time.time_elapsed_in_us[surface->time.index] =
+				flip->flip_addrs[flip_count].flip_timestamp_in_us -
+				surface->time.prev_update_time_in_us;
+			surface->time.prev_update_time_in_us = flip->flip_addrs[flip_count].flip_timestamp_in_us;
+			surface->time.index++;
+			if (surface->time.index >= DC_PLANE_UPDATE_TIMES_MAX)
+				surface->time.index = 0;
+
+			DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x\n",
+					 __func__,
+					 flip->flip_addrs[flip_count].address.grph.addr.high_part,
+					 flip->flip_addrs[flip_count].address.grph.addr.low_part);
+
+			flip_count += 1;
+		}
+
+	}
+
+	if (flip_count) {
+		target = (uint32_t)drm_crtc_vblank_count(pcrtc) + *wait_for_vblank;
+		/* Prepare wait for target vblank early - before the fence-waits */
+		target_vblank = target - (uint32_t)drm_crtc_vblank_count(pcrtc) +
+				amdgpu_get_vblank_counter_kms(pcrtc->dev, acrtc_attach->crtc_id);
+
+		/*
+		 * Wait until we're out of the vertical blank period before the one
+		 * targeted by the flip
+		 */
+		while ((acrtc_attach->enabled &&
+			(amdgpu_display_get_crtc_scanoutpos(dm->ddev, acrtc_attach->crtc_id,
+							    0, &vpos, &hpos, NULL,
+							    NULL, &pcrtc->hwmode)
+			 & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) ==
+			(DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) &&
+			(int)(target_vblank -
+			  amdgpu_get_vblank_counter_kms(dm->ddev, acrtc_attach->crtc_id)) > 0)) {
+			usleep_range(1000, 1100);
 		}
 
+		if (acrtc_attach->base.state->event) {
+			drm_crtc_vblank_get(pcrtc);
+
+			spin_lock_irqsave(&pcrtc->dev->event_lock, flags);
+
+			WARN_ON(acrtc_attach->pflip_status != AMDGPU_FLIP_NONE);
+			prepare_flip_isr(acrtc_attach);
+
+			spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
+		}
+
+		if (acrtc_state->stream) {
+
+			if (acrtc_state->freesync_timing_changed)
+				flip->stream_update.adjust =
+					&acrtc_state->stream->adjust;
+
+			if (acrtc_state->freesync_vrr_info_changed)
+				flip->stream_update.vrr_infopacket =
+					&acrtc_state->stream->vrr_infopacket;
+		}
+
+		mutex_lock(&dm->dc_lock);
+		dc_commit_updates_for_stream(dm->dc,
+						     flip->surface_updates,
+						     flip_count,
+						     acrtc_state->stream,
+						     &flip->stream_update,
+						     dc_state);
+		mutex_unlock(&dm->dc_lock);
 	}
 
 	if (planes_count) {
@@ -5067,7 +5040,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
 			spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
 		}
 
-		dc_stream_attach->abm_level = acrtc_state->abm_level;
+		acrtc_state->stream->abm_level = acrtc_state->abm_level;
 
 		if (false == commit_planes_to_stream(dm,
 							dm->dc,
-- 
2.7.4

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

  parent reply	other threads:[~2019-01-22 18:28 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-01-22 18:28 [PATCH 00/20] DC Patches Jan 22, 2019 sunpeng.li-5C7GfCeVMHo
     [not found] ` <1548181746-23783-1-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2019-01-22 18:28   ` [PATCH 01/20] drm/amd/display: Restructure DCN10 hubbub sunpeng.li-5C7GfCeVMHo
2019-01-22 18:28   ` [PATCH 02/20] drm/amd/display: Introduce DC VM interface sunpeng.li-5C7GfCeVMHo
2019-01-22 18:28   ` [PATCH 03/20] drm/amd/display: Simplify underscan and ABM commit sunpeng.li-5C7GfCeVMHo
2019-01-22 18:28   ` [PATCH 04/20] drm/amd/display: Know what a pageflip is sunpeng.li-5C7GfCeVMHo
     [not found]     ` <1548181746-23783-5-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2019-01-23  9:20       ` Michel Dänzer
2019-01-23 16:08       ` Grodzovsky, Andrey
     [not found]         ` <f91f0b7f-6a8c-2efb-ed5d-7fb0d6e38bab-5C7GfCeVMHo@public.gmane.org>
2019-01-23 19:23           ` Kazlauskas, Nicholas
2019-01-22 18:28   ` sunpeng.li-5C7GfCeVMHo [this message]
     [not found]     ` <1548181746-23783-6-git-send-email-sunpeng.li-5C7GfCeVMHo@public.gmane.org>
2019-01-28 11:59       ` [PATCH 05/20] drm/amd/display: Call into DC once per multiplane flip Michel Dänzer
     [not found]         ` <90388e58-87dc-2033-5c36-cf9c903d6b0b-otUistvHUpPR7s880joybQ@public.gmane.org>
2019-01-28 13:47           ` Kazlauskas, Nicholas
2019-01-22 18:28   ` [PATCH 06/20] drm/amd/display: Let updates with no scaling changes be fast sunpeng.li-5C7GfCeVMHo
2019-01-22 18:28   ` [PATCH 07/20] drm/amd/display: Perform plane updates only when needed sunpeng.li-5C7GfCeVMHo
2019-01-22 18:28   ` [PATCH 08/20] drm/amd/display: Update DMCU versioning mechanism sunpeng.li-5C7GfCeVMHo
2019-01-22 18:28   ` [PATCH 09/20] drm/amd/display: Create switching mechanism for ABM 2.2 sunpeng.li-5C7GfCeVMHo
2019-01-22 18:28   ` [PATCH 10/20] drm/amd/display: Fix use of uninitialized union sunpeng.li-5C7GfCeVMHo
2019-01-22 18:28   ` [PATCH 11/20] drm/amd/display: Default to linear output gamma sunpeng.li-5C7GfCeVMHo
2019-01-22 18:28   ` [PATCH 12/20] drm/amd/display: Adjust ABM 2.2 contrast parameters sunpeng.li-5C7GfCeVMHo
2019-01-22 18:28   ` [PATCH 13/20] revert "drm/amd/display: Add condition to sync eDP SW status and HW status" sunpeng.li-5C7GfCeVMHo
2019-01-22 18:29   ` [PATCH 14/20] drm/amd/display: take dpms_off into account for edp turn off logic sunpeng.li-5C7GfCeVMHo
2019-01-22 18:29   ` [PATCH 15/20] drm/amd/display: 3.2.15 sunpeng.li-5C7GfCeVMHo
2019-01-22 18:29   ` [PATCH 16/20] drm/amd/display: Connect dig_fe to otg directly instead of calling bios sunpeng.li-5C7GfCeVMHo
2019-01-22 18:29   ` [PATCH 17/20] drm/amd/display: Poll pending down rep before clear payload allocation table sunpeng.li-5C7GfCeVMHo
2019-01-22 18:29   ` [PATCH 18/20] drm/amd/display: Enable vblank interrupt during CRC capture sunpeng.li-5C7GfCeVMHo
2019-01-22 18:29   ` [PATCH 19/20] drm/amd/display: Re-enable CRC capture following modeset sunpeng.li-5C7GfCeVMHo
2019-01-22 18:29   ` [PATCH 20/20] drm/amd/display: Add Vline1 interrupt source to InterruptManager sunpeng.li-5C7GfCeVMHo

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=1548181746-23783-6-git-send-email-sunpeng.li@amd.com \
    --to=sunpeng.li-5c7gfcevmho@public.gmane.org \
    --cc=David.Francis-5C7GfCeVMHo@public.gmane.org \
    --cc=amd-gfx-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.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 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.