Re: [v2,4/7] scatterlist: add sg_alloc_table_from_buf() helper

2016-03-30 Thread Vignesh R
Hi,

On 03/30/2016 09:09 PM, Boris BREZILLON wrote:

[...]

> +int sg_alloc_table_from_buf(struct sg_table *sgt, const void *buf, size_t 
> len,
> + const struct sg_constraints *constraints,
> + gfp_t gfp_mask)
> +{
> + struct sg_constraints cons = { };
> + size_t remaining, chunk_len;
> + const void *sg_buf;
> + int i, ret;
> +
> + if (constraints)
> + cons = *constraints;
> +
> + ret = sg_check_constraints(, buf, len);
> + if (ret)
> + return ret;
> +
> + sg_buf = buf;
> + remaining = len;
> + i = 0;
> + sg_for_each_chunk_in_buf(sg_buf, remaining, chunk_len, )
> + i++;
> +
> + ret = sg_alloc_table(sgt, i, gfp_mask);
> + if (ret)
> + return ret;
> +
> + sg_buf = buf;
> + remaining = len;
> + i = 0;
> + sg_for_each_chunk_in_buf(sg_buf, remaining, chunk_len, ) {
> + if (is_vmalloc_addr(sg_buf)) {
> + struct page *vm_page;
> +
> + vm_page = vmalloc_to_page(sg_buf);
> + if (!vm_page) {
> + ret = -ENOMEM;
> + goto err_free_table;
> + }
> +
> + sg_set_page(>sgl[i], vm_page, chunk_len,
> + offset_in_page(sg_buf));
> + } else {
> + sg_set_buf(>sgl[i], sg_buf, chunk_len);
> + }
> +

If the buf address is in PKMAP_BASE - PAGE_OFFSET-1 region (I have
observed that JFFS2 FS provides buffers in above region to MTD layer),
if CONFIG_DEBUG_SG is set then sg_set_buf() will throw a BUG_ON() as
virt_addr_is_valid() will return false. Is there a sane way to handle
buffers of PKMAP_BASE region with sg_*  APIs?
Or, is the function sg_alloc_table_from_buf() not to be used with such
buffers?


-- 
Regards
Vignesh
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


cron job: media_tree daily build: ERRORS

2016-03-30 Thread Hans Verkuil
This message is generated daily by a cron job that builds media_tree for
the kernels and architectures in the list below.

Results of the daily build of media_tree:

date:   Thu Mar 31 04:00:18 CEST 2016
git branch: test
git hash:   d3f5193019443ef8e556b64f3cd359773c4d377b
gcc version:i686-linux-gcc (GCC) 5.3.0
sparse version: v0.5.0-56-g7647c77
smatch version: v0.5.0-3353-gcae47da
host hardware:  x86_64
host os:4.4.0-164

linux-git-arm-at91: OK
linux-git-arm-davinci: OK
linux-git-arm-exynos: OK
linux-git-arm-mx: OK
linux-git-arm-omap: OK
linux-git-arm-omap1: OK
linux-git-arm-pxa: OK
linux-git-blackfin-bf561: OK
linux-git-i686: OK
linux-git-m32r: OK
linux-git-mips: OK
linux-git-powerpc64: OK
linux-git-sh: OK
linux-git-x86_64: OK
linux-2.6.36.4-i686: ERRORS
linux-2.6.37.6-i686: ERRORS
linux-2.6.38.8-i686: ERRORS
linux-2.6.39.4-i686: ERRORS
linux-3.0.60-i686: ERRORS
linux-3.1.10-i686: ERRORS
linux-3.2.37-i686: ERRORS
linux-3.3.8-i686: ERRORS
linux-3.4.27-i686: ERRORS
linux-3.5.7-i686: ERRORS
linux-3.6.11-i686: ERRORS
linux-3.7.4-i686: ERRORS
linux-3.8-i686: ERRORS
linux-3.9.2-i686: ERRORS
linux-3.10.1-i686: ERRORS
linux-3.11.1-i686: ERRORS
linux-3.12.23-i686: ERRORS
linux-3.13.11-i686: ERRORS
linux-3.14.9-i686: ERRORS
linux-3.15.2-i686: ERRORS
linux-3.16.7-i686: ERRORS
linux-3.17.8-i686: ERRORS
linux-3.18.7-i686: ERRORS
linux-3.19-i686: ERRORS
linux-4.0-i686: OK
linux-4.1.1-i686: OK
linux-4.2-i686: OK
linux-4.3-i686: OK
linux-4.4-i686: OK
linux-4.5-i686: OK
linux-4.6-rc1-i686: OK
linux-2.6.36.4-x86_64: ERRORS
linux-2.6.37.6-x86_64: ERRORS
linux-2.6.38.8-x86_64: ERRORS
linux-2.6.39.4-x86_64: ERRORS
linux-3.0.60-x86_64: ERRORS
linux-3.1.10-x86_64: ERRORS
linux-3.2.37-x86_64: ERRORS
linux-3.3.8-x86_64: ERRORS
linux-3.4.27-x86_64: ERRORS
linux-3.5.7-x86_64: ERRORS
linux-3.6.11-x86_64: ERRORS
linux-3.7.4-x86_64: ERRORS
linux-3.8-x86_64: ERRORS
linux-3.9.2-x86_64: ERRORS
linux-3.10.1-x86_64: ERRORS
linux-3.11.1-x86_64: ERRORS
linux-3.12.23-x86_64: ERRORS
linux-3.13.11-x86_64: ERRORS
linux-3.14.9-x86_64: ERRORS
linux-3.15.2-x86_64: ERRORS
linux-3.16.7-x86_64: ERRORS
linux-3.17.8-x86_64: ERRORS
linux-3.18.7-x86_64: ERRORS
linux-3.19-x86_64: ERRORS
linux-4.0-x86_64: OK
linux-4.1.1-x86_64: OK
linux-4.2-x86_64: OK
linux-4.3-x86_64: OK
linux-4.4-x86_64: OK
linux-4.5-x86_64: OK
linux-4.6-rc1-x86_64: ERRORS
apps: OK
spec-git: OK
sparse: WARNINGS
smatch: ERRORS

Detailed results are available here:

http://www.xs4all.nl/~hverkuil/logs/Thursday.log

Full logs are available here:

http://www.xs4all.nl/~hverkuil/logs/Thursday.tar.bz2

The Media Infrastructure API from this daily build is here:

http://www.xs4all.nl/~hverkuil/spec/media.html
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 1/2] [media] media: change pipeline validation return error

2016-03-30 Thread Helen Mae Koike Fornazier
According to the V4L2 API, the VIDIOC_STREAMON ioctl should return EPIPE
if there is a format mismatch in the pipeline configuration.

As the .vidioc_streamon in the v4l2_ioctl_ops usually forwards the error
caused by the v4l2_subdev_link_validate_default (if it is in use), it
should return -EPIPE when it detect the mismatch.

When an entity is connected to a non enabled link,
media_entity_pipeline_start should return -ENOLINK, as the link does not
exist.

Signed-off-by: Helen Mae Koike Fornazier 
Acked-by: Sakari Ailus 
---

Nothing has changed since v3

The patch is based on 'media/master' branch and available at
https://github.com/helen-fornazier/opw-staging media/devel

 drivers/media/media-entity.c  | 2 +-
 drivers/media/v4l2-core/v4l2-subdev.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index c53c1d5..d8a2299 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -445,7 +445,7 @@ __must_check int __media_entity_pipeline_start(struct 
media_entity *entity,
bitmap_or(active, active, has_no_links, entity->num_pads);
 
if (!bitmap_full(active, entity->num_pads)) {
-   ret = -EPIPE;
+   ret = -ENOLINK;
dev_dbg(entity->graph_obj.mdev->dev,
"\"%s\":%u must be connected by an enabled 
link\n",
entity->name,
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c 
b/drivers/media/v4l2-core/v4l2-subdev.c
index d630838..918e79d 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -508,7 +508,7 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev 
*sd,
if (source_fmt->format.width != sink_fmt->format.width
|| source_fmt->format.height != sink_fmt->format.height
|| source_fmt->format.code != sink_fmt->format.code)
-   return -EINVAL;
+   return -EPIPE;
 
/* The field order must match, or the sink field order must be NONE
 * to support interlaced hardware connected to bridges that support
@@ -516,7 +516,7 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev 
*sd,
 */
if (source_fmt->format.field != sink_fmt->format.field &&
sink_fmt->format.field != V4L2_FIELD_NONE)
-   return -EINVAL;
+   return -EPIPE;
 
return 0;
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 0/2] media: updating error codes on streamon

2016-03-30 Thread Helen Mae Koike Fornazier
Fix error code on streamon

Changes since v3:

[media] media: change pipeline validation return error
* Nothing has changed
[media] DocBook: update error code in videoc-streamon
* Added "link" word
* Added Ack-by 

The patch set is based on 'media/master' branch and available at
https://github.com/helen-fornazier/opw-staging media/devel

Helen Mae Koike Fornazier (2):
  [media] media: change pipeline validation return error
  [media] DocBook: update error code in videoc-streamon

 Documentation/DocBook/media/v4l/vidioc-streamon.xml | 8 
 drivers/media/media-entity.c| 2 +-
 drivers/media/v4l2-core/v4l2-subdev.c   | 4 ++--
 3 files changed, 11 insertions(+), 3 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 2/2] [media] DocBook: update error code in videoc-streamon

2016-03-30 Thread Helen Mae Koike Fornazier
Add description of ENOLINK error

Signed-off-by: Helen Mae Koike Fornazier 
Acked-by: Sakari Ailus 
---

Changes since v3:
* ..."pipeline configuration"... to ..."pipeline link configuration"...
* Added Acked-by

The patch is based on 'media/master' branch and available at
https://github.com/helen-fornazier/opw-staging media/devel

 Documentation/DocBook/media/v4l/vidioc-streamon.xml | 8 
 1 file changed, 8 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/vidioc-streamon.xml 
b/Documentation/DocBook/media/v4l/vidioc-streamon.xml
index df2c63d..89fd7ce 100644
--- a/Documentation/DocBook/media/v4l/vidioc-streamon.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-streamon.xml
@@ -123,6 +123,14 @@ synchronize with other events.
  

   
+  
+   ENOLINK
+   
+ The driver implements Media Controller interface and
+ the pipeline link configuration is invalid.
+ 
+   
+  
 
   
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 2/2] [media] DocBook: update error code in videoc-streamon

2016-03-30 Thread Sakari Ailus

Hi Helen,

Helen Mae Koike Fornazier wrote:

Add description of ENOLINK error

Signed-off-by: Helen Mae Koike Fornazier 
---

The patch set is based on 'media/master' branch and available at
 https://github.com/helen-fornazier/opw-staging media/devel

Changes since v2:
* this is a new commit in the set

  Documentation/DocBook/media/v4l/vidioc-streamon.xml | 8 
  1 file changed, 8 insertions(+)

diff --git a/Documentation/DocBook/media/v4l/vidioc-streamon.xml 
b/Documentation/DocBook/media/v4l/vidioc-streamon.xml
index df2c63d..c4b88b0 100644
--- a/Documentation/DocBook/media/v4l/vidioc-streamon.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-streamon.xml
@@ -123,6 +123,14 @@ synchronize with other events.
  


+  
+   ENOLINK
+   
+ The driver implements Media Controller interface and
+ the pipeline configuration is invalid.


...pipeline link configuration...

Then it's apparent this is really about links (and not e.g. about formats).

With that,

Acked-by: Sakari Ailus 


+ 
+   
+  
  

  




--
Kind regards,

Sakari Ailus
sakari.ai...@linux.intel.com
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 1/2] [media] media: change pipeline validation return error

