All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com>
To: Intel-gfx@lists.freedesktop.org
Subject: [CI 24/33] drm/i915: Move i915_gem_chipset_flush to intel_gt
Date: Thu, 20 Jun 2019 21:38:26 +0100	[thread overview]
Message-ID: <20190620203835.1421-24-tvrtko.ursulin@linux.intel.com> (raw)
In-Reply-To: <20190620203835.1421-1-tvrtko.ursulin@linux.intel.com>

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

This aligns better with the rest of restructuring.

v2:
 * Move call out of line. (Chris)

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c  |  5 +++--
 drivers/gpu/drm/i915/gem/i915_gem_phys.c        |  3 ++-
 drivers/gpu/drm/i915/gem/selftests/huge_pages.c |  4 +++-
 drivers/gpu/drm/i915/gt/intel_gt.c              |  9 ++++++++-
 drivers/gpu/drm/i915/gt/intel_gt.h              |  1 +
 drivers/gpu/drm/i915/gt/selftest_hangcheck.c    | 14 ++++++++++----
 drivers/gpu/drm/i915/gt/selftest_workarounds.c  |  5 +++--
 drivers/gpu/drm/i915/i915_drv.h                 |  8 --------
 drivers/gpu/drm/i915/i915_gem.c                 |  3 ++-
 drivers/gpu/drm/i915/selftests/i915_request.c   | 10 ++++++----
 drivers/gpu/drm/i915/selftests/igt_spinner.c    |  7 +++++--
 drivers/gpu/drm/i915/selftests/igt_spinner.h    |  3 +++
 12 files changed, 46 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 5fae0e50aad0..cf8edb6822ee 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -16,6 +16,7 @@
 
 #include "gem/i915_gem_ioctls.h"
 #include "gt/intel_context.h"
+#include "gt/intel_gt.h"
 #include "gt/intel_gt_pm.h"
 
 #include "i915_gem_ioctls.h"
@@ -994,7 +995,7 @@ static void reloc_gpu_flush(struct reloc_cache *cache)
 	__i915_gem_object_flush_map(cache->rq->batch->obj, 0, cache->rq_size);
 	i915_gem_object_unpin_map(cache->rq->batch->obj);
 
-	i915_gem_chipset_flush(cache->rq->i915);
+	intel_gt_chipset_flush(cache->rq->engine->gt);
 
 	i915_request_add(cache->rq);
 	cache->rq = NULL;
@@ -1954,7 +1955,7 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb)
 	eb->exec = NULL;
 
 	/* Unconditionally flush any chipset caches (for streaming writes). */
-	i915_gem_chipset_flush(eb->i915);
+	intel_gt_chipset_flush(eb->engine->gt);
 	return 0;
 
 err_skip:
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
index 2deac933cf59..7b900ee4ed8d 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
@@ -13,6 +13,7 @@
 #include <drm/drm_legacy.h> /* for drm_pci.h! */
 #include <drm/drm_pci.h>
 
+#include "gt/intel_gt.h"
 #include "i915_drv.h"
 #include "i915_gem_object.h"
 #include "i915_scatterlist.h"
@@ -60,7 +61,7 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
 		vaddr += PAGE_SIZE;
 	}
 
-	i915_gem_chipset_flush(to_i915(obj->base.dev));
+	intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
 
 	st = kmalloc(sizeof(*st), GFP_KERNEL);
 	if (!st) {
diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
index b74729b6f353..dcf60a8c229e 100644
--- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
+++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
@@ -10,6 +10,8 @@
 
 #include "gem/i915_gem_pm.h"
 
+#include "gt/intel_gt.h"
+
 #include "igt_gem_utils.h"
 #include "mock_context.h"
 
@@ -926,7 +928,7 @@ gpu_write_dw(struct i915_vma *vma, u64 offset, u32 val)
 	}
 
 	*cmd = MI_BATCH_BUFFER_END;
-	i915_gem_chipset_flush(i915);
+	intel_gt_chipset_flush(vma->vm->gt);
 
 	i915_gem_object_unpin_map(obj);
 
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index 4fd9977fe284..f632b7b5b490 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -180,7 +180,7 @@ void intel_gt_flush_ggtt_writes(struct intel_gt *gt)
 	if (INTEL_INFO(i915)->has_coherent_ggtt)
 		return;
 
