Re: [PATCH v6 00/11] mmc: use nonblock mmc requests to minimize latency

2011-06-28 Thread saeed bishara
On Mon, Jun 27, 2011 at 2:02 PM, Russell King - ARM Linux
li...@arm.linux.org.uk wrote:
 On Mon, Jun 27, 2011 at 01:34:48PM +0300, saeed bishara wrote:
 Russell,
   I'm curious about the correctness of this patch for systems with
 outer cache. shouldn't the dsb be issued before the outer cache
 maintenance?

 Maybe we should do two passes over SG lists then - one for the inner and
 another for the outer cache?

 In effect we could do three passes:

 1. Calculate the total size of the SG list to determine whether full
   cache flush is more efficient.
 2. Flush inner cache
   Then dsb()
 3. Flush outer cache
   Another dsb()

looking at l2x0 cache, it seems to me that it would be possible to do
asynchronous l2 cache maintenance for
range operations, so maybe that can be utilized in order to
parallelism between inner cache and outer cache maintenance,
so the flow can be:
2. Flush sg buffer from inner cache
3. dsb()
4. start Flush outer cache for that buffer
5. Flush next sg buffer from inner cache
6. dsb
7. goto 4.
8. when no more buffers left, wait for outer cache operations

saeed

___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


[PATCH v8 04/12] mmc: mmc_test: add debugfs file to list all tests

2011-06-28 Thread Per Forlin
Add a debugfs file testlist to print all available tests

Signed-off-by: Per Forlin per.for...@linaro.org
---
 drivers/mmc/card/mmc_test.c |   39 ++-
 1 files changed, 38 insertions(+), 1 deletions(-)

diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index 233cdfa..e8508e9 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -2445,6 +2445,32 @@ static const struct file_operations mmc_test_fops_test = 
{
.release= single_release,
 };
 
+static int mtf_testlist_show(struct seq_file *sf, void *data)
+{
+   int i;
+
+   mutex_lock(mmc_test_lock);
+
+   for (i = 0; i  ARRAY_SIZE(mmc_test_cases); i++)
+   seq_printf(sf, %d:\t%s\n, i+1, mmc_test_cases[i].name);
+
+   mutex_unlock(mmc_test_lock);
+
+   return 0;
+}
+
+static int mtf_testlist_open(struct inode *inode, struct file *file)
+{
+   return single_open(file, mtf_testlist_show, inode-i_private);
+}
+
+static const struct file_operations mmc_test_fops_testlist = {
+   .open   = mtf_testlist_open,
+   .read   = seq_read,
+   .llseek = seq_lseek,
+   .release= single_release,
+};
+
 static void mmc_test_free_file_test(struct mmc_card *card)
 {
struct mmc_test_dbgfs_file *df, *dfs;
@@ -2476,7 +2502,18 @@ static int mmc_test_register_file_test(struct mmc_card 
*card)
 
if (IS_ERR_OR_NULL(file)) {
dev_err(card-dev,
-   Can't create file. Perhaps debugfs is disabled.\n);
+   Can't create test. Perhaps debugfs is disabled.\n);
+   ret = -ENODEV;
+   goto err;
+   }
+
+   if (card-debugfs_root)
+   file = debugfs_create_file(testlist, S_IRUGO,
+   card-debugfs_root, card, mmc_test_fops_testlist);
+
+   if (IS_ERR_OR_NULL(file)) {
+   dev_err(card-dev,
+   Can't create testlist. Perhaps debugfs is 
disabled.\n);
ret = -ENODEV;
goto err;
}
-- 
1.7.4.1


___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


[PATCH v8 00/12] use nonblock mmc requests to minimize latency

2011-06-28 Thread Per Forlin
How significant is the cache maintenance over head?
It depends, the eMMC are much faster now
compared to a few years ago and cache maintenance cost more due to
multiple cache levels and speculative cache pre-fetch. In relation the
cost for handling the caches have increased and is now a bottle neck
dealing with fast eMMC together with DMA.

The intention for introducing non-blocking mmc requests is to minimize the
time between a mmc request ends and another mmc request starts. In the
current implementation the MMC controller is idle when dma_map_sg and
dma_unmap_sg is processing. Introducing non-blocking mmc request makes it
possible to prepare the caches for next job in parallel to an active
mmc request.

This is done by making the issue_rw_rq() non-blocking.
The increase in throughput is proportional to the time it takes to
prepare (major part of preparations is dma_map_sg and dma_unmap_sg)
a request and how fast the memory is. The faster the MMC/SD is
the more significant the prepare request time becomes. Measurements on U5500
and Panda on eMMC and SD shows significant performance gain for large
reads when running DMA mode. In the PIO case the performance is unchanged.

There are two optional hooks pre_req() and post_req() that the host driver
may implement in order to move work to before and after the actual mmc_request
function is called. In the DMA case pre_req() may do dma_map_sg() and prepare
the dma descriptor and post_req runs the dma_unmap_sg.

Details on measurements from IOZone and mmc_test:
https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfMMC-async-req

Changes since v7:
 * rebase on mmc-next, on top of Russell's updated error handling.
 * Clarify description of mmc_start_req()
 * Resolve compile without CONFIG_DMA_ENIGNE issue for mmci
 * Add mmc test to measure how performance is affected by sg length
 * Add missing wait_for_busy in mmc_test non-blocking test. This call got lost
   in v4 of this patchset when refactoring mmc_start_req.
 * Add sub-prefix (core block queue) to relevant patches.

Per Forlin (12):
  mmc: core: add non-blocking mmc request function
  omap_hsmmc: add support for pre_req and post_req
  mmci: implement pre_req() and post_req()
  mmc: mmc_test: add debugfs file to list all tests
  mmc: mmc_test: add test for non-blocking transfers
  mmc: mmc_test: test to measure how sg_len affect performance
  mmc: block: add member in mmc queue struct to hold request data
  mmc: block: add a block request prepare function
  mmc: block: move error code in issue_rw_rq to a separate function.
  mmc: queue: add a second mmc queue request member
  mmc: core: add random fault injection
  mmc: block: add handling for two parallel block requests in
issue_rw_rq

 drivers/mmc/card/block.c  |  505 -
 drivers/mmc/card/mmc_test.c   |  491 ++--
 drivers/mmc/card/queue.c  |  184 ++--
 drivers/mmc/card/queue.h  |   33 ++-
 drivers/mmc/core/core.c   |  167 +-
 drivers/mmc/core/debugfs.c|5 +
 drivers/mmc/host/mmci.c   |  147 +++-
 drivers/mmc/host/mmci.h   |8 +
 drivers/mmc/host/omap_hsmmc.c |   87 +++-
 include/linux/mmc/core.h  |6 +-
 include/linux/mmc/host.h  |   24 ++
 lib/Kconfig.debug |   11 +
 12 files changed, 1345 insertions(+), 323 deletions(-)

-- 
1.7.4.1


___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


[PATCH v8 02/12] omap_hsmmc: add support for pre_req and post_req

2011-06-28 Thread Per Forlin
pre_req() runs dma_map_sg(), post_req() runs dma_unmap_sg.
If not calling pre_req() before omap_hsmmc_request()
dma_map_sg will be issued before starting the transfer.
It is optional to use pre_req(). If issuing pre_req()
post_req() must be to be called as well.

Signed-off-by: Per Forlin per.for...@linaro.org
---
 drivers/mmc/host/omap_hsmmc.c |   87 +++--
 1 files changed, 83 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index cd317af..b29ca90 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -141,6 +141,11 @@
 #define OMAP_HSMMC_WRITE(base, reg, val) \
__raw_writel((val), (base) + OMAP_HSMMC_##reg)
 
+struct omap_hsmmc_next {
+   unsigned intdma_len;
+   s32 cookie;
+};
+
 struct omap_hsmmc_host {
struct  device  *dev;
struct  mmc_host*mmc;
@@ -184,6 +189,7 @@ struct omap_hsmmc_host {
int reqs_blocked;
int use_reg;
int req_in_progress;
+   struct omap_hsmmc_next  next_data;
 
struct  omap_mmc_platform_data  *pdata;
 };
@@ -1343,8 +1349,9 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, 
void *cb_data)
return;
}
 
-   dma_unmap_sg(mmc_dev(host-mmc), data-sg, data-sg_len,
-   omap_hsmmc_get_dma_dir(host, data));
+   if (!data-host_cookie)
+   dma_unmap_sg(mmc_dev(host-mmc), data-sg, data-sg_len,
+omap_hsmmc_get_dma_dir(host, data));
 
req_in_progress = host-req_in_progress;
dma_ch = host-dma_ch;
@@ -1362,6 +1369,45 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, 
void *cb_data)
}
 }
 
+static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host,
+  struct mmc_data *data,
+  struct omap_hsmmc_next *next)
+{
+   int dma_len;
+
+   if (!next  data-host_cookie 
+   data-host_cookie != host-next_data.cookie) {
+   printk(KERN_WARNING [%s] invalid cookie: data-host_cookie %d
+   host-next_data.cookie %d\n,
+  __func__, data-host_cookie, host-next_data.cookie);
+   data-host_cookie = 0;
+   }
+
+   /* Check if next job is already prepared */
+   if (next ||
+   (!next  data-host_cookie != host-next_data.cookie)) {
+   dma_len = dma_map_sg(mmc_dev(host-mmc), data-sg,
+data-sg_len,
+omap_hsmmc_get_dma_dir(host, data));
+
+   } else {
+   dma_len = host-next_data.dma_len;
+   host-next_data.dma_len = 0;
+   }
+
+
+   if (dma_len == 0)
+   return -EINVAL;
+
+   if (next) {
+   next-dma_len = dma_len;
+   data-host_cookie = ++next-cookie  0 ? 1 : next-cookie;
+   } else
+   host-dma_len = dma_len;
+
+   return 0;
+}
+
 /*
  * Routine to configure and start DMA for the MMC card
  */
@@ -1395,9 +1441,10 @@ static int omap_hsmmc_start_dma_transfer(struct 
omap_hsmmc_host *host,
mmc_hostname(host-mmc), ret);
return ret;
}
+   ret = omap_hsmmc_pre_dma_transfer(host, data, NULL);
+   if (ret)
+   return ret;
 
