Re: [PATCH 4/8] dma-buf: add peer2peer flag
On Sun, Mar 25, 2018 at 12:59:56PM +0200, Christian König wrote: > Add a peer2peer flag noting that the importer can deal with device > resources which are not backed by pages. > > Signed-off-by: Christian König Um strictly speaking they all should, but ttm never bothered to use the real interfaces but just hacked around the provided sg list, grabbing the underlying struct pages, then rebuilding&remapping the sg list again. The entire point of using sg lists was exactly to allow this use case of peer2peer dma (or well in general have special exporters which managed memory/IO ranges not backed by struct page). So essentially you're having a "I'm totally not broken flag" here. I think a better approach would be if we add a requires_struct_page or so, and annotate the current importers accordingly. Or we just fix them up (it is all in shared ttm code after all, I think everyone else got this right). -Daniel > --- > drivers/dma-buf/dma-buf.c | 1 + > include/linux/dma-buf.h | 4 > 2 files changed, 5 insertions(+) > > diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c > index ffaa2f9a9c2c..f420225f93c6 100644 > --- a/drivers/dma-buf/dma-buf.c > +++ b/drivers/dma-buf/dma-buf.c > @@ -565,6 +565,7 @@ struct dma_buf_attachment *dma_buf_attach(const struct > dma_buf_attach_info *info > > attach->dev = info->dev; > attach->dmabuf = dmabuf; > + attach->peer2peer = info->peer2peer; > attach->priv = info->priv; > attach->invalidate = info->invalidate; > > diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h > index 15dd8598bff1..1ef50bd9bc5b 100644 > --- a/include/linux/dma-buf.h > +++ b/include/linux/dma-buf.h > @@ -313,6 +313,7 @@ struct dma_buf { > * @dmabuf: buffer for this attachment. > * @dev: device attached to the buffer. > * @node: list of dma_buf_attachment. > + * @peer2peer: true if the importer can handle peer resources without pages. > * @priv: exporter specific attachment data. > * > * This structure holds the attachment information between the dma_buf buffer > @@ -328,6 +329,7 @@ struct dma_buf_attachment { > struct dma_buf *dmabuf; > struct device *dev; > struct list_head node; > + bool peer2peer; > void *priv; > > /** > @@ -392,6 +394,7 @@ struct dma_buf_export_info { > * @dmabuf: the exported dma_buf > * @dev: the device which wants to import the attachment > * @priv:private data of importer to this attachment > + * @peer2peer: true if the importer can handle peer resources without > pages > * @invalidate: callback to use for invalidating mappings > * > * This structure holds the information required to attach to a buffer. Used > @@ -401,6 +404,7 @@ struct dma_buf_attach_info { > struct dma_buf *dmabuf; > struct device *dev; > void *priv; > + bool peer2peer; > void (*invalidate)(struct dma_buf_attachment *attach); > }; > > -- > 2.14.1 > > ___ > dri-devel mailing list > dri-de...@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
Hi Kieran, On Wednesday, 28 March 2018 22:04:49 EEST Kieran Bingham wrote: > On 28/03/18 13:27, Kieran Bingham wrote: > > On 26/02/18 21:45, Laurent Pinchart wrote: > >> The entities in the pipeline are all started when the LIF is setup. > >> Remove the outdated comment that state otherwise. > >> > >> Signed-off-by: Laurent Pinchart > >> > > > > I'll start with the easy ones :-) > > In fact, couldn't this patch be squashed into [PATCH 01/15] in this series ? I suppose it could, I'll do so. > > Reviewed-by: Kieran Bingham > > > >> --- > >> > >> drivers/media/platform/vsp1/vsp1_drm.c | 6 +- > >> 1 file changed, 1 insertion(+), 5 deletions(-) > >> > >> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c > >> b/drivers/media/platform/vsp1/vsp1_drm.c index > >> e31fb371eaf9..a1f2ba044092 100644 > >> --- a/drivers/media/platform/vsp1/vsp1_drm.c > >> +++ b/drivers/media/platform/vsp1/vsp1_drm.c > >> @@ -221,11 +221,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned > >> int pipe_index,>> > >>return -EPIPE; > >> > >>} > >> > >> - /* > >> - * Enable the VSP1. We don't start the entities themselves right at > >> this > >> - * point as there's no plane configured yet, so we can't start > >> - * processing buffers. > >> - */ > >> + /* Enable the VSP1. */ > >> > >>ret = vsp1_device_get(vsp1); > >>if (ret < 0) > >> > >>return ret; -- Regards, Laurent Pinchart
Re: [PATCH for v3.18 00/18] Backport CVE-2017-13166 fixes to Kernel 3.18
2018년 03월 29일 13:25에 Greg KH 이(가) 쓴 글: > On Thu, Mar 29, 2018 at 08:22:08AM +0900, Inki Dae wrote: >> Really thanks for doing this. :) There would be many users who use >> Linux-3.18 for their products yet. > > For new products? They really should not be. The kernel is officially Really no. Old products would still be using Linux-3.18 kernel without kernel upgrade. For new product, most of SoC vendors will use Linux-4.x including us. Actually, we are preparing for kernel upgrade for some devices even some old devices (to Linux-4.14-LTS) and almost done. > end-of-life, but I'm keeping it alive for a short while longer just > because too many people seem to still be using it. However, they are > not actually updating the kernel in their devices, so I don't think I > will be doing many more new 3.18.y releases. > > It's a problem when people ask for support, and then don't use the > releases given to them :( > > What is keeping you on 3.18.y and not allowing you to move to a newer > kernel version? We also want to move to latest kernel version. However, there is a case that we cannot upgrade the kernel. In case that SoC vendor never share firmwares and relevant data sheets, we cannot upgrade the kernel. However, we have to resolve the security issues for users of this device. Thanks, Inki Dae > > thanks, > > greg k-h > > >
Re: [PATCH] media: v4l2-compat-ioctl32: don't oops on overlay
Hello, On Wednesday, 28 March 2018 23:16:08 EEST Sakari Ailus wrote: > On Wed, Mar 28, 2018 at 02:59:22PM -0300, Mauro Carvalho Chehab wrote: > > At put_v4l2_window32(), it tries to access kp->clips. However, > > kp points to an userspace pointer. So, it should be obtained > > > > via get_user(), otherwise it can OOPS: > > vivid-000: == END STATUS == > > BUG: unable to handle kernel paging request at fffb18e0 > > IP: [] __put_v4l2_format32+0x169/0x220 [videodev] > > PGD 3f5776067 PUD 3f576f067 PMD 3f5769067 PTE 80042548f067 > > Oops: 0001 [#1] SMP > > Modules linked in: vivid videobuf2_vmalloc videobuf2_memops > > v4l2_dv_timings videobuf2_core v4l2_common videodev media xt_CHECKSUM > > iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat > > nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack > > nf_conntrack tun bridge stp llc ebtable_filter ebtables ip6table_filter > > ip6_tables bluetooth rfkill binfmt_misc snd_hda_codec_hdmi i915 > > snd_hda_intel snd_hda_controller snd_hda_codec intel_rapl > > x86_pkg_temp_thermal snd_hwdep intel_powerclamp snd_pcm coretemp > > snd_seq_midi kvm_intel kvm snd_seq_midi_event snd_rawmidi i2c_algo_bit > > drm_kms_helper snd_seq drm crct10dif_pclmul e1000e snd_seq_device > > crc32_pclmul snd_timer ghash_clmulni_intel snd mei_me mei ptp pps_core > > soundcore lpc_ich video crc32c_intel [last unloaded: media] CPU: 2 PID: > > 28332 Comm: v4l2-compliance Not tainted 3.18.102+ #107 Hardware name: > >/NUC5i7RYB, BIOS RYBDWi35.86A.0364.2017.0511.0949 > > 05/11/2017 task: 8804293f8000 ti: 8803f564 task.ti: > > 8803f564 RIP: 0010:[] [] > > __put_v4l2_format32+0x169/0x220 [videodev] RSP: 0018:8803f5643e28 > > EFLAGS: 00010246 > > RAX: RBX: RCX: fffb1ab4 > > RDX: fffb1a68 RSI: fffb18d8 RDI: fffb1aa8 > > RBP: 8803f5643e48 R08: 0001 R09: 8803f54b0378 > > R10: R11: 0168 R12: fffb18c0 > > R13: fffb1a94 R14: fffb18c8 R15: > > FS: () GS:880456d0(0063) > > knlGS:f7100980 CS: 0010 DS: 002b ES: 002b CR0: 80050033 > > CR2: fffb18e0 CR3: 0003f552b000 CR4: 003407e0 > > > > Stack: > > fffb1a94 c0cc5640 0056 8804274f3600 > > 8803f5643ed0 c0547e16 0003 8803f5643eb0 > > 81301460 88009db44b01 880441942520 8800c0d05640 > > > > Call Trace: > > [] v4l2_compat_ioctl32+0x12d6/0x1b1d [videodev] > > [] ? file_has_perm+0x70/0xc0 > > [] compat_SyS_ioctl+0xec/0x1200 > > [] sysenter_dispatch+0x7/0x21 > > > > Code: 00 00 48 8b 80 48 c0 ff ff 48 83 e8 38 49 39 c6 0f 87 2b ff ff ff > > 49 8d 45 1c e8 a3 ce e3 c0 85 c0 0f 85 1a ff ff ff 41 8d 40 ff <4d> 8b > > 64 24 20 41 89 d5 48 8d 44 40 03 4d 8d 34 c4 eb 15 0f 1f RIP > > [] __put_v4l2_format32+0x169/0x220 [videodev] RSP > > > > CR2: fffb18e0 > > > > Tested with vivid driver on Kernel v3.18.102. > > > > Same bug happens upstream too: > > BUG: KASAN: user-memory-access in __put_v4l2_format32+0x98/0x4d0 > > [videodev] > > Read of size 8 at addr ffe48400 by task v4l2-compliance/8713 > > > > CPU: 0 PID: 8713 Comm: v4l2-compliance Not tainted 4.16.0-rc4+ #108 > > Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0364.2017.0511.0949 > > 05/11/2017> > > Call Trace: > > dump_stack+0x5c/0x7c > > kasan_report+0x164/0x380 > > ? __put_v4l2_format32+0x98/0x4d0 [videodev] > > __put_v4l2_format32+0x98/0x4d0 [videodev] > > v4l2_compat_ioctl32+0x1aec/0x27a0 [videodev] > > ? __fsnotify_inode_delete+0x20/0x20 > > ? __put_v4l2_format32+0x4d0/0x4d0 [videodev] > > compat_SyS_ioctl+0x646/0x14d0 > > ? do_ioctl+0x30/0x30 > > do_fast_syscall_32+0x191/0x3f4 > > entry_SYSENTER_compat+0x6b/0x7a > > > > == > > Disabling lock debugging due to kernel taint > > BUG: unable to handle kernel paging request at ffe48400 > > IP: __put_v4l2_format32+0x98/0x4d0 [videodev] > > PGD 3a22fb067 P4D 3a22fb067 PUD 39b6f0067 PMD 39b6f1067 PTE > > 8003256af067 Oops: 0001 [#1] SMP KASAN > > Modules linked in: vivid videobuf2_vmalloc videobuf2_dma_contig > > videobuf2_memops v4l2_tpg v4l2_dv_timings videobuf2_v4l2 > > videobuf2_common v4l2_common videodev xt_CHECKSUM iptable_mangle > > ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat > > nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack libcrc32c tun > > bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables > > bluetooth rfkill ecdh_generic binfmt_misc snd_hda_codec_hdmi intel_rapl > > x86_pkg_temp_thermal intel_powerclamp i915 coretemp snd_hda_intel > > snd_hda_codec kvm_intel snd_hwdep snd_hda_core kvm snd_pcm i
[PATCH v2] media: i2c: wm9090: replace codec to component
From: Kuninori Morimoto Now we can replace Codec to Component. Let's do it. Note: xxx_codec_xxx() -> xxx_component_xxx() .idle_bias_off = 0 -> .idle_bias_on = 1 .ignore_pmdown_time = 0 -> .use_pmdown_time = 1 - -> .endianness = 1 - -> .non_legacy_dai_naming = 1 Signed-off-by: Kuninori Morimoto --- v1 -> v2 - fixup .remove return drivers/media/i2c/tda1997x.c | 21 +++-- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/drivers/media/i2c/tda1997x.c b/drivers/media/i2c/tda1997x.c index 3021913..2dc4df5 100644 --- a/drivers/media/i2c/tda1997x.c +++ b/drivers/media/i2c/tda1997x.c @@ -2444,7 +2444,7 @@ static int tda1997x_pcm_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct tda1997x_state *state = snd_soc_dai_get_drvdata(dai); - struct snd_soc_codec *codec = dai->codec; + struct snd_soc_component *component = dai->component; struct snd_pcm_runtime *rtd = substream->runtime; int rate, err; @@ -2452,11 +2452,11 @@ static int tda1997x_pcm_startup(struct snd_pcm_substream *substream, err = snd_pcm_hw_constraint_minmax(rtd, SNDRV_PCM_HW_PARAM_RATE, rate, rate); if (err < 0) { - dev_err(codec->dev, "failed to constrain samplerate to %dHz\n", + dev_err(component->dev, "failed to constrain samplerate to %dHz\n", rate); return err; } - dev_info(codec->dev, "set samplerate constraint to %dHz\n", rate); + dev_info(component->dev, "set samplerate constraint to %dHz\n", rate); return 0; } @@ -2479,20 +2479,22 @@ static int tda1997x_pcm_startup(struct snd_pcm_substream *substream, .ops = &tda1997x_dai_ops, }; -static int tda1997x_codec_probe(struct snd_soc_codec *codec) +static int tda1997x_codec_probe(struct snd_soc_component *component) { return 0; } -static int tda1997x_codec_remove(struct snd_soc_codec *codec) +static void tda1997x_codec_remove(struct snd_soc_component *component) { - return 0; } -static struct snd_soc_codec_driver tda1997x_codec_driver = { +static struct snd_soc_component_driver tda1997x_codec_driver = { .probe = tda1997x_codec_probe, .remove = tda1997x_codec_remove, - .reg_word_size = sizeof(u16), + .idle_bias_on = 1, + .use_pmdown_time= 1, + .endianness = 1, + .non_legacy_dai_naming = 1, }; static int tda1997x_probe(struct i2c_client *client, @@ -2737,7 +2739,7 @@ static int tda1997x_probe(struct i2c_client *client, else formats = SNDRV_PCM_FMTBIT_S16_LE; tda1997x_audio_dai.capture.formats = formats; - ret = snd_soc_register_codec(&state->client->dev, + ret = devm_snd_soc_register_component(&state->client->dev, &tda1997x_codec_driver, &tda1997x_audio_dai, 1); if (ret) { @@ -2782,7 +2784,6 @@ static int tda1997x_remove(struct i2c_client *client) struct tda1997x_platform_data *pdata = &state->pdata; if (pdata->audout_format) { - snd_soc_unregister_codec(&client->dev); mutex_destroy(&state->audio_lock); } -- 1.9.1
Re: [PATCH] media: i2c: wm9090: replace codec to component
Hi Thank you for this report. I will post v2 patch, soon kbuild test robot wrote: > > [1 ] > Hi Kuninori, > > Thank you for the patch! Yet something to improve: > > [auto build test ERROR on linuxtv-media/master] > [also build test ERROR on next-20180328] > [cannot apply to v4.16-rc7] > [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/Kuninori-Morimoto/media-i2c-wm9090-replace-codec-to-component/20180329-082843 > base: git://linuxtv.org/media_tree.git master > config: i386-allmodconfig (attached as .config) > compiler: gcc-7 (Debian 7.3.0-1) 7.3.0 > reproduce: > # save the attached .config to linux build tree > make ARCH=i386 > > All errors (new ones prefixed by >>): > > >> drivers/media/i2c/tda1997x.c:2494:12: error: initialization from > >> incompatible pointer type [-Werror=incompatible-pointer-types] > .remove = tda1997x_codec_remove, >^ >drivers/media/i2c/tda1997x.c:2494:12: note: (near initialization for > 'tda1997x_codec_driver.remove') >cc1: some warnings being treated as errors > > vim +2494 drivers/media/i2c/tda1997x.c > > 9ac0038d Tim Harvey2018-02-15 2491 > b534b135 Kuninori Morimoto 2018-03-28 2492 static struct > snd_soc_component_driver tda1997x_codec_driver = { > 9ac0038d Tim Harvey2018-02-15 2493 .probe = tda1997x_codec_probe, > 9ac0038d Tim Harvey2018-02-15 @2494 .remove = tda1997x_codec_remove, > b534b135 Kuninori Morimoto 2018-03-28 2495 .idle_bias_on = 1, > b534b135 Kuninori Morimoto 2018-03-28 2496 .use_pmdown_time= 1, > b534b135 Kuninori Morimoto 2018-03-28 2497 .endianness = 1, > b534b135 Kuninori Morimoto 2018-03-28 2498 .non_legacy_dai_naming = 1, > 9ac0038d Tim Harvey2018-02-15 2499 }; > 9ac0038d Tim Harvey2018-02-15 2500 > > :: The code at line 2494 was first introduced by commit > :: 9ac0038db9a7e10fc8f425010ec98b7afc2ff621 media: i2c: Add TDA1997x HDMI > receiver driver > > :: TO: Tim Harvey > :: CC: Mauro Carvalho Chehab > > --- > 0-DAY kernel test infrastructureOpen Source Technology Center > https://lists.01.org/pipermail/kbuild-all Intel Corporation > [2 .config.gz ] >
Re: [PATCH for v3.18 00/18] Backport CVE-2017-13166 fixes to Kernel 3.18
On Thu, Mar 29, 2018 at 08:22:08AM +0900, Inki Dae wrote: > Really thanks for doing this. :) There would be many users who use > Linux-3.18 for their products yet. For new products? They really should not be. The kernel is officially end-of-life, but I'm keeping it alive for a short while longer just because too many people seem to still be using it. However, they are not actually updating the kernel in their devices, so I don't think I will be doing many more new 3.18.y releases. It's a problem when people ask for support, and then don't use the releases given to them :( What is keeping you on 3.18.y and not allowing you to move to a newer kernel version? thanks, greg k-h
cron job: media_tree daily build: WARNINGS
This message is generated daily by a cron job that builds media_tree for the kernels and architectures in the list below. Results of the daily build of media_tree: date: Thu Mar 29 05:00:13 CEST 2018 media-tree git hash:6ccd228e0cfce2a4f44558422d25c60fcb1a6710 media_build git hash: d16c7406ed6cc5fc20c87c3711741c43039275d2 v4l-utils git hash: 098e402950fd45b5a572cccfe1d103661d418417 gcc version:i686-linux-gcc (GCC) 7.3.0 sparse version: v0.5.0-3994-g45eb2282 smatch version: v0.5.0-3994-g45eb2282 host hardware: x86_64 host os:4.14.0-3-amd64 linux-git-arm-at91: OK linux-git-arm-davinci: OK linux-git-arm-multi: OK linux-git-arm-pxa: OK linux-git-arm-stm32: OK linux-git-arm64: OK linux-git-blackfin-bf561: OK linux-git-i686: OK linux-git-m32r: OK linux-git-mips: OK linux-git-powerpc64: OK linux-git-sh: OK linux-git-x86_64: OK linux-2.6.36.4-i686: WARNINGS linux-2.6.36.4-x86_64: WARNINGS linux-2.6.37.6-i686: WARNINGS linux-2.6.37.6-x86_64: WARNINGS linux-2.6.38.8-i686: WARNINGS linux-2.6.38.8-x86_64: WARNINGS linux-2.6.39.4-i686: WARNINGS linux-2.6.39.4-x86_64: WARNINGS linux-3.0.101-i686: WARNINGS linux-3.0.101-x86_64: WARNINGS linux-3.1.10-i686: WARNINGS linux-3.1.10-x86_64: WARNINGS linux-3.2.100-i686: WARNINGS linux-3.2.100-x86_64: WARNINGS linux-3.3.8-i686: WARNINGS linux-3.3.8-x86_64: WARNINGS linux-3.4.113-i686: WARNINGS linux-3.4.113-x86_64: WARNINGS linux-3.5.7-i686: WARNINGS linux-3.5.7-x86_64: WARNINGS linux-3.6.11-i686: WARNINGS linux-3.6.11-x86_64: WARNINGS linux-3.7.10-i686: WARNINGS linux-3.7.10-x86_64: WARNINGS linux-3.8.13-i686: WARNINGS linux-3.8.13-x86_64: WARNINGS linux-3.9.11-i686: WARNINGS linux-3.9.11-x86_64: WARNINGS linux-3.10.108-i686: WARNINGS linux-3.10.108-x86_64: WARNINGS linux-3.11.10-i686: WARNINGS linux-3.11.10-x86_64: WARNINGS linux-3.12.74-i686: WARNINGS linux-3.12.74-x86_64: WARNINGS linux-3.13.11-i686: WARNINGS linux-3.13.11-x86_64: WARNINGS linux-3.14.79-i686: WARNINGS linux-3.14.79-x86_64: WARNINGS linux-3.15.10-i686: WARNINGS linux-3.15.10-x86_64: WARNINGS linux-3.16.55-i686: WARNINGS linux-3.16.55-x86_64: WARNINGS linux-3.17.8-i686: WARNINGS linux-3.17.8-x86_64: WARNINGS linux-3.18.100-i686: WARNINGS linux-3.18.100-x86_64: WARNINGS linux-3.19.8-i686: WARNINGS linux-3.19.8-x86_64: WARNINGS linux-4.0.9-i686: WARNINGS linux-4.0.9-x86_64: WARNINGS linux-4.1.50-i686: WARNINGS linux-4.1.50-x86_64: WARNINGS linux-4.2.8-i686: WARNINGS linux-4.2.8-x86_64: WARNINGS linux-4.3.6-i686: WARNINGS linux-4.3.6-x86_64: WARNINGS linux-4.4.99-i686: OK linux-4.4.99-x86_64: OK linux-4.5.7-i686: WARNINGS linux-4.5.7-x86_64: OK linux-4.6.7-i686: OK linux-4.6.7-x86_64: OK linux-4.7.10-i686: OK linux-4.7.10-x86_64: WARNINGS linux-4.8.17-i686: OK linux-4.8.17-x86_64: OK linux-4.9.87-i686: OK linux-4.9.87-x86_64: OK linux-4.10.17-i686: OK linux-4.10.17-x86_64: OK linux-4.11.12-i686: OK linux-4.11.12-x86_64: OK linux-4.12.14-i686: OK linux-4.12.14-x86_64: OK linux-4.13.16-i686: OK linux-4.13.16-x86_64: OK linux-4.14.27-i686: OK linux-4.14.27-x86_64: OK linux-4.15.10-i686: OK linux-4.15.10-x86_64: OK linux-4.16-rc5-i686: OK linux-4.16-rc5-x86_64: OK apps: WARNINGS spec-git: OK sparse: WARNINGS smatch: OK Detailed results are available here: http://www.xs4all.nl/~hverkuil/logs/Thursday.log Full logs are available here: http://www.xs4all.nl/~hverkuil/logs/Thursday.tar.bz2 The Media Infrastructure API from this daily build is here: http://www.xs4all.nl/~hverkuil/spec/index.html
Re: [PATCH] media: i2c: wm9090: replace codec to component
Hi Kuninori, Thank you for the patch! Yet something to improve: [auto build test ERROR on linuxtv-media/master] [also build test ERROR on next-20180328] [cannot apply to v4.16-rc7] [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/Kuninori-Morimoto/media-i2c-wm9090-replace-codec-to-component/20180329-082843 base: git://linuxtv.org/media_tree.git master config: i386-allmodconfig (attached as .config) compiler: gcc-7 (Debian 7.3.0-1) 7.3.0 reproduce: # save the attached .config to linux build tree make ARCH=i386 All errors (new ones prefixed by >>): >> drivers/media/i2c/tda1997x.c:2494:12: error: initialization from >> incompatible pointer type [-Werror=incompatible-pointer-types] .remove = tda1997x_codec_remove, ^ drivers/media/i2c/tda1997x.c:2494:12: note: (near initialization for 'tda1997x_codec_driver.remove') cc1: some warnings being treated as errors vim +2494 drivers/media/i2c/tda1997x.c 9ac0038d Tim Harvey2018-02-15 2491 b534b135 Kuninori Morimoto 2018-03-28 2492 static struct snd_soc_component_driver tda1997x_codec_driver = { 9ac0038d Tim Harvey2018-02-15 2493 .probe = tda1997x_codec_probe, 9ac0038d Tim Harvey2018-02-15 @2494 .remove = tda1997x_codec_remove, b534b135 Kuninori Morimoto 2018-03-28 2495 .idle_bias_on = 1, b534b135 Kuninori Morimoto 2018-03-28 2496 .use_pmdown_time= 1, b534b135 Kuninori Morimoto 2018-03-28 2497 .endianness = 1, b534b135 Kuninori Morimoto 2018-03-28 2498 .non_legacy_dai_naming = 1, 9ac0038d Tim Harvey2018-02-15 2499 }; 9ac0038d Tim Harvey2018-02-15 2500 :: The code at line 2494 was first introduced by commit :: 9ac0038db9a7e10fc8f425010ec98b7afc2ff621 media: i2c: Add TDA1997x HDMI receiver driver :: TO: Tim Harvey :: CC: Mauro Carvalho Chehab --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
Re: [linux-sunxi] [PATCH v9 0/2] Initial Allwinner V3s CSI Support
Hi, On Wed, 28 Mar 2018 16:29:47 -0700 Martin Kelly wrote: > On 03/05/2018 05:51 PM, Yong Deng wrote: > > This patchset add initial support for Allwinner V3s CSI. > > > > Allwinner V3s SoC features two CSI module. CSI0 is used for MIPI CSI-2 > > interface and CSI1 is used for parallel interface. This is not > > documented in datasheet but by test and guess. > > > > This patchset implement a v4l2 framework driver and add a binding > > documentation for it. > > > > Currently, the driver only support the parallel interface. And has been > > tested with a BT1120 signal which generating from FPGA. The following > > fetures are not support with this patchset: > >- ISP > >- MIPI-CSI2 > >- Master clock for camera sensor > >- Power regulator for the front end IC > > > > Hi Yong, > > Thanks so much, this driver is a great contribution! > > Unfortunately the board I'm working with (nanopi neo air) uses the MIPI > CSI-2 CSI0 interface rather than CSI1. Do you have any plans to support > the MIPI CSI-2 interface at some point? If not, do you know the scope of > what would be involved? AFAIK, there is no document about MIPI CSI-2. You can take a look at the source code in BSP: https://github.com/friendlyarm/h3_lichee/tree/master/linux-3.4/drivers/media/video/sunxi-vfe/mipi_csi And try to port it to mainline. Thanks, Yong
Re: [linux-sunxi] [PATCH v9 0/2] Initial Allwinner V3s CSI Support
On 03/05/2018 05:51 PM, Yong Deng wrote: This patchset add initial support for Allwinner V3s CSI. Allwinner V3s SoC features two CSI module. CSI0 is used for MIPI CSI-2 interface and CSI1 is used for parallel interface. This is not documented in datasheet but by test and guess. This patchset implement a v4l2 framework driver and add a binding documentation for it. Currently, the driver only support the parallel interface. And has been tested with a BT1120 signal which generating from FPGA. The following fetures are not support with this patchset: - ISP - MIPI-CSI2 - Master clock for camera sensor - Power regulator for the front end IC Hi Yong, Thanks so much, this driver is a great contribution! Unfortunately the board I'm working with (nanopi neo air) uses the MIPI CSI-2 CSI0 interface rather than CSI1. Do you have any plans to support the MIPI CSI-2 interface at some point? If not, do you know the scope of what would be involved?
Re: [PATCH for v3.18 00/18] Backport CVE-2017-13166 fixes to Kernel 3.18
Hi Mauro, 2018년 03월 29일 03:12에 Mauro Carvalho Chehab 이(가) 쓴 글: > Hi Greg, > > Those are the backports meant to solve CVE-2017-13166 on Kernel 3.18. > > It contains two v4l2-ctrls fixes that are required to avoid crashes > at the test application. > > I wrote two patches myself for Kernel 3.18 in order to solve some > issues specific for Kernel 3.18 with aren't needed upstream. > one is actually a one-line change backport. The other one makes > sure that both 32-bits and 64-bits version of some ioctl calls > will return the same value for a reserved field. > > I noticed an extra bug while testing it, but the bug also hits upstream, > and should be backported all the way down all stable/LTS versions. > So, I'll send it the usual way, after merging upsream. Really thanks for doing this. :) There would be many users who use Linux-3.18 for their products yet. Thanks, Inki Dae > > Regards, > Mauro > > > Daniel Mentz (2): > media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha > media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic > > Hans Verkuil (12): > media: v4l2-ioctl.c: don't copy back the result for -ENOTTY > media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF > media: v4l2-compat-ioctl32.c: fix the indentation > media: v4l2-compat-ioctl32.c: move 'helper' functions to > __get/put_v4l2_format32 > media: v4l2-compat-ioctl32.c: avoid sizeof(type) > media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32 > media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer > media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs > media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32 > media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type > media: v4l2-compat-ioctl32.c: don't copy back the result for certain > errors > media: v4l2-ctrls: fix sparse warning > > Mauro Carvalho Chehab (2): > media: v4l2-compat-ioctl32: use compat_u64 for video standard > media: v4l2-compat-ioctl32: initialize a reserved field > > Ricardo Ribalda (2): > vb2: V4L2_BUF_FLAG_DONE is set after DQBUF > media: media/v4l2-ctrls: volatiles should not generate CH_VALUE > > drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1020 > +++-- > drivers/media/v4l2-core/v4l2-ctrls.c | 96 ++- > drivers/media/v4l2-core/v4l2-ioctl.c |5 +- > drivers/media/v4l2-core/videobuf2-core.c |5 + > 4 files changed, 691 insertions(+), 435 deletions(-) >
Re: [PATCH v4 1/5] dvb-frontends/dvb-pll: add i2c driver support
On 03/28/2018 08:00 PM, tsk...@gmail.com wrote: From: Akihiro Tsukada registers the module as an i2c driver, but keeps dvb_pll_attach() untouched for compatibility. Signed-off-by: Akihiro Tsukada --- Changes since v3: - use standard i2c_device_id instead of dvb_pll_config drivers/media/dvb-frontends/dvb-pll.c | 67 +++ drivers/media/dvb-frontends/dvb-pll.h | 24 + 2 files changed, 91 insertions(+) diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index 5553b89b804..e2a93aae04f 100644 --- a/drivers/media/dvb-frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c @@ -827,6 +827,73 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, } EXPORT_SYMBOL(dvb_pll_attach); + +static int +dvb_pll_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct dvb_pll_config *cfg; + struct dvb_frontend *fe; + unsigned int desc_id; + + cfg = client->dev.platform_data; + fe = cfg->fe; + i2c_set_clientdata(client, fe); + desc_id = (unsigned int) id->driver_data; + + if (!dvb_pll_attach(fe, client->addr, client->adapter, desc_id)) + return -ENOMEM; + + dev_info(&client->dev, "DVB Simple Tuner attached.\n"); Print used pll chip name here + return 0; +} + +static int dvb_pll_remove(struct i2c_client *client) +{ + struct dvb_frontend *fe; + + fe = i2c_get_clientdata(client); + dvb_pll_release(fe); + return 0; +} + + +static const struct i2c_device_id dvb_pll_id[] = { + {DVB_PLL_THOMSON_DTT7579_NAME,DVB_PLL_THOMSON_DTT7579}, + {DVB_PLL_THOMSON_DTT759X_NAME,DVB_PLL_THOMSON_DTT759X}, + {DVB_PLL_LG_Z201_NAME,DVB_PLL_LG_Z201}, + {DVB_PLL_UNKNOWN_1_NAME, DVB_PLL_UNKNOWN_1}, + {DVB_PLL_TUA6010XS_NAME, DVB_PLL_TUA6010XS}, + {DVB_PLL_ENV57H1XD5_NAME, DVB_PLL_ENV57H1XD5}, + {DVB_PLL_TUA6034_NAME,DVB_PLL_TUA6034}, + {DVB_PLL_TDA665X_NAME,DVB_PLL_TDA665X}, + {DVB_PLL_TDED4_NAME, DVB_PLL_TDED4}, + {DVB_PLL_TDHU2_NAME, DVB_PLL_TDHU2}, + {DVB_PLL_SAMSUNG_TBMV_NAME, DVB_PLL_SAMSUNG_TBMV}, + {DVB_PLL_PHILIPS_SD1878_TDA8261_NAME, DVB_PLL_PHILIPS_SD1878_TDA8261}, + {DVB_PLL_OPERA1_NAME, DVB_PLL_OPERA1}, + {DVB_PLL_SAMSUNG_DTOS403IH102A_NAME, DVB_PLL_SAMSUNG_DTOS403IH102A}, + {DVB_PLL_SAMSUNG_TDTC9251DH0_NAME,DVB_PLL_SAMSUNG_TDTC9251DH0}, + {DVB_PLL_SAMSUNG_TBDU18132_NAME, DVB_PLL_SAMSUNG_TBDU18132}, + {DVB_PLL_SAMSUNG_TBMU24112_NAME, DVB_PLL_SAMSUNG_TBMU24112}, + {DVB_PLL_TDEE4_NAME, DVB_PLL_TDEE4}, + {DVB_PLL_THOMSON_DTT7520X_NAME, DVB_PLL_THOMSON_DTT7520X}, + {} +}; + + +MODULE_DEVICE_TABLE(i2c, dvb_pll_id); + +static struct i2c_driver dvb_pll_driver = { + .driver = { + .name = "dvb_pll", + }, + .probe= dvb_pll_probe, + .remove = dvb_pll_remove, + .id_table = dvb_pll_id, +}; + +module_i2c_driver(dvb_pll_driver); + MODULE_DESCRIPTION("dvb pll library"); MODULE_AUTHOR("Gerd Knorr"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dvb-pll.h b/drivers/media/dvb-frontends/dvb-pll.h index ca885e71d2f..e96994bf668 100644 --- a/drivers/media/dvb-frontends/dvb-pll.h +++ b/drivers/media/dvb-frontends/dvb-pll.h @@ -30,6 +30,30 @@ #define DVB_PLL_TDEE418 #define DVB_PLL_THOMSON_DTT7520X 19 +#define DVB_PLL_THOMSON_DTT7579_NAME "dtt7579" +#define DVB_PLL_THOMSON_DTT759X_NAME"dtt759x" +#define DVB_PLL_LG_Z201_NAME"z201" +#define DVB_PLL_UNKNOWN_1_NAME "unknown_1" +#define DVB_PLL_TUA6010XS_NAME "tua6010xs" +#define DVB_PLL_ENV57H1XD5_NAME "env57h1xd5" +#define DVB_PLL_TUA6034_NAME"tua6034" +#define DVB_PLL_TDA665X_NAME"tda665x" +#define DVB_PLL_TDED4_NAME "tded4" +#define DVB_PLL_TDHU2_NAME "tdhu2" +#define DVB_PLL_SAMSUNG_TBMV_NAME "tbmv" +#define DVB_PLL_PHILIPS_SD1878_TDA8261_NAME "sd1878_tda8261" +#define DVB_PLL_OPERA1_NAME "opera1" +#define DVB_PLL_SAMSUNG_DTOS403IH102A_NAME "dtos403ih102a" +#define DVB_PLL_SAMSUNG_TDTC9251DH0_NAME"tdtc9251dh0" +#define DVB_PLL_SAMSUNG_TBDU18132_NAME "tbdu18132" +#define DVB_PLL_SAMSUNG_TBMU24112_NAME "tbmu24112" +#define DVB_PLL_TDEE4_NAME "tdee4" +#define DVB_PLL_THOMSON_DTT7520X_NAME "dtt7520x" Defining these names like that does not give any value. IMHO better to just add those chip names directly to chip id table. + +struct dvb_pll_config { + struct dvb_frontend *fe; +}; + #if IS_REACHABLE(CONFIG_DVB_PLL) /** * Attach a dvb-pll to the
Re: [PATCH v4] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861
On 03/28/2018 03:37 PM, Akihiro TSUKADA wrote: Hi, thanks for the comment. You should implement i2c adapter to demod driver and not add such glue to that USB-bridge. I mean that "relayed" stuff, i2c communication to tuner via demod. I2C-mux may not work I think as there is no gate-style multiplexing so you probably need plain i2c adapter. There is few examples already on some demod drivers. I am afraid that the glue is actually necessary. host - USB -> gl861 - I2C(1) -> tc90522 (addr:X) \- I2C(2) -> tua6034 (addr:Y) To send an i2c read message to tua6034, one has to issue two transactions: 1. write via I2C(1) to addr:X, [ reg:0xfe, val: Y ] 2. read via I2C(1) from addr:X, [ out_data0, out_data1, ] The problem is that the transaction 1 is (somehow) implemented with the different USB request than the other i2c transactions on I2C(1). (this is confirmed by a packet capture on Windows box). Although tc90522 already creats the i2c adapter for I2C(2), tc90522 cannot know/control the USB implementation of I2C(1), only the bridge driver can do this. I simply cannot see why it cannot work. Just add i2c adapter and suitable logic there. Transaction on your example is simply and there is no problem to implement that kind of logic to demod i2c adapter. If gl861 driver i2c adapter logic is broken it can be fixed easily too. It seems to support only i2c writes with len 1 and 2 bytes, but fixing it should be easy if you has some sniffs. Antti -- http://palosaari.fi/
Re: [PATCH] media: v4l2-compat-ioctl32: don't oops on overlay
Hi Mauro, On Wed, Mar 28, 2018 at 02:59:22PM -0300, Mauro Carvalho Chehab wrote: > At put_v4l2_window32(), it tries to access kp->clips. However, > kp points to an userspace pointer. So, it should be obtained > via get_user(), otherwise it can OOPS: > > vivid-000: == END STATUS == > BUG: unable to handle kernel paging request at fffb18e0 > IP: [] __put_v4l2_format32+0x169/0x220 [videodev] > PGD 3f5776067 PUD 3f576f067 PMD 3f5769067 PTE 80042548f067 > Oops: 0001 [#1] SMP > Modules linked in: vivid videobuf2_vmalloc videobuf2_memops v4l2_dv_timings > videobuf2_core v4l2_common videodev media xt_CHECKSUM iptable_mangle > ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat > nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack tun bridge stp llc > ebtable_filter ebtables ip6table_filter ip6_tables bluetooth rfkill > binfmt_misc snd_hda_codec_hdmi i915 snd_hda_intel snd_hda_controller > snd_hda_codec intel_rapl x86_pkg_temp_thermal snd_hwdep intel_powerclamp > snd_pcm coretemp snd_seq_midi kvm_intel kvm snd_seq_midi_event snd_rawmidi > i2c_algo_bit drm_kms_helper snd_seq drm crct10dif_pclmul e1000e > snd_seq_device crc32_pclmul snd_timer ghash_clmulni_intel snd mei_me mei ptp > pps_core soundcore lpc_ich video crc32c_intel [last unloaded: media] > CPU: 2 PID: 28332 Comm: v4l2-compliance Not tainted 3.18.102+ #107 > Hardware name: /NUC5i7RYB, BIOS > RYBDWi35.86A.0364.2017.0511.0949 05/11/2017 > task: 8804293f8000 ti: 8803f564 task.ti: 8803f564 > RIP: 0010:[] [] > __put_v4l2_format32+0x169/0x220 [videodev] > RSP: 0018:8803f5643e28 EFLAGS: 00010246 > RAX: RBX: RCX: fffb1ab4 > RDX: fffb1a68 RSI: fffb18d8 RDI: fffb1aa8 > RBP: 8803f5643e48 R08: 0001 R09: 8803f54b0378 > R10: R11: 0168 R12: fffb18c0 > R13: fffb1a94 R14: fffb18c8 R15: > FS: () GS:880456d0(0063) knlGS:f7100980 > CS: 0010 DS: 002b ES: 002b CR0: 80050033 > CR2: fffb18e0 CR3: 0003f552b000 CR4: 003407e0 > Stack: > fffb1a94 c0cc5640 0056 8804274f3600 > 8803f5643ed0 c0547e16 0003 8803f5643eb0 > 81301460 88009db44b01 880441942520 8800c0d05640 > Call Trace: > [] v4l2_compat_ioctl32+0x12d6/0x1b1d [videodev] > [] ? file_has_perm+0x70/0xc0 > [] compat_SyS_ioctl+0xec/0x1200 > [] sysenter_dispatch+0x7/0x21 > Code: 00 00 48 8b 80 48 c0 ff ff 48 83 e8 38 49 39 c6 0f 87 2b ff ff ff 49 > 8d 45 1c e8 a3 ce e3 c0 85 c0 0f 85 1a ff ff ff 41 8d 40 ff <4d> 8b 64 24 20 > 41 89 d5 48 8d 44 40 03 4d 8d 34 c4 eb 15 0f 1f > RIP [] __put_v4l2_format32+0x169/0x220 [videodev] > RSP > CR2: fffb18e0 > > Tested with vivid driver on Kernel v3.18.102. > > Same bug happens upstream too: > > BUG: KASAN: user-memory-access in __put_v4l2_format32+0x98/0x4d0 [videodev] > Read of size 8 at addr ffe48400 by task v4l2-compliance/8713 > > CPU: 0 PID: 8713 Comm: v4l2-compliance Not tainted 4.16.0-rc4+ #108 > Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0364.2017.0511.0949 05/11/2017 > Call Trace: > dump_stack+0x5c/0x7c > kasan_report+0x164/0x380 > ? __put_v4l2_format32+0x98/0x4d0 [videodev] > __put_v4l2_format32+0x98/0x4d0 [videodev] > v4l2_compat_ioctl32+0x1aec/0x27a0 [videodev] > ? __fsnotify_inode_delete+0x20/0x20 > ? __put_v4l2_format32+0x4d0/0x4d0 [videodev] > compat_SyS_ioctl+0x646/0x14d0 > ? do_ioctl+0x30/0x30 > do_fast_syscall_32+0x191/0x3f4 > entry_SYSENTER_compat+0x6b/0x7a > == > Disabling lock debugging due to kernel taint > BUG: unable to handle kernel paging request at ffe48400 > IP: __put_v4l2_format32+0x98/0x4d0 [videodev] > PGD 3a22fb067 P4D 3a22fb067 PUD 39b6f0067 PMD 39b6f1067 PTE 8003256af067 > Oops: 0001 [#1] SMP KASAN > Modules linked in: vivid videobuf2_vmalloc videobuf2_dma_contig > videobuf2_memops v4l2_tpg v4l2_dv_timings videobuf2_v4l2 videobuf2_common > v4l2_common videodev xt_CHECKSUM iptable_mangle ipt_MASQUERADE > nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 > nf_defrag_ipv4 xt_conntrack nf_conntrack libcrc32c tun bridge stp llc > ebtable_filter ebtables ip6table_filter ip6_tables bluetooth rfkill > ecdh_generic binfmt_misc snd_hda_codec_hdmi intel_rapl x86_pkg_temp_thermal > intel_powerclamp i915 coretemp snd_hda_intel snd_hda_codec kvm_intel > snd_hwdep snd_hda_core kvm snd_pcm irqbypass crct10dif_pclmul crc32_pclmul > snd_seq_midi ghash_clmulni_intel snd_seq_midi_event i2c_algo_bit intel_cstate > snd_rawmidi intel_uncore snd_seq drm_kms_helper e1000e snd_seq_device > snd_timer intel_rapl_perf > drm ptp snd mei_me mei lpc_ich pps_core so
Re: [PATCH 2/8] PCI: Add pci_find_common_upstream_dev()
On 28/03/18 01:44 PM, Christian König wrote: > Well, isn't that exactly what dma_map_resource() is good for? As far as > I can see it makes sure IOMMU is aware of the access route and > translates a CPU address into a PCI Bus address. > I'm using that with the AMD IOMMU driver and at least there it works > perfectly fine. Yes, it would be nice, but no arch has implemented this yet. We are just lucky in the x86 case because that arch is simple and doesn't need to do anything for P2P (partially due to the Bus and CPU addresses being the same). But in the general case, you can't rely on it. >>> Yeah, but not for ours. See if you want to do real peer 2 peer you need >>> to keep both the operation as well as the direction into account. >> Not sure what you are saying here... I'm pretty sure we are doing "real" >> peer 2 peer... >> >>> For example when you can do writes between A and B that doesn't mean >>> that writes between B and A work. And reads are generally less likely to >>> work than writes. etc... >> If both devices are behind a switch then the PCI spec guarantees that A >> can both read and write B and vice versa. > > Sorry to say that, but I know a whole bunch of PCI devices which > horrible ignores that. Can you elaborate? As far as the device is concerned it shouldn't know whether a request comes from a peer or from the host. If it does do crazy stuff like that it's well out of spec. It's up to the switch (or root complex if good support exists) to route the request to the device and it's the root complex that tends to be what drops the load requests which causes the asymmetries. Logan
Re: [PATCH 2/8] PCI: Add pci_find_common_upstream_dev()
Am 28.03.2018 um 20:57 schrieb Logan Gunthorpe: On 28/03/18 12:28 PM, Christian König wrote: I'm just using amdgpu as blueprint because I'm the co-maintainer of it and know it mostly inside out. Ah, I see. The resource addresses are translated using dma_map_resource(). As far as I know that should be sufficient to offload all the architecture specific stuff to the DMA subsystem. It's not. The dma_map infrastructure currently has no concept of peer-to-peer mappings and is designed for system memory only. No architecture I'm aware of will translate PCI CPU addresses into PCI Bus addresses which is necessary for any transfer that doesn't go through the root complex (though on arches like x86 the CPU and Bus address happen to be the same). There's a lot of people that would like to see this change but it's likely going to be a long road before it does. Well, isn't that exactly what dma_map_resource() is good for? As far as I can see it makes sure IOMMU is aware of the access route and translates a CPU address into a PCI Bus address. Furthermore, one of the reasons our patch-set avoids going through the root complex at all is that IOMMU drivers will need to be made aware that it is operating on P2P memory and do arch-specific things accordingly. There will also need to be flags that indicate whether a given IOMMU driver supports this. None of this work is done or easy. I'm using that with the AMD IOMMU driver and at least there it works perfectly fine. Yeah, but not for ours. See if you want to do real peer 2 peer you need to keep both the operation as well as the direction into account. Not sure what you are saying here... I'm pretty sure we are doing "real" peer 2 peer... For example when you can do writes between A and B that doesn't mean that writes between B and A work. And reads are generally less likely to work than writes. etc... If both devices are behind a switch then the PCI spec guarantees that A can both read and write B and vice versa. Sorry to say that, but I know a whole bunch of PCI devices which horrible ignores that. For example all AMD APUs fall under that category... Only once you involve root complexes do you have this problem. Ie. you have unknown support which may be no support, or partial support (stores but not loads); or sometimes bad performance; or a combination of both... and you need some way to figure out all this mess and that is hard. Whoever tries to implement a white list will have to sort all this out. Yes, exactly and unfortunately it looks like I'm the poor guy who needs to do this :) Regards, Christian. Logan ___ amd-gfx mailing list amd-...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
Re: [PATCH 02/15] v4l: vsp1: Remove outdated comment
On 28/03/18 13:27, Kieran Bingham wrote: > Hi Laurent, > > Thank you for the patch. > > On 26/02/18 21:45, Laurent Pinchart wrote: >> The entities in the pipeline are all started when the LIF is setup. >> Remove the outdated comment that state otherwise. >> >> Signed-off-by: Laurent Pinchart > > I'll start with the easy ones :-) In fact, couldn't this patch be squashed into [PATCH 01/15] in this series ? -- Kieran > Reviewed-by: Kieran Bingham > >> --- >> drivers/media/platform/vsp1/vsp1_drm.c | 6 +- >> 1 file changed, 1 insertion(+), 5 deletions(-) >> >> diff --git a/drivers/media/platform/vsp1/vsp1_drm.c >> b/drivers/media/platform/vsp1/vsp1_drm.c >> index e31fb371eaf9..a1f2ba044092 100644 >> --- a/drivers/media/platform/vsp1/vsp1_drm.c >> +++ b/drivers/media/platform/vsp1/vsp1_drm.c >> @@ -221,11 +221,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int >> pipe_index, >> return -EPIPE; >> } >> >> -/* >> - * Enable the VSP1. We don't start the entities themselves right at this >> - * point as there's no plane configured yet, so we can't start >> - * processing buffers. >> - */ >> +/* Enable the VSP1. */ >> ret = vsp1_device_get(vsp1); >> if (ret < 0) >> return ret; >>
Re: [PATCH 08/15] v4l: vsp1: Setup BRU at atomic commit time
Hi Laurent, On 26/02/18 21:45, Laurent Pinchart wrote: > To implement fully dynamic plane assignment to pipelines, we need to > reassign the BRU and BRS to the DRM pipelines in the atomic commit > handler. In preparation for this setup factor out the BRU source pad > code and call it both at LIF setup and atomic commit time. > > Signed-off-by: Laurent Pinchart Oops .. skipped one. But this looks ok to me. Reviewed-by: Kieran Bingham > --- > drivers/media/platform/vsp1/vsp1_drm.c | 56 > +- > drivers/media/platform/vsp1/vsp1_drm.h | 5 +++ > 2 files changed, 60 insertions(+), 1 deletion(-) > > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c > b/drivers/media/platform/vsp1/vsp1_drm.c > index 7bf697ba7969..6ad8aa6c8138 100644 > --- a/drivers/media/platform/vsp1/vsp1_drm.c > +++ b/drivers/media/platform/vsp1/vsp1_drm.c > @@ -148,12 +148,51 @@ static int vsp1_du_pipeline_setup_rpf(struct > vsp1_device *vsp1, > return 0; > } > > +/* Setup the BRU source pad. */ > +static int vsp1_du_pipeline_setup_bru(struct vsp1_device *vsp1, > + struct vsp1_pipeline *pipe) > +{ > + struct vsp1_drm_pipeline *drm_pipe = to_vsp1_drm_pipeline(pipe); > + struct v4l2_subdev_format format = { > + .which = V4L2_SUBDEV_FORMAT_ACTIVE, > + }; > + int ret; > + > + /* > + * Configure the format on the BRU source and verify that it matches the > + * requested format. We don't set the media bus code as it is configured > + * on the BRU sink pad 0 and propagated inside the entity, not on the > + * source pad. > + */ > + format.pad = pipe->bru->source_pad; > + format.format.width = drm_pipe->width; > + format.format.height = drm_pipe->height; > + format.format.field = V4L2_FIELD_NONE; > + > + ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL, > +&format); > + if (ret < 0) > + return ret; > + > + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n", > + __func__, format.format.width, format.format.height, > + format.format.code, BRU_NAME(pipe->bru), pipe->bru->source_pad); > + > + if (format.format.width != drm_pipe->width || > + format.format.height != drm_pipe->height) { > + dev_dbg(vsp1->dev, "%s: format mismatch\n", __func__); > + return -EPIPE; > + } > + > + return 0; > +} > + > static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf) > { > return vsp1->drm->inputs[rpf->entity.index].zpos; > } > > -/* Setup the input side of the pipeline (RPFs and BRU sink pads). */ > +/* Setup the input side of the pipeline (RPFs and BRU). */ > static int vsp1_du_pipeline_setup_input(struct vsp1_device *vsp1, > struct vsp1_pipeline *pipe) > { > @@ -191,6 +230,18 @@ static int vsp1_du_pipeline_setup_input(struct > vsp1_device *vsp1, > inputs[j] = rpf; > } > > + /* > + * Setup the BRU. This must be done before setting up the RPF input > + * pipelines as the BRU sink compose rectangles depend on the BRU source > + * format. > + */ > + ret = vsp1_du_pipeline_setup_bru(vsp1, pipe); > + if (ret < 0) { > + dev_err(vsp1->dev, "%s: failed to setup %s source\n", __func__, > + BRU_NAME(pipe->bru)); > + return ret; > + } > + > /* Setup the RPF input pipeline for every enabled input. */ > for (i = 0; i < pipe->bru->source_pad; ++i) { > struct vsp1_rwpf *rpf = inputs[i]; > @@ -355,6 +406,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int > pipe_index, > return 0; > } > > + drm_pipe->width = cfg->width; > + drm_pipe->height = cfg->height; > + > dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n", > __func__, pipe_index, cfg->width, cfg->height); > > diff --git a/drivers/media/platform/vsp1/vsp1_drm.h > b/drivers/media/platform/vsp1/vsp1_drm.h > index 9aa19325cbe9..c8dd75ba01f6 100644 > --- a/drivers/media/platform/vsp1/vsp1_drm.h > +++ b/drivers/media/platform/vsp1/vsp1_drm.h > @@ -20,12 +20,17 @@ > /** > * vsp1_drm_pipeline - State for the API exposed to the DRM driver > * @pipe: the VSP1 pipeline used for display > + * @width: output display width > + * @height: output display height > * @du_complete: frame completion callback for the DU driver (optional) > * @du_private: data to be passed to the du_complete callback > */ > struct vsp1_drm_pipeline { > struct vsp1_pipeline pipe; > > + unsigned int width; > + unsigned int height; > + > /* Frame synchronisation */ > void (*du_complete)(void *, bool); > void *du_private; >
Re: [PATCH 2/8] PCI: Add pci_find_common_upstream_dev()
On 28/03/18 12:28 PM, Christian König wrote: > I'm just using amdgpu as blueprint because I'm the co-maintainer of it > and know it mostly inside out. Ah, I see. > The resource addresses are translated using dma_map_resource(). As far > as I know that should be sufficient to offload all the architecture > specific stuff to the DMA subsystem. It's not. The dma_map infrastructure currently has no concept of peer-to-peer mappings and is designed for system memory only. No architecture I'm aware of will translate PCI CPU addresses into PCI Bus addresses which is necessary for any transfer that doesn't go through the root complex (though on arches like x86 the CPU and Bus address happen to be the same). There's a lot of people that would like to see this change but it's likely going to be a long road before it does. Furthermore, one of the reasons our patch-set avoids going through the root complex at all is that IOMMU drivers will need to be made aware that it is operating on P2P memory and do arch-specific things accordingly. There will also need to be flags that indicate whether a given IOMMU driver supports this. None of this work is done or easy. > Yeah, but not for ours. See if you want to do real peer 2 peer you need > to keep both the operation as well as the direction into account. Not sure what you are saying here... I'm pretty sure we are doing "real" peer 2 peer... > For example when you can do writes between A and B that doesn't mean > that writes between B and A work. And reads are generally less likely to > work than writes. etc... If both devices are behind a switch then the PCI spec guarantees that A can both read and write B and vice versa. Only once you involve root complexes do you have this problem. Ie. you have unknown support which may be no support, or partial support (stores but not loads); or sometimes bad performance; or a combination of both... and you need some way to figure out all this mess and that is hard. Whoever tries to implement a white list will have to sort all this out. Logan
Re: [PATCH 0/3] Improve latency of IR decoding
Hi Sean, On Sat, Mar 24, 2018 at 02:50:42PM +, Sean Young wrote: > The current IR decoding is much too slow. Many IR protocols rely on > a trailing space for decoding (e.g. rc-6 needs to know when the bits > end). The trailing space is generated by the IR timeout, and if this > is longer than required, keys can be perceived as sticky and slugish. > > The other issue the keyup timer. IR has no concept of a keyup message, > this is implied by the absence of IR. So, minimising the timeout for > this further improves the handling. > > With these patches in place, using IR with the builtin decoders is much > improved and feels very snappy. thanks a lot for the patches! I didn't have much time to test yet, but quick checks on Amlogic/meson-ir (kernel 4.16-rc7 + media tree + your patches) and Raspberry Pi (RPi foundation kernel 4.14 + my backport of your patches) look really promising. I found one issue, though, in ir-sharp-decoder.c max_space must be set to SHARP_ECHO_SPACE - otherwise we get a timeout between the normal and inverted message part and decoding fails. One thing I'm wondering is if the keyup timer marging might be too tight now. Basically we have just the fixed 10ms marging from idle timeout. The repeat periods of the protocols are rather accurate/strict, so (programmable) remotes not sticking to the official timing might cause repeated keyup/down events if they are repeating a tad to slow. I'm not sure if this could be an issue, but maybe we should add a safety margin to the repeat periods as well? For example 10 or 20 percent of the specced repeat periods. What do you think? To get some more test coverage I've asked my colleague to include my backport patch in the LibreELEC testbuilds for x86 and RPi. We've got some 500 regular users of these so if something's not working we should find out soon. I just hope I didn't mess up the backport... Here's the link to my 4.14 patch: https://github.com/HiassofT/LibreELEC.tv/blob/le9-ir-latency/packages/linux/patches/default/linux-999-improve-ir-timeout-handling.patch so long & thanks, Hias > > Sean Young (3): > media: rc: set timeout to smallest value required by enabled protocols > media: rc: add ioctl to get the current timeout > media: rc: per-protocol repeat period and minimum keyup timer > > Documentation/media/uapi/rc/lirc-func.rst | 1 + > .../media/uapi/rc/lirc-set-rec-timeout.rst | 14 +++-- > drivers/media/cec/cec-core.c | 2 +- > drivers/media/rc/ir-imon-decoder.c | 1 + > drivers/media/rc/ir-jvc-decoder.c | 1 + > drivers/media/rc/ir-mce_kbd-decoder.c | 1 + > drivers/media/rc/ir-nec-decoder.c | 1 + > drivers/media/rc/ir-rc5-decoder.c | 1 + > drivers/media/rc/ir-rc6-decoder.c | 1 + > drivers/media/rc/ir-sanyo-decoder.c| 1 + > drivers/media/rc/ir-sharp-decoder.c| 1 + > drivers/media/rc/ir-sony-decoder.c | 1 + > drivers/media/rc/ir-xmp-decoder.c | 1 + > drivers/media/rc/lirc_dev.c| 9 ++- > drivers/media/rc/rc-core-priv.h| 1 + > drivers/media/rc/rc-ir-raw.c | 31 +- > drivers/media/rc/rc-main.c | 68 > +++--- > include/uapi/linux/lirc.h | 6 ++ > 18 files changed, 101 insertions(+), 41 deletions(-) > > -- > 2.14.3 >
Re: [PATCH 2/8] PCI: Add pci_find_common_upstream_dev()
Am 28.03.2018 um 18:25 schrieb Logan Gunthorpe: On 28/03/18 10:02 AM, Christian König wrote: Yeah, that looks very similar to what I picked up from the older patches, going to read up on that after my vacation. Yeah, I was just reading through your patchset and there are a lot of similarities. Though, I'm not sure what you're trying to accomplish as I could not find a cover letter and it seems to only enable one driver. Yeah, it was the last day before my easter vacation and I wanted it out of the door. Is it meant to enable DMA transactions only between two AMD GPUs? Not really, DMA-buf is a general framework for sharing buffers between device drivers. It is widely used in the GFX stack on laptops with both Intel+AMD, Intel+NVIDIA or AMD+AMD graphics devices. Additional to that ARM uses it quite massively for their GFX stacks because they have rendering and displaying device separated. I'm just using amdgpu as blueprint because I'm the co-maintainer of it and know it mostly inside out. I also don't see where you've taken into account the PCI bus address. On some architectures this is not the same as the CPU physical address. The resource addresses are translated using dma_map_resource(). As far as I know that should be sufficient to offload all the architecture specific stuff to the DMA subsystem. Just in general why are you interested in the "distance" of the devices? We've taken a general approach where some drivers may provide p2p memory (ie. an NVMe card or an RDMA NIC) and other drivers make use of it (ie. the NVMe-of driver). The orchestrator driver needs to find the most applicable provider device for a transaction in a situation that may have multiple providers and multiple clients. So the most applicable provider is the one that's closest ("distance"-wise) to all the clients for the P2P transaction. That seems to make sense. And BTW: At least for writes that Peer 2 Peer transactions between different root complexes work is actually more common than the other way around. Maybe on x86 with hardware made in the last few years. But on PowerPC, ARM64, and likely a lot more the chance of support is *much* less. Also, hardware that only supports P2P stores is hardly full support and is insufficient for our needs. Yeah, but not for ours. See if you want to do real peer 2 peer you need to keep both the operation as well as the direction into account. For example when you can do writes between A and B that doesn't mean that writes between B and A work. And reads are generally less likely to work than writes. etc... Since the use case I'm targeting for is GFX or GFX+V4L (or GFX+NIC in the future) I really need to handle all such use cases as well. So I'm a bit torn between using a blacklist or a whitelist. A whitelist is certainly more conservative approach, but that could get a bit long. I think a whitelist approach is correct. Given old hardware and other architectures, a black list is going to be too long and too difficult to comprehensively populate. Yeah, it would certainly be better if we have something in the root complex capabilities. But you're right that a whitelist sounds the less painful way. Regards, Christian. Logan ___ amd-gfx mailing list amd-...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/amd-gfx
[PATCH for v3.18 07/18] media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32
From: Hans Verkuil commit 8ed5a59dcb47a6f76034ee760b36e089f3e82529 upstream. The struct v4l2_plane32 should set m.userptr as well. The same happens in v4l2_buffer32 and v4l2-compliance tests for this. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 47 --- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index b7dd98168a68..a27fd9105948 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -287,19 +287,24 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __ sizeof(up->data_offset))) return -EFAULT; - if (memory == V4L2_MEMORY_USERPTR) { + switch (memory) { + case V4L2_MEMORY_MMAP: + case V4L2_MEMORY_OVERLAY: + if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, +sizeof(up32->m.mem_offset))) + return -EFAULT; + break; + case V4L2_MEMORY_USERPTR: if (get_user(p, &up32->m.userptr)) return -EFAULT; up_pln = compat_ptr(p); if (put_user((unsigned long)up_pln, &up->m.userptr)) return -EFAULT; - } else if (memory == V4L2_MEMORY_DMABUF) { + break; + case V4L2_MEMORY_DMABUF: if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(up32->m.fd))) return -EFAULT; - } else { - if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset, -sizeof(up32->m.mem_offset))) - return -EFAULT; + break; } return 0; @@ -308,22 +313,32 @@ static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __ static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32, enum v4l2_memory memory) { + unsigned long p; + if (copy_in_user(up32, up, 2 * sizeof(__u32)) || copy_in_user(&up32->data_offset, &up->data_offset, sizeof(up->data_offset))) return -EFAULT; - /* For MMAP, driver might've set up the offset, so copy it back. -* USERPTR stays the same (was userspace-provided), so no copying. */ - if (memory == V4L2_MEMORY_MMAP) + switch (memory) { + case V4L2_MEMORY_MMAP: + case V4L2_MEMORY_OVERLAY: if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset, sizeof(up->m.mem_offset))) return -EFAULT; - /* For DMABUF, driver might've set up the fd, so copy it back. */ - if (memory == V4L2_MEMORY_DMABUF) + break; + case V4L2_MEMORY_USERPTR: + if (get_user(p, &up->m.userptr) || + put_user((compat_ulong_t)ptr_to_compat((__force void *)p), +&up32->m.userptr)) + return -EFAULT; + break; + case V4L2_MEMORY_DMABUF: if (copy_in_user(&up32->m.fd, &up->m.fd, sizeof(up->m.fd))) return -EFAULT; + break; + } return 0; } @@ -383,6 +398,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user } else { switch (kp->memory) { case V4L2_MEMORY_MMAP: + case V4L2_MEMORY_OVERLAY: if (get_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; @@ -396,10 +412,6 @@ static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user kp->m.userptr = (unsigned long)compat_ptr(tmp); } break; - case V4L2_MEMORY_OVERLAY: - if (get_user(kp->m.offset, &up->m.offset)) - return -EFAULT; - break; case V4L2_MEMORY_DMABUF: if (get_user(kp->m.fd, &up->m.fd)) return -EFAULT; @@ -456,6 +468,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user } else { switch (kp->memory) { case V4L2_MEMORY_MMAP: + case V4L2_MEMORY_OVERLAY: if (put_user(kp->m.offset, &up->m.offset)) return -EFAULT; break; @@ -463,10 +476,6 @@ static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v
[PATCH for v3.18 03/18] media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF
From: Hans Verkuil commit 3ee6d040719ae09110e5cdf24d5386abe5d1b776 upstream. The result of the VIDIOC_PREPARE_BUF ioctl was never copied back to userspace since it was missing in the switch. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index aa11f02c0a8f..fc4f92a0c985 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -996,6 +996,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar err = put_v4l2_create32(&karg.v2crt, up); break; + case VIDIOC_PREPARE_BUF: case VIDIOC_QUERYBUF: case VIDIOC_QBUF: case VIDIOC_DQBUF: -- 2.14.3
[PATCH for v3.18 15/18] media: v4l2-ctrls: fix sparse warning
From: Hans Verkuil The warning is simple: drivers/media/v4l2-core/v4l2-ctrls.c:1685:15: warning: incorrect type in assignment (different address spaces) but the fix isn't. The core problem was that the conversion from user to kernelspace was done at too low a level and that needed to be moved up. That made it possible to drop pointers to v4l2_ext_control from set_ctrl and validate_new and clean up this sparse warning because those functions now always operate on kernelspace pointers. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls.c | 87 +--- 1 file changed, 52 insertions(+), 35 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 7905ad9ffa35..3c4e22855652 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1668,10 +1668,8 @@ static int check_range(enum v4l2_ctrl_type type, } /* Validate a new control */ -static int validate_new(const struct v4l2_ctrl *ctrl, - struct v4l2_ext_control *c) +static int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new) { - union v4l2_ctrl_ptr ptr; unsigned idx; int err = 0; @@ -1684,19 +1682,14 @@ static int validate_new(const struct v4l2_ctrl *ctrl, case V4L2_CTRL_TYPE_BOOLEAN: case V4L2_CTRL_TYPE_BUTTON: case V4L2_CTRL_TYPE_CTRL_CLASS: - ptr.p_s32 = &c->value; - return ctrl->type_ops->validate(ctrl, 0, ptr); - case V4L2_CTRL_TYPE_INTEGER64: - ptr.p_s64 = &c->value64; - return ctrl->type_ops->validate(ctrl, 0, ptr); + return ctrl->type_ops->validate(ctrl, 0, p_new); default: break; } } - ptr.p = c->ptr; - for (idx = 0; !err && idx < c->size / ctrl->elem_size; idx++) - err = ctrl->type_ops->validate(ctrl, idx, ptr); + for (idx = 0; !err && idx < ctrl->elems; idx++) + err = ctrl->type_ops->validate(ctrl, idx, p_new); return err; } @@ -3020,6 +3013,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; + union v4l2_ctrl_ptr p_new; cs->error_idx = i; @@ -3033,7 +3027,17 @@ static int validate_ctrls(struct v4l2_ext_controls *cs, best-effort to avoid that. */ if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)) return -EBUSY; - ret = validate_new(ctrl, &cs->controls[i]); + /* +* Skip validation for now if the payload needs to be copied +* from userspace into kernelspace. We'll validate those later. +*/ + if (ctrl->is_ptr) + continue; + if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64) + p_new.p_s64 = &cs->controls[i].value64; + else + p_new.p_s32 = &cs->controls[i].value; + ret = validate_new(ctrl, p_new); if (ret) return ret; } @@ -3128,7 +3132,11 @@ 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 { - ret = user_to_new(cs->controls + idx, helpers[idx].ctrl); + struct v4l2_ctrl *ctrl = helpers[idx].ctrl; + + ret = user_to_new(cs->controls + idx, ctrl); + if (!ret && ctrl->is_ptr) + ret = validate_new(ctrl, ctrl->p_new); idx = helpers[idx].next; } while (!ret && idx); @@ -3178,10 +3186,10 @@ int v4l2_subdev_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls); /* Helper function for VIDIOC_S_CTRL compatibility */ -static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, - struct v4l2_ext_control *c, u32 ch_flags) +static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags) { struct v4l2_ctrl *master = ctrl->cluster[0]; + int ret; int i; /* Reset the 'is_new' flags of the cluster */ @@ -3189,8 +3197,9 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, if (master->cluster[i]) master->cluster[i]->is_new = 0; - if (c) - user_to_new(c, ctrl); + ret = validate_new(ctrl, ctrl->p_new); +
[PATCH for v3.18 09/18] media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs
From: Hans Verkuil commit 273caa260035c03d89ad63d72d8cd3d9e5c5e3f1 upstream. If the device is of type VFL_TYPE_SUBDEV then vdev->ioctl_ops is NULL so the 'if (!ops->vidioc_query_ext_ctrl)' check would crash. Add a test for !ops to the condition. All sub-devices that have controls will use the control framework, so they do not have an equivalent to ops->vidioc_query_ext_ctrl. Returning false if ops is NULL is the correct thing to do here. Fixes: b8c601e8af ("v4l2-compat-ioctl32.c: fix ctrl_is_pointer") Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Reported-by: Laurent Pinchart Reviewed-by: Laurent Pinchart Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index c78462e79a0a..bd4890769e0b 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -600,7 +600,7 @@ static inline bool ctrl_is_pointer(struct file *file, u32 id) return ctrl && ctrl->is_ptr; } - if (!ops->vidioc_query_ext_ctrl) + if (!ops || !ops->vidioc_query_ext_ctrl) return false; return !ops->vidioc_query_ext_ctrl(file, fh, &qec) && -- 2.14.3
[PATCH for v3.18 04/18] media: v4l2-compat-ioctl32.c: fix the indentation
From: Hans Verkuil commit b7b957d429f601d6d1942122b339474f31191d75 upstream. The indentation of this source is all over the place. Fix this. This patch only changes whitespace. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 216 +- 1 file changed, 108 insertions(+), 108 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index fc4f92a0c985..866019bbf513 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -48,11 +48,11 @@ struct v4l2_window32 { static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) { if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || - copy_from_user(&kp->w, &up->w, sizeof(up->w)) || - get_user(kp->field, &up->field) || - get_user(kp->chromakey, &up->chromakey) || - get_user(kp->clipcount, &up->clipcount)) - return -EFAULT; + copy_from_user(&kp->w, &up->w, sizeof(up->w)) || + get_user(kp->field, &up->field) || + get_user(kp->chromakey, &up->chromakey) || + get_user(kp->clipcount, &up->clipcount)) + return -EFAULT; if (kp->clipcount > 2048) return -EINVAL; if (kp->clipcount) { @@ -82,10 +82,10 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) { if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || - put_user(kp->field, &up->field) || - put_user(kp->chromakey, &up->chromakey) || - put_user(kp->clipcount, &up->clipcount)) - return -EFAULT; + put_user(kp->field, &up->field) || + put_user(kp->chromakey, &up->chromakey) || + put_user(kp->clipcount, &up->clipcount)) + return -EFAULT; return 0; } @@ -97,7 +97,7 @@ static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pi } static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, - struct v4l2_pix_format_mplane __user *up) +struct v4l2_pix_format_mplane __user *up) { if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane))) return -EFAULT; @@ -112,7 +112,7 @@ static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pi } static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, - struct v4l2_pix_format_mplane __user *up) +struct v4l2_pix_format_mplane __user *up) { if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane))) return -EFAULT; @@ -200,7 +200,7 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); default: printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", - kp->type); + kp->type); return -EINVAL; } } @@ -241,7 +241,7 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); default: printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", - kp->type); + kp->type); return -EINVAL; } } @@ -275,7 +275,7 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 { /* other fields are not set by the user, nor used by the driver */ if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || - get_user(kp->index, &up->index)) + get_user(kp->index, &up->index)) return -EFAULT; return 0; } @@ -283,13 +283,13 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) { if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || - put_user(kp->index, &up->index) || - copy_to_user(up->id, &kp->id, sizeof(__u64)) || - copy_to_user(up->name, kp->name, 24) || - copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || - put_user(kp->frame
[PATCH for v3.18 10/18] media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha
From: Daniel Mentz commit 025a26fa14f8fd55d50ab284a30c016a5be953d0 upstream. Commit b2787845fb91 ("V4L/DVB (5289): Add support for video output overlays.") added the field global_alpha to struct v4l2_window but did not update the compat layer accordingly. This change adds global_alpha to struct v4l2_window32 and copies the value for global_alpha back and forth. Signed-off-by: Daniel Mentz Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index bd4890769e0b..fd32c9ccc2bb 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -45,6 +45,7 @@ struct v4l2_window32 { compat_caddr_t clips; /* actually struct v4l2_clip32 * */ __u32 clipcount; compat_caddr_t bitmap; + __u8global_alpha; }; static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) @@ -53,7 +54,8 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user copy_from_user(&kp->w, &up->w, sizeof(up->w)) || get_user(kp->field, &up->field) || get_user(kp->chromakey, &up->chromakey) || - get_user(kp->clipcount, &up->clipcount)) + get_user(kp->clipcount, &up->clipcount) || + get_user(kp->global_alpha, &up->global_alpha)) return -EFAULT; if (kp->clipcount > 2048) return -EINVAL; @@ -86,7 +88,8 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || put_user(kp->field, &up->field) || put_user(kp->chromakey, &up->chromakey) || - put_user(kp->clipcount, &up->clipcount)) + put_user(kp->clipcount, &up->clipcount) || + put_user(kp->global_alpha, &up->global_alpha)) return -EFAULT; return 0; } -- 2.14.3
[PATCH for v3.18 05/18] media: v4l2-compat-ioctl32.c: move 'helper' functions to __get/put_v4l2_format32
From: Hans Verkuil commit 486c521510c44a04cd756a9267e7d1e271c8a4ba upstream. These helper functions do not really help. Move the code to the __get/put_v4l2_format32 functions. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 84 +-- 1 file changed, 16 insertions(+), 68 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 866019bbf513..702757012dc7 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -89,64 +89,6 @@ static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user return 0; } -static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) -{ - if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format))) - return -EFAULT; - return 0; -} - -static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, -struct v4l2_pix_format_mplane __user *up) -{ - if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane))) - return -EFAULT; - return 0; -} - -static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up) -{ - if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format))) - return -EFAULT; - return 0; -} - -static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp, -struct v4l2_pix_format_mplane __user *up) -{ - if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane))) - return -EFAULT; - return 0; -} - -static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) -{ - if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format))) - return -EFAULT; - return 0; -} - -static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up) -{ - if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format))) - return -EFAULT; - return 0; -} - -static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) -{ - if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format))) - return -EFAULT; - return 0; -} - -static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up) -{ - if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format))) - return -EFAULT; - return 0; -} - struct v4l2_format32 { __u32 type; /* enum v4l2_buf_type */ union { @@ -184,20 +126,23 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us switch (kp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); + return copy_from_user(&kp->fmt.pix, &up->fmt.pix, + sizeof(kp->fmt.pix)) ? -EFAULT : 0; case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp, - &up->fmt.pix_mp); + return copy_from_user(&kp->fmt.pix_mp, &up->fmt.pix_mp, + sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0; case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: return get_v4l2_window32(&kp->fmt.win, &up->fmt.win); case V4L2_BUF_TYPE_VBI_CAPTURE: case V4L2_BUF_TYPE_VBI_OUTPUT: - return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi); + return copy_from_user(&kp->fmt.vbi, &up->fmt.vbi, + sizeof(kp->fmt.vbi)) ? -EFAULT : 0; case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: - return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced); + return copy_from_user(&kp->fmt.sliced, &up->fmt.sliced, + sizeof(kp->fmt.sliced)) ? -EFAULT : 0; default: printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", kp->type); @@ -225,20 +170,23 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us switch (kp->type) { case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_OUTPUT: - return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix); + return c
[PATCH for v3.18 13/18] media: v4l2-compat-ioctl32.c: don't copy back the result for certain errors
From: Hans Verkuil commit d83a8243aaefe62ace433e4384a4f077bed86acb upstream. Some ioctls need to copy back the result even if the ioctl returned an error. However, don't do this for the error code -ENOTTY. It makes no sense in that cases. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index a5f74a508f58..9e5807842dad 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -943,6 +943,9 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar set_fs(old_fs); } + if (err == -ENOTTY) + return err; + /* Special case: even after an error we need to put the results back for these ioctls since the error_idx will contain information on which control failed. */ -- 2.14.3
[PATCH for v3.18 11/18] media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32
From: Hans Verkuil commit a751be5b142ef6bcbbb96d9899516f4d9c8d0ef4 upstream. put_v4l2_window32() didn't copy back the clip list to userspace. Drivers can update the clip rectangles, so this should be done. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 61 ++- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index fd32c9ccc2bb..8a5c93ce4348 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -50,6 +50,11 @@ struct v4l2_window32 { static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) { + struct v4l2_clip32 __user *uclips; + struct v4l2_clip __user *kclips; + compat_caddr_t p; + u32 n; + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || copy_from_user(&kp->w, &up->w, sizeof(up->w)) || get_user(kp->field, &up->field) || @@ -59,38 +64,54 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user return -EFAULT; if (kp->clipcount > 2048) return -EINVAL; - if (kp->clipcount) { - struct v4l2_clip32 __user *uclips; - struct v4l2_clip __user *kclips; - int n = kp->clipcount; - compat_caddr_t p; - - if (get_user(p, &up->clips)) - return -EFAULT; - uclips = compat_ptr(p); - kclips = compat_alloc_user_space(n * sizeof(*kclips)); - kp->clips = kclips; - while (--n >= 0) { - if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) - return -EFAULT; - if (put_user(n ? kclips + 1 : NULL, &kclips->next)) - return -EFAULT; - uclips += 1; - kclips += 1; - } - } else + if (!kp->clipcount) { kp->clips = NULL; + return 0; + } + + n = kp->clipcount; + if (get_user(p, &up->clips)) + return -EFAULT; + uclips = compat_ptr(p); + kclips = compat_alloc_user_space(n * sizeof(*kclips)); + kp->clips = kclips; + while (n--) { + if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) + return -EFAULT; + if (put_user(n ? kclips + 1 : NULL, &kclips->next)) + return -EFAULT; + uclips++; + kclips++; + } return 0; } static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) { + struct v4l2_clip __user *kclips = kp->clips; + struct v4l2_clip32 __user *uclips; + u32 n = kp->clipcount; + compat_caddr_t p; + if (copy_to_user(&up->w, &kp->w, sizeof(kp->w)) || put_user(kp->field, &up->field) || put_user(kp->chromakey, &up->chromakey) || put_user(kp->clipcount, &up->clipcount) || put_user(kp->global_alpha, &up->global_alpha)) return -EFAULT; + + if (!kp->clipcount) + return 0; + + if (get_user(p, &up->clips)) + return -EFAULT; + uclips = compat_ptr(p); + while (n--) { + if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c))) + return -EFAULT; + uclips++; + kclips++; + } return 0; } -- 2.14.3
[PATCH for v3.18 17/18] media: v4l2-compat-ioctl32: use compat_u64 for video standard
Instead of using the "v4l2_std_id" typedef, use compat_u64, as otherwise it fails to properly handle some ioctls. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index e03aa0961360..c76438dd3ead 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -686,7 +686,7 @@ struct v4l2_input32 { __u32type; /* Type of input */ __u32audioset; /* Associated audios (bitfield) */ __u32tuner; /* Associated tuner */ - v4l2_std_id std; + compat_u64 std; __u32status; __u32capabilities; __u32reserved[3]; -- 2.14.3
[PATCH for v3.18 16/18] media: media/v4l2-ctrls: volatiles should not generate CH_VALUE
From: Ricardo Ribalda Volatile controls should not generate CH_VALUE events. Set has_changed to false to prevent this happening. Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ctrls.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 3c4e22855652..2bdb2a3512a4 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1619,6 +1619,15 @@ static int cluster_changed(struct v4l2_ctrl *master) if (ctrl == NULL) continue; + /* +* Set has_changed to false to avoid generating +* the event V4L2_EVENT_CTRL_CH_VALUE +*/ + if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE) { + ctrl->has_changed = false; + continue; + } + for (idx = 0; !ctrl_changed && idx < ctrl->elems; idx++) ctrl_changed = !ctrl->type_ops->equal(ctrl, idx, ctrl->p_cur, ctrl->p_new); -- 2.14.3
[PATCH for v3.18 08/18] media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer
From: Hans Verkuil commit b8c601e8af2d08f733d74defa8465303391bb930 upstream. ctrl_is_pointer just hardcoded two known string controls, but that caused problems when using e.g. custom controls that use a pointer for the payload. Reimplement this function: it now finds the v4l2_ctrl (if the driver uses the control framework) or it calls vidioc_query_ext_ctrl (if the driver implements that directly). In both cases it can now check if the control is a pointer control or not. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 57 ++- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index a27fd9105948..c78462e79a0a 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) @@ -575,24 +577,39 @@ struct v4l2_ext_control32 { }; } __attribute__ ((packed)); -/* The following function really belong in v4l2-common, but that causes - a circular dependency between modules. We need to think about this, but - for now this will do. */ - -/* Return non-zero if this control is a pointer type. Currently only - type STRING is a pointer type. */ -static inline int ctrl_is_pointer(u32 id) +/* Return true if this control is a pointer type. */ +static inline bool ctrl_is_pointer(struct file *file, u32 id) { - switch (id) { - case V4L2_CID_RDS_TX_PS_NAME: - case V4L2_CID_RDS_TX_RADIO_TEXT: - return 1; - default: - return 0; + struct video_device *vdev = video_devdata(file); + struct v4l2_fh *fh = NULL; + struct v4l2_ctrl_handler *hdl = NULL; + struct v4l2_query_ext_ctrl qec = { id }; + const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops; + + if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags)) + fh = file->private_data; + + if (fh && fh->ctrl_handler) + hdl = fh->ctrl_handler; + else if (vdev->ctrl_handler) + hdl = vdev->ctrl_handler; + + if (hdl) { + struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id); + + return ctrl && ctrl->is_ptr; } + + if (!ops->vidioc_query_ext_ctrl) + return false; + + return !ops->vidioc_query_ext_ctrl(file, fh, &qec) && + (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD); } -static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) +static int get_v4l2_ext_controls32(struct file *file, + struct v4l2_ext_controls *kp, + struct v4l2_ext_controls32 __user *up) { struct v4l2_ext_control32 __user *ucontrols; struct v4l2_ext_control __user *kcontrols; @@ -624,7 +641,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext return -EFAULT; if (get_user(id, &kcontrols->id)) return -EFAULT; - if (ctrl_is_pointer(id)) { + if (ctrl_is_pointer(file, id)) { void __user *s; if (get_user(p, &ucontrols->string)) @@ -639,7 +656,9 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext return 0; } -static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up) +static int put_v4l2_ext_controls32(struct file *file, + struct v4l2_ext_controls *kp, + struct v4l2_ext_controls32 __user *up) { struct v4l2_ext_control32 __user *ucontrols; struct v4l2_ext_control __user *kcontrols = @@ -671,7 +690,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext /* Do not modify the pointer when copying a pointer control. The contents of the pointer was changed, not the pointer itself. */ - if (ctrl_is_pointer(id)) + if (ctrl_is_pointer(file, id)) size -= sizeof(ucontrols->value64); if (copy_in_user(ucontrols, kcontrols, size)) return -EFAULT; @@ -884,7 +903,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar case VIDIOC_G_EXT_CTRLS: case VIDIOC_S_EXT_CTRLS: case VIDIOC_TRY_EXT_CTRLS: - err = get_v4l2_ext_controls32(&karg.v2ecs, up); + err = get_v4l2_ext_controls32(file, &karg.v2ecs, up); compatible_arg = 0;
[PATCH for v3.18 02/18] vb2: V4L2_BUF_FLAG_DONE is set after DQBUF
From: Ricardo Ribalda commit 3171cc2b4eb9831ab4df1d80d0410a945b8bc84e upstream. According to the doc, V4L2_BUF_FLAG_DONE is cleared after DQBUF: V4L2_BUF_FLAG_DONE 0x0004 ... After calling the VIDIOC_QBUF or VIDIOC_DQBUF it is always cleared ... Unfortunately, it seems that videobuf2 keeps it set after DQBUF. This can be tested with vivid and dev_debug: [257604.338082] video1: VIDIOC_DQBUF: 71:33:25.00260479 index=3, type=vid-cap, flags=0x2004, field=none, sequence=163, memory=userptr, bytesused=460800, offset/userptr=0x344b000, length=460800 This patch forces FLAG_DONE to 0 after calling DQBUF. Reported-by: Dimitrios Katsaros Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/videobuf2-core.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index d5c300150cf4..f0811b7e900d 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c @@ -2075,6 +2075,11 @@ static int vb2_internal_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool n dprintk(1, "dqbuf of buffer %d, with state %d\n", vb->v4l2_buf.index, vb->state); + /* +* After calling the VIDIOC_DQBUF V4L2_BUF_FLAG_DONE must be +* cleared. +*/ + b->flags &= ~V4L2_BUF_FLAG_DONE; return 0; } -- 2.14.3
[PATCH for v3.18 12/18] media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type
From: Hans Verkuil commit 169f24ca68bf0f247d111aef07af00dd3a02ae88 upstream. There is nothing wrong with using an unknown buffer type. So stop spamming the kernel log whenever this happens. The kernel will just return -EINVAL to signal this. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 4 1 file changed, 4 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 8a5c93ce4348..a5f74a508f58 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -170,8 +170,6 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us return copy_from_user(&kp->fmt.sliced, &up->fmt.sliced, sizeof(kp->fmt.sliced)) ? -EFAULT : 0; default: - printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", - kp->type); return -EINVAL; } } @@ -214,8 +212,6 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us return copy_to_user(&up->fmt.sliced, &kp->fmt.sliced, sizeof(kp->fmt.sliced)) ? -EFAULT : 0; default: - printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n", - kp->type); return -EINVAL; } } -- 2.14.3
[PATCH for v3.18 01/18] media: v4l2-ioctl.c: don't copy back the result for -ENOTTY
From: Hans Verkuil commit 181a4a2d5a0a7b43cab08a70710d727e7764ccdd upstream. If the ioctl returned -ENOTTY, then don't bother copying back the result as there is no point. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-ioctl.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 9ccb19a435ef..bb2387fcbfee 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2539,8 +2539,11 @@ video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, /* Handles IOCTL */ err = func(file, cmd, parg); - if (err == -ENOIOCTLCMD) + if (err == -ENOTTY || err == -ENOIOCTLCMD) { err = -ENOTTY; + goto out; + } + if (err == 0) { if (cmd == VIDIOC_DQBUF) trace_v4l2_dqbuf(video_devdata(file)->minor, parg); -- 2.14.3
[PATCH for v3.18 06/18] media: v4l2-compat-ioctl32.c: avoid sizeof(type)
From: Hans Verkuil commit 333b1e9f96ce05f7498b581509bb30cde03018bf upstream. Instead of doing sizeof(struct foo) use sizeof(*up). There even were cases where 4 * sizeof(__u32) was used instead of sizeof(kp->reserved), which is very dangerous when the size of the reserved array changes. Signed-off-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 80 +-- 1 file changed, 38 insertions(+), 42 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 702757012dc7..b7dd98168a68 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -47,7 +47,7 @@ struct v4l2_window32 { static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) || + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || copy_from_user(&kp->w, &up->w, sizeof(up->w)) || get_user(kp->field, &up->field) || get_user(kp->chromakey, &up->chromakey) || @@ -64,7 +64,7 @@ static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user if (get_user(p, &up->clips)) return -EFAULT; uclips = compat_ptr(p); - kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip)); + kclips = compat_alloc_user_space(n * sizeof(*kclips)); kp->clips = kclips; while (--n >= 0) { if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c))) @@ -152,14 +152,14 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32))) + if (!access_ok(VERIFY_READ, up, sizeof(*up))) return -EFAULT; return __get_v4l2_format32(kp, up); } static int get_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) { - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) || + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || copy_from_user(kp, up, offsetof(struct v4l2_create_buffers32, format))) return -EFAULT; return __get_v4l2_format32(&kp->format, &up->format); @@ -196,17 +196,17 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) || - put_user(kp->type, &up->type)) + if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) return -EFAULT; return __put_v4l2_format32(kp, up); } static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) || - copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt))) - return -EFAULT; + if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || + copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) || + copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved))) + return -EFAULT; return __put_v4l2_format32(&kp->format, &up->format); } @@ -222,7 +222,7 @@ struct v4l2_standard32 { static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) { /* other fields are not set by the user, nor used by the driver */ - if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) || + if (!access_ok(VERIFY_READ, up, sizeof(*up)) || get_user(kp->index, &up->index)) return -EFAULT; return 0; @@ -230,13 +230,13 @@ static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up) { - if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) || + if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) || put_user(kp->index, &up->index) || copy_to_user(up->id, &kp->id, sizeof(__u64)) || - copy_to_user(up->name, kp->name, 24) || + copy_to_user(up->name, kp->name, sizeof(up->name)) || copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) || put_user(kp->framelines, &up->framelines) || - copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32))) + copy_to_user(up->reserved, kp->reserved, sizeof(kp->res
[PATCH for v3.18 14/18] media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic
From: Daniel Mentz commit a1dfb4c48cc1e64eeb7800a27c66a6f7e88d075a upstream. The 32-bit compat v4l2 ioctl handling is implemented based on its 64-bit equivalent. It converts 32-bit data structures into its 64-bit equivalents and needs to provide the data to the 64-bit ioctl in user space memory which is commonly allocated using compat_alloc_user_space(). However, due to how that function is implemented, it can only be called a single time for every syscall invocation. Supposedly to avoid this limitation, the existing code uses a mix of memory from the kernel stack and memory allocated through compat_alloc_user_space(). Under normal circumstances, this would not work, because the 64-bit ioctl expects all pointers to point to user space memory. As a workaround, set_fs(KERNEL_DS) is called to temporarily disable this extra safety check and allow kernel pointers. However, this might introduce a security vulnerability: The result of the 32-bit to 64-bit conversion is writeable by user space because the output buffer has been allocated via compat_alloc_user_space(). A malicious user space process could then manipulate pointers inside this output buffer, and due to the previous set_fs(KERNEL_DS) call, functions like get_user() or put_user() no longer prevent kernel memory access. The new approach is to pre-calculate the total amount of user space memory that is needed, allocate it using compat_alloc_user_space() and then divide up the allocated memory to accommodate all data structures that need to be converted. An alternative approach would have been to retain the union type karg that they allocated on the kernel stack in do_video_ioctl(), copy all data from user space into karg and then back to user space. However, we decided against this approach because it does not align with other compat syscall implementations. Instead, we tried to replicate the get_user/put_user pairs as found in other places in the kernel: if (get_user(clipcount, &up->clipcount) || put_user(clipcount, &kp->clipcount)) return -EFAULT; Notes from hans.verk...@cisco.com: This patch was taken from: https://github.com/LineageOS/android_kernel_samsung_apq8084/commit/97b733953c06e4f0398ade18850f0817778255f7 Clearly nobody could be bothered to upstream this patch or at minimum tell us :-( We only heard about this a week ago. This patch was rebased and cleaned up. Compared to the original I also swapped the order of the convert_in_user arguments so that they matched copy_in_user. It was hard to review otherwise. I also replaced the ALLOC_USER_SPACE/ALLOC_AND_GET by a normal function. Fixes: 6b5a9492ca ("v4l: introduce string control support.") Signed-off-by: Daniel Mentz Co-developed-by: Hans Verkuil Acked-by: Sakari Ailus Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Sasha Levin --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 747 +- 1 file changed, 486 insertions(+), 261 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 9e5807842dad..e03aa0961360 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -22,6 +22,14 @@ #include #include +/* Use the same argument order as copy_in_user */ +#define assign_in_user(to, from) \ +({ \ + typeof(*from) __assign_tmp; \ + \ + get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \ +}) + static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret = -ENOIOCTLCMD; @@ -35,12 +43,12 @@ static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct v4l2_clip32 { struct v4l2_rectc; - compat_caddr_t next; + compat_caddr_t next; }; struct v4l2_window32 { struct v4l2_rectw; - __u32 field; /* enum v4l2_field */ + __u32 field; /* enum v4l2_field */ __u32 chromakey; compat_caddr_t clips; /* actually struct v4l2_clip32 * */ __u32 clipcount; @@ -48,37 +56,41 @@ struct v4l2_window32 { __u8global_alpha; }; -static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up) +static int get_v4l2_window32(struct v4l2_window __user *kp, +struct v4l2_window32 __user *up, +void __user *aux_buf, u32 aux_space) { struct v4l2_clip32 __user *uclips; struct v4l2_clip __user *kclips; compat_caddr_t p; - u32 n; + u32 clipcount; if (!access_ok(VERIFY_READ, up, sizeof(
[PATCH for v3.18 18/18] media: v4l2-compat-ioctl32: initialize a reserved field
The get_v4l2_create32() function is missing a logic with would be cleaning a reserved field, causing v4l2-compliance to complain: Buffer ioctls (Input 0): fail: v4l2-test-buffers.cpp(506): check_0(crbufs.reserved, sizeof(crbufs.reserved)) test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: FAIL Signed-off-by: Mauro Carvalho Chehab --- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index c76438dd3ead..ca0a43ad4ec8 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -247,7 +247,8 @@ static int get_v4l2_create32(struct v4l2_create_buffers __user *kp, { if (!access_ok(VERIFY_READ, up, sizeof(*up)) || copy_in_user(kp, up, -offsetof(struct v4l2_create_buffers32, format))) +offsetof(struct v4l2_create_buffers32, format)) || + copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved))) return -EFAULT; return __get_v4l2_format32(&kp->format, &up->format, aux_buf, aux_space); -- 2.14.3
[PATCH for v3.18 00/18] Backport CVE-2017-13166 fixes to Kernel 3.18
Hi Greg, Those are the backports meant to solve CVE-2017-13166 on Kernel 3.18. It contains two v4l2-ctrls fixes that are required to avoid crashes at the test application. I wrote two patches myself for Kernel 3.18 in order to solve some issues specific for Kernel 3.18 with aren't needed upstream. one is actually a one-line change backport. The other one makes sure that both 32-bits and 64-bits version of some ioctl calls will return the same value for a reserved field. I noticed an extra bug while testing it, but the bug also hits upstream, and should be backported all the way down all stable/LTS versions. So, I'll send it the usual way, after merging upsream. Regards, Mauro Daniel Mentz (2): media: v4l2-compat-ioctl32: Copy v4l2_window->global_alpha media: v4l2-compat-ioctl32.c: refactor compat ioctl32 logic Hans Verkuil (12): media: v4l2-ioctl.c: don't copy back the result for -ENOTTY media: v4l2-compat-ioctl32.c: add missing VIDIOC_PREPARE_BUF media: v4l2-compat-ioctl32.c: fix the indentation media: v4l2-compat-ioctl32.c: move 'helper' functions to __get/put_v4l2_format32 media: v4l2-compat-ioctl32.c: avoid sizeof(type) media: v4l2-compat-ioctl32.c: copy m.userptr in put_v4l2_plane32 media: v4l2-compat-ioctl32.c: fix ctrl_is_pointer media: v4l2-compat-ioctl32.c: make ctrl_is_pointer work for subdevs media: v4l2-compat-ioctl32.c: copy clip list in put_v4l2_window32 media: v4l2-compat-ioctl32.c: drop pr_info for unknown buffer type media: v4l2-compat-ioctl32.c: don't copy back the result for certain errors media: v4l2-ctrls: fix sparse warning Mauro Carvalho Chehab (2): media: v4l2-compat-ioctl32: use compat_u64 for video standard media: v4l2-compat-ioctl32: initialize a reserved field Ricardo Ribalda (2): vb2: V4L2_BUF_FLAG_DONE is set after DQBUF media: media/v4l2-ctrls: volatiles should not generate CH_VALUE drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 1020 +++-- drivers/media/v4l2-core/v4l2-ctrls.c | 96 ++- drivers/media/v4l2-core/v4l2-ioctl.c |5 +- drivers/media/v4l2-core/videobuf2-core.c |5 + 4 files changed, 691 insertions(+), 435 deletions(-) -- 2.14.3
[PATCH] media: v4l2-compat-ioctl32: don't oops on overlay
At put_v4l2_window32(), it tries to access kp->clips. However, kp points to an userspace pointer. So, it should be obtained via get_user(), otherwise it can OOPS: vivid-000: == END STATUS == BUG: unable to handle kernel paging request at fffb18e0 IP: [] __put_v4l2_format32+0x169/0x220 [videodev] PGD 3f5776067 PUD 3f576f067 PMD 3f5769067 PTE 80042548f067 Oops: 0001 [#1] SMP Modules linked in: vivid videobuf2_vmalloc videobuf2_memops v4l2_dv_timings videobuf2_core v4l2_common videodev media xt_CHECKSUM iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables bluetooth rfkill binfmt_misc snd_hda_codec_hdmi i915 snd_hda_intel snd_hda_controller snd_hda_codec intel_rapl x86_pkg_temp_thermal snd_hwdep intel_powerclamp snd_pcm coretemp snd_seq_midi kvm_intel kvm snd_seq_midi_event snd_rawmidi i2c_algo_bit drm_kms_helper snd_seq drm crct10dif_pclmul e1000e snd_seq_device crc32_pclmul snd_timer ghash_clmulni_intel snd mei_me mei ptp pps_core soundcore lpc_ich video crc32c_intel [last unloaded: media] CPU: 2 PID: 28332 Comm: v4l2-compliance Not tainted 3.18.102+ #107 Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0364.2017.0511.0949 05/11/2017 task: 8804293f8000 ti: 8803f564 task.ti: 8803f564 RIP: 0010:[] [] __put_v4l2_format32+0x169/0x220 [videodev] RSP: 0018:8803f5643e28 EFLAGS: 00010246 RAX: RBX: RCX: fffb1ab4 RDX: fffb1a68 RSI: fffb18d8 RDI: fffb1aa8 RBP: 8803f5643e48 R08: 0001 R09: 8803f54b0378 R10: R11: 0168 R12: fffb18c0 R13: fffb1a94 R14: fffb18c8 R15: FS: () GS:880456d0(0063) knlGS:f7100980 CS: 0010 DS: 002b ES: 002b CR0: 80050033 CR2: fffb18e0 CR3: 0003f552b000 CR4: 003407e0 Stack: fffb1a94 c0cc5640 0056 8804274f3600 8803f5643ed0 c0547e16 0003 8803f5643eb0 81301460 88009db44b01 880441942520 8800c0d05640 Call Trace: [] v4l2_compat_ioctl32+0x12d6/0x1b1d [videodev] [] ? file_has_perm+0x70/0xc0 [] compat_SyS_ioctl+0xec/0x1200 [] sysenter_dispatch+0x7/0x21 Code: 00 00 48 8b 80 48 c0 ff ff 48 83 e8 38 49 39 c6 0f 87 2b ff ff ff 49 8d 45 1c e8 a3 ce e3 c0 85 c0 0f 85 1a ff ff ff 41 8d 40 ff <4d> 8b 64 24 20 41 89 d5 48 8d 44 40 03 4d 8d 34 c4 eb 15 0f 1f RIP [] __put_v4l2_format32+0x169/0x220 [videodev] RSP CR2: fffb18e0 Tested with vivid driver on Kernel v3.18.102. Same bug happens upstream too: BUG: KASAN: user-memory-access in __put_v4l2_format32+0x98/0x4d0 [videodev] Read of size 8 at addr ffe48400 by task v4l2-compliance/8713 CPU: 0 PID: 8713 Comm: v4l2-compliance Not tainted 4.16.0-rc4+ #108 Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0364.2017.0511.0949 05/11/2017 Call Trace: dump_stack+0x5c/0x7c kasan_report+0x164/0x380 ? __put_v4l2_format32+0x98/0x4d0 [videodev] __put_v4l2_format32+0x98/0x4d0 [videodev] v4l2_compat_ioctl32+0x1aec/0x27a0 [videodev] ? __fsnotify_inode_delete+0x20/0x20 ? __put_v4l2_format32+0x4d0/0x4d0 [videodev] compat_SyS_ioctl+0x646/0x14d0 ? do_ioctl+0x30/0x30 do_fast_syscall_32+0x191/0x3f4 entry_SYSENTER_compat+0x6b/0x7a == Disabling lock debugging due to kernel taint BUG: unable to handle kernel paging request at ffe48400 IP: __put_v4l2_format32+0x98/0x4d0 [videodev] PGD 3a22fb067 P4D 3a22fb067 PUD 39b6f0067 PMD 39b6f1067 PTE 8003256af067 Oops: 0001 [#1] SMP KASAN Modules linked in: vivid videobuf2_vmalloc videobuf2_dma_contig videobuf2_memops v4l2_tpg v4l2_dv_timings videobuf2_v4l2 videobuf2_common v4l2_common videodev xt_CHECKSUM iptable_mangle ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_nat_ipv4 nf_nat nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack libcrc32c tun bridge stp llc ebtable_filter ebtables ip6table_filter ip6_tables bluetooth rfkill ecdh_generic binfmt_misc snd_hda_codec_hdmi intel_rapl x86_pkg_temp_thermal intel_powerclamp i915 coretemp snd_hda_intel snd_hda_codec kvm_intel snd_hwdep snd_hda_core kvm snd_pcm irqbypass crct10dif_pclmul crc32_pclmul snd_seq_midi ghash_clmulni_intel snd_seq_midi_event i2c_algo_bit intel_cstate snd_rawmidi intel_uncore snd_seq drm_kms_helper e1000e snd_seq_device snd_timer intel_rapl_perf drm ptp snd mei_me mei lpc_ich pps_core soundcore video crc32c_intel CPU: 0 PID: 8713 Comm: v4l2-compliance Tainted: GB4.16.0-rc4+ #108 Hardware name: /NUC5i7RYB, BIOS RYBDWi35.86A.0364.2017.0511.0949 05/11/2017 RIP: 0010:__put_v4l2_format32+0x98/0x4d0 [videodev] RSP: 0018:8803b9
[PATCH v2 3/5] dvb: earth-pt1: decompose pt1 driver into sub drivers
From: Akihiro Tsukada earth-pt1 was a monolithic module and included demod/tuner drivers. This patch removes those FE parts and attach demod/tuner i2c drivers. Signed-off-by: Akihiro Tsukada --- Changes since v1: - use i2c_board_info.name to specify pll_desc of the tuner drivers/media/pci/pt1/Kconfig| 3 + drivers/media/pci/pt1/Makefile | 3 +- drivers/media/pci/pt1/pt1.c | 329 +++- drivers/media/pci/pt1/va1j5jf8007s.c | 732 --- drivers/media/pci/pt1/va1j5jf8007s.h | 42 -- drivers/media/pci/pt1/va1j5jf8007t.c | 532 - drivers/media/pci/pt1/va1j5jf8007t.h | 42 -- 7 files changed, 227 insertions(+), 1456 deletions(-) delete mode 100644 drivers/media/pci/pt1/va1j5jf8007s.c delete mode 100644 drivers/media/pci/pt1/va1j5jf8007s.h delete mode 100644 drivers/media/pci/pt1/va1j5jf8007t.c delete mode 100644 drivers/media/pci/pt1/va1j5jf8007t.h diff --git a/drivers/media/pci/pt1/Kconfig b/drivers/media/pci/pt1/Kconfig index 24501d5bf70..2718b4c6b7c 100644 --- a/drivers/media/pci/pt1/Kconfig +++ b/drivers/media/pci/pt1/Kconfig @@ -1,6 +1,9 @@ config DVB_PT1 tristate "PT1 cards" depends on DVB_CORE && PCI && I2C + select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT + select MEDIA_TUNER_QM1D1B0004 if MEDIA_SUBDRV_AUTOSELECT help Support for Earthsoft PT1 PCI cards. diff --git a/drivers/media/pci/pt1/Makefile b/drivers/media/pci/pt1/Makefile index ab873ae088a..bc491e08dd6 100644 --- a/drivers/media/pci/pt1/Makefile +++ b/drivers/media/pci/pt1/Makefile @@ -1,5 +1,6 @@ -earth-pt1-objs := pt1.o va1j5jf8007s.o va1j5jf8007t.o +earth-pt1-objs := pt1.o obj-$(CONFIG_DVB_PT1) += earth-pt1.o ccflags-y += -Idrivers/media/dvb-frontends +ccflags-y += -Idrivers/media/tuners diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c index 4f6867af831..60bf517e7fe 100644 --- a/drivers/media/pci/pt1/pt1.c +++ b/drivers/media/pci/pt1/pt1.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -33,8 +35,9 @@ #include #include -#include "va1j5jf8007t.h" -#include "va1j5jf8007s.h" +#include "tc90522.h" +#include "qm1d1b0004.h" +#include "dvb-pll.h" #define DRIVER_NAME "earth-pt1" @@ -63,6 +66,11 @@ struct pt1_table { struct pt1_buffer bufs[PT1_NR_BUFS]; }; +enum pt1_fe_clk { + PT1_FE_CLK_20MHZ, /* PT1 */ + PT1_FE_CLK_25MHZ, /* PT2 */ +}; + #define PT1_NR_ADAPS 4 struct pt1_adapter; @@ -81,6 +89,8 @@ struct pt1 { struct mutex lock; int power; int reset; + + enum pt1_fe_clk fe_clk; }; struct pt1_adapter { @@ -97,6 +107,8 @@ struct pt1_adapter { int users; struct dmxdev dmxdev; struct dvb_frontend *fe; + struct i2c_client *demod_i2c_client; + struct i2c_client *tuner_i2c_client; int (*orig_set_voltage)(struct dvb_frontend *fe, enum fe_sec_voltage voltage); int (*orig_sleep)(struct dvb_frontend *fe); @@ -106,6 +118,144 @@ struct pt1_adapter { int sleep; }; +union pt1_tuner_config { + struct qm1d1b0004_config qm1d1b0004; + struct dvb_pll_config tda6651; +}; + +struct pt1_config { + struct i2c_board_info demod_info; + struct tc90522_config demod_cfg; + + struct i2c_board_info tuner_info; + union pt1_tuner_config tuner_cfg; +}; + +static const struct pt1_config pt1_configs[PT1_NR_ADAPS] = { + { + .demod_info = { + I2C_BOARD_INFO(TC90522_I2C_DEV_SAT, 0x1b), + }, + .tuner_info = { + I2C_BOARD_INFO("qm1d1b0004", 0x60), + }, + }, + { + .demod_info = { + I2C_BOARD_INFO(TC90522_I2C_DEV_TER, 0x1a), + }, + .tuner_info = { + I2C_BOARD_INFO(DVB_PLL_TDA665X_EARTH_PT1_NAME, 0x61), + }, + }, + { + .demod_info = { + I2C_BOARD_INFO(TC90522_I2C_DEV_SAT, 0x19), + }, + .tuner_info = { + I2C_BOARD_INFO("qm1d1b0004", 0x60), + }, + }, + { + .demod_info = { + I2C_BOARD_INFO(TC90522_I2C_DEV_TER, 0x18), + }, + .tuner_info = { + I2C_BOARD_INFO(DVB_PLL_TDA665X_EARTH_PT1_NAME, 0x61), + }, + }, +}; + +static const u8 va1j5jf8007s_20mhz_configs[][2] = { + {0x04, 0x02}, {0x0d, 0x55}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01}, + {0x1c, 0x0a}, {0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0}, + {0x52, 0x89}, {0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69}, + {0x87, 0x04}, {0x8e, 0x02}, {0xa3, 0xf7}, {0xa5, 0xc0}, +}; + +static c
[PATCH v2 5/5] dvb: earth-pt1: replace schedule_timeout with usleep_range
From: Akihiro Tsukada As described in Document/timers/timers-howto.txt, hrtimer-based delay should be used for small sleeps. Signed-off-by: Akihiro Tsukada --- Changes since v1: - none drivers/media/pci/pt1/pt1.c | 34 +++--- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c index 80510616c4c..43249269469 100644 --- a/drivers/media/pci/pt1/pt1.c +++ b/drivers/media/pci/pt1/pt1.c @@ -18,7 +18,10 @@ */ #include +#include #include +#include +#include #include #include #include @@ -321,7 +324,7 @@ static int pt1_unlock(struct pt1 *pt1) for (i = 0; i < 3; i++) { if (pt1_read_reg(pt1, 0) & 0x8000) return 0; - schedule_timeout_uninterruptible((HZ + 999) / 1000); + usleep_range(1000, 2000); } dev_err(&pt1->pdev->dev, "could not unlock\n"); return -EIO; @@ -335,7 +338,7 @@ static int pt1_reset_pci(struct pt1 *pt1) for (i = 0; i < 10; i++) { if (pt1_read_reg(pt1, 0) & 0x0001) return 0; - schedule_timeout_uninterruptible((HZ + 999) / 1000); + usleep_range(1000, 2000); } dev_err(&pt1->pdev->dev, "could not reset PCI\n"); return -EIO; @@ -349,7 +352,7 @@ static int pt1_reset_ram(struct pt1 *pt1) for (i = 0; i < 10; i++) { if (pt1_read_reg(pt1, 0) & 0x0002) return 0; - schedule_timeout_uninterruptible((HZ + 999) / 1000); + usleep_range(1000, 2000); } dev_err(&pt1->pdev->dev, "could not reset RAM\n"); return -EIO; @@ -366,7 +369,7 @@ static int pt1_do_enable_ram(struct pt1 *pt1) if ((pt1_read_reg(pt1, 0) & 0x0004) != status) return 0; } - schedule_timeout_uninterruptible((HZ + 999) / 1000); + usleep_range(1000, 2000); } dev_err(&pt1->pdev->dev, "could not enable RAM\n"); return -EIO; @@ -376,7 +379,7 @@ static int pt1_enable_ram(struct pt1 *pt1) { int i, ret; int phase; - schedule_timeout_uninterruptible((HZ + 999) / 1000); + usleep_range(1000, 2000); phase = pt1->pdev->device == 0x211a ? 128 : 166; for (i = 0; i < phase; i++) { ret = pt1_do_enable_ram(pt1); @@ -463,6 +466,9 @@ static int pt1_thread(void *data) struct pt1_buffer_page *page; bool was_frozen; +#define PT1_FETCH_DELAY 10 +#define PT1_FETCH_DELAY_DELTA 2 + pt1 = data; set_freezable(); @@ -476,7 +482,13 @@ static int pt1_thread(void *data) page = pt1->tables[pt1->table_index].bufs[pt1->buf_index].page; if (!pt1_filter(pt1, page)) { - schedule_timeout_interruptible((HZ + 999) / 1000); + ktime_t delay; + + delay = PT1_FETCH_DELAY * NSEC_PER_MSEC; + set_current_state(TASK_INTERRUPTIBLE); + schedule_hrtimeout_range(&delay, + PT1_FETCH_DELAY_DELTA * NSEC_PER_MSEC, + HRTIMER_MODE_REL); continue; } @@ -712,7 +724,7 @@ pt1_update_power(struct pt1 *pt1) adap = pt1->adaps[i]; switch (adap->voltage) { case SEC_VOLTAGE_13: /* actually 11V */ - bits |= 1 << 1; + bits |= 1 << 2; break; case SEC_VOLTAGE_18: /* actually 15V */ bits |= 1 << 1 | 1 << 2; @@ -766,7 +778,7 @@ static int pt1_wakeup(struct dvb_frontend *fe) adap = container_of(fe->dvb, struct pt1_adapter, adap); adap->sleep = 0; pt1_update_power(adap->pt1); - schedule_timeout_uninterruptible((HZ + 999) / 1000); + usleep_range(1000, 2000); ret = config_demod(adap->demod_i2c_client, adap->pt1->fe_clk); if (ret == 0 && adap->orig_init) @@ -1073,7 +1085,7 @@ static int pt1_i2c_end(struct pt1 *pt1, int addr) do { if (signal_pending(current)) return -EINTR; - schedule_timeout_interruptible((HZ + 999) / 1000); + usleep_range(1000, 2000); } while (pt1_read_reg(pt1, 0) & 0x0080); return 0; } @@ -1376,11 +1388,11 @@ static int pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pt1->power = 1; pt1_update_power(pt1); - schedule_timeout_uninterruptible((HZ + 49) / 50); + msleep(20); pt1->reset = 0; pt1_update_power(pt1); - schedule_timeout_uninterruptible((HZ + 999) / 1000); + usleep_range(1000, 2000); ret = pt1_init_frontends(pt1);
[PATCH v2 2/5] tuners: add new i2c driver for Sharp qm1d1b0004 ISDB-S tuner
From: Akihiro Tsukada The tuner is used in Earthsoft PT1/PT2 DVB boards, and the driver was extraced from (the former) va1j5jf8007s.c of PT1. it might contain PT1 specific configs. Signed-off-by: Akihiro Tsukada --- Changes since v1: - none drivers/media/tuners/Kconfig | 7 + drivers/media/tuners/Makefile | 1 + drivers/media/tuners/qm1d1b0004.c | 264 ++ drivers/media/tuners/qm1d1b0004.h | 24 4 files changed, 296 insertions(+) create mode 100644 drivers/media/tuners/qm1d1b0004.c create mode 100644 drivers/media/tuners/qm1d1b0004.h diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig index 6687514df97..147f3cd0bb9 100644 --- a/drivers/media/tuners/Kconfig +++ b/drivers/media/tuners/Kconfig @@ -284,4 +284,11 @@ config MEDIA_TUNER_QM1D1C0042 default m if !MEDIA_SUBDRV_AUTOSELECT help Sharp QM1D1C0042 trellis coded 8PSK tuner driver. + +config MEDIA_TUNER_QM1D1B0004 + tristate "Sharp QM1D1B0004 tuner" + depends on MEDIA_SUPPORT && I2C + default m if !MEDIA_SUBDRV_AUTOSELECT + help + Sharp QM1D1B0004 ISDB-S tuner driver. endmenu diff --git a/drivers/media/tuners/Makefile b/drivers/media/tuners/Makefile index 0ff21f1c7ee..7b4f8423501 100644 --- a/drivers/media/tuners/Makefile +++ b/drivers/media/tuners/Makefile @@ -41,6 +41,7 @@ obj-$(CONFIG_MEDIA_TUNER_IT913X) += it913x.o obj-$(CONFIG_MEDIA_TUNER_R820T) += r820t.o obj-$(CONFIG_MEDIA_TUNER_MXL301RF) += mxl301rf.o obj-$(CONFIG_MEDIA_TUNER_QM1D1C0042) += qm1d1c0042.o +obj-$(CONFIG_MEDIA_TUNER_QM1D1B0004) += qm1d1b0004.o obj-$(CONFIG_MEDIA_TUNER_M88RS6000T) += m88rs6000t.o obj-$(CONFIG_MEDIA_TUNER_TDA18250) += tda18250.o diff --git a/drivers/media/tuners/qm1d1b0004.c b/drivers/media/tuners/qm1d1b0004.c new file mode 100644 index 000..9dac1b875c1 --- /dev/null +++ b/drivers/media/tuners/qm1d1b0004.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sharp QM1D1B0004 satellite tuner + * + * Copyright (C) 2014 Akihiro Tsukada + * + * based on (former) drivers/media/pci/pt1/va1j5jf8007s.c. + */ + +/* + * Note: + * Since the data-sheet of this tuner chip is not available, + * this driver lacks some tuner_ops and config options. + * In addition, the implementation might be dependent on the specific use + * in the FE module: VA1J5JF8007S and/or in the product: Earthsoft PT1/PT2. + */ + +#include +#include +#include +#include "qm1d1b0004.h" + +/* + * Tuner I/F (copied from the former va1j5jf8007s.c) + * b[0] I2C addr + * b[1] "0":1, BG:2, divider_quotient[7:3]:5 + * b[2] divider_quotient[2:0]:3, divider_remainder:5 + * b[3] "111":3, LPF[3:2]:2, TM:1, "0":1, REF:1 + * b[4] BANDX, PSC:1, LPF[1:0]:2, DIV:1, "0":1 + * + * PLL frequency step := + *REF == 0 -> PLL XTL frequency(4MHz) / 8 + *REF == 1 -> PLL XTL frequency(4MHz) / 4 + * + * PreScaler := + *PSC == 0 -> x32 + *PSC == 1 -> x16 + * + * divider_quotient := (frequency / PLL frequency step) / PreScaler + * divider_remainder := (frequency / PLL frequency step) % PreScaler + * + * LPF := LPF Frequency / 1000 / 2 - 2 + * LPF Frequency @ baudrate=28.86Mbps = 3 + * + * band (1..9) + * band 1 (freq < 986000) -> DIV:1, BANDX:5, PSC:1 + * band 2 (freq < 1072000) -> DIV:1, BANDX:6, PSC:1 + * band 3 (freq < 1154000) -> DIV:1, BANDX:7, PSC:0 + * band 4 (freq < 1291000) -> DIV:0, BANDX:1, PSC:0 + * band 5 (freq < 1447000) -> DIV:0, BANDX:2, PSC:0 + * band 6 (freq < 1615000) -> DIV:0, BANDX:3, PSC:0 + * band 7 (freq < 1791000) -> DIV:0, BANDX:4, PSC:0 + * band 8 (freq < 1972000) -> DIV:0, BANDX:5, PSC:0 + * band 9 (freq < 215) -> DIV:0, BANDX:6, PSC:0 + */ + +#define QM1D1B0004_PSC_MASK (1 << 4) + +#define QM1D1B0004_XTL_FREQ 4000 +#define QM1D1B0004_LPF_FALLBACK 3 + +static const struct qm1d1b0004_config default_cfg = { + .lpf_freq = QM1D1B0004_CFG_LPF_DFLT, + .half_step = false, +}; + +struct qm1d1b0004_state { + struct qm1d1b0004_config cfg; + struct i2c_client *i2c; +}; + + +struct qm1d1b0004_cb_map { + u32 frequency; + u8 cb; +}; + +static const struct qm1d1b0004_cb_map cb_maps[] = { + { 986000, 0xb2 }, + { 1072000, 0xd2 }, + { 1154000, 0xe2 }, + { 1291000, 0x20 }, + { 1447000, 0x40 }, + { 1615000, 0x60 }, + { 1791000, 0x80 }, + { 1972000, 0xa0 }, +}; + +static u8 lookup_cb(u32 frequency) +{ + int i; + const struct qm1d1b0004_cb_map *map; + + for (i = 0; i < ARRAY_SIZE(cb_maps); i++) { + map = &cb_maps[i]; + if (frequency < map->frequency) + return map->cb; + } + return 0xc0; +} + +static int qm1d1b0004_set_params(struct dvb_frontend *fe) +{ + struct qm1d1b0004_state *state; + u32 frequency, pll, lpf_freq; + u16 word; + u8 buf[4], cb, lpf; + int ret; + + state = fe->tuner_priv; + frequency = fe->dtv_proper
[PATCH v2 1/5] dvb-frontends/dvb-pll: add tda6651 ISDB-T pll_desc
From: Akihiro Tsukada This patch adds a PLL "description" of Philips TDA6651 for ISDB-T. It was extracted from (the former) va1j5jf8007t.c of EarthSoft PT1, thus the desc might include PT1 specific configs. Signed-off-by: Akihiro Tsukada --- Changes since v1: - use new style of specifying pll_desc of the tuner drivers/media/dvb-frontends/dvb-pll.c | 24 drivers/media/dvb-frontends/dvb-pll.h | 2 ++ 2 files changed, 26 insertions(+) diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index deb27aefb9b..62363786e98 100644 --- a/drivers/media/dvb-frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c @@ -550,6 +550,28 @@ static const struct dvb_pll_desc dvb_pll_tua6034_friio = { } }; +/* Philips TDA6651 ISDB-T, used in Earthsoft PT1 */ +static const struct dvb_pll_desc dvb_pll_tda665x_earth_pt1 = { + .name = "Philips TDA6651 ISDB-T (EarthSoft PT1)", + .min= 9000, + .max= 77000, + .iffreq = 5700, + .initdata = (u8[]){ 5, 0x0e, 0x7f, 0xc1, 0x80, 0x80 }, + .count = 10, + .entries = { + { 14000, 142857, 0xc1, 0x81 }, + { 17000, 142857, 0xc1, 0xa1 }, + { 22000, 142857, 0xc1, 0x62 }, + { 33000, 142857, 0xc1, 0xa2 }, + { 40200, 142857, 0xc1, 0xe2 }, + { 45000, 142857, 0xc1, 0x64 }, + { 55000, 142857, 0xc1, 0x84 }, + { 6, 142857, 0xc1, 0xa4 }, + { 7, 142857, 0xc1, 0xc4 }, + { 77000, 142857, 0xc1, 0xe4 }, + } +}; + /* --- */ static const struct dvb_pll_desc *pll_list[] = { @@ -574,6 +596,7 @@ static const struct dvb_pll_desc *pll_list[] = { [DVB_PLL_SAMSUNG_TBDU18132] = &dvb_pll_samsung_tbdu18132, [DVB_PLL_SAMSUNG_TBMU24112] = &dvb_pll_samsung_tbmu24112, [DVB_PLL_TUA6034_FRIIO] = &dvb_pll_tua6034_friio, + [DVB_PLL_TDA665X_EARTH_PT1] = &dvb_pll_tda665x_earth_pt1, }; /* --- */ @@ -896,6 +919,7 @@ static const struct i2c_device_id dvb_pll_id[] = { {DVB_PLL_TDEE4_NAME, DVB_PLL_TDEE4}, {DVB_PLL_THOMSON_DTT7520X_NAME, DVB_PLL_THOMSON_DTT7520X}, {DVB_PLL_TUA6034_FRIIO_NAME, DVB_PLL_TUA6034_FRIIO}, + {DVB_PLL_TDA665X_EARTH_PT1_NAME, DVB_PLL_TDA665X_EARTH_PT1}, {} }; diff --git a/drivers/media/dvb-frontends/dvb-pll.h b/drivers/media/dvb-frontends/dvb-pll.h index c1c27c0d1b1..ddaa5d2efd8 100644 --- a/drivers/media/dvb-frontends/dvb-pll.h +++ b/drivers/media/dvb-frontends/dvb-pll.h @@ -30,6 +30,7 @@ #define DVB_PLL_TDEE4 18 #define DVB_PLL_THOMSON_DTT7520X 19 #define DVB_PLL_TUA6034_FRIIO 20 +#define DVB_PLL_TDA665X_EARTH_PT1 21 #define DVB_PLL_THOMSON_DTT7579_NAME "dtt7579" #define DVB_PLL_THOMSON_DTT759X_NAME"dtt759x" @@ -51,6 +52,7 @@ #define DVB_PLL_TDEE4_NAME "tdee4" #define DVB_PLL_THOMSON_DTT7520X_NAME "dtt7520x" #define DVB_PLL_TUA6034_FRIIO_NAME "tua6034_friio" +#define DVB_PLL_TDA665X_EARTH_PT1_NAME "tda665x_earthpt1" struct dvb_pll_config { struct dvb_frontend *fe; -- 2.16.3
[PATCH v2 0/5] dvb/pci/pt1: decompose earth-pt1 into sub drivers
From: Akihiro Tsukada Changes since v1: - use new style of specifying pll_desc of the terrestrial tuner Akihiro Tsukada (5): dvb-frontends/dvb-pll: add tda6651 ISDB-T pll_desc tuners: add new i2c driver for Sharp qm1d1b0004 ISDB-S tuner dvb: earth-pt1: decompose pt1 driver into sub drivers dvb: earth-pt1: add support for suspend/resume dvb: earth-pt1: replace schedule_timeout with usleep_range drivers/media/dvb-frontends/dvb-pll.c | 24 ++ drivers/media/dvb-frontends/dvb-pll.h | 2 + drivers/media/pci/pt1/Kconfig | 3 + drivers/media/pci/pt1/Makefile| 3 +- drivers/media/pci/pt1/pt1.c | 470 -- drivers/media/pci/pt1/va1j5jf8007s.c | 732 -- drivers/media/pci/pt1/va1j5jf8007s.h | 42 -- drivers/media/pci/pt1/va1j5jf8007t.c | 532 drivers/media/pci/pt1/va1j5jf8007t.h | 42 -- drivers/media/tuners/Kconfig | 7 + drivers/media/tuners/Makefile | 1 + drivers/media/tuners/qm1d1b0004.c | 264 drivers/media/tuners/qm1d1b0004.h | 24 ++ 13 files changed, 677 insertions(+), 1469 deletions(-) delete mode 100644 drivers/media/pci/pt1/va1j5jf8007s.c delete mode 100644 drivers/media/pci/pt1/va1j5jf8007s.h delete mode 100644 drivers/media/pci/pt1/va1j5jf8007t.c delete mode 100644 drivers/media/pci/pt1/va1j5jf8007t.h create mode 100644 drivers/media/tuners/qm1d1b0004.c create mode 100644 drivers/media/tuners/qm1d1b0004.h -- 2.16.3
[PATCH v2 4/5] dvb: earth-pt1: add support for suspend/resume
From: Akihiro Tsukada Without this patch, re-loading of the module was required after resume. Signed-off-by: Akihiro Tsukada --- Changes since v1: - none drivers/media/pci/pt1/pt1.c | 107 +++- 1 file changed, 105 insertions(+), 2 deletions(-) diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c index 60bf517e7fe..80510616c4c 100644 --- a/drivers/media/pci/pt1/pt1.c +++ b/drivers/media/pci/pt1/pt1.c @@ -461,12 +461,18 @@ static int pt1_thread(void *data) { struct pt1 *pt1; struct pt1_buffer_page *page; + bool was_frozen; pt1 = data; set_freezable(); - while (!kthread_should_stop()) { - try_to_freeze(); + while (!kthread_freezable_should_stop(&was_frozen)) { + if (was_frozen) { + int i; + + for (i = 0; i < PT1_NR_ADAPS; i++) + pt1_set_stream(pt1, i, !!pt1->adaps[i]->users); + } page = pt1->tables[pt1->table_index].bufs[pt1->buf_index].page; if (!pt1_filter(pt1, page)) { @@ -1165,6 +1171,98 @@ static void pt1_i2c_init(struct pt1 *pt1) pt1_i2c_emit(pt1, i, 0, 0, 1, 1, 0); } +#ifdef CONFIG_PM_SLEEP + +static int pt1_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct pt1 *pt1 = pci_get_drvdata(pdev); + + pt1_init_streams(pt1); + pt1_disable_ram(pt1); + pt1->power = 0; + pt1->reset = 1; + pt1_update_power(pt1); + return 0; +} + +static int pt1_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct pt1 *pt1 = pci_get_drvdata(pdev); + int ret; + int i; + + pt1->power = 0; + pt1->reset = 1; + pt1_update_power(pt1); + + pt1_i2c_init(pt1); + pt1_i2c_wait(pt1); + + ret = pt1_sync(pt1); + if (ret < 0) + goto resume_err; + + pt1_identify(pt1); + + ret = pt1_unlock(pt1); + if (ret < 0) + goto resume_err; + + ret = pt1_reset_pci(pt1); + if (ret < 0) + goto resume_err; + + ret = pt1_reset_ram(pt1); + if (ret < 0) + goto resume_err; + + ret = pt1_enable_ram(pt1); + if (ret < 0) + goto resume_err; + + pt1_init_streams(pt1); + + pt1->power = 1; + pt1_update_power(pt1); + msleep(20); + + pt1->reset = 0; + pt1_update_power(pt1); + usleep_range(1000, 2000); + + for (i = 0; i < PT1_NR_ADAPS; i++) + dvb_frontend_reinitialise(pt1->adaps[i]->fe); + + pt1_init_table_count(pt1); + for (i = 0; i < pt1_nr_tables; i++) { + int j; + + for (j = 0; j < PT1_NR_BUFS; j++) + pt1->tables[i].bufs[j].page->upackets[PT1_NR_UPACKETS-1] + = 0; + pt1_increment_table_count(pt1); + } + pt1_register_tables(pt1, pt1->tables[0].addr >> PT1_PAGE_SHIFT); + + pt1->table_index = 0; + pt1->buf_index = 0; + for (i = 0; i < PT1_NR_ADAPS; i++) { + pt1->adaps[i]->upacket_count = 0; + pt1->adaps[i]->packet_count = 0; + pt1->adaps[i]->st_count = -1; + } + + return 0; + +resume_err: + dev_info(&pt1->pdev->dev, "failed to resume PT1/PT2."); + return 0; /* resume anyway */ +} + +#endif /* CONFIG_PM_SLEEP */ + static void pt1_remove(struct pci_dev *pdev) { struct pt1 *pt1; @@ -1325,11 +1423,16 @@ static const struct pci_device_id pt1_id_table[] = { }; MODULE_DEVICE_TABLE(pci, pt1_id_table); +static SIMPLE_DEV_PM_OPS(pt1_pm_ops, pt1_suspend, pt1_resume); + static struct pci_driver pt1_driver = { .name = DRIVER_NAME, .probe = pt1_probe, .remove = pt1_remove, .id_table = pt1_id_table, +#if CONFIG_PM_SLEEP + .driver.pm = &pt1_pm_ops, +#endif }; module_pci_driver(pt1_driver); -- 2.16.3
[PATCH] media: coda: do not try to propagate format if capture queue busy
The driver helpfully resets the capture queue format and selection rectangle whenever output format is changed. This only works while the capture queue is not busy. Signed-off-by: Philipp Zabel --- drivers/media/platform/coda/coda-common.c | 28 +++- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index 04e35d70ce2e..d3e22c14fad4 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -786,9 +786,8 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, struct v4l2_format *f) { struct coda_ctx *ctx = fh_to_ctx(priv); - struct coda_q_data *q_data_src; struct v4l2_format f_cap; - struct v4l2_rect r; + struct vb2_queue *dst_vq; int ret; ret = coda_try_fmt_vid_out(file, priv, f); @@ -804,23 +803,26 @@ static int coda_s_fmt_vid_out(struct file *file, void *priv, ctx->ycbcr_enc = f->fmt.pix.ycbcr_enc; ctx->quantization = f->fmt.pix.quantization; + dst_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); + if (!dst_vq) + return -EINVAL; + + /* +* Setting the capture queue format is not possible while the capture +* queue is still busy. This is not an error, but the user will have to +* make sure themselves that the capture format is set correctly before +* starting the output queue again. +*/ + if (vb2_is_busy(dst_vq)) + return 0; + memset(&f_cap, 0, sizeof(f_cap)); f_cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; coda_g_fmt(file, priv, &f_cap); f_cap.fmt.pix.width = f->fmt.pix.width; f_cap.fmt.pix.height = f->fmt.pix.height; - ret = coda_try_fmt_vid_cap(file, priv, &f_cap); - if (ret) - return ret; - - q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT); - r.left = 0; - r.top = 0; - r.width = q_data_src->width; - r.height = q_data_src->height; - - return coda_s_fmt(ctx, &f_cap, &r); + return coda_s_fmt_vid_cap(file, priv, &f_cap); } static int coda_reqbufs(struct file *file, void *priv, -- 2.16.1
[PATCH v4 2/5] dvb-frontends/dvb-pll: add tua6034 ISDB-T tuner used in Friio
From: Akihiro Tsukada This driver already contains tua6034-based device settings, but they are not for ISDB-T and have different parameters. Signed-off-by: Akihiro Tsukada --- Changes since v3: - rebase on the new style of specifying pll_desc Changes since v2: (patch #27927 dvb: tua6034: add a new driver for Infineon tua6034 tuner) - extends dvb-pll instead of creating a new driver drivers/media/dvb-frontends/dvb-pll.c | 19 +++ drivers/media/dvb-frontends/dvb-pll.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index e2a93aae04f..deb27aefb9b 100644 --- a/drivers/media/dvb-frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c @@ -533,6 +533,23 @@ static const struct dvb_pll_desc dvb_pll_alps_tdee4 = { } }; +/* Infineon TUA6034 ISDB-T, used in Friio */ +/* CP cur. 50uA, AGC takeover: 103dBuV, PORT3 on */ +static const struct dvb_pll_desc dvb_pll_tua6034_friio = { + .name = "Infineon TUA6034 ISDB-T (Friio)", + .min= 9000, + .max= 77000, + .iffreq = 5700, + .initdata = (u8[]){ 4, 0x9a, 0x50, 0xb2, 0x08 }, + .sleepdata = (u8[]){ 4, 0x9a, 0x70, 0xb3, 0x0b }, + .count = 3, + .entries = { + { 17000, 142857, 0xba, 0x09 }, + { 47000, 142857, 0xba, 0x0a }, + { 77000, 142857, 0xb2, 0x08 }, + } +}; + /* --- */ static const struct dvb_pll_desc *pll_list[] = { @@ -556,6 +573,7 @@ static const struct dvb_pll_desc *pll_list[] = { [DVB_PLL_SAMSUNG_TDTC9251DH0]= &dvb_pll_samsung_tdtc9251dh0, [DVB_PLL_SAMSUNG_TBDU18132] = &dvb_pll_samsung_tbdu18132, [DVB_PLL_SAMSUNG_TBMU24112] = &dvb_pll_samsung_tbmu24112, + [DVB_PLL_TUA6034_FRIIO] = &dvb_pll_tua6034_friio, }; /* --- */ @@ -877,6 +895,7 @@ static const struct i2c_device_id dvb_pll_id[] = { {DVB_PLL_SAMSUNG_TBMU24112_NAME, DVB_PLL_SAMSUNG_TBMU24112}, {DVB_PLL_TDEE4_NAME, DVB_PLL_TDEE4}, {DVB_PLL_THOMSON_DTT7520X_NAME, DVB_PLL_THOMSON_DTT7520X}, + {DVB_PLL_TUA6034_FRIIO_NAME, DVB_PLL_TUA6034_FRIIO}, {} }; diff --git a/drivers/media/dvb-frontends/dvb-pll.h b/drivers/media/dvb-frontends/dvb-pll.h index e96994bf668..c1c27c0d1b1 100644 --- a/drivers/media/dvb-frontends/dvb-pll.h +++ b/drivers/media/dvb-frontends/dvb-pll.h @@ -29,6 +29,7 @@ #define DVB_PLL_SAMSUNG_TBMU24112 17 #define DVB_PLL_TDEE4 18 #define DVB_PLL_THOMSON_DTT7520X 19 +#define DVB_PLL_TUA6034_FRIIO 20 #define DVB_PLL_THOMSON_DTT7579_NAME "dtt7579" #define DVB_PLL_THOMSON_DTT759X_NAME"dtt759x" @@ -49,6 +50,7 @@ #define DVB_PLL_SAMSUNG_TBMU24112_NAME "tbmu24112" #define DVB_PLL_TDEE4_NAME "tdee4" #define DVB_PLL_THOMSON_DTT7520X_NAME "dtt7520x" +#define DVB_PLL_TUA6034_FRIIO_NAME "tua6034_friio" struct dvb_pll_config { struct dvb_frontend *fe; -- 2.16.3
[PATCH v4 4/5] dvb-usb-v2/gl861: use usleep_range() for short delay
From: Akihiro Tsukada As the kernel doc "timers-howto.txt" reads, short delay with msleep() can take much longer. In a case of raspbery-pi platform where CONFIG_HZ_100 was set, it actually affected the init of Friio devices since it issues lots of i2c transactions with short delay. Signed-off-by: Akihiro Tsukada --- Changes since v3: - none drivers/media/usb/dvb-usb-v2/gl861.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c index a0280126bfc..6f6dfa65bba 100644 --- a/drivers/media/usb/dvb-usb-v2/gl861.c +++ b/drivers/media/usb/dvb-usb-v2/gl861.c @@ -45,7 +45,7 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, return -EINVAL; } - msleep(1); /* avoid I2C errors */ + usleep_range(1000, 2000); /* avoid I2C errors */ return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type, value, index, rbuf, rlen, 2000); -- 2.16.3
[PATCH v4 5/5] dvb-usb-v2/gl861: ensure USB message buffers DMA'able
From: Akihiro Tsukada i2c message buf might be on stack. Signed-off-by: Akihiro Tsukada --- Changes since v3: - none drivers/media/usb/dvb-usb-v2/gl861.c | 20 +--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c index 6f6dfa65bba..a5c83b561a4 100644 --- a/drivers/media/usb/dvb-usb-v2/gl861.c +++ b/drivers/media/usb/dvb-usb-v2/gl861.c @@ -22,6 +22,8 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, u16 value = addr << (8 + 1); int wo = (rbuf == NULL || rlen == 0); /* write-only */ u8 req, type; + u8 *buf; + int ret; if (wo) { req = GL861_REQ_I2C_WRITE; @@ -44,11 +46,23 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, KBUILD_MODNAME, wlen); return -EINVAL; } - + buf = NULL; + if (rlen > 0) { + buf = kmalloc(rlen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + } usleep_range(1000, 2000); /* avoid I2C errors */ - return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type, - value, index, rbuf, rlen, 2000); + ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), req, type, + value, index, buf, rlen, 2000); + if (rlen > 0) { + if (ret > 0) + memcpy(rbuf, buf, rlen); + kfree(buf); + } + + return ret; } /* Friio specific I2C read/write */ -- 2.16.3
[PATCH v5 3/5] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861
From: Akihiro Tsukada Friio device contains "gl861" bridge and "tc90522" demod, for which the separate drivers are already in the kernel. But friio driver was monolithic and did not use them, practically copying those features. This patch decomposes friio driver into sub drivers and re-uses existing ones, thus reduces some code. It adds some features to gl861, to support the friio-specific init/config of the devices and implement i2c communications to the tuner via demod with USB vendor requests. Signed-off-by: Akihiro Tsukada --- Changes since v4: - use new style of specifying pll_desc of the tuner driver Changes since v3: - make dvb_usb_device_properties static Changes since v2: (patch #27928, dvb-usb-friio: split and merge into dvb-usbv2-gl861) - used the new i2c binding helpers instead of my own one - merged gl861-friio.c with gl861.c drivers/media/usb/dvb-usb-v2/Kconfig | 5 +- drivers/media/usb/dvb-usb-v2/gl861.c | 465 ++- drivers/media/usb/dvb-usb-v2/gl861.h | 1 + drivers/media/usb/dvb-usb/Kconfig| 6 - drivers/media/usb/dvb-usb/Makefile | 3 - drivers/media/usb/dvb-usb/friio-fe.c | 441 - drivers/media/usb/dvb-usb/friio.c| 522 --- drivers/media/usb/dvb-usb/friio.h| 99 --- 8 files changed, 462 insertions(+), 1080 deletions(-) delete mode 100644 drivers/media/usb/dvb-usb/friio-fe.c delete mode 100644 drivers/media/usb/dvb-usb/friio.c delete mode 100644 drivers/media/usb/dvb-usb/friio.h diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig index 0e4944b2b0f..e0a1f377295 100644 --- a/drivers/media/usb/dvb-usb-v2/Kconfig +++ b/drivers/media/usb/dvb-usb-v2/Kconfig @@ -95,10 +95,13 @@ config DVB_USB_GL861 tristate "Genesys Logic GL861 USB2.0 support" depends on DVB_USB_V2 select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TC90522 if MEDIA_SUBDRV_AUTOSELECT select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT + select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT help Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 - receiver with USB ID 0db0:5581. + receiver with USB ID 0db0:5581, Friio White ISDB-T receiver + with USB ID 0x7a69:0001. config DVB_USB_LME2510 tristate "LME DM04/QQBOX DVB-S USB2.0 support" diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c index b1b09c54786..a0280126bfc 100644 --- a/drivers/media/usb/dvb-usb-v2/gl861.c +++ b/drivers/media/usb/dvb-usb-v2/gl861.c @@ -10,6 +10,8 @@ #include "zl10353.h" #include "qt1010.h" +#include "tc90522.h" +#include "dvb-pll.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); @@ -49,6 +51,80 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr, value, index, rbuf, rlen, 2000); } +/* Friio specific I2C read/write */ +/* special USB request is used in Friio's init/config */ +static int +gl861_i2c_rawwrite(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen) +{ + u8 *buf; + int ret; + + buf = kmalloc(wlen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + usleep_range(1000, 2000); /* avoid I2C errors */ + memcpy(buf, wbuf, wlen); + ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), +GL861_REQ_I2C_RAW, GL861_WRITE, +addr << (8 + 1), 0x0100, buf, wlen, 2000); + kfree(buf); + return ret; +} + +/* + * In Friio, + * I2C commnucations to the tuner are relay'ed via the demod (via the bridge), + * so its encapsulation to USB message is different from the one to the demod. + */ +static int +gl861_i2c_rawread(struct dvb_usb_device *d, u8 addr, u8 *rbuf, u16 rlen) +{ + u8 *buf; + int ret; + + buf = kmalloc(rlen, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + usleep_range(1000, 2000); /* avoid I2C errors */ + + ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), +GL861_REQ_I2C_READ, GL861_READ, +addr << (8 + 1), 0x0100, buf, rlen, 2000); + if (ret > 0 && rbuf) + memcpy(rbuf, buf, rlen); + kfree(buf); + + return ret; +} + +static int +gl861_i2c_relay_write(struct dvb_usb_device *d, struct i2c_msg *msg) +{ + u8 *buf; + int ret; + + if (msg->flags & I2C_M_RD) + return -EINVAL; + if (msg->len < 2) + return -EINVAL; + + buf = kmalloc(msg->len - 1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + memcpy(buf, msg->buf + 1, msg->len - 1); + + usleep_range(1000, 2000); /* avoid I2C errors */ + + ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0), +GL861_REQ_I2C_RAW, GL861_WRITE, +
[PATCH v4 1/5] dvb-frontends/dvb-pll: add i2c driver support
From: Akihiro Tsukada registers the module as an i2c driver, but keeps dvb_pll_attach() untouched for compatibility. Signed-off-by: Akihiro Tsukada --- Changes since v3: - use standard i2c_device_id instead of dvb_pll_config drivers/media/dvb-frontends/dvb-pll.c | 67 +++ drivers/media/dvb-frontends/dvb-pll.h | 24 + 2 files changed, 91 insertions(+) diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index 5553b89b804..e2a93aae04f 100644 --- a/drivers/media/dvb-frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c @@ -827,6 +827,73 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, } EXPORT_SYMBOL(dvb_pll_attach); + +static int +dvb_pll_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct dvb_pll_config *cfg; + struct dvb_frontend *fe; + unsigned int desc_id; + + cfg = client->dev.platform_data; + fe = cfg->fe; + i2c_set_clientdata(client, fe); + desc_id = (unsigned int) id->driver_data; + + if (!dvb_pll_attach(fe, client->addr, client->adapter, desc_id)) + return -ENOMEM; + + dev_info(&client->dev, "DVB Simple Tuner attached.\n"); + return 0; +} + +static int dvb_pll_remove(struct i2c_client *client) +{ + struct dvb_frontend *fe; + + fe = i2c_get_clientdata(client); + dvb_pll_release(fe); + return 0; +} + + +static const struct i2c_device_id dvb_pll_id[] = { + {DVB_PLL_THOMSON_DTT7579_NAME,DVB_PLL_THOMSON_DTT7579}, + {DVB_PLL_THOMSON_DTT759X_NAME,DVB_PLL_THOMSON_DTT759X}, + {DVB_PLL_LG_Z201_NAME,DVB_PLL_LG_Z201}, + {DVB_PLL_UNKNOWN_1_NAME, DVB_PLL_UNKNOWN_1}, + {DVB_PLL_TUA6010XS_NAME, DVB_PLL_TUA6010XS}, + {DVB_PLL_ENV57H1XD5_NAME, DVB_PLL_ENV57H1XD5}, + {DVB_PLL_TUA6034_NAME,DVB_PLL_TUA6034}, + {DVB_PLL_TDA665X_NAME,DVB_PLL_TDA665X}, + {DVB_PLL_TDED4_NAME, DVB_PLL_TDED4}, + {DVB_PLL_TDHU2_NAME, DVB_PLL_TDHU2}, + {DVB_PLL_SAMSUNG_TBMV_NAME, DVB_PLL_SAMSUNG_TBMV}, + {DVB_PLL_PHILIPS_SD1878_TDA8261_NAME, DVB_PLL_PHILIPS_SD1878_TDA8261}, + {DVB_PLL_OPERA1_NAME, DVB_PLL_OPERA1}, + {DVB_PLL_SAMSUNG_DTOS403IH102A_NAME, DVB_PLL_SAMSUNG_DTOS403IH102A}, + {DVB_PLL_SAMSUNG_TDTC9251DH0_NAME,DVB_PLL_SAMSUNG_TDTC9251DH0}, + {DVB_PLL_SAMSUNG_TBDU18132_NAME, DVB_PLL_SAMSUNG_TBDU18132}, + {DVB_PLL_SAMSUNG_TBMU24112_NAME, DVB_PLL_SAMSUNG_TBMU24112}, + {DVB_PLL_TDEE4_NAME, DVB_PLL_TDEE4}, + {DVB_PLL_THOMSON_DTT7520X_NAME, DVB_PLL_THOMSON_DTT7520X}, + {} +}; + + +MODULE_DEVICE_TABLE(i2c, dvb_pll_id); + +static struct i2c_driver dvb_pll_driver = { + .driver = { + .name = "dvb_pll", + }, + .probe= dvb_pll_probe, + .remove = dvb_pll_remove, + .id_table = dvb_pll_id, +}; + +module_i2c_driver(dvb_pll_driver); + MODULE_DESCRIPTION("dvb pll library"); MODULE_AUTHOR("Gerd Knorr"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb-frontends/dvb-pll.h b/drivers/media/dvb-frontends/dvb-pll.h index ca885e71d2f..e96994bf668 100644 --- a/drivers/media/dvb-frontends/dvb-pll.h +++ b/drivers/media/dvb-frontends/dvb-pll.h @@ -30,6 +30,30 @@ #define DVB_PLL_TDEE4 18 #define DVB_PLL_THOMSON_DTT7520X 19 +#define DVB_PLL_THOMSON_DTT7579_NAME "dtt7579" +#define DVB_PLL_THOMSON_DTT759X_NAME"dtt759x" +#define DVB_PLL_LG_Z201_NAME"z201" +#define DVB_PLL_UNKNOWN_1_NAME "unknown_1" +#define DVB_PLL_TUA6010XS_NAME "tua6010xs" +#define DVB_PLL_ENV57H1XD5_NAME "env57h1xd5" +#define DVB_PLL_TUA6034_NAME"tua6034" +#define DVB_PLL_TDA665X_NAME"tda665x" +#define DVB_PLL_TDED4_NAME "tded4" +#define DVB_PLL_TDHU2_NAME "tdhu2" +#define DVB_PLL_SAMSUNG_TBMV_NAME "tbmv" +#define DVB_PLL_PHILIPS_SD1878_TDA8261_NAME "sd1878_tda8261" +#define DVB_PLL_OPERA1_NAME "opera1" +#define DVB_PLL_SAMSUNG_DTOS403IH102A_NAME "dtos403ih102a" +#define DVB_PLL_SAMSUNG_TDTC9251DH0_NAME"tdtc9251dh0" +#define DVB_PLL_SAMSUNG_TBDU18132_NAME "tbdu18132" +#define DVB_PLL_SAMSUNG_TBMU24112_NAME "tbmu24112" +#define DVB_PLL_TDEE4_NAME "tdee4" +#define DVB_PLL_THOMSON_DTT7520X_NAME "dtt7520x" + +struct dvb_pll_config { + struct dvb_frontend *fe; +}; + #if IS_REACHABLE(CONFIG_DVB_PLL) /** * Attach a dvb-pll to the supplied frontend structure. -- 2.16.3
[PATCH v4 0/5] dvb-usb-friio: decompose friio and merge with gl861
From: Akihiro Tsukada This series decomposes dvb-usb-friio into sub drivers and merge the bridge driver with dvb-usb-gl861. As to the demod & tuner drivers, existing drivers are re-used. Changes since v3: - dvb-pll,gl681: use i2c_device_id/i2c_board_info to specify pll_desc Changes since v2: - used the new i2c binding helpers instead of my own one - extends dvb-pll instead of creating a new tuner driver - merged gl861-friio.c with gl861.c - improved module counting - made i2c communications on USB robust (regarding DMA) Replaces: patch #27927, dvb: tua6034: add a new driver for Infineon tua6034 tuner patch #27928, dvb-usb-friio: split and merge into dvb-usbv2-gl861 Akihiro Tsukada (5): dvb-frontends/dvb-pll: add i2c driver support dvb-frontends/dvb-pll: add tua6034 ISDB-T tuner used in Friio dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861 dvb-usb-v2/gl861: use usleep_range() for short delay dvb-usb-v2/gl861: ensure USB message buffers DMA'able drivers/media/dvb-frontends/dvb-pll.c | 86 ++ drivers/media/dvb-frontends/dvb-pll.h | 26 ++ drivers/media/usb/dvb-usb-v2/Kconfig | 5 +- drivers/media/usb/dvb-usb-v2/gl861.c | 485 ++- drivers/media/usb/dvb-usb-v2/gl861.h | 1 + drivers/media/usb/dvb-usb/Kconfig | 6 - drivers/media/usb/dvb-usb/Makefile| 3 - drivers/media/usb/dvb-usb/friio-fe.c | 441 drivers/media/usb/dvb-usb/friio.c | 522 -- drivers/media/usb/dvb-usb/friio.h | 99 --- 10 files changed, 591 insertions(+), 1083 deletions(-) delete mode 100644 drivers/media/usb/dvb-usb/friio-fe.c delete mode 100644 drivers/media/usb/dvb-usb/friio.c delete mode 100644 drivers/media/usb/dvb-usb/friio.h -- 2.16.3
Re: [PATCH v4] dvb-usb/friio, dvb-usb-v2/gl861: decompose friio and merge with gl861
Hi Akihiro, Thank you for the patch! Yet something to improve: [auto build test ERROR on linuxtv-media/master] [also build test ERROR on v4.16-rc7 next-20180328] [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/tskd08-gmail-com/dvb-usb-friio-dvb-usb-v2-gl861-decompose-friio-and-merge-with-gl861/20180329-001436 base: git://linuxtv.org/media_tree.git master config: x86_64-randconfig-x019-201812 (attached as .config) compiler: gcc-7 (Debian 7.3.0-1) 7.3.0 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All errors (new ones prefixed by >>): >> drivers/media/usb/dvb-usb-v2/gl861.c:203:24: error: field 'tuner_cfg' has >> incomplete type struct dvb_pll_config tuner_cfg; ^ >> drivers/media/usb/dvb-usb-v2/gl861.c:210:3: error: field name not in record >> or union initializer .desc_id = DVB_PLL_TUA6034_FRIIO, ^ drivers/media/usb/dvb-usb-v2/gl861.c:210:3: note: (near initialization for 'friio_config.tuner_cfg') >> drivers/media/usb/dvb-usb-v2/gl861.c:210:14: error: 'DVB_PLL_TUA6034_FRIIO' >> undeclared here (not in a function); did you mean 'DVB_PLL_TUA6034'? .desc_id = DVB_PLL_TUA6034_FRIIO, ^ DVB_PLL_TUA6034 drivers/media/usb/dvb-usb-v2/gl861.c: In function 'friio_tuner_attach': >> drivers/media/usb/dvb-usb-v2/gl861.c:414:24: error: storage size of 'cfg' >> isn't known struct dvb_pll_config cfg; ^~~ drivers/media/usb/dvb-usb-v2/gl861.c:414:24: warning: unused variable 'cfg' [-Wunused-variable] vim +/tuner_cfg +203 drivers/media/usb/dvb-usb-v2/gl861.c 197 198 struct friio_config { 199 struct i2c_board_info demod_info; 200 struct tc90522_config demod_cfg; 201 202 struct i2c_board_info tuner_info; > 203 struct dvb_pll_config tuner_cfg; 204 }; 205 206 static const struct friio_config friio_config = { 207 .demod_info = { I2C_BOARD_INFO(TC90522_I2C_DEV_TER, 0x18), }, 208 .tuner_info = { I2C_BOARD_INFO("dvb_pll", 0x60), }, 209 .tuner_cfg = { > 210 .desc_id = DVB_PLL_TUA6034_FRIIO, 211 }, 212 }; 213 --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
Re: [PATCH 2/8] PCI: Add pci_find_common_upstream_dev()
On 28/03/18 10:02 AM, Christian König wrote: > Yeah, that looks very similar to what I picked up from the older > patches, going to read up on that after my vacation. Yeah, I was just reading through your patchset and there are a lot of similarities. Though, I'm not sure what you're trying to accomplish as I could not find a cover letter and it seems to only enable one driver. Is it meant to enable DMA transactions only between two AMD GPUs? I also don't see where you've taken into account the PCI bus address. On some architectures this is not the same as the CPU physical address. > Just in general why are you interested in the "distance" of the devices? We've taken a general approach where some drivers may provide p2p memory (ie. an NVMe card or an RDMA NIC) and other drivers make use of it (ie. the NVMe-of driver). The orchestrator driver needs to find the most applicable provider device for a transaction in a situation that may have multiple providers and multiple clients. So the most applicable provider is the one that's closest ("distance"-wise) to all the clients for the P2P transaction. > And BTW: At least for writes that Peer 2 Peer transactions between > different root complexes work is actually more common than the other way > around. Maybe on x86 with hardware made in the last few years. But on PowerPC, ARM64, and likely a lot more the chance of support is *much* less. Also, hardware that only supports P2P stores is hardly full support and is insufficient for our needs. > So I'm a bit torn between using a blacklist or a whitelist. A whitelist > is certainly more conservative approach, but that could get a bit long. I think a whitelist approach is correct. Given old hardware and other architectures, a black list is going to be too long and too difficult to comprehensively populate. Logan
Re: [PATCH 2/8] PCI: Add pci_find_common_upstream_dev()
Am 28.03.2018 um 17:47 schrieb Logan Gunthorpe: On 28/03/18 09:07 AM, Christian König wrote: Am 28.03.2018 um 14:38 schrieb Christoph Hellwig: On Sun, Mar 25, 2018 at 12:59:54PM +0200, Christian König wrote: From: "wda...@nvidia.com" Add an interface to find the first device which is upstream of both devices. Please work with Logan and base this on top of the outstanding peer to peer patchset. Can you point me to that? The last code I could find about that was from 2015. The latest posted series is here: https://lkml.org/lkml/2018/3/12/830 However, we've made some significant changes to the area that's similar to what you are doing. You can find lasted un-posted here: https://github.com/sbates130272/linux-p2pmem/tree/pci-p2p-v4-pre2 Specifically this function would be of interest to you: https://github.com/sbates130272/linux-p2pmem/blob/0e9468ae2a5a5198513dd12990151e09105f0351/drivers/pci/p2pdma.c#L239 However, the difference between what we are doing is that we are interested in the distance through the common upstream device and you appear to be finding the actual common device. Yeah, that looks very similar to what I picked up from the older patches, going to read up on that after my vacation. Just in general why are you interested in the "distance" of the devices? And BTW: At least for writes that Peer 2 Peer transactions between different root complexes work is actually more common than the other way around. So I'm a bit torn between using a blacklist or a whitelist. A whitelist is certainly more conservative approach, but that could get a bit long. Thanks, Christian. Thanks, Logan
Re: [PATCH 2/8] PCI: Add pci_find_common_upstream_dev()
On 28/03/18 09:07 AM, Christian König wrote: > Am 28.03.2018 um 14:38 schrieb Christoph Hellwig: >> On Sun, Mar 25, 2018 at 12:59:54PM +0200, Christian König wrote: >>> From: "wda...@nvidia.com" >>> >>> Add an interface to find the first device which is upstream of both >>> devices. >> Please work with Logan and base this on top of the outstanding peer >> to peer patchset. > > Can you point me to that? The last code I could find about that was from > 2015. The latest posted series is here: https://lkml.org/lkml/2018/3/12/830 However, we've made some significant changes to the area that's similar to what you are doing. You can find lasted un-posted here: https://github.com/sbates130272/linux-p2pmem/tree/pci-p2p-v4-pre2 Specifically this function would be of interest to you: https://github.com/sbates130272/linux-p2pmem/blob/0e9468ae2a5a5198513dd12990151e09105f0351/drivers/pci/p2pdma.c#L239 However, the difference between what we are doing is that we are interested in the distance through the common upstream device and you appear to be finding the actual common device. Thanks, Logan
Re: [PATCH 2/8] PCI: Add pci_find_common_upstream_dev()
Am 28.03.2018 um 14:38 schrieb Christoph Hellwig: On Sun, Mar 25, 2018 at 12:59:54PM +0200, Christian König wrote: From: "wda...@nvidia.com" Add an interface to find the first device which is upstream of both devices. Please work with Logan and base this on top of the outstanding peer to peer patchset. Can you point me to that? The last code I could find about that was from 2015. Thanks, Christian.
Re: [PATCH 09/15] v4l: vsp1: Replace manual DRM pipeline input setup in vsp1_du_setup_lif
Hi Laurent, On 26/02/18 21:45, Laurent Pinchart wrote: > The vsp1_du_setup_lif() function setups the DRM pipeline input manually. s/ setups the / sets up the / > This duplicates the code from the vsp1_du_pipeline_setup_input() > function. Replace the manual implementation by a call to the function. > > As the pipeline has no enabled input in vsp1_du_setup_lif(), the > vsp1_du_pipeline_setup_input() function will not setup any RPF, and will > thus not setup formats on the BRU sink pads. This isn't a problem as all > inputs are disabled, and the BRU sink pads will be reconfigured from the > atomic commit handler when inputs will be enabled. > > Signed-off-by: Laurent Pinchart Aside from the above, Reviewed-by: Kieran Bingham > --- > drivers/media/platform/vsp1/vsp1_drm.c | 40 > +- > 1 file changed, 6 insertions(+), 34 deletions(-) > > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c > b/drivers/media/platform/vsp1/vsp1_drm.c > index 6ad8aa6c8138..00ce99bd1605 100644 > --- a/drivers/media/platform/vsp1/vsp1_drm.c > +++ b/drivers/media/platform/vsp1/vsp1_drm.c > @@ -412,47 +412,19 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int > pipe_index, > dev_dbg(vsp1->dev, "%s: configuring LIF%u with format %ux%u\n", > __func__, pipe_index, cfg->width, cfg->height); > > - /* > - * Configure the format at the BRU sinks and propagate it through the > - * pipeline. > - */ > + /* Setup formats through the pipeline. */ > + ret = vsp1_du_pipeline_setup_input(vsp1, pipe); > + if (ret < 0) > + return ret; > + > memset(&format, 0, sizeof(format)); > format.which = V4L2_SUBDEV_FORMAT_ACTIVE; > - > - for (i = 0; i < pipe->bru->source_pad; ++i) { > - format.pad = i; > - > - format.format.width = cfg->width; > - format.format.height = cfg->height; > - format.format.code = MEDIA_BUS_FMT_ARGB_1X32; > - format.format.field = V4L2_FIELD_NONE; > - > - ret = v4l2_subdev_call(&pipe->bru->subdev, pad, > -set_fmt, NULL, &format); > - if (ret < 0) > - return ret; > - > - dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n", > - __func__, format.format.width, format.format.height, > - format.format.code, BRU_NAME(pipe->bru), i); > - } > - > - format.pad = pipe->bru->source_pad; > + format.pad = RWPF_PAD_SINK; > format.format.width = cfg->width; > format.format.height = cfg->height; > format.format.code = MEDIA_BUS_FMT_ARGB_1X32; > format.format.field = V4L2_FIELD_NONE; > > - ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL, > -&format); > - if (ret < 0) > - return ret; > - > - dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n", > - __func__, format.format.width, format.format.height, > - format.format.code, BRU_NAME(pipe->bru), i); > - > - format.pad = RWPF_PAD_SINK; > ret = v4l2_subdev_call(&pipe->output->entity.subdev, pad, set_fmt, NULL, > &format); > if (ret < 0) >
Re: [PATCH 07/15] v4l: vsp1: Move DRM atomic commit pipeline setup to separate function
Hi Laurent, On 26/02/18 21:45, Laurent Pinchart wrote: > The DRM pipeline setup code used at atomic commit time is similar to the > setup code used when enabling the pipeline. Move it to a separate > function in order to share it. > > Signed-off-by: Laurent Pinchart Assuming no hidden secret code addition in this code move that I haven't seen.. Only a minor nit below asking if the function should be pluralised (_inputs, rather than _input) Reviewed-by: Kieran Bingham > --- > drivers/media/platform/vsp1/vsp1_drm.c | 347 > + > 1 file changed, 180 insertions(+), 167 deletions(-) > > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c > b/drivers/media/platform/vsp1/vsp1_drm.c > index 9a043a915c0b..7bf697ba7969 100644 > --- a/drivers/media/platform/vsp1/vsp1_drm.c > +++ b/drivers/media/platform/vsp1/vsp1_drm.c > @@ -46,6 +46,185 @@ static void vsp1_du_pipeline_frame_end(struct > vsp1_pipeline *pipe, > * Pipeline Configuration > */ > > +/* Setup one RPF and the connected BRU sink pad. */ > +static int vsp1_du_pipeline_setup_rpf(struct vsp1_device *vsp1, > + struct vsp1_pipeline *pipe, > + struct vsp1_rwpf *rpf, > + unsigned int bru_input) > +{ > + struct v4l2_subdev_selection sel; > + struct v4l2_subdev_format format; > + const struct v4l2_rect *crop; > + int ret; > + > + /* > + * Configure the format on the RPF sink pad and propagate it up to the > + * BRU sink pad. > + */ > + crop = &vsp1->drm->inputs[rpf->entity.index].crop; > + > + memset(&format, 0, sizeof(format)); > + format.which = V4L2_SUBDEV_FORMAT_ACTIVE; > + format.pad = RWPF_PAD_SINK; > + format.format.width = crop->width + crop->left; > + format.format.height = crop->height + crop->top; > + format.format.code = rpf->fmtinfo->mbus; > + format.format.field = V4L2_FIELD_NONE; > + > + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, > +&format); > + if (ret < 0) > + return ret; > + > + dev_dbg(vsp1->dev, > + "%s: set format %ux%u (%x) on RPF%u sink\n", > + __func__, format.format.width, format.format.height, > + format.format.code, rpf->entity.index); > + > + memset(&sel, 0, sizeof(sel)); > + sel.which = V4L2_SUBDEV_FORMAT_ACTIVE; > + sel.pad = RWPF_PAD_SINK; > + sel.target = V4L2_SEL_TGT_CROP; > + sel.r = *crop; > + > + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_selection, NULL, > +&sel); > + if (ret < 0) > + return ret; > + > + dev_dbg(vsp1->dev, > + "%s: set selection (%u,%u)/%ux%u on RPF%u sink\n", > + __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, > + rpf->entity.index); > + > + /* > + * RPF source, hardcode the format to ARGB to turn on format > + * conversion if needed. > + */ > + format.pad = RWPF_PAD_SOURCE; > + > + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, get_fmt, NULL, > +&format); > + if (ret < 0) > + return ret; > + > + dev_dbg(vsp1->dev, > + "%s: got format %ux%u (%x) on RPF%u source\n", > + __func__, format.format.width, format.format.height, > + format.format.code, rpf->entity.index); > + > + format.format.code = MEDIA_BUS_FMT_ARGB_1X32; > + > + ret = v4l2_subdev_call(&rpf->entity.subdev, pad, set_fmt, NULL, > +&format); > + if (ret < 0) > + return ret; > + > + /* BRU sink, propagate the format from the RPF source. */ > + format.pad = bru_input; > + > + ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_fmt, NULL, > +&format); > + if (ret < 0) > + return ret; > + > + dev_dbg(vsp1->dev, "%s: set format %ux%u (%x) on %s pad %u\n", > + __func__, format.format.width, format.format.height, > + format.format.code, BRU_NAME(pipe->bru), format.pad); > + > + sel.pad = bru_input; > + sel.target = V4L2_SEL_TGT_COMPOSE; > + sel.r = vsp1->drm->inputs[rpf->entity.index].compose; > + > + ret = v4l2_subdev_call(&pipe->bru->subdev, pad, set_selection, NULL, > +&sel); > + if (ret < 0) > + return ret; > + > + dev_dbg(vsp1->dev, "%s: set selection (%u,%u)/%ux%u on %s pad %u\n", > + __func__, sel.r.left, sel.r.top, sel.r.width, sel.r.height, > + BRU_NAME(pipe->bru), sel.pad); > + > + return 0; > +} > + > +static unsigned int rpf_zpos(struct vsp1_device *vsp1, struct vsp1_rwpf *rpf) > +{ > + return vsp1->drm->inputs[rpf->entity.index].zpos; > +} > + > +/* Setup the input side of the pipeline (RPFs and BRU sink pads). */ > +static int vsp1_du_pipeline_setup_
Re: [PATCH 12/18] media: staging: atomisp: avoid a warning if 32 bits build
Em Wed, 28 Mar 2018 17:13:29 +0300 Dan Carpenter escreveu: > On Mon, Mar 26, 2018 at 05:10:45PM -0400, Mauro Carvalho Chehab wrote: > > Checking if a size_t value is bigger than ULONG_INT only makes > > sense if building on 64 bits, as warned by: > > > > drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c:697 > > gmin_get_config_var() warn: impossible condition '(*out_len > (~0)) => > > (0-u32max > u32max)' > > > > Signed-off-by: Mauro Carvalho Chehab > > --- > > .../staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c| > > 2 ++ > > 1 file changed, 2 insertions(+) > > > > diff --git > > a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c > > b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c > > index be0c5e11e86b..3283c1b05d6a 100644 > > --- > > a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c > > +++ > > b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c > > @@ -693,9 +693,11 @@ static int gmin_get_config_var(struct device *dev, > > const char *var, > > for (i = 0; i < sizeof(var8) && var8[i]; i++) > > var16[i] = var8[i]; > > > > +#ifdef CONFIG_64BIT > > /* To avoid owerflows when calling the efivar API */ > > if (*out_len > ULONG_MAX) > > return -EINVAL; > > +#endif > > I should just silence this particular warning in Smatch. I feel like > this is a pretty common thing and the ifdefs aren't very pretty. :( Smatch actually warned about a real thing here: atomisp is doing a check in 32bits that it is always true. So, IMO, something is needed to prevent 32bits extra useless code somehow, perhaps via some EFI-var specific function that would do nothing on 32 bits. That's the first time I noticed this code on media (although I might have missed something), so I guess this kind of checking is actually not that common. Regards, Mauro
Re: [PATCH 06/15] v4l: vsp1: Share duplicated DRM pipeline configuration code
On 26/02/18 21:45, Laurent Pinchart wrote: > Move the duplicated DRM pipeline configuration code to a function and > call it from vsp1_du_setup_lif() and vsp1_du_atomic_flush(). > > Signed-off-by: Laurent Pinchart LGTM. I thought I had a bit of deja-vu on this patch ... but I can't seem to find anything already posted. Reviewed-by: Kieran Bingham > --- > drivers/media/platform/vsp1/vsp1_drm.c | 95 > +++--- > 1 file changed, 43 insertions(+), 52 deletions(-) > > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c > b/drivers/media/platform/vsp1/vsp1_drm.c > index e210917fdc3f..9a043a915c0b 100644 > --- a/drivers/media/platform/vsp1/vsp1_drm.c > +++ b/drivers/media/platform/vsp1/vsp1_drm.c > @@ -42,6 +42,47 @@ static void vsp1_du_pipeline_frame_end(struct > vsp1_pipeline *pipe, > drm_pipe->du_complete(drm_pipe->du_private, completed); > } > > +/* > - > + * Pipeline Configuration > + */ > + > +/* Configure all entities in the pipeline. */ > +static void vsp1_du_pipeline_configure(struct vsp1_pipeline *pipe) > +{ > + struct vsp1_entity *entity; > + struct vsp1_entity *next; > + struct vsp1_dl_list *dl; > + > + dl = vsp1_dl_list_get(pipe->output->dlm); > + > + list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) { > + /* Disconnect unused RPFs from the pipeline. */ > + if (entity->type == VSP1_ENTITY_RPF && > + !pipe->inputs[entity->index]) { > + vsp1_dl_list_write(dl, entity->route->reg, > +VI6_DPR_NODE_UNUSED); > + > + entity->pipe = NULL; > + list_del(&entity->list_pipe); > + > + continue; > + } > + > + vsp1_entity_route_setup(entity, pipe, dl); > + > + if (entity->ops->configure) { > + entity->ops->configure(entity, pipe, dl, > +VSP1_ENTITY_PARAMS_INIT); > + entity->ops->configure(entity, pipe, dl, > +VSP1_ENTITY_PARAMS_RUNTIME); > + entity->ops->configure(entity, pipe, dl, > +VSP1_ENTITY_PARAMS_PARTITION); > + } > + } > + > + vsp1_dl_list_commit(dl); > +} > + > /* > - > * DU Driver API > */ > @@ -85,9 +126,6 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int > pipe_index, > struct vsp1_drm_pipeline *drm_pipe; > struct vsp1_pipeline *pipe; > struct vsp1_bru *bru; > - struct vsp1_entity *entity; > - struct vsp1_entity *next; > - struct vsp1_dl_list *dl; > struct v4l2_subdev_format format; > unsigned long flags; > unsigned int i; > @@ -239,22 +277,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int > pipe_index, > vsp1_write(vsp1, VI6_DISP_IRQ_ENB, 0); > > /* Configure all entities in the pipeline. */ > - dl = vsp1_dl_list_get(pipe->output->dlm); > - > - list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) { > - vsp1_entity_route_setup(entity, pipe, dl); > - > - if (entity->ops->configure) { > - entity->ops->configure(entity, pipe, dl, > -VSP1_ENTITY_PARAMS_INIT); > - entity->ops->configure(entity, pipe, dl, > -VSP1_ENTITY_PARAMS_RUNTIME); > - entity->ops->configure(entity, pipe, dl, > -VSP1_ENTITY_PARAMS_PARTITION); > - } > - } > - > - vsp1_dl_list_commit(dl); > + vsp1_du_pipeline_configure(pipe); > > /* Start the pipeline. */ > spin_lock_irqsave(&pipe->irqlock, flags); > @@ -490,15 +513,9 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned > int pipe_index) > struct vsp1_pipeline *pipe = &drm_pipe->pipe; > struct vsp1_rwpf *inputs[VSP1_MAX_RPF] = { NULL, }; > struct vsp1_bru *bru = to_bru(&pipe->bru->subdev); > - struct vsp1_entity *entity; > - struct vsp1_entity *next; > - struct vsp1_dl_list *dl; > unsigned int i; > int ret; > > - /* Prepare the display list. */ > - dl = vsp1_dl_list_get(pipe->output->dlm); > - > /* Count the number of enabled inputs and sort them by Z-order. */ > pipe->num_inputs = 0; > > @@ -557,33 +574,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned > int pipe_index) > __func__, rpf->entity.index); > } > > - /* Configure all entities in the pipeline. */ > - list_for_each_entry_safe(entity, next, &pipe->entities, list_pipe) { > - /* Disconnect unuse
Re: [PATCH 12/18] media: staging: atomisp: avoid a warning if 32 bits build
On Mon, Mar 26, 2018 at 05:10:45PM -0400, Mauro Carvalho Chehab wrote: > Checking if a size_t value is bigger than ULONG_INT only makes > sense if building on 64 bits, as warned by: > > drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c:697 > gmin_get_config_var() warn: impossible condition '(*out_len > (~0)) => > (0-u32max > u32max)' > > Signed-off-by: Mauro Carvalho Chehab > --- > .../staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c| 2 > ++ > 1 file changed, 2 insertions(+) > > diff --git > a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c > b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c > index be0c5e11e86b..3283c1b05d6a 100644 > --- a/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c > +++ b/drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c > @@ -693,9 +693,11 @@ static int gmin_get_config_var(struct device *dev, const > char *var, > for (i = 0; i < sizeof(var8) && var8[i]; i++) > var16[i] = var8[i]; > > +#ifdef CONFIG_64BIT > /* To avoid owerflows when calling the efivar API */ > if (*out_len > ULONG_MAX) > return -EINVAL; > +#endif I should just silence this particular warning in Smatch. I feel like this is a pretty common thing and the ifdefs aren't very pretty. :( regards, dan carpenter
Re: [PATCH 05/15] v4l: vsp1: Use vsp1_entity.pipe to check if entity belongs to a pipeline
Hi Laurent, On 26/02/18 21:45, Laurent Pinchart wrote: > The DRM pipeline handling code uses the entity's pipe list head to check > whether the entity is already included in a pipeline. This method is a > bit fragile in the sense that it uses list_empty() on a list_head that > is a list member. Replace it by a simpler check for the entity pipe > pointer. Yes, excellent. > > Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham > --- > drivers/media/platform/vsp1/vsp1_drm.c | 8 > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c > b/drivers/media/platform/vsp1/vsp1_drm.c > index a7ad85ab0b08..e210917fdc3f 100644 > --- a/drivers/media/platform/vsp1/vsp1_drm.c > +++ b/drivers/media/platform/vsp1/vsp1_drm.c > @@ -119,9 +119,9 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int > pipe_index, >* Remove the RPF from the pipe and the list of BRU >* inputs. >*/ > - WARN_ON(list_empty(&rpf->entity.list_pipe)); > + WARN_ON(!rpf->entity.pipe); Does this WARN_ON() have much value any more ? I think it could probably be removed... unless there is a race between potential calls through vsp1_du_atomic_flush() and vsp1_du_setup_lif() - but I would be very surprised if that wasn't protected at the DRM levels. (Removing it if chosen doesn't need to be in this patch though) > rpf->entity.pipe = NULL; > - list_del_init(&rpf->entity.list_pipe); > + list_del(&rpf->entity.list_pipe); > pipe->inputs[i] = NULL; > > bru->inputs[rpf->bru_input].rpf = NULL; > @@ -537,7 +537,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned > int pipe_index) > continue; > } > > - if (list_empty(&rpf->entity.list_pipe)) { > + if (!rpf->entity.pipe) { > rpf->entity.pipe = pipe; > list_add_tail(&rpf->entity.list_pipe, &pipe->entities); > } > @@ -566,7 +566,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned > int pipe_index) > VI6_DPR_NODE_UNUSED); > > entity->pipe = NULL; > - list_del_init(&entity->list_pipe); > + list_del(&entity->list_pipe); > > continue; > } >
[PATCH 22/29] videobuf2-core: add vb2_core_request_has_buffers
From: Hans Verkuil Add a new helper function that returns true if a media_request contains buffers. Signed-off-by: Hans Verkuil --- drivers/media/common/videobuf2/videobuf2-core.c | 12 include/media/videobuf2-core.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 7499221da1c5..b9d898b116c4 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -1333,6 +1333,18 @@ static const struct media_request_object_ops vb2_core_req_ops = { .release = vb2_req_release, }; +bool vb2_core_request_has_buffers(struct media_request *req) +{ + struct media_request_object *obj; + + list_for_each_entry(obj, &req->objects, list) { + if (obj->ops == &vb2_core_req_ops) + return true; + } + return false; +} +EXPORT_SYMBOL_GPL(vb2_core_request_has_buffers); + int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb, struct media_request *req) { diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 72663c2a3ba3..e23dc028aee7 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h @@ -1158,4 +1158,6 @@ bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb); */ int vb2_verify_memory_type(struct vb2_queue *q, enum vb2_memory memory, unsigned int type); + +bool vb2_core_request_has_buffers(struct media_request *req); #endif /* _MEDIA_VIDEOBUF2_CORE_H */ -- 2.15.1
[PATCH 20/29] videobuf2-core: integrate with media requests
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 | 106 +--- drivers/media/common/videobuf2/videobuf2-v4l2.c | 4 +- drivers/media/dvb-core/dvb_vb2.c| 2 +- include/media/videobuf2-core.h | 17 +++- 4 files changed, 113 insertions(+), 16 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 3d436ccb61f8..7499221da1c5 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -930,6 +930,14 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state) vb->state = state; } atomic_dec(&q->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(&vb->req_obj); + media_request_object_put(&vb->req_obj); + } + spin_unlock_irqrestore(&q->done_lock, flags); trace_vb2_buf_done(q, vb); @@ -1276,11 +1284,60 @@ static int __buf_prepare(struct vb2_buffer *vb, const void *pb) return 0; } -int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb) +static int vb2_req_prepare(struct media_request_object *obj) { - struct vb2_buffer *vb; + 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; + + ret = __buf_prepare(vb, NULL); + if (ret) + vb->state = VB2_BUF_STATE_IN_REQUEST; + 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); + + __vb2_dqbuf(vb); + vb->state = VB2_BUF_STATE_IN_REQUEST; + 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); + + vb2_core_qbuf(vb->vb2_queue, vb->index, NULL, NULL); +} + +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 media_request *req) +{ + struct vb2_buffer *vb; + vb = q->bufs[index]; if (vb->state != VB2_BUF_STATE_DEQUEUED) { dprintk(1, "invalid buffer state %d\n", @@ -1288,16 +1345,24 @@ int vb2_core_prepare_buf(struct vb2_queue *q, unsigned int index, void *pb) return -EINVAL; } - ret = __buf_prepare(vb, pb); - if (ret) - return ret; + if (req) { + vb->state = VB2_BUF_STATE_IN_REQUEST; + media_request_object_init(&vb->req_obj); + media_request_object_bind(req, &vb2_core_req_ops, + q, &vb->req_obj); + } else { + int ret = __buf_prepare(vb, pb); + + if (ret) + return ret; + } /* Fill buffer information for the userspace */ call_void_bufop(q, fill_user_buffer, vb, pb); dprintk(2, "prepare of buffer %d succeeded\n", vb->index); - return ret; + return 0; } EXPORT_SYMBOL_GPL(vb2_core_prepare_buf); @@ -1364,13 +1429,27 @@ static int vb2_start_streaming(struct vb2_queue *q) return ret; } -int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb) +int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb, + struct media_request *req) { struct vb2_buffer *vb; int ret; vb = q->bufs[index]; + if (vb->state == VB2_BUF_STATE_DEQUEUED && req) { + vb->state = VB2_BUF_STATE_IN_REQUEST; + media_request_object_init(&vb->req_obj); + media_request_object_bind(req, &vb2_core_req_ops, + q, &vb->req_obj); + /* Fill buffer information for the userspace */ + if (pb) +
[PATCH 23/29] videobuf2-v4l2: add vb2_request_queue helper
From: Hans Verkuil Generic helper function that checks if there are buffers in the request and if so, prepares and queues all objects in the request. Signed-off-by: Hans Verkuil --- drivers/media/common/videobuf2/videobuf2-v4l2.c | 39 + include/media/videobuf2-v4l2.h | 3 ++ 2 files changed, 42 insertions(+) diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index d3ea5ec697a6..ebb951db7a8f 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -1054,6 +1054,45 @@ void vb2_ops_wait_finish(struct vb2_queue *vq) } EXPORT_SYMBOL_GPL(vb2_ops_wait_finish); +int vb2_request_queue(struct media_request *req) +{ + struct media_request_object *obj; + struct media_request_object *failed_obj = NULL; + int ret = 0; + + if (!vb2_core_request_has_buffers(req)) + return -ENOENT; + + list_for_each_entry(obj, &req->objects, list) { + if (!obj->ops->prepare) + continue; + + ret = obj->ops->prepare(obj); + + if (ret) { + failed_obj = obj; + break; + } + } + + if (ret) { + list_for_each_entry(obj, &req->objects, list) { + if (obj == failed_obj) + break; + if (obj->ops->unprepare) + obj->ops->unprepare(obj); + } + return ret; + } + + list_for_each_entry(obj, &req->objects, list) { + if (obj->ops->queue) + obj->ops->queue(obj); + } + return 0; +} +EXPORT_SYMBOL_GPL(vb2_request_queue); + 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-v4l2.h b/include/media/videobuf2-v4l2.h index cf312ab4e7e8..0baa3023d7ad 100644 --- a/include/media/videobuf2-v4l2.h +++ b/include/media/videobuf2-v4l2.h @@ -301,4 +301,7 @@ void vb2_ops_wait_prepare(struct vb2_queue *vq); */ void vb2_ops_wait_finish(struct vb2_queue *vq); +struct media_request; +int vb2_request_queue(struct media_request *req); + #endif /* _MEDIA_VIDEOBUF2_V4L2_H */ -- 2.15.1
[PATCH 21/29] videobuf2-v4l2: integrate with media requests
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 | 77 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 | 12 +++- 14 files changed, 99 insertions(+), 32 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index b8d370b97cca..d3ea5ec697a6 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 | \ @@ -318,13 +321,17 @@ 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; + *p_req = NULL; if (b->type != q->type) { dprintk(1, "%s: invalid buffer type\n", opname); return -EINVAL; @@ -354,7 +361,31 @@ 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; + + 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_find(mdev, b->request_fd); + if (IS_ERR(req)) { + dprintk(1, "%s: invalid request_fd\n", opname); + return PTR_ERR(req); + } + *p_req = req; + + return 0; } /* @@ -437,6 +468,9 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) case VB2_BUF_STATE_ACTIVE: b->flags |= V4L2_BUF_FLAG_QUEUED; break; + case VB2_BUF_STATE_IN_REQUEST: + b->flags |= V4L2_BUF_FLAG_IN_REQUEST; + break; case VB2_BUF_STATE_ERROR: b->flags |= V4L2_BUF_FLAG_ERROR; /* fall through */ @@ -455,6 +489,10 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) if (vb2_buffer_in_use(q, vb)) b->flags |= V4L2_BUF_FLAG_MAPPED; + if (vb->req_obj.req) { + b->flags |= V4L2_BUF_FLAG_REQUEST_FD; + b->request_fd = -1; + } if (!q->is_output && b->flags & V4L2_BUF_FLAG_DONE && @@ -533,8 +571,10 @@ int vb2_reqbufs
[PATCH 27/29] vim2m: support requests
From: Hans Verkuil Add support for requests to vim2m. Signed-off-by: Hans Verkuil --- drivers/media/platform/vim2m.c | 25 + 1 file changed, 25 insertions(+) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index 9b18b32c255d..2dcf0ea85705 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -387,8 +387,26 @@ static void device_run(void *priv) src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); + /* Apply request if needed */ + if (src_buf->vb2_buf.req_obj.req) + v4l2_ctrl_request_setup(src_buf->vb2_buf.req_obj.req, + &ctx->hdl); + if (dst_buf->vb2_buf.req_obj.req && + dst_buf->vb2_buf.req_obj.req != src_buf->vb2_buf.req_obj.req) + v4l2_ctrl_request_setup(dst_buf->vb2_buf.req_obj.req, + &ctx->hdl); + device_process(ctx, src_buf, dst_buf); + /* Complete request if needed */ + if (src_buf->vb2_buf.req_obj.req) + v4l2_ctrl_request_complete(src_buf->vb2_buf.req_obj.req, + &ctx->hdl); + if (dst_buf->vb2_buf.req_obj.req && + dst_buf->vb2_buf.req_obj.req != src_buf->vb2_buf.req_obj.req) + v4l2_ctrl_request_complete(dst_buf->vb2_buf.req_obj.req, + &ctx->hdl); + /* Run a timer, which simulates a hardware irq */ schedule_irq(dev, ctx->transtime); } @@ -823,6 +841,8 @@ static void vim2m_stop_streaming(struct vb2_queue *q) vbuf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx); if (vbuf == NULL) return; + v4l2_ctrl_request_complete(vbuf->vb2_buf.req_obj.req, + &ctx->hdl); spin_lock_irqsave(&ctx->dev->irqlock, flags); v4l2_m2m_buf_done(vbuf, VB2_BUF_STATE_ERROR); spin_unlock_irqrestore(&ctx->dev->irqlock, flags); @@ -1003,6 +1023,10 @@ static const struct v4l2_m2m_ops m2m_ops = { .job_abort = job_abort, }; +static const struct media_device_ops m2m_media_ops = { + .req_queue = vb2_request_queue, +}; + static int vim2m_probe(struct platform_device *pdev) { struct vim2m_dev *dev; @@ -1027,6 +1051,7 @@ static int vim2m_probe(struct platform_device *pdev) dev->mdev.dev = &pdev->dev; strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model)); media_device_init(&dev->mdev); + dev->mdev.ops = &m2m_media_ops; dev->v4l2_dev.mdev = &dev->mdev; dev->pad[0].flags = MEDIA_PAD_FL_SINK; dev->pad[1].flags = MEDIA_PAD_FL_SOURCE; -- 2.15.1
[PATCH 25/29] media: vim2m: add media device
From: Alexandre Courbot 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: Alexandre Courbot --- drivers/media/platform/vim2m.c | 43 +- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index 065483e62db4..ef970434af13 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(&dev->irqlock); - - ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); - if (ret) - return ret; - atomic_set(&dev->num_inst, 0); mutex_init(&dev->dev_mutex); @@ -1013,6 +1012,22 @@ static int vim2m_probe(struct platform_device *pdev) vfd->lock = &dev->dev_mutex; vfd->v4l2_dev = &dev->v4l2_dev; +#ifdef CONFIG_MEDIA_CONTROLLER + dev->mdev.dev = &pdev->dev; + strlcpy(dev->mdev.model, "vim2m", sizeof(dev->mdev.model)); + media_device_init(&dev->mdev); + dev->v4l2_dev.mdev = &dev->mdev; + dev->pad[0].flags = MEDIA_PAD_FL_SINK; + dev->pad[1].flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&vfd->entity, 2, dev->pad); + if (ret) + return ret; +#endif + + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); + if (ret) + goto unreg_media; + ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); if (ret) { v4l2_err(&dev->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(&dev->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(&dev->vfd); unreg_dev: v4l2_device_unregister(&dev->v4l2_dev); +unreg_media: +#ifdef CONFIG_MEDIA_CONTROLLER + media_device_unregister(&dev->mdev); +#endif return ret; } @@ -1050,6 +1076,13 @@ static int vim2m_remove(struct platform_device *pdev) struct vim2m_dev *dev = platform_get_drvdata(pdev); v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME); + +#ifdef CONFIG_MEDIA_CONTROLLER + if (media_devnode_is_registered(dev->mdev.devnode)) + media_device_unregister(&dev->mdev); + media_device_cleanup(&dev->mdev); +#endif + v4l2_m2m_release(dev->m2m_dev); del_timer_sync(&dev->timer); video_unregister_device(&dev->vfd); -- 2.15.1
[PATCH 24/29] Documentation: v4l: document request API
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 --- Documentation/media/uapi/v4l/buffer.rst| 19 +- Documentation/media/uapi/v4l/common.rst| 1 + Documentation/media/uapi/v4l/request-api.rst | 199 + Documentation/media/uapi/v4l/user-func.rst | 1 + .../media/uapi/v4l/vidioc-g-ext-ctrls.rst | 22 ++- .../media/uapi/v4l/vidioc-new-request.rst | 64 +++ Documentation/media/uapi/v4l/vidioc-qbuf.rst | 8 + 7 files changed, 308 insertions(+), 6 deletions(-) create mode 100644 Documentation/media/uapi/v4l/request-api.rst create mode 100644 Documentation/media/uapi/v4l/vidioc-new-request.rst diff --git a/Documentation/media/uapi/v4l/buffer.rst b/Documentation/media/uapi/v4l/buffer.rst index e2c85ddc990b..e23eae12905c 100644 --- a/Documentation/media/uapi/v4l/buffer.rst +++ b/Documentation/media/uapi/v4l/buffer.rst @@ -306,10 +306,13 @@ struct v4l2_buffer - A place holder for future extensions. Drivers and applications must set this to 0. * - __u32 - - ``reserved`` + - ``request_fd`` - - - A place holder for future extensions. Drivers and applications - must set this to 0. + - The file descriptor of the request to queue the buffer to. If specified +and flag ``V4L2_BUF_FLAG_REQUEST_FD`` is set, then the buffer will be + queued to that request. This is set by the user when calling + :ref:`VIDIOC_QBUF` and :ref:`VIDIOC_PREPARE_BUF` and ignored by other + ioctls. @@ -514,6 +517,11 @@ Buffer Flags streaming may continue as normal and the buffer may be reused normally. Drivers set this flag when the ``VIDIOC_DQBUF`` ioctl is called. +* .. _`V4L2-BUF-FLAG-IN-REQUEST`: + + - ``V4L2_BUF_FLAG_IN_REQUEST`` + - 0x0080 + - This buffer is part of a request the hasn't been queued yet. * .. _`V4L2-BUF-FLAG-KEYFRAME`: - ``V4L2_BUF_FLAG_KEYFRAME`` @@ -589,6 +597,11 @@ Buffer Flags the format. Any Any subsequent call to the :ref:`VIDIOC_DQBUF ` ioctl will not block anymore, but return an ``EPIPE`` error code. +* .. _`V4L2-BUF-FLAG-REQUEST-FD`: + + - ``V4L2_BUF_FLAG_REQUEST_FD`` + - 0x0080 + - The ``request_fd`` field contains a valid file descriptor. * .. _`V4L2-BUF-FLAG-TIMESTAMP-MASK`: - ``V4L2_BUF_FLAG_TIMESTAMP_MASK`` diff --git a/Documentation/media/uapi/v4l/common.rst b/Documentation/media/uapi/v4l/common.rst index 13f2ed3fc5a6..a4aa0059d45a 100644 --- a/Documentation/media/uapi/v4l/common.rst +++ b/Documentation/media/uapi/v4l/common.rst @@ -44,3 +44,4 @@ applicable to all devices. crop selection-api streaming-par +request-api diff --git a/Documentation/media/uapi/v4l/request-api.rst b/Documentation/media/uapi/v4l/request-api.rst new file mode 100644 index ..0c1f2896e197 --- /dev/null +++ b/Documentation/media/uapi/v4l/request-api.rst @@ -0,0 +1,199 @@ +.. -*- coding: utf-8; mode: rst -*- + +.. _media-request-api: + +Request API +=== + +The Request API has been designed to allow V4L2 to deal with requirements of +modern devices (stateless codecs, MIPI cameras, ...) and APIs (Android Codec +v2). One such requirement is the ability for devices belonging to the same +pipeline to reconfigure and collaborate closely on a per-frame basis. Another is +efficient support of stateless codecs, which need per-frame controls to be set +asynchronously in order to be efficiently used. + +Supporting these features without the Request API is possible but terribly +inefficient: user-space would have to flush all activity on the media pipeline, +reconfigure it for the next frame, queue the buffers to be processed with that +configuration, and wait until they are all available for dequeing before +considering the next frame. This defeats the purpose of having buffer queues +since in practice only one buffer would be queued at a time. + +The Request API allows a specific configuration of the pipeline (media +controller topology + controls for each device) to be associated with specific +buffers. The parameters are applied by each participating device as buffers +associated to a request flow in. This allows user-space to schedule several +tasks ("requests") with different parameters in advance, knowing that the +parameters will be applied when needed to get the expected result. Controls +values at the time of request completion are also available for reading. + +Usage += + +The Request API is used on top of standard media controller and V4L2 calls, +which are augmented with an extra ``request_fd`` parameter. Request themselves +are allocated from either a supporting V4L2 device node, or a supporting media +controller node. The origin of requests determine their scope: requests +allocat
[PATCH 28/29] vivid: add mc
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 82ec216f2ad8..69386b26d5dd 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 = &dev->mdev; + + /* Initialize media device */ + strlcpy(dev->mdev.model, VIVID_MODULE_NAME, sizeof(dev->mdev.model)); + dev->mdev.dev = &pdev->dev; + media_device_init(&dev->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 = &dev->mutex; video_set_drvdata(vfd, dev); +#ifdef CONFIG_MEDIA_CONTROLLER + dev->vid_cap_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&vfd->entity, 1, &dev->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 = &dev->mutex; video_set_drvdata(vfd, dev); +#ifdef CONFIG_MEDIA_CONTROLLER + dev->vid_out_pad.flags = MEDIA_PAD_FL_SOURCE; + ret = media_entity_pads_init(&vfd->entity, 1, &dev->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(&vfd->entity, 1, &dev->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(&vfd->entity, 1, &dev->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 = &dev->mutex; video_set_drvdata(vfd, dev); +#ifdef CONFIG_MEDIA_CONTROLLER + dev->sdr_cap_pad.flags = MEDIA_PAD_FL_SINK; + ret = media_entity_pads_init(&vfd->entity, 1, &dev->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(&dev->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(&dev->mdev); +#endif video_unregister_device(&dev->radio_tx_dev); video_unregister_device(&dev->radio_rx_dev); video_unregister_device(&dev->sdr_cap_dev); @@ -1444,6 +1501,10 @@ static int vivid_remove(struct platform_device *pdev) if (!dev)
[PATCH 17/29] videodev2.h: Add request_fd field to v4l2_buffer
From: Hans Verkuil When queuing buffers allow for passing the request that should be associated with this buffer. If V4L2_BUF_FLAG_REQUEST_FD is set, then request_fd is used as the file descriptor. If a buffer is stored in a request, but not yet queued to the driver, then V4L2_BUF_FLAG_IN_REQUEST is set. Signed-off-by: Hans Verkuil --- drivers/media/common/videobuf2/videobuf2-v4l2.c | 2 +- drivers/media/usb/cpia2/cpia2_v4l.c | 2 +- drivers/media/v4l2-core/v4l2-compat-ioctl32.c | 9 ++--- drivers/media/v4l2-core/v4l2-ioctl.c| 4 ++-- include/uapi/linux/videodev2.h | 10 +- 5 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index 886a2d8d5c6c..4e9c77f21858 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -204,7 +204,7 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb) b->timecode = vbuf->timecode; b->sequence = vbuf->sequence; b->reserved2 = 0; - b->reserved = 0; + b->request_fd = 0; if (q->is_multiplanar) { /* diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index 99f106b13280..13aee9f67d05 100644 --- a/drivers/media/usb/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c @@ -949,7 +949,7 @@ static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->m.offset = cam->buffers[buf->index].data - cam->frame_buffer; buf->length = cam->frame_size; buf->reserved2 = 0; - buf->reserved = 0; + buf->request_fd = 0; memset(&buf->timecode, 0, sizeof(buf->timecode)); DBG("DQBUF #%d status:%d seq:%d length:%d\n", buf->index, diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c index 0782b3666deb..7e27d0feac94 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -387,7 +387,7 @@ struct v4l2_buffer32 { } m; __u32 length; __u32 reserved2; - __u32 reserved; + __s32 request_fd; }; static int get_v4l2_plane32(struct v4l2_plane __user *up, @@ -486,6 +486,7 @@ static int get_v4l2_buffer32(struct v4l2_buffer __user *kp, { u32 type; u32 length; + s32 request_fd; enum v4l2_memory memory; struct v4l2_plane32 __user *uplane32; struct v4l2_plane __user *uplane; @@ -500,7 +501,9 @@ static int get_v4l2_buffer32(struct v4l2_buffer __user *kp, get_user(memory, &up->memory) || put_user(memory, &kp->memory) || get_user(length, &up->length) || - put_user(length, &kp->length)) + put_user(length, &kp->length) || + get_user(request_fd, &up->request_fd) || + put_user(request_fd, &kp->request_fd)) return -EFAULT; if (V4L2_TYPE_IS_OUTPUT(type)) @@ -605,7 +608,7 @@ static int put_v4l2_buffer32(struct v4l2_buffer __user *kp, copy_in_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) || assign_in_user(&up->sequence, &kp->sequence) || assign_in_user(&up->reserved2, &kp->reserved2) || - assign_in_user(&up->reserved, &kp->reserved) || + assign_in_user(&up->request_fd, &kp->request_fd) || get_user(length, &kp->length) || put_user(length, &up->length)) return -EFAULT; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index ceeb6df0ef19..fd31f18b0aef 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -437,13 +437,13 @@ static void v4l_print_buffer(const void *arg, bool write_only) const struct v4l2_plane *plane; int i; - pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, flags=0x%08x, field=%s, sequence=%d, memory=%s", + pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, request_fd=%d, flags=0x%08x, field=%s, sequence=%d, memory=%s", p->timestamp.tv_sec / 3600, (int)(p->timestamp.tv_sec / 60) % 60, (int)(p->timestamp.tv_sec % 60), (long)p->timestamp.tv_usec, p->index, - prt_names(p->type, v4l2_type_names), + prt_names(p->type, v4l2_type_names), p->request_fd, p->flags, prt_names(p->field, v4l2_field_names), p->sequence, prt_names(p->memory, v4l2_memory_names)); diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h index 6f41baa53787..88e2264b68f8 100644 --- a/include/uapi/linux/videodev2.h +++ b/in
[PATCH 29/29] vivid: add request support
From: Hans Verkuil Add support for requests to vivid. Signed-off-by: Hans Verkuil --- drivers/media/platform/vivid/vivid-core.c| 7 +++ 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 | 8 drivers/media/platform/vivid/vivid-vbi-cap.c | 2 ++ drivers/media/platform/vivid/vivid-vbi-out.c | 2 ++ drivers/media/platform/vivid/vivid-vid-cap.c | 2 ++ drivers/media/platform/vivid/vivid-vid-out.c | 2 ++ 8 files changed, 47 insertions(+) diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c index 69386b26d5dd..20e74d36b673 100644 --- a/drivers/media/platform/vivid/vivid-core.c +++ b/drivers/media/platform/vivid/vivid-core.c @@ -627,6 +627,12 @@ 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_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 +670,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 = &pdev->dev; media_device_init(&dev->mdev); + dev->mdev.ops = &vivid_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 3fdb280c36ca..c192b4b1b9de 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, + &dev->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, + &dev->ctrl_hdl_vid_cap); vb2_buffer_done(&vid_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, + &dev->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, + &dev->ctrl_hdl_vbi_cap); vb2_buffer_done(&vbi_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(&buf->list); + v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req, + &dev->ctrl_hdl_vid_cap); vb2_buffer_done(&buf->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(&buf->list); + v4l2_ctrl_request_complete(buf->vb.vb2_buf.req_obj.req, + &dev->ctrl_hdl_vbi_cap); vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR); dprintk(dev, 2, "vbi_cap buffer %d done\n", buf->vb.vb2_buf.ind
[PATCH 26/29] vim2m: use workqueue
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 ef970434af13..9b18b32c255d 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(&vim2m_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 = &dev->vfd; vfd->lock = &dev->dev_mutex; vfd->v4l2_dev = &dev->v4l2_dev; + INIT_WORK(&dev->work_run, device_work); #ifdef CONFIG_MEDIA_CONTROLLER dev->mdev.dev = &pdev->dev; -- 2.15.1
[PATCH 18/29] vb2: store userspace data in vb2_v4l2_buffer
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 | 25 +- 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, 197 insertions(+), 160 deletions(-) diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index d3f7bb33a54d..3d436ccb61f8 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -968,9 +968,8 @@ static int __prepare_mmap(struct vb2_buffer *vb, const void *pb) { 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); } @@ -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 */ @@ -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); diff --git a/drivers/media/common/videobuf2/videobuf2-v4l2.c b/drivers/media/common/videobuf2/videobuf2-v4l2.c index 4e9c77f21858..bf7a3ba9fed0 100644 --- a/drivers/media/common/videobuf2/videobuf2-v4l2.c +++ b/drivers/media/common/videobuf2/videobuf2-v4l2.c @@ -154,9 +154,177 @@ static void vb2_warn_zero_bytesused(struct vb2_buffer *vb) pr_warn("use the actual size instead.\n"); } +static int vb2_fill_vb2_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b) +{ + struct vb2_queue *q = vb->vb2_queue; + struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); + struct vb2_plane *planes = vbuf->planes; + unsigned int plane; + int ret; + + ret = __verify_length(vb, b); + if (ret < 0) { + dprintk(1, "plane parameters verification failed: %d\n", ret); + return ret; + } + if (b->field == V4L2_FIELD_ALTERNATE && q->is_output) { + /* +* If the format's field is ALTERNATE, then the buffer's field +* should be either TOP or BOTTOM, not ALTERNATE since that +* makes no sense. The driver has to know whether the +* buffer represents a top or a bottom field in order to +* program any DMA correctly. Using ALTERNATE is wrong, since +* that just says that it is either a top or a bottom field, +* but not which of the two it is. +*/ + dprintk(1, "the field is incorrectly set to ALTERNATE for an output buffer\n"); + return -EINVAL; + } + vbuf->sequence = 0; + + if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) { + switch (b->memory) { + case VB2_MEMORY_USERPTR: + for (plane = 0; plane < vb->num_planes; ++plane) { + planes[plane].m.userptr = + b->m.planes[plane].
[PATCH 19/29] videobuf2-core: embed media_request_object
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 224c4820a044..3d54654c3cd4 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.15.1
Re: [RFCv9 PATCH 00/29] Request API
On 03/28/2018 03:50 PM, Hans Verkuil wrote: > From: Hans Verkuil > > Hi all, > > This patch series is an attempt to pick the best parts of > Alexandre's RFCv4: "sending too many recipients in a short time. Please try again later." So patches 17 and up will appear a bit later. I'll drop the CC list to avoid hitting this issue again. My ISP is not friendly for kernel developers who need to post large series to many people :-( Regards, Hans
[RFCv9 PATCH 11/29] v4l2-ctrls: use ref in helper instead of ctrl
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 Signed-off-by: Alexandre Courbot --- 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 e8d6dee375ef..fc13f328c6fc 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.16.1
[RFCv9 PATCH 08/29] v4l2-ctrls: v4l2_ctrl_add_handler: add from_other_dev
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-v4l2.c | 3 +- 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, 62 insertions(+), 49 deletions(-) diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c index c6e78d870ccd..6064d28224e8 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(&dev->hdl, 9); if (subdev) - v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler, NULL); + v4l2_ctrl_add_handler(&dev->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(&dev->hdl, 2); if (subdev) v4l2_ctrl_add_handler(&dev->hdl, subdev->ctrl_handler, - NULL); + NULL, true); break; default: v4l2_ctrl_handler_init(&dev->hdl, 0); diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index f697698fe38d..cdcb36d8c5c3 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(&btv->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 a71f3c7569ce..762823871c78 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(&dev->cxhdl, tsport->height == 576); - v4l2_ctrl_add_handler(&dev->ctrl_handler, &dev->cxhdl.hdl, NULL); + v4l2_ctrl_add_handler(&dev->ctrl_handler, &dev->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 0e0952e60795..39f69d89a663 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(&dev->cxhdl, 36); if (err) goto fail_core; - v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl, NULL); + v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl, NULL, false);
[RFCv9 PATCH 03/29] media-request: allocate media requests
From: Hans Verkuil Add support for allocating a new request. This is only supported if mdev->ops->req_queue is set, i.e. the driver indicates that it supports queueing requests. Signed-off-by: Hans Verkuil --- drivers/media/Makefile| 3 ++- drivers/media/media-device.c | 14 ++ drivers/media/media-request.c | 23 +++ include/media/media-device.h | 13 + include/media/media-request.h | 22 ++ 5 files changed, 74 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 594b462ddf0e..985d35ec6b29 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 35e81f7c0d2f..acb583c0eacd 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 @@ -366,6 +367,15 @@ static long media_device_get_topology(struct media_device *mdev, return ret; } +static long media_device_request_alloc(struct media_device *mdev, + struct media_request_alloc *alloc) +{ + if (!mdev->ops || !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() */ @@ -414,6 +424,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, @@ -686,6 +697,9 @@ void media_device_init(struct media_device *mdev) INIT_LIST_HEAD(&mdev->pads); INIT_LIST_HEAD(&mdev->links); INIT_LIST_HEAD(&mdev->entity_notify); + + spin_lock_init(&mdev->req_lock); + mutex_init(&mdev->req_queue_mutex); mutex_init(&mdev->graph_mutex); ida_init(&mdev->entity_internal_idx); diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c new file mode 100644 index ..ead78613fdbe --- /dev/null +++ b/drivers/media/media-request.c @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Media device request objects + * + * Copyright (C) 2018 Intel Corporation + * Copyright (C) 2018, The Chromium OS Authors. All rights reserved. + * + * Author: Sakari Ailus + */ + +#include +#include +#include +#include + +#include +#include + +int media_request_alloc(struct media_device *mdev, + struct media_request_alloc *alloc) +{ + return -ENOMEM; +} diff --git a/include/media/media-device.h b/include/media/media-device.h index bcc6ec434f1f..07e323c57202 100644 --- a/include/media/media-device.h +++ b/include/media/media-device.h @@ -19,6 +19,7 @@ #ifndef _MEDIA_DEVICE_H #define _MEDIA_DEVICE_H +#include #include #include @@ -27,6 +28,7 @@ struct ida; struct device; +struct media_device; /** * struct media_entity_notify - Media Entity Notify @@ -50,10 +52,16 @@ struct media_entity_notify { * struct media_device_ops - Media device operations * @link_notify: Link state change notification callback. This callback is * called with the graph_mutex held. + * @req_alloc: Allocate a request + * @req_free: Free a request + * @req_queue: Queue a request */ struct media_device_ops { int (*link_notify)(struct media_link *link, u32 flags, unsigned int notification); + struct media_request *(*req_alloc)(struct media_device *mdev); + void (*req_free)(struct media_request *req); + int (*req_queue)(struct media_request *req); }; /** @@ -88,6 +96,8 @@ struct media_device_ops { * @disable_source: Disable Source Handler function pointer * * @ops: Operation handler callbacks + * @req_lock: Serialise access to requests + * @req_queue_mutex: Serialise validating and queueing requests * * This structure represents an abstract high-level media device. It allows easy * access to entities and provides basic media device-level support. The @@ -158,6 +168,9 @@ struct media_device { void (*disable_source)(struct media_entity *entity); const str
[RFCv9 PATCH 04/29] media-request: core request support
From: Hans Verkuil Implement the core of the media request processing. Drivers can bind request objects to a request. These objects can then be marked completed if the driver finished using them, or just be unbound if the results do not need to be kept (e.g. in the case of buffers). Once all objects that were added are either unbound or completed, the request is marked 'complete' and a POLLPRI signal is sent via poll. Both requests and request objects are refcounted. While a request is queued its refcount is incremented (since it is in use by a driver). Once it is completed the refcount is decremented. When the user closes the request file descriptor the refcount is also decremented. Once it reaches 0 all request objects in the request are unbound and put() and the request itself is freed. Signed-off-by: Hans Verkuil --- drivers/media/media-request.c | 269 +- include/media/media-request.h | 148 +++ 2 files changed, 416 insertions(+), 1 deletion(-) diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c index ead78613fdbe..8135d9d32af9 100644 --- a/drivers/media/media-request.c +++ b/drivers/media/media-request.c @@ -16,8 +16,275 @@ #include #include +static const char * const request_state[] = { + "idle", + "queueing", + "queued", + "complete", + "cleaning", +}; + +static const char * +media_request_state_str(enum media_request_state state) +{ + if (WARN_ON(state >= ARRAY_SIZE(request_state))) + return "unknown"; + return request_state[state]; +} + +static void media_request_clean(struct media_request *req) +{ + struct media_request_object *obj, *obj_safe; + + WARN_ON(req->state != MEDIA_REQUEST_STATE_CLEANING); + + list_for_each_entry_safe(obj, obj_safe, &req->objects, list) { + media_request_object_unbind(obj); + media_request_object_put(obj); + } + + req->num_incomplete_objects = 0; + wake_up_interruptible(&req->poll_wait); +} + +static void media_request_release(struct kref *kref) +{ + struct media_request *req = + container_of(kref, struct media_request, kref); + struct media_device *mdev = req->mdev; + unsigned long flags; + + dev_dbg(mdev->dev, "request: release %s\n", req->debug_str); + + spin_lock_irqsave(&req->lock, flags); + req->state = MEDIA_REQUEST_STATE_CLEANING; + spin_unlock_irqrestore(&req->lock, flags); + + media_request_clean(req); + + if (mdev->ops->req_free) + mdev->ops->req_free(req); + else + kfree(req); +} + +void media_request_put(struct media_request *req) +{ + kref_put(&req->kref, media_request_release); +} +EXPORT_SYMBOL_GPL(media_request_put); + +static int media_request_close(struct inode *inode, struct file *filp) +{ + struct media_request *req = filp->private_data; + + media_request_put(req); + return 0; +} + +static unsigned int media_request_poll(struct file *filp, + struct poll_table_struct *wait) +{ + struct media_request *req = filp->private_data; + unsigned long flags; + enum media_request_state state; + + if (!(poll_requested_events(wait) & POLLPRI)) + return 0; + + spin_lock_irqsave(&req->lock, flags); + state = req->state; + spin_unlock_irqrestore(&req->lock, flags); + + if (state == MEDIA_REQUEST_STATE_COMPLETE) + return POLLPRI; + if (state == MEDIA_REQUEST_STATE_IDLE) + return POLLERR; + + poll_wait(filp, &req->poll_wait, wait); + return 0; +} + +static long media_request_ioctl(struct file *filp, unsigned int cmd, + unsigned long __arg) +{ + return -ENOIOCTLCMD; +} + +static const struct file_operations request_fops = { + .owner = THIS_MODULE, + .poll = media_request_poll, + .unlocked_ioctl = media_request_ioctl, + .release = media_request_close, +}; + int media_request_alloc(struct media_device *mdev, struct media_request_alloc *alloc) { - return -ENOMEM; + struct media_request *req; + struct file *filp; + char comm[TASK_COMM_LEN]; + int fd; + int ret; + + fd = get_unused_fd_flags(O_CLOEXEC); + if (fd < 0) + return fd; + + filp = anon_inode_getfile("request", &request_fops, NULL, O_CLOEXEC); + if (IS_ERR(filp)) { + ret = PTR_ERR(filp); + goto err_put_fd; + } + + if (mdev->ops->req_alloc) + req = mdev->ops->req_alloc(mdev); + else + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) { + ret = -ENOMEM; + goto err_fput; + } + + filp->private_data = req; + req->mdev = mdev; + req->state = MEDIA_REQ
[RFCv9 PATCH 02/29] uapi/linux/media.h: add request API
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 | 8 1 file changed, 8 insertions(+) diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h index c7e9a5cba24e..f8769e74f847 100644 --- a/include/uapi/linux/media.h +++ b/include/uapi/linux/media.h @@ -342,11 +342,19 @@ 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) + +#define MEDIA_REQUEST_IOC_QUEUE_IO('|', 0x80) +#define MEDIA_REQUEST_IOC_REINIT _IO('|', 0x81) #if !defined(__KERNEL__) || defined(__NEED_MEDIA_LEGACY_API) -- 2.16.1
[RFCv9 PATCH 05/29] media-request: add request ioctls
From: Hans Verkuil Implement the MEDIA_REQUEST_IOC_QUEUE and MEDIA_REQUEST_IOC_REINIT ioctls. Signed-off-by: Hans Verkuil --- drivers/media/media-request.c | 80 +-- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c index 8135d9d32af9..3ee3b27fd644 100644 --- a/drivers/media/media-request.c +++ b/drivers/media/media-request.c @@ -105,10 +105,86 @@ static unsigned int media_request_poll(struct file *filp, return 0; } +static long media_request_ioctl_queue(struct media_request *req) +{ + struct media_device *mdev = req->mdev; + unsigned long flags; + int ret = 0; + + dev_dbg(mdev->dev, "request: queue %s\n", req->debug_str); + + spin_lock_irqsave(&req->lock, flags); + if (req->state != MEDIA_REQUEST_STATE_IDLE) { + dev_dbg(mdev->dev, + "request: unable to queue %s, request in state %s\n", + req->debug_str, media_request_state_str(req->state)); + spin_unlock_irqrestore(&req->lock, flags); + return -EINVAL; + } + req->state = MEDIA_REQUEST_STATE_QUEUEING; + + spin_unlock_irqrestore(&req->lock, flags); + + /* +* Ensure the request that is validated will be the one that gets queued +* next by serialising the queueing process. +*/ + mutex_lock(&mdev->req_queue_mutex); + + ret = mdev->ops->req_queue(req); + spin_lock_irqsave(&req->lock, flags); + req->state = ret ? MEDIA_REQUEST_STATE_IDLE : MEDIA_REQUEST_STATE_QUEUED; + spin_unlock_irqrestore(&req->lock, flags); + mutex_unlock(&mdev->req_queue_mutex); + + if (ret) { + dev_dbg(mdev->dev, "request: can't queue %s (%d)\n", + req->debug_str, ret); + } else { + media_request_get(req); + } + + return ret; +} + +static long media_request_ioctl_reinit(struct media_request *req) +{ + struct media_device *mdev = req->mdev; + unsigned long flags; + + spin_lock_irqsave(&req->lock, flags); + 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(&req->lock, flags); + return -EINVAL; + } + req->state = MEDIA_REQUEST_STATE_CLEANING; + spin_unlock_irqrestore(&req->lock, flags); + + media_request_clean(req); + + spin_lock_irqsave(&req->lock, flags); + req->state = MEDIA_REQUEST_STATE_IDLE; + spin_unlock_irqrestore(&req->lock, flags); + return 0; +} + static long media_request_ioctl(struct file *filp, unsigned int cmd, - unsigned long __arg) + unsigned long arg) { - return -ENOIOCTLCMD; + struct media_request *req = filp->private_data; + + switch (cmd) { + case MEDIA_REQUEST_IOC_QUEUE: + return media_request_ioctl_queue(req); + case MEDIA_REQUEST_IOC_REINIT: + return media_request_ioctl_reinit(req); + default: + return -ENOIOCTLCMD; + } } static const struct file_operations request_fops = { -- 2.16.1
[RFCv9 PATCH 06/29] media-request: add media_request_find
From: Hans Verkuil Add media_request_find() to find a request based on the file descriptor. The caller has to call media_request_put() for the returned request since this function increments the refcount. Signed-off-by: Hans Verkuil --- drivers/media/media-request.c | 47 +++ include/media/media-request.h | 9 + 2 files changed, 56 insertions(+) diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c index 3ee3b27fd644..d54fd353d8a6 100644 --- a/drivers/media/media-request.c +++ b/drivers/media/media-request.c @@ -194,6 +194,53 @@ static const struct file_operations request_fops = { .release = media_request_close, }; +/** + * media_request_find - Find a request based on the file descriptor + * @mdev: The media device + * @request: The request file handle + * + * Find and return the request associated with the given file descriptor, or + * an error if no such request exists. + * + * When the function returns a request it increases its reference count. The + * caller is responsible for releasing the reference by calling + * media_request_put() on the request. + */ +struct media_request * +media_request_find(struct media_device *mdev, int request_fd) +{ + struct file *filp; + struct media_request *req; + + if (!mdev || !mdev->ops || !mdev->ops->req_queue) + return ERR_PTR(-ENOENT); + + filp = fget(request_fd); + if (!filp) + return ERR_PTR(-ENOENT); + + if (filp->f_op != &request_fops) + goto err_fput; + req = filp->private_data; + media_request_get(req); + + if (req->mdev != mdev) + goto err_kref_put; + + fput(filp); + + return req; + +err_kref_put: + media_request_put(req); + +err_fput: + fput(filp); + + return ERR_PTR(-EBADF); +} +EXPORT_SYMBOL_GPL(media_request_find); + int media_request_alloc(struct media_device *mdev, struct media_request_alloc *alloc) { diff --git a/include/media/media-request.h b/include/media/media-request.h index baed99eb1279..c01b05570a31 100644 --- a/include/media/media-request.h +++ b/include/media/media-request.h @@ -57,6 +57,9 @@ static inline void media_request_get(struct media_request *req) void media_request_put(struct media_request *req); +struct media_request * +media_request_find(struct media_device *mdev, int request_fd); + int media_request_alloc(struct media_device *mdev, struct media_request_alloc *alloc); #else @@ -67,6 +70,12 @@ static inline void media_request_get(struct media_request *req) static inline void media_request_put(struct media_request *req) { } + +static inline struct media_request * +media_request_find(struct media_device *mdev, int request_fd) +{ + return ERR_PTR(-ENOENT); +} #endif struct media_request_object_ops { -- 2.16.1
[RFCv9 PATCH 16/29] v4l2-ctrls: integrate with requests
From: Hans Verkuil Add the media_device pointer to the v4l2_g/s/try_ext_ctrls functions and pass that in from the v4l2 core. The control framework will look up the request from the request_fd file descriptor and bind/unbind the request objects. Signed-off-by: Hans Verkuil --- drivers/media/platform/omap3isp/ispvideo.c | 2 +- drivers/media/v4l2-core/v4l2-ctrls.c | 136 ++--- drivers/media/v4l2-core/v4l2-ioctl.c | 12 +-- drivers/media/v4l2-core/v4l2-subdev.c | 9 +- include/media/v4l2-ctrls.h | 13 ++- 5 files changed, 148 insertions(+), 24 deletions(-) diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index a751c89a3ea8..bd564c2e767f 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 = &ctrl; - ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, &ctrls); + ret = v4l2_g_ext_ctrls(pipe->external->ctrl_handler, NULL, &ctrls); 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 6cf6b2154462..e31bce0207b4 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1898,6 +1898,7 @@ int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler *hdl, lockdep_set_class_and_name(hdl->lock, key, name); INIT_LIST_HEAD(&hdl->ctrls); INIT_LIST_HEAD(&hdl->ctrl_refs); + INIT_LIST_HEAD(&hdl->requests); hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8; hdl->buckets = kvmalloc_array(hdl->nr_of_buckets, sizeof(hdl->buckets[0]), @@ -1918,6 +1919,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(&hdl->requests)) { + struct v4l2_ctrl_handler *req, *next_req; + + list_for_each_entry_safe(req, next_req, &hdl->requests, requests) { + media_request_object_unbind(&req->req_obj); + media_request_object_put(&req->req_obj); + } + } mutex_lock(hdl->lock); /* Free all nodes */ list_for_each_entry_safe(ref, next_ref, &hdl->ctrl_refs, node) { @@ -2844,6 +2853,7 @@ static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl, bool (*filter)(const struct v4l2_ctrl *ctrl)) { struct v4l2_ctrl_ref *ref; + struct media_request *req = hdl->req_obj.req; int err; if (WARN_ON(!hdl || hdl == from)) @@ -2857,6 +2867,7 @@ static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl, err = v4l2_ctrl_handler_init(hdl, (from->nr_of_buckets - 1) * 8); if (err) return err; + hdl->req_obj.req = req; if (!from) return 0; @@ -2892,6 +2903,14 @@ static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl, return err; } +static void v4l2_ctrl_request_unbind(struct media_request_object *obj) +{ + struct v4l2_ctrl_handler *hdl = + container_of(obj, struct v4l2_ctrl_handler, req_obj); + + list_del_init(&hdl->requests); +} + static void v4l2_ctrl_request_release(struct media_request_object *obj) { struct v4l2_ctrl_handler *hdl = @@ -2902,6 +2921,7 @@ static void v4l2_ctrl_request_release(struct media_request_object *obj) } static const struct media_request_object_ops req_ops = { + .unbind = v4l2_ctrl_request_unbind, .release = v4l2_ctrl_request_release, }; @@ -2910,10 +2930,16 @@ static int v4l2_ctrl_request_bind(struct media_request *req, struct v4l2_ctrl_handler *from, bool (*filter)(const struct v4l2_ctrl *ctrl)) { - int ret = v4l2_ctrl_request_clone(hdl, from, filter); + int ret; - if (!ret) + hdl->req_obj.req = req; + ret = v4l2_ctrl_request_clone(hdl, from, filter); + hdl->req_obj.req = NULL; + + if (!ret) { + list_add_tail(&hdl->requests, &from->requests); media_request_object_bind(req, &req_ops, from, &hdl->req_obj); + } return ret; } @@ -2977,6 +3003,7 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl, if (cs->which && cs->which != V4L2_CTRL_WHICH_DEF_VAL && + cs->which != V4L2_CTRL_WHICH_REQUEST && V4L2_CTRL_ID2WHICH(id) != cs->which) return -EINVAL; @@ -3056,15 +3083,15 @@ static int prepare_ext_ctrls(struct v4l2_ctrl
[RFCv9 PATCH 07/29] media-request: add media_request_object_find
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 | 26 ++ include/media/media-request.h | 25 + 2 files changed, 51 insertions(+) diff --git a/drivers/media/media-request.c b/drivers/media/media-request.c index d54fd353d8a6..10a05dd7b571 100644 --- a/drivers/media/media-request.c +++ b/drivers/media/media-request.c @@ -309,6 +309,32 @@ 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 (!ops && !priv) + return NULL; + + spin_lock_irqsave(&req->lock, flags); + list_for_each_entry(obj, &req->objects, list) { + if ((!ops || obj->ops == ops) && + (!priv || obj->priv == priv)) { + media_request_object_get(obj); + found = obj; + break; + } + } + spin_unlock_irqrestore(&req->lock, flags); + return found; +} +EXPORT_SYMBOL_GPL(media_request_object_find); + void media_request_object_put(struct media_request_object *obj) { kref_put(&obj->kref, media_request_object_release); diff --git a/include/media/media-request.h b/include/media/media-request.h index c01b05570a31..570f3a205776 100644 --- a/include/media/media-request.h +++ b/include/media/media-request.h @@ -122,6 +122,23 @@ 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, may be NULL. + * @priv: Find an object with this priv value, may be NULL. + * + * At least one of @ops and @priv must be non-NULL. If one of + * these is NULL, then skip checking for that field. + * + * Returns NULL if not found or the object (the refcount is increased + * in that case). + */ +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 * @@ -154,6 +171,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.16.1
[RFCv9 PATCH 14/29] v4l2-ctrls: do not clone non-standard controls
From: Alexandre Courbot Only standard controls can be successfully cloned: handler_new_ref, used by v4l2_ctrl_request_clone(), forcibly calls v4l2_ctrl_new_std() which fails to find custom controls names, and we eventually hit the condition that name == NULL in v4l2_ctrl_new(). This prevents us from using non-standard controls with requests, but that is enough for testing purposes. Signed-off-by: Alexandre Courbot --- drivers/media/v4l2-core/v4l2-ctrls.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 62f91c0f1e5f..6cf6b2154462 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -2876,6 +2876,11 @@ static int v4l2_ctrl_request_clone(struct v4l2_ctrl_handler *hdl, if (filter && !filter(ctrl)) continue; err = handler_new_ref(hdl, ctrl, &new_ref, false); + 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; if (from->req_obj.req) -- 2.16.1
[RFCv9 PATCH 15/29] videodev2.h: add request_fd field to v4l2_ext_controls
From: Alexandre Courbot If which is V4L2_CTRL_WHICH_REQUEST, 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 --- 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 5198c9eeb348..0782b3666deb 100644 --- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c +++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c @@ -732,7 +732,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 * */ }; @@ -807,6 +808,7 @@ static int get_v4l2_ext_controls32(struct file *file, get_user(count, &up->count) || put_user(count, &kp->count) || assign_in_user(&kp->error_idx, &up->error_idx) || + assign_in_user(&kp->request_fd, &up->request_fd) || copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved))) return -EFAULT; @@ -865,6 +867,7 @@ static int put_v4l2_ext_controls32(struct file *file, get_user(count, &kp->count) || put_user(count, &up->count) || assign_in_user(&up->error_idx, &kp->error_idx) || + assign_in_user(&up->request_fd, &kp->request_fd) || copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) || get_user(kcontrols, &kp->controls)) return -EFAULT; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index a5dab16ff2d2..2c623da33155 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 600877be5c22..6f41baa53787 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 0x0f01 enum v4l2_ctrl_type { V4L2_CTRL_TYPE_INTEGER = 1, -- 2.16.1
[RFCv9 PATCH 13/29] v4l2-ctrls: add core request API
From: Hans Verkuil Add the two core request functions: v4l2_ctrl_request_setup() applies the contents of the request to the current driver state. v4l2_ctrl_request_complete() marks the request complete. After this the contents is fixed. Signed-off-by: Hans Verkuil --- drivers/media/v4l2-core/v4l2-ctrls.c | 172 +++ include/media/v4l2-ctrls.h | 9 ++ 2 files changed, 181 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 80714c5bad8b..62f91c0f1e5f 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1781,6 +1781,14 @@ static void new_to_req(struct v4l2_ctrl_ref *ref) ptr_to_ptr(ref->ctrl, ref->ctrl->p_new, ref->p_req); } +/* Copy the request value to the new value */ +static void req_to_new(struct v4l2_ctrl_ref *ref) +{ + if (!ref) + return; + ptr_to_ptr(ref->ctrl, ref->p_req, 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) @@ -2831,6 +2839,78 @@ 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, + bool (*filter)(const struct v4l2_ctrl *ctrl)) +{ + 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 != &hdl->_lock); + v4l2_ctrl_handler_free(hdl); + err = v4l2_ctrl_handler_init(hdl, (from->nr_of_buckets - 1) * 8); + if (err) + return err; + if (!from) + return 0; + + mutex_lock(from->lock); + list_for_each_entry(ref, &from->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 and control classes */ + if (ctrl->type == V4L2_CTRL_TYPE_BUTTON || + ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) + continue; + /* Filter any unwanted controls */ + if (filter && !filter(ctrl)) + continue; + err = handler_new_ref(hdl, ctrl, &new_ref, false); + if (err) + break; + if (from->req_obj.req) + ptr_to_ptr(ctrl, ref->p_req, new_ref->p_req); + else + ptr_to_ptr(ctrl, ctrl->p_cur, new_ref->p_req); + } + mutex_unlock(from->lock); + return err; +} + +static void v4l2_ctrl_request_release(struct media_request_object *obj) +{ + struct v4l2_ctrl_handler *hdl = + container_of(obj, struct v4l2_ctrl_handler, req_obj); + + v4l2_ctrl_handler_free(hdl); + kfree(hdl); +} + +static const struct media_request_object_ops req_ops = { + .release = v4l2_ctrl_request_release, +}; + +static int v4l2_ctrl_request_bind(struct media_request *req, + struct v4l2_ctrl_handler *hdl, + struct v4l2_ctrl_handler *from, + bool (*filter)(const struct v4l2_ctrl *ctrl)) +{ + int ret = v4l2_ctrl_request_clone(hdl, from, filter); + + if (!ret) + media_request_object_bind(req, &req_ops, from, &hdl->req_obj); + return ret; +} /* Some general notes on the atomic requirements of VIDIOC_G/TRY/S_EXT_CTRLS: @@ -3458,6 +3538,98 @@ int __v4l2_ctrl_s_ctrl_string(struct v4l2_ctrl *ctrl, const char *s) } EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string); +void v4l2_ctrl_request_complete(struct media_request *req, + struct v4l2_ctrl_handler *hdl) +{ + struct media_request_object *obj; + + if (!req || !hdl) + return; + + obj = media_request_object_find(req, &req_ops, hdl); + if (!obj) + return; + + media_request_object_complete(obj); + media_request_object_put(obj); +} +EXPORT_SYMBOL(v4l2_ctrl_request_complete); + +void v4l2_ctrl_request_setup(struct media_request *req, +struct v4l2_ctrl_handler *hdl) +{ + struct media_request_object *obj; + struct v4l2_ctrl_ref *ref; + + if (!req || !hdl) + return; + + obj = media_request_object_find(req, &req_ops, hdl); + if (!obj) + return; + if (obj->completed) { + media_request_object_put(obj); + return; + } + hdl = container_o
[RFCv9 PATCH 12/29] v4l2-ctrls: support g/s_ext_ctrls for requests
From: Hans Verkuil The v4l2_g/s_ext_ctrls functions now support control handlers that represent requests. Signed-off-by: Hans Verkuil Signed-off-by: Alexandre Courbot --- drivers/media/v4l2-core/v4l2-ctrls.c | 37 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index fc13f328c6fc..80714c5bad8b 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,14 @@ 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); +} + /* 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) @@ -3002,7 +3017,8 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs struct v4l2_ctrl *ctrl); struct v4l2_ctrl *master; - ctrl_to_user = def_value ? def_to_user : cur_to_user; + ctrl_to_user = def_value ? def_to_user : + (hdl->req_obj.req ? NULL : cur_to_user); if (helpers[i].mref == NULL) continue; @@ -3028,8 +3044,12 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs u32 idx = i; do { - ret = ctrl_to_user(cs->controls + idx, - helpers[idx].ref->ctrl); + if (ctrl_to_user) + ret = ctrl_to_user(cs->controls + idx, + helpers[idx].ref->ctrl); + else + ret = req_to_user(cs->controls + idx, + helpers[idx].ref); idx = helpers[idx].next; } while (!ret && idx); } @@ -3302,7 +3322,16 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl, } while (!ret && idx); if (!ret) - ret = try_or_set_cluster(fh, master, set, 0); + ret = try_or_set_cluster(fh, master, +!hdl->req_obj.req && set, 0); + if (!ret && hdl->req_obj.req && set) { + for (j = 0; j < master->ncontrols; j++) { + struct v4l2_ctrl_ref *ref = + find_ref(hdl, master->cluster[j]->id); + + new_to_req(ref); + } + } /* Copy the new values back to userspace. */ if (!ret) { -- 2.16.1
[RFCv9 PATCH 10/29] v4l2-ctrls: alloc memory for p_req
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 | 18 +++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index d09f49530d9e..e8d6dee375ef 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1997,6 +1997,7 @@ 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, + struct v4l2_ctrl_ref **ctrl_ref, bool from_other_dev) { struct v4l2_ctrl_ref *ref; @@ -2004,6 +2005,10 @@ static int handler_new_ref(struct v4l2_ctrl_handler *hdl, 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 (hdl->req_obj.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 = &new_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)) { 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); if (ret) break; } -- 2.16.1
[RFCv9 PATCH 01/29] v4l2-device.h: always expose mdev
From: Hans Verkuil The mdev field is only present if CONFIG_MEDIA_CONTROLLER is set. But since we will need to pass the media_device to vb2 snd the control framework it is very convenient to just make this field available all the time. If CONFIG_MEDIA_CONTROLLER is not set, then it will just be NULL. Signed-off-by: Hans Verkuil --- include/media/v4l2-device.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 0c9e4da55499..b330e4a08a6b 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h @@ -33,7 +33,7 @@ struct v4l2_ctrl_handler; * struct v4l2_device - main struct to for V4L2 device drivers * * @dev: pointer to struct device. - * @mdev: pointer to struct media_device + * @mdev: pointer to struct media_device, may be NULL. * @subdevs: used to keep track of the registered subdevs * @lock: lock this struct; can be used by the driver as well * if this struct is embedded into a larger struct. @@ -58,9 +58,7 @@ struct v4l2_ctrl_handler; */ struct v4l2_device { struct device *dev; -#if defined(CONFIG_MEDIA_CONTROLLER) struct media_device *mdev; -#endif struct list_head subdevs; spinlock_t lock; char name[V4L2_DEVICE_NAME_SIZE]; -- 2.16.1
[RFCv9 PATCH 09/29] v4l2-ctrls: prepare internal structs for request API
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 aa1dd2015e84..d09f49530d9e 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(&hdl->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 f8faa54b5e7e..89a985607126 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 then the &struct 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 &struct media_request_object, used to link into a + * &struct 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.16.1
[RFCv9 PATCH 00/29] Request API
From: Hans Verkuil Hi all, This patch series is an attempt to pick the best parts of Alexandre's RFCv4: https://lkml.org/lkml/2018/2/19/872 and Sakari's RFCv2: https://www.mail-archive.com/linux-media@vger.kernel.org/msg128170.html and based on the RFCv2 of the Request public API proposal: https://www.mail-archive.com/linux-media@vger.kernel.org/msg128098.html together with my own ideas. I've no idea what version to give this series, so I just went with v9 since that's the version of my internal git branch. This has been tested with vim2m and vivid using v4l2-compliance. The v4l-utils repo supporting requests is here: https://git.linuxtv.org/hverkuil/v4l-utils.git/log/?h=request The goal is to use request and request objects as implemented in Sakari's RFCv2, together with the vb2 and control framework support as implemented in Alexandre's RFCv4. In addition, I tried hard to minimize the impact of requests to drivers. TODO/Remarks: 1) missing prototype documentation in media-requests.c/h. Some is documented, but not everything. 2) improve the control handler implementation: currently this just clones the driver's control handler when a request object is created. And only standard controls can be contained in a request. I probably need another day of work to get this done properly by chaining control handlers as they are queued. The control patches are also a bit messy, so that needs to be cleaned up as well. I hope I can spend some time on this next week after Easter as this is the main TODO item. I expect I'll need 1-2 days of work to finished this. That said, the current implementation should be OK for stateless codecs. 3) No VIDIOC_REQUEST_ALLOC 'shortcut' ioctl. Sorry, I just ran out of time. Alexandre, Tomasz, feel free to add it back (it should be quite easy to do) and post a patch. I'll add it to my patch series. As mentioned before: whether or not we actually want this has not been decided yet. 4) vim2m: the media topology is a bit bogus, this needs to be fixed (i.e. a proper HW entity should be added). But for now it is good enough for testing. 5) I think this should slide in fairly easy after the fence support is merged. I made sure the request API changes in public headers did not clash with the changes made by the fence API. 6) I did not verify the Request API documentation patch. I did update it with the new buffer flags and 'which' value, but it probably is out of date in places. 7) More testing. I think I have fairly good coverage in v4l2-compliance, but no doubt I've missed a few test cases. 8) debugfs: it would be really useful to expose the number of request and request objects in debugfs to simplify debugging. Esp. to make sure everything is freed correctly. 9) Review copyright/authorship lines. I'm not sure if everything is correct. Alexandre, Sakari, if you see something that is not right in this respect, just let me know! Everything seemed to slip nicely into place while working on this, so I hope this is finally an implementation that we can proceed to upstream and build upon for complex camera pipelines in the future. This patch series is also available here: https://git.linuxtv.org/hverkuil/media_tree.git/log/?h=reqv9 Regards, Hans Alexandre Courbot (4): v4l2-ctrls: do not clone non-standard controls videodev2.h: add request_fd field to v4l2_ext_controls Documentation: v4l: document request API media: vim2m: add media device Hans Verkuil (25): v4l2-device.h: always expose mdev uapi/linux/media.h: add request API media-request: allocate media requests media-request: core request support media-request: add request ioctls media-request: add media_request_find media-request: add media_request_object_find 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: support g/s_ext_ctrls for requests v4l2-ctrls: add core request API v4l2-ctrls: integrate with 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 vb2_core_request_has_buffers videobuf2-v4l2: add vb2_request_queue helper vim2m: use workqueue vim2m: support requests vivid: add mc vivid: add request support Documentation/media/uapi/v4l/buffer.rst| 19 +- Documentation/media/uapi/v4l/common.rst| 1 + Documentation/media/uapi/v4l/request-api.rst | 199 ++ Documentation/media/uapi/v4l/user-func.rst | 1 + .../media/uapi/v4l/vidioc-g-ext-ctrls.rst | 22 +- .../media/uapi/v4l/vidioc-new-request.rst | 64 +++ Documentation/media/uapi/v4l/vidioc-qbuf.rst
Re: [PATCH 04/15] v4l: vsp1: Store pipeline pointer in vsp1_entity
Hi Laurent, Thank you for the patch. On 26/02/18 21:45, Laurent Pinchart wrote: > Various types of objects subclassing vsp1_entity currently store a > pointer to the pipeline. Move the pointer to vsp1_entity to simplify the > code and avoid storing the pipeline in more entity subclasses later. This certainly seems like a good improvement to make. > Signed-off-by: Laurent Pinchart Some terse diffstat there to get through - but it all looks good in the end. Reviewed-by: Kieran Bingham > --- > drivers/media/platform/vsp1/vsp1_drm.c| 20 +-- > drivers/media/platform/vsp1/vsp1_drv.c| 2 +- > drivers/media/platform/vsp1/vsp1_entity.h | 2 ++ > drivers/media/platform/vsp1/vsp1_histo.c | 2 +- > drivers/media/platform/vsp1/vsp1_histo.h | 3 --- > drivers/media/platform/vsp1/vsp1_pipe.c | 33 > +-- > drivers/media/platform/vsp1/vsp1_rwpf.h | 2 -- > drivers/media/platform/vsp1/vsp1_video.c | 17 +++- > 8 files changed, 34 insertions(+), 47 deletions(-) > > diff --git a/drivers/media/platform/vsp1/vsp1_drm.c > b/drivers/media/platform/vsp1/vsp1_drm.c > index a267f12f0cc8..a7ad85ab0b08 100644 > --- a/drivers/media/platform/vsp1/vsp1_drm.c > +++ b/drivers/media/platform/vsp1/vsp1_drm.c > @@ -120,6 +120,7 @@ int vsp1_du_setup_lif(struct device *dev, unsigned int > pipe_index, >* inputs. >*/ > WARN_ON(list_empty(&rpf->entity.list_pipe)); > + rpf->entity.pipe = NULL; Aha - This reads confusingly as a diff ... because first it ensures the entity is in a pipe with the WARN_ON, but then sets the pipe to NULL. But I'm going to hazard a guess and say this is the (!cfg) section of the vsp1_du_setup_lif() call... /me checks. Yes, of course it is... so that's fine. > list_del_init(&rpf->entity.list_pipe); > pipe->inputs[i] = NULL; > > @@ -536,8 +537,10 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned > int pipe_index) > continue; > } > > - if (list_empty(&rpf->entity.list_pipe)) > + if (list_empty(&rpf->entity.list_pipe)) { > + rpf->entity.pipe = pipe; > list_add_tail(&rpf->entity.list_pipe, &pipe->entities); > + } > > bru->inputs[i].rpf = rpf; > rpf->bru_input = i; > @@ -562,6 +565,7 @@ void vsp1_du_atomic_flush(struct device *dev, unsigned > int pipe_index) > vsp1_dl_list_write(dl, entity->route->reg, > VI6_DPR_NODE_UNUSED); > > + entity->pipe = NULL; > list_del_init(&entity->list_pipe); > > continue; > @@ -625,24 +629,28 @@ int vsp1_drm_init(struct vsp1_device *vsp1) > > vsp1_pipeline_init(pipe); > > + pipe->frame_end = vsp1_du_pipeline_frame_end; > + Aha - just a code move - I was going to ask why this was here. That's fine. > /* >* The DRM pipeline is static, add entities manually. The first >* pipeline uses the BRU and the second pipeline the BRS. >*/ > pipe->bru = i == 0 ? &vsp1->bru->entity : &vsp1->brs->entity; > - pipe->lif = &vsp1->lif[i]->entity; > pipe->output = vsp1->wpf[i]; > - pipe->output->pipe = pipe; > - pipe->frame_end = vsp1_du_pipeline_frame_end; > + pipe->lif = &vsp1->lif[i]->entity; > > + pipe->bru->pipe = pipe; > pipe->bru->sink = &pipe->output->entity; > pipe->bru->sink_pad = 0; > + list_add_tail(&pipe->bru->list_pipe, &pipe->entities); > + > + pipe->output->entity.pipe = pipe; Ick ... pipe->bru->pipe, but pipe->output->entity.pipe ... BRU is already an entity, whereas output is an RPF. A bit painful on the eyes for review - but nothing to be done there I don't think. > pipe->output->entity.sink = pipe->lif; > pipe->output->entity.sink_pad = 0; > + list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities); > > - list_add_tail(&pipe->bru->list_pipe, &pipe->entities); > + pipe->lif->pipe = pipe; > list_add_tail(&pipe->lif->list_pipe, &pipe->entities); > - list_add_tail(&pipe->output->entity.list_pipe, &pipe->entities); > } > > /* Disable all RPFs initially. */ > diff --git a/drivers/media/platform/vsp1/vsp1_drv.c > b/drivers/media/platform/vsp1/vsp1_drv.c > index eed9516e25e1..58a7993f2306 100644 > --- a/drivers/media/platform/vsp1/vsp1_drv.c > +++ b/drivers/media/platform/vsp1/vsp1_drv.c > @@ -63,7 +63,7 @@ static irqreturn_t vsp1_irq_handler(int irq, void *data) > vsp1_write(vsp1, VI6_WPF_IRQ_STA(i), ~status & mask); > >
Re: [PATCH 2/8] PCI: Add pci_find_common_upstream_dev()
On Sun, Mar 25, 2018 at 12:59:54PM +0200, Christian König wrote: > From: "wda...@nvidia.com" > > Add an interface to find the first device which is upstream of both > devices. Please work with Logan and base this on top of the outstanding peer to peer patchset.
Re: [PATCH 1/8] lib/scatterlist: add sg_set_dma_addr() helper
On Sun, Mar 25, 2018 at 12:59:53PM +0200, Christian König wrote: > Use this function to set an sg entry to point to device resources mapped > using dma_map_resource(). The page pointer is set to NULL and only the DMA > address, length and offset values are valid. NAK. Please provide a higher level primitive. Btw, you series seems to miss a cover letter.