Re: [Xen-devel][RFC 3/3] xen/gntdev: Add support for Linux dma buffers

2018-05-21 Thread Oleksandr Andrushchenko

On 05/22/2018 12:31 AM, Dongwon Kim wrote:

Still need more time to review the whole code changes

Take your time, I just wanted to make sure that all interested parties
are in the discussion, so we all finally have what we all want, not
a thing covering only my use-cases

  but I noticed one thing.

We've been using the term "hyper_dmabuf" for hypervisor-agnostic linux dmabuf
solution and we are planning to call any of our future solution for other
hypervisors the same name. So having same name for this xen-specific structure
or functions you implemented is confusing. Would you change it to something
else like... "xen_"?

Np, will rename


On Thu, May 17, 2018 at 11:26:04AM +0300, Oleksandr Andrushchenko wrote:

From: Oleksandr Andrushchenko 

Signed-off-by: Oleksandr Andrushchenko 
---
  drivers/xen/gntdev.c  | 954 +-
  include/uapi/xen/gntdev.h | 101 
  include/xen/gntdev_exp.h  |  23 +
  3 files changed, 1066 insertions(+), 12 deletions(-)
  create mode 100644 include/xen/gntdev_exp.h

diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 9510f228efe9..0ee88e193362 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -4,6 +4,8 @@
   * Device for accessing (in user-space) pages that have been granted by other
   * domains.
   *
+ * DMA buffer implementation is based on drivers/gpu/drm/drm_prime.c.
+ *
   * Copyright (c) 2006-2007, D G Murray.
   *   (c) 2009 Gerd Hoffmann 
   *
@@ -37,6 +39,9 @@
  #include 
  #include 
  
+#include 

+#include 
+
  #include 
  #include 
  #include 
@@ -61,16 +66,39 @@ static atomic_t pages_mapped = ATOMIC_INIT(0);
  static int use_ptemod;
  #define populate_freeable_maps use_ptemod
  
+#ifndef GRANT_INVALID_REF

+/*
+ * Note on usage of grant reference 0 as invalid grant reference:
+ * grant reference 0 is valid, but never exposed to a driver,
+ * because of the fact it is already in use/reserved by the PV console.
+ */
+#define GRANT_INVALID_REF  0
+#endif
+
  struct gntdev_priv {
/* maps with visible offsets in the file descriptor */
struct list_head maps;
/* maps that are not visible; will be freed on munmap.
 * Only populated if populate_freeable_maps == 1 */
struct list_head freeable_maps;
+   /* List of dma-bufs. */
+   struct list_head dma_bufs;
/* lock protects maps and freeable_maps */
struct mutex lock;
struct mm_struct *mm;
struct mmu_notifier mn;
+
+   /* Private data of the hyper DMA buffers. */
+
+   struct device *dev;
+   /* List of exported DMA buffers. */
+   struct list_head dmabuf_exp_list;
+   /* List of wait objects. */
+   struct list_head dmabuf_exp_wait_list;
+   /* List of imported DMA buffers. */
+   struct list_head dmabuf_imp_list;
+   /* This is the lock which protects dma_buf_xxx lists. */
+   struct mutex dmabuf_lock;
  };
  
  struct unmap_notify {

@@ -95,10 +123,65 @@ struct grant_map {
struct gnttab_unmap_grant_ref *kunmap_ops;
struct page **pages;
unsigned long pages_vm_start;
+
+   /*
+* All the fields starting with dmabuf_ are only valid if this
+* mapping is used for exporting a DMA buffer.
+* If dmabuf_vaddr is not NULL then this mapping is backed by DMA
+* capable memory.
+*/
+
+   /* Flags used to create this DMA buffer: GNTDEV_DMABUF_FLAG_XXX. */
+   bool dmabuf_flags;
+   /* Virtual/CPU address of the DMA buffer. */
+   void *dmabuf_vaddr;
+   /* Bus address of the DMA buffer. */
+   dma_addr_t dmabuf_bus_addr;
+};
+
+struct hyper_dmabuf {
+   struct gntdev_priv *priv;
+   struct dma_buf *dmabuf;
+   struct list_head next;
+   int fd;
+
+   union {
+   struct {
+   /* Exported buffers are reference counted. */
+   struct kref refcount;
+   struct grant_map *map;
+   } exp;
+   struct {
+   /* Granted references of the imported buffer. */
+   grant_ref_t *refs;
+   /* Scatter-gather table of the imported buffer. */
+   struct sg_table *sgt;
+   /* dma-buf attachment of the imported buffer. */
+   struct dma_buf_attachment *attach;
+   } imp;
+   } u;
+
+   /* Number of pages this buffer has. */
+   int nr_pages;
+   /* Pages of this buffer. */
+   struct page **pages;
+};
+
+struct hyper_dmabuf_wait_obj {
+   struct list_head next;
+   struct hyper_dmabuf *hyper_dmabuf;
+   struct completion completion;
+};
+
+struct hyper_dambuf_attachment {

minor typo: dam->dma (same thing in other places as well.)

sure, thanks



+   struct sg_table *sgt;
+   enum dma_data_direction 

Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers

2018-05-21 Thread Oleksandr Andrushchenko

On 05/21/2018 11:36 PM, Boris Ostrovsky wrote:

On 05/21/2018 03:13 PM, Oleksandr Andrushchenko wrote:

On 05/21/2018 09:53 PM, Boris Ostrovsky wrote:

On 05/21/2018 01:32 PM, Oleksandr Andrushchenko wrote:

On 05/21/2018 07:35 PM, Boris Ostrovsky wrote:

On 05/21/2018 01:40 AM, Oleksandr Andrushchenko wrote:

On 05/19/2018 01:04 AM, Boris Ostrovsky wrote:

On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote:

From: Oleksandr Andrushchenko 

A commit message would be useful.

Sure, v1 will have it

Signed-off-by: Oleksandr Andrushchenko


     for (i = 0; i < nr_pages; i++) {
-    page = alloc_page(gfp);
-    if (page == NULL) {
-    nr_pages = i;
-    state = BP_EAGAIN;
-    break;
+    if (ext_pages) {
+    page = ext_pages[i];
+    } else {
+    page = alloc_page(gfp);
+    if (page == NULL) {
+    nr_pages = i;
+    state = BP_EAGAIN;
+    break;
+    }
     }
     scrub_page(page);
     list_add(>lru, );
@@ -529,7 +565,7 @@ static enum bp_state
decrease_reservation(unsigned long nr_pages, gfp_t gfp)
     i = 0;
     list_for_each_entry_safe(page, tmp, , lru) {
     /* XENMEM_decrease_reservation requires a GFN */
-    frame_list[i++] = xen_page_to_gfn(page);
+    frames[i++] = xen_page_to_gfn(page);
       #ifdef CONFIG_XEN_HAVE_PVMMU
     /*
@@ -552,18 +588,22 @@ static enum bp_state
decrease_reservation(unsigned long nr_pages, gfp_t gfp)
     #endif
     list_del(>lru);
     -    balloon_append(page);
+    if (!ext_pages)
+    balloon_append(page);

So what you are proposing is not really ballooning. You are just
piggybacking on existing interfaces, aren't you?

Sort of. Basically I need to {increase|decrease}_reservation, not
actually
allocating ballooned pages.
Do you think I can simply EXPORT_SYMBOL for
{increase|decrease}_reservation?
Any other suggestion?

I am actually wondering how much of that code you end up reusing. You
pretty much create new code paths in both routines and common code
ends
up being essentially the hypercall.

Well, I hoped that it would be easier to maintain if I modify existing
code
to support both use-cases, but I am also ok to create new routines if
this
seems to be reasonable - please let me know

    So the question is --- would it make
sense to do all of this separately from the balloon driver?

This can be done, but which driver will host this code then? If we
move from
the balloon driver, then this could go to either gntdev or grant-table.
What's your preference?

A separate module?
Is there any use for this feature outside of your zero-copy DRM driver?

Intel's hyper dma-buf (Dongwon/Matt CC'ed), V4L/GPU at least.

At the time I tried to upstream zcopy driver it was discussed and
decided that
it would be better if I remove all DRM specific code and move it to
Xen drivers.
Thus, this RFC.

But it can also be implemented as a dedicated Xen dma-buf driver which
will have all the
code from this RFC + a bit more (char/misc device handling at least).
This will also require a dedicated user-space library, just like
libxengnttab.so
for gntdev (now I have all new IOCTLs covered there).

If the idea of a dedicated Xen dma-buf driver seems to be more
attractive we
can work toward this solution. BTW, I do support this idea, but was not
sure if Xen community accepts yet another driver which duplicates
quite some code
of the existing gntdev/balloon/grant-table. And now after this RFC I
hope that all cons
and pros of both dedicated driver and gntdev/balloon/grant-table
extension are
clearly seen and we can make a decision.


IIRC the objection for a separate module was in the context of gntdev
was discussion, because (among other things) people didn't want to have
yet another file in /dev/xen/

Here we are talking about (a new) balloon-like module which doesn't
create any new user-visible interfaces. And as for duplicating code ---
as I said, I am not convinced there is much of duplication.

I might even argue that we should add a new config option for this module.

I am not quite sure I am fully following you here: so, you suggest
that we have balloon.c unchanged, but instead create a new
module (namely a file under the same folder as balloon.c, e.g.
dma-buf-reservation.c) and move those {increase|decrease}_reservation
routines (specific to dma-buf) to that new file? And make it selectable
via Kconfig? If so, then how about the changes to grant-table and gntdev?
Those will look inconsistent then.

If you suggest a new kernel driver module:
IMO, there is nothing bad if we create a dedicated kernel module
(driver) for Xen dma-buf handling selectable under Kconfig option.
Yes, this will create a yet another device under /dev/xen,
but most people will never see it if we set Kconfig to default to "n".
And then we'll need 

[PATCH v3] media: imx319: Add imx319 camera sensor driver

2018-05-21 Thread bingbu . cao
From: Bingbu Cao 

Add a V4L2 sub-device driver for the Sony IMX319 image sensor.
This is a camera sensor using the I2C bus for control and the
CSI-2 bus for data.

Signed-off-by: Bingbu Cao 
Signed-off-by: Tianshu Qiu 
---
 MAINTAINERS|7 +
 drivers/media/i2c/Kconfig  |   11 +
 drivers/media/i2c/Makefile |1 +
 drivers/media/i2c/imx319.c | 2434 
 4 files changed, 2453 insertions(+)
 create mode 100644 drivers/media/i2c/imx319.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e73a55a6a855..87b6c338d827 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13084,6 +13084,13 @@ S: Maintained
 F: drivers/media/i2c/imx274.c
 F: Documentation/devicetree/bindings/media/i2c/imx274.txt
 
+SONY IMX319 SENSOR DRIVER
+M: Bingbu Cao 
+L: linux-media@vger.kernel.org
+T: git git://linuxtv.org/media_tree.git
+S: Maintained
+F: drivers/media/i2c/imx319.c
+
 SONY MEMORYSTICK CARD SUPPORT
 M: Alex Dubov 
 W: http://tifmxx.berlios.de/
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 1f9d7c6aa31a..c3d279cc293e 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -604,6 +604,17 @@ config VIDEO_IMX274
  This is a V4L2 sensor-level driver for the Sony IMX274
  CMOS image sensor.
 
+config VIDEO_IMX319
+   tristate "Sony IMX319 sensor support"
+   depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+   depends on MEDIA_CAMERA_SUPPORT
+   help
+ This is a Video4Linux2 sensor driver for the Sony
+ IMX319 camera.
+
+ To compile this driver as a module, choose M here: the
+ module will be called imx319.
+
 config VIDEO_OV2640
tristate "OmniVision OV2640 sensor support"
depends on VIDEO_V4L2 && I2C
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 16fc34eda5cc..3adb3be4a486 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -104,5 +104,6 @@ obj-$(CONFIG_VIDEO_OV2659)  += ov2659.o
 obj-$(CONFIG_VIDEO_TC358743)   += tc358743.o
 obj-$(CONFIG_VIDEO_IMX258) += imx258.o
 obj-$(CONFIG_VIDEO_IMX274) += imx274.o
+obj-$(CONFIG_VIDEO_IMX319) += imx319.o
 
 obj-$(CONFIG_SDR_MAX2175) += max2175.o
diff --git a/drivers/media/i2c/imx319.c b/drivers/media/i2c/imx319.c
new file mode 100644
index ..706bbafc75ec
--- /dev/null
+++ b/drivers/media/i2c/imx319.c
@@ -0,0 +1,2434 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018 Intel Corporation
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define IMX319_REG_MODE_SELECT 0x0100
+#define IMX319_MODE_STANDBY0x00
+#define IMX319_MODE_STREAMING  0x01
+
+/* Chip ID */
+#define IMX319_REG_CHIP_ID 0x0016
+#define IMX319_CHIP_ID 0x0319
+
+/* V_TIMING internal */
+#define IMX319_REG_FLL 0x0340
+#define IMX319_FLL_MAX 0x
+
+/* Exposure control */
+#define IMX319_REG_EXPOSURE0x0202
+#define IMX319_EXPOSURE_MIN1
+#define IMX319_EXPOSURE_STEP   1
+#define IMX319_EXPOSURE_DEFAULT0x04ee
+
+/* Analog gain control */
+#define IMX319_REG_ANALOG_GAIN 0x0204
+#define IMX319_ANA_GAIN_MIN0
+#define IMX319_ANA_GAIN_MAX960
+#define IMX319_ANA_GAIN_STEP   1
+#define IMX319_ANA_GAIN_DEFAULT0
+
+/* Digital gain control */
+#define IMX319_REG_DPGA_USE_GLOBAL_GAIN0x3ff9
+#define IMX319_REG_DIG_GAIN_GLOBAL 0x020e
+#define IMX319_DGTL_GAIN_MIN   256
+#define IMX319_DGTL_GAIN_MAX   4095
+#define IMX319_DGTL_GAIN_STEP  1
+#define IMX319_DGTL_GAIN_DEFAULT   256
+
+/* Test Pattern Control */
+#define IMX319_REG_TEST_PATTERN0x0600
+#define IMX319_TEST_PATTERN_DISABLED   0
+#define IMX319_TEST_PATTERN_SOLID_COLOR1
+#define IMX319_TEST_PATTERN_COLOR_BARS 2
+#define IMX319_TEST_PATTERN_GRAY_COLOR_BARS3
+#define IMX319_TEST_PATTERN_PN94
+
+/* Flip Control */
+#define IMX319_REG_ORIENTATION 0x0101
+
+struct imx319_reg {
+   u16 address;
+   u8 val;
+};
+
+struct imx319_reg_list {
+   u32 num_of_regs;
+   const struct imx319_reg *regs;
+};
+
+/* Mode : resolution and related config */
+struct imx319_mode {
+   /* Frame width */
+   u32 width;
+   /* Frame height */
+   u32 height;
+
+   /* V-timing */
+   u32 fll_def;
+   u32 fll_min;
+
+   /* H-timing */
+   u32 llp;
+
+   /* Default register values */
+   struct imx319_reg_list reg_list;
+};
+
+struct imx319 {
+   struct v4l2_subdev sd;
+   struct media_pad pad;
+
+   struct v4l2_ctrl_handler ctrl_handler;
+   /* V4L2 Controls */
+   struct v4l2_ctrl 

cron job: media_tree daily build: ERRORS

2018-05-21 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:   Tue May 22 05:00:12 CEST 2018
media-tree git hash:7e6b6b945272c20f6b78d319e07f27897a8373c9
media_build git hash:   e274c18d3d2dfb2ab4a9b198718c0831ef078f02
v4l-utils git hash: e2038ec6451293787b929338c2a671c732b8693d
gcc version:i686-linux-gcc (GCC) 8.1.0
sparse version: 0.5.2-RC1
smatch version: 0.5.1
host hardware:  x86_64
host os:4.16.0-1-amd64

linux-git-arm-at91: WARNINGS
linux-git-arm-davinci: OK
linux-git-arm-multi: WARNINGS
linux-git-arm-pxa: WARNINGS
linux-git-arm-stm32: OK
linux-git-arm64: WARNINGS
linux-git-i686: WARNINGS
linux-git-mips: OK
linux-git-powerpc64: WARNINGS
linux-git-sh: OK
linux-git-x86_64: WARNINGS
Check COMPILE_TEST: OK
linux-2.6.36.4-i686: ERRORS
linux-2.6.36.4-x86_64: ERRORS
linux-2.6.37.6-i686: ERRORS
linux-2.6.37.6-x86_64: ERRORS
linux-2.6.38.8-i686: ERRORS
linux-2.6.38.8-x86_64: ERRORS
linux-2.6.39.4-i686: ERRORS
linux-2.6.39.4-x86_64: ERRORS
linux-3.0.101-i686: ERRORS
linux-3.0.101-x86_64: ERRORS
linux-3.1.10-i686: ERRORS
linux-3.1.10-x86_64: ERRORS
linux-3.2.101-i686: ERRORS
linux-3.2.101-x86_64: ERRORS
linux-3.3.8-i686: ERRORS
linux-3.3.8-x86_64: ERRORS
linux-3.4.113-i686: ERRORS
linux-3.4.113-x86_64: ERRORS
linux-3.5.7-i686: ERRORS
linux-3.5.7-x86_64: ERRORS
linux-3.6.11-i686: ERRORS
linux-3.6.11-x86_64: ERRORS
linux-3.7.10-i686: ERRORS
linux-3.7.10-x86_64: ERRORS
linux-3.8.13-i686: ERRORS
linux-3.8.13-x86_64: ERRORS
linux-3.9.11-i686: ERRORS
linux-3.9.11-x86_64: ERRORS
linux-3.10.108-i686: ERRORS
linux-3.10.108-x86_64: ERRORS
linux-3.11.10-i686: ERRORS
linux-3.11.10-x86_64: ERRORS
linux-3.12.74-i686: ERRORS
linux-3.12.74-x86_64: ERRORS
linux-3.13.11-i686: ERRORS
linux-3.13.11-x86_64: ERRORS
linux-3.14.79-i686: ERRORS
linux-3.14.79-x86_64: ERRORS
linux-3.15.10-i686: ERRORS
linux-3.15.10-x86_64: ERRORS
linux-3.16.56-i686: ERRORS
linux-3.16.56-x86_64: ERRORS
linux-3.17.8-i686: ERRORS
linux-3.17.8-x86_64: ERRORS
linux-3.18.102-i686: ERRORS
linux-3.18.102-x86_64: ERRORS
linux-3.19.8-i686: ERRORS
linux-3.19.8-x86_64: ERRORS
linux-4.0.9-i686: ERRORS
linux-4.0.9-x86_64: ERRORS
linux-4.1.51-i686: ERRORS
linux-4.1.51-x86_64: ERRORS
linux-4.2.8-i686: ERRORS
linux-4.2.8-x86_64: ERRORS
linux-4.3.6-i686: ERRORS
linux-4.3.6-x86_64: ERRORS
linux-4.4.109-i686: ERRORS
linux-4.4.109-x86_64: ERRORS
linux-4.5.7-i686: ERRORS
linux-4.5.7-x86_64: ERRORS
linux-4.6.7-i686: ERRORS
linux-4.6.7-x86_64: ERRORS
linux-4.7.10-i686: ERRORS
linux-4.7.10-x86_64: ERRORS
linux-4.8.17-i686: ERRORS
linux-4.8.17-x86_64: ERRORS
linux-4.9.91-i686: ERRORS
linux-4.9.91-x86_64: ERRORS
linux-4.10.17-i686: OK
linux-4.10.17-x86_64: WARNINGS
linux-4.11.12-i686: OK
linux-4.11.12-x86_64: WARNINGS
linux-4.12.14-i686: OK
linux-4.12.14-x86_64: WARNINGS
linux-4.13.16-i686: WARNINGS
linux-4.13.16-x86_64: WARNINGS
linux-4.14.31-i686: WARNINGS
linux-4.14.31-x86_64: WARNINGS
linux-4.15.14-i686: WARNINGS
linux-4.15.14-x86_64: WARNINGS
linux-4.16.8-i686: WARNINGS
linux-4.16.8-x86_64: WARNINGS
linux-4.17-rc4-i686: WARNINGS
linux-4.17-rc4-x86_64: WARNINGS
apps: OK
spec-git: OK
sparse: WARNINGS

Detailed results are available here:

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

Full logs are available here:

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

The Media Infrastructure API from this daily build is here:

http://www.xs4all.nl/~hverkuil/spec/index.html


Proposal

2018-05-21 Thread Miss Zeliha Omer Faruk



Hello

Greetings to you please i have a business proposal for you contact me
for more detailes asap thanks.

Best Regards,
Miss.Zeliha ömer faruk
Esentepe Mahallesi Büyükdere
Caddesi Kristal Kule Binasi
No:215
Sisli - Istanbul, Turkey



Re: i.MX6 IPU CSI analog video input on Ventana

2018-05-21 Thread Steve Longerbeam

Hi Krzysztof, I've been on vacation, just returned today. I will
find the time this week to attempt to reproduce your results on
a SabreAuto quad with the adv7180.

Btw, if you just need to capture an interlaced frame (lines 0,1,2,...)
without motion compensation, there is no need to use the VDIC
path. Capturing directly from ipu2_csi1 should work, I've tested
this many times on a SabreAuto. But I will try to reproduce your
results.

Steve


On 05/21/2018 01:09 AM, Krzysztof Hałasa wrote:

Tested with NTSC camera, it's the same as with PAL.
The only case when IPU2_CSI1_SENS_CONF register is set to interlaced
mode (PRCTL=3, CCIR interlaced mode (BT.656)) is when all parts of the
pipeline are set to interlaced:

"adv7180 2-0020":0 [fmt:UYVY2X8/720x576 field:interlaced]
"ipu2_csi1_mux":1  [fmt:UYVY2X8/720x576 field:interlaced]
"ipu2_csi1_mux":2  [fmt:UYVY2X8/720x576 field:interlaced]
"ipu2_csi1":0  [fmt:UYVY2X8/720x576 field:interlaced]
"ipu2_csi1":2  [fmt:AYUV32/720x576 field:interlaced]

The image is stable and in sync, the "only" problem is that I get two
concatenated field images (in one V4L2 frame) instead of a normal
interlaced frame (all lines in order - 0, 1, 2, 3, 4 etc).
IOW I get V4L2_FIELD_ALTERNATE, V4L2_FIELD_SEQ_TB or V4L2_FIELD_SEQ_BT
(the data format, I don't mean the pixel format.field) while I need to
get V4L2_FIELD_INTERLACED, V4L2_FIELD_INTERLACED_TB or _BT.


If I set "ipu2_csi1":2 to field:none, the IPU2_CSI1_SENS_CONF is set to
progressive mode (PRCTL=2). It's the last element of the pipeline I can
configure, it's connected straight to "ipu2_csi1 capture" aka
/dev/videoX. I think CSI can't work with interlaced camera (and ADV7180)
when set to progressive, can it?


I wonder... perhaps to get an interlaced frame I need to route the data
through VDIC (ipu2_vdic, the deinterlacer)?




Re: [Xen-devel][RFC 3/3] xen/gntdev: Add support for Linux dma buffers

2018-05-21 Thread Dongwon Kim
Still need more time to review the whole code changes but I noticed one thing.

We've been using the term "hyper_dmabuf" for hypervisor-agnostic linux dmabuf
solution and we are planning to call any of our future solution for other
hypervisors the same name. So having same name for this xen-specific structure
or functions you implemented is confusing. Would you change it to something
else like... "xen_"? 

On Thu, May 17, 2018 at 11:26:04AM +0300, Oleksandr Andrushchenko wrote:
> From: Oleksandr Andrushchenko 
> 
> Signed-off-by: Oleksandr Andrushchenko 
> ---
>  drivers/xen/gntdev.c  | 954 +-
>  include/uapi/xen/gntdev.h | 101 
>  include/xen/gntdev_exp.h  |  23 +
>  3 files changed, 1066 insertions(+), 12 deletions(-)
>  create mode 100644 include/xen/gntdev_exp.h
> 
> diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
> index 9510f228efe9..0ee88e193362 100644
> --- a/drivers/xen/gntdev.c
> +++ b/drivers/xen/gntdev.c
> @@ -4,6 +4,8 @@
>   * Device for accessing (in user-space) pages that have been granted by other
>   * domains.
>   *
> + * DMA buffer implementation is based on drivers/gpu/drm/drm_prime.c.
> + *
>   * Copyright (c) 2006-2007, D G Murray.
>   *   (c) 2009 Gerd Hoffmann 
>   *
> @@ -37,6 +39,9 @@
>  #include 
>  #include 
>  
> +#include 
> +#include 
> +
>  #include 
>  #include 
>  #include 
> @@ -61,16 +66,39 @@ static atomic_t pages_mapped = ATOMIC_INIT(0);
>  static int use_ptemod;
>  #define populate_freeable_maps use_ptemod
>  
> +#ifndef GRANT_INVALID_REF
> +/*
> + * Note on usage of grant reference 0 as invalid grant reference:
> + * grant reference 0 is valid, but never exposed to a driver,
> + * because of the fact it is already in use/reserved by the PV console.
> + */
> +#define GRANT_INVALID_REF0
> +#endif
> +
>  struct gntdev_priv {
>   /* maps with visible offsets in the file descriptor */
>   struct list_head maps;
>   /* maps that are not visible; will be freed on munmap.
>* Only populated if populate_freeable_maps == 1 */
>   struct list_head freeable_maps;
> + /* List of dma-bufs. */
> + struct list_head dma_bufs;
>   /* lock protects maps and freeable_maps */
>   struct mutex lock;
>   struct mm_struct *mm;
>   struct mmu_notifier mn;
> +
> + /* Private data of the hyper DMA buffers. */
> +
> + struct device *dev;
> + /* List of exported DMA buffers. */
> + struct list_head dmabuf_exp_list;
> + /* List of wait objects. */
> + struct list_head dmabuf_exp_wait_list;
> + /* List of imported DMA buffers. */
> + struct list_head dmabuf_imp_list;
> + /* This is the lock which protects dma_buf_xxx lists. */
> + struct mutex dmabuf_lock;
>  };
>  
>  struct unmap_notify {
> @@ -95,10 +123,65 @@ struct grant_map {
>   struct gnttab_unmap_grant_ref *kunmap_ops;
>   struct page **pages;
>   unsigned long pages_vm_start;
> +
> + /*
> +  * All the fields starting with dmabuf_ are only valid if this
> +  * mapping is used for exporting a DMA buffer.
> +  * If dmabuf_vaddr is not NULL then this mapping is backed by DMA
> +  * capable memory.
> +  */
> +
> + /* Flags used to create this DMA buffer: GNTDEV_DMABUF_FLAG_XXX. */
> + bool dmabuf_flags;
> + /* Virtual/CPU address of the DMA buffer. */
> + void *dmabuf_vaddr;
> + /* Bus address of the DMA buffer. */
> + dma_addr_t dmabuf_bus_addr;
> +};
> +
> +struct hyper_dmabuf {
> + struct gntdev_priv *priv;
> + struct dma_buf *dmabuf;
> + struct list_head next;
> + int fd;
> +
> + union {
> + struct {
> + /* Exported buffers are reference counted. */
> + struct kref refcount;
> + struct grant_map *map;
> + } exp;
> + struct {
> + /* Granted references of the imported buffer. */
> + grant_ref_t *refs;
> + /* Scatter-gather table of the imported buffer. */
> + struct sg_table *sgt;
> + /* dma-buf attachment of the imported buffer. */
> + struct dma_buf_attachment *attach;
> + } imp;
> + } u;
> +
> + /* Number of pages this buffer has. */
> + int nr_pages;
> + /* Pages of this buffer. */
> + struct page **pages;
> +};
> +
> +struct hyper_dmabuf_wait_obj {
> + struct list_head next;
> + struct hyper_dmabuf *hyper_dmabuf;
> + struct completion completion;
> +};
> +
> +struct hyper_dambuf_attachment {
minor typo: dam->dma (same thing in other places as well.)

> + struct sg_table *sgt;
> + enum dma_data_direction dir;
>  };
>  
>  static int unmap_grant_pages(struct grant_map *map, int offset, int pages);
>  
> +static struct miscdevice gntdev_miscdev;
> +
>  /* 

Re: [PATCH v2] media: imx319: Add imx319 camera sensor driver

2018-05-21 Thread kbuild test robot
Hi Bingbu,

I love your patch! Perhaps something to improve:

[auto build test WARNING on next-20180517]
[also build test WARNING on v4.17-rc6]
[cannot apply to linuxtv-media/master linus/master v4.17-rc6 v4.17-rc5 
v4.17-rc4]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/bingbu-cao-intel-com/media-imx319-Add-imx319-camera-sensor-driver/20180522-020817


coccinelle warnings: (new ones prefixed by >>)

>> drivers/media/i2c/imx319.c:1874:2-3: Unneeded semicolon
   drivers/media/i2c/imx319.c:1917:2-3: Unneeded semicolon

Please review and possibly fold the followup patch.

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


[PATCH] media: imx319: fix semicolon.cocci warnings

2018-05-21 Thread kbuild test robot
From: kbuild test robot 

drivers/media/i2c/imx319.c:1874:2-3: Unneeded semicolon
drivers/media/i2c/imx319.c:1917:2-3: Unneeded semicolon


 Remove unneeded semicolon.

Generated by: scripts/coccinelle/misc/semicolon.cocci

Fixes: 6ee66fafab37 ("media: imx319: Add imx319 camera sensor driver")
CC: Bingbu Cao 
Signed-off-by: kbuild test robot 
---

 imx319.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

--- a/drivers/media/i2c/imx319.c
+++ b/drivers/media/i2c/imx319.c
@@ -1871,7 +1871,7 @@ static int imx319_set_ctrl(struct v4l2_c
 imx319->exposure->minimum,
 max, imx319->exposure->step, max);
break;
-   };
+   }
 
/*
 * Applying V4L2 control value only happens
@@ -1914,7 +1914,7 @@ static int imx319_set_ctrl(struct v4l2_c
 "ctrl(id:0x%x,val:0x%x) is not handled\n",
 ctrl->id, ctrl->val);
break;
-   };
+   }
 
pm_runtime_put(>dev);
 


Re: [media] duplicate code in media drivers

2018-05-21 Thread Devin Heitmueller
>> diff -u -p drivers/media/dvb-frontends/au8522_decoder.c 
>> /tmp/nothing/media/dvb-frontends/au8522_decoder.c
>> --- drivers/media/dvb-frontends/au8522_decoder.c
>> +++ /tmp/nothing/media/dvb-frontends/au8522_decoder.c
>> @@ -280,14 +280,9 @@ static void setup_decoder_defaults(struc
>> AU8522_TOREGAAGC_REG0E5H_CVBS);
>> au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);
>>
>> -   if (is_svideo) {
>> /* Despite what the table says, for the HVR-950q we still 
>> need
>>to be in CVBS mode for the S-Video input (reason 
>> unknown). */
>> /* filter_coef_type = 3; */
>> -   filter_coef_type = 5;
>> -   } else {
>> -   filter_coef_type = 5;
>> -   }
>
> Better ask Devin about this (c/c).

This was a case where the implementation didn't match the datasheet,
and it wasn't clear why the filter coefficients weren't working
properly.  Essentially I should have labeled that as a TODO or FIXME
when I disabled the "right" value and forced it to always be five.  It
was also likely that the filter coefficients would need to differ if
taking video over the IF interface as opposed to CVBS/S-video, which
is why I didn't want to get rid of the logic entirely.  That said, the
only product I've ever seen with the tda18271 mated to the au8522 will
likely never be supported for analog video under Linux for unrelated
reasons.

That said, it's worked "good enough" since I wrote the code nine years
ago, so if somebody wants to submit a patch to either get rid of the
if() statement or mark it as a FIXME that will likely never actually
get fixed, I wouldn't have an objection to either.

Devin

-- 
Devin J. Heitmueller - Kernel Labs
http://www.kernellabs.com


Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers

2018-05-21 Thread Boris Ostrovsky
On 05/21/2018 03:13 PM, Oleksandr Andrushchenko wrote:
> On 05/21/2018 09:53 PM, Boris Ostrovsky wrote:
>> On 05/21/2018 01:32 PM, Oleksandr Andrushchenko wrote:
>>> On 05/21/2018 07:35 PM, Boris Ostrovsky wrote:
 On 05/21/2018 01:40 AM, Oleksandr Andrushchenko wrote:
> On 05/19/2018 01:04 AM, Boris Ostrovsky wrote:
>> On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote:
>>> From: Oleksandr Andrushchenko 
>> A commit message would be useful.
> Sure, v1 will have it
>>> Signed-off-by: Oleksandr Andrushchenko
>>> 
>>>
>>>     for (i = 0; i < nr_pages; i++) {
>>> -    page = alloc_page(gfp);
>>> -    if (page == NULL) {
>>> -    nr_pages = i;
>>> -    state = BP_EAGAIN;
>>> -    break;
>>> +    if (ext_pages) {
>>> +    page = ext_pages[i];
>>> +    } else {
>>> +    page = alloc_page(gfp);
>>> +    if (page == NULL) {
>>> +    nr_pages = i;
>>> +    state = BP_EAGAIN;
>>> +    break;
>>> +    }
>>>     }
>>>     scrub_page(page);
>>>     list_add(>lru, );
>>> @@ -529,7 +565,7 @@ static enum bp_state
>>> decrease_reservation(unsigned long nr_pages, gfp_t gfp)
>>>     i = 0;
>>>     list_for_each_entry_safe(page, tmp, , lru) {
>>>     /* XENMEM_decrease_reservation requires a GFN */
>>> -    frame_list[i++] = xen_page_to_gfn(page);
>>> +    frames[i++] = xen_page_to_gfn(page);
>>>       #ifdef CONFIG_XEN_HAVE_PVMMU
>>>     /*
>>> @@ -552,18 +588,22 @@ static enum bp_state
>>> decrease_reservation(unsigned long nr_pages, gfp_t gfp)
>>>     #endif
>>>     list_del(>lru);
>>>     -    balloon_append(page);
>>> +    if (!ext_pages)
>>> +    balloon_append(page);
>> So what you are proposing is not really ballooning. You are just
>> piggybacking on existing interfaces, aren't you?
> Sort of. Basically I need to {increase|decrease}_reservation, not
> actually
> allocating ballooned pages.
> Do you think I can simply EXPORT_SYMBOL for
> {increase|decrease}_reservation?
> Any other suggestion?
 I am actually wondering how much of that code you end up reusing. You
 pretty much create new code paths in both routines and common code
 ends
 up being essentially the hypercall.
>>> Well, I hoped that it would be easier to maintain if I modify existing
>>> code
>>> to support both use-cases, but I am also ok to create new routines if
>>> this
>>> seems to be reasonable - please let me know
    So the question is --- would it make
 sense to do all of this separately from the balloon driver?
>>> This can be done, but which driver will host this code then? If we
>>> move from
>>> the balloon driver, then this could go to either gntdev or grant-table.
>>> What's your preference?
>> A separate module?
>
>> Is there any use for this feature outside of your zero-copy DRM driver?
> Intel's hyper dma-buf (Dongwon/Matt CC'ed), V4L/GPU at least.
>
> At the time I tried to upstream zcopy driver it was discussed and
> decided that
> it would be better if I remove all DRM specific code and move it to
> Xen drivers.
> Thus, this RFC.
>
> But it can also be implemented as a dedicated Xen dma-buf driver which
> will have all the
> code from this RFC + a bit more (char/misc device handling at least).
> This will also require a dedicated user-space library, just like
> libxengnttab.so
> for gntdev (now I have all new IOCTLs covered there).
>
> If the idea of a dedicated Xen dma-buf driver seems to be more
> attractive we
> can work toward this solution. BTW, I do support this idea, but was not
> sure if Xen community accepts yet another driver which duplicates
> quite some code
> of the existing gntdev/balloon/grant-table. And now after this RFC I
> hope that all cons
> and pros of both dedicated driver and gntdev/balloon/grant-table
> extension are
> clearly seen and we can make a decision.


IIRC the objection for a separate module was in the context of gntdev
was discussion, because (among other things) people didn't want to have
yet another file in /dev/xen/

Here we are talking about (a new) balloon-like module which doesn't
create any new user-visible interfaces. And as for duplicating code ---
as I said, I am not convinced there is much of duplication.

I might even argue that we should add a new config option for this module.


-boris

>
>>
>> -boris
> Thank you,
> Oleksandr
> [1]
> https://lists.freedesktop.org/archives/dri-devel/2018-April/173163.html



Re: Bugfix for Tevii S650

2018-05-21 Thread Andy Shevchenko
+Cc: Mauro

On Mon, May 21, 2018 at 3:01 PM, Light  wrote:
> Hi,
>
> staring with kernel 4.1 the tevii S650 usb box is not working any more, last
> working version was 4.0.
>
> The  bug was also reported here
> https://www.spinics.net/lists/linux-media/msg121356.html
>
> I found a solution for it and uploaded a patch to the kernel bugzilla.
>
> See here: https://bugzilla.kernel.org/show_bug.cgi?id=197731
>
> Can somebody of the maintainers have a look on it and apply the patch to the
> kernes sources?

You forget to Cc to maintainers (at least Mauro).

-- 
With Best Regards,
Andy Shevchenko


Re: [media] duplicate code in media drivers

2018-05-21 Thread Mauro Carvalho Chehab
Em Mon, 21 May 2018 14:39:51 -0500
"Gustavo A. R. Silva"  escreveu:

> Hi Mauro,
> 
> I found some duplicate code with the help of Coccinelle and Coverity. Notice 
> that these are not code patches, they only point out the duplicate code in 
> some media drivers:
> 
> diff -u -p drivers/media/pci/bt8xx/dvb-bt8xx.c 
> /tmp/nothing/media/pci/bt8xx/dvb-bt8xx.c
> --- drivers/media/pci/bt8xx/dvb-bt8xx.c
> +++ /tmp/nothing/media/pci/bt8xx/dvb-bt8xx.c
> @@ -389,9 +389,7 @@ static int advbt771_samsung_tdtc9251dh0_
> else if (c->frequency < 6)
> bs = 0x08;
> else if (c->frequency < 73000)
> -   bs = 0x08;
> else
> -   bs = 0x08;
> 
> pllbuf[0] = 0x61;
> pllbuf[1] = div >> 8;


Hmm... I *suspect* that "bs" here controls the frequency range for the
tuner. Analog tuners have separate frequency regions that are controlled
via a register, into a 4 or 5 bytes I2C sequence. They're all somewhat
a clone of an old Philips design.

It should be safe to convert the "BS" sequence on something like:

if (c->frequency < 17300)
bs = 0x01;
else if (c->frequency < 47000)
bs = 0x02;
else 
bs = 0x08;



> diff -u -p drivers/media/usb/dvb-usb/dib0700_devices.c 
> /tmp/nothing/media/usb/dvb-usb/dib0700_devices.c
> --- drivers/media/usb/dvb-usb/dib0700_devices.c
> +++ /tmp/nothing/media/usb/dvb-usb/dib0700_devices.c
> @@ -1741,13 +1741,6 @@ static int dib809x_tuner_attach(struct d
> struct dib0700_adapter_state *st = adap->priv;
> struct i2c_adapter *tun_i2c = 
> st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, 
> DIBX000_I2C_INTERFACE_TUNER, 1);
> 
> -   if (adap->id == 0) {
> -   if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, 
> tun_i2c, _dib0090_config) == NULL)
> -   return -ENODEV;
> -   } else {
> -   if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, 
> tun_i2c, _dib0090_config) == NULL)
> -   return -ENODEV;
> -   }

I'm almost sure that, on the second if, it should be adap->fe_adap[1].fe.
I tried in the past to check this, but didn't got an answer from the one
that wrote the code.

Maybe we could add a /* FIXME: check if it is fe_adap[1] */ on the
second clause.

> 
> st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
> adap->fe_adap[0].fe->ops.tuner_ops.set_params = 
> dib8096_set_param_override;
> diff -u -p drivers/media/dvb-frontends/mb86a16.c 
> /tmp/nothing/media/dvb-frontends/mb86a16.c
> --- drivers/media/dvb-frontends/mb86a16.c
> +++ /tmp/nothing/media/dvb-frontends/mb86a16.c
> @@ -1466,9 +1466,7 @@ static int mb86a16_set_fe(struct mb86a16
> wait_t = (1572864 + 
> state->srate / 2) / state->srate;
> if (state->srate < 5000)
> /* FIXME ! , should 
> be a long wait ! */
> -   
> msleep_interruptible(wait_t);
> else
> -   
> msleep_interruptible(wait_t);

I suspect that the goal here is to point that sleeping for
(1572864 + state->srate / 2) / state->srate when srate is low will mean
that it will take a lot of time to converge (probably causing timeout at
userspace).

Basically, if srate is < 5000, the sleep time will be between
314 and 1575364 ms. The worse case scenario - although not realistic,
in practice - is to wait up to 26 seconds. This is a very long time!

Probably, the right fix here would be to check if wait_t is bigger than
a certain amount of time. If so, return an error.

I'm not against removing the if, but, if so, better to add a /* FIXME */
block explaining that.

That's said, this is an old device. I doubt anyone would fix it.


> 
> if (sync_chk(state, ) == 
> 0) {
> iq_vt_set(state, 1);
> diff -u -p drivers/media/dvb-frontends/au8522_decoder.c 
> /tmp/nothing/media/dvb-frontends/au8522_decoder.c
> --- drivers/media/dvb-frontends/au8522_decoder.c
> +++ /tmp/nothing/media/dvb-frontends/au8522_decoder.c
> @@ -280,14 +280,9 @@ static void setup_decoder_defaults(struc
> AU8522_TOREGAAGC_REG0E5H_CVBS);
> au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);
> 
> -   if (is_svideo) {
> /* Despite what the table says, for the HVR-950q we still need
>to be in CVBS mode for the S-Video input (reason unknown). 
> */
> /* filter_coef_type = 3; */
> -   filter_coef_type = 5;
> -   } else {
> -   filter_coef_type = 5;
> -   }

Better ask Devin about this 

[media] duplicate code in media drivers

2018-05-21 Thread Gustavo A. R. Silva
Hi Mauro,

I found some duplicate code with the help of Coccinelle and Coverity. Notice 
that these are not code patches, they only point out the duplicate code in some 
media drivers:

diff -u -p drivers/media/pci/bt8xx/dvb-bt8xx.c 
/tmp/nothing/media/pci/bt8xx/dvb-bt8xx.c
--- drivers/media/pci/bt8xx/dvb-bt8xx.c
+++ /tmp/nothing/media/pci/bt8xx/dvb-bt8xx.c
@@ -389,9 +389,7 @@ static int advbt771_samsung_tdtc9251dh0_
else if (c->frequency < 6)
bs = 0x08;
else if (c->frequency < 73000)
-   bs = 0x08;
else
-   bs = 0x08;

pllbuf[0] = 0x61;
pllbuf[1] = div >> 8;
diff -u -p drivers/media/usb/dvb-usb/dib0700_devices.c 
/tmp/nothing/media/usb/dvb-usb/dib0700_devices.c
--- drivers/media/usb/dvb-usb/dib0700_devices.c
+++ /tmp/nothing/media/usb/dvb-usb/dib0700_devices.c
@@ -1741,13 +1741,6 @@ static int dib809x_tuner_attach(struct d
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c = 
st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, 
DIBX000_I2C_INTERFACE_TUNER, 1);

-   if (adap->id == 0) {
-   if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, 
_dib0090_config) == NULL)
-   return -ENODEV;
-   } else {
-   if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, 
_dib0090_config) == NULL)
-   return -ENODEV;
-   }

st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
adap->fe_adap[0].fe->ops.tuner_ops.set_params = 
dib8096_set_param_override;
diff -u -p drivers/media/dvb-frontends/mb86a16.c 
/tmp/nothing/media/dvb-frontends/mb86a16.c
--- drivers/media/dvb-frontends/mb86a16.c
+++ /tmp/nothing/media/dvb-frontends/mb86a16.c
@@ -1466,9 +1466,7 @@ static int mb86a16_set_fe(struct mb86a16
wait_t = (1572864 + 
state->srate / 2) / state->srate;
if (state->srate < 5000)
/* FIXME ! , should be 
a long wait ! */
-   
msleep_interruptible(wait_t);
else
-   
msleep_interruptible(wait_t);

if (sync_chk(state, ) == 
0) {
iq_vt_set(state, 1);
diff -u -p drivers/media/dvb-frontends/au8522_decoder.c 
/tmp/nothing/media/dvb-frontends/au8522_decoder.c
--- drivers/media/dvb-frontends/au8522_decoder.c
+++ /tmp/nothing/media/dvb-frontends/au8522_decoder.c
@@ -280,14 +280,9 @@ static void setup_decoder_defaults(struc
AU8522_TOREGAAGC_REG0E5H_CVBS);
au8522_writereg(state, AU8522_REG016H, AU8522_REG016H_CVBS);

-   if (is_svideo) {
/* Despite what the table says, for the HVR-950q we still need
   to be in CVBS mode for the S-Video input (reason unknown). */
/* filter_coef_type = 3; */
-   filter_coef_type = 5;
-   } else {
-   filter_coef_type = 5;
-   }

/* Load the Video Decoder Filter Coefficients */
for (i = 0; i < NUM_FILTER_COEF; i++) {


I wonder if some of the cases above were intentionally coded that way or some 
code needs to be removed.

Thanks
--
Gustavo


Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers

2018-05-21 Thread Oleksandr Andrushchenko

On 05/21/2018 09:53 PM, Boris Ostrovsky wrote:

On 05/21/2018 01:32 PM, Oleksandr Andrushchenko wrote:

On 05/21/2018 07:35 PM, Boris Ostrovsky wrote:

On 05/21/2018 01:40 AM, Oleksandr Andrushchenko wrote:

On 05/19/2018 01:04 AM, Boris Ostrovsky wrote:

On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote:

From: Oleksandr Andrushchenko 

A commit message would be useful.

Sure, v1 will have it

Signed-off-by: Oleksandr Andrushchenko


    for (i = 0; i < nr_pages; i++) {
-    page = alloc_page(gfp);
-    if (page == NULL) {
-    nr_pages = i;
-    state = BP_EAGAIN;
-    break;
+    if (ext_pages) {
+    page = ext_pages[i];
+    } else {
+    page = alloc_page(gfp);
+    if (page == NULL) {
+    nr_pages = i;
+    state = BP_EAGAIN;
+    break;
+    }
    }
    scrub_page(page);
    list_add(>lru, );
@@ -529,7 +565,7 @@ static enum bp_state
decrease_reservation(unsigned long nr_pages, gfp_t gfp)
    i = 0;
    list_for_each_entry_safe(page, tmp, , lru) {
    /* XENMEM_decrease_reservation requires a GFN */
-    frame_list[i++] = xen_page_to_gfn(page);
+    frames[i++] = xen_page_to_gfn(page);
      #ifdef CONFIG_XEN_HAVE_PVMMU
    /*
@@ -552,18 +588,22 @@ static enum bp_state
decrease_reservation(unsigned long nr_pages, gfp_t gfp)
    #endif
    list_del(>lru);
    -    balloon_append(page);
+    if (!ext_pages)
+    balloon_append(page);

So what you are proposing is not really ballooning. You are just
piggybacking on existing interfaces, aren't you?

Sort of. Basically I need to {increase|decrease}_reservation, not
actually
allocating ballooned pages.
Do you think I can simply EXPORT_SYMBOL for
{increase|decrease}_reservation?
Any other suggestion?

I am actually wondering how much of that code you end up reusing. You
pretty much create new code paths in both routines and common code ends
up being essentially the hypercall.

Well, I hoped that it would be easier to maintain if I modify existing
code
to support both use-cases, but I am also ok to create new routines if
this
seems to be reasonable - please let me know

   So the question is --- would it make
sense to do all of this separately from the balloon driver?

This can be done, but which driver will host this code then? If we
move from
the balloon driver, then this could go to either gntdev or grant-table.
What's your preference?

A separate module?



Is there any use for this feature outside of your zero-copy DRM driver?

Intel's hyper dma-buf (Dongwon/Matt CC'ed), V4L/GPU at least.

At the time I tried to upstream zcopy driver it was discussed and 
decided that
it would be better if I remove all DRM specific code and move it to Xen 
drivers.

Thus, this RFC.

But it can also be implemented as a dedicated Xen dma-buf driver which 
will have all the

code from this RFC + a bit more (char/misc device handling at least).
This will also require a dedicated user-space library, just like 
libxengnttab.so

for gntdev (now I have all new IOCTLs covered there).

If the idea of a dedicated Xen dma-buf driver seems to be more attractive we
can work toward this solution. BTW, I do support this idea, but was not
sure if Xen community accepts yet another driver which duplicates quite 
some code
of the existing gntdev/balloon/grant-table. And now after this RFC I 
hope that all cons
and pros of both dedicated driver and gntdev/balloon/grant-table 
extension are

clearly seen and we can make a decision.



-boris

Thank you,
Oleksandr
[1] https://lists.freedesktop.org/archives/dri-devel/2018-April/173163.html


Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers

2018-05-21 Thread Boris Ostrovsky
On 05/21/2018 01:32 PM, Oleksandr Andrushchenko wrote:
> On 05/21/2018 07:35 PM, Boris Ostrovsky wrote:
>> On 05/21/2018 01:40 AM, Oleksandr Andrushchenko wrote:
>>> On 05/19/2018 01:04 AM, Boris Ostrovsky wrote:
 On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote:
> From: Oleksandr Andrushchenko 
 A commit message would be useful.
>>> Sure, v1 will have it
> Signed-off-by: Oleksandr Andrushchenko
> 
>
>    for (i = 0; i < nr_pages; i++) {
> -    page = alloc_page(gfp);
> -    if (page == NULL) {
> -    nr_pages = i;
> -    state = BP_EAGAIN;
> -    break;
> +    if (ext_pages) {
> +    page = ext_pages[i];
> +    } else {
> +    page = alloc_page(gfp);
> +    if (page == NULL) {
> +    nr_pages = i;
> +    state = BP_EAGAIN;
> +    break;
> +    }
>    }
>    scrub_page(page);
>    list_add(>lru, );
> @@ -529,7 +565,7 @@ static enum bp_state
> decrease_reservation(unsigned long nr_pages, gfp_t gfp)
>    i = 0;
>    list_for_each_entry_safe(page, tmp, , lru) {
>    /* XENMEM_decrease_reservation requires a GFN */
> -    frame_list[i++] = xen_page_to_gfn(page);
> +    frames[i++] = xen_page_to_gfn(page);
>      #ifdef CONFIG_XEN_HAVE_PVMMU
>    /*
> @@ -552,18 +588,22 @@ static enum bp_state
> decrease_reservation(unsigned long nr_pages, gfp_t gfp)
>    #endif
>    list_del(>lru);
>    -    balloon_append(page);
> +    if (!ext_pages)
> +    balloon_append(page);
 So what you are proposing is not really ballooning. You are just
 piggybacking on existing interfaces, aren't you?
>>> Sort of. Basically I need to {increase|decrease}_reservation, not
>>> actually
>>> allocating ballooned pages.
>>> Do you think I can simply EXPORT_SYMBOL for
>>> {increase|decrease}_reservation?
>>> Any other suggestion?
>>
>> I am actually wondering how much of that code you end up reusing. You
>> pretty much create new code paths in both routines and common code ends
>> up being essentially the hypercall.
> Well, I hoped that it would be easier to maintain if I modify existing
> code
> to support both use-cases, but I am also ok to create new routines if
> this
> seems to be reasonable - please let me know
>>   So the question is --- would it make
>> sense to do all of this separately from the balloon driver?
> This can be done, but which driver will host this code then? If we
> move from
> the balloon driver, then this could go to either gntdev or grant-table.
> What's your preference?

A separate module?

Is there any use for this feature outside of your zero-copy DRM driver?

-boris



[PATCH] media: si470x: fix potential Spectre variant 1

2018-05-21 Thread Gustavo A. R. Silva
band->index can be controlled by user-space, hence leading to
a potential exploitation of the Spectre variant 1 vulnerability.

This issue was detected with the help of Smatch:
drivers/media/radio/si470x/radio-si470x-common.c:758 
si470x_vidioc_enum_freq_bands() warn: potential spectre issue 'bands'

Fix this by sanitizing band->index before using it to index
`bands'

Notice that given that speculation windows are large, the policy is
to kill the speculation on the first load and not worry if it can be
completed with a dependent load/store [1].

[1] https://marc.info/?l=linux-kernel=152449131114778=2

Cc: sta...@vger.kernel.org
Signed-off-by: Gustavo A. R. Silva 
---
 drivers/media/radio/si470x/radio-si470x-common.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/media/radio/si470x/radio-si470x-common.c 
b/drivers/media/radio/si470x/radio-si470x-common.c
index c40e175..e81f9aa 100644
--- a/drivers/media/radio/si470x/radio-si470x-common.c
+++ b/drivers/media/radio/si470x/radio-si470x-common.c
@@ -110,6 +110,10 @@
 /* kernel includes */
 #include "radio-si470x.h"
 
+/* Hardening for Spectre-v1 */
+#include 
+
+
 /**
  * Module Parameters
  **/
@@ -755,7 +759,7 @@ static int si470x_vidioc_enum_freq_bands(struct file *file, 
void *priv,
return -EINVAL;
if (band->index >= ARRAY_SIZE(bands))
return -EINVAL;
-   *band = bands[band->index];
+   *band = bands[array_index_nospec(band->index, ARRAY_SIZE(bands))];
return 0;
 }
 
-- 
2.7.4



Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers

2018-05-21 Thread Oleksandr Andrushchenko

On 05/21/2018 07:35 PM, Boris Ostrovsky wrote:

On 05/21/2018 01:40 AM, Oleksandr Andrushchenko wrote:

On 05/19/2018 01:04 AM, Boris Ostrovsky wrote:

On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote:

From: Oleksandr Andrushchenko 

A commit message would be useful.

Sure, v1 will have it

Signed-off-by: Oleksandr Andrushchenko


   for (i = 0; i < nr_pages; i++) {
-    page = alloc_page(gfp);
-    if (page == NULL) {
-    nr_pages = i;
-    state = BP_EAGAIN;
-    break;
+    if (ext_pages) {
+    page = ext_pages[i];
+    } else {
+    page = alloc_page(gfp);
+    if (page == NULL) {
+    nr_pages = i;
+    state = BP_EAGAIN;
+    break;
+    }
   }
   scrub_page(page);
   list_add(>lru, );
@@ -529,7 +565,7 @@ static enum bp_state
decrease_reservation(unsigned long nr_pages, gfp_t gfp)
   i = 0;
   list_for_each_entry_safe(page, tmp, , lru) {
   /* XENMEM_decrease_reservation requires a GFN */
-    frame_list[i++] = xen_page_to_gfn(page);
+    frames[i++] = xen_page_to_gfn(page);
     #ifdef CONFIG_XEN_HAVE_PVMMU
   /*
@@ -552,18 +588,22 @@ static enum bp_state
decrease_reservation(unsigned long nr_pages, gfp_t gfp)
   #endif
   list_del(>lru);
   -    balloon_append(page);
+    if (!ext_pages)
+    balloon_append(page);

So what you are proposing is not really ballooning. You are just
piggybacking on existing interfaces, aren't you?

Sort of. Basically I need to {increase|decrease}_reservation, not
actually
allocating ballooned pages.
Do you think I can simply EXPORT_SYMBOL for
{increase|decrease}_reservation?
Any other suggestion?


I am actually wondering how much of that code you end up reusing. You
pretty much create new code paths in both routines and common code ends
up being essentially the hypercall.

Well, I hoped that it would be easier to maintain if I modify existing code
to support both use-cases, but I am also ok to create new routines if this
seems to be reasonable - please let me know

  So the question is --- would it make
sense to do all of this separately from the balloon driver?

This can be done, but which driver will host this code then? If we move from
the balloon driver, then this could go to either gntdev or grant-table.
What's your preference?


-boris

Thank you,
Oleksandr


[PATCH v2 1/4] dt-bindings: media: rcar-vin: Describe optional ep properties

2018-05-21 Thread Jacopo Mondi
Describe the optional properties for endpoint nodes of port@0
and port@1 of the R-Car VIN driver device tree bindings documentation.

Signed-off-by: Jacopo Mondi 
Acked-by: Niklas Söderlund 
---
 Documentation/devicetree/bindings/media/rcar_vin.txt | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt 
b/Documentation/devicetree/bindings/media/rcar_vin.txt
index 5c6f2a7..dab3118 100644
--- a/Documentation/devicetree/bindings/media/rcar_vin.txt
+++ b/Documentation/devicetree/bindings/media/rcar_vin.txt
@@ -54,6 +54,16 @@ from local SoC CSI-2 receivers (port1) depending on SoC.
   from external SoC pins described in video-interfaces.txt[1].
   Describing more then one endpoint in port 0 is invalid. Only VIN
   instances that are connected to external pins should have port 0.
+
+  - Optional properties for endpoint nodes of port@0:
+- hsync-active: active state of the HSYNC signal, 0/1 for LOW/HIGH
+ respectively. Default is active high.
+- vsync-active: active state of the VSYNC signal, 0/1 for LOW/HIGH
+ respectively. Default is active high.
+
+   If both HSYNC and VSYNC polarities are not specified, embedded
+   synchronization is selected.
+
 - port 1 - sub-nodes describing one or more endpoints connected to
   the VIN from local SoC CSI-2 receivers. The endpoint numbers must
   use the following schema.
@@ -63,6 +73,8 @@ from local SoC CSI-2 receivers (port1) depending on SoC.
 - Endpoint 2 - sub-node describing the endpoint connected to CSI40
 - Endpoint 3 - sub-node describing the endpoint connected to CSI41
 
+  Endpoint nodes of port@1 do not support any optional endpoint property.
+
 Device node example for Gen2 platforms
 --
 
@@ -113,7 +125,6 @@ Board setup example for Gen2 platforms (vin1 composite 
video input)
 
 vin1ep0: endpoint {
 remote-endpoint = <>;
-bus-width = <8>;
 };
 };
 };
-- 
2.7.4



[PATCH v2 2/4] dt-bindings: media: rcar-vin: Document data-active

2018-05-21 Thread Jacopo Mondi
Document 'data-active' property in R-Car VIN device tree bindings.

Signed-off-by: Jacopo Mondi 

v1 -> v2:
- HSYNC is used in place of data enable signal only when running with
  explicit synchronizations.
- The property is no more mandatory when running with embedded
  synchronizations, and default is selected.
---
 Documentation/devicetree/bindings/media/rcar_vin.txt | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt 
b/Documentation/devicetree/bindings/media/rcar_vin.txt
index dab3118..2c144b4 100644
--- a/Documentation/devicetree/bindings/media/rcar_vin.txt
+++ b/Documentation/devicetree/bindings/media/rcar_vin.txt
@@ -64,6 +64,12 @@ from local SoC CSI-2 receivers (port1) depending on SoC.
If both HSYNC and VSYNC polarities are not specified, embedded
synchronization is selected.
 
+- data-active: data enable signal line polarity (CLKENB pin).
+  0/1 for LOW/HIGH respectively. If not specified and running with
+ embedded synchronization, the default is active high. If not
+ specified and running with explicit synchronization, HSYNC is used
+ as data enable signal.
+
 - port 1 - sub-nodes describing one or more endpoints connected to
   the VIN from local SoC CSI-2 receivers. The endpoint numbers must
   use the following schema.
-- 
2.7.4



[PATCH v2 4/4] ARM: dts: rcar-gen2: Remove unused VIN properties

2018-05-21 Thread Jacopo Mondi
The 'bus-width' and 'pclk-sample' properties are not parsed by the VIN
driver and only confuse users. Remove them in all Gen2 SoC that use
them.

Signed-off-by: Jacopo Mondi 
---
 arch/arm/boot/dts/r8a7790-lager.dts   | 3 ---
 arch/arm/boot/dts/r8a7791-koelsch.dts | 3 ---
 arch/arm/boot/dts/r8a7791-porter.dts  | 1 -
 arch/arm/boot/dts/r8a7793-gose.dts| 3 ---
 arch/arm/boot/dts/r8a7794-alt.dts | 1 -
 arch/arm/boot/dts/r8a7794-silk.dts| 1 -
 6 files changed, 12 deletions(-)

diff --git a/arch/arm/boot/dts/r8a7790-lager.dts 
b/arch/arm/boot/dts/r8a7790-lager.dts
index 092610e..9cdabfcf 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -885,10 +885,8 @@
port {
vin0ep2: endpoint {
remote-endpoint = <_out>;
-   bus-width = <24>;
hsync-active = <0>;
vsync-active = <0>;
-   pclk-sample = <1>;
data-active = <1>;
};
};
@@ -904,7 +902,6 @@
port {
vin1ep0: endpoint {
remote-endpoint = <>;
-   bus-width = <8>;
};
};
 };
diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts 
b/arch/arm/boot/dts/r8a7791-koelsch.dts
index 8ab793d..033c9e3 100644
--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -857,10 +857,8 @@
port {
vin0ep2: endpoint {
remote-endpoint = <_out>;
-   bus-width = <24>;
hsync-active = <0>;
vsync-active = <0>;
-   pclk-sample = <1>;
data-active = <1>;
};
};
@@ -875,7 +873,6 @@
port {
vin1ep: endpoint {
remote-endpoint = <>;
-   bus-width = <8>;
};
};
 };
diff --git a/arch/arm/boot/dts/r8a7791-porter.dts 
b/arch/arm/boot/dts/r8a7791-porter.dts
index a01101b..c16e870 100644
--- a/arch/arm/boot/dts/r8a7791-porter.dts
+++ b/arch/arm/boot/dts/r8a7791-porter.dts
@@ -388,7 +388,6 @@
port {
vin0ep: endpoint {
remote-endpoint = <>;
-   bus-width = <8>;
};
};
 };
diff --git a/arch/arm/boot/dts/r8a7793-gose.dts 
b/arch/arm/boot/dts/r8a7793-gose.dts
index aa209f6..60aaddb 100644
--- a/arch/arm/boot/dts/r8a7793-gose.dts
+++ b/arch/arm/boot/dts/r8a7793-gose.dts
@@ -765,10 +765,8 @@
port {
vin0ep2: endpoint {
remote-endpoint = <_out>;
-   bus-width = <24>;
hsync-active = <0>;
vsync-active = <0>;
-   pclk-sample = <1>;
data-active = <1>;
};
};
@@ -784,7 +782,6 @@
port {
vin1ep: endpoint {
remote-endpoint = <_out>;
-   bus-width = <8>;
};
};
 };
diff --git a/arch/arm/boot/dts/r8a7794-alt.dts 
b/arch/arm/boot/dts/r8a7794-alt.dts
index e170275..8ed7a71 100644
--- a/arch/arm/boot/dts/r8a7794-alt.dts
+++ b/arch/arm/boot/dts/r8a7794-alt.dts
@@ -388,7 +388,6 @@
port {
vin0ep: endpoint {
remote-endpoint = <>;
-   bus-width = <8>;
};
};
 };
diff --git a/arch/arm/boot/dts/r8a7794-silk.dts 
b/arch/arm/boot/dts/r8a7794-silk.dts
index 7808aae..6adfcd6 100644
--- a/arch/arm/boot/dts/r8a7794-silk.dts
+++ b/arch/arm/boot/dts/r8a7794-silk.dts
@@ -477,7 +477,6 @@
port {
vin0ep: endpoint {
remote-endpoint = <>;
-   bus-width = <8>;
};
};
 };
-- 
2.7.4



[PATCH v2 3/4] media: rcar-vin: Handle CLOCKENB pin polarity

2018-05-21 Thread Jacopo Mondi
Handle CLOCKENB pin polarity, or use HSYNC in its place if polarity is
not specified and we're running on parallel data bus with explicit
synchronism signals.

While at there, simplify the media bus handling flags logic, inspecting
flags only if the system is running on parallel media bus type and ignore
flags when on CSI-2. Also change comments style to remove un-necessary
camel case and add a full stop at the end of sentences.

Signed-off-by: Jacopo Mondi 
---
 drivers/media/platform/rcar-vin/rcar-dma.c | 34 ++
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/drivers/media/platform/rcar-vin/rcar-dma.c 
b/drivers/media/platform/rcar-vin/rcar-dma.c
index 17f291f..ffd3d62 100644
--- a/drivers/media/platform/rcar-vin/rcar-dma.c
+++ b/drivers/media/platform/rcar-vin/rcar-dma.c
@@ -123,6 +123,8 @@
 /* Video n Data Mode Register 2 bits */
 #define VNDMR2_VPS (1 << 30)
 #define VNDMR2_HPS (1 << 29)
+#define VNDMR2_CES (1 << 28)
+#define VNDMR2_CHS (1 << 23)
 #define VNDMR2_FTEV(1 << 17)
 #define VNDMR2_VLV(n)  ((n & 0xf) << 12)
 
@@ -684,21 +686,35 @@ static int rvin_setup(struct rvin_dev *vin)
break;
}
 
-   /* Enable VSYNC Field Toogle mode after one VSYNC input */
+   /* Enable VSYNC field toggle mode after one VSYNC input. */
if (vin->info->model == RCAR_GEN3)
dmr2 = VNDMR2_FTEV;
else
dmr2 = VNDMR2_FTEV | VNDMR2_VLV(1);
 
-   /* Hsync Signal Polarity Select */
-   if (!vin->is_csi &&
-   !(vin->parallel->mbus_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
-   dmr2 |= VNDMR2_HPS;
+   /* Synchronism signal polarities: only for parallel data bus. */
+   if (!vin->is_csi) {
+   /* Hsync signal polarity select. */
+   if (!(vin->parallel->mbus_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
+   dmr2 |= VNDMR2_HPS;
 
-   /* Vsync Signal Polarity Select */
-   if (!vin->is_csi &&
-   !(vin->parallel->mbus_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
-   dmr2 |= VNDMR2_VPS;
+   /* Vsync signal polarity select. */
+   if (!(vin->parallel->mbus_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
+   dmr2 |= VNDMR2_VPS;
+
+   /*
+* Data enable signal polarity select.
+* Use HSYNC as data-enable if not specified and running
+* with explicit synchronizations; otherwise default 'high'
+* is selected.
+*/
+   if (vin->parallel->mbus_flags & V4L2_MBUS_DATA_ACTIVE_LOW)
+   dmr2 |= VNDMR2_CES;
+   else if (!(vin->parallel->mbus_flags &
+V4L2_MBUS_DATA_ACTIVE_HIGH) &&
+vin->parallel->mbus_type == V4L2_MBUS_PARALLEL)
+   dmr2 |= VNDMR2_CHS;
+   }
 
/*
 * Output format
-- 
2.7.4



[PATCH v2 0/4] media: rcar-vin: Brush endpoint properties

2018-05-21 Thread Jacopo Mondi
Hello,
   this series touches the bindings and the driver handling endpoint
properties for digital subdevices of the R-Car VIN driver.

The first patch simply documents what are the endpoint properties supported
at the moment while the second extends them with 'data-active' one.

As the VIN hardware allows to use HSYNC as data enable signal when the CLCKENB
pin is left unconnected, the 'data-active' property presence determinates
if HSYNC has to be used or not as data enable signal. Compared to v1, the
handling logic of this property has changed, and HSYNC is selected in its place
only when running V4L2_MBUS_PARALLEL media bus type. When running with
embedded synchronizations if the property is not specified, the default value
is used (this helps with retro-compatibility too).

I understand this may sound problematic. The property is optional, but when
not specified it may cause HSYNC to be used as data-active, which is not what
one may expect. Anyhow, the processor manual suggests this:

Note: When using ITU-R BT.601, BT.709, BT.1358 interface, and the
VIn_CLKENB pin is unused, the CHS bit must be set to 1.

So it seems reasonable to me.

Alternatively, a dedicated property, as 'renesas,chs' may be introduced, but
I don't particularly like this and I would prefer users to read bindings
documentation carefully, provided I wrote it clearly enough...

While this is still debated too, I left un-touched patch [4/4] that removes
un-used endpoint properties from all Gen-2 DTS that use them. Those properties
are not parsed by the driver nor documented by bindings, and their presence is
only confusing future users.

The series depends on:
[PATCH v3 0/9] rcar-vin: Add support for parallel input on Gen3

Available here for the interested:
git://jmondi.org d3/media-master/salvator-x-dts_csi2/d3-vin-driver-v3

Thanks
   j

v1 -> v2:
- Change data-active properties handling: the property is only considered
  when running with explicit synchronization signals.
- Drop patch 3/6 and 6/6 from v1 as they're not needed anymore as data-active
  handling logic changed.

Jacopo Mondi (4):
  dt-bindings: media: rcar-vin: Describe optional ep properties
  dt-bindings: media: rcar-vin: Document data-active
  media: rcar-vin: Handle CLOCKENB pin polarity
  ARM: dts: rcar-gen2: Remove unused VIN properties

 .../devicetree/bindings/media/rcar_vin.txt | 19 +++-
 arch/arm/boot/dts/r8a7790-lager.dts|  3 ---
 arch/arm/boot/dts/r8a7791-koelsch.dts  |  3 ---
 arch/arm/boot/dts/r8a7791-porter.dts   |  1 -
 arch/arm/boot/dts/r8a7793-gose.dts |  3 ---
 arch/arm/boot/dts/r8a7794-alt.dts  |  1 -
 arch/arm/boot/dts/r8a7794-silk.dts |  1 -
 drivers/media/platform/rcar-vin/rcar-dma.c | 25 ++
 8 files changed, 34 insertions(+), 22 deletions(-)

--
2.7.4



[PATCH v10 03/16] hackrf: group device capabilities

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

Instead of putting V4L2_CAP_STREAMING and V4L2_CAP_READWRITE
everywhere, set device_caps earlier with these values.

Signed-off-by: Gustavo Padovan 
---
 drivers/media/usb/hackrf/hackrf.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/media/usb/hackrf/hackrf.c 
b/drivers/media/usb/hackrf/hackrf.c
index 7eb53517a82f..6d692fb3e8dd 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -909,18 +909,15 @@ static int hackrf_querycap(struct file *file, void *fh,
 
dev_dbg(>dev, "\n");
 
+   cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
if (vdev->vfl_dir == VFL_DIR_RX)
-   cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER |
-  V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
-
+   cap->device_caps |= V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER;
else
-   cap->device_caps = V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR |
-  V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+   cap->device_caps |= V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR;
 
cap->capabilities = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_TUNER |
V4L2_CAP_SDR_OUTPUT | V4L2_CAP_MODULATOR |
-   V4L2_CAP_STREAMING | V4L2_CAP_READWRITE |
-   V4L2_CAP_DEVICE_CAPS;
+   V4L2_CAP_DEVICE_CAPS | cap->device_caps;
strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
strlcpy(cap->card, dev->rx_vdev.name, sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
-- 
2.16.3



[PATCH v10 01/16] videobuf2: Make struct vb2_buffer refcounted

2018-05-21 Thread Ezequiel Garcia
The in-fence implementation involves having a per-buffer fence callback,
that triggers on the fence signal. The fence callback is called asynchronously
and needs a valid reference to the associated ideobuf2 buffer.

Allow this by making the vb2_buffer refcounted, so it can be passed
to other contexts.

Signed-off-by: Ezequiel Garcia 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 27 ++---
 include/media/videobuf2-core.h  |  7 +--
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index d3f7bb33a54d..f1feb45c1e37 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -190,6 +190,26 @@ module_param(debug, int, 0644);
 static void __vb2_queue_cancel(struct vb2_queue *q);
 static void __enqueue_in_driver(struct vb2_buffer *vb);
 
+static void __vb2_buffer_free(struct kref *kref)
+{
+   struct vb2_buffer *vb =
+   container_of(kref, struct vb2_buffer, refcount);
+   kfree(vb);
+}
+
+static void __vb2_buffer_put(struct vb2_buffer *vb)
+{
+   if (vb)
+   kref_put(>refcount, __vb2_buffer_free);
+}
+
+static struct vb2_buffer *__vb2_buffer_get(struct vb2_buffer *vb)
+{
+   if (vb)
+   kref_get(>refcount);
+   return vb;
+}
+
 /*
  * __vb2_buf_mem_alloc() - allocate video memory for the given buffer
  */
@@ -346,6 +366,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum 
vb2_memory memory,
break;
}
 
+   kref_init(>refcount);
vb->state = VB2_BUF_STATE_DEQUEUED;
vb->vb2_queue = q;
vb->num_planes = num_planes;
@@ -365,7 +386,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum 
vb2_memory memory,
dprintk(1, "failed allocating memory for buffer 
%d\n",
buffer);
q->bufs[vb->index] = NULL;
-   kfree(vb);
+   __vb2_buffer_put(vb);
break;
}
__setup_offsets(vb);
@@ -380,7 +401,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum 
vb2_memory memory,
buffer, vb);
__vb2_buf_mem_free(vb);
q->bufs[vb->index] = NULL;
-   kfree(vb);
+   __vb2_buffer_put(vb);
break;
}
}
@@ -520,7 +541,7 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned 
int buffers)
/* Free videobuf buffers */
for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
 ++buffer) {
-   kfree(q->bufs[buffer]);
+   __vb2_buffer_put(q->bufs[buffer]);
q->bufs[buffer] = NULL;
}
 
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index f6818f732f34..baa4632c7e59 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -12,11 +12,12 @@
 #ifndef _MEDIA_VIDEOBUF2_CORE_H
 #define _MEDIA_VIDEOBUF2_CORE_H
 
+#include 
+#include 
+#include 
 #include 
 #include 
 #include 
-#include 
-#include 
 
 #define VB2_MAX_FRAME  (32)
 #define VB2_MAX_PLANES (8)
@@ -249,6 +250,7 @@ struct vb2_buffer {
 
/* private: internal use only
 *
+* refcount:refcount for this buffer
 * state:   current buffer state; do not change
 * queued_entry:entry on the queued buffers list, which holds
 *  all buffers queued from userspace
@@ -256,6 +258,7 @@ struct vb2_buffer {
 *  to be dequeued to userspace
 * vb2_plane:   per-plane information; do not change
 */
+   struct kref refcount;
enum vb2_buffer_state   state;
 
struct vb2_planeplanes[VB2_MAX_PLANES];
-- 
2.16.3



[PATCH v10 04/16] omap3isp: group device capabilities

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

Instead of putting V4L2_CAP_STREAMING everywhere, set device_caps
earlier with this value.

v2: move cap->capabilities assignment down (Hans Verkuil)

Signed-off-by: Gustavo Padovan 
---
 drivers/media/platform/omap3isp/ispvideo.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispvideo.c 
b/drivers/media/platform/omap3isp/ispvideo.c
index a751c89a3ea8..db9aae222134 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -658,13 +658,15 @@ isp_video_querycap(struct file *file, void *fh, struct 
v4l2_capability *cap)
strlcpy(cap->card, video->video.name, sizeof(cap->card));
strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
 
-   cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
-   | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
+   cap->device_caps = V4L2_CAP_STREAMING;
 
if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-   cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+   cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
else
-   cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+   cap->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
+
+   cap->capabilities = cap->device_caps | V4L2_CAP_VIDEO_CAPTURE |
+   V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_DEVICE_CAPS;
 
return 0;
 }
-- 
2.16.3



[PATCH v10 05/16] vb2: move vb2_ops functions to videobuf2-core.[ch]

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

vb2_ops_wait_prepare() and vb2_ops_wait_finish() were in the
wrong file.

Signed-off-by: Gustavo Padovan 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 14 ++
 drivers/media/common/videobuf2/videobuf2-v4l2.c | 14 --
 include/media/videobuf2-core.h  | 18 ++
 include/media/videobuf2-v4l2.h  | 18 --
 4 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index f1feb45c1e37..61e7b6407586 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -677,6 +677,20 @@ int vb2_verify_memory_type(struct vb2_queue *q,
 }
 EXPORT_SYMBOL(vb2_verify_memory_type);
 
+/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
+
+void vb2_ops_wait_prepare(struct vb2_queue *vq)
+{
+   mutex_unlock(vq->lock);
+}
+EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
+
+void vb2_ops_wait_finish(struct vb2_queue *vq)
+{
+   mutex_lock(vq->lock);
+}
+EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
+
 int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
unsigned int *count)
 {
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 886a2d8d5c6c..64503615d00b 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -947,20 +947,6 @@ unsigned long vb2_fop_get_unmapped_area(struct file *file, 
unsigned long addr,
 EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
 #endif
 
-/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
-
-void vb2_ops_wait_prepare(struct vb2_queue *vq)
-{
-   mutex_unlock(vq->lock);
-}
-EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
-
-void vb2_ops_wait_finish(struct vb2_queue *vq)
-{
-   mutex_lock(vq->lock);
-}
-EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
-
 MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
 MODULE_AUTHOR("Pawel Osciak , Marek Szyprowski");
 MODULE_LICENSE("GPL");
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index baa4632c7e59..137f72702101 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -403,6 +403,24 @@ struct vb2_ops {
void (*buf_queue)(struct vb2_buffer *vb);
 };
 
+/**
+ * vb2_ops_wait_prepare - helper function to lock a struct _queue
+ *
+ * @vq: pointer to  vb2_queue
+ *
+ * ..note:: only use if vq->lock is non-NULL.
+ */
+void vb2_ops_wait_prepare(struct vb2_queue *vq);
+
+/**
+ * vb2_ops_wait_finish - helper function to unlock a struct _queue
+ *
+ * @vq: pointer to  vb2_queue
+ *
+ * ..note:: only use if vq->lock is non-NULL.
+ */
+void vb2_ops_wait_finish(struct vb2_queue *vq);
+
 /**
  * struct vb2_buf_ops - driver-specific callbacks.
  *
diff --git a/include/media/videobuf2-v4l2.h b/include/media/videobuf2-v4l2.h
index 3d5e2d739f05..cf83b01dc44e 100644
--- a/include/media/videobuf2-v4l2.h
+++ b/include/media/videobuf2-v4l2.h
@@ -273,22 +273,4 @@ unsigned long vb2_fop_get_unmapped_area(struct file *file, 
unsigned long addr,
unsigned long len, unsigned long pgoff, unsigned long flags);
 #endif
 
-/**
- * vb2_ops_wait_prepare - helper function to lock a struct _queue
- *
- * @vq: pointer to  vb2_queue
- *
- * ..note:: only use if vq->lock is non-NULL.
- */
-void vb2_ops_wait_prepare(struct vb2_queue *vq);
-
-/**
- * vb2_ops_wait_finish - helper function to unlock a struct _queue
- *
- * @vq: pointer to  vb2_queue
- *
- * ..note:: only use if vq->lock is non-NULL.
- */
-void vb2_ops_wait_finish(struct vb2_queue *vq);
-
 #endif /* _MEDIA_VIDEOBUF2_V4L2_H */
-- 
2.16.3



[PATCH v10 06/16] vb2: add is_unordered callback for drivers

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

Explicit synchronization benefits a lot from ordered queues, they fit
better in a pipeline with DRM for example so create a opt-in way for
drivers notify videobuf2 that the queue is unordered.

Drivers don't need implement it if the queue is ordered.

v5: rename it to vb2_ops_is_unordered() (Hans Verkuil)

v4: go back to a bitfield property for the unordered property.

v3: - make it bool (Hans)
- create vb2_ops_set_unordered() helper

v2: - improve comments for is_unordered flag (Hans Verkuil)

Signed-off-by: Gustavo Padovan 
---
 drivers/media/common/videobuf2/videobuf2-core.c |  6 ++
 include/media/videobuf2-core.h  | 16 
 2 files changed, 22 insertions(+)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 61e7b6407586..a9a0a9d1decb 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -691,6 +691,12 @@ void vb2_ops_wait_finish(struct vb2_queue *vq)
 }
 EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
 
+bool vb2_ops_is_unordered(struct vb2_queue *q)
+{
+   return true;
+}
+EXPORT_SYMBOL_GPL(vb2_ops_is_unordered);
+
 int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
unsigned int *count)
 {
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 137f72702101..71538ae2c255 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -376,6 +376,10 @@ struct vb2_buffer {
  * callback by calling vb2_buffer_done() with either
  * %VB2_BUF_STATE_DONE or %VB2_BUF_STATE_ERROR; may use
  * vb2_wait_for_all_buffers() function
+ * @is_unordered:  tell if the queue is unordered, i.e. buffers can be
+ * dequeued in a different order from how they were queued.
+ * The default is assumed to be ordered and this function
+ * only needs to be implemented for unordered queues.
  * @buf_queue: passes buffer vb to the driver; driver may start
  * hardware operation on this buffer; driver should give
  * the buffer back by calling vb2_buffer_done() function;
@@ -399,6 +403,7 @@ struct vb2_ops {
 
int (*start_streaming)(struct vb2_queue *q, unsigned int count);
void (*stop_streaming)(struct vb2_queue *q);
+   bool (*is_unordered)(struct vb2_queue *q);
 
void (*buf_queue)(struct vb2_buffer *vb);
 };
@@ -421,6 +426,16 @@ void vb2_ops_wait_prepare(struct vb2_queue *vq);
  */
 void vb2_ops_wait_finish(struct vb2_queue *vq);
 
+/**
+ * vb2_ops_is_unordered - helper function to check if queue is unordered
+ *
+ * @vq: pointer to  vb2_queue
+ *
+ * This helper just returns true to notify that the driver can't deal with
+ * ordered queues.
+ */
+bool vb2_ops_is_unordered(struct vb2_queue *q);
+
 /**
  * struct vb2_buf_ops - driver-specific callbacks.
  *
@@ -590,6 +605,7 @@ struct vb2_queue {
u32 cnt_wait_finish;
u32 cnt_start_streaming;
u32 cnt_stop_streaming;
+   u32 cnt_is_unordered;
 #endif
 };
 
-- 
2.16.3



[PATCH v10 07/16] v4l: add unordered flag to format description ioctl

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

For explicit synchronization it important for userspace to know if the
format being used by the driver can deliver the buffers back to userspace
in the same order they were queued with QBUF.

Ordered streams fits nicely in a pipeline with DRM for example, where
ordered buffer are expected.

v2: Improve documentation (Hans)

Signed-off-by: Gustavo Padovan 
---
 Documentation/media/uapi/v4l/vidioc-enum-fmt.rst | 7 +++
 include/uapi/linux/videodev2.h   | 1 +
 2 files changed, 8 insertions(+)

diff --git a/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst 
b/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst
index 019c513df217..df8e039b9ac2 100644
--- a/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst
+++ b/Documentation/media/uapi/v4l/vidioc-enum-fmt.rst
@@ -116,6 +116,13 @@ one until ``EINVAL`` is returned.
   - This format is not native to the device but emulated through
software (usually libv4l2), where possible try to use a native
format instead for better performance.
+* - ``V4L2_FMT_FLAG_UNORDERED``
+  - 0x0004
+  - This format doesn't guarantee ordered buffer handling. I.e. the order
+   in which buffers are dequeued with
+   :ref:`VIDIOC_DQBUF ` may be different
+   from the order in which they were queued with
+   :ref:`VIDIOC_QBUF `.
 
 
 Return Value
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 600877be5c22..a8842a5ca636 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -717,6 +717,7 @@ struct v4l2_fmtdesc {
 
 #define V4L2_FMT_FLAG_COMPRESSED 0x0001
 #define V4L2_FMT_FLAG_EMULATED   0x0002
+#define V4L2_FMT_FLAG_UNORDERED  0x0004
 
/* Frame Size and frame rate enumeration */
 /*
-- 
2.16.3



[PATCH v10 08/16] v4l: mark unordered formats

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

Now that we've introduced the V4L2_FMT_FLAG_UNORDERED flag,
mark the appropriate formats.

v2: Set unordered flag before calling the driver callback.

Signed-off-by: Gustavo Padovan 
Signed-off-by: Ezequiel Garcia 
---
 drivers/media/v4l2-core/v4l2-ioctl.c | 74 +++-
 1 file changed, 57 insertions(+), 17 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index f48c505550e0..2135ac235a96 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -1102,6 +1102,27 @@ static int v4l_enumoutput(const struct v4l2_ioctl_ops 
*ops,
return ops->vidioc_enum_output(file, fh, p);
 }
 
+static void v4l_fill_unordered_fmtdesc(struct v4l2_fmtdesc *fmt)
+{
+   switch (fmt->pixelformat) {
+   case V4L2_PIX_FMT_MPEG:
+   case V4L2_PIX_FMT_H264:
+   case V4L2_PIX_FMT_H264_NO_SC:
+   case V4L2_PIX_FMT_H264_MVC:
+   case V4L2_PIX_FMT_H263:
+   case V4L2_PIX_FMT_MPEG1:
+   case V4L2_PIX_FMT_MPEG2:
+   case V4L2_PIX_FMT_MPEG4:
+   case V4L2_PIX_FMT_XVID:
+   case V4L2_PIX_FMT_VC1_ANNEX_G:
+   case V4L2_PIX_FMT_VC1_ANNEX_L:
+   case V4L2_PIX_FMT_VP8:
+   case V4L2_PIX_FMT_VP9:
+   case V4L2_PIX_FMT_HEVC:
+   fmt->flags |= V4L2_FMT_FLAG_UNORDERED;
+   }
+}
+
 static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
 {
const unsigned sz = sizeof(fmt->description);
@@ -1310,61 +1331,80 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt)
 
if (descr)
WARN_ON(strlcpy(fmt->description, descr, sz) >= sz);
-   fmt->flags = flags;
+   fmt->flags |= flags;
 }
 
-static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
-   struct file *file, void *fh, void *arg)
-{
-   struct v4l2_fmtdesc *p = arg;
-   int ret = check_fmt(file, p->type);
 
-   if (ret)
-   return ret;
-   ret = -EINVAL;
+static int __vidioc_enum_fmt(const struct v4l2_ioctl_ops *ops,
+struct v4l2_fmtdesc *p,
+struct file *file, void *fh)
+{
+   int ret = 0;
 
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (unlikely(!ops->vidioc_enum_fmt_vid_cap))
break;
-   ret = ops->vidioc_enum_fmt_vid_cap(file, fh, arg);
+   ret = ops->vidioc_enum_fmt_vid_cap(file, fh, p);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (unlikely(!ops->vidioc_enum_fmt_vid_cap_mplane))
break;
-   ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg);
+   ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, p);
break;
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
if (unlikely(!ops->vidioc_enum_fmt_vid_overlay))
break;
-   ret = ops->vidioc_enum_fmt_vid_overlay(file, fh, arg);
+   ret = ops->vidioc_enum_fmt_vid_overlay(file, fh, p);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
if (unlikely(!ops->vidioc_enum_fmt_vid_out))
break;
-   ret = ops->vidioc_enum_fmt_vid_out(file, fh, arg);
+   ret = ops->vidioc_enum_fmt_vid_out(file, fh, p);
break;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
if (unlikely(!ops->vidioc_enum_fmt_vid_out_mplane))
break;
-   ret = ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
+   ret = ops->vidioc_enum_fmt_vid_out_mplane(file, fh, p);
break;
case V4L2_BUF_TYPE_SDR_CAPTURE:
if (unlikely(!ops->vidioc_enum_fmt_sdr_cap))
break;
-   ret = ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
+   ret = ops->vidioc_enum_fmt_sdr_cap(file, fh, p);
break;
case V4L2_BUF_TYPE_SDR_OUTPUT:
if (unlikely(!ops->vidioc_enum_fmt_sdr_out))
break;
-   ret = ops->vidioc_enum_fmt_sdr_out(file, fh, arg);
+   ret = ops->vidioc_enum_fmt_sdr_out(file, fh, p);
break;
case V4L2_BUF_TYPE_META_CAPTURE:
if (unlikely(!ops->vidioc_enum_fmt_meta_cap))
break;
-   ret = ops->vidioc_enum_fmt_meta_cap(file, fh, arg);
+   ret = ops->vidioc_enum_fmt_meta_cap(file, fh, p);
break;
}
+   return ret;
+}
+
+static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
+   struct file *file, void *fh, void *arg)
+{
+   struct v4l2_fmtdesc *p = arg;
+   int ret = check_fmt(file, p->type);
+
+   if (ret)
+   return ret;

[PATCH v10 10/16] vb2: mark codec drivers as unordered

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

In preparation to have full support to explicit fence we are
marking codec as non-ordered preventively. It is easier and safer from an
uAPI point of view to move from unordered to ordered than the opposite.

v2: mark only codec drivers as unordered (Nicolas and Hans)

Signed-off-by: Gustavo Padovan 
Signed-off-by: Ezequiel Garcia 
---
 drivers/media/platform/coda/coda-common.c  | 1 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 1 +
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c | 1 +
 drivers/media/platform/qcom/venus/vdec.c   | 1 +
 drivers/media/platform/qcom/venus/venc.c   | 1 +
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c   | 1 +
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c   | 1 +
 7 files changed, 7 insertions(+)

diff --git a/drivers/media/platform/coda/coda-common.c 
b/drivers/media/platform/coda/coda-common.c
index 04e35d70ce2e..cac36a11efa2 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -1649,6 +1649,7 @@ static const struct vb2_ops coda_qops = {
.stop_streaming = coda_stop_streaming,
.wait_prepare   = vb2_ops_wait_prepare,
.wait_finish= vb2_ops_wait_finish,
+   .is_unordered   = vb2_ops_is_unordered,
 };
 
 static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
index 86f0a7134365..a4a02f3790fa 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
@@ -1445,6 +1445,7 @@ static const struct vb2_ops mtk_vdec_vb2_ops = {
.buf_finish = vb2ops_vdec_buf_finish,
.start_streaming= vb2ops_vdec_start_streaming,
.stop_streaming = vb2ops_vdec_stop_streaming,
+   .is_unordered   = vb2_ops_is_unordered,
 };
 
 const struct v4l2_ioctl_ops mtk_vdec_ioctl_ops = {
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
index 1b1a28abbf1f..d37d670346b9 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c
@@ -931,6 +931,7 @@ static const struct vb2_ops mtk_venc_vb2_ops = {
.wait_finish= vb2_ops_wait_finish,
.start_streaming= vb2ops_venc_start_streaming,
.stop_streaming = vb2ops_venc_stop_streaming,
+   .is_unordered   = vb2_ops_is_unordered,
 };
 
 static int mtk_venc_encode_header(void *priv)
diff --git a/drivers/media/platform/qcom/venus/vdec.c 
b/drivers/media/platform/qcom/venus/vdec.c
index 49bbd1861d3a..8d7b4fc95880 100644
--- a/drivers/media/platform/qcom/venus/vdec.c
+++ b/drivers/media/platform/qcom/venus/vdec.c
@@ -794,6 +794,7 @@ static const struct vb2_ops vdec_vb2_ops = {
.start_streaming = vdec_start_streaming,
.stop_streaming = venus_helper_vb2_stop_streaming,
.buf_queue = venus_helper_vb2_buf_queue,
+   .is_unordered = vb2_ops_is_unordered,
 };
 
 static void vdec_buf_done(struct venus_inst *inst, unsigned int buf_type,
diff --git a/drivers/media/platform/qcom/venus/venc.c 
b/drivers/media/platform/qcom/venus/venc.c
index 6b2ce479584e..713c79ba9639 100644
--- a/drivers/media/platform/qcom/venus/venc.c
+++ b/drivers/media/platform/qcom/venus/venc.c
@@ -983,6 +983,7 @@ static const struct vb2_ops venc_vb2_ops = {
.start_streaming = venc_start_streaming,
.stop_streaming = venus_helper_vb2_stop_streaming,
.buf_queue = venus_helper_vb2_buf_queue,
+   .is_unordered = vb2_ops_is_unordered,
 };
 
 static void venc_buf_done(struct venus_inst *inst, unsigned int buf_type,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 5cf4d9921264..4402a5d621b2 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -1105,6 +1105,7 @@ static struct vb2_ops s5p_mfc_dec_qops = {
.start_streaming= s5p_mfc_start_streaming,
.stop_streaming = s5p_mfc_stop_streaming,
.buf_queue  = s5p_mfc_buf_queue,
+   .is_unordered   = vb2_ops_is_unordered,
 };
 
 const struct s5p_mfc_codec_ops *get_dec_codec_ops(void)
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c 
b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index 5c0462ca9993..376bd8eab8d8 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -2613,6 +2613,7 @@ static struct vb2_ops s5p_mfc_enc_qops = {
.start_streaming= s5p_mfc_start_streaming,
.stop_streaming = s5p_mfc_stop_streaming,
.buf_queue  = s5p_mfc_buf_queue,
+   .is_unordered   = 

[PATCH v10 09/16] cobalt: add .is_unordered() for cobalt

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

The cobalt driver may reorder the capture buffers so we need to report
it as such.

v3: set formats as unordered
v2: use vb2_ops_set_unordered() helper

Signed-off-by: Gustavo Padovan 
Signed-off-by: Ezequiel Garcia 
---
 drivers/media/pci/cobalt/cobalt-v4l2.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/media/pci/cobalt/cobalt-v4l2.c 
b/drivers/media/pci/cobalt/cobalt-v4l2.c
index e2a4c705d353..ccca1a96df90 100644
--- a/drivers/media/pci/cobalt/cobalt-v4l2.c
+++ b/drivers/media/pci/cobalt/cobalt-v4l2.c
@@ -430,6 +430,7 @@ static const struct vb2_ops cobalt_qops = {
.stop_streaming = cobalt_stop_streaming,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
+   .is_unordered = vb2_ops_is_unordered,
 };
 
 /* V4L2 ioctls */
@@ -695,14 +696,17 @@ static int cobalt_enum_fmt_vid_cap(struct file *file, 
void *priv_fh,
case 0:
strlcpy(f->description, "YUV 4:2:2", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_YUYV;
+   f->flags |= V4L2_FMT_FLAG_UNORDERED;
break;
case 1:
strlcpy(f->description, "RGB24", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_RGB24;
+   f->flags |= V4L2_FMT_FLAG_UNORDERED;
break;
case 2:
strlcpy(f->description, "RGB32", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_BGR32;
+   f->flags |= V4L2_FMT_FLAG_UNORDERED;
break;
default:
return -EINVAL;
-- 
2.16.3



[PATCH v10 13/16] vb2: add out-fence support to QBUF

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

If V4L2_BUF_FLAG_OUT_FENCE flag is present on the QBUF call we create
an out_fence and send its fd to userspace in the fence_fd field as a
return arg for the QBUF call.

The fence is signaled on buffer_done(), when the job on the buffer is
finished.

v12: - Pass the fence_fd in vb2_qbuf for clarity.
 - Increase fence seqno if fence context if shared
 - Check get_unused_fd return

v11: - Return fence_fd to userpace only in the QBUF ioctl.
 - Rework implementation to avoid storing the sync_file
   as state, which is not really needed.

v10: - use -EIO for fence error (Hans Verkuil)
 - add comment around fence context creation (Hans Verkuil)

v9: - remove in-fences changes from this patch (Alex Courbot)
- improve fence context creation (Hans Verkuil)
- clean up out fences if vb2_core_qbuf() fails (Hans Verkuil)

v8: - return 0 as fence_fd if OUT_FENCE flag not used (Mauro)
- fix crash when checking not using fences in vb2_buffer_done()

v7: - merge patch that add the infrastructure to out-fences into
  this one (Alex Courbot)
- Do not install the fd if there is no fence. (Alex Courbot)
- do not report error on requeueing, just WARN_ON_ONCE() (Hans)

v6: - get rid of the V4L2_EVENT_OUT_FENCE event. We always keep the
  ordering in vb2 for queueing in the driver, so the event is not
  necessary anymore and the out_fence_fd is sent back to userspace
  on QBUF call return arg
- do not allow requeueing with out-fences, instead mark the buffer
  with an error and wake up to userspace.
- send the out_fence_fd back to userspace on the fence_fd field

v5: - delay fd_install to DQ_EVENT (Hans)
- if queue is fully ordered send OUT_FENCE event right away
  (Brian)
- rename 'q->ordered' to 'q->ordered_in_driver'
- merge change to implement OUT_FENCE event here

v4: - return the out_fence_fd in the BUF_QUEUED event(Hans)

v3: - add WARN_ON_ONCE(q->ordered) on requeueing (Hans)
- set the OUT_FENCE flag if there is a fence pending (Hans)
- call fd_install() after vb2_core_qbuf() (Hans)
- clean up fence if vb2_core_qbuf() fails (Hans)
- add list to store sync_file and fence for the next queued buffer

v2: check if the queue is ordered.

Signed-off-by: Gustavo Padovan 
Signed-off-by: Ezequiel Garcia 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 113 +++-
 drivers/media/common/videobuf2/videobuf2-v4l2.c |  10 ++-
 drivers/media/dvb-core/dvb_vb2.c|   2 +-
 include/media/videobuf2-core.h  |  20 -
 4 files changed, 136 insertions(+), 9 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 86b5ebe25263..edc2fdaf56de 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -380,6 +381,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum 
vb2_memory memory,
vb->planes[plane].length = plane_sizes[plane];
vb->planes[plane].min_length = plane_sizes[plane];
}
+   vb->out_fence_fd = -1;
q->bufs[vb->index] = vb;
 
/* Allocate video buffer memory for the MMAP type */
@@ -976,10 +978,22 @@ static void vb2_process_buffer_done(struct vb2_buffer 
*vb, enum vb2_buffer_state
case VB2_BUF_STATE_QUEUED:
return;
case VB2_BUF_STATE_REQUEUEING:
+   /* Requeuing with explicit synchronization, spit warning */
+   WARN_ON_ONCE(vb->out_fence);
+
if (q->start_streaming_called)
__enqueue_in_driver(vb);
return;
default:
+   if (vb->out_fence) {
+   if (state == VB2_BUF_STATE_ERROR)
+   dma_fence_set_error(vb->out_fence, -EIO);
+   dma_fence_signal(vb->out_fence);
+   dma_fence_put(vb->out_fence);
+   vb->out_fence = NULL;
+   vb->out_fence_fd = -1;
+   }
+
/* Inform any processes that may be waiting for buffers */
wake_up(>done_wq);
break;
@@ -1406,6 +1420,76 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned 
int index, void *pb)
 }
 EXPORT_SYMBOL_GPL(vb2_core_prepare_buf);
 
+static inline const char *vb2_fence_get_driver_name(struct dma_fence *fence)
+{
+   return "vb2_fence";
+}
+
+static inline const char *vb2_fence_get_timeline_name(struct dma_fence *fence)
+{
+   return "vb2_fence_timeline";
+}
+
+static inline bool vb2_fence_enable_signaling(struct dma_fence *fence)
+{
+   return true;
+}
+
+static const struct 

[PATCH v10 12/16] vb2: add in-fence support to QBUF

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

Receive in-fence from userspace and add support for waiting on them
before queueing the buffer to the driver. Buffers can't be queued to the
driver before its fences signal. And a buffer can't be queued to the driver
out of the order they were queued from userspace. That means that even if
its fence signals it must wait for all other buffers, ahead of it in the queue,
to signal first.

If the fence for some buffer fails we do not queue it to the driver,
instead we mark it as error and wait until the previous buffer is done
to notify userspace of the error. We wait here to deliver the buffers back
to userspace in order.

v13: - cleanup implementation.
 - remove wrong Kconfig changes.
 - print noisy warning on unexpected enqueue conditioin
 - schedule a vb2_start_streaming work from the fence callback

v12: fixed dvb_vb2.c usage of vb2_core_qbuf.

v11: - minor doc/comments fixes (Hans Verkuil)
 - reviewed the in-fence path at __fill_v4l2_buffer()

v10: - rename fence to in_fence in many places
 - handle fences signalling with error better (Hans Verkuil)

v9: - improve comments and docs (Hans Verkuil)
- fix unlocking of vb->fence_cb_lock on vb2_core_qbuf (Hans Verkuil)
- move in-fences code that was in the out-fences patch here (Alex)

v8: - improve comments about fences with errors

v7: - get rid of the fence array stuff for ordering and just use
  get_num_buffers_ready() (Hans)
- fix issue of queuing the buffer twice (Hans)
- avoid the dma_fence_wait() in core_qbuf() (Alex)
- merge preparation commit in

v6: - With fences always keep the order userspace queues the buffers.
- Protect in_fence manipulation with a lock (Brian Starkey)
- check if fences have the same context before adding a fence array
- Fix last_fence ref unbalance in __set_in_fence() (Brian Starkey)
- Clean up fence if __set_in_fence() fails (Brian Starkey)
- treat -EINVAL from dma_fence_add_callback() (Brian Starkey)

v5: - use fence_array to keep buffers ordered in vb2 core when
  needed (Brian Starkey)
- keep backward compat on the reserved2 field (Brian Starkey)
- protect fence callback removal with lock (Brian Starkey)

v4: - Add a comment about dma_fence_add_callback() not returning a
  error (Hans)
- Call dma_fence_put(vb->in_fence) if fence signaled (Hans)
- select SYNC_FILE under config VIDEOBUF2_CORE (Hans)
- Move dma_fence_is_signaled() check to __enqueue_in_driver() (Hans)
- Remove list_for_each_entry() in __vb2_core_qbuf() (Hans)
- Remove if (vb->state != VB2_BUF_STATE_QUEUED) from
  vb2_start_streaming() (Hans)
- set IN_FENCE flags on __fill_v4l2_buffer (Hans)
- Queue buffers to the driver as soon as they are ready (Hans)
- call fill_user_buffer() after queuing the buffer (Hans)
- add err: label to clean up fence
- add dma_fence_wait() before calling vb2_start_streaming()

v3: - document fence parameter
- remove ternary if at vb2_qbuf() return (Mauro)
- do not change if conditions behaviour (Mauro)

v2: - fix vb2_queue_or_prepare_buf() ret check
- remove check for VB2_MEMORY_DMABUF only (Javier)
- check num of ready buffers to start streaming
- when queueing, start from the first ready buffer
- handle queue cancel

Signed-off-by: Gustavo Padovan 
Signed-off-by: Ezequiel Garcia 
---
 drivers/media/common/videobuf2/Kconfig  |   1 +
 drivers/media/common/videobuf2/videobuf2-core.c | 224 
 drivers/media/common/videobuf2/videobuf2-v4l2.c |  37 +++-
 drivers/media/dvb-core/dvb_vb2.c|   2 +-
 include/media/videobuf2-core.h  |  19 +-
 5 files changed, 242 insertions(+), 41 deletions(-)

diff --git a/drivers/media/common/videobuf2/Kconfig 
b/drivers/media/common/videobuf2/Kconfig
index 17c32ea58395..27ad9e8a268b 100644
--- a/drivers/media/common/videobuf2/Kconfig
+++ b/drivers/media/common/videobuf2/Kconfig
@@ -1,6 +1,7 @@
 # Used by drivers that need Videobuf2 modules
 config VIDEOBUF2_CORE
select DMA_SHARED_BUFFER
+   select SYNC_FILE
tristate
 
 config VIDEOBUF2_V4L2
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index a9a0a9d1decb..86b5ebe25263 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -27,6 +27,7 @@
 #include 
 
 #include 
+#include 
 #include 
 
 #include 
@@ -189,6 +190,7 @@ module_param(debug, int, 0644);
 
 static void __vb2_queue_cancel(struct vb2_queue *q);
 static void __enqueue_in_driver(struct vb2_buffer *vb);
+static void __qbuf_work(struct work_struct *work);
 
 static void __vb2_buffer_free(struct kref *kref)
 {
@@ -373,6 +375,7 @@ static int __vb2_queue_alloc(struct vb2_queue *q, enum 
vb2_memory memory,
vb->index = 

[PATCH v10 11/16] vb2: add explicit fence user API

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

Turn the reserved2 field into fence_fd that we will use to send
an in-fence to the kernel or return an out-fence from the kernel to
userspace.

Two new flags were added, V4L2_BUF_FLAG_IN_FENCE, that should be used
when sending an in-fence to the kernel to be waited on, and
V4L2_BUF_FLAG_OUT_FENCE, to ask the kernel to give back an out-fence.

v8: return -1 if new flags are set.
v7: minor fixes on the Documentation (Hans Verkuil)

v6: big improvement on doc (Hans Verkuil)

v5: - keep using reserved2 field for cpia2
- set fence_fd to 0 for now, for compat with userspace(Mauro)

v4: make it a union with reserved2 and fence_fd (Hans Verkuil)

v3: make the out_fence refer to the current buffer (Hans Verkuil)

v2: add documentation

Signed-off-by: Gustavo Padovan 
---
 Documentation/media/uapi/v4l/buffer.rst | 48 ++---
 drivers/media/common/videobuf2/videobuf2-v4l2.c |  6 +++-
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c   |  4 +--
 include/uapi/linux/videodev2.h  |  8 -
 4 files changed, 58 insertions(+), 8 deletions(-)

diff --git a/Documentation/media/uapi/v4l/buffer.rst 
b/Documentation/media/uapi/v4l/buffer.rst
index e2c85ddc990b..971b7453040c 100644
--- a/Documentation/media/uapi/v4l/buffer.rst
+++ b/Documentation/media/uapi/v4l/buffer.rst
@@ -300,11 +300,23 @@ struct v4l2_buffer
multi-planar API the application sets this to the number of
elements in the ``planes`` array. The driver will fill in the
actual number of valid elements in that array.
-* - __u32
-  - ``reserved2``
+* - __s32
+  - ``fence_fd``
   -
-  - A place holder for future extensions. Drivers and applications
-   must set this to 0.
+  - Used to communicate a fence file descriptor from userspace to kernel
+   and vice-versa. On :ref:`VIDIOC_QBUF ` when sending
+   an in-fence for V4L2 to wait on, the ``V4L2_BUF_FLAG_IN_FENCE`` flag 
must
+   be used and this field set to the fence file descriptor of the in-fence.
+   If the in-fence is not valid ` VIDIOC_QBUF`` returns an error.
+
+To get an out-fence back from V4L2 the ``V4L2_BUF_FLAG_OUT_FENCE``
+   must be set, the kernel will return the out-fence file descriptor in
+   this field. If it fails to create the out-fence ``VIDIOC_QBUF` returns
+an error.
+
+   For all other ioctls V4L2 sets this field to -1 if
+   ``V4L2_BUF_FLAG_IN_FENCE`` and/or ``V4L2_BUF_FLAG_OUT_FENCE`` are set,
+   otherwise this field is set to 0 for backward compatibility.
 * - __u32
   - ``reserved``
   -
@@ -648,6 +660,34 @@ Buffer Flags
   - Start Of Exposure. The buffer timestamp has been taken when the
exposure of the frame has begun. This is only valid for the
``V4L2_BUF_TYPE_VIDEO_CAPTURE`` buffer type.
+* .. _`V4L2-BUF-FLAG-IN-FENCE`:
+
+  - ``V4L2_BUF_FLAG_IN_FENCE``
+  - 0x0020
+  - Ask V4L2 to wait on the fence passed in the ``fence_fd`` field. The
+   buffer won't be queued to the driver until the fence signals. The order
+   in which buffers are queued is guaranteed to be preserved, so any
+   buffers queued after this buffer will also be blocked until this fence
+   signals. This flag must be set before calling ``VIDIOC_QBUF``. For
+   other ioctls the driver just reports the value of the flag.
+
+If the fence signals the flag is cleared and not reported anymore.
+   If the fence is not valid ``VIDIOC_QBUF`` returns an error.
+* .. _`V4L2-BUF-FLAG-OUT-FENCE`:
+
+  - ``V4L2_BUF_FLAG_OUT_FENCE``
+  - 0x0040
+  - Request for a fence to be attached to the buffer. The driver will fill
+   in the out-fence fd in the ``fence_fd`` field when :ref:`VIDIOC_QBUF
+   ` returns. This flag must be set before calling
+   ``VIDIOC_QBUF``. This flag is only an input, and is not set by the 
kernel.
+
+If the creation of the out-fence fails ``VIDIOC_QBUF`` returns an
+   error.
+
+Note that it is valid to set both ``V4L2_BUF_FLAG_IN_FENCE`` and
+`V4L2_BUF_FLAG_OUT_FENCE`` flags. In such case, the ``fence_fd``
+field is used to both set the in-fence and return the out-fence.
 
 
 
diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index 64503615d00b..8312f61adfa6 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -203,9 +203,13 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void 
*pb)
b->timestamp = ns_to_timeval(vb->timestamp);
b->timecode = vbuf->timecode;
b->sequence = vbuf->sequence;
-   b->reserved2 = 0;
b->reserved = 0;
 
+   if (b->flags & (V4L2_BUF_FLAG_IN_FENCE | V4L2_BUF_FLAG_OUT_FENCE))
+   b->fence_fd = -1;
+   else
+   

[PATCH v10 15/16] v4l: Add V4L2_CAP_FENCES to drivers

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

Drivers that use videobuf2 are capable of using fences and
should report that to userspace.

v10: - Add CAPS_FENCES to drivers that don't use fh->m2m_ctx.
 - Keep the ifdef V4L2_MEM2MEM_DEV.
 - Set CAPS_FENCES after vidioc_querycap.
v9: Add in the core.

Signed-off-by: Gustavo Padovan 
Signed-off-by: Ezequiel Garcia 
---
 drivers/media/platform/exynos-gsc/gsc-m2m.c|  3 ++-
 drivers/media/platform/m2m-deinterlace.c   |  3 ++-
 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c   |  3 ++-
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c |  2 +-
 .../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c |  3 ++-
 drivers/media/platform/mx2_emmaprp.c   |  3 ++-
 drivers/media/platform/qcom/venus/vdec.c   |  3 ++-
 drivers/media/platform/qcom/venus/venc.c   |  3 ++-
 drivers/media/platform/sh_veu.c|  3 ++-
 drivers/media/v4l2-core/v4l2-ioctl.c   | 24 +-
 10 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c 
b/drivers/media/platform/exynos-gsc/gsc-m2m.c
index e9ff27949a91..fbf072c8aedd 100644
--- a/drivers/media/platform/exynos-gsc/gsc-m2m.c
+++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c
@@ -298,7 +298,8 @@ static int gsc_m2m_querycap(struct file *file, void *fh,
strlcpy(cap->card, GSC_MODULE_NAME " gscaler", sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
 dev_name(>pdev->dev));
-   cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE;
+   cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE |
+  V4L2_CAP_FENCES;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
 }
diff --git a/drivers/media/platform/m2m-deinterlace.c 
b/drivers/media/platform/m2m-deinterlace.c
index 1e4195144f39..b7421de1268f 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -461,7 +461,8 @@ static int vidioc_querycap(struct file *file, void *priv,
 * and are scheduled for removal.
 */
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
-  V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
+  V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING |
+  V4L2_CAP_FENCES;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 
return 0;
diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c 
b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
index 583d47724ee8..7aba2ba128ba 100644
--- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
+++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c
@@ -1242,7 +1242,8 @@ int mtk_mdp_register_m2m_device(struct mtk_mdp_dev *mdp)
ret = -ENOMEM;
goto err_video_alloc;
}
-   mdp->vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
+   mdp->vdev->device_caps = V4L2_CAP_FENCES | V4L2_CAP_VIDEO_M2M_MPLANE |
+V4L2_CAP_STREAMING;
mdp->vdev->fops = _mdp_m2m_fops;
mdp->vdev->ioctl_ops = _mdp_m2m_ioctl_ops;
mdp->vdev->release = video_device_release;
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
index 4334b7394861..75318a4129ea 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c
@@ -321,7 +321,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
vfd_dec->v4l2_dev   = >v4l2_dev;
vfd_dec->vfl_dir= VFL_DIR_M2M;
vfd_dec->device_caps= V4L2_CAP_VIDEO_M2M_MPLANE |
-   V4L2_CAP_STREAMING;
+   V4L2_CAP_STREAMING | V4L2_CAP_FENCES;
 
snprintf(vfd_dec->name, sizeof(vfd_dec->name), "%s",
MTK_VCODEC_DEC_NAME);
diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c 
b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
index 83f859e8509c..1c9d4e7262bb 100644
--- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
+++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c
@@ -339,7 +339,8 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
vfd_enc->v4l2_dev   = >v4l2_dev;
vfd_enc->vfl_dir= VFL_DIR_M2M;
vfd_enc->device_caps= V4L2_CAP_VIDEO_M2M_MPLANE |
-   V4L2_CAP_STREAMING;
+   V4L2_CAP_STREAMING |
+   V4L2_CAP_FENCES;
 
snprintf(vfd_enc->name, sizeof(vfd_enc->name), "%s",
 MTK_VCODEC_ENC_NAME);
diff --git a/drivers/media/platform/mx2_emmaprp.c 

[PATCH v10 16/16] v4l: Document explicit synchronization behavior

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

Add section to VIDIOC_QBUF and VIDIOC_QUERY_BUF about it

v9: assorted improvements.

v8: amend querybuf documentation.

v7: minor issues and English improvements (Hans Verkuil)

v6: Close some gaps in the docs (Hans)

v5: - Remove V4L2_CAP_ORDERED
- Add doc about V4L2_FMT_FLAG_UNORDERED

v4: - Document ordering behavior for in-fences
- Document V4L2_CAP_ORDERED capability
- Remove doc about OUT_FENCE event
- Document immediate return of out-fence in QBUF

v3: - make the out_fence refer to the current buffer (Hans)
- Note what happens when the IN_FENCE is not set (Hans)

v2: - mention that fences are files (Hans)
- rework for the new API

Signed-off-by: Gustavo Padovan 
Signed-off-by: Ezequiel Garcia 
---
 Documentation/media/uapi/v4l/vidioc-qbuf.rst | 53 +++-
 Documentation/media/uapi/v4l/vidioc-querybuf.rst | 12 --
 2 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/Documentation/media/uapi/v4l/vidioc-qbuf.rst 
b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
index 9e448a4aa3aa..f09e21247a6c 100644
--- a/Documentation/media/uapi/v4l/vidioc-qbuf.rst
+++ b/Documentation/media/uapi/v4l/vidioc-qbuf.rst
@@ -54,7 +54,7 @@ When the buffer is intended for output (``type`` is
 or ``V4L2_BUF_TYPE_VBI_OUTPUT``) applications must also initialize the
 ``bytesused``, ``field`` and ``timestamp`` fields, see :ref:`buffer`
 for details. Applications must also set ``flags`` to 0. The
-``reserved2`` and ``reserved`` fields must be set to 0. When using the
+``reserved`` field must be set to 0. When using the
 :ref:`multi-planar API `, the ``m.planes`` field must
 contain a userspace pointer to a filled-in array of struct
 :c:type:`v4l2_plane` and the ``length`` field must be set
@@ -118,6 +118,57 @@ immediately with an ``EAGAIN`` error code when no buffer 
is available.
 The struct :c:type:`v4l2_buffer` structure is specified in
 :ref:`buffer`.
 
+Explicit Synchronization
+
+
+Explicit Synchronization allows us to control the synchronization of
+shared buffers from userspace by passing fences to the kernel and/or
+receiving them from it. Fences passed to the kernel are named in-fences and
+the kernel should wait on them to signal before using the buffer. On the other
+side, the kernel can create out-fences for the buffers it queues to the
+drivers. Out-fences signal when the driver is finished with buffer, i.e., the
+buffer is ready. The fences are represented as a file and passed as a file
+descriptor to userspace.
+
+The in-fences are communicated to the kernel at the ``VIDIOC_QBUF`` ioctl
+using the ``V4L2_BUF_FLAG_IN_FENCE`` buffer flag and the `fence_fd` field. If
+an in-fence needs to be passed to the kernel, `fence_fd` should be set to the
+fence file descriptor number and the ``V4L2_BUF_FLAG_IN_FENCE`` should be set
+as well. Setting one but not the other will cause ``VIDIOC_QBUF`` to return
+with an error.
+
+It is guaranteed that all buffers queued with an in-fence will be queued to
+the drivers in the same order. Fences may signal out of order, so this 
guarantee
+is necessary to not change ordering. While waiting for a fence to signal,
+all buffers queued afterwards will also be blocked until that fence signals.
+
+If the in-fence signals with an error the buffer will be marked with
+``V4L2_BUF_FLAG_ERROR`` when returned to userspace at ``VIDIOC_DQBUF``.
+Even with the error the order of dequeueing the buffers is preserved.
+
+To get an out-fence back from V4L2 the ``V4L2_BUF_FLAG_OUT_FENCE`` flag should
+be set to ask for a fence to be attached to the buffer. The out-fence fd is
+sent to userspace as a ``VIDIOC_QBUF`` return argument in the `fence_fd` field.
+
+Note the same `fence_fd` field is used for both sending the in-fence as
+at input argument and to receive the out-fence as a return argument. A buffer 
can
+have both an in-fence and an out-fence.
+
+At streamoff the out-fences will either signal normally if the driver waits
+for the operations on the buffers to finish or signal with an error if the
+driver cancels the pending operations. Buffers with in-fences won't be queued
+to the driver if their fences signal. They will be cleaned up.
+
+The ``V4L2_FMT_FLAG_UNORDERED`` flag in ``VIDIOC_ENUM_FMT`` tells userspace
+that when using this format, the order in which buffers are dequeued can
+be different from the order in which they were queued.
+
+Ordering is important to fences because it can optimize the pipeline with
+other drivers like a DRM/KMS display driver. For example, if a capture from the
+camera is happening in an ordered manner one can send the capture buffer
+out-fence to the DRM/KMS driver and rest assured that the buffers will be 
shown on
+the screen in the correct order. If the queue is not ordered, then such
+arrangements with other drivers may not be possible.
 
 Return Value
 

[PATCH v10 14/16] v4l: introduce the fences capability

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

Drivers capable of using fences (vb2 drivers) should report the
V4L2_CAP_FENCES to userspace, so add this flag to the uapi.

v2: minor doc/english fix (Hans Verkuil)

Signed-off-by: Gustavo Padovan 
---
 Documentation/media/uapi/v4l/vidioc-querycap.rst | 3 +++
 include/uapi/linux/videodev2.h   | 1 +
 2 files changed, 4 insertions(+)

diff --git a/Documentation/media/uapi/v4l/vidioc-querycap.rst 
b/Documentation/media/uapi/v4l/vidioc-querycap.rst
index 66fb1b3d6e6e..df3ad57f07a3 100644
--- a/Documentation/media/uapi/v4l/vidioc-querycap.rst
+++ b/Documentation/media/uapi/v4l/vidioc-querycap.rst
@@ -254,6 +254,9 @@ specification the ioctl returns an ``EINVAL`` error code.
 * - ``V4L2_CAP_TOUCH``
   - 0x1000
   - This is a touch device.
+* - ``V4L2_CAP_FENCES``
+  - 0x2000
+  - The device supports explicit synchronization.
 * - ``V4L2_CAP_DEVICE_CAPS``
   - 0x8000
   - The driver fills the ``device_caps`` field. This capability can
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 1f18dc68ecab..cab35fca7c7f 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -460,6 +460,7 @@ struct v4l2_capability {
 #define V4L2_CAP_STREAMING  0x0400  /* streaming I/O ioctls */
 
 #define V4L2_CAP_TOUCH  0x1000  /* Is a touch device */
+#define V4L2_CAP_FENCES 0x2000  /* Supports explicit 
synchronization */
 
 #define V4L2_CAP_DEVICE_CAPS0x8000  /* sets device 
capabilities field */
 
-- 
2.16.3



[PATCH v10 02/16] xilinx: regroup caps on querycap

2018-05-21 Thread Ezequiel Garcia
From: Gustavo Padovan 

To better organize the code we concentrate the setting of
V4L2_CAP_STREAMING in one place.

v2: move cap->capabilities assignment down (Hans Verkuil)

Signed-off-by: Gustavo Padovan 
---
 drivers/media/platform/xilinx/xilinx-dma.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/media/platform/xilinx/xilinx-dma.c 
b/drivers/media/platform/xilinx/xilinx-dma.c
index 522cdfdd3345..d041f94be832 100644
--- a/drivers/media/platform/xilinx/xilinx-dma.c
+++ b/drivers/media/platform/xilinx/xilinx-dma.c
@@ -494,13 +494,15 @@ xvip_dma_querycap(struct file *file, void *fh, struct 
v4l2_capability *cap)
struct v4l2_fh *vfh = file->private_data;
struct xvip_dma *dma = to_xvip_dma(vfh->vdev);
 
-   cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
- | dma->xdev->v4l2_caps;
+   cap->device_caps = V4L2_CAP_STREAMING;
 
if (dma->queue.type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-   cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+   cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
else
-   cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+   cap->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
+
+   cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS
+ | dma->xdev->v4l2_caps;
 
strlcpy(cap->driver, "xilinx-vipp", sizeof(cap->driver));
strlcpy(cap->card, dma->video.name, sizeof(cap->card));
-- 
2.16.3



[PATCH v10 00/16] V4L2 Explicit Synchronization

2018-05-21 Thread Ezequiel Garcia
Hi all,

The most relevant change for this round is that all the work
done in the fence callback is now moved to a workqueue,
that runs with the queue lock held.
 
Although this introduces some latency, it is however needed
to take the vb2_queue mutex and safely call vb2 ops.

Given the fence callback can be called fully asynchronously,
and given it needs to be associated with a vb2_buffer,
we now need to refcount vb2_buffer. This allows to safely "attach"
the vb2_buffer to the fence callback.

To prevent annoying deadlocks, and because the fence callback
is called with the fence spinlock, it's best to avoid calling
dma_fence_put in the fence callback itself. So the fence is now
put in the DQBUF operation (or in cancel paths).

Hopefully, I took care of all the feedback provided by
Hans and Brian on v9. Please let me know if you guys catch
anything else.

Thanks!

Changes from v9:

 * Move fence callback to workqueue, and call vb2_start_streaming if needed.
 * Refcount vb2_buffer.
 * Check return of get_unused_fd.
 * Increase seqno for out-fences that reuse the context.
 * Go back to is_unordered callback.
 * Mark unordered formats in cobalt driver.
 * Improve CAP_FENCES check.
 * Minor documentation changes.

Ezequiel Garcia (1):
  videobuf2: Make struct vb2_buffer refcounted

Gustavo Padovan (15):
  xilinx: regroup caps on querycap
  hackrf: group device capabilities
  omap3isp: group device capabilities
  vb2: move vb2_ops functions to videobuf2-core.[ch]
  vb2: add is_unordered callback for drivers
  v4l: add unordered flag to format description ioctl
  v4l: mark unordered formats
  cobalt: add .is_unordered() for cobalt
  vb2: mark codec drivers as unordered
  vb2: add explicit fence user API
  vb2: add in-fence support to QBUF
  vb2: add out-fence support to QBUF
  v4l: introduce the fences capability
  v4l: Add V4L2_CAP_FENCES to drivers
  v4l: Document explicit synchronization behavior

 Documentation/media/uapi/v4l/buffer.rst|  48 ++-
 Documentation/media/uapi/v4l/vidioc-enum-fmt.rst   |   7 +
 Documentation/media/uapi/v4l/vidioc-qbuf.rst   |  53 ++-
 Documentation/media/uapi/v4l/vidioc-querybuf.rst   |  12 +-
 Documentation/media/uapi/v4l/vidioc-querycap.rst   |   3 +
 drivers/media/common/videobuf2/Kconfig |   1 +
 drivers/media/common/videobuf2/videobuf2-core.c| 376 ++---
 drivers/media/common/videobuf2/videobuf2-v4l2.c|  65 +++-
 drivers/media/dvb-core/dvb_vb2.c   |   2 +-
 drivers/media/pci/cobalt/cobalt-v4l2.c |   4 +
 drivers/media/platform/coda/coda-common.c  |   1 +
 drivers/media/platform/exynos-gsc/gsc-m2m.c|   3 +-
 drivers/media/platform/m2m-deinterlace.c   |   3 +-
 drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c   |   3 +-
 drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c |   1 +
 .../media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c |   2 +-
 drivers/media/platform/mtk-vcodec/mtk_vcodec_enc.c |   1 +
 .../media/platform/mtk-vcodec/mtk_vcodec_enc_drv.c |   3 +-
 drivers/media/platform/mx2_emmaprp.c   |   3 +-
 drivers/media/platform/omap3isp/ispvideo.c |  10 +-
 drivers/media/platform/qcom/venus/vdec.c   |   4 +-
 drivers/media/platform/qcom/venus/venc.c   |   4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c   |   1 +
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c   |   1 +
 drivers/media/platform/sh_veu.c|   3 +-
 drivers/media/platform/xilinx/xilinx-dma.c |  10 +-
 drivers/media/usb/hackrf/hackrf.c  |  11 +-
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c  |   4 +-
 drivers/media/v4l2-core/v4l2-ioctl.c   |  98 +-
 include/media/videobuf2-core.h |  76 -
 include/media/videobuf2-v4l2.h |  18 -
 include/uapi/linux/videodev2.h |  10 +-
 32 files changed, 708 insertions(+), 133 deletions(-)

-- 
2.16.3



Re: [Xen-devel] [RFC 1/3] xen/balloon: Allow allocating DMA buffers

2018-05-21 Thread Boris Ostrovsky
On 05/21/2018 01:40 AM, Oleksandr Andrushchenko wrote:
> On 05/19/2018 01:04 AM, Boris Ostrovsky wrote:
>> On 05/17/2018 04:26 AM, Oleksandr Andrushchenko wrote:
>>> From: Oleksandr Andrushchenko 
>>
>> A commit message would be useful.
> Sure, v1 will have it
>>
>>> Signed-off-by: Oleksandr Andrushchenko
>>> 
>>>
>>>   for (i = 0; i < nr_pages; i++) {
>>> -    page = alloc_page(gfp);
>>> -    if (page == NULL) {
>>> -    nr_pages = i;
>>> -    state = BP_EAGAIN;
>>> -    break;
>>> +    if (ext_pages) {
>>> +    page = ext_pages[i];
>>> +    } else {
>>> +    page = alloc_page(gfp);
>>> +    if (page == NULL) {
>>> +    nr_pages = i;
>>> +    state = BP_EAGAIN;
>>> +    break;
>>> +    }
>>>   }
>>>   scrub_page(page);
>>>   list_add(>lru, );
>>> @@ -529,7 +565,7 @@ static enum bp_state
>>> decrease_reservation(unsigned long nr_pages, gfp_t gfp)
>>>   i = 0;
>>>   list_for_each_entry_safe(page, tmp, , lru) {
>>>   /* XENMEM_decrease_reservation requires a GFN */
>>> -    frame_list[i++] = xen_page_to_gfn(page);
>>> +    frames[i++] = xen_page_to_gfn(page);
>>>     #ifdef CONFIG_XEN_HAVE_PVMMU
>>>   /*
>>> @@ -552,18 +588,22 @@ static enum bp_state
>>> decrease_reservation(unsigned long nr_pages, gfp_t gfp)
>>>   #endif
>>>   list_del(>lru);
>>>   -    balloon_append(page);
>>> +    if (!ext_pages)
>>> +    balloon_append(page);
>>
>> So what you are proposing is not really ballooning. You are just
>> piggybacking on existing interfaces, aren't you?
> Sort of. Basically I need to {increase|decrease}_reservation, not
> actually
> allocating ballooned pages.
> Do you think I can simply EXPORT_SYMBOL for
> {increase|decrease}_reservation?
> Any other suggestion?


I am actually wondering how much of that code you end up reusing. You
pretty much create new code paths in both routines and common code ends
up being essentially the hypercall. So the question is --- would it make
sense to do all of this separately from the balloon driver?


-boris


Re: [PATCH 1/3] media: rc: nuvoton: Tweak the interrupt enabling dance

2018-05-21 Thread Michał Winiarski
On Mon, May 21, 2018 at 04:54:07PM +0100, Sean Young wrote:
> On Mon, May 21, 2018 at 04:38:01PM +0200, Michał Winiarski wrote:
> > It appears that we need to enable CIR device before attempting to touch
> > some of the registers. Previously, this was not a big issue, since we
> > were rarely seeing nvt_close() getting called.
> > 
> > Unfortunately, since:
> > cb84343fced1 ("media: lirc: do not call close() or open() on unregistered 
> > devices")
> > 
> > The initial open() during probe from rc_setup_rx_device() is no longer
> > successful, which means that userspace clients will actually end up
> > calling nvt_open()/nvt_close().
> > And since nvt_open() is broken, the device doesn't seem to work as
> > expected.
> 
> Since that commit was in v4.16, should we have the following:
> 
> Cc: sta...@vger.kernel.org # v4.16+
> 
> On this commit (and not the other two, if I understand them correctly)?

Correct. I even had it in the series attached to the bugzilla.
Dropped it because the bug reporters have not confirmed that it fixes their
problem yet. (works for me though...)

-Michał

> 
> Thanks,
> Sean
> 
> > 
> > Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199597
> > Signed-off-by: Michał Winiarski 
> > Cc: Jarod Wilson 
> > Cc: Sean Young 
> > ---
> >  drivers/media/rc/nuvoton-cir.c | 6 +++---
> >  1 file changed, 3 insertions(+), 3 deletions(-)


Re: [PATCH 01/11] media: tm6000: fix potential Spectre variant 1

2018-05-21 Thread Gustavo A. R. Silva



On 05/17/2018 01:08 PM, Gustavo A. R. Silva wrote:


BTW, Mauro, you sent a patch to fix an spectre v1 issue in this file 
yesterday: dvb_ca_en50221.c:1480, but it seems there is another instance 
of the same issue some lines above:


diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c 
b/drivers/media/dvb-core/dvb_ca_en50221.c

index 1310526..7edd9db 100644
--- a/drivers/media/dvb-core/dvb_ca_en50221.c
+++ b/drivers/media/dvb-core/dvb_ca_en50221.c
@@ -1398,6 +1398,7 @@ static int dvb_ca_en50221_io_do_ioctl(struct file 
*file,


     info->type = CA_CI_LINK;
     info->flags = 0;
+   slot = array_index_nospec(slot, ca->slot_count + 1);
     sl = >slot_info[slot];
     if ((sl->slot_state != DVB_CA_SLOTSTATE_NONE) &&
     (sl->slot_state != DVB_CA_SLOTSTATE_INVALID)) {




Hi Mauro,

Just to let you know, I was running smatch during the weekend and the 
tool is still reporting all these Spectre media warnings (and a lot more):


https://patchwork.linuxtv.org/project/linux-media/list/?submitter=7277

Thanks
--
Gustavo


Re: i.MX6 IPU CSI analog video input on Ventana

2018-05-21 Thread Tim Harvey
On Mon, May 21, 2018 at 1:09 AM, Krzysztof Hałasa  wrote:
> Tested with NTSC camera, it's the same as with PAL.
> The only case when IPU2_CSI1_SENS_CONF register is set to interlaced
> mode (PRCTL=3, CCIR interlaced mode (BT.656)) is when all parts of the
> pipeline are set to interlaced:
>
> "adv7180 2-0020":0 [fmt:UYVY2X8/720x576 field:interlaced]
> "ipu2_csi1_mux":1  [fmt:UYVY2X8/720x576 field:interlaced]
> "ipu2_csi1_mux":2  [fmt:UYVY2X8/720x576 field:interlaced]
> "ipu2_csi1":0  [fmt:UYVY2X8/720x576 field:interlaced]
> "ipu2_csi1":2  [fmt:AYUV32/720x576 field:interlaced]
>
> The image is stable and in sync, the "only" problem is that I get two
> concatenated field images (in one V4L2 frame) instead of a normal
> interlaced frame (all lines in order - 0, 1, 2, 3, 4 etc).
> IOW I get V4L2_FIELD_ALTERNATE, V4L2_FIELD_SEQ_TB or V4L2_FIELD_SEQ_BT
> (the data format, I don't mean the pixel format.field) while I need to
> get V4L2_FIELD_INTERLACED, V4L2_FIELD_INTERLACED_TB or _BT.
>
>
> If I set "ipu2_csi1":2 to field:none, the IPU2_CSI1_SENS_CONF is set to
> progressive mode (PRCTL=2). It's the last element of the pipeline I can
> configure, it's connected straight to "ipu2_csi1 capture" aka
> /dev/videoX. I think CSI can't work with interlaced camera (and ADV7180)
> when set to progressive, can it?
>
>
> I wonder... perhaps to get an interlaced frame I need to route the data
> through VDIC (ipu2_vdic, the deinterlacer)?

Krzysztof,

Right, your doing a raw capture where you get both fields in one
buffer and I'm not clear what to do with that.

Here's what I've used on a GW54xx with IMX6Q and an adv7180 for NTSC.

using VDIC to deinterlace:
# adv7180 -> vdic -> ic_prpvf -> /dev/video3
# VDIC will de-interlace using motion compensation
media-ctl -r # reset all links
# Setup links
media-ctl -l '"adv7180 2-0020":0 -> "ipu2_csi1_mux":1[1]'
media-ctl -l '"ipu2_csi1_mux":2 -> "ipu2_csi1":0[1]'
media-ctl -l '"ipu2_csi1":1 -> "ipu2_vdic":0[1]'
media-ctl -l '"ipu2_vdic":2 -> "ipu2_ic_prp":0[1]'
media-ctl -l '"ipu2_ic_prp":2 -> "ipu2_ic_prpvf":0[1]'
media-ctl -l '"ipu2_ic_prpvf":1 -> "ipu2_ic_prpvf capture":0[1]'
# Configure pads
media-ctl -V "'adv7180 2-0020':0 [fmt:UYVY2X8/720x480]"
media-ctl -V "'ipu2_csi1_mux':2 [fmt:UYVY2X8/720x480 field:interlaced]"
media-ctl -V "'ipu2_csi1':1 [fmt:UYVY2X8/720x480 field:interlaced]"
media-ctl -V "'ipu2_vdic':2 [fmt:UYVY2X8/720x480 field:interlaced]"
media-ctl -V "'ipu2_ic_prp':2 [fmt:UYVY2X8/720x480 field:none]"
media-ctl -V "'ipu2_ic_prpvf':1 [fmt:UYVY2X8/720x480 field:none]"
# streaming can now begin on /dev/video3
v4l2-ctl -d3 --set-fmt-video=width=720,height=480,pixelformat=UYVY
v4l2-ctl -d3 --set-ctrl=deinterlacing_mode=3 # set max motion
compensation (default)
# this is the default so could be skipped; also its the only value
allowed when capturing direct from CSI
v4l2-ctl -d3 --stream-mmap --stream-to=/x.raw --stream-count=1 # capture 1 frame
convert -size 720x480 -depth 16 uyvy:/x.raw /var/www/html/frame.png #
and convert
# or stream jpeg's via gst
gst-launch-1.0 v4l2src device=/dev/video3 ! "video/x-raw,format=UYVY"
! jpegenc ! queue ! avimux name=mux ! udpsink host=172.24.20.19
port=5000

or de-interlace via IDMAC:
# PRPVF will do simple IDMAC line interweaving for de-interlacing,
since VDIC is not involved in the pipeline, but it will only enable
this in the IDMAC if it sees interlaced input at prpvf
media-ctl -r # reset all links
# Setup links
media-ctl -l '"adv7180 2-0020":0 -> "ipu2_csi1_mux":1[1]'
media-ctl -l '"ipu2_csi1_mux":2 -> "ipu2_csi1":0[1]'
media-ctl -l '"ipu2_csi1":1 -> "ipu2_ic_prp":0[1]'
media-ctl -l '"ipu2_ic_prp":2 -> "ipu2_ic_prpvf":0[1]'
media-ctl -l '"ipu2_ic_prpvf":1 -> "ipu2_ic_prpvf capture":0[1]'
# Configure pads
media-ctl -V "'adv7180 2-0020':0 [fmt:UYVY2X8/720x480]"
media-ctl -V "'ipu2_csi1_mux':2 [fmt:UYVY2X8/720x480 field:interlaced]"
media-ctl -V "'ipu2_csi1':1 [fmt:UYVY2X8/720x480 field:interlaced]"
media-ctl -V "'ipu2_ic_prp':2 [fmt:UYVY2X8/720x480 field:interlaced]"
media-ctl -V "'ipu2_ic_prpvf':1 [fmt:UYVY2X8/720x480 field:none]"
# streaming can now begin on /dev/video3
v4l2-ctl -d3 --set-fmt-video=width=720,height=480,pixelformat=UYVY
v4l2-ctl -d3 --stream-mmap --stream-to=/x.raw --stream-count=1 # capture
gst-launch-1.0 v4l2src device=/dev/video3 ! "video/x-raw,format=UYVY"
! jpegenc ! queue ! avimux name=mux ! udpsink host=172.24.20.19
port=5000

or the following for non deinterlaced:
# adv7180 -> ic_prp -> ic_prpenc -> /dev/video2
media-ctl -r # reset all links
# Setup links
media-ctl -l '"adv7180 2-0020":0 -> "ipu2_csi1_mux":1[1]'
media-ctl -l '"ipu2_csi1_mux":2 -> "ipu2_csi1":0[1]'
media-ctl -l '"ipu2_csi1":1 -> "ipu2_ic_prp":0[1]'
media-ctl -l '"ipu2_ic_prp":1 -> "ipu2_ic_prpenc":0[1]'
media-ctl -l '"ipu2_ic_prpenc":1 -> "ipu2_ic_prpenc capture":0[1]'
# Configure pads
media-ctl -V "'adv7180 2-0020':0 [fmt:UYVY2X8/720x480]"
media-ctl -V "'ipu2_csi1_mux':2 [fmt:UYVY2X8/720x480 field:interlaced]"

Re: [PATCH 1/3] media: rc: nuvoton: Tweak the interrupt enabling dance

2018-05-21 Thread Sean Young
On Mon, May 21, 2018 at 04:38:01PM +0200, Michał Winiarski wrote:
> It appears that we need to enable CIR device before attempting to touch
> some of the registers. Previously, this was not a big issue, since we
> were rarely seeing nvt_close() getting called.
> 
> Unfortunately, since:
> cb84343fced1 ("media: lirc: do not call close() or open() on unregistered 
> devices")
> 
> The initial open() during probe from rc_setup_rx_device() is no longer
> successful, which means that userspace clients will actually end up
> calling nvt_open()/nvt_close().
> And since nvt_open() is broken, the device doesn't seem to work as
> expected.

Since that commit was in v4.16, should we have the following:

Cc: sta...@vger.kernel.org # v4.16+

On this commit (and not the other two, if I understand them correctly)?

Thanks,
Sean

> 
> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199597
> Signed-off-by: Michał Winiarski 
> Cc: Jarod Wilson 
> Cc: Sean Young 
> ---
>  drivers/media/rc/nuvoton-cir.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
> index 5e1d866a61a5..ce8949b6549d 100644
> --- a/drivers/media/rc/nuvoton-cir.c
> +++ b/drivers/media/rc/nuvoton-cir.c
> @@ -922,6 +922,9 @@ static int nvt_open(struct rc_dev *dev)
>   struct nvt_dev *nvt = dev->priv;
>   unsigned long flags;
>  
> + /* enable the CIR logical device */
> + nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
> +
>   spin_lock_irqsave(>lock, flags);
>  
>   /* set function enable flags */
> @@ -937,9 +940,6 @@ static int nvt_open(struct rc_dev *dev)
>  
>   spin_unlock_irqrestore(>lock, flags);
>  
> - /* enable the CIR logical device */
> - nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
> -
>   return 0;
>  }
>  
> -- 
> 2.17.0


Re: [PATCH v2 04/29] venus: hfi_cmds: add set_properties for 4xx version

2018-05-21 Thread Stanimir Varbanov
Hi Tomasz,

On 05/18/2018 05:16 PM, Tomasz Figa wrote:
> On Tue, May 15, 2018 at 5:13 PM Stanimir Varbanov <
> stanimir.varba...@linaro.org> wrote:
> 
>> Adds set_properties method to handle newer 4xx properties and
>> fall-back to 3xx for the rest.
> 
>> Signed-off-by: Stanimir Varbanov 
>> ---
>>   drivers/media/platform/qcom/venus/hfi_cmds.c | 64
> +++-
>>   1 file changed, 63 insertions(+), 1 deletion(-)
> 
>> diff --git a/drivers/media/platform/qcom/venus/hfi_cmds.c
> b/drivers/media/platform/qcom/venus/hfi_cmds.c
>> index 1cfeb7743041..6bd287154796 100644
>> --- a/drivers/media/platform/qcom/venus/hfi_cmds.c
>> +++ b/drivers/media/platform/qcom/venus/hfi_cmds.c
> 
> [snip]
> 
>> +   case HFI_PROPERTY_CONFIG_VENC_MAX_BITRATE:
>> +   /* not implemented on Venus 4xx */
> 
> Shouldn't return -EINVAL here, similar to what
> pkt_session_set_property_1x() does for unknown property?

Probably the right error code should be ENOTSUPP, but I kind of
following the rule to silently not return the error to simplify the
callers of set_property (otherwise I have to have a version conditional
code in the callers).

> 
>> +   break;
>> +   default:
>> +   ret = pkt_session_set_property_3xx(pkt, cookie, ptype,
> pdata);
>> +   break;
> 
> nit: How about simply return pkt_session_set_property_3xx(pkt, cookie,
> ptype, pdata); and removing the |ret| variable completely, since the return
> below the switch can just return 0 all the time?

OK, I will do that way.

> 
>> +   }
>> +
>> +   return ret;
>> +}
>> +
>>   int pkt_session_get_property(struct hfi_session_get_property_pkt *pkt,
>>   void *cookie, u32 ptype)
>>   {
>> @@ -1181,7 +1240,10 @@ int pkt_session_set_property(struct
> hfi_session_set_property_pkt *pkt,
>>  if (hfi_ver == HFI_VERSION_1XX)
>>  return pkt_session_set_property_1x(pkt, cookie, ptype,
> pdata);
> 
>> -   return pkt_session_set_property_3xx(pkt, cookie, ptype, pdata);
>> +   if (hfi_ver == HFI_VERSION_3XX)
>> +   return pkt_session_set_property_3xx(pkt, cookie, ptype,
> pdata);
>> +
>> +   return pkt_session_set_property_4xx(pkt, cookie, ptype, pdata);
> 
> nit: Since we're adding third variant, I'd consider using function pointers
> here, but no strong opinion.

Let's keep that for future improvements.

-- 
regards,
Stan


[PATCH 1/3] media: rc: nuvoton: Tweak the interrupt enabling dance

2018-05-21 Thread Michał Winiarski
It appears that we need to enable CIR device before attempting to touch
some of the registers. Previously, this was not a big issue, since we
were rarely seeing nvt_close() getting called.

Unfortunately, since:
cb84343fced1 ("media: lirc: do not call close() or open() on unregistered 
devices")

The initial open() during probe from rc_setup_rx_device() is no longer
successful, which means that userspace clients will actually end up
calling nvt_open()/nvt_close().
And since nvt_open() is broken, the device doesn't seem to work as
expected.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=199597
Signed-off-by: Michał Winiarski 
Cc: Jarod Wilson 
Cc: Sean Young 
---
 drivers/media/rc/nuvoton-cir.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index 5e1d866a61a5..ce8949b6549d 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -922,6 +922,9 @@ static int nvt_open(struct rc_dev *dev)
struct nvt_dev *nvt = dev->priv;
unsigned long flags;
 
+   /* enable the CIR logical device */
+   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
+
spin_lock_irqsave(>lock, flags);
 
/* set function enable flags */
@@ -937,9 +940,6 @@ static int nvt_open(struct rc_dev *dev)
 
spin_unlock_irqrestore(>lock, flags);
 
-   /* enable the CIR logical device */
-   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
-
return 0;
 }
 
-- 
2.17.0



[PATCH 2/3] media: rc: nuvoton: Keep track of users on CIR enable/disable

2018-05-21 Thread Michał Winiarski
Core rc keeps track of the users - let's use it to tweak the code and
use the common code path on suspend/resume.

Signed-off-by: Michał Winiarski 
Cc: Jarod Wilson 
Cc: Sean Young 
---
 drivers/media/rc/nuvoton-cir.c | 82 +++---
 1 file changed, 36 insertions(+), 46 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index ce8949b6549d..eebd6fef5602 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -543,27 +543,9 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt)
nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV |
  CIR_FIFOCON_RX_TRIGGER_LEV, CIR_FIFOCON);
 
-   /*
-* Enable TX and RX, specify carrier on = low, off = high, and set
-* sample period (currently 50us)
-*/
-   nvt_cir_reg_write(nvt,
- CIR_IRCON_TXEN | CIR_IRCON_RXEN |
- CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
- CIR_IRCON);
-
/* clear hardware rx and tx fifos */
nvt_clear_cir_fifo(nvt);
nvt_clear_tx_fifo(nvt);
-
-   /* clear any and all stray interrupts */
-   nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
-
-   /* and finally, enable interrupts */
-   nvt_set_cir_iren(nvt);
-
-   /* enable the CIR logical device */
-   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
 }
 
 static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
@@ -892,6 +874,32 @@ static irqreturn_t nvt_cir_isr(int irq, void *data)
return IRQ_HANDLED;
 }
 
+static void nvt_enable_cir(struct nvt_dev *nvt)
+{
+   unsigned long flags;
+
+   /* enable the CIR logical device */
+   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
+
+   spin_lock_irqsave(>lock, flags);
+
+   /*
+* Enable TX and RX, specify carrier on = low, off = high, and set
+* sample period (currently 50us)
+*/
+   nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN |
+ CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
+ CIR_IRCON);
+
+   /* clear all pending interrupts */
+   nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
+
+   /* enable interrupts */
+   nvt_set_cir_iren(nvt);
+
+   spin_unlock_irqrestore(>lock, flags);
+}
+
 static void nvt_disable_cir(struct nvt_dev *nvt)
 {
unsigned long flags;
@@ -920,25 +928,8 @@ static void nvt_disable_cir(struct nvt_dev *nvt)
 static int nvt_open(struct rc_dev *dev)
 {
struct nvt_dev *nvt = dev->priv;
-   unsigned long flags;
 
-   /* enable the CIR logical device */
-   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
-
-   spin_lock_irqsave(>lock, flags);
-
-   /* set function enable flags */
-   nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN |
- CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL,
- CIR_IRCON);
-
-   /* clear all pending interrupts */
-   nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS);
-
-   /* enable interrupts */
-   nvt_set_cir_iren(nvt);
-
-   spin_unlock_irqrestore(>lock, flags);
+   nvt_enable_cir(nvt);
 
return 0;
 }
@@ -1093,19 +1084,13 @@ static void nvt_remove(struct pnp_dev *pdev)
 static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state)
 {
struct nvt_dev *nvt = pnp_get_drvdata(pdev);
-   unsigned long flags;
 
nvt_dbg("%s called", __func__);
 
-   spin_lock_irqsave(>lock, flags);
-
-   /* disable all CIR interrupts */
-   nvt_cir_reg_write(nvt, 0, CIR_IREN);
-
-   spin_unlock_irqrestore(>lock, flags);
-
-   /* disable cir logical dev */
-   nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
+   mutex_lock(>rdev->lock);
+   if (nvt->rdev->users)
+   nvt_disable_cir(nvt);
+   mutex_unlock(>rdev->lock);
 
/* make sure wake is enabled */
nvt_enable_wake(nvt);
@@ -1122,6 +1107,11 @@ static int nvt_resume(struct pnp_dev *pdev)
nvt_cir_regs_init(nvt);
nvt_cir_wake_regs_init(nvt);
 
+   mutex_lock(>rdev->lock);
+   if (nvt->rdev->users)
+   nvt_enable_cir(nvt);
+   mutex_unlock(>rdev->lock);
+
return 0;
 }
 
-- 
2.17.0



[PATCH 3/3] media: rc: nuvoton: Keep device enabled during reg init

2018-05-21 Thread Michał Winiarski
Doing writes when the device is disabled seems to be a NOOP.
Let's enable the device, write the values, and then disable it on init.
This changes the behavior for wake device, which is now being disabled
after init.

Signed-off-by: Michał Winiarski 
Cc: Jarod Wilson 
Cc: Sean Young 
---
 drivers/media/rc/nuvoton-cir.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index eebd6fef5602..61b68cde35f1 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -535,6 +535,8 @@ static void nvt_set_cir_iren(struct nvt_dev *nvt)
 
 static void nvt_cir_regs_init(struct nvt_dev *nvt)
 {
+   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR);
+
/* set sample limit count (PE interrupt raised when reached) */
nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH);
nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL);
@@ -546,10 +548,14 @@ static void nvt_cir_regs_init(struct nvt_dev *nvt)
/* clear hardware rx and tx fifos */
nvt_clear_cir_fifo(nvt);
nvt_clear_tx_fifo(nvt);
+
+   nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
 }
 
 static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
 {
+   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
+
/*
 * Disable RX, set specific carrier on = low, off = high,
 * and sample period (currently 50us)
@@ -562,8 +568,7 @@ static void nvt_cir_wake_regs_init(struct nvt_dev *nvt)
/* clear any and all stray interrupts */
nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS);
 
-   /* enable the CIR WAKE logical device */
-   nvt_enable_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE);
+   nvt_disable_logical_dev(nvt, LOGICAL_DEV_CIR);
 }
 
 static void nvt_enable_wake(struct nvt_dev *nvt)
-- 
2.17.0



Re: [PATCH v2 03/29] venus: hfi: update sequence event to handle more properties

2018-05-21 Thread Stanimir Varbanov
Hi Tomasz,

On 05/18/2018 04:53 PM, Tomasz Figa wrote:
> On Tue, May 15, 2018 at 5:14 PM Stanimir Varbanov <
> stanimir.varba...@linaro.org> wrote:
> 
>> HFI version 4xx can pass more properties in the sequence change
>> event, extend the event structure with them.
> 
>> Signed-off-by: Stanimir Varbanov 
>> ---
>>   drivers/media/platform/qcom/venus/hfi.h  |  9 ++
>>   drivers/media/platform/qcom/venus/hfi_msgs.c | 46
> 
>>   2 files changed, 55 insertions(+)
> 
>> diff --git a/drivers/media/platform/qcom/venus/hfi.h
> b/drivers/media/platform/qcom/venus/hfi.h
>> index 5466b7d60dd0..21376d93170f 100644
>> --- a/drivers/media/platform/qcom/venus/hfi.h
>> +++ b/drivers/media/platform/qcom/venus/hfi.h
>> @@ -74,6 +74,15 @@ struct hfi_event_data {
>>  u32 tag;
>>  u32 profile;
>>  u32 level;
> 
> nit; Could we add a comment saying that it showed in 4xx?

Sure, I can add a comment.

> 
> [snip]
> 
>> +   case HFI_PROPERTY_CONFIG_VDEC_ENTROPY:
>> +   data_ptr += sizeof(u32);
>> +   entropy_mode = *(u32 *)data_ptr;
>> +   event.entropy_mode = entropy_mode;
> 
> Is the |entropy_mode| local variable necessary?

Isn't GCC smart enough ;) Sure, I can drop entropy_mode local variable.

-- 
regards,
Stan


Re: [PATCH v2 02/29] venus: hfi: preparation to support venus 4xx

2018-05-21 Thread Stanimir Varbanov
Hi Tomasz,

Thanks for the comments!

On 05/18/2018 12:44 PM, Tomasz Figa wrote:
> Hi Stanimir,
> 
> On Tue, May 15, 2018 at 5:14 PM Stanimir Varbanov <
> stanimir.varba...@linaro.org> wrote:
> 
>> This covers the differences between 1xx,3xx and 4xx.
> 
>> Signed-off-by: Stanimir Varbanov 
>> ---
>>drivers/media/platform/qcom/venus/core.h |  4 ++
>>drivers/media/platform/qcom/venus/helpers.c  | 37 +++
>>drivers/media/platform/qcom/venus/hfi_helper.h   | 84
> ++--
>>drivers/media/platform/qcom/venus/hfi_venus_io.h | 24 +++
>>drivers/media/platform/qcom/venus/vdec.c |  5 +-
>>drivers/media/platform/qcom/venus/venc.c |  5 +-
>>6 files changed, 137 insertions(+), 22 deletions(-)
> 
> Please see my comments inline.
> 
> [snip]
> 
>> @@ -257,12 +273,11 @@ static int load_scale_clocks(struct venus_core
> *core)
> 
>>set_freq:
> 
>> -   if (core->res->hfi_version == HFI_VERSION_3XX) {
>> -   ret = clk_set_rate(clk, freq);
>> +   ret = clk_set_rate(clk, freq);
>> +
>> +   if (IS_V3(core) || IS_V4(core)) {
>>   ret |= clk_set_rate(core->core0_clk, freq);
>>   ret |= clk_set_rate(core->core1_clk, freq);
>> -   } else {
>> -   ret = clk_set_rate(clk, freq);
>>   }
> 
> nit: The clock API defines NULL clock as a special no-op value and so
> clk_set_rate(NULL, ...) would return 0 instantly. Maybe it would just make
> sense to have core0_clk and core1_clk set to NULL for V1 and remove the
> condition here?

OK, we could avoid the condition but I'll add a comment that those
clocks exist from v3 onwards.

> 
>>   if (ret) {
>> diff --git a/drivers/media/platform/qcom/venus/hfi_helper.h
> b/drivers/media/platform/qcom/venus/hfi_helper.h
>> index 55d8eb21403a..1bc5aab1ce6b 100644
>> --- a/drivers/media/platform/qcom/venus/hfi_helper.h
>> +++ b/drivers/media/platform/qcom/venus/hfi_helper.h
>> @@ -121,6 +121,7 @@
>>#define HFI_EXTRADATA_METADATA_FILLER  0x7fe2
> 
>>#define HFI_INDEX_EXTRADATA_INPUT_CROP 0x070e
>> +#define HFI_INDEX_EXTRADATA_OUTPUT_CROP0x070f
> 
> nit: Would it make sense to suffix this _4XX, so that reader could know
> that it was introduced in this version? Similarly for other newly added
> definitions.

I personally don't like the version suffix on defines. Also seems this
is not used in the code, so I'll drop it for now.

> 
>>#define HFI_INDEX_EXTRADATA_DIGITAL_ZOOM   0x0710
>>#define HFI_INDEX_EXTRADATA_ASPECT_RATIO   0x7f13
> 
>> @@ -376,13 +377,18 @@
>>#define HFI_BUFFER_OUTPUT2 0x3
>>#define HFI_BUFFER_INTERNAL_PERSIST0x4
>>#define HFI_BUFFER_INTERNAL_PERSIST_1  0x5
>> -#define HFI_BUFFER_INTERNAL_SCRATCH0x101
>> -#define HFI_BUFFER_EXTRADATA_INPUT 0x102
>> -#define HFI_BUFFER_EXTRADATA_OUTPUT0x103
>> -#define HFI_BUFFER_EXTRADATA_OUTPUT2   0x104
>> -#define HFI_BUFFER_INTERNAL_SCRATCH_1  0x105
>> -#define HFI_BUFFER_INTERNAL_SCRATCH_2  0x106
>> -
>> +#define HFI_BUFFER_INTERNAL_SCRATCH(ver)   \
>> +   (((ver) == HFI_VERSION_4XX) ? 0x6 : 0x101)
>> +#define HFI_BUFFER_INTERNAL_SCRATCH_1(ver) \
>> +   (((ver) == HFI_VERSION_4XX) ? 0x7 : 0x105)
>> +#define HFI_BUFFER_INTERNAL_SCRATCH_2(ver) \
>> +   (((ver) == HFI_VERSION_4XX) ? 0x8 : 0x106)
>> +#define HFI_BUFFER_EXTRADATA_INPUT(ver)\
>> +   (((ver) == HFI_VERSION_4XX) ? 0xc : 0x102)
>> +#define HFI_BUFFER_EXTRADATA_OUTPUT(ver)   \
>> +   (((ver) == HFI_VERSION_4XX) ? 0xa : 0x103)
>> +#define HFI_BUFFER_EXTRADATA_OUTPUT2(ver)  \
>> +   (((ver) == HFI_VERSION_4XX) ? 0xb : 0x104)
> 
> nit: Does it make sense to add an argument, rather than simply defining
> separate HFI_BUFFER_INTERNAL_SCRATCH_1XX and
> HFI_BUFFER_INTERNAL_SCRATCH_4XX? In my subjective opinion, the argument

I'd like to keep the name of the define version agnostic.

> just makes it harder to read, as it's not clear how it is used inside the
> macro from reading just the call to it. Also it would get messy when adding
> further variants in future.
> 
> [snip]
> 
>> +/* HFI 4XX reorder the fields, use these macros */
>> +#define HFI_BUFREQ_HOLD_COUNT(bufreq, ver) \
>> +   ((ver) == HFI_VERSION_4XX ? 0 : (bufreq)->hold_count)
>> +#define HFI_BUFREQ_COUNT_MIN(bufreq, ver)  \
>> +   ((ver) == HFI_VERSION_4XX ? (bufreq)->hold_count :
> (bufreq)->count_min)
>> +#define HFI_BUFREQ_COUNT_MIN_HOST(bufreq, ver) \
>> +   ((ver) == HFI_VERSION_4XX ? (bufreq)->count_min : 0)
>> +
> 
> Hmm, this is a bit messy. The macro is supposed to return count_min, but it
> returns hold_count. Shouldn't we define a separate

yep, that was the purpose of the 

[PATCH v4 0/5] Add ChromeOS EC CEC Support

2018-05-21 Thread Neil Armstrong
Hi All,

The new Google "Fizz" Intel-based ChromeOS device is gaining CEC support
through it's Embedded Controller, to enable the Linux CEC Core to communicate
with it and get the CEC Physical Address from the correct HDMI Connector, the
following must be added/changed:
- Add the CEC sub-device registration in the ChromeOS EC MFD Driver
- Add the CEC related commands and events definitions into the EC MFD driver
- Add a way to get a CEC notifier with it's (optional) connector name
- Add the CEC notifier to the i915 HDMI driver
- Add the proper ChromeOS EC CEC Driver

The CEC notifier with the connector name is the tricky point, since even on
Device-Tree platforms, there is no way to distinguish between multiple HDMI
connectors from the same DRM driver. The solution I implemented is pretty
simple and only adds an optional connector name to eventually distinguish
an HDMI connector notifier from another if they share the same device.

Feel free to comment this patchset !

Changes since v3 (incorrectly reported as v2):
 - Renamed "Chrome OS" to "ChromeOS"
 - Updated cros_ec_commands.h new structs definitions to kernel doc format
 - Added Reviwed-By tags

Changes since v2:
 - Add i915 port_identifier() and use this stable name as cec_notifier conn name
 - Fixed and cleaned up the CEC commands and events handling
 - Rebased the CEC sub-device registration on top of Enric's serie
 - Fixed comments typo on cec driver
 - Protected the DMI match only with PCI and DMI Kconfigs

Changes since v1:
 - Added cec_notifier_put to intel_hdmi
 - Fixed all small reported issues on the EC CEC driver
 - Moved the cec_notifier_get out of the #if .. #else .. #endif

Changes since RFC:
 - Moved CEC sub-device registration after CEC commands and events definitions 
patch
 - Removed get_notifier_get_byname
 - Added CEC_CORE select into i915 Kconfig
 - Removed CEC driver fallback if notifier is not configured on HW, added 
explicit warn
 - Fixed CEC core return type on error
 - Moved to cros-ec-cec media platform directory
 - Use bus_find_device() to find the pci i915 device instead of 
get_notifier_get_byname()
 - Fix Logical Address setup
 - Added comment about HW support
 - Removed memset of msg structures

Neil Armstrong (5):
  media: cec-notifier: Get notifier by device and connector name
  drm/i915: hdmi: add CEC notifier to intel_hdmi
  mfd: cros-ec: Introduce CEC commands and events definitions.
  mfd: cros_ec_dev: Add CEC sub-device registration
  media: platform: Add ChromeOS EC CEC driver

 drivers/gpu/drm/i915/Kconfig |   1 +
 drivers/gpu/drm/i915/intel_display.h |  20 ++
 drivers/gpu/drm/i915/intel_drv.h |   2 +
 drivers/gpu/drm/i915/intel_hdmi.c|  13 +
 drivers/media/cec/cec-notifier.c |  11 +-
 drivers/media/platform/Kconfig   |  11 +
 drivers/media/platform/Makefile  |   2 +
 drivers/media/platform/cros-ec-cec/Makefile  |   1 +
 drivers/media/platform/cros-ec-cec/cros-ec-cec.c | 347 +++
 drivers/mfd/cros_ec_dev.c|  16 ++
 drivers/platform/chrome/cros_ec_proto.c  |  40 ++-
 include/linux/mfd/cros_ec.h  |   2 +-
 include/linux/mfd/cros_ec_commands.h | 103 +++
 include/media/cec-notifier.h |  27 +-
 14 files changed, 580 insertions(+), 16 deletions(-)
 create mode 100644 drivers/media/platform/cros-ec-cec/Makefile
 create mode 100644 drivers/media/platform/cros-ec-cec/cros-ec-cec.c

-- 
2.7.4



[PATCH v4 3/5] mfd: cros-ec: Introduce CEC commands and events definitions.

2018-05-21 Thread Neil Armstrong
The EC can expose a CEC bus, this patch adds the CEC related definitions
needed by the cros-ec-cec driver.
Having a 16 byte mkbp event size makes it possible to send CEC
messages from the EC to the AP directly inside the mkbp event
instead of first doing a notification and then a read.

Signed-off-by: Stefan Adolfsson 
Signed-off-by: Neil Armstrong 
---
 drivers/platform/chrome/cros_ec_proto.c |  40 ++---
 include/linux/mfd/cros_ec.h |   2 +-
 include/linux/mfd/cros_ec_commands.h| 103 
 3 files changed, 135 insertions(+), 10 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index e7bbdf9..c4f6c44 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -504,10 +504,31 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
 
+static int get_next_event_xfer(struct cros_ec_device *ec_dev,
+  struct cros_ec_command *msg,
+  int version, uint32_t size)
+{
+   int ret;
+
+   msg->version = version;
+   msg->command = EC_CMD_GET_NEXT_EVENT;
+   msg->insize = size;
+   msg->outsize = 0;
+
+   ret = cros_ec_cmd_xfer(ec_dev, msg);
+   if (ret > 0) {
+   ec_dev->event_size = ret - 1;
+   memcpy(_dev->event_data, msg->data, ec_dev->event_size);
+   }
+
+   return ret;
+}
+
 static int get_next_event(struct cros_ec_device *ec_dev)
 {
u8 buffer[sizeof(struct cros_ec_command) + sizeof(ec_dev->event_data)];
struct cros_ec_command *msg = (struct cros_ec_command *)
+   static int cmd_version = 1;
int ret;
 
if (ec_dev->suspended) {
@@ -515,18 +536,19 @@ static int get_next_event(struct cros_ec_device *ec_dev)
return -EHOSTDOWN;
}
 
-   msg->version = 0;
-   msg->command = EC_CMD_GET_NEXT_EVENT;
-   msg->insize = sizeof(ec_dev->event_data);
-   msg->outsize = 0;
+   if (cmd_version == 1) {
+   ret = get_next_event_xfer(ec_dev, msg, cmd_version,
+   sizeof(struct ec_response_get_next_event_v1));
+   if (ret < 0 || msg->result != EC_RES_INVALID_VERSION)
+   return ret;
 
-   ret = cros_ec_cmd_xfer(ec_dev, msg);
-   if (ret > 0) {
-   ec_dev->event_size = ret - 1;
-   memcpy(_dev->event_data, msg->data,
-  sizeof(ec_dev->event_data));
+   /* Fallback to version 0 for future send attempts */
+   cmd_version = 0;
}
 
+   ret = get_next_event_xfer(ec_dev, msg, cmd_version,
+ sizeof(struct ec_response_get_next_event));
+
return ret;
 }
 
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index f36125e..32caef3 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -147,7 +147,7 @@ struct cros_ec_device {
bool mkbp_event_supported;
struct blocking_notifier_head event_notifier;
 
-   struct ec_response_get_next_event event_data;
+   struct ec_response_get_next_event_v1 event_data;
int event_size;
u32 host_event_wake_mask;
 };
diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index f2edd99..9b8bc4a 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -804,6 +804,8 @@ enum ec_feature_code {
EC_FEATURE_MOTION_SENSE_FIFO = 24,
/* EC has RTC feature that can be controlled by host commands */
EC_FEATURE_RTC = 27,
+   /* EC supports CEC commands */
+   EC_FEATURE_CEC = 35,
 };
 
 #define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
@@ -2078,6 +2080,12 @@ enum ec_mkbp_event {
/* EC sent a sysrq command */
EC_MKBP_EVENT_SYSRQ = 6,
 
+   /* Notify the AP that something happened on CEC */
+   EC_MKBP_CEC_EVENT = 8,
+
+   /* Send an incoming CEC message to the AP */
+   EC_MKBP_EVENT_CEC_MESSAGE = 9,
+
/* Number of MKBP events */
EC_MKBP_EVENT_COUNT,
 };
@@ -2093,12 +2101,31 @@ union ec_response_get_next_data {
uint32_t   sysrq;
 } __packed;
 
+union ec_response_get_next_data_v1 {
+   uint8_t   key_matrix[16];
+
+   /* Unaligned */
+   uint32_t  host_event;
+
+   uint32_t   buttons;
+   uint32_t   switches;
+   uint32_t   sysrq;
+   uint32_t   cec_events;
+   uint8_tcec_message[16];
+} __packed;
+
 struct ec_response_get_next_event {
uint8_t event_type;
/* Followed by event data if any */
union ec_response_get_next_data data;
 } __packed;
 
+struct ec_response_get_next_event_v1 {
+   uint8_t event_type;
+   /* Followed by event data if any */
+   union 

[PATCH v4 5/5] media: platform: Add ChromeOS EC CEC driver

2018-05-21 Thread Neil Armstrong
The ChromeOS Embedded Controller can expose a CEC bus, this patch add the
driver for such feature of the Embedded Controller.

This driver is part of the cros-ec MFD and will be add as a sub-device when
the feature bit is exposed by the EC.

The controller will only handle a single logical address and handles
all the messages retries and will only expose Success or Error.

The controller will be tied to the HDMI CEC notifier by using the platform
DMI Data and the i915 device name and connector name.

Signed-off-by: Neil Armstrong 
Reviewed-by: Enric Balletbo i Serra 
---
 drivers/media/platform/Kconfig   |  11 +
 drivers/media/platform/Makefile  |   2 +
 drivers/media/platform/cros-ec-cec/Makefile  |   1 +
 drivers/media/platform/cros-ec-cec/cros-ec-cec.c | 347 +++
 4 files changed, 361 insertions(+)
 create mode 100644 drivers/media/platform/cros-ec-cec/Makefile
 create mode 100644 drivers/media/platform/cros-ec-cec/cros-ec-cec.c

diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index c7a1cf8..bc37ecf 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -546,6 +546,17 @@ menuconfig CEC_PLATFORM_DRIVERS
 
 if CEC_PLATFORM_DRIVERS
 
+config VIDEO_CROS_EC_CEC
+   tristate "ChromeOS EC CEC driver"
+   depends on MFD_CROS_EC || COMPILE_TEST
+   select CEC_CORE
+   select CEC_NOTIFIER
+   ---help---
+ If you say yes here you will get support for the
+ ChromeOS Embedded Controller's CEC.
+ The CEC bus is present in the HDMI connector and enables communication
+ between compatible devices.
+
 config VIDEO_MESON_AO_CEC
tristate "Amlogic Meson AO CEC driver"
depends on ARCH_MESON || COMPILE_TEST
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 932515d..830696f 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -92,3 +92,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS)+= 
qcom/camss-8x16/
 obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
 
 obj-y  += meson/
+
+obj-y  += cros-ec-cec/
diff --git a/drivers/media/platform/cros-ec-cec/Makefile 
b/drivers/media/platform/cros-ec-cec/Makefile
new file mode 100644
index 000..9ce97f9
--- /dev/null
+++ b/drivers/media/platform/cros-ec-cec/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_VIDEO_CROS_EC_CEC) += cros-ec-cec.o
diff --git a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c 
b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
new file mode 100644
index 000..7f897a2
--- /dev/null
+++ b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
@@ -0,0 +1,347 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * CEC driver for ChromeOS Embedded Controller
+ *
+ * Copyright (c) 2018 BayLibre, SAS
+ * Author: Neil Armstrong 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DRV_NAME   "cros-ec-cec"
+
+/**
+ * struct cros_ec_cec - Driver data for EC CEC
+ *
+ * @cros_ec: Pointer to EC device
+ * @notifier: Notifier info for responding to EC events
+ * @adap: CEC adapter
+ * @notify: CEC notifier pointer
+ * @rx_msg: storage for a received message
+ */
+struct cros_ec_cec {
+   struct cros_ec_device *cros_ec;
+   struct notifier_block notifier;
+   struct cec_adapter *adap;
+   struct cec_notifier *notify;
+   struct cec_msg rx_msg;
+};
+
+static void handle_cec_message(struct cros_ec_cec *cros_ec_cec)
+{
+   struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+   uint8_t *cec_message = cros_ec->event_data.data.cec_message;
+   unsigned int len = cros_ec->event_size;
+
+   cros_ec_cec->rx_msg.len = len;
+   memcpy(cros_ec_cec->rx_msg.msg, cec_message, len);
+
+   cec_received_msg(cros_ec_cec->adap, _ec_cec->rx_msg);
+}
+
+static void handle_cec_event(struct cros_ec_cec *cros_ec_cec)
+{
+   struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
+   uint32_t events = cros_ec->event_data.data.cec_events;
+
+   if (events & EC_MKBP_CEC_SEND_OK)
+   cec_transmit_attempt_done(cros_ec_cec->adap,
+ CEC_TX_STATUS_OK);
+
+   /* FW takes care of all retries, tell core to avoid more retries */
+   if (events & EC_MKBP_CEC_SEND_FAILED)
+   cec_transmit_attempt_done(cros_ec_cec->adap,
+ CEC_TX_STATUS_MAX_RETRIES |
+ CEC_TX_STATUS_NACK);
+}
+
+static int cros_ec_cec_event(struct notifier_block *nb,
+unsigned long queued_during_suspend,
+void *_notify)
+{
+   struct cros_ec_cec *cros_ec_cec;
+   struct cros_ec_device *cros_ec;
+
+   

[PATCH v4 2/5] drm/i915: hdmi: add CEC notifier to intel_hdmi

2018-05-21 Thread Neil Armstrong
This patchs adds the cec_notifier feature to the intel_hdmi part
of the i915 DRM driver. It uses the HDMI DRM connector name to differentiate
between each HDMI ports.
The changes will allow the i915 HDMI code to notify EDID and HPD changes
to an eventual CEC adapter.

Signed-off-by: Neil Armstrong 
Reviewed-by: Hans Verkuil 
---
 drivers/gpu/drm/i915/Kconfig |  1 +
 drivers/gpu/drm/i915/intel_display.h | 20 
 drivers/gpu/drm/i915/intel_drv.h |  2 ++
 drivers/gpu/drm/i915/intel_hdmi.c| 13 +
 4 files changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index dfd9588..2d65d56 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -23,6 +23,7 @@ config DRM_I915
select SYNC_FILE
select IOSF_MBI
select CRC32
+   select CEC_CORE if CEC_NOTIFIER
help
  Choose this option if you have a system that has "Intel Graphics
  Media Accelerator" or "HD Graphics" integrated graphics,
diff --git a/drivers/gpu/drm/i915/intel_display.h 
b/drivers/gpu/drm/i915/intel_display.h
index 4e7418b..c68d1c8 100644
--- a/drivers/gpu/drm/i915/intel_display.h
+++ b/drivers/gpu/drm/i915/intel_display.h
@@ -126,6 +126,26 @@ enum port {
 
 #define port_name(p) ((p) + 'A')
 
+static inline const char *port_identifier(enum port port)
+{
+   switch (port) {
+   case PORT_A:
+   return "Port A";
+   case PORT_B:
+   return "Port B";
+   case PORT_C:
+   return "Port C";
+   case PORT_D:
+   return "Port D";
+   case PORT_E:
+   return "Port E";
+   case PORT_F:
+   return "Port F";
+   default:
+   return "";
+   }
+}
+
 enum dpio_channel {
DPIO_CH0,
DPIO_CH1
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d436858..b50e51b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -39,6 +39,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /**
  * __wait_for - magic wait macro
@@ -1001,6 +1002,7 @@ struct intel_hdmi {
bool has_audio;
bool rgb_quant_range_selectable;
struct intel_connector *attached_connector;
+   struct cec_notifier *notifier;
 };
 
 struct intel_dp_mst_encoder;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c 
b/drivers/gpu/drm/i915/intel_hdmi.c
index 1baef4a..d522b5b 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1868,6 +1868,8 @@ intel_hdmi_set_edid(struct drm_connector *connector)
connected = true;
}
 
+   cec_notifier_set_phys_addr_from_edid(intel_hdmi->notifier, edid);
+
return connected;
 }
 
@@ -1876,6 +1878,7 @@ intel_hdmi_detect(struct drm_connector *connector, bool 
force)
 {
enum drm_connector_status status;
struct drm_i915_private *dev_priv = to_i915(connector->dev);
+   struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
 
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
  connector->base.id, connector->name);
@@ -1891,6 +1894,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool 
force)
 
intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS);
 
+   if (status != connector_status_connected)
+   cec_notifier_phys_addr_invalidate(intel_hdmi->notifier);
+
return status;
 }
 
@@ -2031,6 +2037,8 @@ static void chv_hdmi_pre_enable(struct intel_encoder 
*encoder,
 
 static void intel_hdmi_destroy(struct drm_connector *connector)
 {
+   if (intel_attached_hdmi(connector)->notifier)
+   cec_notifier_put(intel_attached_hdmi(connector)->notifier);
kfree(to_intel_connector(connector)->detect_edid);
drm_connector_cleanup(connector);
kfree(connector);
@@ -2358,6 +2366,11 @@ void intel_hdmi_init_connector(struct intel_digital_port 
*intel_dig_port,
u32 temp = I915_READ(PEG_BAND_GAP_DATA);
I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd);
}
+
+   intel_hdmi->notifier = cec_notifier_get_conn(dev->dev,
+port_identifier(port));
+   if (!intel_hdmi->notifier)
+   DRM_DEBUG_KMS("CEC notifier get failed\n");
 }
 
 void intel_hdmi_init(struct drm_i915_private *dev_priv,
-- 
2.7.4



[PATCH v4 4/5] mfd: cros_ec_dev: Add CEC sub-device registration

2018-05-21 Thread Neil Armstrong
The EC can expose a CEC bus, thus add the cros-ec-cec MFD sub-device
when the CEC feature bit is present.

Signed-off-by: Neil Armstrong 
Reviewed-by: Enric Balletbo i Serra 
---
 drivers/mfd/cros_ec_dev.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index 1d6dc5c..272969e 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -383,6 +383,10 @@ static void cros_ec_sensors_register(struct cros_ec_dev 
*ec)
kfree(msg);
 }
 
+static const struct mfd_cell cros_ec_cec_cells[] = {
+   { .name = "cros-ec-cec" }
+};
+
 static const struct mfd_cell cros_ec_rtc_cells[] = {
{ .name = "cros-ec-rtc" }
 };
@@ -426,6 +430,18 @@ static int ec_device_probe(struct platform_device *pdev)
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
cros_ec_sensors_register(ec);
 
+   /* Check whether this EC instance has CEC host command support */
+   if (cros_ec_check_features(ec, EC_FEATURE_CEC)) {
+   retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
+cros_ec_cec_cells,
+ARRAY_SIZE(cros_ec_cec_cells),
+NULL, 0, NULL);
+   if (retval)
+   dev_err(ec->dev,
+   "failed to add cros-ec-cec device: %d\n",
+   retval);
+   }
+
/* Check whether this EC instance has RTC host command support */
if (cros_ec_check_features(ec, EC_FEATURE_RTC)) {
retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
-- 
2.7.4



[PATCH v4 1/5] media: cec-notifier: Get notifier by device and connector name

2018-05-21 Thread Neil Armstrong
In non device-tree world, we can need to get the notifier by the driver
name directly and eventually defer probe if not yet created.

This patch adds a variant of the get function by using the device name
instead and will not create a notifier if not yet created.

But the i915 driver exposes at least 2 HDMI connectors, this patch also
adds the possibility to add a connector name tied to the notifier device
to form a tuple and associate different CEC controllers for each HDMI
connectors.

Signed-off-by: Neil Armstrong 
---
 drivers/media/cec/cec-notifier.c | 11 ---
 include/media/cec-notifier.h | 27 ---
 2 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/drivers/media/cec/cec-notifier.c b/drivers/media/cec/cec-notifier.c
index 16dffa0..dd2078b 100644
--- a/drivers/media/cec/cec-notifier.c
+++ b/drivers/media/cec/cec-notifier.c
@@ -21,6 +21,7 @@ struct cec_notifier {
struct list_head head;
struct kref kref;
struct device *dev;
+   const char *conn;
struct cec_adapter *cec_adap;
void (*callback)(struct cec_adapter *adap, u16 pa);
 
@@ -30,13 +31,14 @@ struct cec_notifier {
 static LIST_HEAD(cec_notifiers);
 static DEFINE_MUTEX(cec_notifiers_lock);
 
-struct cec_notifier *cec_notifier_get(struct device *dev)
+struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char 
*conn)
 {
struct cec_notifier *n;
 
mutex_lock(_notifiers_lock);
list_for_each_entry(n, _notifiers, head) {
-   if (n->dev == dev) {
+   if (n->dev == dev &&
+   (!conn || !strcmp(n->conn, conn))) {
kref_get(>kref);
mutex_unlock(_notifiers_lock);
return n;
@@ -46,6 +48,8 @@ struct cec_notifier *cec_notifier_get(struct device *dev)
if (!n)
goto unlock;
n->dev = dev;
+   if (conn)
+   n->conn = kstrdup(conn, GFP_KERNEL);
n->phys_addr = CEC_PHYS_ADDR_INVALID;
mutex_init(>lock);
kref_init(>kref);
@@ -54,7 +58,7 @@ struct cec_notifier *cec_notifier_get(struct device *dev)
mutex_unlock(_notifiers_lock);
return n;
 }
-EXPORT_SYMBOL_GPL(cec_notifier_get);
+EXPORT_SYMBOL_GPL(cec_notifier_get_conn);
 
 static void cec_notifier_release(struct kref *kref)
 {
@@ -62,6 +66,7 @@ static void cec_notifier_release(struct kref *kref)
container_of(kref, struct cec_notifier, kref);
 
list_del(>head);
+   kfree(n->conn);
kfree(n);
 }
 
diff --git a/include/media/cec-notifier.h b/include/media/cec-notifier.h
index cf0add7..814eeef 100644
--- a/include/media/cec-notifier.h
+++ b/include/media/cec-notifier.h
@@ -20,8 +20,10 @@ struct cec_notifier;
 #if IS_REACHABLE(CONFIG_CEC_CORE) && IS_ENABLED(CONFIG_CEC_NOTIFIER)
 
 /**
- * cec_notifier_get - find or create a new cec_notifier for the given device.
+ * cec_notifier_get_conn - find or create a new cec_notifier for the given
+ * device and connector tuple.
  * @dev: device that sends the events.
+ * @conn: the connector name from which the event occurs
  *
  * If a notifier for device @dev already exists, then increase the refcount
  * and return that notifier.
@@ -31,7 +33,8 @@ struct cec_notifier;
  *
  * Return NULL if the memory could not be allocated.
  */
-struct cec_notifier *cec_notifier_get(struct device *dev);
+struct cec_notifier *cec_notifier_get_conn(struct device *dev,
+  const char *conn);
 
 /**
  * cec_notifier_put - decrease refcount and delete when the refcount reaches 0.
@@ -85,7 +88,8 @@ void cec_register_cec_notifier(struct cec_adapter *adap,
   struct cec_notifier *notifier);
 
 #else
-static inline struct cec_notifier *cec_notifier_get(struct device *dev)
+static inline struct cec_notifier *cec_notifier_get_conn(struct device *dev,
+const char *conn)
 {
/* A non-NULL pointer is expected on success */
return (struct cec_notifier *)0xdeadfeed;
@@ -121,6 +125,23 @@ static inline void cec_register_cec_notifier(struct 
cec_adapter *adap,
 #endif
 
 /**
+ * cec_notifier_get - find or create a new cec_notifier for the given device.
+ * @dev: device that sends the events.
+ *
+ * If a notifier for device @dev already exists, then increase the refcount
+ * and return that notifier.
+ *
+ * If it doesn't exist, then allocate a new notifier struct and return a
+ * pointer to that new struct.
+ *
+ * Return NULL if the memory could not be allocated.
+ */
+static inline struct cec_notifier *cec_notifier_get(struct device *dev)
+{
+   return cec_notifier_get_conn(dev, NULL);
+}
+
+/**
  * cec_notifier_phys_addr_invalidate() - set the physical address to INVALID
  *
  * @n: the CEC notifier
-- 
2.7.4



Re: [ANN] Meeting to discuss improvements to support MC-based cameras on generic apps

2018-05-21 Thread Laurent Pinchart
Hi Dave,

On Monday, 21 May 2018 15:16:19 EEST Dave Stevenson wrote:
> On 19 May 2018 at 08:04, Laurent Pinchart wrote:
> > On Friday, 18 May 2018 18:37:01 EEST Dave Stevenson wrote:
> >> On 18 May 2018 at 16:05, Mauro Carvalho Chehab wrote:
> >>> Em Fri, 18 May 2018 15:27:24 +0300
> >> 
> >> 
> >> 
> > There, instead of an USB camera, the hardware is equipped with a
> > MC-based ISP, connected to its camera. Currently, despite having
> > a Kernel driver for it, the camera doesn't work with any
> > userspace application.
> > 
> > I'm also aware of other projects that are considering the usage of
> > mc-based devices for non-dedicated hardware.
>  
>  What are those projects ?
> >>> 
> >>> Well, cheap ARM-based hardware like RPi3 already has this issue: they
> >>> have an ISP (or some GPU firmware meant to emulate an ISP). While
> >>> those hardware could have multiple sensors, typically they have just
> >>> one.
> >> 
> >> Slight hijack, but a closely linked issue for the Pi.
> >> The way I understand the issue of V4L2 / MC on Pi is a more
> >> fundamental mismatch in architecture. Please correct me if I'm wrong
> >> here.
> >> 
> >> The Pi CSI2 receiver peripheral always writes the incoming data to
> >> SDRAM, and the ISP is then a memory to memory device.
> >> 
> >> V4L2 subdevices are not dma controllers and therefore have no buffers
> >> allocated to them. So to support the full complexity of the pipeline
> >> in V4L2 requires that something somewhere would have to be dequeuing
> >> the buffers from the CSI receiver V4L2 device and queuing them to the
> >> input of a (theoretical) ISP M2M V4L2 device, and returning them once
> >> processed. The application only cares about the output of the ISP M2M
> >> device.
> > 
> > Regardless of the software stack architecture, something running on the
> > CPU has to perform that job. We have decided that that "something" needs
> > to run in userspace, to avoid pushing use-case-dependent code to the
> > kernel.
> > 
> > Note that this isn't specific to the RPi. The OMAP3 ISP, while integrating
> > the CSI-2 receiver and being able to process data on the fly, can also
> > write the raw images to memory and then process them in memory-to-memory
> > mode. This feature is used mostly for still image capture to perform
> > pre-processing with the CPU (or possibly GPU) on the raw images before
> > processing them in the ISP. There's no way we could implement this fully
> > in the kernel.
> 
> Sure. I was mainly flagging that having to manage buffers also needs
> to be considered in order to make a usable system. Just configuring an
> MC pipeline won't solve all the issues.
> 
> >> So I guess my question is whether there is a sane mechanism to remove
> >> that buffer allocation and handling from the app? Without it we are
> >> pretty much forced to hide bigger blobs of functionality to even
> >> vaguely fit in with V4L2.
> > 
> > We need a way to remove that from the application, but it won't be pushed
> > down to the kernel. These tasks should be handled by a userspace
> > framework, transparently for the application. The purpose of this
> > discussion is to decide on the design of the framework.
> 
> I'm in agreement there, but hadn't seen discussion on buffer
> management, only MC configuration.

I'll take the blame for not having been clear enough. We certainly need to 
support more than static pipeline configuration and 3A algorithms, there's a 
need to support interactions with the device at runtime even for simple 
capture without 3A. That's a use case I certainly want to see addressed.

> >> I'm at the point where it shouldn't be a huge amount of work to create
> >> at least a basic ISP V4L2 M2M device, but I'm not planning on doing it
> >> if it pushes the above buffer handling onto the app because it simply
> >> won't get used beyond demo apps. The likes of Cheese, Scratch, etc,
> >> just won't do it.
> >> 
> >> 
> >> To avoid ambiguity, the Pi has a hardware ISP block. There are other
> >> SoCs that use either GPU code or a DSP to implement their ISP.
> > 
> > Is that ISP documented publicly ?
> 
> Not publicly, and as it's Broadcom's IP we can't release it :-(
> 
> What I have working is using the Broadcom MMAL API (very similar to
> OpenMAX IL) to wrap the ISP hardware block via the VideoCore firmware.
> Currently it has the major controls exposed (black level, digital
> gain, white balance, CCMs, lens shading tables) and I'll add
> additional controls as time permits or use cases require. Resizing and
> format conversion are done based on input and output formats. Defining
> stats regions and extracting the resulting stats is still to be done.
> Overall it keeps all the implementation details hidden so we don't
> break NDAs, but should allow efficient processing. It supports
> dma-bufs in and out, so no extra copies of the data should be
> required.
> 
> I'm currently finishing off a V4L2 M2M wrapper around the MMAL
> 

Re: [PATCH v2 08/29] venus: hfi_venus: fix suspend function for venus 3xx versions

2018-05-21 Thread Stanimir Varbanov
Hi Tomasz,

On 05/18/2018 06:14 PM, Tomasz Figa wrote:
> On Tue, May 15, 2018 at 5:11 PM Stanimir Varbanov <
> stanimir.varba...@linaro.org> wrote:
> 
>> This fixes the suspend function for Venus 3xx versions by
>> add a check for WFI (wait for interrupt) bit. This bit
>> is on when the ARM9 is idle and entered in low power mode.
> 
>> Signed-off-by: Stanimir Varbanov 
>> ---
>>   drivers/media/platform/qcom/venus/hfi_venus.c| 59
> 
>>   drivers/media/platform/qcom/venus/hfi_venus_io.h |  1 +
>>   2 files changed, 41 insertions(+), 19 deletions(-)
> 
>> diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c
> b/drivers/media/platform/qcom/venus/hfi_venus.c
>> index 53546174aab8..aac351f699a0 100644
>> --- a/drivers/media/platform/qcom/venus/hfi_venus.c
>> +++ b/drivers/media/platform/qcom/venus/hfi_venus.c
>> @@ -1447,7 +1447,7 @@ static int venus_suspend_3xx(struct venus_core
> *core)
>>   {
>>  struct venus_hfi_device *hdev = to_hfi_priv(core);
>>  struct device *dev = core->dev;
>> -   u32 ctrl_status, wfi_status;
>> +   u32 ctrl_status, cpu_status;
>>  int ret;
>>  int cnt = 100;
> 
>> @@ -1463,29 +1463,50 @@ static int venus_suspend_3xx(struct venus_core
> *core)
>>  return -EINVAL;
>>  }
> 
>> -   ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0);
>> -   if (!(ctrl_status & CPU_CS_SCIACMDARG0_PC_READY)) {
>> -   wfi_status = venus_readl(hdev, WRAPPER_CPU_STATUS);
>> +   /*
>> +* Power collapse sequence for Venus 3xx and 4xx versions:
>> +* 1. Check for ARM9 and video core to be idle by checking WFI bit
>> +*(bit 0) in CPU status register and by checking Idle (bit
> 30) in
>> +*Control status register for video core.
>> +* 2. Send a command to prepare for power collapse.
>> +* 3. Check for WFI and PC_READY bits.
>> +*/
>> +
>> +   while (--cnt) {
>> +   cpu_status = venus_readl(hdev, WRAPPER_CPU_STATUS);
>>  ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0);
> 
>> -   ret = venus_prepare_power_collapse(hdev, false);
>> -   if (ret) {
>> -   dev_err(dev, "prepare for power collapse fail
> (%d)\n",
>> -   ret);
>> -   return ret;
>> -   }
>> +   if (cpu_status & WRAPPER_CPU_STATUS_WFI &&
>> +   ctrl_status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK)
>> +   break;
> 
>> -   cnt = 100;
>> -   while (cnt--) {
>> -   wfi_status = venus_readl(hdev,
> WRAPPER_CPU_STATUS);
>> -   ctrl_status = venus_readl(hdev,
> CPU_CS_SCIACMDARG0);
>> -   if (ctrl_status & CPU_CS_SCIACMDARG0_PC_READY &&
>> -   wfi_status & BIT(0))
>> -   break;
>> -   usleep_range(1000, 1500);
>> -   }
>> +   usleep_range(1000, 1500);
>>  }
> 
> To avoid opencoding the polling, I'd suggest doing a readx_poll_timeout()
> trick:

I like the idea, will try to rework that and use readx_poll_timeout.



-- 
regards,
Stan


Re: [PATCH v2 07/29] venus: hfi_venus: add halt AXI support for Venus 4xx

2018-05-21 Thread Stanimir Varbanov
Hi Tomasz,

On 05/18/2018 05:23 PM, Tomasz Figa wrote:
> On Tue, May 15, 2018 at 5:12 PM Stanimir Varbanov <
> stanimir.varba...@linaro.org> wrote:
> 
>> Add AXI halt support for version 4xx by using venus wrapper
>> registers.
> 
>> Signed-off-by: Stanimir Varbanov 
>> ---
>>   drivers/media/platform/qcom/venus/hfi_venus.c | 17 +
>>   1 file changed, 17 insertions(+)
> 
>> diff --git a/drivers/media/platform/qcom/venus/hfi_venus.c
> b/drivers/media/platform/qcom/venus/hfi_venus.c
>> index 734ce11b0ed0..53546174aab8 100644
>> --- a/drivers/media/platform/qcom/venus/hfi_venus.c
>> +++ b/drivers/media/platform/qcom/venus/hfi_venus.c
>> @@ -532,6 +532,23 @@ static int venus_halt_axi(struct venus_hfi_device
> *hdev)
>>  u32 val;
>>  int ret;
> 
>> +   if (hdev->core->res->hfi_version == HFI_VERSION_4XX) {
>> +   val = venus_readl(hdev, WRAPPER_CPU_AXI_HALT);
>> +   val |= BIT(16);
> 
> Can we have the bit defined?
> 
>> +   venus_writel(hdev, WRAPPER_CPU_AXI_HALT, val);
>> +
>> +   ret = readl_poll_timeout(base +
> WRAPPER_CPU_AXI_HALT_STATUS,
>> +val, val & BIT(24),
> 
> Ditto.

Sure will add defines.

-- 
regards,
Stan


Re: [ANN] Meeting to discuss improvements to support MC-based cameras on generic apps

2018-05-21 Thread Dave Stevenson
Hi Laurent

On 19 May 2018 at 08:04, Laurent Pinchart
 wrote:
> Hi Dave,
>
> On Friday, 18 May 2018 18:37:01 EEST Dave Stevenson wrote:
>> On 18 May 2018 at 16:05, Mauro Carvalho Chehab wrote:
>> > Em Fri, 18 May 2018 15:27:24 +0300
>>
>> 
>>
>> >>> There, instead of an USB camera, the hardware is equipped with a
>> >>> MC-based ISP, connected to its camera. Currently, despite having
>> >>> a Kernel driver for it, the camera doesn't work with any
>> >>> userspace application.
>> >>>
>> >>> I'm also aware of other projects that are considering the usage of
>> >>> mc-based devices for non-dedicated hardware.
>> >>
>> >> What are those projects ?
>> >
>> > Well, cheap ARM-based hardware like RPi3 already has this issue: they
>> > have an ISP (or some GPU firmware meant to emulate an ISP). While
>> > those hardware could have multiple sensors, typically they have just
>> > one.
>>
>> Slight hijack, but a closely linked issue for the Pi.
>> The way I understand the issue of V4L2 / MC on Pi is a more
>> fundamental mismatch in architecture. Please correct me if I'm wrong
>> here.
>>
>> The Pi CSI2 receiver peripheral always writes the incoming data to
>> SDRAM, and the ISP is then a memory to memory device.
>>
>> V4L2 subdevices are not dma controllers and therefore have no buffers
>> allocated to them. So to support the full complexity of the pipeline
>> in V4L2 requires that something somewhere would have to be dequeuing
>> the buffers from the CSI receiver V4L2 device and queuing them to the
>> input of a (theoretical) ISP M2M V4L2 device, and returning them once
>> processed. The application only cares about the output of the ISP M2M
>> device.
>
> Regardless of the software stack architecture, something running on the CPU
> has to perform that job. We have decided that that "something" needs to run in
> userspace, to avoid pushing use-case-dependent code to the kernel.
>
> Note that this isn't specific to the RPi. The OMAP3 ISP, while integrating the
> CSI-2 receiver and being able to process data on the fly, can also write the
> raw images to memory and then process them in memory-to-memory mode. This
> feature is used mostly for still image capture to perform pre-processing with
> the CPU (or possibly GPU) on the raw images before processing them in the ISP.
> There's no way we could implement this fully in the kernel.

Sure. I was mainly flagging that having to manage buffers also needs
to be considered in order to make a usable system. Just configuring an
MC pipeline won't solve all the issues.

>> So I guess my question is whether there is a sane mechanism to remove
>> that buffer allocation and handling from the app? Without it we are
>> pretty much forced to hide bigger blobs of functionality to even
>> vaguely fit in with V4L2.
>
> We need a way to remove that from the application, but it won't be pushed down
> to the kernel. These tasks should be handled by a userspace framework,
> transparently for the application. The purpose of this discussion is to decide
> on the design of the framework.

I'm in agreement there, but hadn't seen discussion on buffer
management, only MC configuration.

>> I'm at the point where it shouldn't be a huge amount of work to create
>> at least a basic ISP V4L2 M2M device, but I'm not planning on doing it
>> if it pushes the above buffer handling onto the app because it simply
>> won't get used beyond demo apps. The likes of Cheese, Scratch, etc,
>> just won't do it.
>>
>>
>> To avoid ambiguity, the Pi has a hardware ISP block. There are other
>> SoCs that use either GPU code or a DSP to implement their ISP.
>
> Is that ISP documented publicly ?

Not publicly, and as it's Broadcom's IP we can't release it :-(

What I have working is using the Broadcom MMAL API (very similar to
OpenMAX IL) to wrap the ISP hardware block via the VideoCore firmware.
Currently it has the major controls exposed (black level, digital
gain, white balance, CCMs, lens shading tables) and I'll add
additional controls as time permits or use cases require. Resizing and
format conversion are done based on input and output formats. Defining
stats regions and extracting the resulting stats is still to be done.
Overall it keeps all the implementation details hidden so we don't
break NDAs, but should allow efficient processing. It supports
dma-bufs in and out, so no extra copies of the data should be
required.

I'm currently finishing off a V4L2 M2M wrapper around the MMAL
video_encode and video_decode components, so modifying it to support
the ISP component shouldn't be difficult if there is value in doing
so.
I know it's not the ideal, but our hands are tied.

  Dave


Bugfix for Tevii S650

2018-05-21 Thread Light

Hi,

staring with kernel 4.1 the tevii S650 usb box is not working any more, 
last working version was 4.0.


The  bug was also reported here 
https://www.spinics.net/lists/linux-media/msg121356.html


I found a solution for it and uploaded a patch to the kernel bugzilla.

See here: https://bugzilla.kernel.org/show_bug.cgi?id=197731

Can somebody of the maintainers have a look on it and apply the patch to 
the kernes sources?


Light




[PATCH v14.2 v14 06/36] media-request: Add support for updating request objects optimally

2018-05-21 Thread Sakari Ailus
Add a new request state (UPDATING) as well as a count for updating the
request objects. This way, several updates may take place simultaneously
without affecting each other. The drivers (as well as frameworks) still
must serialise access to their own data structures; what is guaranteed by
the new state is simply correct and optimal handling of requests.

Signed-off-by: Sakari Ailus 
---
since v14.1:

- Add dummy variants of the update lock functions to be used if MC is
  disabled.

 drivers/media/media-request.c |  7 -
 include/media/media-request.h | 65 ++-
 2 files changed, 70 insertions(+), 2 deletions(-)

diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index a1576cf528605..cbffb0261df02 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -12,6 +12,7 @@
 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -22,6 +23,7 @@ static const char * const request_state[] = {
[MEDIA_REQUEST_STATE_QUEUED] = "queued",
[MEDIA_REQUEST_STATE_COMPLETE]   = "complete",
[MEDIA_REQUEST_STATE_CLEANING]   = "cleaning",
+   [MEDIA_REQUEST_STATE_UPDATING]   = "updating",
 };
 
 static const char *
@@ -38,12 +40,14 @@ static void media_request_clean(struct media_request *req)
 
/* Just a sanity check. No other code path is allowed to change this. */
WARN_ON(req->state != MEDIA_REQUEST_STATE_CLEANING);
+   WARN_ON(refcount_read(>updating_count));
 
list_for_each_entry_safe(obj, obj_safe, >objects, list) {
media_request_object_unbind(obj);
media_request_object_put(obj);
}
 
+   refcount_set(>updating_count, 0);
req->num_incomplete_objects = 0;
wake_up_interruptible_all(>poll_wait);
 }
@@ -294,6 +298,7 @@ int media_request_alloc(struct media_device *mdev,
INIT_LIST_HEAD(>objects);
spin_lock_init(>lock);
init_waitqueue_head(>poll_wait);
+   refcount_set(>updating_count, 0);
 
alloc->fd = fd;
 
@@ -385,7 +390,7 @@ int media_request_object_bind(struct media_request *req,
 
spin_lock_irqsave(>lock, flags);
 
-   if (WARN_ON(req->state != MEDIA_REQUEST_STATE_IDLE))
+   if (WARN_ON(req->state != MEDIA_REQUEST_STATE_UPDATING))
goto unlock;
 
list_add_tail(>list, >objects);
diff --git a/include/media/media-request.h b/include/media/media-request.h
index e175538d3c669..2a622b2d400f8 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -15,7 +15,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 #include 
 
@@ -28,6 +28,9 @@
  * @MEDIA_REQUEST_STATE_QUEUED:Queued
  * @MEDIA_REQUEST_STATE_COMPLETE:  Completed, the request is done
  * @MEDIA_REQUEST_STATE_CLEANING:  Cleaning, the request is being re-inited
+ * @MEDIA_REQUEST_STATE_UPDATING:  The request is being updated, i.e.
+ * request objects are being added,
+ * modified or removed
  */
 enum media_request_state {
MEDIA_REQUEST_STATE_IDLE,
@@ -35,6 +38,7 @@ enum media_request_state {
MEDIA_REQUEST_STATE_QUEUED,
MEDIA_REQUEST_STATE_COMPLETE,
MEDIA_REQUEST_STATE_CLEANING,
+   MEDIA_REQUEST_STATE_UPDATING,
 };
 
 struct media_request_object;
@@ -56,6 +60,7 @@ struct media_request {
struct kref kref;
char debug_str[TASK_COMM_LEN + 11];
enum media_request_state state;
+   refcount_t updating_count;
struct list_head objects;
unsigned int num_incomplete_objects;
struct wait_queue_head poll_wait;
@@ -65,6 +70,54 @@ struct media_request {
 #ifdef CONFIG_MEDIA_CONTROLLER
 
 /**
+ * media_request_lock_for_update - Lock the request for updating its objects
+ *
+ * @req: The media request
+ *
+ * Use before updating a request, i.e. adding, modifying or removing a request
+ * object in it. A reference to the request must be held during the update. 
This
+ * usually takes place automatically through a file handle. Use
+ * @media_request_unlock_for_update when done.
+ */
+static inline int __must_check
+media_request_lock_for_update(struct media_request *req)
+{
+   unsigned long flags;
+   int ret = 0;
+
+   spin_lock_irqsave(>lock, flags);
+   if (req->state == MEDIA_REQUEST_STATE_IDLE ||
+   req->state == MEDIA_REQUEST_STATE_UPDATING) {
+   req->state = MEDIA_REQUEST_STATE_UPDATING;
+   refcount_inc(>updating_count);
+   } else {
+   ret = -EBUSY;
+   }
+   spin_unlock_irqrestore(>lock, flags);
+
+   return ret;
+}
+
+/**
+ * media_request_unlock_for_update - Unlock a request previously locked for
+ *  update
+ *
+ * @req: The media request
+ *
+ * Unlock a request that has previously been locked using
+ * @media_request_lock_for_update.
+ 

[PATCH v14.1 v14 06/36] media-request: Add support for updating request objects optimally

2018-05-21 Thread Sakari Ailus
Add a new request state (UPDATING) as well as a count for updating the
request objects. This way, several updates may take place simultaneously
without affecting each other. The drivers (as well as frameworks) still
must serialise access to their own data structures; what is guaranteed by
the new state is simply correct and optimal handling of requests.

Signed-off-by: Sakari Ailus 
---
since v14:

- Correctly initialise the refcount to zero, as well as check it's zero
  when the request is cleaned

 drivers/media/media-request.c |  7 +-
 include/media/media-request.h | 55 ++-
 2 files changed, 60 insertions(+), 2 deletions(-)

diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index a1576cf528605..cbffb0261df02 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -12,6 +12,7 @@
 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -22,6 +23,7 @@ static const char * const request_state[] = {
[MEDIA_REQUEST_STATE_QUEUED] = "queued",
[MEDIA_REQUEST_STATE_COMPLETE]   = "complete",
[MEDIA_REQUEST_STATE_CLEANING]   = "cleaning",
+   [MEDIA_REQUEST_STATE_UPDATING]   = "updating",
 };
 
 static const char *
@@ -38,12 +40,14 @@ static void media_request_clean(struct media_request *req)
 
/* Just a sanity check. No other code path is allowed to change this. */
WARN_ON(req->state != MEDIA_REQUEST_STATE_CLEANING);
+   WARN_ON(refcount_read(>updating_count));
 
list_for_each_entry_safe(obj, obj_safe, >objects, list) {
media_request_object_unbind(obj);
media_request_object_put(obj);
}
 
+   refcount_set(>updating_count, 0);
req->num_incomplete_objects = 0;
wake_up_interruptible_all(>poll_wait);
 }
@@ -294,6 +298,7 @@ int media_request_alloc(struct media_device *mdev,
INIT_LIST_HEAD(>objects);
spin_lock_init(>lock);
init_waitqueue_head(>poll_wait);
+   refcount_set(>updating_count, 0);
 
alloc->fd = fd;
 
@@ -385,7 +390,7 @@ int media_request_object_bind(struct media_request *req,
 
spin_lock_irqsave(>lock, flags);
 
-   if (WARN_ON(req->state != MEDIA_REQUEST_STATE_IDLE))
+   if (WARN_ON(req->state != MEDIA_REQUEST_STATE_UPDATING))
goto unlock;
 
list_add_tail(>list, >objects);
diff --git a/include/media/media-request.h b/include/media/media-request.h
index e175538d3c669..84186b7be7de8 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -15,7 +15,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 #include 
 
@@ -28,6 +28,9 @@
  * @MEDIA_REQUEST_STATE_QUEUED:Queued
  * @MEDIA_REQUEST_STATE_COMPLETE:  Completed, the request is done
  * @MEDIA_REQUEST_STATE_CLEANING:  Cleaning, the request is being re-inited
+ * @MEDIA_REQUEST_STATE_UPDATING:  The request is being updated, i.e.
+ * request objects are being added,
+ * modified or removed
  */
 enum media_request_state {
MEDIA_REQUEST_STATE_IDLE,
@@ -35,6 +38,7 @@ enum media_request_state {
MEDIA_REQUEST_STATE_QUEUED,
MEDIA_REQUEST_STATE_COMPLETE,
MEDIA_REQUEST_STATE_CLEANING,
+   MEDIA_REQUEST_STATE_UPDATING,
 };
 
 struct media_request_object;
@@ -56,6 +60,7 @@ struct media_request {
struct kref kref;
char debug_str[TASK_COMM_LEN + 11];
enum media_request_state state;
+   refcount_t updating_count;
struct list_head objects;
unsigned int num_incomplete_objects;
struct wait_queue_head poll_wait;
@@ -65,6 +70,54 @@ struct media_request {
 #ifdef CONFIG_MEDIA_CONTROLLER
 
 /**
+ * media_request_lock_for_update - Lock the request for updating its objects
+ *
+ * @req: The media request
+ *
+ * Use before updating a request, i.e. adding, modifying or removing a request
+ * object in it. A reference to the request must be held during the update. 
This
+ * usually takes place automatically through a file handle. Use
+ * @media_request_unlock_for_update when done.
+ */
+static inline int __must_check
+media_request_lock_for_update(struct media_request *req)
+{
+   unsigned long flags;
+   int ret = 0;
+
+   spin_lock_irqsave(>lock, flags);
+   if (req->state == MEDIA_REQUEST_STATE_IDLE ||
+   req->state == MEDIA_REQUEST_STATE_UPDATING) {
+   req->state = MEDIA_REQUEST_STATE_UPDATING;
+   refcount_inc(>updating_count);
+   } else {
+   ret = -EBUSY;
+   }
+   spin_unlock_irqrestore(>lock, flags);
+
+   return ret;
+}
+
+/**
+ * media_request_unlock_for_update - Unlock a request previously locked for
+ *  update
+ *
+ * @req: The media request
+ *
+ * Unlock a request that has previously been locked using
+ * 

[PATCH] media: uvcvideo: Fix driver reference counting

2018-05-21 Thread Philipp Zabel
kref_init initializes the reference count to 1, not 0. This additional
reference is never released since the conversion to reference counters.
As a result, uvc_delete is not called anymore when UVC cameras are
disconnected.
Fix this by adding an additional kref_put in uvc_disconnect and in the
probe error path. This also allows to remove the temporary additional
reference in uvc_unregister_video.

Fixes: 9d15cd958c17 ("media: uvcvideo: Convert from using an atomic variable to 
a reference count")
Signed-off-by: Philipp Zabel 
---
 drivers/media/usb/uvc/uvc_driver.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_driver.c 
b/drivers/media/usb/uvc/uvc_driver.c
index 2469b49b2b30..8e138201330f 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1871,13 +1871,6 @@ static void uvc_unregister_video(struct uvc_device *dev)
 {
struct uvc_streaming *stream;
 
-   /* Unregistering all video devices might result in uvc_delete() being
-* called from inside the loop if there's no open file handle. To avoid
-* that, increment the refcount before iterating over the streams and
-* decrement it when done.
-*/
-   kref_get(>ref);
-
list_for_each_entry(stream, >streams, list) {
if (!video_is_registered(>vdev))
continue;
@@ -1887,8 +1880,6 @@ static void uvc_unregister_video(struct uvc_device *dev)
 
uvc_debugfs_cleanup_stream(stream);
}
-
-   kref_put(>ref, uvc_delete);
 }
 
 int uvc_register_video_device(struct uvc_device *dev,
@@ -2184,6 +2175,7 @@ static int uvc_probe(struct usb_interface *intf,
 
 error:
uvc_unregister_video(dev);
+   kref_put(>ref, uvc_delete);
return -ENODEV;
 }
 
@@ -2201,6 +2193,7 @@ static void uvc_disconnect(struct usb_interface *intf)
return;
 
uvc_unregister_video(dev);
+   kref_put(>ref, uvc_delete);
 }
 
 static int uvc_suspend(struct usb_interface *intf, pm_message_t message)
-- 
2.17.0



[GIT PULL for 4.18] Renesas R-Car CSI-2 receiver driver

2018-05-21 Thread Sakari Ailus
Hi Mauro,

Here's the driver for the Renesas R-Car CSI-2 receiver.

Please pull.


The following changes since commit 8ed8bba70b4355b1ba029b151ade84475dd12991:

  media: imx274: remove non-indexed pointers from mode_table (2018-05-17 
06:22:08 -0400)

are available in the git repository at:

  ssh://linuxtv.org/git/sailus/media_tree.git for-4.18-6

for you to fetch changes up to defb00ec395644ba5a5423e7f59254a253c7755b:

  rcar-csi2: set default format if a unsupported one is requested (2018-05-17 
13:56:39 +0300)


Niklas Söderlund (3):
  rcar-csi2: add Renesas R-Car MIPI CSI-2 receiver documentation
  rcar-csi2: add Renesas R-Car MIPI CSI-2 receiver driver
  rcar-csi2: set default format if a unsupported one is requested

 .../bindings/media/renesas,rcar-csi2.txt   |  101 ++
 MAINTAINERS|1 +
 drivers/media/platform/rcar-vin/Kconfig|   12 +
 drivers/media/platform/rcar-vin/Makefile   |1 +
 drivers/media/platform/rcar-vin/rcar-csi2.c| 1084 
 5 files changed, 1199 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/media/renesas,rcar-csi2.txt
 create mode 100644 drivers/media/platform/rcar-vin/rcar-csi2.c

-- 
Sakari Ailus
e-mail: sakari.ai...@iki.fi


[PATCH] [media] hdpvr: fix spelling mistake: "Hauppage" -> "Hauppauge"

2018-05-21 Thread Colin King
From: Colin Ian King 

Trivial fix to spelling mistake in name field

Signed-off-by: Colin Ian King 
---
 drivers/media/usb/hdpvr/hdpvr-i2c.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/media/usb/hdpvr/hdpvr-i2c.c 
b/drivers/media/usb/hdpvr/hdpvr-i2c.c
index 4720d79b0282..c71ddefd2e58 100644
--- a/drivers/media/usb/hdpvr/hdpvr-i2c.c
+++ b/drivers/media/usb/hdpvr/hdpvr-i2c.c
@@ -173,7 +173,7 @@ static const struct i2c_algorithm hdpvr_algo = {
 };
 
 static const struct i2c_adapter hdpvr_i2c_adapter_template = {
-   .name   = "Hauppage HD PVR I2C",
+   .name   = "Hauppauge HD PVR I2C",
.owner  = THIS_MODULE,
.algo   = _algo,
 };
-- 
2.17.0



Re: [PATCH v2 0/5] Add ChromeOS EC CEC Support

2018-05-21 Thread Neil Armstrong
On 18/05/2018 16:04, Enric Balletbo Serra wrote:
> Hi Neil,
> 
> 2018-05-18 15:04 GMT+02:00 Neil Armstrong :
>> Hi All,
>>
>> The new Google "Fizz" Intel-based ChromeOS device is gaining CEC support
>> through it's Embedded Controller, to enable the Linux CEC Core to communicate
>> with it and get the CEC Physical Address from the correct HDMI Connector, the
>> following must be added/changed:
>> - Add the CEC sub-device registration in the ChromeOS EC MFD Driver
>> - Add the CEC related commands and events definitions into the EC MFD driver
>> - Add a way to get a CEC notifier with it's (optional) connector name
>> - Add the CEC notifier to the i915 HDMI driver
>> - Add the proper ChromeOS EC CEC Driver
>>
>> The CEC notifier with the connector name is the tricky point, since even on
>> Device-Tree platforms, there is no way to distinguish between multiple HDMI
>> connectors from the same DRM driver. The solution I implemented is pretty
>> simple and only adds an optional connector name to eventually distinguish
>> an HDMI connector notifier from another if they share the same device.
>>
>> Feel free to comment this patchset !
>>
>> Changes since v2:
>>  - Add i915 port_identifier() and use this stable name as cec_notifier conn 
>> name
>>  - Fixed and cleaned up the CEC commands and events handling
>>  - Rebased the CEC sub-device registration on top of Enric's serie
>>  - Fixed comments typo on cec driver
>>  - Protected the DMI match only with PCI and DMI Kconfigs
>>
> 
> Just because I got confused when I saw two v2 in my inbox. This is v3, right?

Yes, sorry it's v3... next will be v4.

> 
>> Changes since v1:
>>  - Added cec_notifier_put to intel_hdmi
>>  - Fixed all small reported issues on the EC CEC driver
>>  - Moved the cec_notifier_get out of the #if .. #else .. #endif
>>
>> Changes since RFC:
>>  - Moved CEC sub-device registration after CEC commands and events 
>> definitions patch
>>  - Removed get_notifier_get_byname
>>  - Added CEC_CORE select into i915 Kconfig
>>  - Removed CEC driver fallback if notifier is not configured on HW, added 
>> explicit warn
>>  - Fixed CEC core return type on error
>>  - Moved to cros-ec-cec media platform directory
>>  - Use bus_find_device() to find the pci i915 device instead of 
>> get_notifier_get_byname()
>>  - Fix Logical Address setup
>>  - Added comment about HW support
>>  - Removed memset of msg structures
>>
>> Neil Armstrong (5):
>>   media: cec-notifier: Get notifier by device and connector name
>>   drm/i915: hdmi: add CEC notifier to intel_hdmi
>>   mfd: cros-ec: Introduce CEC commands and events definitions.
>>   mfd: cros_ec_dev: Add CEC sub-device registration
>>   media: platform: Add Chrome OS EC CEC driver
>>
>>  drivers/gpu/drm/i915/Kconfig |   1 +
>>  drivers/gpu/drm/i915/intel_display.h |  20 ++
>>  drivers/gpu/drm/i915/intel_drv.h |   2 +
>>  drivers/gpu/drm/i915/intel_hdmi.c|  13 +
>>  drivers/media/cec/cec-notifier.c |  11 +-
>>  drivers/media/platform/Kconfig   |  11 +
>>  drivers/media/platform/Makefile  |   2 +
>>  drivers/media/platform/cros-ec-cec/Makefile  |   1 +
>>  drivers/media/platform/cros-ec-cec/cros-ec-cec.c | 347 
>> +++
>>  drivers/mfd/cros_ec_dev.c|  16 ++
>>  drivers/platform/chrome/cros_ec_proto.c  |  40 ++-
>>  include/linux/mfd/cros_ec.h  |   2 +-
>>  include/linux/mfd/cros_ec_commands.h |  80 ++
>>  include/media/cec-notifier.h |  27 +-
>>  14 files changed, 557 insertions(+), 16 deletions(-)
>>  create mode 100644 drivers/media/platform/cros-ec-cec/Makefile
>>  create mode 100644 drivers/media/platform/cros-ec-cec/cros-ec-cec.c
>>
>> --
>> 2.7.4
>>



Re: [PATCH v2 5/5] media: platform: Add Chrome OS EC CEC driver

2018-05-21 Thread Neil Armstrong
Hi Enric,

On 18/05/2018 17:02, Enric Balletbo Serra wrote:
> Hi Neil,
> 
> 2018-05-18 15:05 GMT+02:00 Neil Armstrong :
>> The Chrome OS Embedded Controller can expose a CEC bus, this patch add the
> 
> A minor nit, there is a "consensus" on tell cros-ec as "ChromeOS
> Embedded Controller" or "ChromeOS EC". Yes, I know that you can see in
> the kernel many other ways to refer to the ChromeOS EC, but to
> standardize a little bit, could you replace all occurrences s/Chrome
> OS/ChromeOS/. Thanks.

Ok, I'll do a cleanup.

> 
>> driver for such feature of the Embedded Controller.
>>
>> This driver is part of the cros-ec MFD and will be add as a sub-device when
>> the feature bit is exposed by the EC.
>>
>> The controller will only handle a single logical address and handles
>> all the messages retries and will only expose Success or Error.
>>
>> The controller will be tied to the HDMI CEC notifier by using the platform
>> DMI Data and the i915 device name and connector name.
>>
>> Signed-off-by: Neil Armstrong 
>> ---
>>  drivers/media/platform/Kconfig   |  11 +
>>  drivers/media/platform/Makefile  |   2 +
>>  drivers/media/platform/cros-ec-cec/Makefile  |   1 +
>>  drivers/media/platform/cros-ec-cec/cros-ec-cec.c | 347 
>> +++
>>  4 files changed, 361 insertions(+)
>>  create mode 100644 drivers/media/platform/cros-ec-cec/Makefile
>>  create mode 100644 drivers/media/platform/cros-ec-cec/cros-ec-cec.c
>>
>> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
>> index c7a1cf8..e55a8ed2 100644
>> --- a/drivers/media/platform/Kconfig
>> +++ b/drivers/media/platform/Kconfig
>> @@ -546,6 +546,17 @@ menuconfig CEC_PLATFORM_DRIVERS
>>
>>  if CEC_PLATFORM_DRIVERS
>>
>> +config VIDEO_CROS_EC_CEC
>> +   tristate "Chrome OS EC CEC driver"
> 
> here
> 
>> +   depends on MFD_CROS_EC || COMPILE_TEST
>> +   select CEC_CORE
>> +   select CEC_NOTIFIER
>> +   ---help---
>> + If you say yes here you will get support for the
>> + Chrome OS Embedded Controller's CEC.
> 
> here
> 
>> + The CEC bus is present in the HDMI connector and enables 
>> communication
>> + between compatible devices.
>> +
>>  config VIDEO_MESON_AO_CEC
>> tristate "Amlogic Meson AO CEC driver"
>> depends on ARCH_MESON || COMPILE_TEST
>> diff --git a/drivers/media/platform/Makefile 
>> b/drivers/media/platform/Makefile
>> index 932515d..830696f 100644
>> --- a/drivers/media/platform/Makefile
>> +++ b/drivers/media/platform/Makefile
>> @@ -92,3 +92,5 @@ obj-$(CONFIG_VIDEO_QCOM_CAMSS)+= 
>> qcom/camss-8x16/
>>  obj-$(CONFIG_VIDEO_QCOM_VENUS) += qcom/venus/
>>
>>  obj-y  += meson/
>> +
>> +obj-y  += cros-ec-cec/
>> diff --git a/drivers/media/platform/cros-ec-cec/Makefile 
>> b/drivers/media/platform/cros-ec-cec/Makefile
>> new file mode 100644
>> index 000..9ce97f9
>> --- /dev/null
>> +++ b/drivers/media/platform/cros-ec-cec/Makefile
>> @@ -0,0 +1 @@
>> +obj-$(CONFIG_VIDEO_CROS_EC_CEC) += cros-ec-cec.o
>> diff --git a/drivers/media/platform/cros-ec-cec/cros-ec-cec.c 
>> b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
>> new file mode 100644
>> index 000..7e1e275
>> --- /dev/null
>> +++ b/drivers/media/platform/cros-ec-cec/cros-ec-cec.c
>> @@ -0,0 +1,347 @@
>> +// SPDX-License-Identifier: GPL-2.0+
>> +/*
>> + * CEC driver for Chrome OS Embedded Controller
> 
> and here
> 
>> + *
>> + * Copyright (c) 2018 BayLibre, SAS
>> + * Author: Neil Armstrong 
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#define DRV_NAME   "cros-ec-cec"
>> +
>> +/**
>> + * struct cros_ec_cec - Driver data for EC CEC
>> + *
>> + * @cros_ec: Pointer to EC device
>> + * @notifier: Notifier info for responding to EC events
>> + * @adap: CEC adapter
>> + * @notify: CEC notifier pointer
>> + * @rx_msg: storage for a received message
>> + */
>> +struct cros_ec_cec {
>> +   struct cros_ec_device *cros_ec;
>> +   struct notifier_block notifier;
>> +   struct cec_adapter *adap;
>> +   struct cec_notifier *notify;
>> +   struct cec_msg rx_msg;
>> +};
>> +
>> +static void handle_cec_message(struct cros_ec_cec *cros_ec_cec)
>> +{
>> +   struct cros_ec_device *cros_ec = cros_ec_cec->cros_ec;
>> +   uint8_t *cec_message = cros_ec->event_data.data.cec_message;
>> +   unsigned int len = cros_ec->event_size;
>> +
>> +   cros_ec_cec->rx_msg.len = len;
>> +   memcpy(cros_ec_cec->rx_msg.msg, cec_message, len);
>> +
>> +   cec_received_msg(cros_ec_cec->adap, _ec_cec->rx_msg);
>> +}
>> +
>> +static void handle_cec_event(struct cros_ec_cec *cros_ec_cec)
>> +{
>> +   struct cros_ec_device *cros_ec = 

Re: [PATCH v2 3/5] mfd: cros-ec: Introduce CEC commands and events definitions.

2018-05-21 Thread Neil Armstrong
Hi Enric,

On 18/05/2018 18:19, Enric Balletbo Serra wrote:
> Hi Neil,
> 
> 2018-05-18 15:05 GMT+02:00 Neil Armstrong :
>> The EC can expose a CEC bus, this patch adds the CEC related definitions
>> needed by the cros-ec-cec driver.
>> Having a 16 byte mkbp event size makes it possible to send CEC
>> messages from the EC to the AP directly inside the mkbp event
>> instead of first doing a notification and then a read.
>>
>> Signed-off-by: Stefan Adolfsson 
>> Signed-off-by: Neil Armstrong 
>> ---
>>  drivers/platform/chrome/cros_ec_proto.c | 40 +
>>  include/linux/mfd/cros_ec.h |  2 +-
>>  include/linux/mfd/cros_ec_commands.h| 80 
>> +
>>  3 files changed, 112 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/platform/chrome/cros_ec_proto.c 
>> b/drivers/platform/chrome/cros_ec_proto.c
>> index e7bbdf9..c4f6c44 100644
>> --- a/drivers/platform/chrome/cros_ec_proto.c
>> +++ b/drivers/platform/chrome/cros_ec_proto.c
>> @@ -504,10 +504,31 @@ int cros_ec_cmd_xfer_status(struct cros_ec_device 
>> *ec_dev,
>>  }
>>  EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
>>
>> +static int get_next_event_xfer(struct cros_ec_device *ec_dev,
>> +  struct cros_ec_command *msg,
>> +  int version, uint32_t size)
>> +{
>> +   int ret;
>> +
>> +   msg->version = version;
>> +   msg->command = EC_CMD_GET_NEXT_EVENT;
>> +   msg->insize = size;
>> +   msg->outsize = 0;
>> +
>> +   ret = cros_ec_cmd_xfer(ec_dev, msg);
>> +   if (ret > 0) {
>> +   ec_dev->event_size = ret - 1;
>> +   memcpy(_dev->event_data, msg->data, ec_dev->event_size);
>> +   }
>> +
>> +   return ret;
>> +}
>> +
>>  static int get_next_event(struct cros_ec_device *ec_dev)
>>  {
>> u8 buffer[sizeof(struct cros_ec_command) + 
>> sizeof(ec_dev->event_data)];
>> struct cros_ec_command *msg = (struct cros_ec_command *)
>> +   static int cmd_version = 1;
> 
> Personal opinion, but I don't like this static here, and also I don't
> think this is scalable. Could we ask for the command version?

I don't have an opinion, I only followed how it was implemented on the
chromeos kernel and adapted to mainline. If you have a better way, I'll use it !

> 
>> int ret;
>>
>> if (ec_dev->suspended) {
>> @@ -515,18 +536,19 @@ static int get_next_event(struct cros_ec_device 
>> *ec_dev)
>> return -EHOSTDOWN;
>> }
>>
>> -   msg->version = 0;
>> -   msg->command = EC_CMD_GET_NEXT_EVENT;
>> -   msg->insize = sizeof(ec_dev->event_data);
>> -   msg->outsize = 0;
>> +   if (cmd_version == 1) {
>> +   ret = get_next_event_xfer(ec_dev, msg, cmd_version,
>> +   sizeof(struct 
>> ec_response_get_next_event_v1));
>> +   if (ret < 0 || msg->result != EC_RES_INVALID_VERSION)
>> +   return ret;
>>
>> -   ret = cros_ec_cmd_xfer(ec_dev, msg);
>> -   if (ret > 0) {
>> -   ec_dev->event_size = ret - 1;
>> -   memcpy(_dev->event_data, msg->data,
>> -  sizeof(ec_dev->event_data));
>> +   /* Fallback to version 0 for future send attempts */
>> +   cmd_version = 0;
>> }
>>
> 
> So we always do a failed transfer on all these EC devices that does
> not support CEC. I am wondering if wouldn't be better pass the command
> version to the cros_ec_get_next_event function. The driver should know
> which version to use, just a random idea.

No, the driver cannot know the command version, this depends on the FW version
and the platform. AFAIK this must be discovered.

> 
>> +   ret = get_next_event_xfer(ec_dev, msg, cmd_version,
>> + sizeof(struct ec_response_get_next_event));
>> +
>> return ret;
>>  }
>>
>> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
>> index f36125e..32caef3 100644
>> --- a/include/linux/mfd/cros_ec.h
>> +++ b/include/linux/mfd/cros_ec.h
>> @@ -147,7 +147,7 @@ struct cros_ec_device {
>> bool mkbp_event_supported;
>> struct blocking_notifier_head event_notifier;
>>
>> -   struct ec_response_get_next_event event_data;
>> +   struct ec_response_get_next_event_v1 event_data;
>> int event_size;
>> u32 host_event_wake_mask;
>>  };
>> diff --git a/include/linux/mfd/cros_ec_commands.h 
>> b/include/linux/mfd/cros_ec_commands.h
>> index f2edd99..16c3a2b 100644
>> --- a/include/linux/mfd/cros_ec_commands.h
>> +++ b/include/linux/mfd/cros_ec_commands.h
> 
> This file is going to be very big and as requested by Lee I plan to
> convert this file to the kernel-doc format, this patch introduces some
> new structs so could you document the new structs in the suggested
> format?

Ok

> 
>> @@ -804,6 +804,8 @@ enum 

[PATCH v14 16/36] v4l2-ctrls: Add documentation for control request support functions

2018-05-21 Thread Sakari Ailus
Add kerneldoc documentation for v4l2_ctrl_request_setup and
v4l2_ctrl_request_complete functions.

Signed-off-by: Sakari Ailus 
---
 include/media/v4l2-ctrls.h | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index a0f7c38d1a902..d2e5653df645e 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -1077,8 +1077,34 @@ int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
  */
 __poll_t v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait);
 
+/**
+ * v4l2_ctrl_request_setup - helper function to apply control values in a 
request
+ *
+ * @req: The request
+ * @hdl: The control handler
+ *
+ * This is a helper function to call the control handler's s_ctrl callback with
+ * the control values contained in the request. Do note that this approach of
+ * applying control values in a request is only applicable to memory-to-memory
+ * devices.
+ */
 void v4l2_ctrl_request_setup(struct media_request *req,
 struct v4l2_ctrl_handler *hdl);
+
+/**
+ * v4l2_ctrl_request_complete - Complete a control handler request object
+ *
+ * @req: The request
+ * @hdl: The control handler
+ *
+ * This function is to be called on each control handler that may have had a
+ * request object associated with it, i.e. control handlers of a driver that
+ * supports requests.
+ *
+ * The function first obtains the values of any volatile controls in the 
control
+ * handler and attach them to the request. Then, the function completes the
+ * request object.
+ */
 void v4l2_ctrl_request_complete(struct media_request *req,
struct v4l2_ctrl_handler *hdl);
 
-- 
2.11.0



[PATCH v14 10/36] videodev2.h: add request_fd field to v4l2_ext_controls

2018-05-21 Thread Sakari Ailus
From: Alexandre Courbot 

If 'which' is V4L2_CTRL_WHICH_REQUEST_VAL, then the 'request_fd' field
can be used to specify a request for the G/S/TRY_EXT_CTRLS ioctls.

Signed-off-by: Alexandre Courbot 
Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 5 -
 drivers/media/v4l2-core/v4l2-ioctl.c  | 6 +++---
 include/uapi/linux/videodev2.h| 4 +++-
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c 
b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 6481212fda772..dcce86c1fe40d 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -834,7 +834,8 @@ struct v4l2_ext_controls32 {
__u32 which;
__u32 count;
__u32 error_idx;
-   __u32 reserved[2];
+   __s32 request_fd;
+   __u32 reserved[1];
compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
 };
 
@@ -909,6 +910,7 @@ static int get_v4l2_ext_controls32(struct file *file,
get_user(count, >count) ||
put_user(count, >count) ||
assign_in_user(>error_idx, >error_idx) ||
+   assign_in_user(>request_fd, >request_fd) ||
copy_in_user(p64->reserved, p32->reserved, sizeof(p64->reserved)))
return -EFAULT;
 
@@ -974,6 +976,7 @@ static int put_v4l2_ext_controls32(struct file *file,
get_user(count, >count) ||
put_user(count, >count) ||
assign_in_user(>error_idx, >error_idx) ||
+   assign_in_user(>request_fd, >request_fd) ||
copy_in_user(p32->reserved, p64->reserved, sizeof(p32->reserved)) ||
get_user(kcontrols, >controls))
return -EFAULT;
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c 
b/drivers/media/v4l2-core/v4l2-ioctl.c
index a40dbec271f1d..60247dcfa77d4 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -553,8 +553,8 @@ static void v4l_print_ext_controls(const void *arg, bool 
write_only)
const struct v4l2_ext_controls *p = arg;
int i;
 
-   pr_cont("which=0x%x, count=%d, error_idx=%d",
-   p->which, p->count, p->error_idx);
+   pr_cont("which=0x%x, count=%d, error_idx=%d, request_fd=%d",
+   p->which, p->count, p->error_idx, p->request_fd);
for (i = 0; i < p->count; i++) {
if (!p->controls[i].size)
pr_cont(", id/val=0x%x/0x%x",
@@ -870,7 +870,7 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int 
allow_priv)
__u32 i;
 
/* zero the reserved fields */
-   c->reserved[0] = c->reserved[1] = 0;
+   c->reserved[0] = 0;
for (i = 0; i < c->count; i++)
c->controls[i].reserved2[0] = 0;
 
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 600877be5c229..16b53b82496c4 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -1592,7 +1592,8 @@ struct v4l2_ext_controls {
};
__u32 count;
__u32 error_idx;
-   __u32 reserved[2];
+   __s32 request_fd;
+   __u32 reserved[1];
struct v4l2_ext_control *controls;
 };
 
@@ -1605,6 +1606,7 @@ struct v4l2_ext_controls {
 #define V4L2_CTRL_MAX_DIMS   (4)
 #define V4L2_CTRL_WHICH_CUR_VAL   0
 #define V4L2_CTRL_WHICH_DEF_VAL   0x0f00
+#define V4L2_CTRL_WHICH_REQUEST_VAL 0x0f01
 
 enum v4l2_ctrl_type {
V4L2_CTRL_TYPE_INTEGER   = 1,
-- 
2.11.0



[PATCH v14 11/36] v4l2-ctrls: v4l2_ctrl_add_handler: add from_other_dev

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Add a 'bool from_other_dev' argument: set to true if the two
handlers refer to different devices (e.g. it is true when
inheriting controls from a subdev into a main v4l2 bridge
driver).

This will be used later when implementing support for the
request API since we need to skip such controls.

TODO: check drivers/staging/media/imx/imx-media-fim.c change.

Signed-off-by: Hans Verkuil 
Signed-off-by: Alexandre Courbot 
---
 drivers/media/dvb-frontends/rtl2832_sdr.c|  5 +--
 drivers/media/pci/bt8xx/bttv-driver.c|  2 +-
 drivers/media/pci/cx23885/cx23885-417.c  |  2 +-
 drivers/media/pci/cx88/cx88-blackbird.c  |  2 +-
 drivers/media/pci/cx88/cx88-video.c  |  2 +-
 drivers/media/pci/saa7134/saa7134-empress.c  |  4 +--
 drivers/media/pci/saa7134/saa7134-video.c|  2 +-
 drivers/media/platform/exynos4-is/fimc-capture.c |  2 +-
 drivers/media/platform/rcar-vin/rcar-core.c  |  2 +-
 drivers/media/platform/rcar_drif.c   |  2 +-
 drivers/media/platform/soc_camera/soc_camera.c   |  3 +-
 drivers/media/platform/vivid/vivid-ctrls.c   | 46 
 drivers/media/usb/cx231xx/cx231xx-417.c  |  2 +-
 drivers/media/usb/cx231xx/cx231xx-video.c|  4 +--
 drivers/media/usb/msi2500/msi2500.c  |  2 +-
 drivers/media/usb/tm6000/tm6000-video.c  |  2 +-
 drivers/media/v4l2-core/v4l2-ctrls.c | 11 +++---
 drivers/media/v4l2-core/v4l2-device.c|  3 +-
 drivers/staging/media/imx/imx-media-dev.c|  2 +-
 drivers/staging/media/imx/imx-media-fim.c|  2 +-
 include/media/v4l2-ctrls.h   |  8 -
 21 files changed, 61 insertions(+), 49 deletions(-)

diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c 
b/drivers/media/dvb-frontends/rtl2832_sdr.c
index c6e78d870ccdc..6064d28224e81 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -1394,7 +1394,8 @@ static int rtl2832_sdr_probe(struct platform_device *pdev)
case RTL2832_SDR_TUNER_E4000:
v4l2_ctrl_handler_init(>hdl, 9);
if (subdev)
-   v4l2_ctrl_add_handler(>hdl, subdev->ctrl_handler, 
NULL);
+   v4l2_ctrl_add_handler(>hdl, subdev->ctrl_handler,
+ NULL, true);
break;
case RTL2832_SDR_TUNER_R820T:
case RTL2832_SDR_TUNER_R828D:
@@ -1423,7 +1424,7 @@ static int rtl2832_sdr_probe(struct platform_device *pdev)
v4l2_ctrl_handler_init(>hdl, 2);
if (subdev)
v4l2_ctrl_add_handler(>hdl, subdev->ctrl_handler,
- NULL);
+ NULL, true);
break;
default:
v4l2_ctrl_handler_init(>hdl, 0);
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c 
b/drivers/media/pci/bt8xx/bttv-driver.c
index de3f44b8dec68..9341ef6e154ff 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -4211,7 +4211,7 @@ static int bttv_probe(struct pci_dev *dev, const struct 
pci_device_id *pci_id)
/* register video4linux + input */
if (!bttv_tvcards[btv->c.type].no_video) {
v4l2_ctrl_add_handler(>radio_ctrl_handler, hdl,
-   v4l2_ctrl_radio_filter);
+   v4l2_ctrl_radio_filter, false);
if (btv->radio_ctrl_handler.error) {
result = btv->radio_ctrl_handler.error;
goto fail2;
diff --git a/drivers/media/pci/cx23885/cx23885-417.c 
b/drivers/media/pci/cx23885/cx23885-417.c
index a71f3c7569ce3..762823871c78a 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1527,7 +1527,7 @@ int cx23885_417_register(struct cx23885_dev *dev)
dev->cxhdl.priv = dev;
dev->cxhdl.func = cx23885_api_func;
cx2341x_handler_set_50hz(>cxhdl, tsport->height == 576);
-   v4l2_ctrl_add_handler(>ctrl_handler, >cxhdl.hdl, NULL);
+   v4l2_ctrl_add_handler(>ctrl_handler, >cxhdl.hdl, NULL, false);
 
/* Allocate and initialize V4L video device */
dev->v4l_device = cx23885_video_dev_alloc(tsport,
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c 
b/drivers/media/pci/cx88/cx88-blackbird.c
index 7a4876cf9f088..722dd101c9b06 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -1183,7 +1183,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver 
*drv)
err = cx2341x_handler_init(>cxhdl, 36);
if (err)
goto fail_core;
-   v4l2_ctrl_add_handler(>cxhdl.hdl, >video_hdl, NULL);
+   v4l2_ctrl_add_handler(>cxhdl.hdl, >video_hdl, NULL, false);
 
   

[PATCH v14 15/36] v4l2-ctrls: add core request support

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Integrate the request support. This adds the v4l2_ctrl_request_complete
and v4l2_ctrl_request_setup functions to complete a request and (as a
helper function) to apply a request to the hardware.

It takes care of queuing requests and correctly chaining control values
in the request queue.

Note that when a request is marked completed it will copy control values
to the internal request state. This can be optimized in the future since
this is sub-optimal when dealing with large compound and/or array controls.

For the initial 'stateless codec' use-case the current implementation is
sufficient.

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 331 ++-
 include/media/v4l2-ctrls.h   |  23 +++
 2 files changed, 348 insertions(+), 6 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index da4cc1485dc43..56b986185463d 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1647,6 +1647,13 @@ static int new_to_user(struct v4l2_ext_control *c,
return ptr_to_user(c, ctrl, ctrl->p_new);
 }
 
+/* Helper function: copy the request value back to the caller */
+static int req_to_user(struct v4l2_ext_control *c,
+  struct v4l2_ctrl_ref *ref)
+{
+   return ptr_to_user(c, ref->ctrl, ref->p_req);
+}
+
 /* Helper function: copy the initial control value back to the caller */
 static int def_to_user(struct v4l2_ext_control *c, struct v4l2_ctrl *ctrl)
 {
@@ -1766,6 +1773,26 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new);
 }
 
+/* Copy the new value to the request value */
+static void new_to_req(struct v4l2_ctrl_ref *ref)
+{
+   if (!ref)
+   return;
+   ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req);
+   ref->req = ref;
+}
+
+/* Copy the request value to the new value */
+static void req_to_new(struct v4l2_ctrl_ref *ref)
+{
+   if (!ref)
+   return;
+   if (ref->req)
+   ptr_to_ptr(ref->ctrl, ref->req->p_req, ref->ctrl->p_new);
+   else
+   ptr_to_ptr(ref->ctrl, ref->ctrl->p_cur, ref->ctrl->p_new);
+}
+
 /* Return non-zero if one or more of the controls in the cluster has a new
value that differs from the current value. */
 static int cluster_changed(struct v4l2_ctrl *master)
@@ -1875,6 +1902,9 @@ int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler 
*hdl,
lockdep_set_class_and_name(hdl->lock, key, name);
INIT_LIST_HEAD(>ctrls);
INIT_LIST_HEAD(>ctrl_refs);
+   INIT_LIST_HEAD(>requests);
+   INIT_LIST_HEAD(>requests_queued);
+   hdl->request_is_queued = false;
hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8;
hdl->buckets = kvmalloc_array(hdl->nr_of_buckets,
  sizeof(hdl->buckets[0]),
@@ -1895,6 +1925,14 @@ void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler 
*hdl)
if (hdl == NULL || hdl->buckets == NULL)
return;
 
+   if (!hdl->req_obj.req && !list_empty(>requests)) {
+   struct v4l2_ctrl_handler *req, *next_req;
+
+   list_for_each_entry_safe(req, next_req, >requests, 
requests) {
+   media_request_object_unbind(>req_obj);
+   media_request_object_put(>req_obj);
+   }
+   }
mutex_lock(hdl->lock);
/* Free all nodes */
list_for_each_entry_safe(ref, next_ref, >ctrl_refs, node) {
@@ -2816,6 +2854,128 @@ int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, 
struct v4l2_querymenu *qm)
 }
 EXPORT_SYMBOL(v4l2_querymenu);
 
+static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl,
+  const struct v4l2_ctrl_handler *from)
+{
+   struct v4l2_ctrl_ref *ref;
+   int err;
+
+   if (WARN_ON(!hdl || hdl == from))
+   return -EINVAL;
+
+   if (hdl->error)
+   return hdl->error;
+
+   WARN_ON(hdl->lock != >_lock);
+
+   mutex_lock(from->lock);
+   list_for_each_entry(ref, >ctrl_refs, node) {
+   struct v4l2_ctrl *ctrl = ref->ctrl;
+   struct v4l2_ctrl_ref *new_ref;
+
+   /* Skip refs inherited from other devices */
+   if (ref->from_other_dev)
+   continue;
+   /* And buttons */
+   if (ctrl->type == V4L2_CTRL_TYPE_BUTTON)
+   continue;
+   err = handler_new_ref(hdl, ctrl, _ref, false, true);
+   if (err) {
+   printk("%s: handler_new_ref on control %x (%s) returned 
%d\n", __func__, ctrl->id, ctrl->name, err);
+   err = 0;
+   continue;
+   }
+   if (err)
+   break;
+   }
+   mutex_unlock(from->lock);
+ 

[PATCH v14 22/36] videobuf2-core: integrate with media requests

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Buffers can now be prepared or queued for a request.

A buffer is unbound from the request at vb2_buffer_done time or
when the queue is cancelled.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 124 ++--
 drivers/media/common/videobuf2/videobuf2-v4l2.c |   4 +-
 drivers/media/dvb-core/dvb_vb2.c|   2 +-
 include/media/videobuf2-core.h  |  18 +++-
 4 files changed, 135 insertions(+), 13 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 70ba43c5b3e28..4064fa15bc409 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -497,8 +497,9 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned 
int buffers)
pr_info(" buf_init: %u buf_cleanup: %u buf_prepare: 
%u buf_finish: %u\n",
vb->cnt_buf_init, vb->cnt_buf_cleanup,
vb->cnt_buf_prepare, vb->cnt_buf_finish);
-   pr_info(" buf_queue: %u buf_done: %u\n",
-   vb->cnt_buf_queue, vb->cnt_buf_done);
+   pr_info(" buf_queue: %u buf_done: %u 
buf_request_complete: %u\n",
+   vb->cnt_buf_queue, vb->cnt_buf_done,
+   vb->cnt_buf_request_complete);
pr_info(" alloc: %u put: %u prepare: %u finish: %u 
mmap: %u\n",
vb->cnt_mem_alloc, vb->cnt_mem_put,
vb->cnt_mem_prepare, vb->cnt_mem_finish,
@@ -930,6 +931,14 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum 
vb2_buffer_state state)
vb->state = state;
}
atomic_dec(>owned_by_drv_count);
+
+   if (vb->req_obj.req) {
+   /* This is not supported at the moment */
+   WARN_ON(state == VB2_BUF_STATE_REQUEUEING);
+   media_request_object_unbind(>req_obj);
+   media_request_object_put(>req_obj);
+   }
+
spin_unlock_irqrestore(>done_lock, flags);
 
trace_vb2_buf_done(q, vb);
@@ -1236,6 +1245,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
 static int __buf_prepare(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
+   enum vb2_buffer_state orig_state = vb->state;
unsigned int plane;
int ret;
 
@@ -1263,7 +1273,7 @@ static int __buf_prepare(struct vb2_buffer *vb)
 
if (ret) {
dprintk(1, "buffer preparation failed: %d\n", ret);
-   vb->state = VB2_BUF_STATE_DEQUEUED;
+   vb->state = orig_state;
return ret;
}
 
@@ -1276,6 +1286,60 @@ static int __buf_prepare(struct vb2_buffer *vb)
return 0;
 }
 
+static int vb2_req_prepare(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+   int ret;
+
+   if (WARN_ON(vb->state != VB2_BUF_STATE_IN_REQUEST))
+   return -EINVAL;
+
+   mutex_lock(vb->vb2_queue->lock);
+   ret = __buf_prepare(vb);
+   mutex_unlock(vb->vb2_queue->lock);
+   return ret;
+}
+
+static void __vb2_dqbuf(struct vb2_buffer *vb);
+
+static void vb2_req_unprepare(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+
+   mutex_lock(vb->vb2_queue->lock);
+   __vb2_dqbuf(vb);
+   vb->state = VB2_BUF_STATE_IN_REQUEST;
+   mutex_unlock(vb->vb2_queue->lock);
+   WARN_ON(!vb->req_obj.req);
+}
+
+int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb,
+ struct media_request *req);
+
+static void vb2_req_queue(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+
+   mutex_lock(vb->vb2_queue->lock);
+   vb2_core_qbuf(vb->vb2_queue, vb->index, NULL, NULL);
+   mutex_unlock(vb->vb2_queue->lock);
+}
+
+static void vb2_req_release(struct media_request_object *obj)
+{
+   struct vb2_buffer *vb = container_of(obj, struct vb2_buffer, req_obj);
+
+   if (vb->state == VB2_BUF_STATE_IN_REQUEST)
+   vb->state = VB2_BUF_STATE_DEQUEUED;
+}
+
+static const struct media_request_object_ops vb2_core_req_ops = {
+   .prepare = vb2_req_prepare,
+   .unprepare = vb2_req_unprepare,
+   .queue = vb2_req_queue,
+   .release = vb2_req_release,
+};
+
 int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb)
 {
struct vb2_buffer *vb;
@@ -1297,7 +1361,7 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned 
int index, void *pb)
 
dprintk(2, "prepare of buffer %d succeeded\n", vb->index);
 
-   return ret;
+   return 0;
 }
 

[PATCH v14 21/36] videobuf2-core: embed media_request_object

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Make vb2_buffer a request object.

Signed-off-by: Hans Verkuil 
---
 include/media/videobuf2-core.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 224c4820a0443..3d54654c3cd48 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define VB2_MAX_FRAME  (32)
 #define VB2_MAX_PLANES (8)
@@ -238,6 +239,7 @@ struct vb2_queue;
  * @num_planes:number of planes in the buffer
  * on an internal driver queue.
  * @timestamp: frame timestamp in ns.
+ * @req_obj:   used to bind this buffer to a request
  */
 struct vb2_buffer {
struct vb2_queue*vb2_queue;
@@ -246,6 +248,7 @@ struct vb2_buffer {
unsigned intmemory;
unsigned intnum_planes;
u64 timestamp;
+   struct media_request_object req_obj;
 
/* private: internal use only
 *
-- 
2.11.0



[PATCH v14 18/36] v4l2-ctrls: Lock the request for updating during S_EXT_CTRLS

2018-05-21 Thread Sakari Ailus
Instead of checking the media request state is idle at one point, lock the
request for updating during the S_EXT_CTRLS call. As a by-product, finding
the request has been moved out of the v4l2_ctrls_find_req_obj() in order
to keep request object lookups to the minimum.

Signed-off-by: Sakari Ailus 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 67 +---
 1 file changed, 40 insertions(+), 27 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index df58a23eb731a..1a99d6e238791 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -3208,9 +3208,8 @@ int __v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl,
 
 static struct media_request_object *
 v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl,
-   struct media_device *mdev, s32 fd, bool set)
+   struct media_request *req, bool set)
 {
-   struct media_request *req = media_request_get_by_fd(mdev, fd);
struct media_request_object *obj;
struct v4l2_ctrl_handler *new_hdl;
int ret;
@@ -3218,36 +3217,29 @@ v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl,
if (IS_ERR(req))
return ERR_CAST(req);
 
-   if (set && atomic_read(>state) != MEDIA_REQUEST_STATE_IDLE) {
-   media_request_put(req);
+   if (set && WARN_ON(req->state != MEDIA_REQUEST_STATE_UPDATING))
return ERR_PTR(-EBUSY);
-   }
 
obj = media_request_object_find(req, _ops, hdl);
-   if (obj) {
-   media_request_put(req);
+   if (obj)
return obj;
-   }
 
new_hdl = kzalloc(sizeof(*new_hdl), GFP_KERNEL);
-   if (!new_hdl) {
-   ret = -ENOMEM;
-   goto put;
-   }
+   if (!new_hdl)
+   return ERR_PTR(-ENOMEM);
+
obj = _hdl->req_obj;
ret = v4l2_ctrl_handler_init(new_hdl, (hdl->nr_of_buckets - 1) * 8);
if (!ret)
ret = v4l2_ctrl_request_bind(req, new_hdl, hdl);
-   if (!ret) {
-   media_request_object_get(obj);
-   media_request_put(req);
-   return obj;
+   if (ret) {
+   kfree(new_hdl);
+
+   return ERR_PTR(ret);
}
-   kfree(new_hdl);
 
-put:
-   media_request_put(req);
-   return ERR_PTR(ret);
+   media_request_object_get(obj);
+   return obj;
 }
 
 int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct media_device *mdev,
@@ -3257,11 +3249,21 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, 
struct media_device *mdev,
int ret;
 
if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) {
+   struct media_request *req;
+
if (!mdev || cs->request_fd < 0)
return -EINVAL;
-   obj = v4l2_ctrls_find_req_obj(hdl, mdev, cs->request_fd, false);
+
+   req = media_request_get_by_fd(mdev, cs->request_fd);
+   if (!req)
+   return -ENOENT;
+
+   obj = v4l2_ctrls_find_req_obj(hdl, req, false);
+   /* Reference to the request held through obj */
+   media_request_put(req);
if (IS_ERR(obj))
return PTR_ERR(obj);
+
hdl = container_of(obj, struct v4l2_ctrl_handler,
   req_obj);
}
@@ -3567,18 +3569,28 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh,
 struct v4l2_ext_controls *cs, bool set)
 {
struct media_request_object *obj = NULL;
+   struct media_request *req = NULL;
int ret;
 
if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) {
if (!mdev || cs->request_fd < 0)
return -EINVAL;
-   obj = v4l2_ctrls_find_req_obj(hdl, mdev, cs->request_fd, true);
+
+   req = media_request_get_by_fd(mdev, cs->request_fd);
+   if (!req)
+   return -ENOENT;
+
+   ret = media_request_lock_for_update(req);
+   if (req) {
+   media_request_put(req);
+   return ret;
+   }
+
+   obj = v4l2_ctrls_find_req_obj(hdl, req, true);
+   /* Reference to the request held through obj */
+   media_request_object_put(obj);
if (IS_ERR(obj))
return PTR_ERR(obj);
-   if (atomic_read(>req->state) != MEDIA_REQUEST_STATE_IDLE) {
-   media_request_object_put(obj);
-   return -EBUSY;
-   }
hdl = container_of(obj, struct v4l2_ctrl_handler,
   req_obj);
}
@@ -3586,7 +3598,8 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh,
ret = __try_set_ext_ctrls(fh, hdl, cs, set);
 
if 

[PATCH v14 13/36] v4l2-ctrls: alloc memory for p_req

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

To store request data the handler_new_ref() allocates memory
for it if needed.

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index d09f49530d9e8..3c1b00baa8d04 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1997,13 +1997,18 @@ EXPORT_SYMBOL(v4l2_ctrl_find);
 /* Allocate a new v4l2_ctrl_ref and hook it into the handler. */
 static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
   struct v4l2_ctrl *ctrl,
-  bool from_other_dev)
+  struct v4l2_ctrl_ref **ctrl_ref,
+  bool from_other_dev, bool allocate_req)
 {
struct v4l2_ctrl_ref *ref;
struct v4l2_ctrl_ref *new_ref;
u32 id = ctrl->id;
u32 class_ctrl = V4L2_CTRL_ID2WHICH(id) | 1;
int bucket = id % hdl->nr_of_buckets;   /* which bucket to use */
+   unsigned int sz_extra = 0;
+
+   if (ctrl_ref)
+   *ctrl_ref = NULL;
 
/*
 * Automatically add the control class if it is not yet present and
@@ -2017,11 +2022,16 @@ static int handler_new_ref(struct v4l2_ctrl_handler 
*hdl,
if (hdl->error)
return hdl->error;
 
-   new_ref = kzalloc(sizeof(*new_ref), GFP_KERNEL);
+   if (allocate_req)
+   sz_extra = ctrl->elems * ctrl->elem_size;
+   new_ref = kzalloc(sizeof(*new_ref) + sz_extra, GFP_KERNEL);
if (!new_ref)
return handler_set_err(hdl, -ENOMEM);
new_ref->ctrl = ctrl;
new_ref->from_other_dev = from_other_dev;
+   if (sz_extra)
+   new_ref->p_req.p = _ref[1];
+
if (ctrl->handler == hdl) {
/* By default each control starts in a cluster of its own.
   new_ref->ctrl is basically a cluster array with one
@@ -2061,6 +2071,8 @@ static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
/* Insert the control node in the hash */
new_ref->next = hdl->buckets[bucket];
hdl->buckets[bucket] = new_ref;
+   if (ctrl_ref)
+   *ctrl_ref = new_ref;
 
 unlock:
mutex_unlock(hdl->lock);
@@ -2202,7 +2214,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct 
v4l2_ctrl_handler *hdl,
ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
}
 
-   if (handler_new_ref(hdl, ctrl, false)) {
+   if (handler_new_ref(hdl, ctrl, NULL, false, false)) {
kvfree(ctrl);
return NULL;
}
@@ -2395,7 +2407,7 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
/* Filter any unwanted controls */
if (filter && !filter(ctrl))
continue;
-   ret = handler_new_ref(hdl, ctrl, from_other_dev);
+   ret = handler_new_ref(hdl, ctrl, NULL, from_other_dev, false);
if (ret)
break;
}
-- 
2.11.0



[PATCH v14 14/36] v4l2-ctrls: use ref in helper instead of ctrl

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

The next patch needs the reference to a control instead of the
control itself, so change struct v4l2_ctrl_helper accordingly.

Signed-off-by: Hans Verkuil 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index 3c1b00baa8d04..da4cc1485dc43 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -37,8 +37,8 @@
 struct v4l2_ctrl_helper {
/* Pointer to the control reference of the master control */
struct v4l2_ctrl_ref *mref;
-   /* The control corresponding to the v4l2_ext_control ID field. */
-   struct v4l2_ctrl *ctrl;
+   /* The control ref corresponding to the v4l2_ext_control ID field. */
+   struct v4l2_ctrl_ref *ref;
/* v4l2_ext_control index of the next control belonging to the
   same cluster, or 0 if there isn't any. */
u32 next;
@@ -2887,6 +2887,7 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler 
*hdl,
ref = find_ref_lock(hdl, id);
if (ref == NULL)
return -EINVAL;
+   h->ref = ref;
ctrl = ref->ctrl;
if (ctrl->flags & V4L2_CTRL_FLAG_DISABLED)
return -EINVAL;
@@ -2909,7 +2910,6 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler 
*hdl,
}
/* Store the ref to the master control of the cluster */
h->mref = ref;
-   h->ctrl = ctrl;
/* Initially set next to 0, meaning that there is no other
   control in this helper array belonging to the same
   cluster */
@@ -2994,7 +2994,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, 
struct v4l2_ext_controls *cs
cs->error_idx = cs->count;
 
for (i = 0; !ret && i < cs->count; i++)
-   if (helpers[i].ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
+   if (helpers[i].ref->ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
ret = -EACCES;
 
for (i = 0; !ret && i < cs->count; i++) {
@@ -3029,7 +3029,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, 
struct v4l2_ext_controls *cs
 
do {
ret = ctrl_to_user(cs->controls + idx,
-  helpers[idx].ctrl);
+  helpers[idx].ref->ctrl);
idx = helpers[idx].next;
} while (!ret && idx);
}
@@ -3168,7 +3168,7 @@ static int validate_ctrls(struct v4l2_ext_controls *cs,
 
cs->error_idx = cs->count;
for (i = 0; i < cs->count; i++) {
-   struct v4l2_ctrl *ctrl = helpers[i].ctrl;
+   struct v4l2_ctrl *ctrl = helpers[i].ref->ctrl;
union v4l2_ctrl_ptr p_new;
 
cs->error_idx = i;
@@ -3280,7 +3280,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct 
v4l2_ctrl_handler *hdl,
do {
/* Check if the auto control is part of the
   list, and remember the new value. */
-   if (helpers[tmp_idx].ctrl == master)
+   if (helpers[tmp_idx].ref->ctrl == master)
new_auto_val = 
cs->controls[tmp_idx].value;
tmp_idx = helpers[tmp_idx].next;
} while (tmp_idx);
@@ -3293,7 +3293,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct 
v4l2_ctrl_handler *hdl,
/* Copy the new caller-supplied control values.
   user_to_new() sets 'is_new' to 1. */
do {
-   struct v4l2_ctrl *ctrl = helpers[idx].ctrl;
+   struct v4l2_ctrl *ctrl = helpers[idx].ref->ctrl;
 
ret = user_to_new(cs->controls + idx, ctrl);
if (!ret && ctrl->is_ptr)
@@ -3309,7 +3309,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct 
v4l2_ctrl_handler *hdl,
idx = i;
do {
ret = new_to_user(cs->controls + idx,
-   helpers[idx].ctrl);
+   helpers[idx].ref->ctrl);
idx = helpers[idx].next;
} while (!ret && idx);
}
-- 
2.11.0



[PATCH v14 12/36] v4l2-ctrls: prepare internal structs for request API

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Embed and initialize a media_request_object in struct v4l2_ctrl_handler.

Add a p_req field to struct v4l2_ctrl_ref that will store the
request value.

Signed-off-by: Hans Verkuil 
Signed-off-by: Alexandre Courbot 
---
 drivers/media/v4l2-core/v4l2-ctrls.c | 1 +
 include/media/v4l2-ctrls.h   | 7 +++
 2 files changed, 8 insertions(+)

diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index aa1dd2015e84b..d09f49530d9e8 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1880,6 +1880,7 @@ int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler 
*hdl,
  sizeof(hdl->buckets[0]),
  GFP_KERNEL | __GFP_ZERO);
hdl->error = hdl->buckets ? 0 : -ENOMEM;
+   media_request_object_init(>req_obj);
return hdl->error;
 }
 EXPORT_SYMBOL(v4l2_ctrl_handler_init_class);
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index d26b8ddebb560..76352eb59f14a 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* forward references */
 struct file;
@@ -249,6 +250,8 @@ struct v4l2_ctrl {
  * ``prepare_ext_ctrls`` function at ``v4l2-ctrl.c``.
  * @from_other_dev: If true, then @ctrl was defined in another
  * device than the  v4l2_ctrl_handler.
+ * @p_req: The request value. Only used if the control handler
+ * is bound to a media request.
  *
  * Each control handler has a list of these refs. The list_head is used to
  * keep a sorted-by-control-ID list of all controls, while the next pointer
@@ -260,6 +263,7 @@ struct v4l2_ctrl_ref {
struct v4l2_ctrl *ctrl;
struct v4l2_ctrl_helper *helper;
bool from_other_dev;
+   union v4l2_ctrl_ptr p_req;
 };
 
 /**
@@ -283,6 +287,8 @@ struct v4l2_ctrl_ref {
  * @notify_priv: Passed as argument to the v4l2_ctrl notify callback.
  * @nr_of_buckets: Total number of buckets in the array.
  * @error: The error code of the first failed control addition.
+ * @req_obj:   The  media_request_object, used to link into a
+ *  media_request.
  */
 struct v4l2_ctrl_handler {
struct mutex _lock;
@@ -295,6 +301,7 @@ struct v4l2_ctrl_handler {
void *notify_priv;
u16 nr_of_buckets;
int error;
+   struct media_request_object req_obj;
 };
 
 /**
-- 
2.11.0



[PATCH v14 20/36] vb2: store userspace data in vb2_v4l2_buffer

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

The userspace-provided plane data needs to be stored in
vb2_v4l2_buffer. Currently this information is applied by
__fill_vb2_buffer() which is called by the core prepare_buf
and qbuf functions, but when using requests these functions
aren't called yet since the buffer won't be prepared until
the media request is actually queued.

In the meantime this information has to be stored somewhere
and vb2_v4l2_buffer is a good place for it.

The __fill_vb2_buffer callback now just copies the relevant
information from vb2_v4l2_buffer into the planes array.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-core.c |  43 ++--
 drivers/media/common/videobuf2/videobuf2-v4l2.c | 324 +---
 drivers/media/dvb-core/dvb_vb2.c|   3 +-
 include/media/videobuf2-core.h  |   3 +-
 include/media/videobuf2-v4l2.h  |   2 +
 5 files changed, 206 insertions(+), 169 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index d3f7bb33a54dd..70ba43c5b3e28 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -964,20 +964,19 @@ EXPORT_SYMBOL_GPL(vb2_discard_done);
 /*
  * __prepare_mmap() - prepare an MMAP buffer
  */
-static int __prepare_mmap(struct vb2_buffer *vb, const void *pb)
+static int __prepare_mmap(struct vb2_buffer *vb)
 {
int ret = 0;
 
-   if (pb)
-   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
-vb, pb, vb->planes);
+   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
+vb, vb->planes);
return ret ? ret : call_vb_qop(vb, buf_prepare, vb);
 }
 
 /*
  * __prepare_userptr() - prepare a USERPTR buffer
  */
-static int __prepare_userptr(struct vb2_buffer *vb, const void *pb)
+static int __prepare_userptr(struct vb2_buffer *vb)
 {
struct vb2_plane planes[VB2_MAX_PLANES];
struct vb2_queue *q = vb->vb2_queue;
@@ -988,12 +987,10 @@ static int __prepare_userptr(struct vb2_buffer *vb, const 
void *pb)
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
/* Copy relevant information provided by the userspace */
-   if (pb) {
-   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
-vb, pb, planes);
-   if (ret)
-   return ret;
-   }
+   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
+vb, planes);
+   if (ret)
+   return ret;
 
for (plane = 0; plane < vb->num_planes; ++plane) {
/* Skip the plane if already verified */
@@ -1093,7 +1090,7 @@ static int __prepare_userptr(struct vb2_buffer *vb, const 
void *pb)
 /*
  * __prepare_dmabuf() - prepare a DMABUF buffer
  */
-static int __prepare_dmabuf(struct vb2_buffer *vb, const void *pb)
+static int __prepare_dmabuf(struct vb2_buffer *vb)
 {
struct vb2_plane planes[VB2_MAX_PLANES];
struct vb2_queue *q = vb->vb2_queue;
@@ -1104,12 +1101,10 @@ static int __prepare_dmabuf(struct vb2_buffer *vb, 
const void *pb)
 
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
/* Copy relevant information provided by the userspace */
-   if (pb) {
-   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
-vb, pb, planes);
-   if (ret)
-   return ret;
-   }
+   ret = call_bufop(vb->vb2_queue, fill_vb2_buffer,
+vb, planes);
+   if (ret)
+   return ret;
 
for (plane = 0; plane < vb->num_planes; ++plane) {
struct dma_buf *dbuf = dma_buf_get(planes[plane].m.fd);
@@ -1238,7 +1233,7 @@ static void __enqueue_in_driver(struct vb2_buffer *vb)
call_void_vb_qop(vb, buf_queue, vb);
 }
 
-static int __buf_prepare(struct vb2_buffer *vb, const void *pb)
+static int __buf_prepare(struct vb2_buffer *vb)
 {
struct vb2_queue *q = vb->vb2_queue;
unsigned int plane;
@@ -1253,13 +1248,13 @@ static int __buf_prepare(struct vb2_buffer *vb, const 
void *pb)
 
switch (q->memory) {
case VB2_MEMORY_MMAP:
-   ret = __prepare_mmap(vb, pb);
+   ret = __prepare_mmap(vb);
break;
case VB2_MEMORY_USERPTR:
-   ret = __prepare_userptr(vb, pb);
+   ret = __prepare_userptr(vb);
break;
case VB2_MEMORY_DMABUF:
-   ret = __prepare_dmabuf(vb, pb);
+   ret = __prepare_dmabuf(vb);
break;
default:
WARN(1, "Invalid queue type\n");
@@ -1293,7 +1288,7 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned 
int index, void *pb)
return -EINVAL;
}
 
-   ret = __buf_prepare(vb, pb);
+  

[PATCH v14 06/36] media-request: Add support for updating request objects optimally

2018-05-21 Thread Sakari Ailus
Add a new request state (UPDATING) as well as a count for updating the
request objects. This way, several updates may take place simultaneously
without affecting each other. The drivers (as well as frameworks) still
must serialise access to their own data structures; what is guaranteed by
the new state is simply correct and optimal handling of requests.

Signed-off-by: Sakari Ailus 
---
 drivers/media/media-request.c |  3 ++-
 include/media/media-request.h | 53 +++
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index a1576cf528605..03e74d72241a0 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -22,6 +22,7 @@ static const char * const request_state[] = {
[MEDIA_REQUEST_STATE_QUEUED] = "queued",
[MEDIA_REQUEST_STATE_COMPLETE]   = "complete",
[MEDIA_REQUEST_STATE_CLEANING]   = "cleaning",
+   [MEDIA_REQUEST_STATE_UPDATING]   = "updating",
 };
 
 static const char *
@@ -385,7 +386,7 @@ int media_request_object_bind(struct media_request *req,
 
spin_lock_irqsave(>lock, flags);
 
-   if (WARN_ON(req->state != MEDIA_REQUEST_STATE_IDLE))
+   if (WARN_ON(req->state != MEDIA_REQUEST_STATE_UPDATING))
goto unlock;
 
list_add_tail(>list, >objects);
diff --git a/include/media/media-request.h b/include/media/media-request.h
index e175538d3c669..42cc6e7f6e532 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -28,6 +28,9 @@
  * @MEDIA_REQUEST_STATE_QUEUED:Queued
  * @MEDIA_REQUEST_STATE_COMPLETE:  Completed, the request is done
  * @MEDIA_REQUEST_STATE_CLEANING:  Cleaning, the request is being re-inited
+ * @MEDIA_REQUEST_STATE_UPDATING:  The request is being updated, i.e.
+ * request objects are being added,
+ * modified or removed
  */
 enum media_request_state {
MEDIA_REQUEST_STATE_IDLE,
@@ -35,6 +38,7 @@ enum media_request_state {
MEDIA_REQUEST_STATE_QUEUED,
MEDIA_REQUEST_STATE_COMPLETE,
MEDIA_REQUEST_STATE_CLEANING,
+   MEDIA_REQUEST_STATE_UPDATING,
 };
 
 struct media_request_object;
@@ -56,6 +60,7 @@ struct media_request {
struct kref kref;
char debug_str[TASK_COMM_LEN + 11];
enum media_request_state state;
+   refcount_t updating_count;
struct list_head objects;
unsigned int num_incomplete_objects;
struct wait_queue_head poll_wait;
@@ -65,6 +70,54 @@ struct media_request {
 #ifdef CONFIG_MEDIA_CONTROLLER
 
 /**
+ * media_request_lock_for_update - Lock the request for updating its objects
+ *
+ * @req: The media request
+ *
+ * Use before updating a request, i.e. adding, modifying or removing a request
+ * object in it. A reference to the request must be held during the update. 
This
+ * usually takes place automatically through a file handle. Use
+ * @media_request_unlock_for_update when done.
+ */
+static inline int __must_check
+media_request_lock_for_update(struct media_request *req)
+{
+   unsigned long flags;
+   int ret = 0;
+
+   spin_lock_irqsave(>lock, flags);
+   if (req->state == MEDIA_REQUEST_STATE_IDLE ||
+   req->state == MEDIA_REQUEST_STATE_UPDATING) {
+   req->state = MEDIA_REQUEST_STATE_UPDATING;
+   refcount_inc(>updating_count);
+   } else {
+   ret = -EBUSY;
+   }
+   spin_unlock_irqrestore(>lock, flags);
+
+   return ret;
+}
+
+/**
+ * media_request_unlock_for_update - Unlock a request previously locked for
+ *  update
+ *
+ * @req: The media request
+ *
+ * Unlock a request that has previously been locked using
+ * @media_request_lock_for_update.
+ */
+static inline void media_request_unlock_for_update(struct media_request *req)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(>lock, flags);
+   if (refcount_dec_and_test(>updating_count))
+   req->state = MEDIA_REQUEST_STATE_IDLE;
+   spin_unlock_irqrestore(>lock, flags);
+}
+
+/**
  * media_request_get - Get the media request
  *
  * @req: The request
-- 
2.11.0



[PATCH v14 09/36] v4l2-dev: lock req_queue_mutex

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

We need to serialize streamon/off with queueing new requests.
These ioctls may trigger the cancellation of a streaming
operation, and that should not be mixed with queuing a new
request at the same time.

Finally close() needs this lock since that too can trigger the
cancellation of a streaming operation.

We take the req_queue_mutex here before any other locks since
it is a very high-level lock.

[Sakari Ailus: No longer acquire req_queue_mutex for controls]

Signed-off-by: Hans Verkuil 
Signed-off-by: Sakari Ailus 
---
 drivers/media/v4l2-core/v4l2-dev.c | 36 +++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/media/v4l2-core/v4l2-dev.c 
b/drivers/media/v4l2-core/v4l2-dev.c
index c4f4357e9ca41..8d4b55ac00f94 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -361,13 +361,35 @@ static long v4l2_ioctl(struct file *filp, unsigned int 
cmd, unsigned long arg)
 
if (vdev->fops->unlocked_ioctl) {
struct mutex *lock = v4l2_ioctl_get_lock(vdev, cmd);
+   struct mutex *queue_lock = NULL;
 
-   if (lock && mutex_lock_interruptible(lock))
+   /*
+* We need to serialize streamon/off with queueing new requests.
+* These ioctls may trigger the cancellation of a streaming
+* operation, and that should not be mixed with queueing a new
+* request at the same time.
+*
+* Also TRY/S_EXT_CTRLS needs this lock to correctly serialize
+* with MEDIA_REQUEST_IOC_QUEUE.
+*/
+   if (vdev->v4l2_dev->mdev &&
+   (cmd == VIDIOC_STREAMON || cmd == VIDIOC_STREAMOFF))
+   queue_lock = >v4l2_dev->mdev->req_queue_mutex;
+
+   if (queue_lock && mutex_lock_interruptible(queue_lock))
+   return -ERESTARTSYS;
+
+   if (lock && mutex_lock_interruptible(lock)) {
+   if (queue_lock)
+   mutex_unlock(queue_lock);
return -ERESTARTSYS;
+   }
if (video_is_registered(vdev))
ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
if (lock)
mutex_unlock(lock);
+   if (queue_lock)
+   mutex_unlock(queue_lock);
} else
ret = -ENOTTY;
 
@@ -450,8 +472,20 @@ static int v4l2_release(struct inode *inode, struct file 
*filp)
struct video_device *vdev = video_devdata(filp);
int ret = 0;
 
+   /*
+* We need to serialize the release() with queueing new requests.
+* The release() may trigger the cancellation of a streaming
+* operation, and that should not be mixed with queueing a new
+* request at the same time.
+*/
+   if (vdev->v4l2_dev->mdev)
+   mutex_lock(>v4l2_dev->mdev->req_queue_mutex);
+
if (vdev->fops->release)
ret = vdev->fops->release(filp);
+
+   if (vdev->v4l2_dev->mdev)
+   mutex_unlock(>v4l2_dev->mdev->req_queue_mutex);
if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP)
dprintk("%s: release\n",
video_device_node_name(vdev));
-- 
2.11.0



[PATCH v14 04/36] media-request: add media_request_object_find

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Add media_request_object_find to find a request object inside a
request based on ops and/or priv values.

Objects of the same type (vb2 buffer, control handler) will have
the same ops value. And objects that refer to the same 'parent'
object (e.g. the v4l2_ctrl_handler that has the current driver
state) will have the same priv value.

The caller has to call media_request_object_put() for the returned
object since this function increments the refcount.

Signed-off-by: Hans Verkuil 
---
 drivers/media/media-request.c | 25 +
 include/media/media-request.h | 24 
 2 files changed, 49 insertions(+)

diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index edc1c3af1959c..c7e11e816e272 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -322,6 +322,31 @@ static void media_request_object_release(struct kref *kref)
obj->ops->release(obj);
 }
 
+struct media_request_object *
+media_request_object_find(struct media_request *req,
+ const struct media_request_object_ops *ops,
+ void *priv)
+{
+   struct media_request_object *obj;
+   struct media_request_object *found = NULL;
+   unsigned long flags;
+
+   if (WARN_ON(!ops || !priv))
+   return NULL;
+
+   spin_lock_irqsave(>lock, flags);
+   list_for_each_entry(obj, >objects, list) {
+   if (obj->ops == ops && obj->priv == priv) {
+   media_request_object_get(obj);
+   found = obj;
+   break;
+   }
+   }
+   spin_unlock_irqrestore(>lock, flags);
+   return found;
+}
+EXPORT_SYMBOL_GPL(media_request_object_find);
+
 void media_request_object_put(struct media_request_object *obj)
 {
kref_put(>kref, media_request_object_release);
diff --git a/include/media/media-request.h b/include/media/media-request.h
index 997e096d7128d..5367b4a2f91ca 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -197,6 +197,22 @@ static inline void media_request_object_get(struct 
media_request_object *obj)
 void media_request_object_put(struct media_request_object *obj);
 
 /**
+ * media_request_object_find - Find an object in a request
+ *
+ * @ops: Find an object with this ops value
+ * @priv: Find an object with this priv value
+ *
+ * Both @ops and @priv must be non-NULL.
+ *
+ * Returns NULL if not found or the object pointer. The caller must
+ * call media_request_object_put() once it finished using the object.
+ */
+struct media_request_object *
+media_request_object_find(struct media_request *req,
+ const struct media_request_object_ops *ops,
+ void *priv);
+
+/**
  * media_request_object_init - Initialise a media request object
  *
  * Initialise a media request object. The object will be released using the
@@ -241,6 +257,14 @@ static inline void media_request_object_put(struct 
media_request_object *obj)
 {
 }
 
+static inline struct media_request_object *
+media_request_object_find(struct media_request *req,
+ const struct media_request_object_ops *ops,
+ void *priv)
+{
+   return NULL;
+}
+
 static inline void media_request_object_init(struct media_request_object *obj)
 {
obj->ops = NULL;
-- 
2.11.0



[PATCH v14 25/36] videobuf2-core: Make request state an enum

2018-05-21 Thread Sakari Ailus
Grab the request spinlock to access media request state

Signed-off-by: Sakari Ailus 
---
 drivers/media/common/videobuf2/videobuf2-core.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-core.c 
b/drivers/media/common/videobuf2/videobuf2-core.c
index 4064fa15bc409..4eebbed67c657 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -1784,6 +1784,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 */
for (i = 0; i < q->num_buffers; ++i) {
struct vb2_buffer *vb = q->bufs[i];
+   struct media_request *req = vb->req_obj.req;
 
/*
 * If a request is associated with this buffer, then
@@ -1791,10 +1792,17 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
 * related request objects. Otherwise those objects would
 * never complete.
 */
-   if (vb->req_obj.req &&
-   atomic_read(>req_obj.req->state) ==
-   MEDIA_REQUEST_STATE_QUEUED)
-   call_void_vb_qop(vb, buf_request_complete, vb);
+   if (req) {
+   enum media_request_state state;
+   unsigned long flags;
+
+   spin_lock_irqsave(>lock, flags);
+   state = req->state;
+   spin_unlock_irqrestore(>lock, flags);
+
+   if (state == MEDIA_REQUEST_STATE_QUEUED)
+   call_void_vb_qop(vb, buf_request_complete, vb);
+   }
 
if (vb->state == VB2_BUF_STATE_PREPARED ||
vb->state == VB2_BUF_STATE_QUEUED) {
-- 
2.11.0



[PATCH v14 00/36] Request API

2018-05-21 Thread Sakari Ailus
Hello everyone,

Here are my changes over v13 set Hans posted earlier. The changes since
v13 include:

- Request state is made enum again. This change was motivated by
  complicated locking scheme in which it was not obvious which locks would
  need to be acquired and when. In some cases the atomic operation may be
  replaced by a regular read operation.

- Add a new "updating" state to tell the request is being updated. The request
  state is changes to this state when its controls are being set, or a
  video buffer is being associated with it. There's update count, so
  multiple updates may take place simultaneously. This also means that the
  drivers may not use this mechanism to serialise access to their own data
  structures.

- Document v4l2_ctrl_request_setup and v4l2_ctrl_request_queue.

- Add media-request.h to Media documentation build.

Hans: Some patches are intended to be merged to the patches they precede.
I didn't do that since I thought they'd be more easily reviewed
separately. I've also changed the patch "v4l2-dev: lock req_queue_mutex" a
little, as described above.

In order to protect applying the requests (controls in particular),
setting the control value from user space need to be prevented if there
are requests pending for that video device. This is missing from the set.

I've also provided further comments on v13 on the list and I believe
others have given comments, too, so this isn't meant to be a set that
could be merged yet.

Hans's v13 and this set, both based on a recent media tree master, may be
found here:





Alexandre Courbot (2):
  videodev2.h: add request_fd field to v4l2_ext_controls
  Documentation: v4l: document request API

Hans Verkuil (25):
  uapi/linux/media.h: add request API
  media-request: implement media requests
  media-request: add media_request_get_by_fd
  media-request: add media_request_object_find
  v4l2-dev: lock req_queue_mutex
  v4l2-ctrls: v4l2_ctrl_add_handler: add from_other_dev
  v4l2-ctrls: prepare internal structs for request API
  v4l2-ctrls: alloc memory for p_req
  v4l2-ctrls: use ref in helper instead of ctrl
  v4l2-ctrls: add core request support
  v4l2-ctrls: support g/s_ext_ctrls for requests
  videodev2.h: Add request_fd field to v4l2_buffer
  vb2: store userspace data in vb2_v4l2_buffer
  videobuf2-core: embed media_request_object
  videobuf2-core: integrate with media requests
  videobuf2-v4l2: integrate with media requests
  videobuf2-core: add request helper functions
  videobuf2-v4l2: add vb2_request_queue/validate helpers
  v4l2-mem2mem: add vb2_m2m_request_queue
  media: vim2m: add media device
  vim2m: use workqueue
  vim2m: support requests
  vivid: add mc
  vivid: add request support
  RFC: media-requests: add debugfs node

Sakari Ailus (9):
  media-request: Make request state an enum
  media-request: Add support for updating request objects optimally
  media-request: Add a sanity check for the media request state
  media: doc: Add media-request.h header to documentation build
  v4l2-ctrls: Add documentation for control request support functions
  v4l2-ctrls: Lock the request for updating during S_EXT_CTRLS
  videobuf2-v4l2: Lock the media request for update for QBUF
  videobuf2-core: Make request state an enum
  v4l: m2m: Simplify exiting the function in v4l2_m2m_try_schedule

 Documentation/media/kapi/mc-core.rst   |   2 +
 Documentation/media/uapi/mediactl/media-funcs.rst  |   3 +
 .../uapi/mediactl/media-ioc-request-alloc.rst  |  71 +++
 .../uapi/mediactl/media-request-ioc-queue.rst  |  46 ++
 .../uapi/mediactl/media-request-ioc-reinit.rst |  51 +++
 Documentation/media/uapi/v4l/buffer.rst|  18 +-
 Documentation/media/uapi/v4l/common.rst|   1 +
 Documentation/media/uapi/v4l/request-api.rst   | 211 +
 .../media/uapi/v4l/vidioc-g-ext-ctrls.rst  |  25 +-
 Documentation/media/uapi/v4l/vidioc-qbuf.rst   |   7 +
 Documentation/media/videodev2.h.rst.exceptions |   1 +
 drivers/media/Makefile |   3 +-
 drivers/media/common/videobuf2/videobuf2-core.c| 192 ++--
 drivers/media/common/videobuf2/videobuf2-v4l2.c| 460 ---
 drivers/media/dvb-core/dvb_vb2.c   |   5 +-
 drivers/media/dvb-frontends/rtl2832_sdr.c  |   5 +-
 drivers/media/media-device.c   |  55 +++
 drivers/media/media-devnode.c  |  17 +
 drivers/media/media-request.c  | 473 +++
 drivers/media/pci/bt8xx/bttv-driver.c  |   2 +-
 drivers/media/pci/cx23885/cx23885-417.c|   2 +-
 drivers/media/pci/cx88/cx88-blackbird.c|   2 +-
 drivers/media/pci/cx88/cx88-video.c|   2 +-
 drivers/media/pci/saa7134/saa7134-empress.c|   4 +-
 

[PATCH v14 30/36] media: vim2m: add media device

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Request API requires a media node. Add one to the vim2m driver so we can
use requests with it.

This probably needs a bit more work to correctly represent m2m
hardware in the media topology.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vim2m.c | 42 +-
 1 file changed, 37 insertions(+), 5 deletions(-)

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 065483e62db4d..9be4da3b85773 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -140,6 +140,10 @@ static struct vim2m_fmt *find_format(struct v4l2_format *f)
 struct vim2m_dev {
struct v4l2_device  v4l2_dev;
struct video_device vfd;
+#ifdef CONFIG_MEDIA_CONTROLLER
+   struct media_device mdev;
+   struct media_padpad[2];
+#endif
 
atomic_tnum_inst;
struct mutexdev_mutex;
@@ -1000,11 +1004,6 @@ static int vim2m_probe(struct platform_device *pdev)
return -ENOMEM;
 
spin_lock_init(>irqlock);
-
-   ret = v4l2_device_register(>dev, >v4l2_dev);
-   if (ret)
-   return ret;
-
atomic_set(>num_inst, 0);
mutex_init(>dev_mutex);
 
@@ -1013,6 +1012,22 @@ static int vim2m_probe(struct platform_device *pdev)
vfd->lock = >dev_mutex;
vfd->v4l2_dev = >v4l2_dev;
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->mdev.dev = >dev;
+   strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model));
+   media_device_init(>mdev);
+   dev->v4l2_dev.mdev = >mdev;
+   dev->pad[0].flags = MEDIA_PAD_FL_SINK;
+   dev->pad[1].flags = MEDIA_PAD_FL_SOURCE;
+   ret = media_entity_pads_init(>entity, 2, dev->pad);
+   if (ret)
+   return ret;
+#endif
+
+   ret = v4l2_device_register(>dev, >v4l2_dev);
+   if (ret)
+   goto unreg_media;
+
ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
if (ret) {
v4l2_err(>v4l2_dev, "Failed to register video device\n");
@@ -1034,6 +1049,13 @@ static int vim2m_probe(struct platform_device *pdev)
goto err_m2m;
}
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   /* Register the media device node */
+   ret = media_device_register(>mdev);
+   if (ret)
+   goto err_m2m;
+#endif
+
return 0;
 
 err_m2m:
@@ -1041,6 +1063,10 @@ static int vim2m_probe(struct platform_device *pdev)
video_unregister_device(>vfd);
 unreg_dev:
v4l2_device_unregister(>v4l2_dev);
+unreg_media:
+#ifdef CONFIG_MEDIA_CONTROLLER
+   media_device_unregister(>mdev);
+#endif
 
return ret;
 }
@@ -1050,6 +1076,12 @@ static int vim2m_remove(struct platform_device *pdev)
struct vim2m_dev *dev = platform_get_drvdata(pdev);
 
v4l2_info(>v4l2_dev, "Removing " MEM2MEM_NAME);
+
+#ifdef CONFIG_MEDIA_CONTROLLER
+   media_device_unregister(>mdev);
+   media_device_cleanup(>mdev);
+#endif
+
v4l2_m2m_release(dev->m2m_dev);
del_timer_sync(>timer);
video_unregister_device(>vfd);
-- 
2.11.0



[PATCH v14 01/36] uapi/linux/media.h: add request API

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Define the public request API.

This adds the new MEDIA_IOC_REQUEST_ALLOC ioctl to allocate a request
and two ioctls that operate on a request in order to queue the
contents of the request to the driver and to re-initialize the
request.

Signed-off-by: Hans Verkuil 
---
 include/uapi/linux/media.h | 12 
 1 file changed, 12 insertions(+)

diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
index c7e9a5cba24ed..32883d4d22b22 100644
--- a/include/uapi/linux/media.h
+++ b/include/uapi/linux/media.h
@@ -342,11 +342,23 @@ struct media_v2_topology {
 
 /* ioctls */
 
+struct __attribute__ ((packed)) media_request_alloc {
+   __s32 fd;
+};
+
 #define MEDIA_IOC_DEVICE_INFO  _IOWR('|', 0x00, struct media_device_info)
 #define MEDIA_IOC_ENUM_ENTITIES_IOWR('|', 0x01, struct 
media_entity_desc)
 #define MEDIA_IOC_ENUM_LINKS   _IOWR('|', 0x02, struct media_links_enum)
 #define MEDIA_IOC_SETUP_LINK   _IOWR('|', 0x03, struct media_link_desc)
 #define MEDIA_IOC_G_TOPOLOGY   _IOWR('|', 0x04, struct media_v2_topology)
+#define MEDIA_IOC_REQUEST_ALLOC_IOWR('|', 0x05, struct 
media_request_alloc)
+
+/*
+ * These ioctls are called from the request file descriptor as returned
+ * by MEDIA_IOC_REQUEST_ALLOC.
+ */
+#define MEDIA_REQUEST_IOC_QUEUE_IO('|',  0x80)
+#define MEDIA_REQUEST_IOC_REINIT   _IO('|',  0x81)
 
 #if !defined(__KERNEL__) || defined(__NEED_MEDIA_LEGACY_API)
 
-- 
2.11.0



[PATCH v14 23/36] videobuf2-v4l2: integrate with media requests

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

This implements the V4L2 part of the request support. The main
change is that vb2_qbuf and vb2_prepare_buf now have a new
media_device pointer. This required changes to several drivers
that did not use the vb2_ioctl_qbuf/prepare_buf helper functions.

Signed-off-by: Hans Verkuil 
---
 drivers/media/common/videobuf2/videobuf2-v4l2.c  | 97 +---
 drivers/media/platform/omap3isp/ispvideo.c   |  2 +-
 drivers/media/platform/s3c-camif/camif-capture.c |  4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_dec.c |  4 +-
 drivers/media/platform/s5p-mfc/s5p_mfc_enc.c |  4 +-
 drivers/media/platform/soc_camera/soc_camera.c   |  4 +-
 drivers/media/usb/uvc/uvc_queue.c|  5 +-
 drivers/media/usb/uvc/uvc_v4l2.c |  3 +-
 drivers/media/usb/uvc/uvcvideo.h |  1 +
 drivers/media/v4l2-core/v4l2-mem2mem.c   |  7 +-
 drivers/staging/media/davinci_vpfe/vpfe_video.c  |  3 +-
 drivers/staging/media/omap4iss/iss_video.c   |  3 +-
 drivers/usb/gadget/function/uvc_queue.c  |  2 +-
 include/media/videobuf2-v4l2.h   | 14 +++-
 14 files changed, 122 insertions(+), 31 deletions(-)

diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c 
b/drivers/media/common/videobuf2/videobuf2-v4l2.c
index b8d370b97ccaf..0a68b19b40da7 100644
--- a/drivers/media/common/videobuf2/videobuf2-v4l2.c
+++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c
@@ -25,6 +25,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -40,10 +41,12 @@ module_param(debug, int, 0644);
pr_info("vb2-v4l2: %s: " fmt, __func__, ## arg); \
} while (0)
 
-/* Flags that are set by the vb2 core */
+/* Flags that are set by us */
 #define V4L2_BUFFER_MASK_FLAGS (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
 V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR | \
 V4L2_BUF_FLAG_PREPARED | \
+V4L2_BUF_FLAG_IN_REQUEST | \
+V4L2_BUF_FLAG_REQUEST_FD | \
 V4L2_BUF_FLAG_TIMESTAMP_MASK)
 /* Output buffer flags that should be passed on to the driver */
 #define V4L2_BUFFER_OUT_FLAGS  (V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME | \
@@ -181,6 +184,7 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, 
struct v4l2_buffer *b
return -EINVAL;
}
vbuf->sequence = 0;
+   vbuf->request_fd = -1;
 
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
switch (b->memory) {
@@ -318,9 +322,12 @@ static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, 
struct v4l2_buffer *b
return 0;
 }
 
-static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b,
-   const char *opname)
+static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device 
*mdev,
+   struct v4l2_buffer *b,
+   const char *opname,
+   struct media_request **p_req)
 {
+   struct media_request *req;
struct vb2_v4l2_buffer *vbuf;
struct vb2_buffer *vb;
int ret;
@@ -354,7 +361,55 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, 
struct v4l2_buffer *b,
 
/* Copy relevant information provided by the userspace */
memset(vbuf->planes, 0, sizeof(vbuf->planes[0]) * vb->num_planes);
-   return vb2_fill_vb2_v4l2_buffer(vb, b);
+   ret = vb2_fill_vb2_v4l2_buffer(vb, b);
+   if (ret)
+   return ret;
+
+   if (!(b->flags & V4L2_BUF_FLAG_REQUEST_FD))
+   return 0;
+
+   /*
+* For proper locking when queueing a request you need to be able
+* to lock access to the vb2 queue, so check that there is a lock
+* that we can use. In addition p_req must be non-NULL.
+*/
+   if (WARN_ON(!q->lock || !p_req))
+   return -EINVAL;
+
+   /*
+* Make sure this op is implemented by the driver. It's easy to forget
+* this callback, but is it important when canceling a buffer in a
+* queued request.
+*/
+   if (WARN_ON(!q->ops->buf_request_complete))
+   return -EINVAL;
+
+   if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+   dprintk(1, "%s: buffer is not in dequeued state\n", opname);
+   return -EINVAL;
+   }
+
+   if (b->request_fd < 0) {
+   dprintk(1, "%s: request_fd < 0\n", opname);
+   return -EINVAL;
+   }
+
+   req = media_request_get_by_fd(mdev, b->request_fd);
+   if (IS_ERR(req)) {
+   dprintk(1, "%s: invalid request_fd\n", opname);
+   return PTR_ERR(req);
+   }
+
+   if (atomic_read(>state) != MEDIA_REQUEST_STATE_IDLE) {
+   dprintk(1, "%s: request is not 

[PATCH v14 05/36] media-request: Make request state an enum

2018-05-21 Thread Sakari Ailus
Make the request state an enum in order to simplify serialising access to
the state as well as other fields in the request. Using the atomic would
be fine as such, but it conveys the suggestion that the atomic operations
alone will be enough for changing that state which is not true.

Signed-off-by: Sakari Ailus 
---
 drivers/media/media-request.c | 57 ++-
 include/media/media-request.h |  2 +-
 2 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index c7e11e816e272..a1576cf528605 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -36,7 +36,8 @@ static void media_request_clean(struct media_request *req)
 {
struct media_request_object *obj, *obj_safe;
 
-   WARN_ON(atomic_read(>state) != MEDIA_REQUEST_STATE_CLEANING);
+   /* Just a sanity check. No other code path is allowed to change this. */
+   WARN_ON(req->state != MEDIA_REQUEST_STATE_CLEANING);
 
list_for_each_entry_safe(obj, obj_safe, >objects, list) {
media_request_object_unbind(obj);
@@ -55,7 +56,8 @@ static void media_request_release(struct kref *kref)
 
dev_dbg(mdev->dev, "request: release %s\n", req->debug_str);
 
-   atomic_set(>state, MEDIA_REQUEST_STATE_CLEANING);
+   /* No other users, no need for a spinlock */
+   req->state = MEDIA_REQUEST_STATE_CLEANING;
 
media_request_clean(req);
 
@@ -85,19 +87,16 @@ static unsigned int media_request_poll(struct file *filp,
struct media_request *req = filp->private_data;
unsigned long flags;
unsigned int ret = 0;
-   enum media_request_state state;
 
if (!(poll_requested_events(wait) & POLLPRI))
return 0;
 
spin_lock_irqsave(>lock, flags);
-   state = atomic_read(>state);
-
-   if (state == MEDIA_REQUEST_STATE_COMPLETE) {
+   if (req->state == MEDIA_REQUEST_STATE_COMPLETE) {
ret = POLLPRI;
goto unlock;
}
-   if (state != MEDIA_REQUEST_STATE_QUEUED) {
+   if (req->state != MEDIA_REQUEST_STATE_QUEUED) {
ret = POLLERR;
goto unlock;
}
@@ -127,10 +126,11 @@ static long media_request_ioctl_queue(struct 
media_request *req)
mutex_lock(>req_queue_mutex);
 
spin_lock_irqsave(>lock, flags);
-   state = atomic_cmpxchg(>state, MEDIA_REQUEST_STATE_IDLE,
-  MEDIA_REQUEST_STATE_VALIDATING);
+   if (req->state == MEDIA_REQUEST_STATE_IDLE)
+   req->state = MEDIA_REQUEST_STATE_VALIDATING;
+   state = req->state;
spin_unlock_irqrestore(>lock, flags);
-   if (state != MEDIA_REQUEST_STATE_IDLE) {
+   if (state != MEDIA_REQUEST_STATE_VALIDATING) {
dev_dbg(mdev->dev,
"request: unable to queue %s, request in state %s\n",
req->debug_str, media_request_state_str(state));
@@ -155,8 +155,10 @@ static long media_request_ioctl_queue(struct media_request 
*req)
 * canceled, and that uses the req_queue_mutex which is still locked
 * while req_queue is called, so that's safe as well.
 */
-   atomic_set(>state,
-  ret ? MEDIA_REQUEST_STATE_IDLE : MEDIA_REQUEST_STATE_QUEUED);
+   spin_lock_irqsave(>lock, flags);
+   req->state = ret ? MEDIA_REQUEST_STATE_IDLE
+: MEDIA_REQUEST_STATE_QUEUED;
+   spin_unlock_irqrestore(>lock, flags);
 
if (!ret)
mdev->ops->req_queue(req);
@@ -178,20 +180,22 @@ static long media_request_ioctl_reinit(struct 
media_request *req)
unsigned long flags;
 
spin_lock_irqsave(>lock, flags);
-   if (atomic_read(>state) != MEDIA_REQUEST_STATE_IDLE &&
-   atomic_read(>state) != MEDIA_REQUEST_STATE_COMPLETE) {
+   if (req->state != MEDIA_REQUEST_STATE_IDLE &&
+   req->state != MEDIA_REQUEST_STATE_COMPLETE) {
dev_dbg(mdev->dev,
"request: %s not in idle or complete state, cannot 
reinit\n",
req->debug_str);
spin_unlock_irqrestore(>lock, flags);
return -EBUSY;
}
-   atomic_set(>state, MEDIA_REQUEST_STATE_CLEANING);
+   req->state = MEDIA_REQUEST_STATE_CLEANING;
spin_unlock_irqrestore(>lock, flags);
 
media_request_clean(req);
 
-   atomic_set(>state, MEDIA_REQUEST_STATE_IDLE);
+   spin_lock_irqsave(>lock, flags);
+   req->state = MEDIA_REQUEST_STATE_IDLE;
+   spin_unlock_irqrestore(>lock, flags);
 
return 0;
 }
@@ -284,7 +288,7 @@ int media_request_alloc(struct media_device *mdev,
 
filp->private_data = req;
req->mdev = mdev;
-   atomic_set(>state, MEDIA_REQUEST_STATE_IDLE);
+   req->state = MEDIA_REQUEST_STATE_IDLE;
req->num_incomplete_objects = 0;
   

[PATCH v14 34/36] vivid: add request support

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Add support for requests to vivid.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vivid/vivid-core.c|  8 
 drivers/media/platform/vivid/vivid-kthread-cap.c | 12 
 drivers/media/platform/vivid/vivid-kthread-out.c | 12 
 drivers/media/platform/vivid/vivid-sdr-cap.c | 16 
 drivers/media/platform/vivid/vivid-vbi-cap.c | 10 ++
 drivers/media/platform/vivid/vivid-vbi-out.c | 10 ++
 drivers/media/platform/vivid/vivid-vid-cap.c | 10 ++
 drivers/media/platform/vivid/vivid-vid-out.c | 10 ++
 8 files changed, 88 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-core.c 
b/drivers/media/platform/vivid/vivid-core.c
index 69386b26d5dd1..a84c7e37c22b4 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -627,6 +627,13 @@ static void vivid_dev_release(struct v4l2_device *v4l2_dev)
kfree(dev);
 }
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+static const struct media_device_ops vivid_media_ops = {
+   .req_validate = vb2_request_validate,
+   .req_queue = vb2_request_queue,
+};
+#endif
+
 static int vivid_create_instance(struct platform_device *pdev, int inst)
 {
static const struct v4l2_dv_timings def_dv_timings =
@@ -664,6 +671,7 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
strlcpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model));
dev->mdev.dev = >dev;
media_device_init(>mdev);
+   dev->mdev.ops = _media_ops;
 #endif
 
/* register v4l2_device */
diff --git a/drivers/media/platform/vivid/vivid-kthread-cap.c 
b/drivers/media/platform/vivid/vivid-kthread-cap.c
index 3fdb280c36caf..c192b4b1b9ded 100644
--- a/drivers/media/platform/vivid/vivid-kthread-cap.c
+++ b/drivers/media/platform/vivid/vivid-kthread-cap.c
@@ -703,6 +703,8 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev 
*dev, int dropped_bufs)
goto update_mv;
 
if (vid_cap_buf) {
+   v4l2_ctrl_request_setup(vid_cap_buf->vb.vb2_buf.req_obj.req,
+   >ctrl_hdl_vid_cap);
/* Fill buffer */
vivid_fillbuff(dev, vid_cap_buf);
dprintk(dev, 1, "filled buffer %d\n",
@@ -713,6 +715,8 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev 
*dev, int dropped_bufs)
dev->fb_cap.fmt.pixelformat == dev->fmt_cap->fourcc)
vivid_overlay(dev, vid_cap_buf);
 
+   v4l2_ctrl_request_complete(vid_cap_buf->vb.vb2_buf.req_obj.req,
+  >ctrl_hdl_vid_cap);
vb2_buffer_done(_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vid_cap buffer %d done\n",
@@ -720,10 +724,14 @@ static void vivid_thread_vid_cap_tick(struct vivid_dev 
*dev, int dropped_bufs)
}
 
if (vbi_cap_buf) {
+   v4l2_ctrl_request_setup(vbi_cap_buf->vb.vb2_buf.req_obj.req,
+   >ctrl_hdl_vbi_cap);
if (dev->stream_sliced_vbi_cap)
vivid_sliced_vbi_cap_process(dev, vbi_cap_buf);
else
vivid_raw_vbi_cap_process(dev, vbi_cap_buf);
+   v4l2_ctrl_request_complete(vbi_cap_buf->vb.vb2_buf.req_obj.req,
+  >ctrl_hdl_vbi_cap);
vb2_buffer_done(_cap_buf->vb.vb2_buf, dev->dqbuf_error ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
dprintk(dev, 2, "vbi_cap %d done\n",
@@ -891,6 +899,8 @@ void vivid_stop_generating_vid_cap(struct vivid_dev *dev, 
bool *pstreaming)
buf = list_entry(dev->vid_cap_active.next,
 struct vivid_buffer, list);
list_del(>list);
+   v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
+  >ctrl_hdl_vid_cap);
vb2_buffer_done(>vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(dev, 2, "vid_cap buffer %d done\n",
buf->vb.vb2_buf.index);
@@ -904,6 +914,8 @@ void vivid_stop_generating_vid_cap(struct vivid_dev *dev, 
bool *pstreaming)
buf = list_entry(dev->vbi_cap_active.next,
 struct vivid_buffer, list);
list_del(>list);
+   v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req,
+  >ctrl_hdl_vbi_cap);
vb2_buffer_done(>vb.vb2_buf, VB2_BUF_STATE_ERROR);
dprintk(dev, 2, "vbi_cap 

[PATCH v14 02/36] media-request: implement media requests

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Add initial media request support:

1) Add MEDIA_IOC_REQUEST_ALLOC ioctl support to media-device.c
2) Add struct media_request to store request objects.
3) Add struct media_request_object to represent a request object.
4) Add MEDIA_REQUEST_IOC_QUEUE/REINIT ioctl support.

Basic lifecycle: the application allocates a request, adds
objects to it, queues the request, polls until it is completed
and can then read the final values of the objects at the time
of completion. When it closes the file descriptor the request
memory will be freed (actually, when the last user of that request
releases the request).

Drivers will bind an object to a request (the 'adds objects to it'
phase), when MEDIA_REQUEST_IOC_QUEUE is called the request is
validated (req_validate op), then queued (the req_queue op).

When done with an object it can either be unbound from the request
(e.g. when the driver has finished with a vb2 buffer) or marked as
completed (e.g. for controls associated with a buffer). When all
objects in the request are completed (or unbound), then the request
fd will signal an exception (poll).

Signed-off-by: Hans Verkuil 
---
 drivers/media/Makefile|   3 +-
 drivers/media/media-device.c  |  14 ++
 drivers/media/media-request.c | 407 ++
 include/media/media-device.h  |  16 ++
 include/media/media-request.h | 244 +
 5 files changed, 683 insertions(+), 1 deletion(-)
 create mode 100644 drivers/media/media-request.c
 create mode 100644 include/media/media-request.h

diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 594b462ddf0ef..985d35ec6b298 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -3,7 +3,8 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
-media-objs := media-device.o media-devnode.o media-entity.o
+media-objs := media-device.o media-devnode.o media-entity.o \
+  media-request.o
 
 #
 # I2C drivers should come before other drivers, otherwise they'll fail
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index ae59c31775557..1119c1058e73a 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -32,6 +32,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #ifdef CONFIG_MEDIA_CONTROLLER
 
@@ -367,6 +368,15 @@ static long media_device_get_topology(struct media_device 
*mdev, void *arg)
return ret;
 }
 
+static long media_device_request_alloc(struct media_device *mdev,
+  struct media_request_alloc *alloc)
+{
+   if (!mdev->ops || !mdev->ops->req_validate || !mdev->ops->req_queue)
+   return -ENOTTY;
+
+   return media_request_alloc(mdev, alloc);
+}
+
 static long copy_arg_from_user(void *karg, void __user *uarg, unsigned int cmd)
 {
/* All media IOCTLs are _IOWR() */
@@ -415,6 +425,7 @@ static const struct media_ioctl_info ioctl_info[] = {
MEDIA_IOC(ENUM_LINKS, media_device_enum_links, 
MEDIA_IOC_FL_GRAPH_MUTEX),
MEDIA_IOC(SETUP_LINK, media_device_setup_link, 
MEDIA_IOC_FL_GRAPH_MUTEX),
MEDIA_IOC(G_TOPOLOGY, media_device_get_topology, 
MEDIA_IOC_FL_GRAPH_MUTEX),
+   MEDIA_IOC(REQUEST_ALLOC, media_device_request_alloc, 0),
 };
 
 static long media_device_ioctl(struct file *filp, unsigned int cmd,
@@ -687,6 +698,8 @@ void media_device_init(struct media_device *mdev)
INIT_LIST_HEAD(>pads);
INIT_LIST_HEAD(>links);
INIT_LIST_HEAD(>entity_notify);
+
+   mutex_init(>req_queue_mutex);
mutex_init(>graph_mutex);
ida_init(>entity_internal_idx);
 
@@ -700,6 +713,7 @@ void media_device_cleanup(struct media_device *mdev)
mdev->entity_internal_idx_max = 0;
media_graph_walk_cleanup(>pm_count_walk);
mutex_destroy(>graph_mutex);
+   mutex_destroy(>req_queue_mutex);
 }
 EXPORT_SYMBOL_GPL(media_device_cleanup);
 
diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
new file mode 100644
index 0..c216c4ab628b5
--- /dev/null
+++ b/drivers/media/media-request.c
@@ -0,0 +1,407 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Media device request objects
+ *
+ * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights 
reserved.
+ * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 Google, Inc.
+ *
+ * Author: Hans Verkuil 
+ * Author: Sakari Ailus 
+ */
+
+#include 
+#include 
+
+#include 
+#include 
+
+static const char * const request_state[] = {
+   [MEDIA_REQUEST_STATE_IDLE]   = "idle",
+   [MEDIA_REQUEST_STATE_VALIDATING] = "validating",
+   [MEDIA_REQUEST_STATE_QUEUED] = "queued",
+   [MEDIA_REQUEST_STATE_COMPLETE]   = "complete",
+   [MEDIA_REQUEST_STATE_CLEANING]   = "cleaning",
+};
+
+static const char *
+media_request_state_str(enum media_request_state state)

[PATCH v14 08/36] media: doc: Add media-request.h header to documentation build

2018-05-21 Thread Sakari Ailus
media-request.h has been recently added; add it to the documentation build
as well.

Signed-off-by: Sakari Ailus 
---
 Documentation/media/kapi/mc-core.rst | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/media/kapi/mc-core.rst 
b/Documentation/media/kapi/mc-core.rst
index 0c05503eaf1fa..69362b3135c23 100644
--- a/Documentation/media/kapi/mc-core.rst
+++ b/Documentation/media/kapi/mc-core.rst
@@ -262,3 +262,5 @@ in the end provide a way to use driver-specific callbacks.
 .. kernel-doc:: include/media/media-devnode.h
 
 .. kernel-doc:: include/media/media-entity.h
+
+.. kernel-doc:: include/media/media-request.h
-- 
2.11.0



[PATCH v14 35/36] RFC: media-requests: add debugfs node

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Keep track of the number of requests and request objects of a media
device. Helps to verify that all request-related memory is freed.

Signed-off-by: Hans Verkuil 
---
 drivers/media/media-device.c  | 41 +
 drivers/media/media-devnode.c | 17 +
 drivers/media/media-request.c |  5 +
 include/media/media-device.h  | 11 +++
 include/media/media-devnode.h |  4 
 include/media/media-request.h |  1 +
 6 files changed, 79 insertions(+)

diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 1119c1058e73a..cefa822f505f2 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -681,6 +681,23 @@ void media_device_unregister_entity(struct media_entity 
*entity)
 }
 EXPORT_SYMBOL_GPL(media_device_unregister_entity);
 
+#ifdef CONFIG_DEBUG_FS
+/*
+ * Log the state of media requests.
+ * Very useful for debugging.
+ */
+static int media_device_requests(struct seq_file *file, void *priv)
+{
+   struct media_device *dev = dev_get_drvdata(file->private);
+
+   seq_printf(file, "number of requests: %d\n",
+  atomic_read(>num_requests));
+   seq_printf(file, "number of request objects: %d\n",
+  atomic_read(>num_request_objects));
+   return 0;
+}
+#endif
+
 /**
  * media_device_init() - initialize a media device
  * @mdev:  The media device
@@ -703,6 +720,9 @@ void media_device_init(struct media_device *mdev)
mutex_init(>graph_mutex);
ida_init(>entity_internal_idx);
 
+   atomic_set(>num_requests, 0);
+   atomic_set(>num_request_objects, 0);
+
dev_dbg(mdev->dev, "Media device initialized\n");
 }
 EXPORT_SYMBOL_GPL(media_device_init);
@@ -754,6 +774,26 @@ int __must_check __media_device_register(struct 
media_device *mdev,
 
dev_dbg(mdev->dev, "Media device registered\n");
 
+#ifdef CONFIG_DEBUG_FS
+   if (!media_top_dir)
+   return 0;
+
+   mdev->media_dir = debugfs_create_dir(dev_name(>dev),
+media_top_dir);
+   if (IS_ERR_OR_NULL(mdev->media_dir)) {
+   dev_warn(mdev->dev, "Failed to create debugfs dir\n");
+   return 0;
+   }
+   mdev->requests_file = debugfs_create_devm_seqfile(>dev,
+   "requests", mdev->media_dir, media_device_requests);
+   if (IS_ERR_OR_NULL(mdev->requests_file)) {
+   dev_warn(mdev->dev, "Failed to create requests file\n");
+   debugfs_remove_recursive(mdev->media_dir);
+   mdev->media_dir = NULL;
+   return 0;
+   }
+#endif
+
return 0;
 }
 EXPORT_SYMBOL_GPL(__media_device_register);
@@ -831,6 +871,7 @@ void media_device_unregister(struct media_device *mdev)
 
dev_dbg(mdev->dev, "Media device unregistered\n");
 
+   debugfs_remove_recursive(mdev->media_dir);
device_remove_file(>devnode->dev, _attr_model);
media_devnode_unregister(mdev->devnode);
/* devnode free is handled in media_devnode_*() */
diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index 6b87a721dc499..4358ed22f208a 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -53,6 +53,12 @@ static dev_t media_dev_t;
 static DEFINE_MUTEX(media_devnode_lock);
 static DECLARE_BITMAP(media_devnode_nums, MEDIA_NUM_DEVICES);
 
+/*
+ * debugfs
+ */
+struct dentry *media_top_dir;
+
+
 /* Called when the last user of the media device exits. */
 static void media_devnode_release(struct device *cd)
 {
@@ -259,6 +265,8 @@ int __must_check media_devnode_register(struct media_device 
*mdev,
goto cdev_add_error;
}
 
+   dev_set_drvdata(>dev, mdev);
+
/* Part 4: Activate this minor. The char device can now be used. */
set_bit(MEDIA_FLAG_REGISTERED, >flags);
 
@@ -310,6 +318,14 @@ static int __init media_devnode_init(void)
return ret;
}
 
+#ifdef CONFIG_DEBUG_FS
+   media_top_dir = debugfs_create_dir("media", NULL);
+   if (IS_ERR_OR_NULL(media_top_dir)) {
+   pr_warn("Failed to create debugfs media dir\n");
+   media_top_dir = NULL;
+   }
+#endif
+
ret = bus_register(_bus_type);
if (ret < 0) {
unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
@@ -322,6 +338,7 @@ static int __init media_devnode_init(void)
 
 static void __exit media_devnode_exit(void)
 {
+   debugfs_remove_recursive(media_top_dir);
bus_unregister(_bus_type);
unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
 }
diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index ef4a436f220a3..cb83c83035b10 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -68,6 +68,7 @@ static void media_request_release(struct kref *kref)

[PATCH v14 31/36] vim2m: use workqueue

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

v4l2_ctrl uses mutexes, so we can't setup a ctrl_handler in
interrupt context. Switch to a workqueue instead.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vim2m.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c
index 9be4da3b85773..a1b0bb08668d3 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/vim2m.c
@@ -150,6 +150,7 @@ struct vim2m_dev {
spinlock_t  irqlock;
 
struct timer_list   timer;
+   struct work_struct  work_run;
 
struct v4l2_m2m_dev *m2m_dev;
 };
@@ -392,9 +393,10 @@ static void device_run(void *priv)
schedule_irq(dev, ctx->transtime);
 }
 
-static void device_isr(struct timer_list *t)
+static void device_work(struct work_struct *w)
 {
-   struct vim2m_dev *vim2m_dev = from_timer(vim2m_dev, t, timer);
+   struct vim2m_dev *vim2m_dev =
+   container_of(w, struct vim2m_dev, work_run);
struct vim2m_ctx *curr_ctx;
struct vb2_v4l2_buffer *src_vb, *dst_vb;
unsigned long flags;
@@ -426,6 +428,13 @@ static void device_isr(struct timer_list *t)
}
 }
 
+static void device_isr(struct timer_list *t)
+{
+   struct vim2m_dev *vim2m_dev = from_timer(vim2m_dev, t, timer);
+
+   schedule_work(_dev->work_run);
+}
+
 /*
  * video ioctls
  */
@@ -806,6 +815,7 @@ static void vim2m_stop_streaming(struct vb2_queue *q)
struct vb2_v4l2_buffer *vbuf;
unsigned long flags;
 
+   flush_scheduled_work();
for (;;) {
if (V4L2_TYPE_IS_OUTPUT(q->type))
vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
@@ -1011,6 +1021,7 @@ static int vim2m_probe(struct platform_device *pdev)
vfd = >vfd;
vfd->lock = >dev_mutex;
vfd->v4l2_dev = >v4l2_dev;
+   INIT_WORK(>work_run, device_work);
 
 #ifdef CONFIG_MEDIA_CONTROLLER
dev->mdev.dev = >dev;
-- 
2.11.0



[PATCH v14 36/36] v4l: m2m: Simplify exiting the function in v4l2_m2m_try_schedule

2018-05-21 Thread Sakari Ailus
The v4l2_m2m_try_schedule function acquires and releases multiple
spinlocks; simplify unlocking the job lock by adding a label to unlock the
job lock and exit the function.

Signed-off-by: Sakari Ailus 
---
 drivers/media/v4l2-core/v4l2-mem2mem.c | 22 --
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c 
b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 80233bf6523ac..2c20c7a6de2b7 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -231,15 +231,13 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
 
/* If the context is aborted then don't schedule it */
if (m2m_ctx->job_flags & TRANS_ABORT) {
-   spin_unlock_irqrestore(_dev->job_spinlock, flags_job);
dprintk("Aborted context\n");
-   return;
+   goto out_unlock;
}
 
if (m2m_ctx->job_flags & TRANS_QUEUED) {
-   spin_unlock_irqrestore(_dev->job_spinlock, flags_job);
dprintk("On job queue already\n");
-   return;
+   goto out_unlock;
}
 
spin_lock_irqsave(_ctx->out_q_ctx.rdy_spinlock, flags_out);
@@ -247,9 +245,8 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
&& !m2m_ctx->out_q_ctx.buffered) {
spin_unlock_irqrestore(_ctx->out_q_ctx.rdy_spinlock,
flags_out);
-   spin_unlock_irqrestore(_dev->job_spinlock, flags_job);
dprintk("No input buffers available\n");
-   return;
+   goto out_unlock;
}
spin_lock_irqsave(_ctx->cap_q_ctx.rdy_spinlock, flags_cap);
if (list_empty(_ctx->cap_q_ctx.rdy_queue)
@@ -258,18 +255,16 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
flags_cap);
spin_unlock_irqrestore(_ctx->out_q_ctx.rdy_spinlock,
flags_out);
-   spin_unlock_irqrestore(_dev->job_spinlock, flags_job);
dprintk("No output buffers available\n");
-   return;
+   goto out_unlock;
}
spin_unlock_irqrestore(_ctx->cap_q_ctx.rdy_spinlock, flags_cap);
spin_unlock_irqrestore(_ctx->out_q_ctx.rdy_spinlock, flags_out);
 
if (m2m_dev->m2m_ops->job_ready
&& (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) {
-   spin_unlock_irqrestore(_dev->job_spinlock, flags_job);
dprintk("Driver not ready\n");
-   return;
+   goto out_unlock;
}
 
list_add_tail(_ctx->queue, _dev->job_queue);
@@ -278,6 +273,13 @@ void v4l2_m2m_try_schedule(struct v4l2_m2m_ctx *m2m_ctx)
spin_unlock_irqrestore(_dev->job_spinlock, flags_job);
 
v4l2_m2m_try_run(m2m_dev);
+
+   return;
+
+out_unlock:
+   spin_unlock_irqrestore(_dev->job_spinlock, flags_job);
+
+   return;
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_try_schedule);
 
-- 
2.11.0



[PATCH v14 07/36] media-request: Add a sanity check for the media request state

2018-05-21 Thread Sakari Ailus
Add a sanity check for the number of the media request states equals the
number of status strings for debug purposes. This necessitates a new
entry in the request state enumeration, called NR_OF_MEDIA_REQUEST_STATE.

Signed-off-by: Sakari Ailus 
---
 drivers/media/media-request.c | 2 ++
 include/media/media-request.h | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c
index 03e74d72241a0..ef4a436f220a3 100644
--- a/drivers/media/media-request.c
+++ b/drivers/media/media-request.c
@@ -28,6 +28,8 @@ static const char * const request_state[] = {
 static const char *
 media_request_state_str(enum media_request_state state)
 {
+   BUILD_BUG_ON(NR_OF_MEDIA_REQUEST_STATE != ARRAY_SIZE(request_state));
+
if (WARN_ON(state >= ARRAY_SIZE(request_state)))
return "invalid";
return request_state[state];
diff --git a/include/media/media-request.h b/include/media/media-request.h
index 42cc6e7f6e532..7a2df18a069ce 100644
--- a/include/media/media-request.h
+++ b/include/media/media-request.h
@@ -31,6 +31,8 @@
  * @MEDIA_REQUEST_STATE_UPDATING:  The request is being updated, i.e.
  * request objects are being added,
  * modified or removed
+ * @NR_OF_MEDIA_REQUEST_STATE: The number of media request states, used
+ * internally for sanity check purposes
  */
 enum media_request_state {
MEDIA_REQUEST_STATE_IDLE,
@@ -39,6 +41,7 @@ enum media_request_state {
MEDIA_REQUEST_STATE_COMPLETE,
MEDIA_REQUEST_STATE_CLEANING,
MEDIA_REQUEST_STATE_UPDATING,
+   NR_OF_MEDIA_REQUEST_STATE,
 };
 
 struct media_request_object;
-- 
2.11.0



[PATCH v14 29/36] Documentation: v4l: document request API

2018-05-21 Thread Sakari Ailus
From: Alexandre Courbot 

Document the request API for V4L2 devices, and amend the documentation
of system calls influenced by it.

Signed-off-by: Alexandre Courbot 
Signed-off-by: Hans Verkuil 
---
 Documentation/media/uapi/mediactl/media-funcs.rst  |   3 +
 .../uapi/mediactl/media-ioc-request-alloc.rst  |  71 +++
 .../uapi/mediactl/media-request-ioc-queue.rst  |  46 +
 .../uapi/mediactl/media-request-ioc-reinit.rst |  51 +
 Documentation/media/uapi/v4l/buffer.rst|  18 +-
 Documentation/media/uapi/v4l/common.rst|   1 +
 Documentation/media/uapi/v4l/request-api.rst   | 211 +
 .../media/uapi/v4l/vidioc-g-ext-ctrls.rst  |  25 ++-
 Documentation/media/uapi/v4l/vidioc-qbuf.rst   |   7 +
 Documentation/media/videodev2.h.rst.exceptions |   1 +
 10 files changed, 428 insertions(+), 6 deletions(-)
 create mode 100644 
Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
 create mode 100644 
Documentation/media/uapi/mediactl/media-request-ioc-queue.rst
 create mode 100644 
Documentation/media/uapi/mediactl/media-request-ioc-reinit.rst
 create mode 100644 Documentation/media/uapi/v4l/request-api.rst

diff --git a/Documentation/media/uapi/mediactl/media-funcs.rst 
b/Documentation/media/uapi/mediactl/media-funcs.rst
index 076856501cdb3..f4da9b3e17ec5 100644
--- a/Documentation/media/uapi/mediactl/media-funcs.rst
+++ b/Documentation/media/uapi/mediactl/media-funcs.rst
@@ -16,3 +16,6 @@ Function Reference
 media-ioc-enum-entities
 media-ioc-enum-links
 media-ioc-setup-link
+media-ioc-request-alloc
+media-request-ioc-queue
+media-request-ioc-reinit
diff --git a/Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst 
b/Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
new file mode 100644
index 0..d45a94c9e23c7
--- /dev/null
+++ b/Documentation/media/uapi/mediactl/media-ioc-request-alloc.rst
@@ -0,0 +1,71 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+.. _media_ioc_request_alloc:
+
+*
+ioctl MEDIA_IOC_REQUEST_ALLOC
+*
+
+Name
+
+
+MEDIA_IOC_REQUEST_ALLOC - Allocate a request
+
+
+Synopsis
+
+
+.. c:function:: int ioctl( int fd, MEDIA_IOC_REQUEST_ALLOC, struct 
media_request_alloc *argp )
+:name: MEDIA_IOC_REQUEST_ALLOC
+
+
+Arguments
+=
+
+``fd``
+File descriptor returned by :ref:`open() `.
+
+``argp``
+
+
+Description
+===
+
+If the media device supports :ref:`requests `, then
+this ioctl can be used to allocate a request. A request is accessed through
+a file descriptor that is returned in struct :c:type:`media_request_alloc`.
+
+If the request was successfully allocated, then the request file descriptor
+can be passed to :ref:`ioctl VIDIOC_QBUF `,
+:ref:`ioctl VIDIOC_G_EXT_CTRLS `,
+:ref:`ioctl VIDIOC_S_EXT_CTRLS ` and
+:ref:`ioctl VIDIOC_TRY_EXT_CTRLS `.
+
+In addition, the request can be queued by calling
+:ref:`MEDIA_REQUEST_IOC_QUEUE` and re-initialized by calling
+:ref:`MEDIA_REQUEST_IOC_REINIT`.
+
+Finally, the file descriptor can be polled to wait for the request to
+complete.
+
+To free the request the file descriptor has to be closed.
+
+.. c:type:: media_request_alloc
+
+.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
+
+.. flat-table:: struct media_request_alloc
+:header-rows:  0
+:stub-columns: 0
+:widths:   1 1 2
+
+*  -  __s32
+   -  ``fd``
+   -  The file descriptor of the request.
+
+Return Value
+
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the
+:ref:`Generic Error Codes ` chapter.
diff --git a/Documentation/media/uapi/mediactl/media-request-ioc-queue.rst 
b/Documentation/media/uapi/mediactl/media-request-ioc-queue.rst
new file mode 100644
index 0..79f745a3d6638
--- /dev/null
+++ b/Documentation/media/uapi/mediactl/media-request-ioc-queue.rst
@@ -0,0 +1,46 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+.. _media_request_ioc_queue:
+
+*
+ioctl MEDIA_REQUEST_IOC_QUEUE
+*
+
+Name
+
+
+MEDIA_REQUEST_IOC_QUEUE - Queue a request
+
+
+Synopsis
+
+
+.. c:function:: int ioctl( int request_fd, MEDIA_REQUEST_IOC_QUEUE )
+:name: MEDIA_REQUEST_IOC_QUEUE
+
+
+Arguments
+=
+
+``request_fd``
+File descriptor returned by :ref:`MEDIA_IOC_REQUEST_ALLOC`.
+
+
+Description
+===
+
+If the media device supports :ref:`requests `, then
+this request ioctl can be used to queue a previously allocated request.
+
+If the request was successfully queued, then the file descriptor can be
+polled to wait for the request to complete.
+
+Return Value
+
+
+On success 0 is returned, on error -1 and the ``errno`` variable is set
+appropriately. The generic error codes are described at the

[PATCH v14 17/36] v4l2-ctrls: support g/s_ext_ctrls for requests

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

The v4l2_g/s_ext_ctrls functions now support control handlers that
represent requests.

The v4l2_ctrls_find_req_obj() function is responsible for finding the
request from the fd.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/omap3isp/ispvideo.c |   2 +-
 drivers/media/v4l2-core/v4l2-ctrls.c   | 113 +++--
 drivers/media/v4l2-core/v4l2-ioctl.c   |  12 +--
 drivers/media/v4l2-core/v4l2-subdev.c  |   9 ++-
 include/media/v4l2-ctrls.h |   7 +-
 5 files changed, 124 insertions(+), 19 deletions(-)

diff --git a/drivers/media/platform/omap3isp/ispvideo.c 
b/drivers/media/platform/omap3isp/ispvideo.c
index 9d228eac24ea5..674e7fd3ad996 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -1028,7 +1028,7 @@ static int isp_video_check_external_subdevs(struct 
isp_video *video,
ctrls.count = 1;
ctrls.controls = 
 
-   ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, );
+   ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, NULL, );
if (ret < 0) {
dev_warn(isp->dev, "no pixel rate control in subdev %s\n",
 pipe->external->name);
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c 
b/drivers/media/v4l2-core/v4l2-ctrls.c
index 56b986185463d..df58a23eb731a 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -3124,7 +3124,8 @@ static int class_check(struct v4l2_ctrl_handler *hdl, u32 
which)
 }
 
 /* Get extended controls. Allocates the helpers array if needed. */
-int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls 
*cs)
+int __v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl,
+  struct v4l2_ext_controls *cs)
 {
struct v4l2_ctrl_helper helper[4];
struct v4l2_ctrl_helper *helpers = helper;
@@ -3204,6 +3205,73 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, 
struct v4l2_ext_controls *cs
kvfree(helpers);
return ret;
 }
+
+static struct media_request_object *
+v4l2_ctrls_find_req_obj(struct v4l2_ctrl_handler *hdl,
+   struct media_device *mdev, s32 fd, bool set)
+{
+   struct media_request *req = media_request_get_by_fd(mdev, fd);
+   struct media_request_object *obj;
+   struct v4l2_ctrl_handler *new_hdl;
+   int ret;
+
+   if (IS_ERR(req))
+   return ERR_CAST(req);
+
+   if (set && atomic_read(>state) != MEDIA_REQUEST_STATE_IDLE) {
+   media_request_put(req);
+   return ERR_PTR(-EBUSY);
+   }
+
+   obj = media_request_object_find(req, _ops, hdl);
+   if (obj) {
+   media_request_put(req);
+   return obj;
+   }
+
+   new_hdl = kzalloc(sizeof(*new_hdl), GFP_KERNEL);
+   if (!new_hdl) {
+   ret = -ENOMEM;
+   goto put;
+   }
+   obj = _hdl->req_obj;
+   ret = v4l2_ctrl_handler_init(new_hdl, (hdl->nr_of_buckets - 1) * 8);
+   if (!ret)
+   ret = v4l2_ctrl_request_bind(req, new_hdl, hdl);
+   if (!ret) {
+   media_request_object_get(obj);
+   media_request_put(req);
+   return obj;
+   }
+   kfree(new_hdl);
+
+put:
+   media_request_put(req);
+   return ERR_PTR(ret);
+}
+
+int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct media_device *mdev,
+struct v4l2_ext_controls *cs)
+{
+   struct media_request_object *obj = NULL;
+   int ret;
+
+   if (cs->which == V4L2_CTRL_WHICH_REQUEST_VAL) {
+   if (!mdev || cs->request_fd < 0)
+   return -EINVAL;
+   obj = v4l2_ctrls_find_req_obj(hdl, mdev, cs->request_fd, false);
+   if (IS_ERR(obj))
+   return PTR_ERR(obj);
+   hdl = container_of(obj, struct v4l2_ctrl_handler,
+  req_obj);
+   }
+
+   ret = __v4l2_g_ext_ctrls(hdl, cs);
+
+   if (obj)
+   media_request_object_put(obj);
+   return ret;
+}
 EXPORT_SYMBOL(v4l2_g_ext_ctrls);
 
 /* Helper function to get a single control */
@@ -3379,9 +3447,9 @@ static void update_from_auto_cluster(struct v4l2_ctrl 
*master)
 }
 
 /* Try or try-and-set controls */
-static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
-struct v4l2_ext_controls *cs,
-bool set)
+static int __try_set_ext_ctrls(struct v4l2_fh *fh,
+  struct v4l2_ctrl_handler *hdl,
+  struct v4l2_ext_controls *cs, bool set)
 {
struct v4l2_ctrl_helper helper[4];
struct v4l2_ctrl_helper *helpers = helper;
@@ -3494,16 +3562,45 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct 
v4l2_ctrl_handler *hdl,
return ret;
 }
 
-int 

[PATCH v14 33/36] vivid: add mc

2018-05-21 Thread Sakari Ailus
From: Hans Verkuil 

Add support for the media_device to vivid. This is a prerequisite
for request support.

Signed-off-by: Hans Verkuil 
---
 drivers/media/platform/vivid/vivid-core.c | 61 +++
 drivers/media/platform/vivid/vivid-core.h |  8 
 2 files changed, 69 insertions(+)

diff --git a/drivers/media/platform/vivid/vivid-core.c 
b/drivers/media/platform/vivid/vivid-core.c
index 82ec216f2ad82..69386b26d5dd1 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -657,6 +657,15 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
 
dev->inst = inst;
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->v4l2_dev.mdev = >mdev;
+
+   /* Initialize media device */
+   strlcpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model));
+   dev->mdev.dev = >dev;
+   media_device_init(>mdev);
+#endif
+
/* register v4l2_device */
snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name),
"%s-%03d", VIVID_MODULE_NAME, inst);
@@ -1173,6 +1182,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->lock = >mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vid_cap_pad.flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(>entity, 1, 
>vid_cap_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
 #ifdef CONFIG_VIDEO_VIVID_CEC
if (in_type_counter[HDMI]) {
struct cec_adapter *adap;
@@ -1225,6 +1241,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->lock = >mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vid_out_pad.flags = MEDIA_PAD_FL_SOURCE;
+   ret = media_entity_pads_init(>entity, 1, 
>vid_out_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
 #ifdef CONFIG_VIDEO_VIVID_CEC
for (i = 0; i < dev->num_outputs; i++) {
struct cec_adapter *adap;
@@ -1274,6 +1297,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->tvnorms = tvnorms_cap;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vbi_cap_pad.flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(>entity, 1, 
>vbi_cap_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
ret = video_register_device(vfd, VFL_TYPE_VBI, 
vbi_cap_nr[inst]);
if (ret < 0)
goto unreg_dev;
@@ -1299,6 +1329,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->tvnorms = tvnorms_out;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->vbi_out_pad.flags = MEDIA_PAD_FL_SOURCE;
+   ret = media_entity_pads_init(>entity, 1, 
>vbi_out_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
ret = video_register_device(vfd, VFL_TYPE_VBI, 
vbi_out_nr[inst]);
if (ret < 0)
goto unreg_dev;
@@ -1322,6 +1359,13 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
vfd->lock = >mutex;
video_set_drvdata(vfd, dev);
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   dev->sdr_cap_pad.flags = MEDIA_PAD_FL_SINK;
+   ret = media_entity_pads_init(>entity, 1, 
>sdr_cap_pad);
+   if (ret)
+   goto unreg_dev;
+#endif
+
ret = video_register_device(vfd, VFL_TYPE_SDR, 
sdr_cap_nr[inst]);
if (ret < 0)
goto unreg_dev;
@@ -1368,12 +1412,25 @@ static int vivid_create_instance(struct platform_device 
*pdev, int inst)
  video_device_node_name(vfd));
}
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   /* Register the media device */
+   ret = media_device_register(>mdev);
+   if (ret) {
+   dev_err(dev->mdev.dev,
+   "media device register failed (err=%d)\n", ret);
+   goto unreg_dev;
+   }
+#endif
+
/* Now that everything is fine, let's add it to device list */
vivid_devs[inst] = dev;
 
return 0;
 
 unreg_dev:
+#ifdef CONFIG_MEDIA_CONTROLLER
+   media_device_unregister(>mdev);
+#endif
video_unregister_device(>radio_tx_dev);
video_unregister_device(>radio_rx_dev);
video_unregister_device(>sdr_cap_dev);
@@ -1444,6 +1501,10 @@ static int vivid_remove(struct platform_device *pdev)
if (!dev)
continue;
 
+#ifdef CONFIG_MEDIA_CONTROLLER
+   

  1   2   >