-   host-dma_len = dma_map_sg(mmc_dev(host-mmc), data-sg,
-   data-sg_len, omap_hsmmc_get_dma_dir(host, data));
host-dma_ch = dma_ch;
host-dma_sg_idx = 0;
 
@@ -1477,6 +1524,35 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, 
struct mmc_request *req)
return 0;
 }
 
+static void omap_hsmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
+   int err)
+{
+   struct omap_hsmmc_host *host = mmc_priv(mmc);
+   struct mmc_data *data = mrq-data;
+
+   if (host-use_dma) {
+   dma_unmap_sg(mmc_dev(host-mmc), data-sg, data-sg_len,
+omap_hsmmc_get_dma_dir(host, data));
+   data-host_cookie = 0;
+   }
+}
+
+static void omap_hsmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
+  bool is_first_req)
+{
+   struct omap_hsmmc_host *host = mmc_priv(mmc);
+
+   if (mrq-data-host_cookie) {
+   mrq-data-host_cookie = 0;
+   return ;
+   }
+
+   if (host-use_dma)
+   if (omap_hsmmc_pre_dma_transfer(host, mrq-data,
+   host-next_data))
+   mrq-data-host_cookie = 0;
+}
+
 /*
  * Request function. for read/write operation
  */
@@ -1925,6 +2001,8 @@ static int omap_hsmmc_disable_fclk(struct mmc_host *mmc, 
int lazy)
 static const struct mmc_host_ops omap_hsmmc_ops = {
.enable = omap_hsmmc_enable_fclk,
 

[PATCH v8 01/12] mmc: core: add non-blocking mmc request function

2011-06-28 Thread Per Forlin
Previously there has only been one function mmc_wait_for_req()
to start and wait for a request. This patch adds
 * mmc_start_req() - starts a request wihtout waiting
   If there is on ongoing request wait for completion
   of that request and start the new one and return.
   Does not wait for the new command to complete.

This patch also adds new function members in struct mmc_host_ops
only called from core.c
 * pre_req - asks the host driver to prepare for the next job
 * post_req - asks the host driver to clean up after a completed job

The intention is to use pre_req() and post_req() to do cache maintenance
while a request is active. pre_req() can be called while a request is active
to minimize latency to start next job. post_req() can be used after the next
job is started to clean up the request. This will minimize the host driver
request end latency. post_req() is typically used before ending the block
request and handing over the buffer to the block layer.

Add a host-private member in mmc_data to be used by
pre_req to mark the data. The host driver will then
check this mark to see if the data is prepared or not.

Signed-off-by: Per Forlin per.for...@linaro.org
---
 drivers/mmc/core/core.c  |  113 +
 include/linux/mmc/core.h |6 ++-
 include/linux/mmc/host.h |   21 +
 3 files changed, 129 insertions(+), 11 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 7843efe..d2d7239 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -198,9 +198,109 @@ mmc_start_request(struct mmc_host *host, struct 
mmc_request *mrq)
 
 static void mmc_wait_done(struct mmc_request *mrq)
 {
-   complete(mrq-done_data);
+   complete(mrq-completion);
 }
 
+static void __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
+{
+   init_completion(mrq-completion);
+   mrq-done = mmc_wait_done;
+   mmc_start_request(host, mrq);
+}
+
+static void mmc_wait_for_req_done(struct mmc_host *host,
+ struct mmc_request *mrq)
+{
+   wait_for_completion(mrq-completion);
+}
+
+/**
+ * mmc_pre_req - Prepare for a new request
+ * @host: MMC host to prepare command
+ * @mrq: MMC request to prepare for
+ * @is_first_req: true if there is no previous started request
+ * that may run in parellel to this call, otherwise false
+ *
+ * mmc_pre_req() is called in prior to mmc_start_req() to let
+ * host prepare for the new request. Preparation of a request may be
+ * performed while another request is running on the host.
+ */
+static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq,
+bool is_first_req)
+{
+   if (host-ops-pre_req)
+   host-ops-pre_req(host, mrq, is_first_req);
+}
+
+/**
+ * mmc_post_req - Post process a completed request
+ * @host: MMC host to post process command
+ * @mrq: MMC request to post process for
+ * @err: Error, if non zero, clean up any resources made in pre_req
+ *
+ * Let the host post process a completed request. Post processing of
+ * a request may be performed while another reuqest is running.
+ */
+static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq,
+int err)
+{
+   if (host-ops-post_req)
+   host-ops-post_req(host, mrq, err);
+}
+
+/**
+ * mmc_start_req - start a non-blocking request
+ * @host: MMC host to start command
+ * @areq: async request to start
+ * @error: out parameter returns 0 for success, otherwise non zero
+ *
+ * Start a new MMC custom command request for a host.
+ * If there is on ongoing async request wait for completion
+ * of that request and start the new one and return.
+ * Does not wait for the new request to complete.
+ *
+ *  Returns the completed request, NULL in case of none completed.
+ * Wait for the an ongoing request (previoulsy started) to complete and
+ * return the completed request. If there is no ongoing request, NULL
+ * is returned without waiting. NULL is not an error condition.
+ */
+struct mmc_async_req *mmc_start_req(struct mmc_host *host,
+   struct mmc_async_req *areq, int *error)
+{
+   int err = 0;
+   struct mmc_async_req *data = host-areq;
+
+   /* Prepare a new request */
+   if (areq)
+   mmc_pre_req(host, areq-mrq, !host-areq);
+
+   if (host-areq) {
+   mmc_wait_for_req_done(host, host-areq-mrq);
+   err = host-areq-err_check(host-card, host-areq);
+   if (err) {
+   mmc_post_req(host, host-areq-mrq, 0);
+   if (areq)
+   mmc_post_req(host, areq-mrq, -EINVAL);
+
+   host-areq = NULL;
+   goto out;
+   }
+   }
+
+   if (areq)
+   

[PATCH v8 03/12] mmci: implement pre_req() and post_req()

2011-06-28 Thread Per Forlin
pre_req() runs dma_map_sg() and prepares the dma descriptor
for the next mmc data transfer. post_req() runs dma_unmap_sg.
If not calling pre_req() before mmci_request(), mmci_request()
will prepare the cache and dma just like it did it before.
It is optional to use pre_req() and post_req() for mmci.

Signed-off-by: Per Forlin per.for...@linaro.org
---
 drivers/mmc/host/mmci.c |  147 ++
 drivers/mmc/host/mmci.h |8 +++
 2 files changed, 142 insertions(+), 13 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index b4a7e4f..6ed6770 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -211,6 +211,9 @@ static void __devinit mmci_dma_setup(struct mmci_host *host)
return;
}
 
+   /* initialize pre request cookie */
+   host-next_data.cookie = 1;
+
/* Try to acquire a generic DMA engine slave channel */
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
@@ -320,7 +323,8 @@ static void mmci_dma_unmap(struct mmci_host *host, struct 
mmc_data *data)
dir = DMA_FROM_DEVICE;
}
 
-   dma_unmap_sg(chan-device-dev, data-sg, data-sg_len, dir);
+   if (!data-host_cookie)
+   dma_unmap_sg(chan-device-dev, data-sg, data-sg_len, dir);
 
/*
 * Use of DMA with scatter-gather is impossible.
@@ -338,7 +342,8 @@ static void mmci_dma_data_error(struct mmci_host *host)
dmaengine_terminate_all(host-dma_current);
 }
 
-static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
+static int mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
+ struct mmci_host_next *next)
 {
struct variant_data *variant = host-variant;
struct dma_slave_config conf = {
@@ -349,13 +354,20 @@ static int mmci_dma_start_data(struct mmci_host *host, 
unsigned int datactrl)
.src_maxburst = variant-fifohalfsize  2, /* # of words */
.dst_maxburst = variant-fifohalfsize  2, /* # of words */
};
-   struct mmc_data *data = host-data;
struct dma_chan *chan;
struct dma_device *device;
struct dma_async_tx_descriptor *desc;
int nr_sg;
 
-   host-dma_current = NULL;
+   /* Check if next job is already prepared */
+   if (data-host_cookie  !next 
+   host-dma_current  host-dma_desc_current)
+   return 0;
+
+   if (!next) {
+   host-dma_current = NULL;
+   host-dma_desc_current = NULL;
+   }
 
if (data-flags  MMC_DATA_READ) {
conf.direction = DMA_FROM_DEVICE;
@@ -370,7 +382,7 @@ static int mmci_dma_start_data(struct mmci_host *host, 
unsigned int datactrl)
return -EINVAL;
 
/* If less than or equal to the fifo size, don't bother with DMA */
-   if (host-size = variant-fifosize)
+   if (data-blksz * data-blocks = variant-fifosize)
return -EINVAL;
 
device = chan-device;
@@ -384,14 +396,38 @@ static int mmci_dma_start_data(struct mmci_host *host, 
unsigned int datactrl)
if (!desc)
goto unmap_exit;
 
-   /* Okay, go for it. */
-   host-dma_current = chan;
+   if (next) {
+   next-dma_chan = chan;
+   next-dma_desc = desc;
+   } else {
+   host-dma_current = chan;
+   host-dma_desc_current = desc;
+   }
+
+   return 0;
 
+ unmap_exit:
+   if (!next)
+   dmaengine_terminate_all(chan);
+   dma_unmap_sg(device-dev, data-sg, data-sg_len, conf.direction);
+   return -ENOMEM;
+}
+
+static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
+{
+   int ret;
+   struct mmc_data *data = host-data;
+
+   ret = mmci_dma_prep_data(host, host-data, NULL);
+   if (ret)
+   return ret;
+
+   /* Okay, go for it. */
dev_vdbg(mmc_dev(host-mmc),
 Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags 
%08x\n,
 data-sg_len, data-blksz, data-blocks, data-flags);
-   dmaengine_submit(desc);
-   dma_async_issue_pending(chan);
+   dmaengine_submit(host-dma_desc_current);
+   dma_async_issue_pending(host-dma_current);
 
datactrl |= MCI_DPSM_DMAENABLE;
 
@@ -406,14 +442,90 @@ static int mmci_dma_start_data(struct mmci_host *host, 
unsigned int datactrl)
writel(readl(host-base + MMCIMASK0) | MCI_DATAENDMASK,
   host-base + MMCIMASK0);
return 0;
+}
 
-unmap_exit:
-   dmaengine_terminate_all(chan);
-   dma_unmap_sg(device-dev, data-sg, data-sg_len, conf.direction);
-   return -ENOMEM;
+static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)
+{
+   struct mmci_host_next *next = host-next_data;
+
+   if (data-host_cookie  data-host_cookie != next-cookie) {
+   printk(KERN_WARNING [%s] invalid 

[PATCH v8 05/12] mmc: mmc_test: add test for non-blocking transfers

2011-06-28 Thread Per Forlin
Add four tests for read and write performance per
different transfer size, 4k to 4M.
 * Read using blocking mmc request
 * Read using non-blocking mmc request
 * Write using blocking mmc request
 * Write using non-blocking mmc request

The host dirver must support pre_req() and post_req()
in order to run the non-blocking test cases.

Signed-off-by: Per Forlin per.for...@linaro.org
---
 drivers/mmc/card/mmc_test.c |  311 +-
 1 files changed, 303 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index e8508e9..466a192 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -148,6 +148,26 @@ struct mmc_test_card {
struct mmc_test_general_result  *gr;
 };
 
+enum mmc_test_prep_media {
+   MMC_TEST_PREP_NONE = 0,
+   MMC_TEST_PREP_WRITE_FULL = 1  0,
+   MMC_TEST_PREP_ERASE = 1  1,
+};
+
+struct mmc_test_multiple_rw {
+   unsigned int *bs;
+   unsigned int len;
+   unsigned int size;
+   bool do_write;
+   bool do_nonblock_req;
+   enum mmc_test_prep_media prepare;
+};
+
+struct mmc_test_async_req {
+   struct mmc_async_req areq;
+   struct mmc_test_card *test;
+};
+
 /***/
 /*  General helper functions   */
 /***/
@@ -661,7 +681,7 @@ static void mmc_test_prepare_broken_mrq(struct 
mmc_test_card *test,
  * Checks that a normal transfer didn't have any errors
  */
 static int mmc_test_check_result(struct mmc_test_card *test,
-   struct mmc_request *mrq)
+struct mmc_request *mrq)
 {
int ret;
 
@@ -685,6 +705,17 @@ static int mmc_test_check_result(struct mmc_test_card 
*test,
return ret;
 }
 
+static int mmc_test_check_result_async(struct mmc_card *card,
+  struct mmc_async_req *areq)
+{
+   struct mmc_test_async_req *test_async =
+   container_of(areq, struct mmc_test_async_req, areq);
+
+   mmc_test_wait_busy(test_async-test);
+
+   return mmc_test_check_result(test_async-test, areq-mrq);
+}
+
 /*
  * Checks that a short transfer behaved as expected
  */
@@ -720,6 +751,89 @@ static int mmc_test_check_broken_result(struct 
mmc_test_card *test,
 }
 
 /*
+ * Tests nonblock transfer with certain parameters
+ */
+static void mmc_test_nonblock_reset(struct mmc_request *mrq,
+   struct mmc_command *cmd,
+   struct mmc_command *stop,
+   struct mmc_data *data)
+{
+   memset(mrq, 0, sizeof(struct mmc_request));
+   memset(cmd, 0, sizeof(struct mmc_command));
+   memset(data, 0, sizeof(struct mmc_data));
+   memset(stop, 0, sizeof(struct mmc_command));
+
+   mrq-cmd = cmd;
+   mrq-data = data;
+   mrq-stop = stop;
+}
+static int mmc_test_nonblock_transfer(struct mmc_test_card *test,
+ struct scatterlist *sg, unsigned sg_len,
+ unsigned dev_addr, unsigned blocks,
+ unsigned blksz, int write, int count)
+{
+   struct mmc_request mrq1;
+   struct mmc_command cmd1;
+   struct mmc_command stop1;
+   struct mmc_data data1;
+
+   struct mmc_request mrq2;
+   struct mmc_command cmd2;
+   struct mmc_command stop2;
+   struct mmc_data data2;
+
+   struct mmc_test_async_req test_areq[2];
+   struct mmc_async_req *done_areq;
+   struct mmc_async_req *cur_areq = test_areq[0].areq;
+   struct mmc_async_req *other_areq = test_areq[1].areq;
+   int i;
+   int ret;
+
+   test_areq[0].test = test;
+   test_areq[1].test = test;
+
+   if (!test-card-host-ops-pre_req ||
+   !test-card-host-ops-post_req)
+   return -RESULT_UNSUP_HOST;
+
+   mmc_test_nonblock_reset(mrq1, cmd1, stop1, data1);
+   mmc_test_nonblock_reset(mrq2, cmd2, stop2, data2);
+
+   cur_areq-mrq = mrq1;
+   cur_areq-err_check = mmc_test_check_result_async;
+   other_areq-mrq = mrq2;
+   other_areq-err_check = mmc_test_check_result_async;
+
+   for (i = 0; i  count; i++) {
+   mmc_test_prepare_mrq(test, cur_areq-mrq, sg, sg_len, dev_addr,
+blocks, blksz, write);
+   done_areq = mmc_start_req(test-card-host, cur_areq, ret);
+
+   if (ret || (!done_areq  i  0))
+   goto err;
+
+   if (done_areq) {
+   if (done_areq-mrq == mrq2)
+   mmc_test_nonblock_reset(mrq2, cmd2,
+   stop2, data2);
+   else
+   mmc_test_nonblock_reset(mrq1, cmd1,
+   

[PATCH v8 10/12] mmc: queue: add a second mmc queue request member

2011-06-28 Thread Per Forlin
Add an additional mmc queue request instance to make way for
two active block requests. One request may be active while the
other request is being prepared.

Signed-off-by: Per Forlin per.for...@linaro.org
---
 drivers/mmc/card/queue.c |   44 ++--
 drivers/mmc/card/queue.h |3 ++-
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 4222e1a..d69d954 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -132,6 +132,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card 
*card,
u64 limit = BLK_BOUNCE_HIGH;
int ret;
struct mmc_queue_req *mqrq_cur = mq-mqrq[0];
+   struct mmc_queue_req *mqrq_prev = mq-mqrq[1];
 
if (mmc_dev(host)-dma_mask  *mmc_dev(host)-dma_mask)
limit = *mmc_dev(host)-dma_mask;
@@ -142,7 +143,9 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card 
*card,
return -ENOMEM;
 
memset(mq-mqrq_cur, 0, sizeof(mq-mqrq_cur));
+   memset(mq-mqrq_prev, 0, sizeof(mq-mqrq_prev));
mq-mqrq_cur = mqrq_cur;
+   mq-mqrq_prev = mqrq_prev;
mq-queue-queuedata = mq;
 
blk_queue_prep_rq(mq-queue, mmc_prep_request);
@@ -178,9 +181,17 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card 
*card,
allocate bounce cur buffer\n,
mmc_card_name(card));
}
+   mqrq_prev-bounce_buf = kmalloc(bouncesz, GFP_KERNEL);
+   if (!mqrq_prev-bounce_buf) {
+   printk(KERN_WARNING %s: unable to 
+   allocate bounce prev buffer\n,
+   mmc_card_name(card));
+   kfree(mqrq_cur-bounce_buf);
+   mqrq_cur-bounce_buf = NULL;
+   }
}
 
-   if (mqrq_cur-bounce_buf) {
+   if (mqrq_cur-bounce_buf  mqrq_prev-bounce_buf) {
blk_queue_bounce_limit(mq-queue, BLK_BOUNCE_ANY);
blk_queue_max_hw_sectors(mq-queue, bouncesz / 512);
blk_queue_max_segments(mq-queue, bouncesz / 512);
@@ -195,11 +206,19 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card 
*card,
if (ret)
goto cleanup_queue;
 
+   mqrq_prev-sg = mmc_alloc_sg(1, ret);
+   if (ret)
+   goto cleanup_queue;
+
+   mqrq_prev-bounce_sg =
+   mmc_alloc_sg(bouncesz / 512, ret);
+   if (ret)
+   goto cleanup_queue;
}
}
 #endif
 
-   if (!mqrq_cur-bounce_buf) {
+   if (!mqrq_cur-bounce_buf  !mqrq_prev-bounce_buf) {
blk_queue_bounce_limit(mq-queue, limit);
blk_queue_max_hw_sectors(mq-queue,
min(host-max_blk_count, host-max_req_size / 512));
@@ -210,6 +229,10 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card 
*card,
if (ret)
goto cleanup_queue;
 
+
+   mqrq_prev-sg = mmc_alloc_sg(host-max_segs, ret);
+   if (ret)
+   goto cleanup_queue;
}
 
sema_init(mq-thread_sem, 1);
@@ -226,6 +249,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card 
*card,
  free_bounce_sg:
kfree(mqrq_cur-bounce_sg);
mqrq_cur-bounce_sg = NULL;
+   kfree(mqrq_prev-bounce_sg);
+   mqrq_prev-bounce_sg = NULL;
 
  cleanup_queue:
kfree(mqrq_cur-sg);
@@ -233,6 +258,11 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card 
*card,
kfree(mqrq_cur-bounce_buf);
mqrq_cur-bounce_buf = NULL;
 
+   kfree(mqrq_prev-sg);
+   mqrq_prev-sg = NULL;
+   kfree(mqrq_prev-bounce_buf);
+   mqrq_prev-bounce_buf = NULL;
+
blk_cleanup_queue(mq-queue);
return ret;
 }
@@ -242,6 +272,7 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
struct request_queue *q = mq-queue;
unsigned long flags;
struct mmc_queue_req *mqrq_cur = mq-mqrq_cur;
+   struct mmc_queue_req *mqrq_prev = mq-mqrq_prev;
 
/* Make sure the queue isn't suspended, as that will deadlock */
mmc_queue_resume(mq);
@@ -264,6 +295,15 @@ void mmc_cleanup_queue(struct mmc_queue *mq)
kfree(mqrq_cur-bounce_buf);
mqrq_cur-bounce_buf = NULL;
 
+   kfree(mqrq_prev-bounce_sg);
+   mqrq_prev-bounce_sg = NULL;
+
+   kfree(mqrq_prev-sg);
+   mqrq_prev-sg = NULL;
+
+   kfree(mqrq_prev-bounce_buf);
+   mqrq_prev-bounce_buf = NULL;
+
mq-card = NULL;
 }
 EXPORT_SYMBOL(mmc_cleanup_queue);
diff --git a/drivers/mmc/card/queue.h 

[PATCH v8 08/12] mmc: block: add a block request prepare function

2011-06-28 Thread Per Forlin
Break out code from mmc_blk_issue_rw_rq to create a
block request prepare function. This doesn't change
any functionallity. This helps when handling more
than one active block request.

Signed-off-by: Per Forlin per.for...@linaro.org
---
 drivers/mmc/card/block.c |  218 --
 1 files changed, 114 insertions(+), 104 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 88bcc4e..a0a76f4 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -812,12 +812,15 @@ static inline void mmc_apply_rel_rw(struct 
mmc_blk_request *brq,
 R1_CC_ERROR |  /* Card controller error */ \
 R1_ERROR)  /* General/unknown error */
 
-static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
+static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
+  struct mmc_card *card,
+  int disable_multi,
+  struct mmc_queue *mq)
 {
+   u32 readcmd, writecmd;
+   struct mmc_blk_request *brq = mqrq-brq;
+   struct request *req = mqrq-req;
struct mmc_blk_data *md = mq-data;
-   struct mmc_card *card = md-queue.card;
-   struct mmc_blk_request *brq = mq-mqrq_cur-brq;
-   int ret = 1, disable_multi = 0, retry = 0;
 
/*
 * Reliable writes are used to implement Forced Unit Access and
@@ -828,119 +831,126 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, 
struct request *req)
(rq_data_dir(req) == WRITE) 
(md-flags  MMC_BLK_REL_WR);
 
-   do {
-   u32 readcmd, writecmd;
-
-   memset(brq, 0, sizeof(struct mmc_blk_request));
-   brq-mrq.cmd = brq-cmd;
-   brq-mrq.data = brq-data;
-
-   brq-cmd.arg = blk_rq_pos(req);
-   if (!mmc_card_blockaddr(card))
-   brq-cmd.arg = 9;
-   brq-cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
-   brq-data.blksz = 512;
-   brq-stop.opcode = MMC_STOP_TRANSMISSION;
-   brq-stop.arg = 0;
-   brq-stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
-   brq-data.blocks = blk_rq_sectors(req);
-
-   /*
-* The block layer doesn't support all sector count
-* restrictions, so we need to be prepared for too big
-* requests.
-*/
-   if (brq-data.blocks  card-host-max_blk_count)
-   brq-data.blocks = card-host-max_blk_count;
+   memset(brq, 0, sizeof(struct mmc_blk_request));
+   brq-mrq.cmd = brq-cmd;
+   brq-mrq.data = brq-data;
 
-   /*
-* After a read error, we redo the request one sector at a time
-* in order to accurately determine which sectors can be read
-* successfully.
-*/
-   if (disable_multi  brq-data.blocks  1)
-   brq-data.blocks = 1;
+   brq-cmd.arg = blk_rq_pos(req);
+   if (!mmc_card_blockaddr(card))
+   brq-cmd.arg = 9;
+   brq-cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
+   brq-data.blksz = 512;
+   brq-stop.opcode = MMC_STOP_TRANSMISSION;
+   brq-stop.arg = 0;
+   brq-stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
+   brq-data.blocks = blk_rq_sectors(req);
 
-   if (brq-data.blocks  1 || do_rel_wr) {
-   /* SPI multiblock writes terminate using a special
-* token, not a STOP_TRANSMISSION request.
-*/
-   if (!mmc_host_is_spi(card-host) ||
-   rq_data_dir(req) == READ)
-   brq-mrq.stop = brq-stop;
-   readcmd = MMC_READ_MULTIPLE_BLOCK;
-   writecmd = MMC_WRITE_MULTIPLE_BLOCK;
-   } else {
-   brq-mrq.stop = NULL;
-   readcmd = MMC_READ_SINGLE_BLOCK;
-   writecmd = MMC_WRITE_BLOCK;
-   }
-   if (rq_data_dir(req) == READ) {
-   brq-cmd.opcode = readcmd;
-   brq-data.flags |= MMC_DATA_READ;
-   } else {
-   brq-cmd.opcode = writecmd;
-   brq-data.flags |= MMC_DATA_WRITE;
-   }
+   /*
+* The block layer doesn't support all sector count
+* restrictions, so we need to be prepared for too big
+* requests.
+*/
+   if (brq-data.blocks  card-host-max_blk_count)
+   brq-data.blocks = card-host-max_blk_count;
 
-   if (do_rel_wr)
-   mmc_apply_rel_rw(brq, card, req);
+   /*
+* After a read error, we redo the request one sector at a time
+* in order to 

[PATCH v8 11/12] mmc: core: add random fault injection

2011-06-28 Thread Per Forlin
This simple fault injection proved to be very useful to
test the error handling in the block.c rw_rq(). It may
still be useful to test if the host driver handle
pre_req() and post_req() correctly in case of errors.

Signed-off-by: Per Forlin per.for...@linaro.org
---
 drivers/mmc/core/core.c|   54 
 drivers/mmc/core/debugfs.c |5 
 include/linux/mmc/host.h   |3 ++
 lib/Kconfig.debug  |   11 +
 4 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d2d7239..62a8cc7 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -23,6 +23,8 @@
 #include linux/log2.h
 #include linux/regulator/consumer.h
 #include linux/pm_runtime.h
+#include linux/fault-inject.h
+#include linux/random.h
 
 #include linux/mmc/card.h
 #include linux/mmc/host.h
@@ -82,6 +84,56 @@ static void mmc_flush_scheduled_work(void)
flush_workqueue(workqueue);
 }
 
+#ifdef CONFIG_FAIL_MMC_REQUEST
+
+static DECLARE_FAULT_ATTR(fail_mmc_request);
+
+static int __init setup_fail_mmc_request(char *str)
+{
+   return setup_fault_attr(fail_mmc_request, str);
+}
+__setup(fail_mmc_request=, setup_fail_mmc_request);
+
+static void mmc_should_fail_request(struct mmc_host *host,
+   struct mmc_request *mrq)
+{
+   struct mmc_command *cmd = mrq-cmd;
+   struct mmc_data *data = mrq-data;
+   static const int data_errors[] = {
+   -ETIMEDOUT,
+   -EILSEQ,
+   -EIO,
+   };
+
+   if (!data)
+   return;
+
+   if (cmd-error || data-error || !host-make_it_fail ||
+   !should_fail(fail_mmc_request, data-blksz * data-blocks))
+   return;
+
+   data-error = data_errors[random32() % ARRAY_SIZE(data_errors)];
+   data-bytes_xfered = (random32() % (data-bytes_xfered  9))  9;
+}
+
+static int __init fail_mmc_request_debugfs(void)
+{
+   return init_fault_attr_dentries(fail_mmc_request,
+   fail_mmc_request);
+}
+
+late_initcall(fail_mmc_request_debugfs);
+
+#else /* CONFIG_FAIL_MMC_REQUEST */
+
+static void mmc_should_fail_request(struct mmc_host *host,
+   struct mmc_request *mrq)
+{
+}
+
+#endif /* CONFIG_FAIL_MMC_REQUEST */
+
+
 /**
  * mmc_request_done - finish processing an MMC request
  * @host: MMC host which completed request
@@ -108,6 +160,8 @@ void mmc_request_done(struct mmc_host *host, struct 
mmc_request *mrq)
cmd-error = 0;
host-ops-request(host, mrq);
} else {
+   mmc_should_fail_request(host, mrq);
+
led_trigger_event(host-led, LED_OFF);
 
pr_debug(%s: req done (CMD%u): %d: %08x %08x %08x %08x\n,
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 998797e..588e76f 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -188,6 +188,11 @@ void mmc_add_host_debugfs(struct mmc_host *host)
root, host-clk_delay))
goto err_node;
 #endif
+#ifdef CONFIG_FAIL_MMC_REQUEST
+   if (!debugfs_create_u8(make-it-fail, S_IRUSR | S_IWUSR,
+  root, host-make_it_fail))
+   goto err_node;
+#endif
return;
 
 err_node:
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 59db6f2..0d0a48f 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -301,6 +301,9 @@ struct mmc_host {
 
struct mmc_async_req*areq;  /* active async req */
 
+#ifdef CONFIG_FAIL_MMC_REQUEST
+   u8  make_it_fail;
+#endif
unsigned long   private[0] cacheline_aligned;
 };
 
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index c768bcd..330fc70 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1057,6 +1057,17 @@ config FAIL_IO_TIMEOUT
  Only works with drivers that use the generic timeout handling,
  for others it wont do anything.
 
+config FAIL_MMC_REQUEST
+   bool Fault-injection capability for MMC IO
+   select DEBUG_FS
+   depends on FAULT_INJECTION
+   help
+ Provide fault-injection capability for MMC IO.
+ This will make the mmc core return data errors. This is
+ useful for testing the error handling in the mmc block device
+ and how the mmc host driver handle retries from
+ the block device.
+
 config FAULT_INJECTION_DEBUG_FS
bool Debugfs entries for fault-injection capabilities
depends on FAULT_INJECTION  SYSFS  DEBUG_FS
-- 
1.7.4.1


___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


[PATCH v8 09/12] mmc: block: move error code in issue_rw_rq to a separate function.

2011-06-28 Thread Per Forlin
Break out code without functional changes. This simplifies the code and
makes way for handle two parallel request.

Signed-off-by: Per Forlin per.for...@linaro.org
---
 drivers/mmc/card/block.c |  220 +++---
 1 files changed, 131 insertions(+), 89 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index a0a76f4..7ed2c68 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -106,6 +106,16 @@ struct mmc_blk_data {
 
 static DEFINE_MUTEX(open_lock);
 
+enum mmc_blk_status {
+   MMC_BLK_SUCCESS = 0,
+   MMC_BLK_PARTIAL,
+   MMC_BLK_RETRY,
+   MMC_BLK_RETRY_SINGLE,
+   MMC_BLK_DATA_ERR,
+   MMC_BLK_CMD_ERR,
+   MMC_BLK_ABORT,
+};
+
 module_param(perdev_minors, int, 0444);
 MODULE_PARM_DESC(perdev_minors, Minors numbers to allocate per device);
 
@@ -812,6 +822,95 @@ static inline void mmc_apply_rel_rw(struct mmc_blk_request 
*brq,
 R1_CC_ERROR |  /* Card controller error */ \
 R1_ERROR)  /* General/unknown error */
 
+int mmc_blk_err_check(struct mmc_blk_request *brq,
+ struct request *req,
+ struct mmc_card *card,
+ struct mmc_blk_data *md)
+{
+   int ret = MMC_BLK_SUCCESS;
+
+   /*
+* sbc.error indicates a problem with the set block count
+* command.  No data will have been transferred.
+*
+* cmd.error indicates a problem with the r/w command.  No
+* data will have been transferred.
+*
+* stop.error indicates a problem with the stop command.  Data
+* may have been transferred, or may still be transferring.
+*/
+   if (brq-sbc.error || brq-cmd.error || brq-stop.error) {
+   switch (mmc_blk_cmd_recovery(card, req, brq)) {
+   case ERR_RETRY:
+   return MMC_BLK_RETRY;
+   case ERR_ABORT:
+   return MMC_BLK_ABORT;
+   case ERR_CONTINUE:
+   break;
+   }
+   }
+
+   /*
+* Check for errors relating to the execution of the
+* initial command - such as address errors.  No data
+* has been transferred.
+*/
+   if (brq-cmd.resp[0]  CMD_ERRORS) {
+   pr_err(%s: r/w command failed, status = %#x\n,
+  req-rq_disk-disk_name, brq-cmd.resp[0]);
+   return MMC_BLK_ABORT;
+   }
+
+   /*
+* Everything else is either success, or a data error of some
+* kind.  If it was a write, we may have transitioned to
+* program mode, which we have to wait for it to complete.
+*/
+   if (!mmc_host_is_spi(card-host)  rq_data_dir(req) != READ) {
+   u32 status;
+   do {
+   int err = get_card_status(card, status, 5);
+   if (err) {
+   printk(KERN_ERR %s: error %d requesting 
status\n,
+  req-rq_disk-disk_name, err);
+   return MMC_BLK_CMD_ERR;
+   }
+   /*
+* Some cards mishandle the status bits,
+* so make sure to check both the busy
+* indication and the card state.
+*/
+   } while (!(status  R1_READY_FOR_DATA) ||
+(R1_CURRENT_STATE(status) == R1_STATE_PRG));
+   }
+
+   if (brq-data.error) {
+   pr_err(%s: error %d transferring data, sector %u, nr %u, cmd 
response %#x, card status %#x\n,
+  req-rq_disk-disk_name, brq-data.error,
+  (unsigned)blk_rq_pos(req),
+  (unsigned)blk_rq_sectors(req),
+  brq-cmd.resp[0], brq-stop.resp[0]);
+
+   if (rq_data_dir(req) == READ) {
+   if (brq-data.blocks  1) {
+   /* Redo read one sector at a time */
+   pr_warning(%s: retrying using single block 
read\n,
+  req-rq_disk-disk_name);
+   return MMC_BLK_RETRY_SINGLE;
+   }
+   return MMC_BLK_DATA_ERR;
+   } else {
+   return MMC_BLK_CMD_ERR;
+   }
+   }
+
+   if (ret == MMC_BLK_SUCCESS 
+   blk_rq_bytes(req) != brq-data.bytes_xfered)
+   ret = MMC_BLK_PARTIAL;
+
+   return ret;
+}
+
 static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq,
   struct mmc_card *card,
   int disable_multi,
@@ -948,6 +1047,7 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, 
struct request *req)
struct mmc_card *card = md-queue.card;
struct mmc_blk_request *brq = 

[PATCH v8 12/12] mmc: block: add handling for two parallel block requests in issue_rw_rq

2011-06-28 Thread Per Forlin
Change mmc_blk_issue_rw_rq() to become asynchronous.
The execution flow looks like this:
The mmc-queue calls issue_rw_rq(), which sends the request
to the host and returns back to the mmc-queue. The mmc-queue calls
issue_rw_rq() again with a new request. This new request is prepared,
in isuue_rw_rq(), then it waits for the active request to complete before
pushing it to the host. When to mmc-queue is empty it will call
isuue_rw_rq() with req=NULL to finish off the active request
without starting a new request.

Signed-off-by: Per Forlin per.for...@linaro.org
---
 drivers/mmc/card/block.c |   80 +
 drivers/mmc/card/queue.c |   17 +++---
 drivers/mmc/card/queue.h |1 +
 3 files changed, 78 insertions(+), 20 deletions(-)

diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 7ed2c68..825741e 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -822,12 +822,14 @@ static inline void mmc_apply_rel_rw(struct 
mmc_blk_request *brq,
 R1_CC_ERROR |  /* Card controller error */ \
 R1_ERROR)  /* General/unknown error */
 
-int mmc_blk_err_check(struct mmc_blk_request *brq,
- struct request *req,
- struct mmc_card *card,
- struct mmc_blk_data *md)
+static int mmc_blk_err_check(struct mmc_card *card,
+struct mmc_async_req *areq)
 {
-   int ret = MMC_BLK_SUCCESS;
+   enum mmc_blk_status ret = MMC_BLK_SUCCESS;
+   struct mmc_queue_req *mq_mrq = container_of(areq, struct mmc_queue_req,
+   mmc_active);
+   struct mmc_blk_request *brq = mq_mrq-brq;
+   struct request *req = mq_mrq-req;
 
/*
 * sbc.error indicates a problem with the set block count
@@ -1038,24 +1040,41 @@ static void mmc_blk_rw_rq_prep(struct mmc_queue_req 
*mqrq,
brq-data.sg_len = i;
}
 
+   mqrq-mmc_active.mrq = brq-mrq;
+   mqrq-mmc_active.err_check = mmc_blk_err_check;
+
mmc_queue_bounce_pre(mqrq);
 }
 
-static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
+static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
 {
struct mmc_blk_data *md = mq-data;
struct mmc_card *card = md-queue.card;
struct mmc_blk_request *brq = mq-mqrq_cur-brq;
int ret = 1, disable_multi = 0, retry = 0;
enum mmc_blk_status status;
+   struct mmc_queue_req *mq_rq;
+   struct request *req;
+   struct mmc_async_req *areq;
 
-   do {
-   mmc_blk_rw_rq_prep(mq-mqrq_cur, card, disable_multi, mq);
-   mmc_wait_for_req(card-host, brq-mrq);
+   if (!rqc  !mq-mqrq_prev-req)
+   return 0;
 
-   mmc_queue_bounce_post(mq-mqrq_cur);
+   do {
+   if (rqc) {
+   mmc_blk_rw_rq_prep(mq-mqrq_cur, card, 0, mq);
+   areq = mq-mqrq_cur-mmc_active;
+   } else
+   areq = NULL;
+   areq = mmc_start_req(card-host, areq, (int *) status);
+   if (!areq)
+   return 0;
+
+   mq_rq = container_of(areq, struct mmc_queue_req, mmc_active);
+   brq = mq_rq-brq;
+   req = mq_rq-req;
+   mmc_queue_bounce_post(mq_rq);
 
-   status = mmc_blk_err_check(brq, req, card, md);
switch (status) {
case MMC_BLK_SUCCESS:
case MMC_BLK_PARTIAL:
@@ -1066,6 +1085,13 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, 
struct request *req)
ret = __blk_end_request(req, 0,
brq-data.bytes_xfered);
spin_unlock_irq(md-lock);
+   if (status == MMC_BLK_SUCCESS  ret) {
+   /* If this happen it is a bug */
+   printk(KERN_ERR %s BUG rq_tot %d d_xfer %d\n,
+  __func__, blk_rq_bytes(req),
+  brq-data.bytes_xfered);
+   goto cmd_abort;
+   }
break;
case MMC_BLK_CMD_ERR:
goto cmd_err;
@@ -1087,9 +1113,19 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, 
struct request *req)
ret = __blk_end_request(req, -EIO,
brq-data.blksz);
spin_unlock_irq(md-lock);
+   if (!ret)
+   goto start_new_req;
break;
}
 
+   if (ret) {
+   /*
+* In case of a none complete request
+* prepare it again and resend.
+   

LAVA Documentation

2011-06-28 Thread Paul Larson
I've started on some basic documentation for LAVA at
https://wiki.linaro.org/Platform/Validation/LAVA/Documentation
This is mostly aimed at those who are trying to set it up for themselves, or
get started on development for it.  However I'm also starting to cover
example jobs, and will expand that section further to list the available
actions and the parameters they can take.  It's a wiki, so feel free to add
to it, or let me know if there's a particular section you have questions
about and want to see expanded sooner.

Thanks,
Paul Larson
___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


Re: [PATCH v8 12/12] mmc: block: add handling for two parallel block requests in issue_rw_rq

2011-06-28 Thread Per Forlin
On 28 June 2011 10:11, Per Forlin per.for...@linaro.org wrote:
 Change mmc_blk_issue_rw_rq() to become asynchronous.
 The execution flow looks like this:
 The mmc-queue calls issue_rw_rq(), which sends the request
 to the host and returns back to the mmc-queue. The mmc-queue calls
 issue_rw_rq() again with a new request. This new request is prepared,
 in isuue_rw_rq(), then it waits for the active request to complete before
 pushing it to the host. When to mmc-queue is empty it will call
 isuue_rw_rq() with req=NULL to finish off the active request
 without starting a new request.

 Signed-off-by: Per Forlin per.for...@linaro.org
 ---
  drivers/mmc/card/block.c |   80 +
  drivers/mmc/card/queue.c |   17 +++---
  drivers/mmc/card/queue.h |    1 +
  3 files changed, 78 insertions(+), 20 deletions(-)

 diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
 index 7ed2c68..825741e 100644
 --- a/drivers/mmc/card/block.c
 +++ b/drivers/mmc/card/block.c
...
 @@ -1066,6 +1085,13 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, 
 struct request *req)
                        ret = __blk_end_request(req, 0,
                                                brq-data.bytes_xfered);
                        spin_unlock_irq(md-lock);
 +                       if (status == MMC_BLK_SUCCESS  ret) {
 +                               /* If this happen it is a bug */
 +                               printk(KERN_ERR %s BUG rq_tot %d d_xfer 
 %d\n,
 +                                      __func__, blk_rq_bytes(req),
 +                                      brq-data.bytes_xfered);
+ rqc = NULL
If there is a new request (rqc != NULL)  it will already be started
when reaching this point.
If rqc is set it will be started again at start_new_req.

I wonder if this paranoia check is necessary. If status ==
MMC_BLK_SUCCESS all bytes are transferred and no error returned from
mmc layer.
 __blk_end_request would always return 0 in this case, please comment
if you disagree.

...
 + start_new_req:
 +       if (rqc) {
 +               mmc_blk_rw_rq_prep(mq-mqrq_cur, card, 0, mq);
 +               mmc_start_req(card-host, mq-mqrq_cur-mmc_active, NULL);
 +       }
 +
        return 0;
  }

/Per

___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


Re: [PATCH v8 00/12] use nonblock mmc requests to minimize latency

2011-06-28 Thread Kyungmin Park
This patches are tested on samsung exynos4 platform.

Acked-by: Kyungmin Park kyungmin.p...@samsung.com

On Tue, Jun 28, 2011 at 5:11 PM, Per Forlin per.for...@linaro.org wrote:
 How significant is the cache maintenance over head?
 It depends, the eMMC are much faster now
 compared to a few years ago and cache maintenance cost more due to
 multiple cache levels and speculative cache pre-fetch. In relation the
 cost for handling the caches have increased and is now a bottle neck
 dealing with fast eMMC together with DMA.

 The intention for introducing non-blocking mmc requests is to minimize the
 time between a mmc request ends and another mmc request starts. In the
 current implementation the MMC controller is idle when dma_map_sg and
 dma_unmap_sg is processing. Introducing non-blocking mmc request makes it
 possible to prepare the caches for next job in parallel to an active
 mmc request.

 This is done by making the issue_rw_rq() non-blocking.
 The increase in throughput is proportional to the time it takes to
 prepare (major part of preparations is dma_map_sg and dma_unmap_sg)
 a request and how fast the memory is. The faster the MMC/SD is
 the more significant the prepare request time becomes. Measurements on U5500
 and Panda on eMMC and SD shows significant performance gain for large
 reads when running DMA mode. In the PIO case the performance is unchanged.

 There are two optional hooks pre_req() and post_req() that the host driver
 may implement in order to move work to before and after the actual mmc_request
 function is called. In the DMA case pre_req() may do dma_map_sg() and prepare
 the dma descriptor and post_req runs the dma_unmap_sg.

 Details on measurements from IOZone and mmc_test:
 https://wiki.linaro.org/WorkingGroups/Kernel/Specs/StoragePerfMMC-async-req

 Changes since v7:
  * rebase on mmc-next, on top of Russell's updated error handling.
  * Clarify description of mmc_start_req()
  * Resolve compile without CONFIG_DMA_ENIGNE issue for mmci
  * Add mmc test to measure how performance is affected by sg length
  * Add missing wait_for_busy in mmc_test non-blocking test. This call got lost
   in v4 of this patchset when refactoring mmc_start_req.
  * Add sub-prefix (core block queue) to relevant patches.

 Per Forlin (12):
  mmc: core: add non-blocking mmc request function
  omap_hsmmc: add support for pre_req and post_req
  mmci: implement pre_req() and post_req()
  mmc: mmc_test: add debugfs file to list all tests
  mmc: mmc_test: add test for non-blocking transfers
  mmc: mmc_test: test to measure how sg_len affect performance
  mmc: block: add member in mmc queue struct to hold request data
  mmc: block: add a block request prepare function
  mmc: block: move error code in issue_rw_rq to a separate function.
  mmc: queue: add a second mmc queue request member
  mmc: core: add random fault injection
  mmc: block: add handling for two parallel block requests in
    issue_rw_rq

  drivers/mmc/card/block.c      |  505 
 -
  drivers/mmc/card/mmc_test.c   |  491 ++--
  drivers/mmc/card/queue.c      |  184 ++--
  drivers/mmc/card/queue.h      |   33 ++-
  drivers/mmc/core/core.c       |  167 +-
  drivers/mmc/core/debugfs.c    |    5 +
  drivers/mmc/host/mmci.c       |  147 +++-
  drivers/mmc/host/mmci.h       |    8 +
  drivers/mmc/host/omap_hsmmc.c |   87 +++-
  include/linux/mmc/core.h      |    6 +-
  include/linux/mmc/host.h      |   24 ++
  lib/Kconfig.debug             |   11 +
  12 files changed, 1345 insertions(+), 323 deletions(-)

 --
 1.7.4.1


 ___
 linux-arm-kernel mailing list
 linux-arm-ker...@lists.infradead.org
 http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


[U-BOOT][GIT PULL] Remaining patches for u-boot on i.MX53 QuickStart

2011-06-28 Thread Eric Miao
Hi John,

These are the patches not yet merged upstream, but are required
for a good enabling of u-boot on i.MX53 QuickStart board. Please
consider pull.

Thanks

The following changes since commit b80e315300b0717be4b273ddb53dbafa483f4066:

  Efika: fix build breakage (2011-06-22 20:04:02 -0600)

are available in the git repository at:
  git://git.linaro.org/bsp/freescale/u-boot-linaro-natty.git master

Eric Miao (2):
  mx53loco: define ERRATUM_ESDHC111
  mx53loco: workaround VPU TO2 Errata by increasing peripheral voltage

Jason Liu (3):
  mx5: Add clock config interface
  mx53loco: PMIC: Add dialog pmic support
  mx53loco: Add power init support

 arch/arm/cpu/armv7/mx5/clock.c|  551 -
 arch/arm/include/asm/arch-mx5/clock.h |4 +
 arch/arm/include/asm/arch-mx5/crm_regs.h  |6 +
 arch/arm/include/asm/arch-mx5/imx-regs.h  |1 +
 arch/arm/include/asm/arch-mx5/sys_proto.h |2 +
 board/freescale/mx53loco/mx53loco.c   |   97 +
 drivers/misc/Makefile |1 +
 drivers/misc/dialog_pmic.c|  123 +++
 include/configs/mx53loco.h|   15 +
 include/da9053.h  |  186 ++
 10 files changed, 983 insertions(+), 3 deletions(-)
 create mode 100644 drivers/misc/dialog_pmic.c
 create mode 100644 include/da9053.h

___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


[PATCH 9/11] Backlight: DA9052 Backlight driver v1

2011-06-28 Thread ashishj3
DA9052 PMIC has capability to supply power for upto 3 banks of 6 white serial
LEDS. It can also control intensity of independent banks. To drive these
banks boost converter will provide up to 24V and forward current of max. 50mA.

This patch controls intensity of the individual WLEDs bank through
DA9052 PMIC.

Signed-off-by: David Dajun Chen dc...@diasemi.com
Signed-off-by: Ashish Jangam ashish.jan...@kpitcummins.com
---
 drivers/video/backlight/Kconfig |6 +
 drivers/video/backlight/Makefile|1 +
 drivers/video/backlight/da9052_bl.c |  216 +++
 3 files changed, 223 insertions(+), 0 deletions(-)
 create mode 100755 drivers/video/backlight/da9052_bl.c
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 0c9373b..a14fb21 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -237,6 +237,12 @@ config BACKLIGHT_DA903X
  If you have a LCD backlight connected to the WLED output of DA9030
  or DA9034 WLED output, say Y here to enable this driver.
 
+config BACKLIGHT_DA9052
+tristate Dialog DA9052 WLED
+depends on PMIC_DA9052
+help
+  Enable the DA9052 Backlight Driver
+
 config BACKLIGHT_MAX8925
tristate Backlight driver for MAX8925
depends on MFD_MAX8925
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index b9ca849..a317e11 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
 obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
 obj-$(CONFIG_BACKLIGHT_PWM)+= pwm_bl.o
 obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
+obj-$(CONFIG_BACKLIGHT_DA9052) += da9052_bl.o
 obj-$(CONFIG_BACKLIGHT_MAX8925)+= max8925_bl.o
 obj-$(CONFIG_BACKLIGHT_APPLE)  += apple_bl.o
 obj-$(CONFIG_BACKLIGHT_TOSA)   += tosa_bl.o
diff --git a/drivers/video/backlight/da9052_bl.c 
b/drivers/video/backlight/da9052_bl.c
new file mode 100755
index 000..ed8b2f8
--- /dev/null
+++ b/drivers/video/backlight/da9052_bl.c
@@ -0,0 +1,216 @@
+/*
+ * Backlight Driver for Dialog DA9052 PMICs
+ *
+ * Copyright(c) 2011 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen dc...@diasemi.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include linux/backlight.h
+#include linux/delay.h
+#include linux/fb.h
+#include linux/platform_device.h
+
+#include linux/mfd/da9052/da9052.h
+#include linux/mfd/da9052/reg.h
+
+#define DA9052_MAX_BRIGHTNESS  0xFF
+
+enum {
+   DA9052_WLEDS_OFF,
+   DA9052_WLEDS_ON,
+};
+
+static unsigned char wled_bank[] = {
+   DA9052_LED1_CONF_REG,
+   DA9052_LED2_CONF_REG,
+   DA9052_LED3_CONF_REG,
+};
+
+struct da9052_bl {
+   struct da9052 *da9052;
+   uint brightness;
+   uint state;
+   uint led_reg;
+};
+
+static int da9052_adjust_wled_brightness(struct da9052_bl *wleds)
+{
+   unsigned char boost_en;
+   unsigned char i_sink;
+   int ret;
+
+   boost_en = 0x3F;
+   i_sink = 0xFF;
+   if (wleds-state == DA9052_WLEDS_OFF) {
+   boost_en = 0x00;
+   i_sink = 0x00;
+   }
+
+   ret = da9052_reg_write(wleds-da9052, DA9052_BOOST_REG, boost_en);
+   if (ret  0) {
+   dev_err(wleds-da9052-dev,
+   Failed to write boost reg, %d\n, ret);
+   return ret;
+   }
+
+   ret = da9052_reg_write(wleds-da9052, DA9052_LED_CONT_REG, i_sink);
+   if (ret  0) {
+   dev_err(wleds-da9052-dev,
+   Failed to write led cont reg, %d\n, ret);
+   return ret;
+   }
+
+   ret = da9052_reg_write(wleds-da9052, wled_bank[wleds-led_reg], 0x0);
+   if (ret  0) {
+   dev_err(wleds-da9052-dev,
+   Failed to write led conf reg, %d, ret);
+   return ret;
+   }
+
+   if (wleds-brightness) {
+   msleep(10);
+   ret = da9052_reg_write(wleds-da9052, wled_bank[wleds-led_reg],
+  wleds-brightness);
+   if (ret  0) {
+   dev_err(wleds-da9052-dev,
+   Failed to write led conf reg, %d, ret);
+   return ret;
+   }
+   }
+
+   return 0;
+}
+
+static int da9052_backlight_update_status(struct backlight_device *bl)
+{
+   int brightness = bl-props.brightness;
+   struct da9052_bl *wleds = bl_get_data(bl);
+
+   wleds-brightness = brightness;
+   wleds-state = DA9052_WLEDS_ON;
+
+   return da9052_adjust_wled_brightness(wleds);
+}
+
+static int da9052_backlight_get_brightness(struct backlight_device *bl)
+{
+   

[PATCH 6/11] HWMON: DA9052 hwmon driver v1

2011-06-28 Thread ashishj3
The DA9052 PMIC provides an Analogue to Digital Converter with 10 bits
resolution and 10 channels.

This patch montiors the DA9052 PMIC's ADC channels mostly for battery parameters
like battery temperature, junction temperature, battery current etc.

Signed-off-by: David Dajun Chen dc...@diasemi.com
Signed-off-by: Ashish Jangam ashish.jan...@kpitcummins.com
---
 Documentation/hwmon/da9052   |   58 
 drivers/hwmon/Kconfig|   10 ++
 drivers/hwmon/Makefile   |1 +
 drivers/hwmon/da9052-hwmon.c |  332 ++
 4 files changed, 401 insertions(+), 0 deletions(-)
 create mode 100755 Documentation/hwmon/da9052
 create mode 100755 drivers/hwmon/da9052-hwmon.c
diff --git a/Documentation/hwmon/da9052 b/Documentation/hwmon/da9052
new file mode 100755
index 000..0b7930f
--- /dev/null
+++ b/Documentation/hwmon/da9052
@@ -0,0 +1,58 @@
+Kernel driver da9052-hwmon
+==
+
+Supported chips:
+  * Dialog Semiconductors DA9052 PMICs
+Prefix: 'da9052'
+Datasheet: Kindly visit www.dialog-semiconductor.com and request for the
+   official datasheet.
+
+Authors: David Dajun Chen dc...@diasemi.com
+
+Description
+---
+
+The DA9052 provides an Analogue to Digital Converter (ADC) with 10 bits
+resolution and track and hold circuitry combined with an analogue input
+multiplexer. The analogue input multiplexer will allow conversion of up to 10
+different inputs. The track and hold circuit ensures stable input voltages at
+the input of the ADC during the conversion.
+
+The ADC is used to measure the following inputs:
+Channel 0: VDDOUT - measurement of the system voltage
+Channel 1: ICH - internal battery charger current measurement
+Channel 2: TBAT - output from the battery NTC
+Channel 3: VBAT - measurement of the battery voltage
+Channel 4: ADC_IN4 - high impedance input (0 - 2.5V)
+Channel 5: ADC_IN5 - high impedance input (0 - 2.5V)
+Channel 6: ADC_IN6 - high impedance input (0 - 2.5V)
+Channel 7: XY - TSI interface to measure the X and Y voltage of the touch
+screen resistive potentiometers
+Channel 8: Internal Tjunc. - sense (internal temp. sensor)
+Channel 9: VBBAT - measurement of the backup battery voltage
+
+By using sysfs attributes we can measure the system voltage VDDOUT, the battery
+charging current ICH, battery temperature TBAT, battery junction temperature
+TJUNC, battery voltage VBAT and the back up battery voltage VBBAT.
+
+Voltage Monitoring
+--
+
+Voltages are sampled by a 10 bit ADC.  Voltages in millivolts are 1.465
+times the ADC value.
+
+Temperature Monitoring
+--
+
+Temperatures are sampled by a 10 bit ADC.  Junction and battery temperatures
+are monitored by the ADC channels.
+
+The junction temperature is calculated:
+   Degrees celsius = 1.708 * (TJUNC_RES - T_OFFSET) - 108.8
+The junction temperature attribute is supported by the driver.
+
+The battery temperature is calculated:
+   Degree Celcius = 1 / (t1 + 1/298)- 273
+where t1 = (1/B)* ln(( ADCval * 2.5)/(R25*ITBAT*255))
+Default values of R25, B, ITBAT are 10e3, 3380 and 50e-6 respectively.
+
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 3236a45..da5ff6d 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -303,6 +303,16 @@ config SENSORS_DS1621
  This driver can also be built as a module.  If so, the module
  will be called ds1621.
 
+config SENSORS_DA9052_ADC
+tristate Dialog DA9052 HWMON
+depends on PMIC_DA9052
+help
+  Say y here to support the ADC found on
+  Dialog Semiconductor DA9052 PMIC.
+
+  This driver can also be built as module. If so, the module
+  will be called da9052-hwmon.
+
 config SENSORS_I5K_AMB
tristate FB-DIMM AMB temperature sensor on Intel 5000 series chipsets
depends on PCI  EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index f7c0c28..88b81ca 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
 obj-$(CONFIG_SENSORS_ATXP1)+= atxp1.o
 obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
 obj-$(CONFIG_SENSORS_PKGTEMP)  += pkgtemp.o
+obj-$(CONFIG_SENSORS_DA9052_ADC) += da9052-hwmon.o
 obj-$(CONFIG_SENSORS_DME1737)  += dme1737.o
 obj-$(CONFIG_SENSORS_DS620)+= ds620.o
 obj-$(CONFIG_SENSORS_DS1621)   += ds1621.o
diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c
new file mode 100755
index 000..e470e9d
--- /dev/null
+++ b/drivers/hwmon/da9052-hwmon.c
@@ -0,0 +1,332 @@
+/*
+ * HWMON Driver for Dialog DA9052
+ *
+ * Copyright(c) 2011 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen dc...@diasemi.com
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or 

Re: [Patch 5/11] Regulator: DA9052 regulator support v1

2011-06-28 Thread Mark Brown
On Mon, Jun 27, 2011 at 02:12:37PM +0530, ashishj3 wrote:

 +static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int 
 min_uA,
 +   int max_uA)
 +{
 + struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
 + int offset = rdev_get_id(rdev);
 + int reg_val;
 +
 + if (min_uA  120 || max_uA  120)
 + return -EINVAL;
 +
 + if (min_uA == 700)
 + reg_val = DA9052_BUCK_CURRENT_LIMIT_700mA;
 + else if (min_uA = 800)
 + reg_val = DA9052_BUCK_CURRENT_LIMIT_800mA;
 + else if (min_uA = 1000)
 + reg_val = DA9052_BUCK_CURRENT_LIMIT_1000mA;
 + else if (min_uA = 1200)
 + reg_val = DA9052_BUCK_CURRENT_LIMIT_1200mA;

What if min_uA is less than 700?

Otherwise this looks reasonable - very much better!

___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


Re: LAVA Documentation

2011-06-28 Thread Christian Robottom Reis
On Tue, Jun 28, 2011 at 09:55:07AM +0100, Paul Larson wrote:
 I've started on some basic documentation for LAVA at
 https://wiki.linaro.org/Platform/Validation/LAVA/Documentation

Good job! I think you should probably split the setting up section from
the writing jobs and hacking parts, since they are pretty different
audiences.

From the developer's perspective, I can think of two initial use cases: I am
in a WG and want to see a test run for this branch I'm working on, and I
am in a Platform unit or Landing team and I want to see how an image
we're generating is behaving on a certain piece of hardware. Can we make
it easy for these people to figure out what to do?
-- 
Christian Robottom Reis, Engineering VP
Brazil (GMT-3) | [+55] 16 9112 6430 | [+1] 612 216 4935
Linaro.org: Open Source Software for ARM SoCs

___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


Re: Please test Android RC builds

2011-06-28 Thread Zach Pfeffer
We have

Android Generic Beagle
https://android-build.linaro.org/builds/~patrik-ryd/dev1106genericb/

as well, but it doesn't get out of uboot. Filing a bug,

On 28 June 2011 14:26, Zach Pfeffer zach.pfef...@linaro.org wrote:
 We've got some RC builds available to test:

 Android Panda LEB
 https://android-build.linaro.org/builds/~patrik-ryd/dev1106lebp/

 Android Generic Panda
 https://android-build.linaro.org/builds/~patrik-ryd/dev1106genericp/

 Beagle does not boot.

 I have attached a little script that makes this easy. Go to the build
 page and copy the start of the boot image's URL. Plug in an SD card
 and the serial terminal and run:

 trybuild.sh 
 https://android-build.linaro.org/jenkins/job/patrik-ryd_dev1106lebp/6/artifact/build/out/target/product/pandaboard
 /dev/sdd

 Once its done it'll drop you into a minicom session.

 For those who test would you mind updating:

 https://bugs.launchpad.net/bugs/803014 with the type of monitor you
 used? The build works with some monitors, but not others.

 Paul,

 Would you manually test these in validation?

 Fathi,

 Please copy these builds as the rc. There's no beagle board build
 since it doesn't boot.

 -Zach


___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


Re: [PATCH 6/11] HWMON: DA9052 hwmon driver v1

2011-06-28 Thread Guenter Roeck
On Tue, 2011-06-28 at 10:24 -0400, ashishj3 wrote:
 The DA9052 PMIC provides an Analogue to Digital Converter with 10 bits
 resolution and 10 channels.
 
 This patch montiors the DA9052 PMIC's ADC channels mostly for battery 
 parameters
 like battery temperature, junction temperature, battery current etc.
 
 Signed-off-by: David Dajun Chen dc...@diasemi.com
 Signed-off-by: Ashish Jangam ashish.jan...@kpitcummins.com

[ ... ]

 +static ssize_t da9052_read_vddout(struct device *dev,
 +  struct device_attribute *devattr, char 
 *buf)
 +{
 +   struct da9052_hwmon *hwmon = dev_get_drvdata(dev);
 +   int ret, vdd = -1;
 +
 +   mutex_lock(hwmon-hwmon_lock);
 +
 +   ret = da9052_enable_vddout_channel(hwmon-da9052);
 +   if (ret  0)
 +   goto hwmon_err;
 +
 +   ret = da9052_reg_read(hwmon-da9052, DA9052_VDD_RES_REG);
 +   if (ret  0)
 +   pr_err(failed to read VDD_RES_REG\n);
 +   else
 +   vdd = ret;
 +
 +   ret = da9052_disable_vddout_channel(hwmon-da9052);
 +   if (ret  0)
 +   goto hwmon_err;
 +
 +   if (vdd = 0) {
 +   mutex_unlock(hwmon-hwmon_lock);
 +   return sprintf(buf, %d\n, vdd);
 +   }
 +
 +hwmon_err:
 +   mutex_unlock(hwmon-hwmon_lock);
 +   return ret;
 +}

This function still produces a bad result if the call to
da9052_reg_read() fails and the call to da9052_disable_vddout_channel()
doesn't. 

I would suggest to replace pr_err() with goto hwmon_err. If you do
that, you don't need to initialize vdd, you don't need the else case for
its assignment, and you don't need if (vdd = 0) either.

Guenter



___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


Re: Android libjpeg

2011-06-28 Thread Mandeep Kumar
Hi All,

I have done some benchmarking on OMAP4  running Ubuntu for various versions
of libjpegs. Benchmarks were collected with modified version of djpeg that
prints out ms time taken for decoding. Sample used for benchmarking is a
12MP image downloaded from a photography website. Here are the results:

*Non Optimized libjpeg-turbo(5 runs):*
 Decoding Time for Run 1: 2022 ms
 Decoding Time for Run 2: 2029 ms
 Decoding Time for Run 3: 2165 ms
 Decoding Time for Run 4: 2027 ms
 Decoding Time for Run 5: 2150 ms
* Median Decoding Time: 2029 ms*

*Linaro's NEON Optimized libjpeg-turbo done in last cycle (5 runs)*
http://git.linaro.org/gitweb?p=people/mandeep-ti/libjpeg-turbo-1.1.0_linaro.git;a=summary
 Decoding Time for Run 1: 1634 ms
 Decoding Time for Run 2: 1634 ms
 Decoding Time for Run 3: 1636 ms
 Decoding Time for Run 4: 1739 ms
 Decoding Time for Run 5: 1738 ms
* Median Decoding Time: 1636 ms*
*Mans Rullgard's libjpeg based of libjpeg 6b (5 runs)*
http://git.mansr.com/?p=libjpeg;a=summary
 Decoding Time for Run 1: 1101 ms
 Decoding Time for Run 2: 1081 ms
 Decoding Time for Run 3: 1081 ms
 Decoding Time for Run 4: 1125 ms
 Decoding Time for Run 5: 1089 ms
* Median Decoding Time: 1089 ms

libjpeg-turbo trunk version that has NEON patches (5 runs). *
http://libjpeg-turbo.svn.sourceforge.net/viewvc/libjpeg-turbo/*
* Decoding Time for Run 1: 1068 ms
 Decoding Time for Run 2: 1065 ms
 Decoding Time for Run 3: 1093 ms
 Decoding Time for Run 4: 1066 ms
 Decoding Time for Run 5: 1067 ms
*Median Decoding Time: 1067 ms*

So basically libjpeg-turbo as of now is pretty much as optimized as anything
out there. As a part of my last cycle work I also produced additional color
conversion routines that I will submit to libjpeg-turbo project after that
libjpeg-turbo should be best library to go (given that it is also highly
optimized for Intel processors).

Thanks  Regards,
Mandeep
*
*


On 24 June 2011 17:09, Zach Pfeffer zach.pfef...@linaro.org wrote:

 We've got a BP for this:


 https://blueprints.launchpad.net/linaro-android/+spec/linaro-android-try-libjpeg-turbo

 On 23 June 2011 03:30, Alexander Sack a...@linaro.org wrote:
  On Thu, Jun 23, 2011 at 3:30 AM, Christian Robottom Reis
  k...@linaro.org wrote:
  Hi there,
 
 I took a look at the AOSP libjpeg code which is included in
 
  git://android.git.kernel.org/platform/external/jpeg
 
  during my flight back home (which incidentally had been diverted and
  landed me in Rio de Janeiro; not sure if I celebrate or cry) and noted
  the following things:
 
 - There is a v6 implementation of the fast IDCT algorithm which
   lives in armv6_idct.S.
 
 - The commit which adds this implementation was added October 2010,
   and there haven't been any changes since.
 
 - The code that selects the decoder IDCT implementation in
   jddctmgr.c always uses that implementation if ANDROID_ARMV6_IDCT
   is defined.
 
 - Google have an ashmem backing store implementation, and have
   code to enable tile-based mode. It's a fairly non-intrusive change
   to use ashmem since it just replaces jpeg_open_backing_store.
 
 - The code is pretty much standard libjpeg without any structural
   changes to it.
 
 - There isn't any NEON code in this branch.
 
 - Mans has an optimized version here:
 
 http://git.mansr.com/?p=libjpeg;a=summary
 
   I don't know if he's submitted this to AOSP or not.
 
  This suggests to me that a simple drop-in of libjpeg-turbo might be
  actually easy to do, and that there is probably a significant
  performance benefit to be achieved. One thing to keep in mind is that
  this code still supports armv6, so we'd probably want to preserve that.
 
  sounds good. Seems like a great starter project for MM WG to get their
  hands dirty on android.
 
  They could have three builds:
 
   1. plain LEB
   2. LEB with mans optimized libjpeg
   3. LEB with libjpeg-turbo
 
  Then benchmark all three and keep AOSP community posted on our intent,
  progress and results.
 
  --
 
   - Alexander
 

___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev


[CALL FOR TESTING] Linaro 11.06 Candidate

2011-06-28 Thread Alexander Sack
Hi,

In preparation for the release of Linaro 11.06 images on 2011-06-30,
a suitable candidate has been selected for testing. The release is
expected to be tested heavily and provide the most stable and
feature-rich images to date this cycle.

Please help our initiative by testing the official Linaro Evaluation
Build (LEB):

* Android:
  http://releases.linaro.org/platform/linaro-n/android/latest/leb-panda/

* Ubuntu:
  http://releases.linaro.org/platform/linaro-n/ubuntu/leb-panda/latest/

On top of our officially supported Linaro Evaluation Builds images above,
the Linaro Platform Team is proud to also provide a set of images prepared by
Linaro developers and community for specific target audience. Developers and
Community Builds images are provided on a best-effort basis and in the hope
that they can be useful. Last reported known to be working images can be found
below:

* Nano:
  http://releases.linaro.org/platform/linaro-n/nano/latest/

* ALIP:
  http://releases.linaro.org/platform/linaro-n/alip/latest/

* Developer:
  http://releases.linaro.org/platform/linaro-n/developer/latest/

A list of all hardware packs hosted by Linaro Platform can be found below:

  http://releases.linaro.org/platform/linaro-n/hwpacks/latest/

Please support the Developers and Community Builds images efforts by testing
and providing feedback for our builds.

As a side note, hwpacks that have an -lt- in their name are outputs from
the Linaro Landing teams, using some of their components.

Similar to the spirit of the Ubuntu based Developers and Community images,
the Linaro Android Platform Team provides a set of vanilla AOSP builds
that use Linaro toolchain and the Linaro mainline kernel for development
boards that have good enough mainline support to run a full AOSP user
experience. Those builds are not officially supported and are provided
in the hope that they might be useful.

* Android Vanilla AOSP for BeagleBoard-xM:
  http://releases.linaro.org/platform/linaro-n/android/latest/beaglexm/

* Android Vanilla AOSP for PandaBoard:
  http://releases.linaro.org/platform/linaro-n/android/latest/panda/

Make your way to the installation instructions:

  https://wiki.linaro.org/Platform/Android/ImageInstallation
  https://wiki.linaro.org/Platform/DevPlatform/Ubuntu/ImageInstallation

For an explanation of how to test and submit your results to the QA
tracker at:

  http://qatracker.linaro.org

For an explanation of how to use the qatracker please see:

  https://wiki.linaro.org/QA/QATracker


Known Issues


Android:
 * Problems with HDMI output on monitors using a hdmi2dvi connector have been
   reported
   - See https://launchpad.net/bugs/803014 for more info
 * Display glitches for the green droids on early splashscreen have been
   reported
   - See https://launchpad.net/bugs/795753 for more info
 * Networking with ethernet requires manual actions to get a connection
   - See https://launchpad.net/bugs/788746 for a workaround
 * Mouse falls asleep and need keyboard to wake up
   - See https://launchpad.net/bugs/772520 has more info
 * Gallery application does not find any photos
   - See https://launchpad.net/bugs/772530 for more info
 * WiFi support is missing in LEB/Android
   - See https://launchpad.net/bugs/803063 for more info
 * u-boot 2011.06 is broken for Android beagleXM images
   - See https://launchpad.net/bugs/803142 for a workaround and fix

Ubuntu:
 * Powering off the panda/LEB causes an oops requiring the user to manually
   shut down the system
   - See https://launchpad.net/bugs/788919
 * Clicking the Shutdown button in LEB/Ubuntu and ALIP causes termination of
   user session, instead of shutting down the system
   - See https://launchpad.net/bugs/785279
 * On OMAP3 platforms have been reported to not have rendering issues, not
   updating icons and parts of the screen correctly
   - See https://launchpad.net/bugs/753878 for details
 * Sound Output on Beagle Xm and Beagle C is not working without manual actions
   - See https://launchpad.net/bugs/760919 for workaround
 * Device Tree support in Linux Linaro hides half of the pandaboard memory.
   - See https://launchpad.net/bugs/707047 for details
 * CPU_FREQ support is broken on common OMAP 3 and OMAP 4 kernel binaries
   - See https://launchpad.net/bugs/784176 for details

-- 

 - Alexander

___
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev