Linux-Next discussions
 help / color / mirror / Atom feed
From: Mark Brown <broonie@kernel.org>
To: Dave Airlie <airlied@redhat.com>, DRI <dri-devel@lists.freedesktop.org>
Cc: Alex Deucher <alexander.deucher@amd.com>,
	Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	Linux Next Mailing List <linux-next@vger.kernel.org>,
	Mario Limonciello <mario.limonciello@amd.com>
Subject: linux-next: manual merge of the drm tree with the drm-fixes tree
Date: Fri, 17 Jul 2026 15:40:30 +0100	[thread overview]
Message-ID: <alo-3o3jWIAqs2ao@sirena.org.uk> (raw)

[-- Attachment #1: Type: text/plain, Size: 16124 bytes --]

Hi all,

Today's linux-next merge of the drm tree got a conflict in:

  drivers/gpu/drm/amd/amdgpu/amdgpu_device.c

between commit:

  8ad5ab4da7db2 ("drm/amdgpu: Disable PCIe dynamic speed switching on Ryzen Pinnacle Ridge")

from the drm-fixes tree and commits:

  9ceb4e034a327 ("drm/amdgpu: Disable PCIe dynamic speed switching on Ryzen Pinnacle Ridge")
  a57c68224d739 ("drm/amd: Move dynamic PCIe switching quirks to X86_MATCH_* macros")

from the drm tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

diff --combined drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index e5f26e5892bac,472e96ae884e5..0000000000000
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@@ -72,8 -72,10 +72,10 @@@
  
  #include "amdgpu_xgmi.h"
  #include "amdgpu_ras.h"
+ #include "amdgpu_wb.h"
  #include "amdgpu_ras_mgr.h"
  #include "amdgpu_pmu.h"
+ #include "amdgpu_smu.h"
  #include "amdgpu_fru_eeprom.h"
  #include "amdgpu_reset.h"
  #include "amdgpu_virt.h"
@@@ -1005,109 -1007,6 +1007,6 @@@ int amdgpu_device_pci_reset(struct amdg
  	return pci_reset_function(adev->pdev);
  }
  
- /*
-  * amdgpu_device_wb_*()
-  * Writeback is the method by which the GPU updates special pages in memory
-  * with the status of certain GPU events (fences, ring pointers,etc.).
-  */
- 
- /**
-  * amdgpu_device_wb_fini - Disable Writeback and free memory
-  *
-  * @adev: amdgpu_device pointer
-  *
-  * Disables Writeback and frees the Writeback memory (all asics).
-  * Used at driver shutdown.
-  */
- static void amdgpu_device_wb_fini(struct amdgpu_device *adev)
- {
- 	if (adev->wb.wb_obj) {
- 		amdgpu_bo_free_kernel(&adev->wb.wb_obj,
- 				      &adev->wb.gpu_addr,
- 				      (void **)&adev->wb.wb);
- 		adev->wb.wb_obj = NULL;
- 	}
- }
- 
- /**
-  * amdgpu_device_wb_init - Init Writeback driver info and allocate memory
-  *
-  * @adev: amdgpu_device pointer
-  *
-  * Initializes writeback and allocates writeback memory (all asics).
-  * Used at driver startup.
-  * Returns 0 on success or an -error on failure.
-  */
- static int amdgpu_device_wb_init(struct amdgpu_device *adev)
- {
- 	int r;
- 
- 	if (adev->wb.wb_obj == NULL) {
- 		/* AMDGPU_MAX_WB * sizeof(uint32_t) * 8 = AMDGPU_MAX_WB 256bit slots */
- 		r = amdgpu_bo_create_kernel(adev, AMDGPU_MAX_WB * sizeof(uint32_t) * 8,
- 					    PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT,
- 					    &adev->wb.wb_obj, &adev->wb.gpu_addr,
- 					    (void **)&adev->wb.wb);
- 		if (r) {
- 			dev_warn(adev->dev, "(%d) create WB bo failed\n", r);
- 			return r;
- 		}
- 
- 		adev->wb.num_wb = AMDGPU_MAX_WB;
- 		memset(&adev->wb.used, 0, sizeof(adev->wb.used));
- 
- 		/* clear wb memory */
- 		memset((char *)adev->wb.wb, 0, AMDGPU_MAX_WB * sizeof(uint32_t) * 8);
- 	}
- 
- 	return 0;
- }
- 
- /**
-  * amdgpu_device_wb_get - Allocate a wb entry
-  *
-  * @adev: amdgpu_device pointer
-  * @wb: wb index
-  *
-  * Allocate a wb slot for use by the driver (all asics).
-  * Returns 0 on success or -EINVAL on failure.
-  */
- int amdgpu_device_wb_get(struct amdgpu_device *adev, u32 *wb)
- {
- 	unsigned long flags, offset;
- 
- 	spin_lock_irqsave(&adev->wb.lock, flags);
- 	offset = find_first_zero_bit(adev->wb.used, adev->wb.num_wb);
- 	if (offset < adev->wb.num_wb) {
- 		__set_bit(offset, adev->wb.used);
- 		spin_unlock_irqrestore(&adev->wb.lock, flags);
- 		*wb = offset << 3; /* convert to dw offset */
- 		return 0;
- 	} else {
- 		spin_unlock_irqrestore(&adev->wb.lock, flags);
- 		return -EINVAL;
- 	}
- }
- 
- /**
-  * amdgpu_device_wb_free - Free a wb entry
-  *
-  * @adev: amdgpu_device pointer
-  * @wb: wb index
-  *
-  * Free a wb slot allocated for use by the driver (all asics)
-  */
- void amdgpu_device_wb_free(struct amdgpu_device *adev, u32 wb)
- {
- 	unsigned long flags;
- 
- 	wb >>= 3;
- 	spin_lock_irqsave(&adev->wb.lock, flags);
- 	if (wb < adev->wb.num_wb)
- 		__clear_bit(wb, adev->wb.used);
- 	spin_unlock_irqrestore(&adev->wb.lock, flags);
- }
- 
  /**
   * amdgpu_device_resize_fb_bar - try to resize FB BAR
   *
@@@ -1304,37 -1203,44 +1203,44 @@@ bool amdgpu_device_seamless_boot_suppor
  	return amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0);
  }
  
- /*
-  * Intel hosts such as Rocket Lake, Alder Lake, Raptor Lake and Sapphire Rapids
-  * don't support dynamic speed switching. Until we have confirmation from Intel
-  * that a specific host supports it, it's safer that we keep it disabled for all.
-  *
-  * https://edc.intel.com/content/www/us/en/design/products/platforms/details/raptor-lake-s/13th-generation-core-processors-datasheet-volume-1-of-2/005/pci-express-support/
-  * https://gitlab.freedesktop.org/drm/amd/-/issues/2663
-  */
- static bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device *adev)
- {
  #if IS_ENABLED(CONFIG_X86)
- 	struct cpuinfo_x86 *c = &cpu_data(0);
- 
- 	/* eGPU change speeds based on USB4 fabric conditions */
- 	if (dev_is_removable(adev->dev))
- 		return true;
- 
- 	if (c->x86_vendor == X86_VENDOR_INTEL)
- 		return false;
- 
+ static const struct x86_cpu_id amdgpu_pcie_dynamic_switching_quirks[] = {
+ 	/*
+ 	 * Intel hosts such as Rocket Lake, Alder Lake, Raptor Lake and Sapphire Rapids
+ 	 * don't support dynamic speed switching. Until we have confirmation from Intel
+ 	 * that a specific host supports it, it's safer that we keep it disabled for all.
+ 	 *
+ 	 * https://edc.intel.com/content/www/us/en/design/products/platforms/details/raptor-lake-s/13th-generation-core-processors-datasheet-volume-1-of-2/005/pci-express-support/
+ 	 * https://gitlab.freedesktop.org/drm/amd/-/issues/2663
+ 	 */
+ 	X86_MATCH_VENDOR_FAM(INTEL, X86_FAMILY_ANY, NULL),
  	/*
  	 * AMD Ryzen Pinnacle Ridge (Zen+, family 0x17 model 0x08) CPUs don't
  	 * support PCIe dynamic speed switching.
  	 * https://gitlab.freedesktop.org/drm/amd/-/work_items/5436
  	 */
- 	if (c->x86_vendor == X86_VENDOR_AMD && c->x86 == 0x17 &&
- 	    c->x86_model == 0x08)
+ 	X86_MATCH_VENDOR_FAM_MODEL(AMD, 0x17, 0x08, NULL),
+ 	{}
+ };
+ 
+ static bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device *adev)
+ {
+ 	/* eGPU change speeds based on USB4 fabric conditions */
+ 	if (dev_is_removable(adev->dev))
+ 		return true;
+ 
+ 	/* Hosts have problems with dynamic speed switching */
+ 	if (x86_match_cpu(amdgpu_pcie_dynamic_switching_quirks))
  		return false;
- #endif
+ 
  	return true;
  }