2016-03-30 Thread Helen Mae Koike Fornazier
According to the V4L2 API, the VIDIOC_STREAMON ioctl should return EPIPE
if there is a format mismatch in the pipeline configuration.

As the .vidioc_streamon in the v4l2_ioctl_ops usually forwards the error
caused by the v4l2_subdev_link_validate_default (if it is in use), it
should return -EPIPE when it detect the mismatch.

When an entity is connected to a non enabled link,
media_entity_pipeline_start should return -ENOLINK, as the link does not
exist.

Signed-off-by: Helen Mae Koike Fornazier 
Acked-by: Sakari Ailus 
---

The patch is based on 'media/master' branch and available at
https://github.com/helen-fornazier/opw-staging media/devel

Changes since v2:
* Added Ack by Sakari

 drivers/media/media-entity.c  | 2 +-
 drivers/media/v4l2-core/v4l2-subdev.c | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index c53c1d5..d8a2299 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -445,7 +445,7 @@ __must_check int __media_entity_pipeline_start(struct 
media_entity *entity,
bitmap_or(active, active, has_no_links, entity->num_pads);
 
if (!bitmap_full(active, entity->num_pads)) {
-   ret = -EPIPE;
+   ret = -ENOLINK;
dev_dbg(entity->graph_obj.mdev->dev,
"\"%s\":%u must be connected by an enabled 
link\n",
entity->name,
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c 
b/drivers/media/v4l2-core/v4l2-subdev.c
index d630838..918e79d 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -508,7 +508,7 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev 
*sd,
if (source_fmt->format.width != sink_fmt->format.width
|| source_fmt->format.height != sink_fmt->format.height
|| source_fmt->format.code != sink_fmt->format.code)
-   return -EINVAL;
+   return -EPIPE;
 
/* The field order must match, or the sink field order must be NONE
 * to support interlaced hardware connected to bridges that support
@@ -516,7 +516,7 @@ int v4l2_subdev_link_validate_default(struct v4l2_subdev 
*sd,
 */
if (source_fmt->format.field != sink_fmt->format.field &&
sink_fmt->format.field != V4L2_FIELD_NONE)
-   return -EINVAL;
+   return -EPIPE;
 
return 0;
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 0/2] media: updating error codes on streamon

2016-03-30 Thread Helen Mae Koike Fornazier
Fix error code on streamon

The patch set is based on 'media/master' branch and available at
https://github.com/helen-fornazier/opw-staging media/devel

Changes since v2:

  [media] media: change pipeline validation return error
* Added Ack by Sakari

  Updated the DocBook in the commit:
[media] DocBook: update error code in videoc-streamon


Helen Mae Koike Fornazier (2):
  [media] media: change pipeline validation return error
  [media] DocBook: update error code in videoc-streamon

 Documentation/DocBook/media/v4l/vidioc-streamon.xml | 8 
 drivers/media/media-entity.c| 2 +-
 drivers/media/v4l2-core/v4l2-subdev.c   | 4 ++--
 3 files changed, 11 insertions(+), 3 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 4/7] scatterlist: add sg_alloc_table_from_buf() helper

2016-03-30 Thread Mark Brown
On Wed, Mar 30, 2016 at 08:18:31PM +0200, Boris Brezillon wrote:

> BTW, do you see other things that should be added in sg_constraints?

It looked to do everything SPI does which is everything I know about.


signature.asc
Description: PGP signature


Re: [PATCH v2 4/7] scatterlist: add sg_alloc_table_from_buf() helper

2016-03-30 Thread Boris Brezillon
On Wed, 30 Mar 2016 09:51:43 -0700
Mark Brown  wrote:

> On Wed, Mar 30, 2016 at 05:39:51PM +0200, Boris Brezillon wrote:
> > sg_alloc_table_from_buf() provides an easy solution to create an sg_table
> > from a virtual address pointer. This function takes care of dealing with
> > vmallocated buffers, buffer alignment, or DMA engine limitations (maximum
> > DMA transfer size).
> 
> This seems nice.  Should we also have a further helper on top of this
> which will get constraints from a dmaengine, it seems like it'd be a
> common need?

Yep, we could create a wrapper extracting dma_slave caps info,
converting it to sg_constraints and calling sg_alloc_table_from_buf().
But let's try to get this function accepted first, and I'll send another
patch providing this wrapper.

BTW, do you see other things that should be added in sg_constraints?

-- 
Boris Brezillon, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 4/7] scatterlist: add sg_alloc_table_from_buf() helper

