linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: tip-bot for Thomas Gleixner <tipbot@zytor.com>
To: linux-tip-commits@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, keith.busch@intel.com,
	mingo@kernel.org, hpa@zytor.com, peterz@infradead.org,
	hch@lst.de, tglx@linutronix.de, axboe@kernel.dk,
	mpe@ellerman.id.au, marc.zyngier@arm.com
Subject: [tip:irq/core] genirq: Allow fwnode to carry name information only
Date: Thu, 22 Jun 2017 09:42:19 -0700	[thread overview]
Message-ID: <tip-d59f6617eef0f76e34f7a9993f5645c5ef467e42@git.kernel.org> (raw)
In-Reply-To: <20170619235443.588784933@linutronix.de>

Commit-ID:  d59f6617eef0f76e34f7a9993f5645c5ef467e42
Gitweb:     http://git.kernel.org/tip/d59f6617eef0f76e34f7a9993f5645c5ef467e42
Author:     Thomas Gleixner <tglx@linutronix.de>
AuthorDate: Tue, 20 Jun 2017 01:37:05 +0200
Committer:  Thomas Gleixner <tglx@linutronix.de>
CommitDate: Thu, 22 Jun 2017 18:21:08 +0200

genirq: Allow fwnode to carry name information only

In order to provide proper debug interface it's required to have domain
names available when the domain is added. Non fwnode based architectures
like x86 have no way to do so.

It's not possible to use domain ops or host data for this as domain ops
might be the same for several instances, but the names have to be unique.

Extend the irqchip fwnode to allow transporting the domain name. If no node
is supplied, create a 'unknown-N' placeholder.

Warn if an invalid node is supplied and treat it like no node. This happens
e.g. with i2 devices on x86 which hand in an ACPI type node which has no
interface for retrieving the name.

[ Folded a fix from Marc to make DT name parsing work ]

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Keith Busch <keith.busch@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Christoph Hellwig <hch@lst.de>
Link: http://lkml.kernel.org/r/20170619235443.588784933@linutronix.de

---
 include/linux/irqdomain.h |  31 +++++++++++++-
 kernel/irq/irqdomain.c    | 105 ++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 122 insertions(+), 14 deletions(-)

diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h
index 9f36160..9cf32a2 100644
--- a/include/linux/irqdomain.h
+++ b/include/linux/irqdomain.h
@@ -189,6 +189,9 @@ enum {
 	/* Irq domain implements MSI remapping */
 	IRQ_DOMAIN_FLAG_MSI_REMAP	= (1 << 5),
 
+	/* Irq domain name was allocated in __irq_domain_add() */
+	IRQ_DOMAIN_NAME_ALLOCATED	= (1 << 6),
+
 	/*
 	 * Flags starting from IRQ_DOMAIN_FLAG_NONCORE are reserved
 	 * for implementation specific purposes and ignored by the
@@ -203,7 +206,33 @@ static inline struct device_node *irq_domain_get_of_node(struct irq_domain *d)
 }
 
 #ifdef CONFIG_IRQ_DOMAIN
-struct fwnode_handle *irq_domain_alloc_fwnode(void *data);
+struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
+						const char *name, void *data);
+
+enum {
+	IRQCHIP_FWNODE_REAL,
+	IRQCHIP_FWNODE_NAMED,
+	IRQCHIP_FWNODE_NAMED_ID,
+};
+
+static inline
+struct fwnode_handle *irq_domain_alloc_named_fwnode(const char *name)
+{
+	return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_NAMED, 0, name, NULL);
+}
+
+static inline
+struct fwnode_handle *irq_domain_alloc_named_id_fwnode(const char *name, int id)
+{
+	return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_NAMED_ID, id, name,
+					 NULL);
+}
+
+static inline struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
+{
+	return __irq_domain_alloc_fwnode(IRQCHIP_FWNODE_REAL, 0, NULL, data);
+}
+
 void irq_domain_free_fwnode(struct fwnode_handle *fwnode);
 struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
 				    irq_hw_number_t hwirq_max, int direct_max,
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c
index 70b9da7..e1b925b 100644
--- a/kernel/irq/irqdomain.c
+++ b/kernel/irq/irqdomain.c
@@ -26,39 +26,61 @@ static struct irq_domain *irq_default_domain;
 static void irq_domain_check_hierarchy(struct irq_domain *domain);
 
 struct irqchip_fwid {
-	struct fwnode_handle fwnode;
-	char *name;
-	void *data;
+	struct fwnode_handle	fwnode;
+	unsigned int		type;
+	char			*name;
+	void			*data;
 };
 
 /**
  * irq_domain_alloc_fwnode - Allocate a fwnode_handle suitable for
  *                           identifying an irq domain
- * @data: optional user-provided data
+ * @type:	Type of irqchip_fwnode. See linux/irqdomain.h
+ * @name:	Optional user provided domain name
+ * @id:		Optional user provided id if name != NULL
+ * @data:	Optional user-provided data
  *
- * Allocate a struct device_node, and return a poiner to the embedded
+ * Allocate a struct irqchip_fwid, and return a poiner to the embedded
  * fwnode_handle (or NULL on failure).
+ *
+ * Note: The types IRQCHIP_FWNODE_NAMED and IRQCHIP_FWNODE_NAMED_ID are
+ * solely to transport name information to irqdomain creation code. The
+ * node is not stored. For other types the pointer is kept in the irq
+ * domain struct.
  */
-struct fwnode_handle *irq_domain_alloc_fwnode(void *data)
+struct fwnode_handle *__irq_domain_alloc_fwnode(unsigned int type, int id,
+						const char *name, void *data)
 {
 	struct irqchip_fwid *fwid;
-	char *name;
+	char *n;
 
 	fwid = kzalloc(sizeof(*fwid), GFP_KERNEL);
-	name = kasprintf(GFP_KERNEL, "irqchip@%p", data);
 
-	if (!fwid || !name) {
+	switch (type) {
+	case IRQCHIP_FWNODE_NAMED:
+		n = kasprintf(GFP_KERNEL, "%s", name);
+		break;
+	case IRQCHIP_FWNODE_NAMED_ID:
+		n = kasprintf(GFP_KERNEL, "%s-%d", name, id);
+		break;
+	default:
+		n = kasprintf(GFP_KERNEL, "irqchip@%p", data);
+		break;
+	}
+
+	if (!fwid || !n) {
 		kfree(fwid);
-		kfree(name);
+		kfree(n);
 		return NULL;
 	}
 
-	fwid->name = name;
+	fwid->type = type;
+	fwid->name = n;
 	fwid->data = data;
 	fwid->fwnode.type = FWNODE_IRQCHIP;
 	return &fwid->fwnode;
 }
-EXPORT_SYMBOL_GPL(irq_domain_alloc_fwnode);
+EXPORT_SYMBOL_GPL(__irq_domain_alloc_fwnode);
 
 /**
  * irq_domain_free_fwnode - Free a non-OF-backed fwnode_handle
@@ -97,20 +119,75 @@ struct irq_domain *__irq_domain_add(struct fwnode_handle *fwnode, int size,
 				    void *host_data)
 {
 	struct device_node *of_node = to_of_node(fwnode);
+	struct irqchip_fwid *fwid;
 	struct irq_domain *domain;
 
+	static atomic_t unknown_domains;
+
 	domain = kzalloc_node(sizeof(*domain) + (sizeof(unsigned int) * size),
 			      GFP_KERNEL, of_node_to_nid(of_node));
 	if (WARN_ON(!domain))
 		return NULL;
 
+	if (fwnode && is_fwnode_irqchip(fwnode)) {
+		fwid = container_of(fwnode, struct irqchip_fwid, fwnode);
+
+		switch (fwid->type) {
+		case IRQCHIP_FWNODE_NAMED:
+		case IRQCHIP_FWNODE_NAMED_ID:
+			domain->name = kstrdup(fwid->name, GFP_KERNEL);
+			if (!domain->name) {
+				kfree(domain);
+				return NULL;
+			}
+			domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;
+			break;
+		default:
+			domain->fwnode = fwnode;
+			domain->name = fwid->name;
+			break;
+		}
+	} else if (of_node) {
+		char *name;
+
+		/*
+		 * DT paths contain '/', which debugfs is legitimately
+		 * unhappy about. Replace them with ':', which does
+		 * the trick and is not as offensive as '\'...
+		 */
+		name = kstrdup(of_node_full_name(of_node), GFP_KERNEL);
+		if (!name) {
+			kfree(domain);
+			return NULL;
+		}
+
+		strreplace(name, '/', ':');
+
+		domain->name = name;
+		domain->fwnode = fwnode;
+		domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;
+	}
+
+	if (!domain->name) {
+		if (fwnode) {
+			pr_err("Invalid fwnode type (%d) for irqdomain\n",
+			       fwnode->type);
+		}
+		domain->name = kasprintf(GFP_KERNEL, "unknown-%d",
+					 atomic_inc_return(&unknown_domains));
+		if (!domain->name) {
+			kfree(domain);
+			return NULL;
+		}
+		domain->flags |= IRQ_DOMAIN_NAME_ALLOCATED;
+	}
+
 	of_node_get(of_node);
 
 	/* Fill structure */
 	INIT_RADIX_TREE(&domain->revmap_tree, GFP_KERNEL);
 	domain->ops = ops;
 	domain->host_data = host_data;
-	domain->fwnode = fwnode;
 	domain->hwirq_max = hwirq_max;
 	domain->revmap_size = size;
 	domain->revmap_direct_max_irq = direct_max;
@@ -152,6 +229,8 @@ void irq_domain_remove(struct irq_domain *domain)
 	pr_debug("Removed domain %s\n", domain->name);
 
 	of_node_put(irq_domain_get_of_node(domain));
+	if (domain->flags & IRQ_DOMAIN_NAME_ALLOCATED)
+		kfree(domain->name);
 	kfree(domain);
 }
 EXPORT_SYMBOL_GPL(irq_domain_remove);

  reply	other threads:[~2017-06-22 16:47 UTC|newest]

Thread overview: 122+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-19 23:37 [patch 00/55] genirq: Debuggability, consolidation and managed affinities Thomas Gleixner
2017-06-19 23:37 ` [patch 01/55] x86/apic: Add name to irq chip Thomas Gleixner
2017-06-22 16:40   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 02/55] iommu/amd: " Thomas Gleixner
2017-06-21 15:51   ` Joerg Roedel
2017-06-22 16:40   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 03/55] iommu/vt-d: " Thomas Gleixner
2017-06-21 15:51   ` Joerg Roedel
2017-06-22 16:41   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 04/55] genirq/msi: Prevent overwriting domain name Thomas Gleixner
2017-06-22 16:41   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 05/55] genirq: Allow fwnode to carry name information only Thomas Gleixner
2017-06-22 16:42   ` tip-bot for Thomas Gleixner [this message]
2017-06-19 23:37 ` [patch 06/55] x86/vector: Create named irq domain Thomas Gleixner
2017-06-22 16:42   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 07/55] x86/ioapic: " Thomas Gleixner
2017-06-22 16:43   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 08/55] x86/htirq: Create named domain Thomas Gleixner
2017-06-22 16:44   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 09/55] x86/uv: Create named irq domain Thomas Gleixner
2017-06-22 16:44   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 10/55] x86/msi: Provide new iommu irqdomain interface Thomas Gleixner
2017-06-22 16:45   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 11/55] iommu/vt-d: Use named irq domain interface Thomas Gleixner
2017-06-21 15:52   ` Joerg Roedel
2017-06-22 16:45   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 12/55] iommu/amd: " Thomas Gleixner
2017-06-21 15:52   ` Joerg Roedel
2017-06-22 16:46   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 13/55] x86/msi: Remove unused remap " Thomas Gleixner
2017-06-22 16:46   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 14/55] x86/msi: Create named irq domains Thomas Gleixner
2017-06-22 16:47   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 15/55] PCI: vmd: Create named irq domain Thomas Gleixner
2017-06-20 20:07   ` Keith Busch
2017-06-20 20:07     ` Thomas Gleixner
2017-06-20 20:39       ` Thomas Gleixner
2017-06-22 16:47   ` [tip:irq/core] PCI/vmd: " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 16/55] genirq/irqdomain: Add map counter Thomas Gleixner
2017-06-22 16:48   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 17/55] genirq/debugfs: Add proper debugfs interface Thomas Gleixner
2017-06-22 16:49   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 18/55] genirq: Add missing comment for IRQD_STARTED Thomas Gleixner
2017-06-22 16:49   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 19/55] genirq: Provide irq_fixup_move_pending() Thomas Gleixner
2017-06-20  4:21   ` Dou Liyang
2017-06-20  6:58     ` Thomas Gleixner
2017-06-22 16:50   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 20/55] x86/irq: Cleanup pending irq move in fixup_irqs() Thomas Gleixner
2017-06-22 16:50   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 21/55] genirq: Remove mask argument from setup_affinity() Thomas Gleixner
2017-06-22 16:51   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 22/55] genirq: Rename setup_affinity() to irq_setup_affinity() Thomas Gleixner
2017-06-22 16:52   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 23/55] genirq: Move initial affinity setup to irq_startup() Thomas Gleixner
2017-06-22 16:52   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 24/55] genirq: Move pending helpers to internal.h Thomas Gleixner
2017-06-22 16:53   ` [tip:irq/core] " tip-bot for Christoph Hellwig
2017-06-19 23:37 ` [patch 25/55] genirq/cpuhotplug: Remove irq disabling logic Thomas Gleixner
2017-06-22 16:53   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 26/55] genirq/cpuhotplug: Dont claim success on error Thomas Gleixner
2017-06-22 16:54   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 27/55] genirq/cpuhotplug: Reorder check logic Thomas Gleixner
2017-06-22 16:54   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 28/55] genirq/cpuhotplug: Do not migrated shutdown irqs Thomas Gleixner
2017-06-22 16:55   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 29/55] genirq/cpuhotplug: Add support for cleaning up move in progress Thomas Gleixner
2017-06-22 16:56   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 30/55] genirq/cpuhotplug: Add support for conditional masking Thomas Gleixner
2017-06-22 16:56   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 31/55] genirq/cpuhotplug: Set force affinity flag on hotplug migration Thomas Gleixner
2017-06-22 16:57   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 32/55] x86/irq: Restructure fixup_irqs() Thomas Gleixner
2017-06-20 21:34   ` Keith Busch
2017-06-20 21:28     ` Thomas Gleixner
2017-06-22 16:57   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 33/55] x86/irq: Use irq_migrate_all_off_this_cpu() Thomas Gleixner
2017-06-22 16:58   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 34/55] genirq: Move irq_fixup_move_pending() to core Thomas Gleixner
2017-06-22 16:58   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 35/55] genirq: Remove pointless arg from show_irq_affinity Thomas Gleixner
2017-06-22 16:59   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 36/55] genirq: Remove pointless gfp argument Thomas Gleixner
2017-06-22 17:00   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 37/55] genirq/proc: Replace ever repeating type cast Thomas Gleixner
2017-06-22 17:00   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 38/55] genirq: Introduce effective affinity mask Thomas Gleixner
2017-06-22 17:01   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 39/55] genirq/cpuhotplug: Use " Thomas Gleixner
2017-06-22 17:01   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 40/55] x86/apic: Move flat_cpu_mask_to_apicid_and() into C source Thomas Gleixner
2017-06-22 17:02   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 41/55] x86/uv: Use default_cpu_mask_to_apicid_and() Thomas Gleixner
2017-06-22 17:03   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 42/55] x86/apic: Move online masking to core code Thomas Gleixner
2017-06-22 17:03   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 43/55] x86/apic: Move cpumask and " Thomas Gleixner
2017-06-22 17:04   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 44/55] x86/apic: Add irq_data argument to apic->cpu_mask_to_apicid() Thomas Gleixner
2017-06-22 17:04   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 45/55] xen/events: Add support for effective affinity mask Thomas Gleixner
2017-06-22 17:05   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 46/55] x86/apic: Implement effective irq mask update Thomas Gleixner
2017-06-22 17:05   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 47/55] genirq: Introduce IRQD_MANAGED_SHUTDOWN Thomas Gleixner
2017-06-22 17:06   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 48/55] genirq: Split out irq_startup() code Thomas Gleixner
2017-06-22 17:06   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 49/55] genirq: Add force argument to irq_startup() Thomas Gleixner
2017-06-22 17:07   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 50/55] genirq: Handle managed irqs gracefully in irq_startup() Thomas Gleixner
2017-06-22 17:08   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 51/55] genirq/cpuhotplug: Handle managed IRQs on CPU hotplug Thomas Gleixner
2017-06-22 17:08   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 52/55] genirq: Introduce IRQD_SINGLE_TARGET flag Thomas Gleixner
2017-06-22 17:09   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 53/55] genirq/cpuhotplug: Avoid irq affinity setting for single targets Thomas Gleixner
2017-06-22 17:09   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 54/55] x86/apic: Mark single target interrupts Thomas Gleixner
2017-06-22 17:10   ` [tip:irq/core] " tip-bot for Thomas Gleixner
2017-06-19 23:37 ` [patch 55/55] genirq/affinity: Assign vectors to all present CPUs Thomas Gleixner
2017-06-20  9:23 ` [patch 00/55] genirq: Debuggability, consolidation and managed affinities Christoph Hellwig

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=tip-d59f6617eef0f76e34f7a9993f5645c5ef467e42@git.kernel.org \
    --to=tipbot@zytor.com \
    --cc=axboe@kernel.dk \
    --cc=hch@lst.de \
    --cc=hpa@zytor.com \
    --cc=keith.busch@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tip-commits@vger.kernel.org \
    --cc=marc.zyngier@arm.com \
    --cc=mingo@kernel.org \
    --cc=mpe@ellerman.id.au \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    /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;
as well as URLs for NNTP newsgroup(s).