+ #else
+ static inline bool amdgpu_device_pcie_dynamic_switching_supported(struct amdgpu_device *adev)
+ {
+ 	return true;
+ }
+ #endif
  
  static bool amdgpu_device_aspm_support_quirk(struct amdgpu_device *adev)
  {
@@@ -2140,6 -2046,8 +2046,8 @@@ static int amdgpu_device_ip_early_init(
  	adev->cg_flags &= amdgpu_cg_mask;
  	adev->pg_flags &= amdgpu_pg_mask;
  
+ 	amdgpu_smu_early_init(adev);
+ 
  	return 0;
  }
  
@@@ -2380,10 -2288,10 +2288,10 @@@ static int amdgpu_device_ip_init(struc
  					r);
  				goto init_failed;
  			}
- 			r = amdgpu_device_wb_init(adev);
+ 			r = amdgpu_wb_init(adev);
  			if (r) {
  				dev_err(adev->dev,
- 					"amdgpu_device_wb_init failed %d\n", r);
+ 					"amdgpu_wb_init failed %d\n", r);
  				goto init_failed;
  			}
  			adev->ip_blocks[i].status.hw = true;
@@@ -2915,7 -2823,7 +2823,7 @@@ static int amdgpu_device_ip_fini(struc
  		if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
  			amdgpu_ucode_free_bo(adev);
  			amdgpu_free_static_csa(&adev->virt.csa_obj);
- 			amdgpu_device_wb_fini(adev);
+ 			amdgpu_wb_fini(adev);
  			amdgpu_device_mem_scratch_fini(adev);
  			amdgpu_ib_pool_fini(adev);
  			amdgpu_seq64_fini(adev);
@@@ -3687,6 -3595,10 +3595,10 @@@ static void amdgpu_device_sys_interface
  		amdgpu_pm_sysfs_fini(adev);
  	if (adev->ucode_sysfs_en)
  		amdgpu_ucode_sysfs_fini(adev);
+ 
+ 	amdgpu_discovery_sysfs_fini(adev);
+ 	amdgpu_preempt_mgr_sysfs_fini(adev);
+ 
  	amdgpu_device_attr_sysfs_fini(adev);
  	amdgpu_fru_sysfs_fini(adev);
  
@@@ -3783,6 -3695,7 +3695,7 @@@ int amdgpu_device_init(struct amdgpu_de
  
  	spin_lock_init(&adev->irq.lock);
  
+ 	amdgpu_early_init_rlc_reg_funcs(adev);
  	amdgpu_device_init_apu_flags(adev);
  
  	r = amdgpu_device_check_arguments(adev);
@@@ -4218,6 -4131,7 +4131,7 @@@ void amdgpu_device_fini_hw(struct amdgp
  
  	if (adev->mman.initialized)
  		drain_workqueue(adev->mman.bdev.wq);
+ 
  	adev->shutdown = true;
  
  	unregister_pm_notifier(&adev->pm_nb);
@@@ -4716,161 -4630,6 +4630,6 @@@ exit
  	return 0;
  }
  
- /**
-  * amdgpu_device_ip_check_soft_reset - did soft reset succeed
-  *
-  * @adev: amdgpu_device pointer
-  *
-  * The list of all the hardware IPs that make up the asic is walked and
-  * the check_soft_reset callbacks are run.  check_soft_reset determines
-  * if the asic is still hung or not.
-  * Returns true if any of the IPs are still in a hung state, false if not.
-  */
- static bool amdgpu_device_ip_check_soft_reset(struct amdgpu_device *adev)
- {
- 	int i;
- 	bool asic_hang = false;
- 
- 	if (amdgpu_sriov_vf(adev))
- 		return true;
- 
- 	if (amdgpu_asic_need_full_reset(adev))
- 		return true;
- 
- 	for (i = 0; i < adev->num_ip_blocks; i++) {
- 		if (!adev->ip_blocks[i].status.valid)
- 			continue;
- 		if (adev->ip_blocks[i].version->funcs->check_soft_reset)
- 			adev->ip_blocks[i].status.hang =
- 				adev->ip_blocks[i].version->funcs->check_soft_reset(
- 					&adev->ip_blocks[i]);
- 		if (adev->ip_blocks[i].status.hang) {
- 			dev_info(adev->dev, "IP block:%s is hung!\n", adev->ip_blocks[i].version->funcs->name);
- 			asic_hang = true;
- 		}
- 	}
- 	return asic_hang;
- }
- 
- /**
-  * amdgpu_device_ip_pre_soft_reset - prepare for soft reset
-  *
-  * @adev: amdgpu_device pointer
-  *
-  * The list of all the hardware IPs that make up the asic is walked and the
-  * pre_soft_reset callbacks are run if the block is hung.  pre_soft_reset
-  * handles any IP specific hardware or software state changes that are
-  * necessary for a soft reset to succeed.
-  * Returns 0 on success, negative error code on failure.
-  */
- static int amdgpu_device_ip_pre_soft_reset(struct amdgpu_device *adev)
- {
- 	int i, r = 0;
- 
- 	for (i = 0; i < adev->num_ip_blocks; i++) {
- 		if (!adev->ip_blocks[i].status.valid)
- 			continue;
- 		if (adev->ip_blocks[i].status.hang &&
- 		    adev->ip_blocks[i].version->funcs->pre_soft_reset) {
- 			r = adev->ip_blocks[i].version->funcs->pre_soft_reset(&adev->ip_blocks[i]);
- 			if (r)
- 				return r;
- 		}
- 	}
- 
- 	return 0;
- }
- 
- /**
-  * amdgpu_device_ip_need_full_reset - check if a full asic reset is needed
-  *
-  * @adev: amdgpu_device pointer
-  *
-  * Some hardware IPs cannot be soft reset.  If they are hung, a full gpu
-  * reset is necessary to recover.
-  * Returns true if a full asic reset is required, false if not.
-  */
- static bool amdgpu_device_ip_need_full_reset(struct amdgpu_device *adev)
- {
- 	int i;
- 
- 	if (amdgpu_asic_need_full_reset(adev))
- 		return true;
- 
- 	for (i = 0; i < adev->num_ip_blocks; i++) {
- 		if (!adev->ip_blocks[i].status.valid)
- 			continue;
- 		if ((adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) ||
- 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_SMC) ||
- 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_ACP) ||
- 		    (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) ||
- 		     adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) {
- 			if (adev->ip_blocks[i].status.hang) {
- 				dev_info(adev->dev, "Some block need full reset!\n");
- 				return true;
- 			}
- 		}
- 	}
- 	return false;
- }
- 
- /**
-  * amdgpu_device_ip_soft_reset - do a soft reset
-  *
-  * @adev: amdgpu_device pointer
-  *
-  * The list of all the hardware IPs that make up the asic is walked and the
-  * soft_reset callbacks are run if the block is hung.  soft_reset handles any
-  * IP specific hardware or software state changes that are necessary to soft
-  * reset the IP.
-  * Returns 0 on success, negative error code on failure.
-  */
- static int amdgpu_device_ip_soft_reset(struct amdgpu_device *adev)
- {
- 	int i, r = 0;
- 
- 	for (i = 0; i < adev->num_ip_blocks; i++) {
- 		if (!adev->ip_blocks[i].status.valid)
- 			continue;
- 		if (adev->ip_blocks[i].status.hang &&
- 		    adev->ip_blocks[i].version->funcs->soft_reset) {
- 			r = adev->ip_blocks[i].version->funcs->soft_reset(&adev->ip_blocks[i]);
- 			if (r)
- 				return r;
- 		}
- 	}
- 
- 	return 0;
- }
- 
- /**
-  * amdgpu_device_ip_post_soft_reset - clean up from soft reset
-  *
-  * @adev: amdgpu_device pointer
-  *
-  * The list of all the hardware IPs that make up the asic is walked and the
-  * post_soft_reset callbacks are run if the asic was hung.  post_soft_reset
-  * handles any IP specific hardware or software state changes that are
-  * necessary after the IP has been soft reset.
-  * Returns 0 on success, negative error code on failure.
-  */
- static int amdgpu_device_ip_post_soft_reset(struct amdgpu_device *adev)
- {
- 	int i, r = 0;
- 
- 	for (i = 0; i < adev->num_ip_blocks; i++) {
- 		if (!adev->ip_blocks[i].status.valid)
- 			continue;
- 		if (adev->ip_blocks[i].status.hang &&
- 		    adev->ip_blocks[i].version->funcs->post_soft_reset)
- 			r = adev->ip_blocks[i].version->funcs->post_soft_reset(&adev->ip_blocks[i]);
- 		if (r)
- 			return r;
- 	}
- 
- 	return 0;
- }
- 
  /**
   * amdgpu_device_reset_sriov - reset ASIC for SR-IOV vf
   *
@@@ -5162,20 -4921,7 +4921,7 @@@ int amdgpu_device_pre_asic_reset(struc
  
  	/* Don't suspend on bare metal if we are not going to HW reset the ASIC */
  	if (!amdgpu_sriov_vf(adev)) {
- 
- 		if (!need_full_reset)
- 			need_full_reset = amdgpu_device_ip_need_full_reset(adev);
- 
- 		if (!need_full_reset && amdgpu_gpu_recovery &&
- 		    amdgpu_device_ip_check_soft_reset(adev)) {
- 			amdgpu_device_ip_pre_soft_reset(adev);
- 			r = amdgpu_device_ip_soft_reset(adev);
- 			amdgpu_device_ip_post_soft_reset(adev);
- 			if (r || amdgpu_device_ip_check_soft_reset(adev)) {
- 				dev_info(adev->dev, "soft reset failed, will fallback to full reset!\n");
- 				need_full_reset = true;
- 			}
- 		}
+ 		need_full_reset = true;
  
  		if (!test_bit(AMDGPU_SKIP_COREDUMP, &reset_context->flags)) {
  			dev_info(tmp_adev->dev, "Dumping IP State\n");
@@@ -5628,8 -5374,7 +5374,7 @@@ static void amdgpu_device_halt_activiti
  		drm_client_dev_suspend(adev_to_drm(tmp_adev));
  
  		/* disable ras on ALL IPs */
- 		if (!need_emergency_restart && !amdgpu_reset_in_dpc(adev) &&
- 		    amdgpu_device_ip_need_full_reset(tmp_adev))
+ 		if (!need_emergency_restart && !amdgpu_reset_in_dpc(adev))
  			amdgpu_ras_suspend(tmp_adev);
  
  		amdgpu_userq_pre_reset(tmp_adev);
@@@ -6901,7 -6646,7 +6646,7 @@@ ssize_t amdgpu_get_soft_full_reset_mask
  
  	if (unlikely(!ring->adev->debug_disable_soft_recovery) &&
  	    !amdgpu_sriov_vf(ring->adev) && ring->funcs->soft_recovery)
- 		size |= AMDGPU_RESET_TYPE_SOFT_RESET;
+ 		size |= AMDGPU_RESET_TYPE_SOFT_RECOVERY;
  
  	return size;
  }
@@@ -6917,8 -6662,8 +6662,8 @@@ ssize_t amdgpu_show_reset_mask(char *bu
  
  	}
  
- 	if (supported_reset & AMDGPU_RESET_TYPE_SOFT_RESET)
- 		size += sysfs_emit_at(buf, size, "soft ");
+ 	if (supported_reset & AMDGPU_RESET_TYPE_SOFT_RECOVERY)
+ 		size += sysfs_emit_at(buf, size, "soft_recovery ");
  
  	if (supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE)
  		size += sysfs_emit_at(buf, size, "queue ");

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

             reply	other threads:[~2026-07-17 14:40 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-17 14:40 Mark Brown [this message]
  -- strict thread matches above, loose matches on Subject: below --
2026-07-17 14:41 linux-next: manual merge of the drm tree with the drm-fixes tree Mark Brown
2026-07-17 14:40 Mark Brown
2026-07-17 14:40 Mark Brown
2026-07-17 14:40 Mark Brown
2026-07-17 14:40 Mark Brown
2026-07-17 15:12 ` Mark Brown
2026-07-10 12:11 Mark Brown
2026-05-29 22:00 Mark Brown
2026-04-03 13:33 Mark Brown
2026-03-27 20:52 Mark Brown
2026-03-27 20:46 Mark Brown
2026-03-09 14:35 Mark Brown
2026-03-06 13:47 Mark Brown
2026-03-06 13:47 Mark Brown
2026-01-30 15:37 Mark Brown
2026-01-30 15:28 Mark Brown
2026-01-23 17:45 Mark Brown
2025-06-27  2:58 Stephen Rothwell
2024-10-18  1:56 Stephen Rothwell
2024-06-27 15:08 Mark Brown
2024-06-27 15:00 Mark Brown
2024-06-21 13:21 Mark Brown
2023-08-18  1:53 Stephen Rothwell
2023-02-13  0:23 Stephen Rothwell
2022-09-26 17:49 broonie
2022-02-25 16:37 broonie
2022-02-24 16:33 broonie
2021-08-06 12:04 Mark Brown
2021-08-10 11:56 ` Geert Uytterhoeven
2021-08-10 12:53   ` Stephen Rothwell
2020-07-10  2:28 Stephen Rothwell
2019-08-23  3:20 Stephen Rothwell
2019-07-05  2:50 Stephen Rothwell
2019-03-01  2:23 Stephen Rothwell
2019-03-01 23:29 ` Alex Deucher
2019-03-04  0:54   ` Stephen Rothwell
2019-03-11 12:36     ` Daniel Vetter
2018-12-14  1:51 Stephen Rothwell
2018-12-07  2:38 Stephen Rothwell
2018-12-07  2:31 Stephen Rothwell

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=alo-3o3jWIAqs2ao@sirena.org.uk \
    --to=broonie@kernel.org \
    --cc=airlied@redhat.com \
    --cc=alexander.deucher@amd.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-next@vger.kernel.org \
    --cc=mario.limonciello@amd.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