2016-03-30 Thread Mark Brown
On Wed, Mar 30, 2016 at 05:39:51PM +0200, Boris Brezillon wrote:
> sg_alloc_table_from_buf() provides an easy solution to create an sg_table
> from a virtual address pointer. This function takes care of dealing with
> vmallocated buffers, buffer alignment, or DMA engine limitations (maximum
> DMA transfer size).

This seems nice.  Should we also have a further helper on top of this
which will get constraints from a dmaengine, it seems like it'd be a
common need?


signature.asc
Description: PGP signature


[PATCH v2 7/7] mtd: nand: sunxi: update DT bindings

2016-03-30 Thread Boris Brezillon
Document dmas and dma-names properties.

Signed-off-by: Boris Brezillon 
Acked-by: Rob Herring 
---
 Documentation/devicetree/bindings/mtd/sunxi-nand.txt | 4 
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/sunxi-nand.txt 
b/Documentation/devicetree/bindings/mtd/sunxi-nand.txt
index 086d6f4..6fdf8f6 100644
--- a/Documentation/devicetree/bindings/mtd/sunxi-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/sunxi-nand.txt
@@ -11,6 +11,10 @@ Required properties:
 * "ahb" : AHB gating clock
 * "mod" : nand controller clock
 
+Optional properties:
+- dmas : shall reference DMA channel associated to the NAND controller.
+- dma-names : shall be "rxtx".
+
 Optional children nodes:
 Children nodes represent the available nand chips.
 
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 0/7] mtd: nand: sunxi: add support for DMA operations

2016-03-30 Thread Boris Brezillon
Hello,

This patch series aims at adding support for DMA assisted operations to
the sunxi_nand driver.

The first 3 patches are just reworks in the existing driver preparing
things for DMA ->read/write_page() operations. Those ones are mainly
re-arranging existing functions, and moving some code into dedicated
functions so we can reuse them when adding the read/write_page()
implementation.

Patch 4 is an attempt to generalize some logic that are duplicated in a
lot of places. It provides a generic solution to create an SG table
from a buffer (passed by virtual address) and its length.
This generic implementation tries to take all possible constraints into
account, like:
- vmallocated buffers
- alignement requirement/preference
- maximum DMA transfer length

I may have missed other things (is there a need for a minimum DMA
transfer constraint?), so don't hesitate to point problems or missing
elements in this implementation.
Note that other subsystems doing the same kind of thing (like SPI of V4L)
could use this implementation. This is why I've put the SPI and V4L
maintainers in Cc.

Patch 5 is providing functions to map/unmap buffers for DMA operations
at the MTD level. This will hopefully limit the number of open-coded
implementations we're currently seeing in a lot of NAND drivers.
Of course, it's making use of sg_alloc_table_from_buf(), introduced in
patch 4.

Patch 6 and 7 are patching the sunxi NAND driver and its DT binding doc
to add DMA support.

I'm particularly interested in getting feedbacks on patch 4 and 5.
Is there a reason nobody ever tried to create such generic functions
(at the scatterlist and MTD levels), and if there are, could you detail
them?

Thanks,

Boris

Side note: patches touching the sunxi NAND driver are depending on
this series [1].

[1]https://lkml.org/lkml/2016/3/7/444

Changes since v1:
- reworked sg_alloc_table_from_buf() to avoid splitting contiguous
  vmalloced area
- fixed a bug in the read_dma()
- fixed dma_direction flag in write_dma()

Boris Brezillon (7):
  mtd: nand: sunxi: move some ECC related operations to their own
functions
  mtd: nand: sunxi: make OOB retrieval optional
  mtd: nand: sunxi: make cur_off parameter optional in extra oob helpers
  scatterlist: add sg_alloc_table_from_buf() helper
  mtd: provide helper to prepare buffers for DMA operations
  mtd: nand: sunxi: add support for DMA assisted operations
  mtd: nand: sunxi: update DT bindings

 .../devicetree/bindings/mtd/sunxi-nand.txt |   4 +
 drivers/mtd/mtdcore.c  |  66 +++
 drivers/mtd/nand/sunxi_nand.c  | 505 ++---
 include/linux/mtd/mtd.h|  25 +
 include/linux/scatterlist.h|  24 +
 lib/scatterlist.c  | 161 +++
 6 files changed, 720 insertions(+), 65 deletions(-)

-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 4/7] scatterlist: add sg_alloc_table_from_buf() helper

2016-03-30 Thread Boris Brezillon
sg_alloc_table_from_buf() provides an easy solution to create an sg_table
from a virtual address pointer. This function takes care of dealing with
vmallocated buffers, buffer alignment, or DMA engine limitations (maximum
DMA transfer size).

Signed-off-by: Boris Brezillon 
---
 include/linux/scatterlist.h |  24 +++
 lib/scatterlist.c   | 161 
 2 files changed, 185 insertions(+)

diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index 556ec1e..4a75362 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -41,6 +41,27 @@ struct sg_table {
unsigned int orig_nents;/* original size of list */
 };
 
