From: daniel.lezcano@linaro.org (Daniel Lezcano)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 11/71] clocksource: sh_cmt: Split static information from sh_cmt_device
Date: Fri, 23 May 2014 12:30:51 +0200 [thread overview]
Message-ID: <1400841111-6683-11-git-send-email-daniel.lezcano@linaro.org> (raw)
In-Reply-To: <1400841111-6683-1-git-send-email-daniel.lezcano@linaro.org>
From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
Create a new sh_cmt_info structure to hold static information about the
device model and reference that structure from the sh_cmt_device
structure.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/clocksource/sh_cmt.c | 192 +++++++++++++++++++++++++++---------------
1 file changed, 122 insertions(+), 70 deletions(-)
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index f94db32..879b8c2 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -37,6 +37,52 @@
struct sh_cmt_device;
+/*
+ * The CMT comes in 5 different identified flavours, depending not only on the
+ * SoC but also on the particular instance. The following table lists the main
+ * characteristics of those flavours.
+ *
+ * 16B 32B 32B-F 48B 48B-2
+ * -----------------------------------------------------------------------------
+ * Channels 2 1/4 1 6 2/8
+ * Control Width 16 16 16 16 32
+ * Counter Width 16 32 32 32/48 32/48
+ * Shared Start/Stop Y Y Y Y N
+ *
+ * The 48-bit gen2 version has a per-channel start/stop register located in the
+ * channel registers block. All other versions have a shared start/stop register
+ * located in the global space.
+ *
+ * Note that CMT0 on r8a73a4, r8a7790 and r8a7791, while implementing 32-bit
+ * channels only, is a 48-bit gen2 CMT with the 48-bit channels unavailable.
+ */
+
+enum sh_cmt_model {
+ SH_CMT_16BIT,
+ SH_CMT_32BIT,
+ SH_CMT_32BIT_FAST,
+ SH_CMT_48BIT,
+ SH_CMT_48BIT_GEN2,
+};
+
+struct sh_cmt_info {
+ enum sh_cmt_model model;
+
+ unsigned long width; /* 16 or 32 bit version of hardware block */
+ unsigned long overflow_bit;
+ unsigned long clear_bits;
+
+ /* callbacks for CMSTR and CMCSR access */
+ unsigned long (*read_control)(void __iomem *base, unsigned long offs);
+ void (*write_control)(void __iomem *base, unsigned long offs,
+ unsigned long value);
+
+ /* callbacks for CMCNT and CMCOR access */
+ unsigned long (*read_count)(void __iomem *base, unsigned long offs);
+ void (*write_count)(void __iomem *base, unsigned long offs,
+ unsigned long value);
+};
+
struct sh_cmt_channel {
struct sh_cmt_device *cmt;
unsigned int index;
@@ -58,49 +104,16 @@ struct sh_cmt_channel {
struct sh_cmt_device {
struct platform_device *pdev;
+ const struct sh_cmt_info *info;
+
void __iomem *mapbase_ch;
void __iomem *mapbase;
struct clk *clk;
struct sh_cmt_channel *channels;
unsigned int num_channels;
-
- unsigned long width; /* 16 or 32 bit version of hardware block */
- unsigned long overflow_bit;
- unsigned long clear_bits;
-
- /* callbacks for CMSTR and CMCSR access */
- unsigned long (*read_control)(void __iomem *base, unsigned long offs);
- void (*write_control)(void __iomem *base, unsigned long offs,
- unsigned long value);
-
- /* callbacks for CMCNT and CMCOR access */
- unsigned long (*read_count)(void __iomem *base, unsigned long offs);
- void (*write_count)(void __iomem *base, unsigned long offs,
- unsigned long value);
};
-/* Examples of supported CMT timer register layouts and I/O access widths:
- *
- * "16-bit counter and 16-bit control" as found on sh7263:
- * CMSTR 0xfffec000 16-bit
- * CMCSR 0xfffec002 16-bit
- * CMCNT 0xfffec004 16-bit
- * CMCOR 0xfffec006 16-bit
- *
- * "32-bit counter and 16-bit control" as found on sh7372, sh73a0, r8a7740:
- * CMSTR 0xffca0000 16-bit
- * CMCSR 0xffca0060 16-bit
- * CMCNT 0xffca0064 32-bit
- * CMCOR 0xffca0068 32-bit
- *
- * "32-bit counter and 32-bit control" as found on r8a73a4 and r8a7790:
- * CMSTR 0xffca0500 32-bit
- * CMCSR 0xffca0510 32-bit
- * CMCNT 0xffca0514 32-bit
- * CMCOR 0xffca0518 32-bit
- */
-
static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
{
return ioread16(base + (offs << 1));
@@ -123,47 +136,100 @@ static void sh_cmt_write32(void __iomem *base, unsigned long offs,
iowrite32(value, base + (offs << 2));
}
+static const struct sh_cmt_info sh_cmt_info[] = {
+ [SH_CMT_16BIT] = {
+ .model = SH_CMT_16BIT,
+ .width = 16,
+ .overflow_bit = 0x80,
+ .clear_bits = ~0x80,
+ .read_control = sh_cmt_read16,
+ .write_control = sh_cmt_write16,
+ .read_count = sh_cmt_read16,
+ .write_count = sh_cmt_write16,
+ },
+ [SH_CMT_32BIT] = {
+ .model = SH_CMT_32BIT,
+ .width = 32,
+ .overflow_bit = 0x8000,
+ .clear_bits = ~0xc000,
+ .read_control = sh_cmt_read16,
+ .write_control = sh_cmt_write16,
+ .read_count = sh_cmt_read32,
+ .write_count = sh_cmt_write32,
+ },
+ [SH_CMT_32BIT_FAST] = {
+ .model = SH_CMT_32BIT_FAST,
+ .width = 32,
+ .overflow_bit = 0x8000,
+ .clear_bits = ~0xc000,
+ .read_control = sh_cmt_read16,
+ .write_control = sh_cmt_write16,
+ .read_count = sh_cmt_read32,
+ .write_count = sh_cmt_write32,
+ },
+ [SH_CMT_48BIT] = {
+ .model = SH_CMT_48BIT,
+ .width = 32,
+ .overflow_bit = 0x8000,
+ .clear_bits = ~0xc000,
+ .read_control = sh_cmt_read32,
+ .write_control = sh_cmt_write32,
+ .read_count = sh_cmt_read32,
+ .write_count = sh_cmt_write32,
+ },
+ [SH_CMT_48BIT_GEN2] = {
+ .model = SH_CMT_48BIT_GEN2,
+ .width = 32,
+ .overflow_bit = 0x8000,
+ .clear_bits = ~0xc000,
+ .read_control = sh_cmt_read32,
+ .write_control = sh_cmt_write32,
+ .read_count = sh_cmt_read32,
+ .write_count = sh_cmt_write32,
+ },
+};
+
#define CMCSR 0 /* channel register */
#define CMCNT 1 /* channel register */
#define CMCOR 2 /* channel register */
static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
{
- return ch->cmt->read_control(ch->cmt->mapbase, 0);
+ return ch->cmt->info->read_control(ch->cmt->mapbase, 0);
}
static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
{
- return ch->cmt->read_control(ch->base, CMCSR);
+ return ch->cmt->info->read_control(ch->base, CMCSR);
}
static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
{
- return ch->cmt->read_count(ch->base, CMCNT);
+ return ch->cmt->info->read_count(ch->base, CMCNT);
}
static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch,
unsigned long value)
{
- ch->cmt->write_control(ch->cmt->mapbase, 0, value);
+ ch->cmt->info->write_control(ch->cmt->mapbase, 0, value);
}
static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch,
unsigned long value)
{
- ch->cmt->write_control(ch->base, CMCSR, value);
+ ch->cmt->info->write_control(ch->base, CMCSR, value);
}
static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch,
unsigned long value)
{
- ch->cmt->write_count(ch->base, CMCNT, value);
+ ch->cmt->info->write_count(ch->base, CMCNT, value);
}
static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch,
unsigned long value)
{
- ch->cmt->write_count(ch->base, CMCOR, value);
+ ch->cmt->info->write_count(ch->base, CMCOR, value);
}
static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
@@ -172,7 +238,7 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
unsigned long v1, v2, v3;
int o1, o2;
- o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->overflow_bit;
+ o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit;
/* Make sure the timer value is stable. Stolen from acpi_pm.c */
do {
@@ -180,7 +246,7 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_channel *ch,
v1 = sh_cmt_read_cmcnt(ch);
v2 = sh_cmt_read_cmcnt(ch);
v3 = sh_cmt_read_cmcnt(ch);
- o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->overflow_bit;
+ o1 = sh_cmt_read_cmcsr(ch) & ch->cmt->info->overflow_bit;
} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
|| (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
@@ -227,7 +293,7 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch, unsigned long *rate)
sh_cmt_start_stop_ch(ch, 0);
/* configure channel, periodic mode and maximum timeout */
- if (ch->cmt->width == 16) {
+ if (ch->cmt->info->width == 16) {
*rate = clk_get_rate(ch->cmt->clk) / 512;
sh_cmt_write_cmcsr(ch, 0x43);
} else {
@@ -405,7 +471,8 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
struct sh_cmt_channel *ch = dev_id;
/* clear flags */
- sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) & ch->cmt->clear_bits);
+ sh_cmt_write_cmcsr(ch, sh_cmt_read_cmcsr(ch) &
+ ch->cmt->info->clear_bits);
/* update clock source counter to begin with if enabled
* the wrap flag should be cleared by the timer specific
@@ -719,10 +786,10 @@ static int sh_cmt_setup_channel(struct sh_cmt_channel *ch, unsigned int index,
return irq;
}
- if (cmt->width == (sizeof(ch->max_match_value) * 8))
+ if (cmt->info->width == (sizeof(ch->max_match_value) * 8))
ch->max_match_value = ~0;
else
- ch->max_match_value = (1 << cmt->width) - 1;
+ ch->max_match_value = (1 << cmt->info->width) - 1;
ch->match_value = ch->max_match_value;
raw_spin_lock_init(&ch->lock);
@@ -800,28 +867,13 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
if (ret < 0)
goto err3;
- if (res2 && (resource_size(res2) == 4)) {
- /* assume both CMSTR and CMCSR to be 32-bit */
- cmt->read_control = sh_cmt_read32;
- cmt->write_control = sh_cmt_write32;
- } else {
- cmt->read_control = sh_cmt_read16;
- cmt->write_control = sh_cmt_write16;
- }
-
- if (resource_size(res) == 6) {
- cmt->width = 16;
- cmt->read_count = sh_cmt_read16;
- cmt->write_count = sh_cmt_write16;
- cmt->overflow_bit = 0x80;
- cmt->clear_bits = ~0x80;
- } else {
- cmt->width = 32;
- cmt->read_count = sh_cmt_read32;
- cmt->write_count = sh_cmt_write32;
- cmt->overflow_bit = 0x8000;
- cmt->clear_bits = ~0xc000;
- }
+ /* identify the model based on the resources */
+ if (resource_size(res) == 6)
+ cmt->info = &sh_cmt_info[SH_CMT_16BIT];
+ else if (res2 && (resource_size(res2) == 4))
+ cmt->info = &sh_cmt_info[SH_CMT_48BIT_GEN2];
+ else
+ cmt->info = &sh_cmt_info[SH_CMT_32BIT];
cmt->channels = kzalloc(sizeof(*cmt->channels), GFP_KERNEL);
if (cmt->channels == NULL) {
--
1.7.9.5
next prev parent reply other threads:[~2014-05-23 10:30 UTC|newest]
Thread overview: 75+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-23 10:22 [GIT PULL] clockevents: new material for 3.16 Daniel Lezcano
2014-05-23 10:30 ` [PATCH 01/71] clocksource: sh_cmt: Use request_irq() instead of setup_irq() Daniel Lezcano
2014-05-23 10:30 ` [PATCH 02/71] clocksource: sh_cmt: Split channel fields from sh_cmt_priv Daniel Lezcano
2014-05-23 10:30 ` [PATCH 03/71] clocksource: sh_cmt: Rename struct sh_cmt_priv to sh_cmt_device Daniel Lezcano
2014-05-23 10:30 ` [PATCH 04/71] clocksource: sh_cmt: Split channel setup to separate function Daniel Lezcano
2014-05-23 10:30 ` [PATCH 05/71] clocksource: sh_cmt: Constify name argument to sh_cmt_register() Daniel Lezcano
2014-05-23 10:30 ` [PATCH 06/71] clocksource: sh_cmt: Rename mapbase/mapbase_str to mapbase_ch/mapbase Daniel Lezcano
2014-05-23 10:30 ` [PATCH 07/71] clocksource: sh_cmt: Add memory base to sh_cmt_channel structure Daniel Lezcano
2014-05-23 10:30 ` [PATCH 08/71] clocksource: sh_cmt: Add index to struct sh_cmt_channel Daniel Lezcano
2014-05-23 10:30 ` [PATCH 09/71] clocksource: sh_cmt: Replace kmalloc + memset with kzalloc Daniel Lezcano
2014-05-23 10:30 ` [PATCH 10/71] clocksource: sh_cmt: Allocate channels dynamically Daniel Lezcano
2014-05-23 10:30 ` Daniel Lezcano [this message]
2014-05-23 10:30 ` [PATCH 12/71] clocksource: sh_cmt: Replace hardcoded register values with macros Daniel Lezcano
2014-05-23 10:30 ` [PATCH 13/71] clocksource: sh_cmt: Set cpumask to cpu_possible_mask Daniel Lezcano
2014-05-23 10:30 ` [PATCH 14/71] clocksource: sh_cmt: Hardcode CMT clock event rating to 125 Daniel Lezcano
2014-05-23 10:30 ` [PATCH 15/71] clocksource: sh_cmt: Hardcode CMT clock source " Daniel Lezcano
2014-05-23 10:30 ` [PATCH 16/71] clocksource: sh_cmt: Add support for multiple channels per device Daniel Lezcano
2014-05-23 10:30 ` [PATCH 17/71] clocksource: sh_cmt: Rename clock to "fck" in the non-legacy case Daniel Lezcano
2014-05-23 10:30 ` [PATCH 18/71] clocksource: sh_cmt: Remove FSF mail address from GPL notice Daniel Lezcano
2014-05-23 10:30 ` [PATCH 19/71] clocksource: sh_cmt: Sort headers alphabetically Daniel Lezcano
2014-05-23 10:31 ` [PATCH 20/71] clocksource: sh_cmt: Request IRQ for clock event device only Daniel Lezcano
2014-05-23 10:31 ` [PATCH 21/71] clocksource: sh_tmu: Use request_irq() instead of setup_irq() Daniel Lezcano
2014-05-23 10:31 ` [PATCH 22/71] clocksource: sh_tmu: Split channel fields from sh_tmu_priv Daniel Lezcano
2014-05-23 10:31 ` [PATCH 23/71] clocksource: sh_tmu: Rename struct sh_tmu_priv to sh_tmu_device Daniel Lezcano
2014-05-23 10:31 ` [PATCH 24/71] clocksource: sh_tmu: Split channel setup to separate function Daniel Lezcano
2014-05-23 10:31 ` [PATCH 25/71] clocksource: sh_tmu: Constify name argument to sh_tmu_register() Daniel Lezcano
2014-05-23 10:31 ` [PATCH 26/71] clocksource: sh_tmu: Add memory base to sh_tmu_channel structure Daniel Lezcano
2014-05-23 10:31 ` [PATCH 27/71] clocksource: sh_tmu: Add index to struct sh_tmu_channel Daniel Lezcano
2014-05-23 10:31 ` [PATCH 28/71] clocksource: sh_tmu: Replace kmalloc + memset with kzalloc Daniel Lezcano
2014-05-23 10:31 ` [PATCH 29/71] clocksource: sh_tmu: Allocate channels dynamically Daniel Lezcano
2014-05-23 10:31 ` [PATCH 30/71] clocksource: sh_tmu: Replace hardcoded register values with macros Daniel Lezcano
2014-05-23 10:31 ` [PATCH 31/71] clocksource: sh_tmu: Hardcode TMU clock event and source ratings to 200 Daniel Lezcano
2014-05-23 10:31 ` [PATCH 32/71] clocksource: sh_tmu: Add support for multiple channels per device Daniel Lezcano
2014-05-23 10:31 ` [PATCH 33/71] clocksource: sh_tmu: Rename clock to "fck" in the non-legacy case Daniel Lezcano
2014-05-23 10:31 ` [PATCH 34/71] clocksource: sh_tmu: Remove FSF mail address from GPL notice Daniel Lezcano
2014-05-23 10:31 ` [PATCH 35/71] clocksource: sh_tmu: Sort headers alphabetically Daniel Lezcano
2014-05-23 10:31 ` [PATCH 36/71] clocksource: sh_mtu2: Use request_irq() instead of setup_irq() Daniel Lezcano
2014-05-23 10:31 ` [PATCH 37/71] clocksource: sh_mtu2: Turn sh_mtu2_priv fields into local variables Daniel Lezcano
2014-05-23 10:31 ` [PATCH 38/71] clocksource: sh_mtu2: Split channel fields from sh_mtu2_priv Daniel Lezcano
2014-05-23 10:31 ` [PATCH 39/71] clocksource: sh_mtu2: Rename struct sh_mtu2_priv to sh_mtu2_device Daniel Lezcano
2014-05-23 10:31 ` [PATCH 40/71] clocksource: sh_mtu2: Split channel setup to separate function Daniel Lezcano
2014-05-23 10:31 ` [PATCH 41/71] clocksource: sh_mtu2: Constify name argument to sh_mtu2_register() Daniel Lezcano
2014-05-23 10:31 ` [PATCH 42/71] clocksource: sh_mtu2: Add memory base to sh_mtu2_channel structure Daniel Lezcano
2014-05-23 10:31 ` [PATCH 43/71] clocksource: sh_mtu2: Add index to struct sh_mtu2_channel Daniel Lezcano
2014-05-23 10:31 ` [PATCH 44/71] clocksource: sh_mtu2: Replace kmalloc + memset with kzalloc Daniel Lezcano
2014-05-23 10:31 ` [PATCH 45/71] clocksource: sh_mtu2: Allocate channels dynamically Daniel Lezcano
2014-05-23 10:31 ` [PATCH 46/71] clocksource: sh_mtu2: Replace hardcoded register values with macros Daniel Lezcano
2014-05-23 10:31 ` [PATCH 47/71] clocksource: sh_mtu2: Set cpumask to cpu_possible_mask Daniel Lezcano
2014-05-23 10:31 ` [PATCH 48/71] clocksource: sh_mtu2: Hardcode MTU2 clock event rating to 200 Daniel Lezcano
2014-05-23 10:31 ` [PATCH 49/71] clocksource: sh_mtu2: Add support for multiple channels per device Daniel Lezcano
2014-05-23 10:31 ` [PATCH 50/71] clocksource: sh_mtu2: Rename clock to "fck" in the non-legacy case Daniel Lezcano
2014-05-23 10:31 ` [PATCH 51/71] clocksource: sh_mtu2: Remove FSF mail address from GPL notice Daniel Lezcano
2014-05-23 10:31 ` [PATCH 52/71] clocksource: sh_mtu2: Sort headers alphabetically Daniel Lezcano
2014-05-23 10:31 ` [PATCH 53/71] clocksource: arm_global_timer: Only check for unusable timer on A9 Daniel Lezcano
2014-05-23 10:31 ` [PATCH 54/71] documentaion: DT: allow a A5 compatible string in global timer Daniel Lezcano
2014-05-23 10:31 ` [PATCH 55/71] dts: ca5: add the global timer for the A5 Daniel Lezcano
2014-05-23 10:31 ` [PATCH 56/71] KConfig: Vexpress: build the ARM_GLOBAL_TIMER with vexpress platform Daniel Lezcano
2014-05-23 10:31 ` [PATCH 57/71] clocksource: efm32: use $vendor, $device scheme for compatible string Daniel Lezcano
2014-05-23 10:31 ` [PATCH 58/71] clocksource: sun5i: Add support for reset controller Daniel Lezcano
2014-05-23 10:31 ` [PATCH 59/71] ARM: sun6i: a31: Add support for the High Speed Timers Daniel Lezcano
2014-05-23 10:31 ` [PATCH 60/71] clocksource: qcom: Implement read_current_timer for udelay Daniel Lezcano
2014-05-23 10:31 ` [PATCH 61/71] clocksource: sh_tmu: Fix channel IRQ retrieval in legacy case Daniel Lezcano
2014-05-23 10:31 ` [PATCH 62/71] clocksource: Fix type confusion for clocksource_mmio_readX_Y Daniel Lezcano
2014-05-23 10:31 ` [PATCH 63/71] clocksource: Fix clocksource_mmio_readX_down Daniel Lezcano
2014-05-23 10:31 ` [PATCH 64/71] clocksource: dw_apb_timer_of: Do not trace read_sched_clock Daniel Lezcano
2014-05-23 10:31 ` [PATCH 65/71] clocksource: em_sti: Remove unnecessary OOM messages Daniel Lezcano
2014-05-23 10:31 ` [PATCH 66/71] clocksource: sh_cmt: " Daniel Lezcano
2014-05-23 10:31 ` [PATCH 67/71] clocksource: sh_mtu2: " Daniel Lezcano
2014-05-23 10:31 ` [PATCH 68/71] clocksource: sh_tmu: " Daniel Lezcano
2014-05-23 10:31 ` [PATCH 69/71] clocksource: ftm: Add FlexTimer Module (FTM) Timer devicetree Documentation Daniel Lezcano
2014-05-23 10:31 ` [PATCH 70/71] ARM: dts: vf610: Add Freescale FlexTimer Module timer node Daniel Lezcano
2014-05-23 10:31 ` [PATCH 71/71] clocksource: Add Freescale FlexTimer Module (FTM) timer support Daniel Lezcano
[not found] ` <20140526194512.032c6630@canb.auug.org.au>
2014-05-26 9:52 ` [GIT PULL] clockevents: new material for 3.16 Daniel Lezcano
2014-05-26 13:40 ` Maxime Ripard
2014-05-26 15:07 ` Philipp Zabel
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=1400841111-6683-11-git-send-email-daniel.lezcano@linaro.org \
--to=daniel.lezcano@linaro.org \
--cc=linux-arm-kernel@lists.infradead.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 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).