From: Maxim Levitsky <maximlevitsky@gmail.com>
To: Alex Dubov <oakad@yahoo.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
LKML <linux-kernel@vger.kernel.org>,
Maxim Levitsky <maximlevitsky@gmail.com>
Subject: [PATCH 12/29] memstick: mspro: rework interface switch
Date: Sat, 23 Oct 2010 01:53:40 +0200 [thread overview]
Message-ID: <1287791637-10329-13-git-send-email-maximlevitsky@gmail.com> (raw)
In-Reply-To: <1287791637-10329-1-git-send-email-maximlevitsky@gmail.com>
Now no old style state machine exist.
Thus this patch removes now unused code.
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
---
drivers/memstick/core/memstick.c | 15 --
drivers/memstick/core/mspro_block.c | 328 +++++++++++++++++------------------
drivers/memstick/core/mspro_block.h | 4 +-
include/linux/memstick.h | 2 -
4 files changed, 162 insertions(+), 187 deletions(-)
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
index e1aa089..5eea1b2 100644
--- a/drivers/memstick/core/memstick.c
+++ b/drivers/memstick/core/memstick.c
@@ -424,21 +424,6 @@ int memstick_set_rw_addr(struct memstick_dev *card)
EXPORT_SYMBOL(memstick_set_rw_addr);
-/**
- * memstick_new_req - notify the host that some requests are pending
- * @host - host to use
- */
-void memstick_new_req(struct memstick_host *host)
-{
- if (host->card) {
- host->retries = cmd_retries;
- INIT_COMPLETION(host->card->mrq_complete);
- host->request(host);
- }
-}
-EXPORT_SYMBOL(memstick_new_req);
-
-
/*** state machine support code ***/
/**
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index e54d467..85018ce 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -372,54 +372,6 @@ static sysfs_show_t mspro_block_attr_show(unsigned char tag)
* finished (and request processor should come back some time later).
*/
-static int h_mspro_block_req_init(struct memstick_dev *card,
- struct memstick_request **mrq)
-{
- struct mspro_block_data *msb = memstick_get_drvdata(card);
-
- *mrq = &card->current_mrq;
- card->next_request = msb->mrq_handler;
- return 0;
-}
-
-static int h_mspro_block_default(struct memstick_dev *card,
- struct memstick_request **mrq)
-{
- return memstick_exit_state_machine(card, *mrq, (*mrq)->error);
-}
-
-
-static int h_mspro_block_get_ro(struct memstick_dev *card,
- struct memstick_request **mrq)
-{
- struct mspro_block_data *msb = memstick_get_drvdata(card);
-
- if (!(*mrq)->error) {
- if ((*mrq)->data[offsetof(struct ms_status_register, status0)]
- & MEMSTICK_STATUS0_WP)
- msb->read_only = 1;
- else
- msb->read_only = 0;
- }
-
- return memstick_exit_state_machine(card, *mrq, (*mrq)->error);
-}
-
-static int h_mspro_block_wait_for_ced(struct memstick_dev *card,
- struct memstick_request **mrq)
-{
- dev_dbg(&card->dev, "wait for ced: value %x\n", (*mrq)->data[0]);
-
- if (!(*mrq)->error) {
- if ((*mrq)->data[0] & (MEMSTICK_INT_CMDNAK | MEMSTICK_INT_ERR))
- (*mrq)->error = -EFAULT;
- else if (!((*mrq)->data[0] & MEMSTICK_INT_CED))
- return 0;
- }
-
- return memstick_exit_state_machine(card, *mrq, (*mrq)->error);
-}
-
static int h_mspro_block_transfer_data(struct memstick_dev *card,
struct memstick_request **mrq)
{
@@ -552,6 +504,109 @@ again:
return 0;
}
+
+static int h_mspro_block_reset(struct memstick_dev *card,
+ struct memstick_request **mrq)
+{
+ struct mspro_block_data *msb = memstick_get_drvdata(card);
+ struct ms_status_register *status;
+ u8 intreg;
+
+ memstick_allocate_request(card, mrq);
+ if ((*mrq)->error)
+ return memstick_exit_state_machine(card, *mrq, (*mrq)->error);
+
+again:
+ switch (card->state) {
+
+ case 0: /* send request for INT reg */
+ if (memstick_read_int_reg(card, *mrq, 10000))
+ break;
+ card->state++;
+
+ case 1: /* process the INT reg and loop if nessesary */
+ intreg = (*mrq)->data[0];
+
+ if (intreg & MEMSTICK_INT_ERR) {
+ if ((intreg & MEMSTICK_INT_CMDNAK)) {
+ msb->read_only = true;
+ return memstick_exit_state_machine(card,
+ *mrq, 0);
+ }
+ return memstick_exit_state_machine(card, *mrq, -EIO);
+ }
+
+ if (intreg & MEMSTICK_INT_CMDNAK)
+ return memstick_exit_state_machine(card, *mrq, -EIO);
+
+
+ if (!(intreg & MEMSTICK_INT_CED)) {
+ card->state--;
+ goto again;
+ }
+
+ memstick_read_int_reg_cleanup(card);
+ card->state++;
+
+ case 2: /* read the R/O status */
+
+ if (!memstick_read_regs(card,
+ offsetof(struct mspro_register, status),
+ sizeof(struct ms_status_register),
+ *mrq))
+ return 0;
+ break;
+
+ case 3: /* process the result & done */
+ status = (struct ms_status_register *)(*mrq)->data;
+ msb->read_only = status->status0 & MEMSTICK_STATUS0_WP;
+ return memstick_exit_state_machine(card, *mrq, 0);
+ }
+
+ card->state++;
+ return 0;
+
+}
+
+static int h_mspro_block_switch_interface(struct memstick_dev *card,
+ struct memstick_request **mrq)
+{
+ struct mspro_block_data *msb = memstick_get_drvdata(card);
+ int error;
+ memstick_allocate_request(card, mrq);
+ if ((*mrq)->error)
+ return memstick_exit_state_machine(card, *mrq, (*mrq)->error);
+
+ switch (card->state) {
+
+ case 0: /* send switch command to the device */
+ if (!memstick_write_regs(card,
+ offsetof(struct mspro_register, param),
+ 1,
+ &msb->system,
+ *mrq))
+ return 0;
+ break;
+
+ case 1: /* switch the host intrface + send dummy read to verify that */
+ /* connection works */
+ error = card->host->set_param(card->host,
+ MEMSTICK_INTERFACE, msb->target_interface);
+ if (error)
+ return memstick_exit_state_machine(card, *mrq, -EFAULT);
+
+ memstick_init_req(*mrq, MS_TPC_GET_INT, NULL, 1);
+ break;
+
+ case 2: /* done */
+ return memstick_exit_state_machine(card, *mrq, 0);
+
+ }
+
+ card->state++;
+ return 0;
+}
+
/*** Data transfer ***/
/* Common helper that prepares state for IO (read, write, read attributes) */
@@ -717,113 +772,77 @@ static void mspro_block_submit_req(struct request_queue *q)
/*** Initialization ***/
-static int mspro_block_wait_for_ced(struct memstick_dev *card)
+/* Reset the card */
+static int mspro_block_reset(struct memstick_dev *card, bool full)
{
struct mspro_block_data *msb = memstick_get_drvdata(card);
+ int error;
- card->next_request = h_mspro_block_req_init;
- msb->mrq_handler = h_mspro_block_wait_for_ced;
- memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1);
- memstick_new_req(card->host);
- wait_for_completion(&card->mrq_complete);
- return card->current_mrq.error;
-}
+ dbg(card, "resetting the card");
-static int mspro_block_set_interface(struct memstick_dev *card,
- unsigned char sys_reg)
-{
- struct memstick_host *host = card->host;
- struct mspro_block_data *msb = memstick_get_drvdata(card);
- struct mspro_param_register param = {
- .system = sys_reg,
- .data_count = 0,
- .data_address = 0,
- .tpc_param = 0
- };
+ msb->system = MEMSTICK_SYS_SERIAL;
- card->next_request = h_mspro_block_req_init;
- msb->mrq_handler = h_mspro_block_default;
- memstick_init_req(&card->current_mrq, MS_TPC_WRITE_REG, ¶m,
- sizeof(param));
- memstick_new_req(host);
- wait_for_completion(&card->mrq_complete);
- return card->current_mrq.error;
+ if (full) {
+ error = memstick_reset(card->host);
+ if (error) {
+ dbg(card, "host controller reset failure");
+ return error;
+ }
+ }
+
+ msleep(150);
+
+ error = memstick_run_state_machine(card, h_mspro_block_reset, true);
+ if (error) {
+ dbg(card, "card reset failure");
+ return error;
+ }
+
+ return mspro_block_switch_interface(card);
}
+/*
+ * Attempts to switch to faster interface.
+ * If switch fails it clears the card capability of this mode
+ * and calls reset which might call this function again but that
+ * time it won't attempt failed mode
+ */
static int mspro_block_switch_interface(struct memstick_dev *card)
{
struct memstick_host *host = card->host;
struct mspro_block_data *msb = memstick_get_drvdata(card);
- int rc = 0;
+ int error = 0;
-try_again:
- if (msb->caps & MEMSTICK_CAP_PAR4)
- rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR4);
- else
+ if (!(card->caps & host->caps & MEMSTICK_CAP_PAR4))
return 0;
- if (rc) {
- printk(KERN_WARNING
- "%s: could not switch to 4-bit mode, error %d\n",
- dev_name(&card->dev), rc);
- return 0;
- }
+ dbg(card, "switching to parallel 4 bit inteface");
msb->system = MEMSTICK_SYS_PAR4;
- host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4);
- printk(KERN_INFO "%s: switching to 4-bit parallel mode\n",
- dev_name(&card->dev));
-
- if (msb->caps & MEMSTICK_CAP_PAR8) {
- rc = mspro_block_set_interface(card, MEMSTICK_SYS_PAR8);
-
- if (!rc) {
- msb->system = MEMSTICK_SYS_PAR8;
- host->set_param(host, MEMSTICK_INTERFACE,
- MEMSTICK_PAR8);
- printk(KERN_INFO
- "%s: switching to 8-bit parallel mode\n",
- dev_name(&card->dev));
- } else
- printk(KERN_WARNING
- "%s: could not switch to 8-bit mode, error %d\n",
- dev_name(&card->dev), rc);
+ msb->target_interface = MEMSTICK_PAR4;
+ error = memstick_run_state_machine(card,
+ h_mspro_block_switch_interface, true);
+ if (error) {
+ dbg(card, "failure to switch to parallel 4 bit inteface");
+ card->caps &= ~MEMSTICK_CAP_PAR4;
+ return mspro_block_reset(card, true);
}
- card->next_request = h_mspro_block_req_init;
- msb->mrq_handler = h_mspro_block_default;
- memstick_init_req(&card->current_mrq, MS_TPC_GET_INT, NULL, 1);
- memstick_new_req(card->host);
- wait_for_completion(&card->mrq_complete);
- rc = card->current_mrq.error;
+ if (!(card->caps & host->caps & MEMSTICK_CAP_PAR8))
+ return 0;
- if (rc) {
- printk(KERN_WARNING
- "%s: interface error, trying to fall back to serial\n",
- dev_name(&card->dev));
- msb->system = MEMSTICK_SYS_SERIAL;
- host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_OFF);
- msleep(10);
- host->set_param(host, MEMSTICK_POWER, MEMSTICK_POWER_ON);
- host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_SERIAL);
-
- rc = memstick_set_rw_addr(card);
- if (!rc)
- rc = mspro_block_set_interface(card, msb->system);
-
- if (!rc) {
- msleep(150);
- rc = mspro_block_wait_for_ced(card);
- if (rc)
- return rc;
-
- if (msb->caps & MEMSTICK_CAP_PAR8) {
- msb->caps &= ~MEMSTICK_CAP_PAR8;
- goto try_again;
- }
- }
+ msb->system = MEMSTICK_SYS_PAR8;
+ msb->target_interface = MEMSTICK_PAR8;
+ dbg(card, "switching to parallel 8 bit inteface");
+ error = memstick_run_state_machine(card,
+ h_mspro_block_switch_interface, true);
+ if (error) {
+ dbg(card, "failure to switch to parallel 8 bit inteface");
+ card->caps &= ~MEMSTICK_CAP_PAR8;
+ return mspro_block_reset(card, true);
}
- return rc;
+
+ return error;
}
/* Read data from attribute space */
@@ -857,7 +876,7 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
int cnt, error, attr_count;
- /* Allocate initial buffer */
+ /* Allocate cache buffer */
buffer_size = msb->page_size;
buffer_address = 0;
buffer = kmalloc(buffer_size, GFP_KERNEL);
@@ -981,52 +1000,27 @@ out_free_buffer:
static int mspro_block_init_card(struct memstick_dev *card)
{
struct mspro_block_data *msb = memstick_get_drvdata(card);
- struct memstick_host *host = card->host;
int rc = 0;
- msb->system = MEMSTICK_SYS_SERIAL;
- card->reg_addr.r_offset = offsetof(struct mspro_register, status);
- card->reg_addr.r_length = sizeof(struct ms_status_register);
- card->reg_addr.w_offset = offsetof(struct mspro_register, param);
- card->reg_addr.w_length = sizeof(struct mspro_param_register);
-
- if (memstick_set_rw_addr(card))
- return -EIO;
+ card->caps = MEMSTICK_CAP_PAR4 | MEMSTICK_CAP_PAR8;
- msb->caps = host->caps;
-
- msleep(150);
- rc = mspro_block_wait_for_ced(card);
+ rc = mspro_block_reset(card, false);
if (rc)
return rc;
- rc = mspro_block_switch_interface(card);
- if (rc)
- return rc;
-
- dev_dbg(&card->dev, "card activated\n");
+ dbg(card, "card activated");
if (msb->system != MEMSTICK_SYS_SERIAL)
- msb->caps |= MEMSTICK_CAP_AUTO_GET_INT;
-
- card->next_request = h_mspro_block_req_init;
- msb->mrq_handler = h_mspro_block_get_ro;
- memstick_init_req(&card->current_mrq, MS_TPC_READ_REG, NULL,
- sizeof(struct ms_status_register));
- memstick_new_req(card->host);
- wait_for_completion(&card->mrq_complete);
- if (card->current_mrq.error)
- return card->current_mrq.error;
+ card->caps |= MEMSTICK_CAP_AUTO_GET_INT;
- dev_dbg(&card->dev, "card r/w status %d\n", msb->read_only ? 0 : 1);
+ dbg(card, "card r/w status %d", msb->read_only ? 0 : 1);
msb->page_size = 512;
rc = mspro_block_read_attributes(card);
if (rc)
return rc;
- dev_dbg(&card->dev, "attributes loaded\n");
+ dbg(card, "attributes loaded");
return 0;
-
}
static int mspro_block_init_disk(struct memstick_dev *card)
diff --git a/drivers/memstick/core/mspro_block.h b/drivers/memstick/core/mspro_block.h
index 82ae2fe..a7ba42d 100644
--- a/drivers/memstick/core/mspro_block.h
+++ b/drivers/memstick/core/mspro_block.h
@@ -135,9 +135,6 @@ struct mspro_block_data {
spinlock_t q_lock;
struct scatterlist req_sg[MSPRO_BLOCK_MAX_SEGS];
- int (*mrq_handler)(struct memstick_dev *card,
- struct memstick_request **mrq);
-
unsigned char read_only:1;
unsigned char eject:1;
unsigned char active:1;
@@ -157,6 +154,7 @@ struct mspro_block_data {
unsigned int current_sg_offset;
unsigned int data_transferred;
unsigned char data_dir:1;
+ unsigned int target_interface;
int io_error;
};
diff --git a/include/linux/memstick.h b/include/linux/memstick.h
index 73586cb..4700543 100644
--- a/include/linux/memstick.h
+++ b/include/linux/memstick.h
@@ -366,8 +366,6 @@ int memstick_exit_state_machine(struct memstick_dev *card,
void memstick_allocate_request(struct memstick_dev *card,
struct memstick_request **mrq);
-void memstick_new_req(struct memstick_host *host);
-
void memstick_init_req_sg(struct memstick_request *mrq, unsigned char tpc,
const struct scatterlist *sg);
void memstick_init_req(struct memstick_request *mrq, unsigned char tpc,
--
1.7.1
next prev parent reply other threads:[~2010-10-22 23:54 UTC|newest]
Thread overview: 84+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-10-22 23:53 [PATCH 0/29] My patch queue for memorystick subsystem Maxim Levitsky
2010-10-22 23:53 ` [PATCH 01/29] memstick: core: header cleanups Maxim Levitsky
2010-10-25 14:44 ` Alex Dubov
2010-10-26 1:10 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 02/29] memstick: core: reorder functions This patch just reorders functions in memstick.c So that host specific and card driver specific functions are now grouped together. This makes it easier to understand the code Maxim Levitsky
2010-10-25 14:50 ` Alex Dubov
2010-10-26 1:14 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 03/29] memstick: core: add new functions Maxim Levitsky
2010-10-25 14:56 ` Alex Dubov
2010-10-26 1:20 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 04/29] memstick: core: rework state machines Maxim Levitsky
2010-10-25 15:01 ` Alex Dubov
2010-10-26 1:34 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 05/29] memstick: mspro_block: move declarations to header and refactor things a bit Maxim Levitsky
2010-10-25 15:07 ` Alex Dubov
2010-10-26 1:46 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 06/29] memstick: mspro: kill the BKL Maxim Levitsky
2010-10-25 15:12 ` Alex Dubov
2010-10-26 1:50 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 07/29] memstick: mspro: two fixes Maxim Levitsky
2010-10-25 15:13 ` Alex Dubov
2010-10-26 1:51 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 08/29] memstick: mspro: add comments to few functions Maxim Levitsky
2010-10-25 15:18 ` Alex Dubov
2010-10-26 1:54 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 09/29] memstick: rework state machines + attribute read function Maxim Levitsky
2010-10-25 15:23 ` Alex Dubov
2010-10-26 1:57 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 10/29] memstick: mspro: create _setup_io helper Maxim Levitsky
2010-10-25 15:25 ` Alex Dubov
2010-10-26 1:58 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 11/29] memstick: mspro: use MS_TPC_EX_SET_CMD Maxim Levitsky
2010-10-25 15:27 ` Alex Dubov
2010-10-26 2:00 ` Maxim Levitsky
2010-10-22 23:53 ` Maxim Levitsky [this message]
2010-10-25 15:28 ` [PATCH 12/29] memstick: mspro: rework interface switch Alex Dubov
2010-10-26 2:01 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 13/29] memstick: core: stop passing pointer to card->current_mrq Maxim Levitsky
2010-10-25 15:41 ` Alex Dubov
2010-10-26 2:04 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 14/29] memstick: remove the memstick_set_rw_addr Maxim Levitsky
2010-10-25 15:55 ` Alex Dubov
2010-10-26 2:08 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 15/29] memstick: jmb38x_ms: Create header Maxim Levitsky
2010-10-25 15:56 ` Alex Dubov
2010-10-26 2:10 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 16/29] memstick: jmb38x_ms: s/jmb38x_ms/j38ms/g Maxim Levitsky
2010-10-25 15:58 ` Alex Dubov
2010-10-26 2:13 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 17/29] memstick: jmb38x_ms: move "reg_data" functions together Maxim Levitsky
2010-10-25 16:00 ` Alex Dubov
2010-10-26 2:14 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 18/29] memstick: jmb38x_ms: rename functions Maxim Levitsky
2010-10-25 16:00 ` Alex Dubov
2010-10-26 2:17 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 19/29] memstick: jmb38x_ms: add register read/write functions Maxim Levitsky
2010-10-25 16:03 ` Alex Dubov
2010-10-26 2:19 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 20/29] memstick: jmb38x_ms: rework PIO Maxim Levitsky
2010-10-25 16:05 ` Alex Dubov
2010-10-26 2:21 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 21/29] memstick: jmb38x_ms: rework TPC execution Maxim Levitsky
2010-10-25 16:08 ` Alex Dubov
2010-10-26 2:22 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 22/29] memstick: jmb38x_ms: rework ISR Maxim Levitsky
2010-10-25 16:11 ` Alex Dubov
2010-10-26 2:23 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 23/29] memstick: jmb38x_ms: use DMA for all TPCs with len greater that 8 by default Maxim Levitsky
2010-10-25 16:12 ` Alex Dubov
2010-10-26 2:29 ` Maxim Levitsky
2010-10-22 23:53 ` [PATCH 24/29] memstick: jmb38x_ms: rework processing of the TPC one after another Maxim Levitsky
2010-10-25 16:14 ` Alex Dubov
2010-10-22 23:53 ` [PATCH 25/29] memstick: jmb38x_ms: pass j38ms_host to few functions instead of memstick_host Maxim Levitsky
2010-10-22 23:53 ` [PATCH 26/29] memstick: jmb38x_ms: rework hardware setup/reset Maxim Levitsky
2010-10-25 16:17 ` Alex Dubov
2010-10-22 23:53 ` [PATCH 27/29] memstick: jmb38x_ms: minor additions Maxim Levitsky
2010-10-22 23:53 ` [PATCH 28/29] memstick: add support for legacy memorysticks Maxim Levitsky
2010-10-22 23:53 ` [PATCH 29/29] memstick: Add driver for Ricoh R5C592 Card reader Maxim Levitsky
2010-10-25 2:01 ` [PATCH 0/29] My patch queue for memorystick subsystem Maxim Levitsky
2010-10-25 14:39 ` Alex Dubov
2010-10-25 16:07 ` Andrew Morton
2010-10-25 16:10 ` Alex Dubov
2010-10-26 2:32 ` Maxim Levitsky
2010-10-25 16:25 ` Alex Dubov
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=1287791637-10329-13-git-send-email-maximlevitsky@gmail.com \
--to=maximlevitsky@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=oakad@yahoo.com \
/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
Powered by JetHome