+/**
+ * struct sg_constraints - SG constraints structure
+ *
+ * @max_chunk_len: maximum chunk buffer length. Each SG entry has to be smaller
+ *than this value. Zero means no constraint.
+ * @required_alignment: minimum alignment. Is used for both size and pointer
+ * alignment. If this constraint is not met, the function
+ * should return -EINVAL.
+ * @preferred_alignment: preferred alignment. Mainly used to optimize
+ *  throughput when the DMA engine performs better when
+ *  doing aligned accesses.
+ *
+ * This structure is here to help sg_alloc_table_from_buf() create the optimal
+ * SG list based on DMA engine constraints.
+ */
+struct sg_constraints {
+   size_t max_chunk_len;
+   size_t required_alignment;
+   size_t preferred_alignment;
+};
+
 /*
  * Notes on SG table design.
  *
@@ -265,6 +286,9 @@ int sg_alloc_table_from_pages(struct sg_table *sgt,
struct page **pages, unsigned int n_pages,
unsigned long offset, unsigned long size,
gfp_t gfp_mask);
+int sg_alloc_table_from_buf(struct sg_table *sgt, const void *buf, size_t len,
+   const struct sg_constraints *constraints,
+   gfp_t gfp_mask);
 
 size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf,
  size_t buflen, off_t skip, bool to_buffer);
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 004fc70..94776ff 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -433,6 +433,167 @@ int sg_alloc_table_from_pages(struct sg_table *sgt,
 }
 EXPORT_SYMBOL(sg_alloc_table_from_pages);
 
+static size_t sg_buf_chunk_len(const void *buf, size_t len,
+  const struct sg_constraints *cons)
+{
+   size_t chunk_len = len;
+
+   if (cons->max_chunk_len)
+   chunk_len = min_t(size_t, chunk_len, cons->max_chunk_len);
+
+   if (is_vmalloc_addr(buf)) {
+   unsigned long offset_in_page = offset_in_page(buf);
+   size_t contig_len = PAGE_SIZE - offset_in_page;
+   unsigned long phys = vmalloc_to_pfn(buf) - offset_in_page;
+   const void *contig_ptr = buf + contig_len;
+
+   /*
+* Vmalloced buffer might be composed of several physically
+* contiguous pages. Avoid extra scattergather entries in
+* this case.
+*/
+   while (contig_len < chunk_len) {
+   if (phys + PAGE_SIZE != vmalloc_to_pfn(contig_ptr))
+   break;
+
+   contig_len += PAGE_SIZE;
+   contig_ptr += PAGE_SIZE;
+   phys += PAGE_SIZE;
+   }
+
+   chunk_len = min_t(size_t, chunk_len, contig_len);
+   }
+
+   if (!IS_ALIGNED((unsigned long)buf, cons->preferred_alignment)) {
+   const void *aligned_buf = PTR_ALIGN(buf,
+   cons->preferred_alignment);
+   size_t unaligned_len = (unsigned long)(aligned_buf - buf);
+
+   chunk_len = min_t(size_t, chunk_len, unaligned_len);
+   } else if (chunk_len > cons->preferred_alignment) {
+   chunk_len &= ~(cons->preferred_alignment - 1);
+   }
+
+   return chunk_len;
+}
+
+#define sg_for_each_chunk_in_buf(buf, len, chunk_len, constraints) \
+   for (chunk_len = sg_buf_chunk_len(buf, len, constraints);   \
+len;   \
+len -= chunk_len, buf += chunk_len,\
+chunk_len = sg_buf_chunk_len(buf, len, constraints))
+
+static int sg_check_constraints(struct sg_constraints *cons,
+   const void *buf, size_t len)
+{
+   if (!cons->required_alignment)
+   cons->required_alignment = 1;
+
+   if (!cons->preferred_alignment)
+   cons->preferred_alignment = cons->required_alignment;
+
+   /* Test if buf and len are properly aligned. */
+   if (!IS_ALIGNED((unsigned long)buf, cons->required_alignment) ||

[PATCH v2 5/7] mtd: provide helper to prepare buffers for DMA operations

2016-03-30 Thread Boris Brezillon
Some NAND controller drivers are making use of DMA to transfer data from
the controller to the buffer passed by the MTD user.
Provide a generic mtd_map/unmap_buf() implementation to avoid open coded
(and sometime erroneous) implementations.

Signed-off-by: Boris Brezillon 
---
 drivers/mtd/mtdcore.c   | 66 +
 include/linux/mtd/mtd.h | 25 +++
 2 files changed, 91 insertions(+)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 3096251..3c368f0 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1253,6 +1253,72 @@ void *mtd_kmalloc_up_to(const struct mtd_info *mtd, 
size_t *size)
 }
 EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to);
 
+#ifdef CONFIG_HAS_DMA
+/**
+ * mtd_map_buf - create an SG table and prepare it for DMA operations
+ *
+ * @mtd: mtd device description object pointer
+ * @dev: device handling the DMA operation
+ * @buf: buf used to create the SG table
+ * @len: length of buf
+ * @constraints: optional constraints to take into account when creating
+ *  the SG table. Can be NULL if no specific constraints
+ *  are required.
+ * @dir: direction of the DMA operation
+ *
+ * This function should be used when an MTD driver wants to do DMA operations
+ * on a buffer passed by the MTD layer. This functions takes care of
+ * vmallocated buffer constraints, and return and sg_table that you can safely
+ * use.
+ */
+int mtd_map_buf(struct mtd_info *mtd, struct device *dev,
+   struct sg_table *sgt, const void *buf, size_t len,
+   const struct sg_constraints *constraints,
+   enum dma_data_direction dir)
+{
+   int ret;
+
+   ret = sg_alloc_table_from_buf(sgt, buf, len, constraints, GFP_KERNEL);
+   if (ret)
+   return ret;
+
+   ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir);
+   if (!ret)
+   ret = -ENOMEM;
+
+   if (ret < 0) {
+   sg_free_table(sgt);
+   return ret;
+   }
+
+   sgt->nents = ret;
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(mtd_map_buf);
+
+/**
+ * mtd_map_buf - unmap an SG table and release its resources
+ *
+ * @mtd: mtd device description object pointer
+ * @dev: device handling the DMA operation
+ * @sgt: SG table
+ * @dir: direction of the DMA operation
+ *
+ * This function unmaps a previously mapped SG table and release SG table
+ * resources. Should be called when your DMA operation is done.
+ */
+void mtd_unmap_buf(struct mtd_info *mtd, struct device *dev,
+  struct sg_table *sgt, enum dma_data_direction dir)
+{
+   if (sgt->orig_nents) {
+   dma_unmap_sg(dev, sgt->sgl, sgt->orig_nents, dir);
+   sg_free_table(sgt);
+   }
+}
+EXPORT_SYMBOL_GPL(mtd_unmap_buf);
+#endif /* !CONFIG_HAS_DMA */
+
 #ifdef CONFIG_PROC_FS
 
 /**/
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 7712721..15cff85 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -410,6 +411,30 @@ extern void register_mtd_user (struct mtd_notifier *new);
 extern int unregister_mtd_user (struct mtd_notifier *old);
 void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
 
+#ifdef CONFIG_HAS_DMA
+int mtd_map_buf(struct mtd_info *mtd, struct device *dev,
+   struct sg_table *sgt, const void *buf, size_t len,
+   const struct sg_constraints *constraints,
+   enum dma_data_direction dir);
+void mtd_unmap_buf(struct mtd_info *mtd, struct device *dev,
+  struct sg_table *sgt, enum dma_data_direction dir);
+#else
+static inline int mtd_map_buf(struct mtd_info *mtd, struct device *dev,
+ struct sg_table *sgt, const void *buf,
+ size_t len,
+ const struct sg_constraints *constraints
+ enum dma_data_direction dir)
+{
+   return -ENOTSUPP;
+}
+
+static void mtd_unmap_buf(struct mtd_info *mtd, struct device *dev,
+ struct sg_table *sgt, enum dma_data_direction dir)
+{
+   return -ENOTSUPP;
+}
+#endif
+
 void mtd_erase_callback(struct erase_info *instr);
 
 static inline int mtd_is_bitflip(int err) {
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 6/7] mtd: nand: sunxi: add support for DMA assisted operations

2016-03-30 Thread Boris Brezillon
The sunxi NAND controller is able to pipeline ECC operations only when
operated in DMA mode, which improves a lot NAND throughput while keeping
CPU usage low.

Signed-off-by: Boris Brezillon 
---
 drivers/mtd/nand/sunxi_nand.c | 324 +-
 1 file changed, 320 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index 6d6b166..1029f28 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -154,6 +154,7 @@
 
 /* define bit use in NFC_ECC_ST */
 #define NFC_ECC_ERR(x) BIT(x)
+#define NFC_ECC_ERR_MSKGENMASK(15, 0)
 #define NFC_ECC_PAT_FOUND(x)   BIT(x + 16)
 #define NFC_ECC_ERR_CNT(b, x)  (((x) >> (((b) % 4) * 8)) & 0xff)
 
@@ -277,6 +278,7 @@ struct sunxi_nfc {
unsigned long clk_rate;
struct list_head chips;
struct completion complete;
+   struct dma_chan *dmac;
 };
 
 static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_hw_control *ctrl)
@@ -369,6 +371,68 @@ static int sunxi_nfc_rst(struct sunxi_nfc *nfc)
return ret;
 }
 
+static int sunxi_nfc_dma_op_prepare(struct mtd_info *mtd, const void *buf,
+   int chunksize, int nchunks,
+   enum dma_data_direction ddir,
+   struct sg_table *sgt)
+{
+   struct nand_chip *nand = mtd_to_nand(mtd);
+   struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+   struct dma_async_tx_descriptor *dmad;
+   enum dma_transfer_direction tdir;
+   dma_cookie_t dmat;
+   int ret;
+
+   if (ddir == DMA_FROM_DEVICE)
+   tdir = DMA_DEV_TO_MEM;
+   else
+   tdir = DMA_MEM_TO_DEV;
+
+   ret = mtd_map_buf(mtd, nfc->dev, sgt, buf, nchunks * chunksize,
+ NULL, ddir);
+   if (ret)
+   return ret;
+
+   dmad = dmaengine_prep_slave_sg(nfc->dmac, sgt->sgl, sgt->nents,
+  tdir, DMA_CTRL_ACK);
+   if (IS_ERR(dmad)) {
+   ret = PTR_ERR(dmad);
+   goto err_unmap_buf;
+   }
+
+   writel(readl(nfc->regs + NFC_REG_CTL) | NFC_RAM_METHOD,
+  nfc->regs + NFC_REG_CTL);
+   writel(nchunks, nfc->regs + NFC_REG_SECTOR_NUM);
+   writel(chunksize, nfc->regs + NFC_REG_CNT);
+   dmat = dmaengine_submit(dmad);
+
+   ret = dma_submit_error(dmat);
+   if (ret)
+   goto err_clr_dma_flag;
+
+   return 0;
+
+err_clr_dma_flag:
+   writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD,
+  nfc->regs + NFC_REG_CTL);
+
+err_unmap_buf:
+   mtd_unmap_buf(mtd, nfc->dev, sgt, ddir);
+   return ret;
+}
+
+static void sunxi_nfc_dma_op_cleanup(struct mtd_info *mtd,
+enum dma_data_direction ddir,
+struct sg_table *sgt)
+{
+   struct nand_chip *nand = mtd_to_nand(mtd);
+   struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+
+   mtd_unmap_buf(mtd, nfc->dev, sgt, ddir);
+   writel(readl(nfc->regs + NFC_REG_CTL) & ~NFC_RAM_METHOD,
+  nfc->regs + NFC_REG_CTL);
+}
+
 static int sunxi_nfc_dev_ready(struct mtd_info *mtd)
 {
struct nand_chip *nand = mtd_to_nand(mtd);
@@ -970,6 +1034,128 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct 
mtd_info *mtd,
*cur_off = mtd->oobsize + mtd->writesize;
 }
 
+static int sunxi_nfc_hw_ecc_read_chunks_dma(struct mtd_info *mtd, uint8_t *buf,
+   int oob_required, int page,
+   int nchunks)
+{
+   struct nand_chip *nand = mtd_to_nand(mtd);
+   bool randomized = nand->options & NAND_NEED_SCRAMBLING;
+   struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+   struct nand_ecc_ctrl *ecc = >ecc;
+   unsigned int max_bitflips = 0;
+   int ret, i, raw_mode = 0;
+   struct sg_table sgt;
+   u32 status;
+
+   ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
+   if (ret)
+   return ret;
+
+   ret = sunxi_nfc_dma_op_prepare(mtd, buf, ecc->size, nchunks,
+  DMA_FROM_DEVICE, );
+   if (ret)
+   return ret;
+
+   sunxi_nfc_hw_ecc_enable(mtd);
+   sunxi_nfc_randomizer_config(mtd, page, false);
+   sunxi_nfc_randomizer_enable(mtd);
+
+   writel((NAND_CMD_RNDOUTSTART << 16) | (NAND_CMD_RNDOUT << 8) |
+  NAND_CMD_READSTART, nfc->regs + NFC_REG_RCMD_SET);
+
+   dma_async_issue_pending(nfc->dmac);
+
+   writel(NFC_PAGE_OP | NFC_DATA_SWAP_METHOD | NFC_DATA_TRANS,
+  nfc->regs + NFC_REG_CMD);
+
+   ret = sunxi_nfc_wait_events(nfc, NFC_CMD_INT_FLAG, true, 0);
+   if (ret)
+   dmaengine_terminate_all(nfc->dmac);
+
+   sunxi_nfc_randomizer_disable(mtd);
+   

[PATCH v2 3/7] mtd: nand: sunxi: make cur_off parameter optional in extra oob helpers

2016-03-30 Thread Boris Brezillon
Allow for NULL cur_offs values when the caller does not know where the
NAND page register pointer point to.

Signed-off-by: Boris Brezillon 
---
 drivers/mtd/nand/sunxi_nand.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index 3e7b919..6d6b166 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -956,7 +956,7 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info 
*mtd,
if (len <= 0)
return;
 
-   if (*cur_off != offset)
+   if (!cur_off || *cur_off != offset)
nand->cmdfunc(mtd, NAND_CMD_RNDOUT,
  offset + mtd->writesize, -1);
 
@@ -966,7 +966,8 @@ static void sunxi_nfc_hw_ecc_read_extra_oob(struct mtd_info 
*mtd,
sunxi_nfc_randomizer_read_buf(mtd, oob + offset, len,
  false, page);
 
-   *cur_off = mtd->oobsize + mtd->writesize;
+   if (cur_off)
+   *cur_off = mtd->oobsize + mtd->writesize;
 }
 
 static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
@@ -1021,13 +1022,14 @@ static void sunxi_nfc_hw_ecc_write_extra_oob(struct 
mtd_info *mtd,
if (len <= 0)
return;
 
-   if (*cur_off != offset)
+   if (!cur_off || *cur_off != offset)
nand->cmdfunc(mtd, NAND_CMD_RNDIN,
  offset + mtd->writesize, -1);
 
sunxi_nfc_randomizer_write_buf(mtd, oob + offset, len, false, page);
 
-   *cur_off = mtd->oobsize + mtd->writesize;
+   if (cur_off)
+   *cur_off = mtd->oobsize + mtd->writesize;
 }
 
 static int sunxi_nfc_hw_ecc_read_page(struct mtd_info *mtd,
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/7] mtd: nand: sunxi: make OOB retrieval optional

2016-03-30 Thread Boris Brezillon
sunxi_nfc_hw_ecc_read_chunk() always retrieves the ECC and protected free
bytes, no matter if the user really asked for it or not. This can take a
non negligible amount of time, especially on NAND chips exposing large OOB
areas (> 1KB). Make it optional.

Signed-off-by: Boris Brezillon 
---
 drivers/mtd/nand/sunxi_nand.c | 26 +++---
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index f6ea0fb..3e7b919 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -867,7 +867,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
   u8 *oob, int oob_off,
   int *cur_off,
   unsigned int *max_bitflips,
-  bool bbm, int page)
+  bool bbm, bool oob_required, int page)
 {
struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
@@ -899,7 +899,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
 
*cur_off = oob_off + ecc->bytes + 4;
 
-   ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob, 0,
+   ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob_required ? oob : NULL, 0,
   readl(nfc->regs + NFC_REG_ECC_ST),
   );
if (erased)
@@ -929,12 +929,14 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info 
*mtd,
} else {
memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
 
-   nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
-   sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4,
- true, page);
+   if (oob_required) {
+   nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
+   sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4,
+ true, page);
 
-   sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, 0,
-   bbm, page);
+   sunxi_nfc_hw_ecc_get_prot_oob_bytes(mtd, oob, 0,
+   bbm, page);
+   }
}
 
sunxi_nfc_hw_ecc_update_stats(mtd, max_bitflips, ret);
@@ -1048,7 +1050,7 @@ static int sunxi_nfc_hw_ecc_read_page(struct mtd_info 
*mtd,
ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
  oob_off + mtd->writesize,
  _off, _bitflips,
- !i, page);
+ !i, oob_required, page);
if (ret < 0)
return ret;
else if (ret)
@@ -1086,8 +1088,8 @@ static int sunxi_nfc_hw_ecc_read_subpage(struct mtd_info 
*mtd,
ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off,
  oob,
  oob_off + mtd->writesize,
- _off, _bitflips,
- !i, page);
+ _off, _bitflips, !i,
+ false, page);
if (ret < 0)
return ret;
}
@@ -1149,7 +1151,9 @@ static int sunxi_nfc_hw_syndrome_ecc_read_page(struct 
mtd_info *mtd,
 
ret = sunxi_nfc_hw_ecc_read_chunk(mtd, data, data_off, oob,
  oob_off, _off,
- _bitflips, !i, page);
+ _bitflips, !i,
+ oob_required,
+ page);
if (ret < 0)
return ret;
else if (ret)
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/7] mtd: nand: sunxi: move some ECC related operations to their own functions

2016-03-30 Thread Boris Brezillon
In order to support DMA operations in a clean way we need to extract some
of the logic coded in sunxi_nfc_hw_ecc_read/write_page() into their own
function.

Signed-off-by: Boris Brezillon 
---
 drivers/mtd/nand/sunxi_nand.c | 163 --
 1 file changed, 108 insertions(+), 55 deletions(-)

diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index a71905c..f6ea0fb 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -776,6 +776,92 @@ static inline void sunxi_nfc_user_data_to_buf(u32 
user_data, u8 *buf)
buf[3] = user_data >> 24;
 }
 
+static inline u32 sunxi_nfc_buf_to_user_data(const u8 *buf)
+{
+   return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
+}
+
+static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct mtd_info *mtd, u8 *oob,
+   int step, bool bbm, int page)
+{
+   struct nand_chip *nand = mtd_to_nand(mtd);
+   struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+
+   sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)),
+  oob);
+
+   /* De-randomize the Bad Block Marker. */
+   if (bbm && (nand->options & NAND_NEED_SCRAMBLING))
+   sunxi_nfc_randomize_bbm(mtd, page, oob);
+}
+
+static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct mtd_info *mtd,
+   const u8 *oob, int step,
+   bool bbm, int page)
+{
+   struct nand_chip *nand = mtd_to_nand(mtd);
+   struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+   u8 user_data[4];
+
+   /* Randomize the Bad Block Marker. */
+   if (bbm && (nand->options & NAND_NEED_SCRAMBLING)) {
+   memcpy(user_data, oob, sizeof(user_data));
+   sunxi_nfc_randomize_bbm(mtd, page, user_data);
+   oob = user_data;
+   }
+
+   writel(sunxi_nfc_buf_to_user_data(oob),
+  nfc->regs + NFC_REG_USER_DATA(step));
+}
+
+static void sunxi_nfc_hw_ecc_update_stats(struct mtd_info *mtd,
+ unsigned int *max_bitflips, int ret)
+{
+   if (ret < 0) {
+   mtd->ecc_stats.failed++;
+   } else {
+   mtd->ecc_stats.corrected += ret;
+   *max_bitflips = max_t(unsigned int, *max_bitflips, ret);
+   }
+}
+
+static int sunxi_nfc_hw_ecc_correct(struct mtd_info *mtd, u8 *data, u8 *oob,
+   int step, u32 status, bool *erased)
+{
+   struct nand_chip *nand = mtd_to_nand(mtd);
+   struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+   struct nand_ecc_ctrl *ecc = >ecc;
+   u32 tmp;
+
+   *erased = false;
+
+   if (status & NFC_ECC_ERR(step))
+   return -EBADMSG;
+
+   if (status & NFC_ECC_PAT_FOUND(step)) {
+   u8 pattern;
+
+   if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) {
+   pattern = 0x0;
+   } else {
+   pattern = 0xff;
+   *erased = true;
+   }
+
+   if (data)
+   memset(data, pattern, ecc->size);
+
+   if (oob)
+   memset(oob, pattern, ecc->bytes + 4);
+
+   return 0;
+   }
+
+   tmp = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(step));
+
+   return NFC_ECC_ERR_CNT(step, tmp);
+}
+
 static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
   u8 *data, int data_off,
   u8 *oob, int oob_off,
@@ -787,7 +873,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
struct nand_ecc_ctrl *ecc = >ecc;
int raw_mode = 0;
-   u32 status;
+   bool erased;
int ret;
 
if (*cur_off != data_off)
@@ -813,27 +899,13 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info 
*mtd,
 
*cur_off = oob_off + ecc->bytes + 4;
 
-   status = readl(nfc->regs + NFC_REG_ECC_ST);
-   if (status & NFC_ECC_PAT_FOUND(0)) {
-   u8 pattern = 0xff;
-
-   if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1)))
-   pattern = 0x0;
-
-   memset(data, pattern, ecc->size);
-   memset(oob, pattern, ecc->bytes + 4);
-
+   ret = sunxi_nfc_hw_ecc_correct(mtd, data, oob, 0,
+  readl(nfc->regs + NFC_REG_ECC_ST),
+  );
+   if (erased)
return 1;
-   }
-
-   ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(0)));
-
-   memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
 
-   nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
-   

Re: [PATCH v2] [media] media: change pipeline validation return error

2016-03-30 Thread Sakari Ailus
Hi Helen,

On Tue, Mar 29, 2016 at 08:49:47PM -0300, Helen Mae Koike Fornazier wrote:
> According to the V4L2 API, the VIDIOC_STREAMON ioctl should return EPIPE
> if there is a format mismatch in the pipeline configuration.
> 
> As the .vidioc_streamon in the v4l2_ioctl_ops usually forwards the error
> caused by the v4l2_subdev_link_validate_default (if it is in use), it
> should return -EPIPE when it detect the mismatch.
> 
> When an entity is connected to a non enabled link,
> media_entity_pipeline_start should return -ENOLINK, as the link does not
> exist.
> 
> Signed-off-by: Helen Mae Koike Fornazier 

Acked-by: Sakari Ailus 

While at it, could you change the documentation of VIDIOC_STREAMON as well?
It documents EPIPE but no ENOLINK. I think it could be e.g.

"The driver implements Media controller interface and the pipeline link
configuration is invalid."

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ai...@iki.fi XMPP: sai...@retiisi.org.uk
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html