linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
To: Archit Taneja <architt@codeaurora.org>, agross@codeaurora.org
Cc: galak@codeaurora.org, linux-arm-msm@vger.kernel.org
Subject: Re: [PATCH 1/3] dmaengine: qcom_bam_dma: Generalize BAM register offset calculations
Date: Fri, 19 Sep 2014 01:26:03 +0100	[thread overview]
Message-ID: <541B781B.6010209@linaro.org> (raw)
In-Reply-To: <1411037575-13153-1-git-send-email-architt@codeaurora.org>

Hi Andy,

Does this patchset supersede "dmaengine: qcom_bam_dma: Add v1.3.0 ..."
https://lkml.org/lkml/2014/4/16/660

--srini


On 18/09/14 11:52, Archit Taneja wrote:
> The BAM DMA IP comes in different versions. The register offset layout varies
> among these versions. The layouts depend on which generation/family of SoCs they
> belong to.
>
"dmaengine: qcom_bam_dma: Add v1.3.0 ..."
https://lkml.org/lkml/
> The current SoCs(like 8084, 8074) have a layout where the Top level registers
> come in the beginning of the address range, followed by pipe and event
> registers. The BAM revision numbers fall above 1.4.0.
>
> The older SoCs (like 8064, 8960) have a layout where the pipe registers come
> first, and the top level come later. These have BAM revision numbers lesser than
> 1.4.0.
> -#define BAM_CTRL		
>
> It isn't suitable to have macros provide the register offsets with the layouts
> changed. Future BAM revisions may have different register layouts too. The
> register addresses are now calculated by referring a table which contains a base
> offset and multipliers for pipe/evnt/ee registers.
>
> We have a common function bam_addr() which computes addresses for all the
> registers. When computing address of top level/ee registers, we pass 0 to the
> pipe argument in addr() since they don't have any multiple instances.
>
> Some of the unused register definitions are removed. We can add new registers as
> we need them.
>
> Signed-off-by: Archit Taneja <architt@codeaurora.org>
> ---
>   drivers/dma/qcom_bam_dma.c | 176 +++++++++++++++++++++++++++++----------------
>   1 file changed, 113 insertions(+), 63 deletions(-)
>
> diff --git a/drivers/dma/qcom_bam_dma.c b/drivers/dma/qcom_bam_dma.c
> index 7a4bbb0..b5a1662 100644
> --- a/drivers/dma/qcom_bam_dma.c
> +++ b/drivers/dma/qcom_bam_dma.c
> @@ -79,35 +79,68 @@ struct bam_async_desc {
>   	struct bam_desc_hw desc[0];
>   };
>
> -#define BAM_CTRL			0x0000
> -#define BAM_REVISION			0x0004
> -#define BAM_SW_REVISION			0x0080
> -#define BAM_NUM_PIPES			0x003C
> -#define BAM_TIMER			0x0040
> -#define BAM_TIMER_CTRL			0x0044
> -#define BAM_DESC_CNT_TRSHLD		0x0008
> -#define BAM_IRQ_SRCS			0x000C
> -#define BAM_IRQ_SRCS_MSK		0x0010
> -#define BAM_IRQ_SRCS_UNMASKED		0x0030
> -#define BAM_IRQ_STTS			0x0014
> -#define BAM_IRQ_CLR			0x0018
> -#define BAM_IRQ_EN			0x001C
> -#define BAM_CNFG_BITS			0x007C
> -#define BAM_IRQ_SRCS_EE(ee)		(0x0800 + ((ee) * 0x80))
> -#define BAM_IRQ_SRCS_MSK_EE(ee)		(0x0804 + ((ee) * 0x80))
> -#define BAM_P_CTRL(pipe)		(0x1000 + ((pipe) * 0x1000))
> -#define BAM_P_RST(pipe)			(0x1004 + ((pipe) * 0x1000))
> -#define BAM_P_HALT(pipe)		(0x1008 + ((pipe) * 0x1000))
> -#define BAM_P_IRQ_STTS(pipe)		(0x1010 + ((pipe) * 0x1000))
> -#define BAM_P_IRQ_CLR(pipe)		(0x1014 + ((pipe) * 0x1000))
> -#define BAM_P_IRQ_EN(pipe)		(0x1018 + ((pipe) * 0x1000))
> -#define BAM_P_EVNT_DEST_ADDR(pipe)	(0x182C + ((pipe) * 0x1000))
> -#define BAM_P_EVNT_REG(pipe)		(0x1818 + ((pipe) * 0x1000))
> -#define BAM_P_SW_OFSTS(pipe)		(0x1800 + ((pipe) * 0x1000))
> -#define BAM_P_DATA_FIFO_ADDR(pipe)	(0x1824 + ((pipe) * 0x1000))
> -#define BAM_P_DESC_FIFO_ADDR(pipe)	(0x181C + ((pipe) * 0x1000))
> -#define BAM_P_EVNT_TRSHLD(pipe)		(0x1828 + ((pipe) * 0x1000))
> -#define BAM_P_FIFO_SIZES(pipe)		(0x1820 + ((pipe) * 0x1000))
> +enum bam_reg {
> +	BAM_CTRL,
> +	BAM_REVISION,
> +	BAM_NUM_PIPES,
> +	BAM_DESC_CNT_TRSHLD,
> +	BAM_IRQ_SRCS,
> +	BAM_IRQ_SRCS_MSK,
> +	BAM_IRQ_SRCS_UNMASKED,
> +	BAM_IRQ_STTS,
> +	BAM_IRQ_CLR,
> +	BAM_IRQ_EN,
> +	BAM_CNFG_BITS,
> +	BAM_IRQ_SRCS_EE,
> +	BAM_IRQ_SRCS_MSK_EE,
> +	BAM_P_CTRL,
> +	BAM_P_RST,
> +	BAM_P_HALT,
> +	BAM_P_IRQ_STTS,
> +	BAM_P_IRQ_CLR,
> +	BAM_P_IRQ_EN,
> +	BAM_P_EVNT_DEST_ADDR,
> +	BAM_P_EVNT_REG,
> +	BAM_P_SW_OFSTS,
> +	BAM_P_DATA_FIFO_ADDR,
> +	BAM_P_DESC_FIFO_ADDR,
> +	BAM_P_EVNT_GEN_TRSHLD,
> +	BAM_P_FIFO_SIZES,
> +};
> +
> +struct reg_offset_data {
> +	u32 base_offset;
> +	unsigned int pipe_mult, evnt_mult, ee_mult;
> +};
> +
> +static const struct reg_offset_data reg_info[] = {
> +	[BAM_CTRL]		= { 0x0000, 0x00, 0x00, 0x00 },
> +	[BAM_REVISION]		= { 0x0004, 0x00, 0x00, 0x00 },
> +	[BAM_NUM_PIPES]		= { 0x003C, 0x00, 0x00, 0x00 },
> +	[BAM_DESC_CNT_TRSHLD]	= { 0x0008, 0x00, 0x00, 0x00 },
> +	[BAM_IRQ_SRCS]		= { 0x000C, 0x00, 0x00, 0x00 },
> +	[BAM_IRQ_SRCS_MSK]	= { 0x0010, 0x00, 0x00, 0x00 },
> +	[BAM_IRQ_SRCS_UNMASKED]	= { 0x0030, 0x00, 0x00, 0x00 },
> +	[BAM_IRQ_STTS]		= { 0x0014, 0x00, 0x00, 0x00 },
> +	[BAM_IRQ_CLR]		= { 0x0018, 0x00, 0x00, 0x00 },
> +	[BAM_IRQ_EN]		= { 0x001C, 0x00, 0x00, 0x00 },
> +	[BAM_CNFG_BITS]		= { 0x007C, 0x00, 0x00, 0x00 },
> +	[BAM_IRQ_SRCS_EE]	= { 0x0800, 0x00, 0x00, 0x80 },
> +	[BAM_IRQ_SRCS_MSK_EE]	= { 0x0804, 0x00, 0x00, 0x80 },
> +	[BAM_P_CTRL]		= { 0x1000, 0x1000, 0x00, 0x00 },
> +	[BAM_P_RST]		= { 0x1004, 0x1000, 0x00, 0x00 },
> +	[BAM_P_HALT]		= { 0x1008, 0x1000, 0x00, 0x00 },
> +	[BAM_P_IRQ_STTS]	= { 0x1010, 0x1000, 0x00, 0x00 },
> +	[BAM_P_IRQ_CLR]		= { 0x1014, 0x1000, 0x00, 0x00 },
> +	[BAM_P_IRQ_EN]		= { 0x1018, 0x1000, 0x00, 0x00 },
> +	[BAM_P_EVNT_DEST_ADDR]	= { 0x102C, 0x00, 0x1000, 0x00 },
> +	[BAM_P_EVNT_REG]	= { 0x1018, 0x00, 0x1000, 0x00 },
> +	[BAM_P_SW_OFSTS]	= { 0x1000, 0x00, 0x1000, 0x00 },
> +	[BAM_P_DATA_FIFO_ADDR]	= { 0x1824, 0x00, 0x1000, 0x00 },
> +	[BAM_P_DESC_FIFO_ADDR]	= { 0x181C, 0x00, 0x1000, 0x00 },
> +	[BAM_P_EVNT_GEN_TRSHLD]	= { 0x1828, 0x00, 0x1000, 0x00 },
> +	[BAM_P_FIFO_SIZES]	= { 0x1820, 0x00, 0x1000, 0x00 },
> +};
>
>   /* BAM CTRL */
>   #define BAM_SW_RST			BIT(0)
> @@ -305,6 +338,23 @@ struct bam_device {
>   };
>
>   /**
> + * bam_addr - returns BAM register address
> + * @bdev: bam device
> + * @pipe: pipe instance (ignored when register doesn't have multiple instances)
> + * @reg:  register enum
> + */
> +static inline void __iomem *bam_addr(struct bam_device *bdev, u32 pipe,
> +		enum bam_reg reg)
> +{
> +	const struct reg_offset_data r = reg_info[reg];
> +
> +	return bdev->regs + r.base_offset +
> +		r.pipe_mult * pipe +
> +		r.evnt_mult * pipe +
> +		r.ee_mult * bdev->ee;
> +}
> +
> +/**
>    * bam_reset_channel - Reset individual BAM DMA channel
>    * @bchan: bam channel
>    *
> @@ -317,8 +367,8 @@ static void bam_reset_channel(struct bam_chan *bchan)
>   	lockdep_assert_held(&bchan->vc.lock);
>
>   	/* reset channel */
> -	writel_relaxed(1, bdev->regs + BAM_P_RST(bchan->id));
> -	writel_relaxed(0, bdev->regs + BAM_P_RST(bchan->id));
> +	writel_relaxed(1, bam_addr(bdev, bchan->id, BAM_P_RST));
> +	writel_relaxed(0, bam_addr(bdev, bchan->id, BAM_P_RST));
>
>   	/* don't allow cpu to reorder BAM register accesses done after this */
>   	wmb();
> @@ -347,17 +397,18 @@ static void bam_chan_init_hw(struct bam_chan *bchan,
>   	 * because we allocated 1 more descriptor (8 bytes) than we can use
>   	 */
>   	writel_relaxed(ALIGN(bchan->fifo_phys, sizeof(struct bam_desc_hw)),
> -			bdev->regs + BAM_P_DESC_FIFO_ADDR(bchan->id));
> -	writel_relaxed(BAM_DESC_FIFO_SIZE, bdev->regs +
> -			BAM_P_FIFO_SIZES(bchan->id));
> +			bam_addr(bdev, bchan->id, BAM_P_DESC_FIFO_ADDR));
> +	writel_relaxed(BAM_DESC_FIFO_SIZE,
> +			bam_addr(bdev, bchan->id, BAM_P_FIFO_SIZES));
>
>   	/* enable the per pipe interrupts, enable EOT, ERR, and INT irqs */
> -	writel_relaxed(P_DEFAULT_IRQS_EN, bdev->regs + BAM_P_IRQ_EN(bchan->id));
> +	writel_relaxed(P_DEFAULT_IRQS_EN,
> +			bam_addr(bdev, bchan->id, BAM_P_IRQ_EN));
>
>   	/* unmask the specific pipe and EE combo */
> -	val = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
> +	val = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE));
>   	val |= BIT(bchan->id);
> -	writel_relaxed(val, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
> +	writel_relaxed(val, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE));
>
>   	/* don't allow cpu to reorder the channel enable done below */
>   	wmb();
> @@ -367,7 +418,7 @@ static void bam_chan_init_hw(struct bam_chan *bchan,
>   	if (dir == DMA_DEV_TO_MEM)
>   		val |= P_DIRECTION;
>
> -	writel_relaxed(val, bdev->regs + BAM_P_CTRL(bchan->id));
> +	writel_relaxed(val, bam_addr(bdev, bchan->id, BAM_P_CTRL));
>
>   	bchan->initialized = 1;
>
> @@ -432,12 +483,12 @@ static void bam_free_chan(struct dma_chan *chan)
>   	bchan->fifo_virt = NULL;
>
>   	/* mask irq for pipe/channel */
> -	val = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
> +	val = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE));
>   	val &= ~BIT(bchan->id);
> -	writel_relaxed(val, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
> +	writel_relaxed(val, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE));
>
>   	/* disable irq */
> -	writel_relaxed(0, bdev->regs + BAM_P_IRQ_EN(bchan->id));
> +	writel_relaxed(0, bam_addr(bdev, bchan->id, BAM_P_IRQ_EN));
>   }
>
>   /**
> @@ -583,14 +634,14 @@ static int bam_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
>   	switch (cmd) {
>   	case DMA_PAUSE:
>   		spin_lock_irqsave(&bchan->vc.lock, flag);
> -		writel_relaxed(1, bdev->regs + BAM_P_HALT(bchan->id));
> +		writel_relaxed(1, bam_addr(bdev, bchan->id, BAM_P_HALT));
>   		bchan->paused = 1;
>   		spin_unlock_irqrestore(&bchan->vc.lock, flag);
>   		break;
>
>   	case DMA_RESUME:
>   		spin_lock_irqsave(&bchan->vc.lock, flag);
> -		writel_relaxed(0, bdev->regs + BAM_P_HALT(bchan->id));
> +		writel_relaxed(0, bam_addr(bdev, bchan->id, BAM_P_HALT));
>   		bchan->paused = 0;
>   		spin_unlock_irqrestore(&bchan->vc.lock, flag);
>   		break;
> @@ -626,7 +677,7 @@ static u32 process_channel_irqs(struct bam_device *bdev)
>   	unsigned long flags;
>   	struct bam_async_desc *async_desc;
>
> -	srcs = readl_relaxed(bdev->regs + BAM_IRQ_SRCS_EE(bdev->ee));
> +	srcs = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_SRCS_EE));
>
>   	/* return early if no pipe/channel interrupts are present */
>   	if (!(srcs & P_IRQ))
> @@ -639,11 +690,9 @@ static u32 process_channel_irqs(struct bam_device *bdev)
>   			continue;
>
>   		/* clear pipe irq */
> -		pipe_stts = readl_relaxed(bdev->regs +
> -			BAM_P_IRQ_STTS(i));
> +		pipe_stts = readl_relaxed(bam_addr(bdev, i, BAM_P_IRQ_STTS));
>
> -		writel_relaxed(pipe_stts, bdev->regs +
> -				BAM_P_IRQ_CLR(i));
> +		writel_relaxed(pipe_stts, bam_addr(bdev, i, BAM_P_IRQ_CLR));
>
>   		spin_lock_irqsave(&bchan->vc.lock, flags);
>   		async_desc = bchan->curr_txd;
> @@ -694,12 +743,12 @@ static irqreturn_t bam_dma_irq(int irq, void *data)
>   		tasklet_schedule(&bdev->task);
>
>   	if (srcs & BAM_IRQ)
> -		clr_mask = readl_relaxed(bdev->regs + BAM_IRQ_STTS);
> +		clr_mask = readl_relaxed(bam_addr(bdev, 0, BAM_IRQ_STTS));
>
>   	/* don't allow reorder of the various accesses to the BAM registers */
>   	mb();
>
> -	writel_relaxed(clr_mask, bdev->regs + BAM_IRQ_CLR);
> +	writel_relaxed(clr_mask, bam_addr(bdev, 0, BAM_IRQ_CLR));
>
>   	return IRQ_HANDLED;
>   }
> @@ -763,7 +812,7 @@ static void bam_apply_new_config(struct bam_chan *bchan,
>   	else
>   		maxburst = bchan->slave.dst_maxburst;
>
> -	writel_relaxed(maxburst, bdev->regs + BAM_DESC_CNT_TRSHLD);
> +	writel_relaxed(maxburst, bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD));
>
>   	bchan->reconfigure = 0;
>   }
> @@ -830,7 +879,7 @@ static void bam_start_dma(struct bam_chan *bchan)
>   	/* ensure descriptor writes and dma start not reordered */
>   	wmb();
>   	writel_relaxed(bchan->tail * sizeof(struct bam_desc_hw),
> -			bdev->regs + BAM_P_EVNT_REG(bchan->id));
> +			bam_addr(bdev, bchan->id, BAM_P_EVNT_REG));
>   }
>
>   /**
> @@ -918,43 +967,44 @@ static int bam_init(struct bam_device *bdev)
>   	u32 val;
>
>   	/* read revision and configuration information */
> -	val = readl_relaxed(bdev->regs + BAM_REVISION) >> NUM_EES_SHIFT;
> +	val = readl_relaxed(bam_addr(bdev, 0, BAM_REVISION)) >> NUM_EES_SHIFT;
>   	val &= NUM_EES_MASK;
>
>   	/* check that configured EE is within range */
>   	if (bdev->ee >= val)
>   		return -EINVAL;
>
> -	val = readl_relaxed(bdev->regs + BAM_NUM_PIPES);
> +	val = readl_relaxed(bam_addr(bdev, 0, BAM_NUM_PIPES));
>   	bdev->num_channels = val & BAM_NUM_PIPES_MASK;
>
>   	/* s/w reset bam */
>   	/* after reset all pipes are disabled and idle */
> -	val = readl_relaxed(bdev->regs + BAM_CTRL);
> +	val = readl_relaxed(bam_addr(bdev, 0, BAM_CTRL));
>   	val |= BAM_SW_RST;
> -	writel_relaxed(val, bdev->regs + BAM_CTRL);
> +	writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
>   	val &= ~BAM_SW_RST;
> -	writel_relaxed(val, bdev->regs + BAM_CTRL);
> +	writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
>
>   	/* make sure previous stores are visible before enabling BAM */
>   	wmb();
>
>   	/* enable bam */
>   	val |= BAM_EN;
> -	writel_relaxed(val, bdev->regs + BAM_CTRL);
> +	writel_relaxed(val, bam_addr(bdev, 0, BAM_CTRL));
>
>   	/* set descriptor threshhold, start with 4 bytes */
> -	writel_relaxed(DEFAULT_CNT_THRSHLD, bdev->regs + BAM_DESC_CNT_TRSHLD);
> +	writel_relaxed(DEFAULT_CNT_THRSHLD,
> +			bam_addr(bdev, 0, BAM_DESC_CNT_TRSHLD));
>
>   	/* Enable default set of h/w workarounds, ie all except BAM_FULL_PIPE */
> -	writel_relaxed(BAM_CNFG_BITS_DEFAULT, bdev->regs + BAM_CNFG_BITS);
> +	writel_relaxed(BAM_CNFG_BITS_DEFAULT, bam_addr(bdev, 0, BAM_CNFG_BITS));
>
>   	/* enable irqs for errors */
>   	writel_relaxed(BAM_ERROR_EN | BAM_HRESP_ERR_EN,
> -				bdev->regs + BAM_IRQ_EN);
> +			bam_addr(bdev, 0, BAM_IRQ_EN));
>
>   	/* unmask global bam interrupt */
> -	writel_relaxed(BAM_IRQ_MSK, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
> +	writel_relaxed(BAM_IRQ_MSK, bam_addr(bdev, 0, BAM_IRQ_SRCS_MSK_EE));
>
>   	return 0;
>   }
> @@ -1084,7 +1134,7 @@ static int bam_dma_remove(struct platform_device *pdev)
>   	dma_async_device_unregister(&bdev->common);
>
>   	/* mask all interrupts for this execution environment */
> -	writel_relaxed(0, bdev->regs + BAM_IRQ_SRCS_MSK_EE(bdev->ee));
> +	writel_relaxed(0, bam_addr(bdev, 0,  BAM_IRQ_SRCS_MSK_EE));
>
>   	devm_free_irq(bdev->dev, bdev->irq, bdev);
>
>

  parent reply	other threads:[~2014-09-19  0:26 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-18 10:52 [PATCH 1/3] dmaengine: qcom_bam_dma: Generalize BAM register offset calculations Archit Taneja
2014-09-18 10:52 ` [PATCH 2/3] dmaengine: qcom_bam_dma: Add BAM v1.3.0 support Archit Taneja
2014-09-19 19:00   ` Kumar Gala
2014-09-22  4:51   ` Andy Gross
2014-09-18 10:52 ` [PATCH 3/3] dt/bindings: dmaengine: qcom_bam_dma: Add compatible string for BAM v1.3.0 Archit Taneja
2014-09-19 19:00   ` Kumar Gala
2014-09-22  4:56   ` Andy Gross
2014-09-19  0:26 ` Srinivas Kandagatla [this message]
2014-09-22  4:44   ` [PATCH 1/3] dmaengine: qcom_bam_dma: Generalize BAM register offset calculations Andy Gross
2014-09-19 19:00 ` Kumar Gala
2014-09-22  4:48 ` Andy Gross
2014-09-29  4:33 ` [PATCH v2 " Archit Taneja
2014-09-29  4:33   ` [PATCH v2 3/3] dt/bindings: dmaengine: qcom_bam_dma: Add compatible string for BAM v1.3.0 Archit Taneja
2014-09-29 22:14   ` [PATCH v2 1/3] dmaengine: qcom_bam_dma: Generalize BAM register offset calculations Andy Gross
     [not found]     ` <20140929221406.GE11142-zC7DfRvBq/JWk0Htik3J/w@public.gmane.org>
2014-10-01  8:22       ` Pramod Gurav
2014-10-02  5:24         ` Andy Gross
     [not found]   ` <1411965189-24499-1-git-send-email-architt-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2014-09-29  4:33     ` [PATCH v2 2/3] dmaengine: qcom_bam_dma: Add BAM v1.3.0 support Archit Taneja
2014-11-12 10:40     ` [PATCH v2 1/3] dmaengine: qcom_bam_dma: Generalize BAM register offset calculations Vinod Koul

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=541B781B.6010209@linaro.org \
    --to=srinivas.kandagatla@linaro.org \
    --cc=agross@codeaurora.org \
    --cc=architt@codeaurora.org \
    --cc=galak@codeaurora.org \
    --cc=linux-arm-msm@vger.kernel.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).