* [FWIW:-)] comparing bonnie++ output
From: Guennadi Liakhovetski @ 2012-12-12 15:40 UTC (permalink / raw)
To: linux-sh
[-- Attachment #1: Type: TEXT/PLAIN, Size: 952 bytes --]
Hi all
I've been asked to prepare and publish some simple scripts / programs to
measure block device performance with a possibility to compare results.
There are a lot of programs available to benchmark block IO, but comparing
results of multiple runs is not always easy.
The expected use is, that you run the attached bash script bonnie_do.sh
several times in each configuration, that you want to benchmark. For
example, if a performance regression is suspected between kernel versions
X and Y, you collect output of this script in two log files X.log and
Y.log.
Then you use the attached bonnie_diff.c to compare the two log files. The
program calculates averages of each of several parameters, that I chose to
compare in each file. Then it compares calculated averages and prints out
absolute and percentual diffs.
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
[-- Attachment #2: Type: TEXT/x-csrc, Size: 1561 bytes --]
/*
* (C) 2012 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
* License: Public domain
*
* This program can be used to compare logfiles, produced by bonnie_do.sh
*
* Running:
* ./bonnie_diff <logfile1> <logfile2>
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
static const int index[] = {3, 5, 7, 9, 11, 13};
#define N (sizeof(index) / sizeof(index[0]))
static const char *name[] = {
"Character Output",
"Block Output",
"Rewrite",
"Character Input",
"Block Input",
"Random Seek",
};
static void avg(FILE *fd, float *val)
{
int i, j;
for (i = 0; i < N; i++)
val[i] = 0.;
for (j = 0; ; j++) {
float v[N];
int ret = fscanf(fd, "%*s %*s %f %*f %f %*f %f %*f %f %*f %f %*f %f %*f",
v, v + 1, v + 2, v + 3, v + 4, v + 5);
if (ret < 6 || ret == EOF)
break;
for (i = 0; i < N; i++)
val[i] += v[i];
}
if (!j)
return;
for (i = 0; i < N; i++)
val[i] /= j;
}
int main(int argc, char *argv[])
{
FILE *fd1, *fd2;
int i;
float val1[N], val2[N];
if (argc != 3) {
errno = -EINVAL;
return 1;
}
fd1 = fopen(argv[1], "r");
if (!fd1)
return 1;
fd2 = fopen(argv[2], "r");
if (!fd2)
return 1;
avg(fd1, val1);
avg(fd2, val2);
for (i = 0; i < N; i++) {
float delta, pdelta;
char *s = "+";
delta = val2[i] - val1[i];
if (delta < 0)
s = "";
pdelta = delta * 100 / val1[i];
printf("%s: %s%f (%s%f%%)\n", name[i], s, delta, s, pdelta);
}
return 0;
}
[-- Attachment #3: Type: APPLICATION/x-sh, Size: 1344 bytes --]
^ permalink raw reply
* [PATCH] sh: enable DMA for MMCIF on ecovec
From: Guennadi Liakhovetski @ 2012-12-12 14:52 UTC (permalink / raw)
To: linux-sh
MMCIF on SH7724 can use DMA for I/O. Enable it on ecovec.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
arch/sh/boards/mach-ecovec24/setup.c | 3 +++
arch/sh/include/cpu-sh4/cpu/sh7724.h | 2 ++
arch/sh/kernel/cpu/sh4a/setup-sh7724.c | 10 ++++++++++
3 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 64559e8a..57c30e8 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -1031,12 +1031,15 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = {
MMC_CAP_8_BIT_DATA |
MMC_CAP_NEEDS_POLL,
.ocr = MMC_VDD_32_33 | MMC_VDD_33_34,
+ .slave_id_tx = SHDMA_SLAVE_MMCIF_TX,
+ .slave_id_rx = SHDMA_SLAVE_MMCIF_RX,
};
static struct platform_device sh_mmcif_device = {
.name = "sh_mmcif",
.id = 0,
.dev = {
+ .coherent_dma_mask = 0xffffffff,
.platform_data = &sh_mmcif_plat,
},
.num_resources = ARRAY_SIZE(sh_mmcif_resources),
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7724.h b/arch/sh/include/cpu-sh4/cpu/sh7724.h
index 38859f9..2e38361 100644
--- a/arch/sh/include/cpu-sh4/cpu/sh7724.h
+++ b/arch/sh/include/cpu-sh4/cpu/sh7724.h
@@ -309,6 +309,8 @@ enum {
SHDMA_SLAVE_SDHI0_RX,
SHDMA_SLAVE_SDHI1_TX,
SHDMA_SLAVE_SDHI1_RX,
+ SHDMA_SLAVE_MMCIF_TX,
+ SHDMA_SLAVE_MMCIF_RX,
};
extern struct clk sh7724_fsimcka_clk;
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index 26b74c2..011c3c5 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -153,6 +153,16 @@ static const struct sh_dmae_slave_config sh7724_dmae_slaves[] = {
.addr = 0x04cf0030,
.chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xca,
+ }, {
+ .slave_id = SHDMA_SLAVE_MMCIF_TX,
+ .addr = 0xa4ca0034,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xcd,
+ }, {
+ .slave_id = SHDMA_SLAVE_MMCIF_RX,
+ .addr = 0xa4ca0034,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xce,
},
};
--
1.7.2.5
^ permalink raw reply related
* [PATCH/RFC] mmc: sh-mmcif: simplify IRQ processing
From: Guennadi Liakhovetski @ 2012-12-12 14:45 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-sh, Magnus Damm, Chris Ball
The classical way to process IRQs is read out the status, ack all triggered
IRQs, possibly mask them, then process them. Follow this simple procesure
instead of the current complex custom algorithm.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
Hi Chris
Attention: this patch is __NOT__ for 3.8, please, let it simmer in -next
until 3.9. It modifies the driver's interrupt handling significantly, so,
we want to have it tested over a longer period.
Thanks
Guennadi
drivers/mmc/host/sh_mmcif.c | 65 ++++++++++++------------------------------
1 files changed, 19 insertions(+), 46 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 90a9255..bbccc12 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -128,6 +128,10 @@
INT_CCSTO | INT_CRCSTO | INT_WDATTO | \
INT_RDATTO | INT_RBSYTO | INT_RSPTO)
+#define INT_ALL (INT_RBSYE | INT_CRSPE | INT_BUFREN | \
+ INT_BUFWEN | INT_CMD12DRE | INT_BUFRE | \
+ INT_DTRANE | INT_CMD12RBE | INT_CMD12CRE)
+
/* CE_INT_MASK */
#define MASK_ALL 0x00000000
#define MASK_MCCSDE (1 << 29)
@@ -159,6 +163,11 @@
MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | \
MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO)
+#define MASK_CLEAN (INT_ERR_STS | MASK_MRBSYE | MASK_MCRSPE | \
+ MASK_MBUFREN | MASK_MBUFWEN | \
+ MASK_MCMD12DRE | MASK_MBUFRE | MASK_MDTRANE | \
+ MASK_MCMD12RBE | MASK_MCMD12CRE)
+
/* CE_HOST_STS1 */
#define STS1_CMDSEQ (1 << 31)
@@ -1201,58 +1210,22 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
{
struct sh_mmcif_host *host = dev_id;
u32 state;
- int err = 0;
state = sh_mmcif_readl(host->addr, MMCIF_CE_INT);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
+ sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state & MASK_CLEAN);
- if (state & INT_ERR_STS) {
- /* error interrupts - process first */
- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
- err = 1;
- } else if (state & INT_RBSYE) {
- sh_mmcif_writel(host->addr, MMCIF_CE_INT,
- ~(INT_RBSYE | INT_CRSPE));
- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE);
- } else if (state & INT_CRSPE) {
- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_CRSPE);
- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCRSPE);
- } else if (state & INT_BUFREN) {
- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFREN);
- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
- } else if (state & INT_BUFWEN) {
- sh_mmcif_writel(host->addr, MMCIF_CE_INT,
- ~(INT_BUFWEN | INT_DTRANE | INT_CMD12DRE |
- INT_CMD12RBE | INT_CMD12CRE));
- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
- } else if (state & INT_CMD12DRE) {
- sh_mmcif_writel(host->addr, MMCIF_CE_INT,
- ~(INT_CMD12DRE | INT_CMD12RBE |
- INT_CMD12CRE | INT_BUFRE));
- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE);
- } else if (state & INT_BUFRE) {
- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFRE);
- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE);
- } else if (state & INT_DTRANE) {
- sh_mmcif_writel(host->addr, MMCIF_CE_INT,
- ~(INT_CMD12DRE | INT_CMD12RBE |
- INT_CMD12CRE | INT_DTRANE));
- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE);
- } else if (state & INT_CMD12RBE) {
- sh_mmcif_writel(host->addr, MMCIF_CE_INT,
- ~(INT_CMD12RBE | INT_CMD12CRE));
- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE);
- } else {
- dev_dbg(&host->pd->dev, "Unsupported interrupt: 0x%x\n", state);
- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
- sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
- err = 1;
- }
- if (err) {
+ if (state & ~MASK_CLEAN)
+ dev_dbg(&host->pd->dev, "IRQ state = 0x%08x incompletely cleared\n",
+ state);
+
+ if (state & INT_ERR_STS || state & ~INT_ALL) {
host->sd_error = true;
- dev_dbg(&host->pd->dev, "int err state = %08x\n", state);
+ dev_dbg(&host->pd->dev, "int err state = 0x%08x\n", state);
}
if (state & ~(INT_CMD12RBE | INT_CMD12CRE)) {
+ if (!host->mrq)
+ dev_dbg(&host->pd->dev, "NULL IRQ state = 0x%08x\n", state);
if (!host->dma_active)
return IRQ_WAKE_THREAD;
else if (host->sd_error)
--
1.7.2.5
^ permalink raw reply related
* [PATCH 14/14] mmc: sh-mmcif: report all errors
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc
Cc: linux-sh, Magnus Damm, Chris Ball, Teppei Kamijou,
Shinya Kuribayashi
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
From: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
Make error reporting in the driver more verbose. This patch is based on
an earlier work by Teppei Kamijou, but we try to not add any new error
messages to the log in the normal case to avoid confusing the user, and
also add a few more dev_dbg() calls.
Signed-off-by: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
[g.liakhovetski@gmx.de: avoid producing new errors in normal case]
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 31 +++++++++++++++++++++++--------
1 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 36eee8d..7abf009 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -514,13 +514,16 @@ static int sh_mmcif_error_manage(struct sh_mmcif_host *host)
}
if (state2 & STS2_CRC_ERR) {
- dev_dbg(&host->pd->dev, ": CRC error\n");
+ dev_err(&host->pd->dev, " CRC error: state %u, wait %u\n",
+ host->state, host->wait_for);
ret = -EIO;
} else if (state2 & STS2_TIMEOUT_ERR) {
- dev_dbg(&host->pd->dev, ": Timeout\n");
+ dev_err(&host->pd->dev, " Timeout: state %u, wait %u\n",
+ host->state, host->wait_for);
ret = -ETIMEDOUT;
} else {
- dev_dbg(&host->pd->dev, ": End/Index error\n");
+ dev_dbg(&host->pd->dev, " End/Index error: state %u, wait %u\n",
+ host->state, host->wait_for);
ret = -EIO;
}
return ret;
@@ -566,6 +569,7 @@ static bool sh_mmcif_read_block(struct sh_mmcif_host *host)
if (host->sd_error) {
data->error = sh_mmcif_error_manage(host);
+ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error);
return false;
}
@@ -606,6 +610,7 @@ static bool sh_mmcif_mread_block(struct sh_mmcif_host *host)
if (host->sd_error) {
data->error = sh_mmcif_error_manage(host);
+ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error);
return false;
}
@@ -642,6 +647,7 @@ static bool sh_mmcif_write_block(struct sh_mmcif_host *host)
if (host->sd_error) {
data->error = sh_mmcif_error_manage(host);
+ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error);
return false;
}
@@ -682,6 +688,7 @@ static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host)
if (host->sd_error) {
data->error = sh_mmcif_error_manage(host);
+ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, data->error);
return false;
}
@@ -823,7 +830,7 @@ static int sh_mmcif_data_trans(struct sh_mmcif_host *host,
sh_mmcif_single_read(host, mrq);
return 0;
default:
- dev_err(&host->pd->dev, "UNSUPPORTED CMD = d'%08d\n", opc);
+ dev_err(&host->pd->dev, "Unsupported CMD%d\n", opc);
return -EINVAL;
}
}
@@ -894,6 +901,7 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
spin_lock_irqsave(&host->lock, flags);
if (host->state != STATE_IDLE) {
+ dev_dbg(&host->pd->dev, "%s() rejected, state %u\n", __func__, host->state);
spin_unlock_irqrestore(&host->lock, flags);
mrq->cmd->error = -EAGAIN;
mmc_request_done(mmc, mrq);
@@ -957,6 +965,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
spin_lock_irqsave(&host->lock, flags);
if (host->state != STATE_IDLE) {
+ dev_dbg(&host->pd->dev, "%s() rejected, state %u\n", __func__, host->state);
spin_unlock_irqrestore(&host->lock, flags);
return;
}
@@ -1042,10 +1051,10 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
break;
default:
cmd->error = sh_mmcif_error_manage(host);
- dev_dbg(&host->pd->dev, "Cmd(d'%d) error %d\n",
- cmd->opcode, cmd->error);
break;
}
+ dev_dbg(&host->pd->dev, "CMD%d error %d\n",
+ cmd->opcode, cmd->error);
host->sd_error = false;
return false;
}
@@ -1097,8 +1106,11 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
/* Woken up by an error IRQ: abort DMA */
data->error = sh_mmcif_error_manage(host);
} else if (!time) {
+ dev_err(host->mmc->parent, "DMA timeout!\n");
data->error = -ETIMEDOUT;
} else if (time < 0) {
+ dev_err(host->mmc->parent,
+ "wait_for_completion_...() error %ld!\n", time);
data->error = time;
}
sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
@@ -1167,6 +1179,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
case MMCIF_WAIT_FOR_STOP:
if (host->sd_error) {
mrq->stop->error = sh_mmcif_error_manage(host);
+ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, mrq->stop->error);
break;
}
sh_mmcif_get_cmd12response(host, mrq->stop);
@@ -1174,8 +1187,10 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
break;
case MMCIF_WAIT_FOR_READ_END:
case MMCIF_WAIT_FOR_WRITE_END:
- if (host->sd_error)
+ if (host->sd_error) {
mrq->data->error = sh_mmcif_error_manage(host);
+ dev_dbg(&host->pd->dev, "%s(): %d\n", __func__, mrq->data->error);
+ }
break;
default:
BUG();
@@ -1292,7 +1307,7 @@ static void mmcif_timeout_work(struct work_struct *work)
/* Don't run after mmc_remove_host() */
return;
- dev_dbg(&host->pd->dev, "Timeout waiting for %u, opcode %u\n",
+ dev_err(&host->pd->dev, "Timeout waiting for %u on CMD%u\n",
host->wait_for, mrq->cmd->opcode);
spin_lock_irqsave(&host->lock, flags);
--
1.7.2.5
^ permalink raw reply related
* [PATCH 13/14] mmc: sh-mmcif: fix I/O errors
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-sh, Magnus Damm, Chris Ball
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
The INT_BUFWEN IRQ often arrives with other bits set too. If they are not
cleared, an additional IRQ can be triggered, sometimes also after the MMC
request has already been completed. This leads to block I/O errors. Earlier
Teppei Kamijou also observed these additional interrupts and proposed to
explicitly wait for them. This patch chooses an alternative approach of
clearing all active bits immediately, when processing the main interrupt.
Reported-by: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 1dd7fc0..36eee8d 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -1238,7 +1238,9 @@ static irqreturn_t sh_mmcif_intr(int irq, void *dev_id)
sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFREN);
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
} else if (state & INT_BUFWEN) {
- sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~INT_BUFWEN);
+ sh_mmcif_writel(host->addr, MMCIF_CE_INT,
+ ~(INT_BUFWEN | INT_DTRANE | INT_CMD12DRE |
+ INT_CMD12RBE | INT_CMD12CRE));
sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
} else if (state & INT_CMD12DRE) {
sh_mmcif_writel(host->addr, MMCIF_CE_INT,
--
1.7.2.5
^ permalink raw reply related
* [PATCH 12/14] mmc: sh-mmcif: reset DMA completion immediately before starting DMA
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-sh, Magnus Damm, Chris Ball
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
DMA completion can be signalled from the DMA callback and from the error
handler. If both are called, the completion struct can enter an
inconsistent state. To prevent this move completion initialisation
immediately before activating DMA.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 03493e4..1dd7fc0 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -419,8 +419,6 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
if (ret < 0)
goto ecfgrx;
- init_completion(&host->dma_complete);
-
return;
ecfgrx:
@@ -1061,6 +1059,12 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
if (!data)
return false;
+ /*
+ * Completion can be signalled from DMA callback and error, so, have to
+ * reset here, before setting .dma_active
+ */
+ init_completion(&host->dma_complete);
+
if (data->flags & MMC_DATA_READ) {
if (host->chan_rx)
sh_mmcif_start_dma_rx(host);
--
1.7.2.5
^ permalink raw reply related
* [PATCH 11/14] mmc: sh-mmcif: reset error code for any opcode
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-sh, Magnus Damm, Chris Ball
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
If a command execution has produced an error, it has to be reset as a part
of the error handling.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 96ab2e1..03493e4 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -1041,7 +1041,6 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
case MMC_SELECT_CARD:
case MMC_APP_CMD:
cmd->error = -ETIMEDOUT;
- host->sd_error = false;
break;
default:
cmd->error = sh_mmcif_error_manage(host);
@@ -1049,6 +1048,7 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
cmd->opcode, cmd->error);
break;
}
+ host->sd_error = false;
return false;
}
if (!(cmd->flags & MMC_RSP_PRESENT)) {
--
1.7.2.5
^ permalink raw reply related
* [PATCH 10/14] mmc: sh-mmcif: fix a race, causing an Oops on SMP
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-sh, Magnus Damm, Chris Ball
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
Oopses have been observed on SMP in the sh-mmcif IRQ thread, when the two
IRQ threads run simultaneously on two CPUs. Also take care to guard the
timeout work and the DMA completion callback from possible NULL-pointer
dereferences and races.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 39 ++++++++++++++++++++++++++++++++++++---
1 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 1a7c602..96ab2e1 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -56,6 +56,7 @@
#include <linux/mmc/sh_mmcif.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/mod_devicetable.h>
+#include <linux/mutex.h>
#include <linux/pagemap.h>
#include <linux/platform_device.h>
#include <linux/pm_qos.h>
@@ -196,6 +197,7 @@ enum mmcif_state {
STATE_IDLE,
STATE_REQUEST,
STATE_IOS,
+ STATE_TIMEOUT,
};
enum mmcif_wait_for {
@@ -232,6 +234,7 @@ struct sh_mmcif_host {
int sg_blkidx;
bool power;
bool card_present;
+ struct mutex thread_lock;
/* DMA support */
struct dma_chan *chan_rx;
@@ -255,11 +258,11 @@ static inline void sh_mmcif_bitclr(struct sh_mmcif_host *host,
static void mmcif_dma_complete(void *arg)
{
struct sh_mmcif_host *host = arg;
- struct mmc_data *data = host->mrq->data;
+ struct mmc_request *mrq = host->mrq;
dev_dbg(&host->pd->dev, "Command completed\n");
- if (WARN(!data, "%s: NULL data in DMA completion!\n",
+ if (WARN(!mrq || !mrq->data, "%s: NULL data in DMA completion!\n",
dev_name(&host->pd->dev)))
return;
@@ -1113,11 +1116,21 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
{
struct sh_mmcif_host *host = dev_id;
- struct mmc_request *mrq = host->mrq;
+ struct mmc_request *mrq;
bool wait = false;
cancel_delayed_work_sync(&host->timeout_work);
+ mutex_lock(&host->thread_lock);
+
+ mrq = host->mrq;
+ if (!mrq) {
+ dev_dbg(&host->pd->dev, "IRQ thread state %u, wait %u: NULL mrq!\n",
+ host->state, host->wait_for);
+ mutex_unlock(&host->thread_lock);
+ return IRQ_HANDLED;
+ }
+
/*
* All handlers return true, if processing continues, and false, if the
* request has to be completed - successfully or not
@@ -1125,6 +1138,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
switch (host->wait_for) {
case MMCIF_WAIT_FOR_REQUEST:
/* We're too late, the timeout has already kicked in */
+ mutex_unlock(&host->thread_lock);
return IRQ_HANDLED;
case MMCIF_WAIT_FOR_CMD:
/* Wait for data? */
@@ -1166,6 +1180,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
if (wait) {
schedule_delayed_work(&host->timeout_work, host->timeout);
/* Wait for more data */
+ mutex_unlock(&host->thread_lock);
return IRQ_HANDLED;
}
@@ -1179,6 +1194,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
sh_mmcif_stop_cmd(host, mrq);
if (!mrq->stop->error) {
schedule_delayed_work(&host->timeout_work, host->timeout);
+ mutex_unlock(&host->thread_lock);
return IRQ_HANDLED;
}
}
@@ -1189,6 +1205,8 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
host->mrq = NULL;
mmc_request_done(host->mmc, mrq);
+ mutex_unlock(&host->thread_lock);
+
return IRQ_HANDLED;
}
@@ -1262,11 +1280,24 @@ static void mmcif_timeout_work(struct work_struct *work)
struct delayed_work *d = container_of(work, struct delayed_work, work);
struct sh_mmcif_host *host = container_of(d, struct sh_mmcif_host, timeout_work);
struct mmc_request *mrq = host->mrq;
+ unsigned long flags;
if (host->dying)
/* Don't run after mmc_remove_host() */
return;
+ dev_dbg(&host->pd->dev, "Timeout waiting for %u, opcode %u\n",
+ host->wait_for, mrq->cmd->opcode);
+
+ spin_lock_irqsave(&host->lock, flags);
+ if (host->state = STATE_IDLE) {
+ spin_unlock_irqrestore(&host->lock, flags);
+ return;
+ }
+
+ host->state = STATE_TIMEOUT;
+ spin_unlock_irqrestore(&host->lock, flags);
+
/*
* Handle races with cancel_delayed_work(), unless
* cancel_delayed_work_sync() is used
@@ -1410,6 +1441,8 @@ static int sh_mmcif_probe(struct platform_device *pdev)
goto erqcd;
}
+ mutex_init(&host->thread_lock);
+
clk_disable(host->hclk);
ret = mmc_add_host(mmc);
if (ret < 0)
--
1.7.2.5
^ permalink raw reply related
* [PATCH 09/14] mmc: sh-mmcif: (cosmetic) simplify boolean return blocks
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-sh, Magnus Damm, Chris Ball
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
Use "return condition" instead of "if (condition) return true; return false"
in functions, returning bool.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 9 ++-------
1 files changed, 2 insertions(+), 7 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index d8d65c0..1a7c602 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -542,10 +542,7 @@ static bool sh_mmcif_next_block(struct sh_mmcif_host *host, u32 *p)
host->pio_ptr = p;
}
- if (host->sg_idx = data->sg_len)
- return false;
-
- return true;
+ return host->sg_idx != data->sg_len;
}
static void sh_mmcif_single_read(struct sh_mmcif_host *host,
@@ -1071,9 +1068,7 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
if (!host->dma_active) {
data->error = sh_mmcif_data_trans(host, host->mrq, cmd->opcode);
- if (!data->error)
- return true;
- return false;
+ return !data->error;
}
/* Running in the IRQ thread, can sleep */
--
1.7.2.5
^ permalink raw reply related
* [PATCH 08/14] mmc: sh-mmcif: Terminate DMA transactions when detecting timeout or error
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc
Cc: linux-sh, Magnus Damm, Chris Ball, Teppei Kamijou,
Shinya Kuribayashi
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
From: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
If a DMA transaction fails, terminate all outstanding DMA transfers and
unmap buffers.
Signed-off-by: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
[g.liakhovetski@gmx.de: forward-port, add dma_unmap_sg() in error cases]
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 31 +++++++++++++++++--------------
1 files changed, 17 insertions(+), 14 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index ac4c3c3..d8d65c0 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -263,15 +263,6 @@ static void mmcif_dma_complete(void *arg)
dev_name(&host->pd->dev)))
return;
- if (data->flags & MMC_DATA_READ)
- dma_unmap_sg(host->chan_rx->device->dev,
- data->sg, data->sg_len,
- DMA_FROM_DEVICE);
- else
- dma_unmap_sg(host->chan_tx->device->dev,
- data->sg, data->sg_len,
- DMA_TO_DEVICE);
-
complete(&host->dma_complete);
}
@@ -1088,14 +1079,20 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
/* Running in the IRQ thread, can sleep */
time = wait_for_completion_interruptible_timeout(&host->dma_complete,
host->timeout);
+
+ if (data->flags & MMC_DATA_READ)
+ dma_unmap_sg(host->chan_rx->device->dev,
+ data->sg, data->sg_len,
+ DMA_FROM_DEVICE);
+ else
+ dma_unmap_sg(host->chan_tx->device->dev,
+ data->sg, data->sg_len,
+ DMA_TO_DEVICE);
+
if (host->sd_error) {
dev_err(host->mmc->parent,
"Error IRQ while waiting for DMA completion!\n");
/* Woken up by an error IRQ: abort DMA */
- if (data->flags & MMC_DATA_READ)
- dmaengine_terminate_all(host->chan_rx);
- else
- dmaengine_terminate_all(host->chan_tx);
data->error = sh_mmcif_error_manage(host);
} else if (!time) {
data->error = -ETIMEDOUT;
@@ -1106,8 +1103,14 @@ static bool sh_mmcif_end_cmd(struct sh_mmcif_host *host)
BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
host->dma_active = false;
- if (data->error)
+ if (data->error) {
data->bytes_xfered = 0;
+ /* Abort DMA */
+ if (data->flags & MMC_DATA_READ)
+ dmaengine_terminate_all(host->chan_rx);
+ else
+ dmaengine_terminate_all(host->chan_tx);
+ }
return false;
}
--
1.7.2.5
^ permalink raw reply related
* [PATCH 07/14] mmc: sh-mmcif: fix missing and consolidate IO completion timeouts
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-sh, Magnus Damm, Chris Ball
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
Read block and write block operations are currently missing completion
timeouts. Add missing timeouts and consolidate them at one location.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 45 +++++++++++++++++++++----------------------
1 files changed, 22 insertions(+), 23 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 092c415..ac4c3c3 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -564,7 +564,6 @@ static void sh_mmcif_single_read(struct sh_mmcif_host *host,
BLOCK_SIZE_MASK) + 3;
host->wait_for = MMCIF_WAIT_FOR_READ;
- schedule_delayed_work(&host->timeout_work, host->timeout);
/* buf read enable */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
@@ -606,7 +605,7 @@ static void sh_mmcif_multi_read(struct sh_mmcif_host *host,
host->sg_idx = 0;
host->sg_blkidx = 0;
host->pio_ptr = sg_virt(data->sg);
- schedule_delayed_work(&host->timeout_work, host->timeout);
+
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
}
@@ -629,7 +628,6 @@ static bool sh_mmcif_mread_block(struct sh_mmcif_host *host)
if (!sh_mmcif_next_block(host, p))
return false;
- schedule_delayed_work(&host->timeout_work, host->timeout);
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN);
return true;
@@ -642,7 +640,6 @@ static void sh_mmcif_single_write(struct sh_mmcif_host *host,
BLOCK_SIZE_MASK) + 3;
host->wait_for = MMCIF_WAIT_FOR_WRITE;
- schedule_delayed_work(&host->timeout_work, host->timeout);
/* buf write enable */
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
@@ -684,7 +681,7 @@ static void sh_mmcif_multi_write(struct sh_mmcif_host *host,
host->sg_idx = 0;
host->sg_blkidx = 0;
host->pio_ptr = sg_virt(data->sg);
- schedule_delayed_work(&host->timeout_work, host->timeout);
+
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
}
@@ -707,7 +704,6 @@ static bool sh_mmcif_mwrite_block(struct sh_mmcif_host *host)
if (!sh_mmcif_next_block(host, p))
return false;
- schedule_delayed_work(&host->timeout_work, host->timeout);
sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN);
return true;
@@ -900,7 +896,6 @@ static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host,
}
host->wait_for = MMCIF_WAIT_FOR_STOP;
- schedule_delayed_work(&host->timeout_work, host->timeout);
}
static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -1121,6 +1116,7 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
{
struct sh_mmcif_host *host = dev_id;
struct mmc_request *mrq = host->mrq;
+ bool wait = false;
cancel_delayed_work_sync(&host->timeout_work);
@@ -1133,29 +1129,24 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
/* We're too late, the timeout has already kicked in */
return IRQ_HANDLED;
case MMCIF_WAIT_FOR_CMD:
- if (sh_mmcif_end_cmd(host))
- /* Wait for data */
- return IRQ_HANDLED;
+ /* Wait for data? */
+ wait = sh_mmcif_end_cmd(host);
break;
case MMCIF_WAIT_FOR_MREAD:
- if (sh_mmcif_mread_block(host))
- /* Wait for more data */
- return IRQ_HANDLED;
+ /* Wait for more data? */
+ wait = sh_mmcif_mread_block(host);
break;
case MMCIF_WAIT_FOR_READ:
- if (sh_mmcif_read_block(host))
- /* Wait for data end */
- return IRQ_HANDLED;
+ /* Wait for data end? */
+ wait = sh_mmcif_read_block(host);
break;
case MMCIF_WAIT_FOR_MWRITE:
- if (sh_mmcif_mwrite_block(host))
- /* Wait data to write */
- return IRQ_HANDLED;
+ /* Wait data to write? */
+ wait = sh_mmcif_mwrite_block(host);
break;
case MMCIF_WAIT_FOR_WRITE:
- if (sh_mmcif_write_block(host))
- /* Wait for data end */
- return IRQ_HANDLED;
+ /* Wait for data end? */
+ wait = sh_mmcif_write_block(host);
break;
case MMCIF_WAIT_FOR_STOP:
if (host->sd_error) {
@@ -1174,6 +1165,12 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
BUG();
}
+ if (wait) {
+ schedule_delayed_work(&host->timeout_work, host->timeout);
+ /* Wait for more data */
+ return IRQ_HANDLED;
+ }
+
if (host->wait_for != MMCIF_WAIT_FOR_STOP) {
struct mmc_data *data = mrq->data;
if (!mrq->cmd->error && data && !data->error)
@@ -1182,8 +1179,10 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id)
if (mrq->stop && !mrq->cmd->error && (!data || !data->error)) {
sh_mmcif_stop_cmd(host, mrq);
- if (!mrq->stop->error)
+ if (!mrq->stop->error) {
+ schedule_delayed_work(&host->timeout_work, host->timeout);
return IRQ_HANDLED;
+ }
}
}
--
1.7.2.5
^ permalink raw reply related
* [PATCH 06/14] mmc: sh_mmcif: Avoid unnecessary mmc_delay() at mmc_card_sleepawake()
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc
Cc: linux-sh, Magnus Damm, Chris Ball, Teppei Kamijou,
Shinya Kuribayashi
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
From: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
SH/R-Mobile MMCIF host controller can wait while the card signals busy.
Set MMC_CAP_WAIT_WHILE_BUSY to inform an upper layer (core/mmc_ops.c)
not to insert unnecessary mmc_delay().
Signed-off-by: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 1665ae4..092c415 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -758,6 +758,7 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
}
switch (opc) {
/* RBSY */
+ case MMC_SLEEP_AWAKE:
case MMC_SWITCH:
case MMC_STOP_TRANSMISSION:
case MMC_SET_WRITE_PROT:
@@ -851,6 +852,7 @@ static void sh_mmcif_start_cmd(struct sh_mmcif_host *host,
switch (opc) {
/* response busy check */
+ case MMC_SLEEP_AWAKE:
case MMC_SWITCH:
case MMC_STOP_TRANSMISSION:
case MMC_SET_WRITE_PROT:
@@ -1357,7 +1359,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
mmc->ops = &sh_mmcif_ops;
sh_mmcif_init_ocr(host);
- mmc->caps = MMC_CAP_MMC_HIGHSPEED;
+ mmc->caps = MMC_CAP_MMC_HIGHSPEED | MMC_CAP_WAIT_WHILE_BUSY;
if (pd && pd->caps)
mmc->caps |= pd->caps;
mmc->max_segs = 32;
--
1.7.2.5
^ permalink raw reply related
* [PATCH 05/14] mmc: sh_mmcif: Use msecs_to_jiffies() for host->timeout
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc
Cc: linux-sh, Magnus Damm, Chris Ball, Teppei Kamijou,
Shinya Kuribayashi
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
From: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
Timeout period should be properly normalized using msecs_to_jiffies().
Signed-off-by: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 1ec3339..1665ae4 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -1348,7 +1348,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
host = mmc_priv(mmc);
host->mmc = mmc;
host->addr = reg;
- host->timeout = 1000;
+ host->timeout = msecs_to_jiffies(1000);
host->pd = pdev;
--
1.7.2.5
^ permalink raw reply related
* [PATCH 04/14] mmc: sh_mmcif: Add support for eMMC Dual Data Rate
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc
Cc: linux-sh, Magnus Damm, Chris Ball, Teppei Kamijou,
Shinya Kuribayashi
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
From: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
Some MMCIF implementations support the Dual Data Rate. With this patch,
platforms can set the MMC_CAP_UHS_DDR50 capability flag in MMCIF platform
data. This will let the MMC core to actually use the DDR mode.
Signed-off-by: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index d80c294..1ec3339 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -88,6 +88,7 @@
#define CMD_SET_TBIT (1 << 7) /* 1: tran mission bit "Low" */
#define CMD_SET_OPDM (1 << 6) /* 1: open/drain */
#define CMD_SET_CCSH (1 << 5)
+#define CMD_SET_DARS (1 << 2) /* Dual Data Rate */
#define CMD_SET_DATW_1 ((0 << 1) | (0 << 0)) /* 1bit */
#define CMD_SET_DATW_4 ((0 << 1) | (1 << 0)) /* 4bit */
#define CMD_SET_DATW_8 ((1 << 1) | (0 << 0)) /* 8bit */
@@ -216,6 +217,7 @@ struct sh_mmcif_host {
struct clk *hclk;
unsigned int clk;
int bus_width;
+ unsigned char timing;
bool sd_error;
bool dying;
long timeout;
@@ -781,6 +783,17 @@ static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host,
dev_err(&host->pd->dev, "Unsupported bus width.\n");
break;
}
+ switch (host->timing) {
+ case MMC_TIMING_UHS_DDR50:
+ /*
+ * MMC core will only set this timing, if the host
+ * advertises the MMC_CAP_UHS_DDR50 capability. MMCIF
+ * implementations with this capability, e.g. sh73a0,
+ * will have to set it in their platform data.
+ */
+ tmp |= CMD_SET_DARS;
+ break;
+ }
}
/* DWEN */
if (opc = MMC_WRITE_BLOCK || opc = MMC_WRITE_MULTIPLE_BLOCK)
@@ -1002,6 +1015,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
sh_mmcif_clock_control(host, ios->clock);
}
+ host->timing = ios->timing;
host->bus_width = ios->bus_width;
host->state = STATE_IDLE;
}
--
1.7.2.5
^ permalink raw reply related
* [PATCH 03/14] mmc: sh_mmcif: add support for bundled MMCIF IRQs
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-sh, Magnus Damm, Chris Ball, Shinya Kuribayashi
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
From: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
On newer SoCs like R-Mobile U2, MMCIF interrupts are bundled.
Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 25 ++++++++++++++++---------
1 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 8a188fe..d80c294 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -1307,10 +1307,11 @@ static int sh_mmcif_probe(struct platform_device *pdev)
struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
struct resource *res;
void __iomem *reg;
+ const char *name;
irq[0] = platform_get_irq(pdev, 0);
irq[1] = platform_get_irq(pdev, 1);
- if (irq[0] < 0 || irq[1] < 0) {
+ if (irq[0] < 0) {
dev_err(&pdev->dev, "Get irq error\n");
return -ENXIO;
}
@@ -1375,15 +1376,19 @@ static int sh_mmcif_probe(struct platform_device *pdev)
sh_mmcif_sync_reset(host);
sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
- ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
+ name = irq[1] < 0 ? dev_name(&pdev->dev) : "sh_mmc:error";
+ ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, name, host);
if (ret) {
- dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n");
+ dev_err(&pdev->dev, "request_irq error (%s)\n", name);
goto ereqirq0;
}
- ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);
- if (ret) {
- dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
- goto ereqirq1;
+ if (irq[1] >= 0) {
+ ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt,
+ 0, "sh_mmc:int", host);
+ if (ret) {
+ dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
+ goto ereqirq1;
+ }
}
if (pd && pd->use_cd_gpio) {
@@ -1408,7 +1413,8 @@ emmcaddh:
if (pd && pd->use_cd_gpio)
mmc_gpio_free_cd(mmc);
erqcd:
- free_irq(irq[1], host);
+ if (irq[1] >= 0)
+ free_irq(irq[1], host);
ereqirq1:
free_irq(irq[0], host);
ereqirq0:
@@ -1457,7 +1463,8 @@ static int sh_mmcif_remove(struct platform_device *pdev)
irq[1] = platform_get_irq(pdev, 1);
free_irq(irq[0], host);
- free_irq(irq[1], host);
+ if (irq[1] >= 0)
+ free_irq(irq[1], host);
platform_set_drvdata(pdev, NULL);
--
1.7.2.5
^ permalink raw reply related
* [PATCH 02/14] mmc: sh_mmcif: ensure run-time suspend call is processed before suspend
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-sh, Magnus Damm, Chris Ball, Teppei Kamijou
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
From: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
With this post-v2.6.35 change applied:
commit a0a1a5fd4fb15ec61117c759fe9f5c16c53d9e9c
Author: Tejun Heo <tj@kernel.org>
Date: Tue Jun 29 10:07:12 2010 +0200
workqueue: reimplement workqueue freeze using max_active
freeze_workqueues_begin() was introduced and workqueue now gets frozen
before device drivers suspend operations.
We have to ensure that run-time PM suspend operation completes before
system-wide suspend is started.
igned-off-by: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
igned-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 543f6ce..8a188fe 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -982,7 +982,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}
}
if (host->power) {
- pm_runtime_put(&host->pd->dev);
+ pm_runtime_put_sync(&host->pd->dev);
clk_disable(host->hclk);
host->power = false;
if (ios->power_mode = MMC_POWER_OFF)
--
1.7.2.5
^ permalink raw reply related
* [PATCH 01/14] mmc: sh_mmcif: force to fail CMD52 immediately
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc
Cc: linux-sh, Magnus Damm, Chris Ball, Teppei Kamijou,
Shinya Kuribayashi
In-Reply-To: <1355323098-18061-1-git-send-email-g.liakhovetski@gmx.de>
From: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
mmc_rescan() sends CMD52 (SD_IO_RW_DIRECT) to reset SDIO card during
card detection. CMD52 should be ignored by SD/eMMC cards, but we can
also abort it in the driver immediately, since MMCIF doesn't support
SDIO cards anyway.
Signed-off-by: Teppei Kamijou <teppei.kamijou.yb@renesas.com>
Signed-off-by: Shinya Kuribayashi <shinya.kuribayashi.px@renesas.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
drivers/mmc/host/sh_mmcif.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 9a4c151..543f6ce 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -911,6 +911,7 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
if ((mrq->cmd->flags & MMC_CMD_MASK) != MMC_CMD_BCR)
break;
case MMC_APP_CMD:
+ case SD_IO_RW_DIRECT:
host->state = STATE_IDLE;
mrq->cmd->error = -ETIMEDOUT;
mmc_request_done(mmc, mrq);
--
1.7.2.5
^ permalink raw reply related
* [PATCH 00/14] mmc: sh-mmcif: 3.8 fixes and improvements
From: Guennadi Liakhovetski @ 2012-12-12 14:38 UTC (permalink / raw)
To: linux-mmc; +Cc: linux-sh, Magnus Damm, Chris Ball
This patch series fixes several bugs in the sh_mmcif.c driver, that showed
up on SMP with DMA (patches 10, 13), adds new features (3, 4) and adds
multiple further improvements and minor fixes. Even though these bugs
currently exist in the mainline, this patch series is not considered to
be suitable for @stable. Patches are rather experimental and it is better
to test them over a complete development cycle. They also are easier
implemented on top of preparatory cosmetic patches.
Guennadi Liakhovetski (6):
mmc: sh-mmcif: fix missing and consolidate IO completion timeouts
mmc: sh-mmcif: (cosmetic) simplify boolean return blocks
mmc: sh-mmcif: fix a race, causing an Oops on SMP
mmc: sh-mmcif: reset error code for any opcode
mmc: sh-mmcif: reset DMA completion immediately before starting DMA
mmc: sh-mmcif: fix I/O errors
Shinya Kuribayashi (1):
mmc: sh_mmcif: add support for bundled MMCIF IRQs
Teppei Kamijou (7):
mmc: sh_mmcif: force to fail CMD52 immediately
mmc: sh_mmcif: ensure run-time suspend call is processed before
suspend
mmc: sh_mmcif: Add support for eMMC Dual Data Rate
mmc: sh_mmcif: Use msecs_to_jiffies() for host->timeout
mmc: sh_mmcif: Avoid unnecessary mmc_delay() at mmc_card_sleepawake()
mmc: sh-mmcif: Terminate DMA transactions when detecting timeout or
error
mmc: sh-mmcif: report all errors
drivers/mmc/host/sh_mmcif.c | 215 +++++++++++++++++++++++++++++--------------
1 files changed, 145 insertions(+), 70 deletions(-)
--
1.7.2.5
Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
^ permalink raw reply
* Re: [RFC PATCH v2 3/5] ARM: kernel: update cpu_suspend code to use cache LoUIS operations
From: Will Deacon @ 2012-12-12 13:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20121212103338.GB23022@e102568-lin.cambridge.arm.com>
On Wed, Dec 12, 2012 at 10:33:38AM +0000, Lorenzo Pieralisi wrote:
> On Tue, Dec 11, 2012 at 11:27:39PM +0000, Stephen Boyd wrote:
> > On 12/11/12 08:38, Will Deacon wrote:
> > > diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
> > > index cd95664..f58248f 100644
> > > --- a/arch/arm/mm/cache-v7.S
> > > +++ b/arch/arm/mm/cache-v7.S
> > > @@ -44,7 +44,8 @@ ENDPROC(v7_flush_icache_all)
> > > ENTRY(v7_flush_dcache_louis)
> > > dmb @ ensure ordering with previous memory accesses
> > > mrc p15, 1, r0, c0, c0, 1 @ read clidr, r0 = clidr
> > > - ands r3, r0, #0xe00000 @ extract LoUIS from clidr
> > > + ALT_SMP(ands r3, r0, #(7 << 21)) @ extract LoUIS from clidr
> > > + ALT_UP(ands r3, r0, #(7 << 27)) @ extract LoUU from clidr
> > > mov r3, r3, lsr #20 @ r3 = LoUIS * 2
> >
> > You need to fix this mov as well, right?
>
> And after doing that I think the suspend finisher will still have
> to call flush_cache_all() since LoUU = 1 on A8, L2 is not cleaned
> and that's probably what we want if it can be retained.
At some point we probably want to describe the level of flushing required in
the device tree as a property of the CPU node (or something similar). That
would allow us to have *one* function for flushing,
e.g. cpu_suspend_flush_cache which flushes to the appropriate level. Then
we could remove the louis flush from the CPU suspend code and instead make
it the finisher's responsibility to call our flushing function when it's
done, which helps to avoid over/under-flushing the cache.
In the meantime, fixing louis as we've suggested should work.
Back to the case in hand.... Lorenzo just pointed out to me that the
finished in question (sh7372_do_idle_sysc) calls v7_flush_dcache_all, so
the louis stuff should be irrelevant. The problem may actually be that the
finisher disables the L2 cache prior to cleaning/invalidating it, which is
the opposite order to that described by the A8 TRM.
Guennadi -- can you try moving the kernel_flush call before the L2 disable
in sh7372_do_idle_sysc please?
Will
^ permalink raw reply
* [PATCH 4/4 v2] devicetree: Add Renesas SH Mobile MSIOF spi controller binding doc
From: Bastian Hecht @ 2012-12-12 11:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355313289-29769-1-git-send-email-hechtb+renesas@gmail.com>
From: Bastian Hecht <hechtb@gmail.com>
Add binding documentation for Renesas' MSIOF SPI controller.
Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v2:
- renamed property "chip_select" to "num-cs"
- renamed property "tx_fifo_size" to "renesas,tx-fifo-size"
- renamed property "rx_fifo_size" to "renesas,rx-fifo-size"
Documentation/devicetree/bindings/spi/sh-msiof.txt | 12 ++++++++++++
1 file changed, 12 insertions(+)
create mode 100644 Documentation/devicetree/bindings/spi/sh-msiof.txt
diff --git a/Documentation/devicetree/bindings/spi/sh-msiof.txt b/Documentation/devicetree/bindings/spi/sh-msiof.txt
new file mode 100644
index 0000000..e622210
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/sh-msiof.txt
@@ -0,0 +1,12 @@
+Renesas MSIOF spi controller
+
+Required properties:
+- compatible : "renesas,sh-msiof" for SuperH or
+ "renesas,sh-mobile-msiof" for SH Mobile series
+- reg : Offset and length of the register set for the device
+- interrupts : interrupt line used by MSIOF
+
+Optional properties:
+- num-cs : total number of chip-selects
+- renesas,tx-fifo-size : Overrides the default tx fifo size given in words
+- renesas,rx-fifo-size : Overrides the default rx fifo size given in words
--
1.7.9.5
^ permalink raw reply related
* [PATCH 3/4 v2] spi: sh-msiof: Add device tree parsing to driver
From: Bastian Hecht @ 2012-12-12 11:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355313289-29769-1-git-send-email-hechtb+renesas@gmail.com>
From: Bastian Hecht <hechtb@gmail.com>
This adds the capability to retrieve setup data from the device tree
node. The usage of platform data is still available.
Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v2:
- renamed property "chip_select" to "num-cs"
- renamed property "tx_fifo_size" to "renesas,tx-fifo-size"
- renamed property "rx_fifo_size" to "renesas,rx-fifo-size"
drivers/spi/spi-sh-msiof.c | 56 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 55 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index 96358d0..8b40d08 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -20,6 +20,7 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -592,6 +593,37 @@ static u32 sh_msiof_spi_txrx_word(struct spi_device *spi, unsigned nsecs,
return 0;
}
+#ifdef CONFIG_OF
+static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
+{
+ struct sh_msiof_spi_info *info;
+ struct device_node *np = dev->of_node;
+ u32 num_cs = 0;
+
+ info = devm_kzalloc(dev, sizeof(struct sh_msiof_spi_info), GFP_KERNEL);
+ if (!info) {
+ dev_err(dev, "failed to allocate setup data\n");
+ return NULL;
+ }
+
+ /* Parse the MSIOF properties */
+ of_property_read_u32(np, "num-cs", &num_cs);
+ of_property_read_u32(np, "renesas,tx-fifo-size",
+ &info->tx_fifo_override);
+ of_property_read_u32(np, "renesas,rx-fifo-size",
+ &info->rx_fifo_override);
+
+ info->num_chipselect = num_cs;
+
+ return info;
+}
+#else
+static struct sh_msiof_spi_info *sh_msiof_spi_parse_dt(struct device *dev)
+{
+ return NULL;
+}
+#endif
+
static int sh_msiof_spi_probe(struct platform_device *pdev)
{
struct resource *r;
@@ -610,7 +642,17 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
p = spi_master_get_devdata(master);
platform_set_drvdata(pdev, p);
- p->info = pdev->dev.platform_data;
+ if (pdev->dev.of_node)
+ p->info = sh_msiof_spi_parse_dt(&pdev->dev);
+ else
+ p->info = pdev->dev.platform_data;
+
+ if (!p->info) {
+ dev_err(&pdev->dev, "failed to obtain device info\n");
+ ret = -ENXIO;
+ goto err1;
+ }
+
init_completion(&p->done);
p->clk = clk_get(&pdev->dev, NULL);
@@ -715,6 +757,17 @@ static int sh_msiof_spi_runtime_nop(struct device *dev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id sh_msiof_match[] = {
+ { .compatible = "renesas,sh-msiof", },
+ { .compatible = "renesas,sh-mobile-msiof", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sh_msiof_match);
+#else
+#define sh_msiof_match NULL
+#endif
+
static struct dev_pm_ops sh_msiof_spi_dev_pm_ops = {
.runtime_suspend = sh_msiof_spi_runtime_nop,
.runtime_resume = sh_msiof_spi_runtime_nop,
@@ -727,6 +780,7 @@ static struct platform_driver sh_msiof_spi_drv = {
.name = "spi_sh_msiof",
.owner = THIS_MODULE,
.pm = &sh_msiof_spi_dev_pm_ops,
+ .of_match_table = sh_msiof_match,
},
};
module_platform_driver(sh_msiof_spi_drv);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/4 v2] spi: Add SH Mobile series as dependency to MSIOF controller
From: Bastian Hecht @ 2012-12-12 11:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1355313289-29769-1-git-send-email-hechtb+renesas@gmail.com>
From: Bastian Hecht <hechtb@gmail.com>
The MSIOF hardware block is used in the SH Mobile series as well, so we
add it here.
Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v2: no changes
drivers/spi/Kconfig | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 1acae35..d0c0ae6 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -341,10 +341,10 @@ config SPI_SC18IS602
config SPI_SH_MSIOF
tristate "SuperH MSIOF SPI controller"
- depends on SUPERH && HAVE_CLK
+ depends on (SUPERH || ARCH_SHMOBILE) && HAVE_CLK
select SPI_BITBANG
help
- SPI driver for SuperH MSIOF blocks.
+ SPI driver for SuperH and SH Mobile MSIOF blocks.
config SPI_SH
tristate "SuperH SPI controller"
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/4 v2] spi: sh-msiof: Remove unneeded clock name
From: Bastian Hecht @ 2012-12-12 11:54 UTC (permalink / raw)
To: linux-arm-kernel
From: Bastian Hecht <hechtb@gmail.com>
clk_get() no longer needs a character string for associating the right
clock as this is done via the device struct now.
Signed-off-by: Bastian Hecht <hechtb+renesas@gmail.com>
---
v2: no changes
drivers/spi/spi-sh-msiof.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index 1f466bc..96358d0 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -597,7 +597,6 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
struct resource *r;
struct spi_master *master;
struct sh_msiof_spi_priv *p;
- char clk_name[16];
int i;
int ret;
@@ -614,10 +613,9 @@ static int sh_msiof_spi_probe(struct platform_device *pdev)
p->info = pdev->dev.platform_data;
init_completion(&p->done);
- snprintf(clk_name, sizeof(clk_name), "msiof%d", pdev->id);
- p->clk = clk_get(&pdev->dev, clk_name);
+ p->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(p->clk)) {
- dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
+ dev_err(&pdev->dev, "cannot get clock\n");
ret = PTR_ERR(p->clk);
goto err1;
}
--
1.7.9.5
^ permalink raw reply related
* Re: [PATCH 4/4] devicetree: Add Renesas SH Mobile MSIOF spi controller binding doc
From: Bastian Hecht @ 2012-12-12 11:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACxGe6s+1Debq2HoVKWPmZ-75JMGmeJ+qxdxqzVWpsKxoyUowQ@mail.gmail.com>
Hello Grant,
>>> +Renesas MSIOF spi controller
>>> +
>>> +Required properties:
>>> +- compatible : "renesas,sh-msiof" for SuperH or
>>> + "renesas,sh-mobile-msiof" for SH Mobile series
>>> +- reg : Offset and length of the register set for the device
>>> +- interrupts : interrupt line used by MSIOF
>>> +
>>> +Optional properties:
>>> +- chip_select : Chip select, defaults to 0
>>
>> This doesn't make a lot of sense to me. What is this property for? Is
>> there more than one CS? And if there is, shouldn't the SPI driver be
>> able to manipulate more than one?
>
> Oh, wait, from reading the code, is this the number of chip select
> lines? If so, then there is a common property for this. This property
> should be named "num-cs".
Yes, this value is nowhere used in the driver but just forwarded to
the SPI subsystem as the number of chip selects.
>>
>>> +- tx_fifo_size : Overrides the default tx fifo size given in words
>>> +- rx_fifo_size : Overrides the default rx fifo size given in words
>>
>> Nit: property names should use '-' instead of '_' (by convention) and
>> custom properties should be prefixed with the manufacturer prefix to
>> avoid namespace collisions. ie. "renesas,tx-fifo-size.
Ok sure! Thanks for pointing it out.
I'll post v2 in a second.
Thanks,
Bastian
>> g.
>
>
>
> --
> Grant Likely, B.Sc., P.Eng.
> Secret Lab Technologies Ltd.
^ permalink raw reply
* Re: [RFC PATCH v2 3/5] ARM: kernel: update cpu_suspend code to use cache LoUIS operations
From: Lorenzo Pieralisi @ 2012-12-12 10:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50C7C16B.7050106@codeaurora.org>
On Tue, Dec 11, 2012 at 11:27:39PM +0000, Stephen Boyd wrote:
> On 12/11/12 08:38, Will Deacon wrote:
> > diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
> > index cd95664..f58248f 100644
> > --- a/arch/arm/mm/cache-v7.S
> > +++ b/arch/arm/mm/cache-v7.S
> > @@ -44,7 +44,8 @@ ENDPROC(v7_flush_icache_all)
> > ENTRY(v7_flush_dcache_louis)
> > dmb @ ensure ordering with previous memory accesses
> > mrc p15, 1, r0, c0, c0, 1 @ read clidr, r0 = clidr
> > - ands r3, r0, #0xe00000 @ extract LoUIS from clidr
> > + ALT_SMP(ands r3, r0, #(7 << 21)) @ extract LoUIS from clidr
> > + ALT_UP(ands r3, r0, #(7 << 27)) @ extract LoUU from clidr
> > mov r3, r3, lsr #20 @ r3 = LoUIS * 2
>
> You need to fix this mov as well, right?
And after doing that I think the suspend finisher will still have
to call flush_cache_all() since LoUU = 1 on A8, L2 is not cleaned
and that's probably what we want if it can be retained.
What about this (compile tested) ?
Lorenzo
--->8
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index cd95664..036f80f 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -44,8 +44,9 @@ ENDPROC(v7_flush_icache_all)
ENTRY(v7_flush_dcache_louis)
dmb @ ensure ordering with previous memory accesses
mrc p15, 1, r0, c0, c0, 1 @ read clidr, r0 = clidr
- ands r3, r0, #0xe00000 @ extract LoUIS from clidr
- mov r3, r3, lsr #20 @ r3 = LoUIS * 2
+ ALT_SMP(lsr r3, r0, #20) @ r3 = clidr[31:20]
+ ALT_UP(lsr r3, r0, #26) @ r3 = clidr[31:26]
+ ands r3, r3, #0xe @ r3 = LoUIS/LoUU * 2
moveq pc, lr @ return if level = 0
mov r10, #0 @ r10 (starting level) = 0
b flush_levels @ start flushing cache levels
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox