From: Jaya Kumar <jayakumar.lkml@gmail.com>
Cc: Jaya Kumar <jayakumar.lkml@gmail.com>,
David Brownell <dbrownell@users.sourceforge.net>,
David Brownell <david-b@pacbell.net>,
Sam Ravnborg <sam@ravnborg.org>,
Jean Delvare <khali@linux-fr.org>,
Eric Miao <eric.miao@marvell.com>,
Haavard Skinnemoen <hskinnemoen@atmel.com>,
Philipp Zabel <philipp.zabel@gmail.com>,
Russell King <rmk@arm.linux.org.uk>,
Ben Gardner <bgardner@wabtec.com>, Greg KH <greg@kroah.com>,
linux-arm-kernel@lists.arm.linux.org.uk,
linux-fbdev-devel@lists.sourceforge.net,
linux-kernel@vger.kernel.org
Subject: [RFC 2.6.27 1/1] gpiolib: add support for batch set of pins
Date: Wed, 26 Nov 2008 06:52:43 +0800 [thread overview]
Message-ID: <12276535632759-git-send-email-jayakumar.lkml@gmail.com> (raw)
Beloved friends,
I would like to request your feedback on the following idea. I hope I have
made sure to CC all the right people and the right lists! If not, PLEASE
let me know! I couldn't find a MAINTAINERS entry for gpiolib so I just
used what I saw in the git log and have also added people and lists that
I think may be interested.
This is just an RFC. If you all feel it is looking like the right approach
then I'll clean it up and make it a patch.
Thanks,
jaya
am300epd was doing 800*600*16*gpio_set_value for each framebuffer transfer
(it uses 16-pins of gpio as its data bus). I found this caused a wee
performance limitation. This patch adds an API for gpio_set_value_bus
which allows users to set batches of consecutive gpio together in a single
call. I have done a test implementation on gumstix (pxa255) with am300epd
and it provides a nice improvement in performance.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: David Brownell <david-b@pacbell.net>
Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Eric Miao <eric.miao@marvell.com>
Cc: Haavard Skinnemoen <hskinnemoen@atmel.com>
Cc: Philipp Zabel <philipp.zabel@gmail.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Ben Gardner <bgardner@wabtec.com>
CC: Greg KH <greg@kroah.com>
Cc: linux-arm-kernel@lists.arm.linux.org.uk
Cc: linux-fbdev-devel@lists.sourceforge.net
Cc: linux-kernel@vger.kernel.org
---
arch/arm/mach-pxa/am300epd.c | 9 ++++++
arch/arm/mach-pxa/gpio.c | 28 +++++++++++++++++++++
arch/arm/mach-pxa/include/mach/gpio.h | 24 ++++++++++++++++++
drivers/gpio/gpiolib.c | 44 +++++++++++++++++++++++++++++++++
include/asm-generic/gpio.h | 6 ++++
5 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-pxa/am300epd.c b/arch/arm/mach-pxa/am300epd.c
index bb81564..f741a98 100644
--- a/arch/arm/mach-pxa/am300epd.c
+++ b/arch/arm/mach-pxa/am300epd.c
@@ -222,8 +222,17 @@ static void am300_set_hdb(struct broadsheetfb_par *par, u16 data)
{
int i;
+#if 1
+ gpio_set_value_bus(DB0_GPIO_PIN, data, 16);
+#endif
+#if 0
+ gpio_set_value_bus(DB0_GPIO_PIN, data, 6);
+ gpio_set_value_bus(DB0_GPIO_PIN + 6, data >> 6, 10);
+#endif
+#if 0 /* simple set */
for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01);
+#endif
}
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
index 14930cf..80b0aa1 100644
--- a/arch/arm/mach-pxa/gpio.c
+++ b/arch/arm/mach-pxa/gpio.c
@@ -132,6 +132,33 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
__raw_writel(mask, pxa->regbase + GPCR_OFFSET);
}
+/*
+ * Set output GPIO level in batches
+ */
+static void pxa_gpio_set_bus(struct gpio_chip *chip, unsigned offset,
+ int values, int bitwidth)
+{
+ struct pxa_gpio_chip *pxa;
+ int mask;
+
+ /* we're guaranteed by the caller that offset + bitwidth remains
+ * in this chip.
+ */
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+
+ mask = ((1 << bitwidth) - 1) << offset;
+ values <<= offset;
+
+ values &= mask;
+ if (values)
+ __raw_writel(values, pxa->regbase + GPSR_OFFSET);
+
+ values = ~values;
+ values &= mask;
+ if (values)
+ __raw_writel(values, pxa->regbase + GPCR_OFFSET);
+}
+
#define GPIO_CHIP(_n) \
[_n] = { \
.regbase = GPIO##_n##_BASE, \
@@ -141,6 +168,7 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
.direction_output = pxa_gpio_direction_output, \
.get = pxa_gpio_get, \
.set = pxa_gpio_set, \
+ .set_bus = pxa_gpio_set_bus, \
.base = (_n) * 32, \
.ngpio = 32, \
}, \
diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h
index 2c538d8..6ee92d3 100644
--- a/arch/arm/mach-pxa/include/mach/gpio.h
+++ b/arch/arm/mach-pxa/include/mach/gpio.h
@@ -56,6 +56,30 @@ static inline void gpio_set_value(unsigned gpio, int value)
}
}
+static inline void gpio_set_value_bus(unsigned gpio, int values, int bitwidth)
+{
+ if (__builtin_constant_p(gpio) &&
+ (gpio + bitwidth < NR_BUILTIN_GPIO) &&
+ ((gpio + bitwidth) <= roundup(gpio+1, 32))) {
+ int shift, mask;
+
+ shift = gpio % 32;
+ mask = ((1 << bitwidth) - 1) << shift;
+ values <<= shift;
+
+ values &= mask;
+ if (values)
+ GPSR(gpio) = values;
+
+ values = ~values;
+ values &= mask;
+ if (values)
+ GPCR(gpio) = values;
+ } else {
+ __gpio_set_value_bus(gpio, values, bitwidth);
+ }
+}
+
#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq(gpio) IRQ_GPIO(gpio)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 9112830..fddf3af 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1057,6 +1057,50 @@ void __gpio_set_value(unsigned gpio, int value)
EXPORT_SYMBOL_GPL(__gpio_set_value);
/**
+ * __gpio_set_value_bus() - assign a batch of consecutive gpio pins together
+ * @gpio: starting gpio pin
+ * @values: values to assign, sequential in host ordering
+ * @bitwidth: total width of bits to be assigned
+ * Context: any
+ *
+ * This is used directly or indirectly to implement gpio_set_value().
+ * It invokes the associated gpio_chip.set() method.
+ */
+void __gpio_set_value_bus(unsigned gpio, int values, int bitwidth)
+{
+ struct gpio_chip *chip;
+ int i = 0;
+ int value, width, remwidth;
+
+ do {
+ chip = gpio_to_chip(gpio + i);
+ WARN_ON(extra_checks && chip->can_sleep);
+
+ if (!chip->set_bus) {
+ while (((gpio + i) < (chip->base + chip->ngpio))
+ && bitwidth) {
+ value = values & (1 << i);
+ chip->set(chip, gpio + i - chip->base, value);
+ i++;
+ bitwidth--;
+ }
+ } else {
+ value = values >> i; /* shift off the used stuff */
+ remwidth = ((chip->base + (int) chip->ngpio) -
+ ((int) gpio + i));
+ width = min(bitwidth, remwidth);
+
+ chip->set_bus(chip, gpio + i - chip->base, value,
+ width);
+ i += width;
+ bitwidth -= width;
+ }
+ } while (bitwidth);
+}
+EXPORT_SYMBOL_GPL(__gpio_set_value_bus);
+
+
+/**
* __gpio_cansleep() - report whether gpio value access will sleep
* @gpio: gpio in question
* Context: any
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 81797ec..9747517 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -44,6 +44,8 @@ struct module;
* returns either the value actually sensed, or zero
* @direction_output: configures signal "offset" as output, or returns error
* @set: assigns output value for signal "offset"
+ * @set_bus: batch assigns output values for consecutive signals starting at
+ * "offset" with width in bits "bitwidth"
* @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
* implementation may not sleep
* @dbg_show: optional routine to show contents in debugfs; default code
@@ -84,6 +86,9 @@ struct gpio_chip {
unsigned offset, int value);
void (*set)(struct gpio_chip *chip,
unsigned offset, int value);
+ void (*set_bus)(struct gpio_chip *chip,
+ unsigned offset, int values,
+ int bitwidth);
int (*to_irq)(struct gpio_chip *chip,
unsigned offset);
@@ -124,6 +129,7 @@ extern void gpio_set_value_cansleep(unsigned gpio, int value);
*/
extern int __gpio_get_value(unsigned gpio);
extern void __gpio_set_value(unsigned gpio, int value);
+extern void __gpio_set_value_bus(unsigned gpio, int values, int bitwidth);
extern int __gpio_cansleep(unsigned gpio);
--
1.5.2.3
WARNING: multiple messages have this Message-ID (diff)
From: Jaya Kumar <jayakumar.lkml@gmail.com>
To: jayakumar.lkml@gmail.com
Cc: Jaya Kumar <jayakumar.lkml@gmail.com>,
David Brownell <dbrownell@users.sourceforge.net>,
David Brownell <david-b@pacbell.net>,
Sam Ravnborg <sam@ravnborg.org>,
Jean Delvare <khali@linux-fr.org>,
Eric Miao <eric.miao@marvell.com>,
Haavard Skinnemoen <hskinnemoen@atmel.com>,
Philipp Zabel <philipp.zabel@gmail.com>,
Russell King <rmk@arm.linux.org.uk>,
Ben Gardner <bgardner@wabtec.com>, Greg KH <greg@kroah.com>,
linux-arm-kernel@lists.arm.linux.org.uk,
linux-fbdev-devel@lists.sourceforge.net,
linux-kernel@vger.kernel.org
Subject: [RFC 2.6.27 1/1] gpiolib: add support for batch set of pins
Date: Wed, 26 Nov 2008 06:52:43 +0800 [thread overview]
Message-ID: <12276535632759-git-send-email-jayakumar.lkml@gmail.com> (raw)
Beloved friends,
I would like to request your feedback on the following idea. I hope I have
made sure to CC all the right people and the right lists! If not, PLEASE
let me know! I couldn't find a MAINTAINERS entry for gpiolib so I just
used what I saw in the git log and have also added people and lists that
I think may be interested.
This is just an RFC. If you all feel it is looking like the right approach
then I'll clean it up and make it a patch.
Thanks,
jaya
am300epd was doing 800*600*16*gpio_set_value for each framebuffer transfer
(it uses 16-pins of gpio as its data bus). I found this caused a wee
performance limitation. This patch adds an API for gpio_set_value_bus
which allows users to set batches of consecutive gpio together in a single
call. I have done a test implementation on gumstix (pxa255) with am300epd
and it provides a nice improvement in performance.
Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: David Brownell <david-b@pacbell.net>
Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Eric Miao <eric.miao@marvell.com>
Cc: Haavard Skinnemoen <hskinnemoen@atmel.com>
Cc: Philipp Zabel <philipp.zabel@gmail.com>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Ben Gardner <bgardner@wabtec.com>
CC: Greg KH <greg@kroah.com>
Cc: linux-arm-kernel@lists.arm.linux.org.uk
Cc: linux-fbdev-devel@lists.sourceforge.net
Cc: linux-kernel@vger.kernel.org
---
arch/arm/mach-pxa/am300epd.c | 9 ++++++
arch/arm/mach-pxa/gpio.c | 28 +++++++++++++++++++++
arch/arm/mach-pxa/include/mach/gpio.h | 24 ++++++++++++++++++
drivers/gpio/gpiolib.c | 44 +++++++++++++++++++++++++++++++++
include/asm-generic/gpio.h | 6 ++++
5 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-pxa/am300epd.c b/arch/arm/mach-pxa/am300epd.c
index bb81564..f741a98 100644
--- a/arch/arm/mach-pxa/am300epd.c
+++ b/arch/arm/mach-pxa/am300epd.c
@@ -222,8 +222,17 @@ static void am300_set_hdb(struct broadsheetfb_par *par, u16 data)
{
int i;
+#if 1
+ gpio_set_value_bus(DB0_GPIO_PIN, data, 16);
+#endif
+#if 0
+ gpio_set_value_bus(DB0_GPIO_PIN, data, 6);
+ gpio_set_value_bus(DB0_GPIO_PIN + 6, data >> 6, 10);
+#endif
+#if 0 /* simple set */
for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01);
+#endif
}
diff --git a/arch/arm/mach-pxa/gpio.c b/arch/arm/mach-pxa/gpio.c
index 14930cf..80b0aa1 100644
--- a/arch/arm/mach-pxa/gpio.c
+++ b/arch/arm/mach-pxa/gpio.c
@@ -132,6 +132,33 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
__raw_writel(mask, pxa->regbase + GPCR_OFFSET);
}
+/*
+ * Set output GPIO level in batches
+ */
+static void pxa_gpio_set_bus(struct gpio_chip *chip, unsigned offset,
+ int values, int bitwidth)
+{
+ struct pxa_gpio_chip *pxa;
+ int mask;
+
+ /* we're guaranteed by the caller that offset + bitwidth remains
+ * in this chip.
+ */
+ pxa = container_of(chip, struct pxa_gpio_chip, chip);
+
+ mask = ((1 << bitwidth) - 1) << offset;
+ values <<= offset;
+
+ values &= mask;
+ if (values)
+ __raw_writel(values, pxa->regbase + GPSR_OFFSET);
+
+ values = ~values;
+ values &= mask;
+ if (values)
+ __raw_writel(values, pxa->regbase + GPCR_OFFSET);
+}
+
#define GPIO_CHIP(_n) \
[_n] = { \
.regbase = GPIO##_n##_BASE, \
@@ -141,6 +168,7 @@ static void pxa_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
.direction_output = pxa_gpio_direction_output, \
.get = pxa_gpio_get, \
.set = pxa_gpio_set, \
+ .set_bus = pxa_gpio_set_bus, \
.base = (_n) * 32, \
.ngpio = 32, \
}, \
diff --git a/arch/arm/mach-pxa/include/mach/gpio.h b/arch/arm/mach-pxa/include/mach/gpio.h
index 2c538d8..6ee92d3 100644
--- a/arch/arm/mach-pxa/include/mach/gpio.h
+++ b/arch/arm/mach-pxa/include/mach/gpio.h
@@ -56,6 +56,30 @@ static inline void gpio_set_value(unsigned gpio, int value)
}
}
+static inline void gpio_set_value_bus(unsigned gpio, int values, int bitwidth)
+{
+ if (__builtin_constant_p(gpio) &&
+ (gpio + bitwidth < NR_BUILTIN_GPIO) &&
+ ((gpio + bitwidth) <= roundup(gpio+1, 32))) {
+ int shift, mask;
+
+ shift = gpio % 32;
+ mask = ((1 << bitwidth) - 1) << shift;
+ values <<= shift;
+
+ values &= mask;
+ if (values)
+ GPSR(gpio) = values;
+
+ values = ~values;
+ values &= mask;
+ if (values)
+ GPCR(gpio) = values;
+ } else {
+ __gpio_set_value_bus(gpio, values, bitwidth);
+ }
+}
+
#define gpio_cansleep __gpio_cansleep
#define gpio_to_irq(gpio) IRQ_GPIO(gpio)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 9112830..fddf3af 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1057,6 +1057,50 @@ void __gpio_set_value(unsigned gpio, int value)
EXPORT_SYMBOL_GPL(__gpio_set_value);
/**
+ * __gpio_set_value_bus() - assign a batch of consecutive gpio pins together
+ * @gpio: starting gpio pin
+ * @values: values to assign, sequential in host ordering
+ * @bitwidth: total width of bits to be assigned
+ * Context: any
+ *
+ * This is used directly or indirectly to implement gpio_set_value().
+ * It invokes the associated gpio_chip.set() method.
+ */
+void __gpio_set_value_bus(unsigned gpio, int values, int bitwidth)
+{
+ struct gpio_chip *chip;
+ int i = 0;
+ int value, width, remwidth;
+
+ do {
+ chip = gpio_to_chip(gpio + i);
+ WARN_ON(extra_checks && chip->can_sleep);
+
+ if (!chip->set_bus) {
+ while (((gpio + i) < (chip->base + chip->ngpio))
+ && bitwidth) {
+ value = values & (1 << i);
+ chip->set(chip, gpio + i - chip->base, value);
+ i++;
+ bitwidth--;
+ }
+ } else {
+ value = values >> i; /* shift off the used stuff */
+ remwidth = ((chip->base + (int) chip->ngpio) -
+ ((int) gpio + i));
+ width = min(bitwidth, remwidth);
+
+ chip->set_bus(chip, gpio + i - chip->base, value,
+ width);
+ i += width;
+ bitwidth -= width;
+ }
+ } while (bitwidth);
+}
+EXPORT_SYMBOL_GPL(__gpio_set_value_bus);
+
+
+/**
* __gpio_cansleep() - report whether gpio value access will sleep
* @gpio: gpio in question
* Context: any
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 81797ec..9747517 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -44,6 +44,8 @@ struct module;
* returns either the value actually sensed, or zero
* @direction_output: configures signal "offset" as output, or returns error
* @set: assigns output value for signal "offset"
+ * @set_bus: batch assigns output values for consecutive signals starting at
+ * "offset" with width in bits "bitwidth"
* @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
* implementation may not sleep
* @dbg_show: optional routine to show contents in debugfs; default code
@@ -84,6 +86,9 @@ struct gpio_chip {
unsigned offset, int value);
void (*set)(struct gpio_chip *chip,
unsigned offset, int value);
+ void (*set_bus)(struct gpio_chip *chip,
+ unsigned offset, int values,
+ int bitwidth);
int (*to_irq)(struct gpio_chip *chip,
unsigned offset);
@@ -124,6 +129,7 @@ extern void gpio_set_value_cansleep(unsigned gpio, int value);
*/
extern int __gpio_get_value(unsigned gpio);
extern void __gpio_set_value(unsigned gpio, int value);
+extern void __gpio_set_value_bus(unsigned gpio, int values, int bitwidth);
extern int __gpio_cansleep(unsigned gpio);
--
1.5.2.3
next reply other threads:[~2008-11-25 22:52 UTC|newest]
Thread overview: 46+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-11-25 22:52 Jaya Kumar [this message]
2008-11-25 22:52 ` [RFC 2.6.27 1/1] gpiolib: add support for batch set of pins Jaya Kumar
2008-11-26 1:20 ` Eric Miao
2008-11-26 3:27 ` Jaya Kumar
2008-11-26 4:15 ` David Brownell
2008-11-26 5:51 ` Jaya Kumar
2008-11-27 20:01 ` Sam Ravnborg
2008-11-27 23:43 ` Jaya Kumar
2008-11-28 5:47 ` Sam Ravnborg
2008-11-29 22:48 ` David Brownell
2008-11-29 23:33 ` Jaya Kumar
2008-11-29 22:54 ` David Brownell
2008-11-29 22:54 ` David Brownell
2008-11-29 23:52 ` Jaya Kumar
2008-11-30 17:55 ` David Brownell
2008-12-01 1:10 ` Jaya Kumar
2008-12-27 14:55 ` Jaya Kumar
2008-12-28 18:46 ` Robin Getz
2008-12-28 22:00 ` Ben Nizette
2008-12-29 0:28 ` Jaya Kumar
2008-12-29 20:32 ` David Brownell
2008-12-29 19:59 ` David Brownell
2009-01-06 23:02 ` Robin Getz
2009-01-07 1:52 ` Ben Nizette
2008-12-29 19:56 ` David Brownell
2008-12-30 0:20 ` Jamie Lokier
2008-12-30 0:43 ` David Brownell
2008-12-31 4:55 ` Robin Getz
2008-12-31 4:58 ` Jaya Kumar
2008-12-31 5:02 ` Jaya Kumar
2008-12-31 17:38 ` Robin Getz
2008-12-31 18:05 ` Jaya Kumar
2009-01-06 22:41 ` Robin Getz
2009-01-10 7:37 ` Jaya Kumar
2008-12-29 19:32 ` David Brownell
2008-12-30 15:45 ` Jaya Kumar
2008-12-29 19:06 ` David Brownell
2008-11-26 9:09 ` Paulius Zaleckas
2008-11-26 9:09 ` Paulius Zaleckas
2008-11-26 9:18 ` Jaya Kumar
2008-11-26 10:08 ` [Linux-fbdev-devel] " Geert Uytterhoeven
2008-11-26 10:25 ` Jaya Kumar
2008-11-26 12:08 ` Geert Uytterhoeven
2008-11-29 22:47 ` David Brownell
2008-11-29 23:04 ` Jaya Kumar
2008-11-30 3:27 ` David Brownell
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=12276535632759-git-send-email-jayakumar.lkml@gmail.com \
--to=jayakumar.lkml@gmail.com \
--cc=bgardner@wabtec.com \
--cc=david-b@pacbell.net \
--cc=dbrownell@users.sourceforge.net \
--cc=eric.miao@marvell.com \
--cc=greg@kroah.com \
--cc=hskinnemoen@atmel.com \
--cc=khali@linux-fr.org \
--cc=linux-arm-kernel@lists.arm.linux.org.uk \
--cc=linux-fbdev-devel@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
--cc=philipp.zabel@gmail.com \
--cc=rmk@arm.linux.org.uk \
--cc=sam@ravnborg.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.