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 20/29] memstick: jmb38x_ms: rework PIO
Date: Sat, 23 Oct 2010 01:53:48 +0200 [thread overview]
Message-ID: <1287791637-10329-21-git-send-email-maximlevitsky@gmail.com> (raw)
In-Reply-To: <1287791637-10329-1-git-send-email-maximlevitsky@gmail.com>
Rewrite PIO code to be just simplier and shorter,
and comment not so obivous parts.
Signed-off-by: Maxim Levitsky<maximlevitsky@gmail.com>
---
drivers/memstick/host/jmb38x_ms.c | 283 +++++++++++++------------------------
drivers/memstick/host/jmb38x_ms.h | 17 +--
2 files changed, 103 insertions(+), 197 deletions(-)
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index bcdb785..5af0a52 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -17,6 +17,7 @@
#include <linux/highmem.h>
#include <linux/memstick.h>
#include <linux/slab.h>
+#include <linux/scatterlist.h>
#include "jmb38x_ms.h"
static int no_dma;
@@ -103,39 +104,34 @@ static inline int j38ms_write_fifo_dword_pio(struct j38ms_host *host, u32 dword)
static unsigned int j38ms_read_fifo_pio(struct j38ms_host *host,
unsigned char *buf, unsigned int length)
{
- unsigned int off = 0;
+ unsigned int orig_len = length;
+ unsigned char tmp_buf[4];
- while (host->io_pos && length) {
- buf[off++] = host->io_word[0] & 0xff;
- host->io_word[0] >>= 8;
- length--;
- host->io_pos--;
+ /* Read bytes from last saved part */
+ if (host->pio_tmp_buf_len) {
+ int count = min(host->pio_tmp_buf_len, length);
+ memcpy(buf, host->pio_tmp_buf, count);
+ buf += count;
+ length -= count;
}
- if (!length)
- return off;
+ /* Read aligned data*/
+ for (; length >= 4 ; buf += 4, length -= 4)
+ if (j38ms_read_fifo_dword_pio(host, (u32 *)buf))
+ return orig_len - length;
- while (!(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
- if (length < 4)
- break;
- *(unsigned int *)(buf + off) = __raw_readl(host->addr + DATA);
- length -= 4;
- off += 4;
- }
+ /* Read last 4 bytes, and
+ save unconsumed part of it to the pio_tmp_buf */
+ if (length && !j38ms_read_fifo_dword_pio(host, (u32 *)tmp_buf)) {
- if (length
- && !(STATUS_FIFO_EMPTY & readl(host->addr + STATUS))) {
- host->io_word[0] = readl(host->addr + DATA);
- for (host->io_pos = 4; host->io_pos; --host->io_pos) {
- buf[off++] = host->io_word[0] & 0xff;
- host->io_word[0] >>= 8;
- length--;
- if (!length)
- break;
- }
+ host->pio_tmp_buf_len = 4 - length;
+ memcpy(buf, tmp_buf, length);
+ memcpy(host->pio_tmp_buf,
+ tmp_buf + length, host->pio_tmp_buf_len);
+ length = 0;
}
- return off;
+ return orig_len - length;
}
/* Write TPC data through normal PIO fifo */
@@ -143,175 +139,106 @@ static unsigned int j38ms_write_fifo_pio(struct j38ms_host *host,
unsigned char *buf,
unsigned int length)
{
- unsigned int off = 0;
-
- if (host->io_pos) {
- while (host->io_pos < 4 && length) {
- host->io_word[0] |= buf[off++] << (host->io_pos * 8);
- host->io_pos++;
- length--;
+ unsigned int orig_len = length;
+
+ /* Complete the last saved bytes*/
+ if (host->pio_tmp_buf_len) {
+ int count = min(4 - host->pio_tmp_buf_len, length);
+ memcpy(host->pio_tmp_buf + host->pio_tmp_buf_len, buf, count);
+ buf += count;
+ length -= count;
+
+ if (host->pio_tmp_buf_len == 4) {
+ if (j38ms_write_fifo_dword_pio(
+ host, *(u32 *)host->pio_tmp_buf))
+ return orig_len - length;
+ else
+ host->pio_tmp_buf_len = 0;
}
}
- if (host->io_pos == 4
- && !(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
- writel(host->io_word[0], host->addr + DATA);
- host->io_pos = 0;
- host->io_word[0] = 0;
- } else if (host->io_pos) {
- return off;
- }
-
- if (!length)
- return off;
-
- while (!(STATUS_FIFO_FULL & readl(host->addr + STATUS))) {
- if (length < 4)
- break;
-
- __raw_writel(*(unsigned int *)(buf + off),
- host->addr + DATA);
- length -= 4;
- off += 4;
- }
+ /* Write aligned data to hardware */
+ for (; length >= 4 ; length -= 4, buf += 4)
+ if (j38ms_write_fifo_dword_pio(host, *(u32 *)buf))
+ return orig_len - length;
- switch (length) {
- case 3:
- host->io_word[0] |= buf[off + 2] << 16;
- host->io_pos++;
- case 2:
- host->io_word[0] |= buf[off + 1] << 8;
- host->io_pos++;
- case 1:
- host->io_word[0] |= buf[off];
- host->io_pos++;
+ /* Save last 3-1 bytes to buffer, because we can't send them now*/
+ if (length) {
+ memset(host->pio_tmp_buf, 0, 4);
+ memcpy(host->pio_tmp_buf, buf, length);
+ host->pio_tmp_buf_len = length;
}
- off += host->io_pos;
-
- return off;
+ return orig_len - length;
}
+
/* Transfer data between current request and FIFO */
-static int j38ms_transfer_data(struct j38ms_host *host)
+static void j38ms_transfer_pio(struct j38ms_host *host)
{
- unsigned int length;
- unsigned int off;
- unsigned int t_size, p_cnt;
unsigned char *buf;
- struct page *pg;
+ unsigned int len;
unsigned long flags = 0;
- if (host->req->long_data) {
- length = host->req->sg.length - host->block_pos;
- off = host->req->sg.offset + host->block_pos;
- } else {
- length = host->req->data_len - host->block_pos;
- off = 0;
- }
+ if (host->req->long_data)
+ local_irq_save(flags);
- while (length) {
- unsigned int uninitialized_var(p_off);
+ dbg_v(host, "PIO: new transfer");
+ while (1) {
if (host->req->long_data) {
- pg = nth_page(sg_page(&host->req->sg),
- off >> PAGE_SHIFT);
- p_off = offset_in_page(off);
- p_cnt = PAGE_SIZE - p_off;
- p_cnt = min(p_cnt, length);
-
- local_irq_save(flags);
- buf = kmap_atomic(pg, KM_BIO_SRC_IRQ) + p_off;
+ if (!sg_miter_next(&host->pio_sg_iter))
+ break;
+
+ buf = host->pio_sg_iter.addr;
+ len = host->pio_sg_iter.length;
} else {
- buf = host->req->data + host->block_pos;
- p_cnt = host->req->data_len - host->block_pos;
+ buf = host->req->data + host->pio_offset;
+ len = host->req->data_len - host->pio_offset;
+
+ if (!len)
+ break;
}
- if (host->req->data_dir == WRITE)
- t_size = !(host->cmd_flags & REG_DATA)
- ? j38ms_write_fifo_pio(host, buf, p_cnt)
- : j38ms_write_tpc_inline(host, buf, p_cnt);
- else
- t_size = !(host->cmd_flags & REG_DATA)
- ? j38ms_read_fifo_pio(host, buf, p_cnt)
- : j38ms_read_tpc_inline(host, buf, p_cnt);
+ len = host->req->data_dir == WRITE ?
+ j38ms_write_fifo_pio(host, buf, len) :
+ j38ms_read_fifo_pio(host, buf, len);
- if (host->req->long_data) {
- kunmap_atomic(buf - p_off, KM_BIO_SRC_IRQ);
- local_irq_restore(flags);
- }
+ if (host->req->long_data)
+ host->pio_sg_iter.consumed = len;
+ else
+ host->pio_offset += len;
- if (!t_size)
- break;
- host->block_pos += t_size;
- length -= t_size;
- off += t_size;
+ dbg(host, "PIO: transfered %d bytes", len);
+ if (!len)
+ goto exit;
}
- if (!length && host->req->data_dir == WRITE) {
- if (host->cmd_flags & REG_DATA) {
- writel(host->io_word[0], host->addr + TPC_P0);
- writel(host->io_word[1], host->addr + TPC_P1);
- } else if (host->io_pos) {
- writel(host->io_word[0], host->addr + DATA);
- }
+ /* Write last non-complete dword of the data */
+ if (host->req->data_dir == WRITE && host->pio_tmp_buf_len) {
+ if (!j38ms_write_fifo_dword_pio(host,
+ *(u32 *)host->pio_tmp_buf))
+ host->pio_tmp_buf_len = 0;
+ }
+exit:
+ if (host->req->long_data) {
+ sg_miter_stop(&host->pio_sg_iter);
+ local_irq_restore(flags);
}
-
- return length;
}
/* Read short TPC data (up to 8 bytes) via 2 special registers*/
-static unsigned int j38ms_read_tpc_inline(struct j38ms_host *host,
- unsigned char *buf,
- unsigned int length)
+static void j38ms_read_tpc_inline(struct j38ms_host *host)
{
- unsigned int off = 0;
-
- while (host->io_pos > 4 && length) {
- buf[off++] = host->io_word[0] & 0xff;
- host->io_word[0] >>= 8;
- length--;
- host->io_pos--;
- }
-
- if (!length)
- return off;
-
- while (host->io_pos && length) {
- buf[off++] = host->io_word[1] & 0xff;
- host->io_word[1] >>= 8;
- length--;
- host->io_pos--;
- }
-
- return off;
+ *(u32 *)(host->req->data + 0) = j38ms_read_reg_raw(host, TPC_P0);
+ *(u32 *)(host->req->data + 4) = j38ms_read_reg_raw(host, TPC_P1);
}
/* Write short TPC data (up to 8 bytes) through 2 special registers */
-static unsigned int j38ms_write_tpc_inline(struct j38ms_host *host,
- unsigned char *buf,
- unsigned int length)
+static void j38ms_write_tpc_inline(struct j38ms_host *host)
{
- unsigned int off = 0;
-
- while (host->io_pos < 4 && length) {
- host->io_word[0] &= ~(0xff << (host->io_pos * 8));
- host->io_word[0] |= buf[off++] << (host->io_pos * 8);
- host->io_pos++;
- length--;
- }
-
- if (!length)
- return off;
-
- while (host->io_pos < 8 && length) {
- host->io_word[1] &= ~(0xff << (host->io_pos * 8));
- host->io_word[1] |= buf[off++] << (host->io_pos * 8);
- host->io_pos++;
- length--;
- }
-
- return off;
+ j38ms_write_reg_raw(host, TPC_P0, *(u32 *)(host->req->data + 0));
+ j38ms_write_reg_raw(host, TPC_P1, *(u32 *)(host->req->data + 4));
}
/*
@@ -344,10 +271,6 @@ static int j38ms_execute_tpc(struct memstick_host *msh)
dev_dbg(&msh->dev, "hstatus %08x\n", readl(host->addr + STATUS));
host->cmd_flags = 0;
- host->block_pos = 0;
- host->io_pos = 0;
- host->io_word[0] = 0;
- host->io_word[1] = 0;
cmd = host->req->tpc << 16;
cmd |= TPC_DATA_SEL;
@@ -407,11 +330,8 @@ static int j38ms_execute_tpc(struct memstick_host *msh)
host->cmd_flags |= REG_DATA;
cmd |= data_len & 0xf;
- if (host->req->data_dir == WRITE) {
- j38ms_transfer_data(host);
- writel(host->io_word[0], host->addr + TPC_P0);
- writel(host->io_word[1], host->addr + TPC_P1);
- }
+ if (host->req->data_dir == WRITE)
+ j38ms_write_tpc_inline(host);
}
mod_timer(&host->timer, jiffies + host->timeout_jiffies);
@@ -504,10 +424,10 @@ static irqreturn_t j38ms_isr(int irq, void *dev_id)
} else {
if (irq_status & (INT_STATUS_FIFO_RRDY
| INT_STATUS_FIFO_WRDY))
- j38ms_transfer_data(host);
+ j38ms_transfer_pio(host);
if (irq_status & INT_STATUS_EOTRAN) {
- j38ms_transfer_data(host);
+ j38ms_transfer_pio(host);
host->cmd_flags |= FIFO_READY;
}
}
@@ -515,17 +435,8 @@ static irqreturn_t j38ms_isr(int irq, void *dev_id)
if (irq_status & INT_STATUS_EOTPC) {
host->cmd_flags |= CMD_READY;
if (host->cmd_flags & REG_DATA) {
- if (host->req->data_dir == READ) {
- host->io_word[0]
- = readl(host->addr
- + TPC_P0);
- host->io_word[1]
- = readl(host->addr
- + TPC_P1);
- host->io_pos = 8;
-
- j38ms_transfer_data(host);
- }
+ if (host->req->data_dir == READ)
+ j38ms_read_tpc_inline(host);
host->cmd_flags |= FIFO_READY;
}
}
diff --git a/drivers/memstick/host/jmb38x_ms.h b/drivers/memstick/host/jmb38x_ms.h
index 35b8bca..d7dffb6 100644
--- a/drivers/memstick/host/jmb38x_ms.h
+++ b/drivers/memstick/host/jmb38x_ms.h
@@ -151,13 +151,16 @@ struct j38ms_host {
int id;
char host_id[32];
int irq;
- unsigned int block_pos;
unsigned long timeout_jiffies;
struct timer_list timer;
struct memstick_request *req;
unsigned char cmd_flags;
- unsigned char io_pos;
- unsigned int io_word[2];
+
+ /* PIO state */
+ struct sg_mapping_iter pio_sg_iter;
+ unsigned char pio_offset;
+ unsigned char pio_tmp_buf[4];
+ unsigned int pio_tmp_buf_len;
};
struct j38ms {
@@ -187,11 +190,3 @@ enum {
#define dbg(host, format, ...) __dbg(host, 1, format, ## __VA_ARGS__)
#define dbg_v(host, format, ...) __dbg(host, 2, format, ## __VA_ARGS__)
#define dbg_reg(host, format, ...) __dbg(host, 3, format, ## __VA_ARGS__)
-
-static unsigned int j38ms_read_tpc_inline(struct j38ms_host *host,
- unsigned char *buf,
- unsigned int length);
-
-static unsigned int j38ms_write_tpc_inline(struct j38ms_host *host,
- unsigned char *buf,
- unsigned int length);
--
1.7.1
next prev parent reply other threads:[~2010-10-22 23:57 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 ` Maxim Levitsky [this message]
2010-10-25 16:05 ` [PATCH 20/29] memstick: jmb38x_ms: rework PIO 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-21-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