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 21/29] memstick: jmb38x_ms: rework TPC execution
Date: Sat, 23 Oct 2010 01:53:49 +0200 [thread overview]
Message-ID: <1287791637-10329-22-git-send-email-maximlevitsky@gmail.com> (raw)
In-Reply-To: <1287791637-10329-1-git-send-email-maximlevitsky@gmail.com>
Code rewritten to make it simplier.
A lot of debug output is added to help
diagnose bugs.
No major functional changes
Signed-off-by: Maxim Levitsky<maximlevitsky@gmail.com>
---
drivers/memstick/host/jmb38x_ms.c | 199 +++++++++++++++++++++----------------
drivers/memstick/host/jmb38x_ms.h | 3 +-
2 files changed, 114 insertions(+), 88 deletions(-)
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index 5af0a52..d15118a 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -254,94 +254,121 @@ static void j38ms_write_tpc_inline(struct j38ms_host *host)
* PIO _reads_ must be aligned. Writes can be not aligned
*
*/
-static int j38ms_execute_tpc(struct memstick_host *msh)
+
+static int j38ms_execute_tpc(struct j38ms_host *host)
{
- struct j38ms_host *host = memstick_priv(msh);
- unsigned char *data;
- unsigned int data_len, cmd, t_val;
+ u32 cmd = 0, t_val;
+ unsigned int data_len = host->req->long_data ?
+ host->req->sg.length : host->req->data_len;
+ bool is_read = host->req->data_dir == READ;
+
+ if (!(j38ms_read_reg(host, STATUS) & STATUS_HAS_MEDIA)) {
+ dbg(host, "IO: card removed, refusing to send TPC");
+ host->req->error = -ENODEV;
+ return host->req->error;
+ }
- if (!(STATUS_HAS_MEDIA & readl(host->addr + STATUS))) {
- dev_dbg(&msh->dev, "no media status\n");
- host->req->error = -ETIME;
+ if (data_len > BLOCK_SIZE_MASK) {
+ dbg(host, "IO: too long TPC (len: %d)", data_len);
+ host->req->error = -ENOSYS;
return host->req->error;
}
- dev_dbg(&msh->dev, "control %08x\n", readl(host->addr + HOST_CONTROL));
- dev_dbg(&msh->dev, "status %08x\n", readl(host->addr + INT_STATUS));
- dev_dbg(&msh->dev, "hstatus %08x\n", readl(host->addr + STATUS));
+ dbg(host, "IO: Start execution of %s",
+ memstick_debug_get_tpc_name(host->req->tpc));
+
+
+ dbg_v(host, "host control: %08x", j38ms_read_reg(host, HOST_CONTROL));
+ dbg_v(host, "int status: %08x", j38ms_read_reg(host, INT_STATUS));
+ dbg_v(host, "card status: %08x", j38ms_read_reg(host, STATUS));
+ host->req->error = 0;
host->cmd_flags = 0;
cmd = host->req->tpc << 16;
- cmd |= TPC_DATA_SEL;
-
- if (host->req->data_dir == READ)
+ if (is_read)
cmd |= TPC_DIR;
- if (host->req->need_card_int)
- cmd |= TPC_WAIT_INT;
-
- data = host->req->data;
-
- if (!no_dma)
- host->cmd_flags |= DMA_DATA;
- if (host->req->long_data) {
- data_len = host->req->sg.length;
- } else {
- data_len = host->req->data_len;
- host->cmd_flags &= ~DMA_DATA;
+ if (host->req->need_card_int) {
+ dbg_v(host, "IO: Will wait for card interrupt");
+ cmd |= TPC_WAIT_INT;
+ /* No, the TPC_GET_INT doesn't work.... */
}
- if (data_len <= 8) {
- cmd &= ~(TPC_DATA_SEL | 0xf);
+ /* Special case for short TPCs */
+ if (!host->req->long_data && data_len <= 8) {
+ dbg(host, "IO: Using 8 byte register window");
host->cmd_flags |= REG_DATA;
cmd |= data_len & 0xf;
- host->cmd_flags &= ~DMA_DATA;
+
+ if (!is_read)
+ j38ms_write_tpc_inline(host);
+ goto exec;
}
- if (host->cmd_flags & DMA_DATA) {
- if (1 != pci_map_sg(host->chip->pdev, &host->req->sg, 1,
- host->req->data_dir == READ
- ? PCI_DMA_FROMDEVICE
- : PCI_DMA_TODEVICE)) {
+ /* Otherwise use internal fifo*/
+ cmd |= TPC_DATA_SEL;
+
+ if (data_len & 0x03) {
+ dbg(host, "Hardware doesn't support not-aligned len TPCs!");
+ host->req->error = -ENOSYS;
+ return host->req->error;
+ }
+
+ /* DMA */
+ if (!no_dma && host->req->long_data) {
+
+ dbg(host, "IO: Using DMA");
+ host->cmd_flags |= DMA_DATA;
+
+ if (pci_map_sg(host->chip->pdev,
+ &host->req->sg, 1, is_read
+ ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE) != 1) {
+
+ dbg(host, "IO: DMA map failed");
host->req->error = -ENOMEM;
return host->req->error;
}
- data_len = sg_dma_len(&host->req->sg);
- writel(sg_dma_address(&host->req->sg),
- host->addr + DMA_ADDRESS);
- writel(((1 << 16) & BLOCK_COUNT_MASK)
- | (data_len & BLOCK_SIZE_MASK),
- host->addr + BLOCK);
- writel(DMA_CONTROL_ENABLE, host->addr + DMA_CONTROL);
- } else if (!(host->cmd_flags & REG_DATA)) {
- writel(((1 << 16) & BLOCK_COUNT_MASK)
- | (data_len & BLOCK_SIZE_MASK),
- host->addr + BLOCK);
- t_val = readl(host->addr + INT_STATUS_ENABLE);
- t_val |= host->req->data_dir == READ
- ? INT_STATUS_FIFO_RRDY
- : INT_STATUS_FIFO_WRDY;
-
- writel(t_val, host->addr + INT_STATUS_ENABLE);
- writel(t_val, host->addr + INT_SIGNAL_ENABLE);
+
+ /* We really shouldn't pretend we support that case */
+ if (sg_dma_len(&host->req->sg) != data_len) {
+ dbg(host, "IO: DMA len mismatch");
+ host->req->error = -EFAULT;
+ return host->req->error;
+ }
+
+ j38ms_write_reg(host, BLOCK, data_len | BLOCK_COUNT_1BLOCK);
+ j38ms_write_reg(host, DMA_ADDRESS,
+ sg_dma_address(&host->req->sg));
+ j38ms_write_reg(host, DMA_CONTROL, DMA_CONTROL_ENABLE);
+ /* PIO */
} else {
- cmd &= ~(TPC_DATA_SEL | 0xf);
- host->cmd_flags |= REG_DATA;
- cmd |= data_len & 0xf;
- if (host->req->data_dir == WRITE)
- j38ms_write_tpc_inline(host);
- }
+ dbg(host, "IO: Using PIO");
+ host->cmd_flags |= PIO_DATA;
- mod_timer(&host->timer, jiffies + host->timeout_jiffies);
- writel(HOST_CONTROL_LED | readl(host->addr + HOST_CONTROL),
- host->addr + HOST_CONTROL);
- host->req->error = 0;
+ host->pio_offset = 0;
+ host->pio_tmp_buf_len = 0;
+ memset(host->pio_tmp_buf, 0, 4);
- writel(cmd, host->addr + TPC);
- dev_dbg(&msh->dev, "executing TPC %08x, len %x\n", cmd, data_len);
+ if (host->req->long_data)
+ sg_miter_start(&host->pio_sg_iter,
+ &host->req->sg, 1, SG_MITER_ATOMIC |
+ (is_read ? SG_MITER_FROM_SG : SG_MITER_TO_SG));
+
+ /* Enable FIFO empty interrupts */
+ t_val = is_read ? INT_STATUS_FIFO_RRDY : INT_STATUS_FIFO_WRDY;
+ j38ms_write_reg(host, BLOCK, data_len | BLOCK_COUNT_1BLOCK);
+ j38ms_set_reg_mask(host, INT_SIGNAL_ENABLE, t_val);
+ j38ms_set_reg_mask(host, INT_STATUS_ENABLE, t_val);
+ }
+exec:
+ mod_timer(&host->timer, jiffies + host->timeout_jiffies);
+
+ /* Let the TPC fly... */
+ j38ms_write_reg(host, TPC, cmd);
+ j38ms_set_reg_mask(host, HOST_CONTROL, HOST_CONTROL_LED);
return 0;
}
@@ -349,44 +376,42 @@ static int j38ms_execute_tpc(struct memstick_host *msh)
static void j38ms_complete_tpc(struct memstick_host *msh, int last)
{
struct j38ms_host *host = memstick_priv(msh);
- unsigned int t_val = 0;
int rc;
-
del_timer(&host->timer);
- dev_dbg(&msh->dev, "c control %08x\n",
- readl(host->addr + HOST_CONTROL));
- dev_dbg(&msh->dev, "c status %08x\n",
- readl(host->addr + INT_STATUS));
- dev_dbg(&msh->dev, "c hstatus %08x\n", readl(host->addr + STATUS));
+ dbg(host, "IO: TPC complete (error : %d)", host->req->error);
- host->req->int_reg = readl(host->addr + STATUS) & 0xff;
+ j38ms_write_reg(host, BLOCK, 0);
+ j38ms_write_reg(host, DMA_CONTROL, 0);
- writel(0, host->addr + BLOCK);
- writel(0, host->addr + DMA_CONTROL);
+ dbg_v(host, "host control: %08x", j38ms_read_reg(host, HOST_CONTROL));
+ dbg_v(host, "int status: %08x", j38ms_read_reg(host, INT_STATUS));
+ dbg_v(host, "card status: %08x", j38ms_read_reg(host, STATUS));
+
+ if (host->req->need_card_int)
+ host->req->int_reg = j38ms_read_reg(host, STATUS) & 0xFF;
if (host->cmd_flags & DMA_DATA) {
pci_unmap_sg(host->chip->pdev, &host->req->sg, 1,
- host->req->data_dir == READ
- ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
- } else {
- t_val = readl(host->addr + INT_STATUS_ENABLE);
- if (host->req->data_dir == READ)
- t_val &= ~INT_STATUS_FIFO_RRDY;
- else
- t_val &= ~INT_STATUS_FIFO_WRDY;
+ host->req->data_dir == READ
+ ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
- writel(t_val, host->addr + INT_STATUS_ENABLE);
- writel(t_val, host->addr + INT_SIGNAL_ENABLE);
+ } else if (host->cmd_flags & PIO_DATA) {
+ u32 t_val = INT_STATUS_FIFO_RRDY | INT_STATUS_FIFO_WRDY;
+
+ /* This is not known well */
+ j38ms_clear_reg_mask(host, INT_STATUS_ENABLE, t_val);
+
+ /* This disables the IRQ to host, really */
+ j38ms_clear_reg_mask(host, INT_SIGNAL_ENABLE, t_val);
}
- writel((~HOST_CONTROL_LED) & readl(host->addr + HOST_CONTROL),
- host->addr + HOST_CONTROL);
+ j38ms_clear_reg_mask(host, HOST_CONTROL, HOST_CONTROL_LED);
if (!last) {
do {
rc = memstick_next_req(msh, &host->req);
- } while (!rc && j38ms_execute_tpc(msh));
+ } while (!rc && j38ms_execute_tpc(host));
} else {
do {
rc = memstick_next_req(msh, &host->req);
@@ -488,7 +513,7 @@ static void j38ms_submit_tasklet(unsigned long data)
do {
rc = memstick_next_req(msh, &host->req);
dev_dbg(&host->chip->pdev->dev, "tasklet req %d\n", rc);
- } while (!rc && j38ms_execute_tpc(msh));
+ } while (!rc && j38ms_execute_tpc(host));
}
spin_unlock_irqrestore(&host->lock, flags);
}
diff --git a/drivers/memstick/host/jmb38x_ms.h b/drivers/memstick/host/jmb38x_ms.h
index d7dffb6..429ed49 100644
--- a/drivers/memstick/host/jmb38x_ms.h
+++ b/drivers/memstick/host/jmb38x_ms.h
@@ -173,7 +173,8 @@ enum {
CMD_READY = 0x01,
FIFO_READY = 0x02,
REG_DATA = 0x04,
- DMA_DATA = 0x08
+ DMA_DATA = 0x08,
+ PIO_DATA = 0x10
};
--
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 ` [PATCH 12/29] memstick: mspro: rework interface switch Maxim Levitsky
2010-10-25 15:28 ` 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 ` Maxim Levitsky [this message]
2010-10-25 16:08 ` [PATCH 21/29] memstick: jmb38x_ms: rework TPC execution 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-22-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