-	i915_gem_chipset_flush(i915);
+	intel_gt_chipset_flush(gt);
 
 	with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
 		struct intel_uncore *uncore = gt->uncore;
@@ -191,3 +191,10 @@ void intel_gt_flush_ggtt_writes(struct intel_gt *gt)
 		spin_unlock_irq(&uncore->lock);
 	}
 }
+
+void intel_gt_chipset_flush(struct intel_gt *gt)
+{
+	wmb();
+	if (INTEL_GEN(gt->i915) < 6)
+		intel_gtt_chipset_flush();
+}
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h
index 6073f3617caa..fb064758b591 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt.h
@@ -18,5 +18,6 @@ void intel_gt_clear_error_registers(struct intel_gt *gt,
 				    intel_engine_mask_t engine_mask);
 
 void intel_gt_flush_ggtt_writes(struct intel_gt *gt);
+void intel_gt_chipset_flush(struct intel_gt *gt);
 
 #endif /* __INTEL_GT_H__ */
diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
index 1ee4c923044f..2d773f11e203 100644
--- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
+++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
@@ -25,6 +25,7 @@
 #include <linux/kthread.h>
 
 #include "gem/i915_gem_context.h"
+#include "gt/intel_gt.h"
 #include "intel_engine_pm.h"
 
 #include "i915_selftest.h"
@@ -43,6 +44,7 @@
 
 struct hang {
 	struct drm_i915_private *i915;
+	struct intel_gt *gt;
 	struct drm_i915_gem_object *hws;
 	struct drm_i915_gem_object *obj;
 	struct i915_gem_context *ctx;
@@ -135,6 +137,8 @@ hang_create_request(struct hang *h, struct intel_engine_cs *engine)
 	u32 *batch;
 	int err;
 
+	h->gt = engine->gt;
+
 	if (i915_gem_object_is_active(h->obj)) {
 		struct drm_i915_gem_object *obj;
 		void *vaddr;
@@ -242,7 +246,7 @@ hang_create_request(struct hang *h, struct intel_engine_cs *engine)
 		*batch++ = lower_32_bits(vma->node.start);
 	}
 	*batch++ = MI_BATCH_BUFFER_END; /* not reached */
-	i915_gem_chipset_flush(h->i915);
+	intel_gt_chipset_flush(engine->gt);
 
 	if (rq->engine->emit_init_breadcrumb) {
 		err = rq->engine->emit_init_breadcrumb(rq);
@@ -276,7 +280,9 @@ static u32 hws_seqno(const struct hang *h, const struct i915_request *rq)
 static void hang_fini(struct hang *h)
 {
 	*h->batch = MI_BATCH_BUFFER_END;
-	i915_gem_chipset_flush(h->i915);
+
+	if (h->gt)
+		intel_gt_chipset_flush(h->gt);
 
 	i915_gem_object_unpin_map(h->obj);
 	i915_gem_object_put(h->obj);
@@ -333,7 +339,7 @@ static int igt_hang_sanitycheck(void *arg)
 		i915_request_get(rq);
 
 		*h.batch = MI_BATCH_BUFFER_END;
-		i915_gem_chipset_flush(i915);
+		intel_gt_chipset_flush(engine->gt);
 
 		i915_request_add(rq);
 
@@ -1509,7 +1515,7 @@ static int igt_reset_queue(void *arg)
 		pr_info("%s: Completed %d resets\n", engine->name, count);
 
 		*h.batch = MI_BATCH_BUFFER_END;
-		i915_gem_chipset_flush(i915);
+		intel_gt_chipset_flush(engine->gt);
 
 		i915_request_put(prev);
 
diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
index 9eaf030affd0..931bc33fc46d 100644
--- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
@@ -5,6 +5,7 @@
  */
 
 #include "gem/i915_gem_pm.h"
+#include "gt/intel_gt.h"
 #include "i915_selftest.h"
 #include "intel_reset.h"
 
@@ -542,7 +543,7 @@ static int check_dirty_whitelist(struct i915_gem_context *ctx,
 
 		i915_gem_object_flush_map(batch->obj);
 		i915_gem_object_unpin_map(batch->obj);
-		i915_gem_chipset_flush(ctx->i915);
+		intel_gt_chipset_flush(engine->gt);
 
 		rq = igt_request_alloc(ctx, engine);
 		if (IS_ERR(rq)) {
@@ -806,7 +807,7 @@ static int scrub_whitelisted_registers(struct i915_gem_context *ctx,
 	*cs++ = MI_BATCH_BUFFER_END;
 
 	i915_gem_object_flush_map(batch->obj);
-	i915_gem_chipset_flush(ctx->i915);
+	intel_gt_chipset_flush(engine->gt);
 
 	rq = igt_request_alloc(ctx, engine);
 	if (IS_ERR(rq)) {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1fd0a73b4b9a..b574aea23581 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2599,14 +2599,6 @@ int __must_check i915_gem_evict_for_node(struct i915_address_space *vm,
 					 unsigned int flags);
 int i915_gem_evict_vm(struct i915_address_space *vm);
 
-/* belongs in i915_gem_gtt.h */
-static inline void i915_gem_chipset_flush(struct drm_i915_private *dev_priv)
-{
-	wmb();
-	if (INTEL_GEN(dev_priv) < 6)
-		intel_gtt_chipset_flush();
-}
-
 /* i915_gem_stolen.c */
 int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
 				struct drm_mm_node *node, u64 size,
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index a9189807cd71..ae36955d819a 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -47,6 +47,7 @@
 #include "gem/i915_gem_pm.h"
 #include "gem/i915_gemfs.h"
 #include "gt/intel_engine_pm.h"
+#include "gt/intel_gt.h"
 #include "gt/intel_gt_pm.h"
 #include "gt/intel_mocs.h"
 #include "gt/intel_reset.h"
@@ -142,7 +143,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
 		return -EFAULT;
 
 	drm_clflush_virt_range(vaddr, args->size);
-	i915_gem_chipset_flush(to_i915(obj->base.dev));
+	intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
 
 	intel_fb_obj_flush(obj, ORIGIN_CPU);
 	return 0;
diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c
index 1a5b9e284ca9..0fdf948a93a0 100644
--- a/drivers/gpu/drm/i915/selftests/i915_request.c
+++ b/drivers/gpu/drm/i915/selftests/i915_request.c
@@ -27,6 +27,8 @@
 #include "gem/i915_gem_pm.h"
 #include "gem/selftests/mock_context.h"
 
+#include "gt/intel_gt.h"
+
 #include "i915_random.h"
 #include "i915_selftest.h"
 #include "igt_live_test.h"
@@ -624,7 +626,7 @@ static struct i915_vma *empty_batch(struct drm_i915_private *i915)
 	__i915_gem_object_flush_map(obj, 0, 64);
 	i915_gem_object_unpin_map(obj);
 
-	i915_gem_chipset_flush(i915);
+	intel_gt_chipset_flush(&i915->gt);
 
 	vma = i915_vma_instance(obj, &i915->ggtt.vm, NULL);
 	if (IS_ERR(vma)) {
@@ -793,7 +795,7 @@ static struct i915_vma *recursive_batch(struct drm_i915_private *i915)
 	__i915_gem_object_flush_map(obj, 0, 64);
 	i915_gem_object_unpin_map(obj);
 
-	i915_gem_chipset_flush(i915);
+	intel_gt_chipset_flush(&i915->gt);
 
 	return vma;
 
@@ -811,7 +813,7 @@ static int recursive_batch_resolve(struct i915_vma *batch)
 		return PTR_ERR(cmd);
 
 	*cmd = MI_BATCH_BUFFER_END;
-	i915_gem_chipset_flush(batch->vm->i915);
+	intel_gt_chipset_flush(batch->vm->gt);
 
 	i915_gem_object_unpin_map(batch->obj);
 
@@ -1033,7 +1035,7 @@ static int live_sequential_engines(void *arg)
 					      I915_MAP_WC);
 		if (!IS_ERR(cmd)) {
 			*cmd = MI_BATCH_BUFFER_END;
-			i915_gem_chipset_flush(i915);
+			intel_gt_chipset_flush(engine->gt);
 
 			i915_gem_object_unpin_map(request[id]->batch->obj);
 		}
diff --git a/drivers/gpu/drm/i915/selftests/igt_spinner.c b/drivers/gpu/drm/i915/selftests/igt_spinner.c
index 1e59b543cf27..0c1f65262a63 100644
--- a/drivers/gpu/drm/i915/selftests/igt_spinner.c
+++ b/drivers/gpu/drm/i915/selftests/igt_spinner.c
@@ -3,6 +3,7 @@
  *
  * Copyright © 2018 Intel Corporation
  */
+#include "gt/intel_gt.h"
 
 #include "gem/selftests/igt_gem_utils.h"
 
@@ -94,6 +95,8 @@ igt_spinner_create_request(struct igt_spinner *spin,
 	u32 *batch;
 	int err;
 
+	spin->gt = engine->gt;
+
 	vma = i915_vma_instance(spin->obj, ctx->vm, NULL);
 	if (IS_ERR(vma))
 		return ERR_CAST(vma);
@@ -138,7 +141,7 @@ igt_spinner_create_request(struct igt_spinner *spin,
 	*batch++ = upper_32_bits(vma->node.start);
 	*batch++ = MI_BATCH_BUFFER_END; /* not reached */
 
-	i915_gem_chipset_flush(spin->i915);
+	intel_gt_chipset_flush(engine->gt);
 
 	if (engine->emit_init_breadcrumb &&
 	    rq->timeline->has_initial_breadcrumb) {
@@ -172,7 +175,7 @@ hws_seqno(const struct igt_spinner *spin, const struct i915_request *rq)
 void igt_spinner_end(struct igt_spinner *spin)
 {
 	*spin->batch = MI_BATCH_BUFFER_END;
-	i915_gem_chipset_flush(spin->i915);
+	intel_gt_chipset_flush(spin->gt);
 }
 
 void igt_spinner_fini(struct igt_spinner *spin)
diff --git a/drivers/gpu/drm/i915/selftests/igt_spinner.h b/drivers/gpu/drm/i915/selftests/igt_spinner.h
index 34a88ac9b47a..1bfc39efa773 100644
--- a/drivers/gpu/drm/i915/selftests/igt_spinner.h
+++ b/drivers/gpu/drm/i915/selftests/igt_spinner.h
@@ -14,8 +14,11 @@
 #include "i915_request.h"
 #include "i915_selftest.h"
 
+struct intel_gt;
+
 struct igt_spinner {
 	struct drm_i915_private *i915;
+	struct intel_gt *gt;
 	struct drm_i915_gem_object *hws;
 	struct drm_i915_gem_object *obj;
 	u32 *batch;
-- 
2.20.1

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

  parent reply	other threads:[~2019-06-20 20:38 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-20 20:38 [CI 01/33] drm/i915: Convert intel_vgt_(de)balloon to uncore Tvrtko Ursulin
2019-06-20 20:38 ` [CI 02/33] drm/i915: Introduce struct intel_gt as replacement for anonymous i915->gt Tvrtko Ursulin
2019-06-20 20:38 ` [CI 03/33] drm/i915: Move intel_gt initialization to a separate file Tvrtko Ursulin
2019-06-20 20:38 ` [CI 04/33] drm/i915: Store some backpointers in struct intel_gt Tvrtko Ursulin
2019-06-20 20:38 ` [CI 05/33] drm/i915: Move intel_gt_pm_init under intel_gt_init_early Tvrtko Ursulin
2019-06-20 20:38 ` [CI 06/33] drm/i915: Make i915_check_and_clear_faults take intel_gt Tvrtko Ursulin
2019-06-20 20:38 ` [CI 07/33] drm/i915: Convert i915_gem_init_swizzling to intel_gt Tvrtko Ursulin
2019-06-20 20:38 ` [CI 08/33] drm/i915: Use intel_uncore_rmw in intel_gt_init_swizzling Tvrtko Ursulin
2019-06-20 20:38 ` [CI 09/33] drm/i915: Convert init_unused_rings to intel_gt Tvrtko Ursulin
2019-06-20 20:38 ` [CI 10/33] drm/i915: Convert gt workarounds " Tvrtko Ursulin
2019-06-20 20:38 ` [CI 11/33] drm/i915: Store backpointer to intel_gt in the engine Tvrtko Ursulin
2019-06-20 20:38 ` [CI 12/33] drm/i915: Convert intel_mocs_init_l3cc_table to intel_gt Tvrtko Ursulin
2019-06-20 20:38 ` [CI 13/33] drm/i915: Convert i915_ppgtt_init_hw " Tvrtko Ursulin
2019-06-20 20:38 ` [CI 14/33] drm/i915: Consolidate some open coded mmio rmw Tvrtko Ursulin
2019-06-20 20:38 ` [CI 15/33] drm/i915: Convert i915_gem_init_hw to intel_gt Tvrtko Ursulin
2019-06-20 20:38 ` [CI 16/33] drm/i915: Move intel_engines_resume into common init Tvrtko Ursulin
2019-06-20 20:38 ` [CI 17/33] drm/i915: Stop using I915_READ/WRITE in intel_wopcm_init_hw Tvrtko Ursulin
2019-06-20 20:38 ` [CI 18/33] drm/i915: Compartmentalize i915_ggtt_probe_hw Tvrtko Ursulin
2019-06-20 20:38 ` [CI 19/33] drm/i915: Compartmentalize i915_ggtt_init_hw Tvrtko Ursulin
2019-06-20 20:38 ` [CI 20/33] drm/i915: Make ggtt invalidation work on ggtt Tvrtko Ursulin
2019-06-20 20:38 ` [CI 21/33] drm/i915: Store intel_gt backpointer in vm Tvrtko Ursulin
2019-06-20 20:38 ` [CI 22/33] drm/i915: Compartmentalize i915_gem_suspend/restore_gtt_mappings Tvrtko Ursulin
2019-06-20 20:38 ` [CI 23/33] drm/i915: Convert i915_gem_flush_ggtt_writes to intel_gt Tvrtko Ursulin
2019-06-20 20:38 ` Tvrtko Ursulin [this message]
2019-06-20 20:38 ` [CI 25/33] drm/i915: Compartmentalize timeline_init/park/fini Tvrtko Ursulin
2019-06-20 20:38 ` [CI 26/33] drm/i915: Compartmentalize i915_ggtt_cleanup_hw Tvrtko Ursulin
2019-06-20 20:38 ` [CI 27/33] drm/i915: Compartmentalize i915_gem_init_ggtt Tvrtko Ursulin
2019-06-20 20:38 ` [CI 28/33] drm/i915: Store ggtt pointer in intel_gt Tvrtko Ursulin
2019-06-20 20:38 ` [CI 29/33] drm/i915: Compartmentalize ring buffer creation Tvrtko Ursulin
2019-06-20 20:38 ` [CI 30/33] drm/i915: Save trip via top-level i915 in a few more places Tvrtko Ursulin
2019-06-20 20:38 ` [CI 31/33] drm/i915: Make timelines gt centric Tvrtko Ursulin
2019-06-20 20:38 ` [CI 32/33] drm/i915: Rename i915_timeline to intel_timeline and move under gt Tvrtko Ursulin
2019-06-20 20:38 ` [CI 33/33] drm/i915: Eliminate dual personality of i915_scratch_offset Tvrtko Ursulin
2019-06-20 23:00 ` ✗ Fi.CI.BAT: failure for series starting with [CI,01/33] drm/i915: Convert intel_vgt_(de)balloon to uncore Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2019-06-21  7:07 [CI 01/33] " Tvrtko Ursulin
2019-06-21  7:08 ` [CI 24/33] drm/i915: Move i915_gem_chipset_flush to intel_gt Tvrtko Ursulin
2019-06-19 21:34 [CI 01/33] drm/i915: Convert intel_vgt_(de)balloon to uncore Tvrtko Ursulin
2019-06-19 21:34 ` [CI 24/33] drm/i915: Move i915_gem_chipset_flush to intel_gt Tvrtko Ursulin

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=20190620203835.1421-24-tvrtko.ursulin@linux.intel.com \
    --to=tvrtko.ursulin@linux.intel.com \
    --cc=Intel-gfx@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 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.