* Re: [WireGuard] [PATCH v3] ip6_output: ensure flow saddr actually belongs to device
From: Jason A. Donenfeld @ 2016-11-14 16:54 UTC (permalink / raw)
To: David Ahern, David Miller
Cc: Netdev, Hannes Frederic Sowa, YOSHIFUJI Hideaki,
WireGuard mailing list, LKML
In-Reply-To: <CAHmME9qC4xqGOwJnauXrJBDkAtmmuJ+kJKL6ufuU9_XWKNFdSA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 201 bytes --]
On Nov 14, 2016 17:19, "David Ahern" <dsa@cumulusnetworks.com> wrote:
>
> LGTM
>
> Acked-by: David Ahern <dsa@cumulusnetworks.com>
Great.
@DaveM: can we get this in 4.9 and in stable?
Thanks,
Jason
[-- Attachment #2: Type: text/html, Size: 410 bytes --]
^ permalink raw reply
* Re: [RFC PATCH v3 02/20] x86: Set the write-protect cache mode for full PAT support
From: Tom Lendacky @ 2016-11-14 16:51 UTC (permalink / raw)
To: Kani, Toshimitsu, bp-Gina5bIWoIWzQB+pC5nmwQ@public.gmane.org
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
rkrcmar-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
kvm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org,
linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org,
glider-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
hpa-YMNOUZJC4hwAvxtiuMwx3w@public.gmane.org,
lwoodman-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
linux-arch-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
corbet-T1hC0tSOHrs@public.gmane.org,
x86-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
kasan-dev-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org,
mingo-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
aryabinin-5HdwGun5lf+gSpxsJD1C4w@public.gmane.org,
riel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
arnd-r2nGTMty4D4@public.gmane.org,
luto-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org,
dvyukov-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org
In-Reply-To: <1478827480.20881.142.camel-ZPxbGqLxI0U@public.gmane.org>
On 11/10/2016 07:26 PM, Kani, Toshimitsu wrote:
> On Thu, 2016-11-10 at 14:14 +0100, Borislav Petkov wrote:
>> + Toshi.
>>
>> On Wed, Nov 09, 2016 at 06:34:48PM -0600, Tom Lendacky wrote:
>>>
>>> For processors that support PAT, set the write-protect cache mode
>>> (_PAGE_CACHE_MODE_WP) entry to the actual write-protect value
>>> (x05).
>
> Using slot 6 may be more cautious (for the same reason slot 7 was used
> for WT), but I do not have a strong opinion for it.
>
> set_page_memtype() cannot track the use of WP type since there is no
> extra-bit available for WP, but WP is only supported by
> early_memremap_xx() interfaces in this series. So, I think we should
> just document that WP is only intended for temporary mappings at boot-
> time until this issue is resolved. Also, we need to make sure that
> this early_memremap for WP is only called after pat_init() is done.
Sounds good, I'll add documentation to cover these points.
>
> A nit - please add WP to the function header comment below.
> "This function initializes PAT MSR and PAT table with an OS-defined
> value to enable additional cache attributes, WC and WT."
Will do.
Thanks,
Tom
>
> Thanks,
> -Toshi
>
^ permalink raw reply
* Re: [RFC PATCH v3 02/20] x86: Set the write-protect cache mode for full PAT support
From: Tom Lendacky @ 2016-11-14 16:51 UTC (permalink / raw)
To: Kani, Toshimitsu, bp-Gina5bIWoIWzQB+pC5nmwQ@public.gmane.org
Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
rkrcmar-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
kvm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
matt-mF/unelCI9GS6iBeEJttW/XRex20P6io@public.gmane.org,
linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org,
glider-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org,
hpa-YMNOUZJC4hwAvxtiuMwx3w@public.gmane.org,
lwoodman-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
linux-arch-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
corbet-T1hC0tSOHrs@public.gmane.org,
x86-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
kasan-dev-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org,
mingo-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
aryabinin-5HdwGun5lf+gSpxsJD1C4w@public.gmane.org,
riel-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
arnd-r2nGTMty4D4@public.gmane.org,
luto-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
tglx-hfZtesqFncYOwBW4kG4KsQ@public.gmane.org,
dvyukov-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org
In-Reply-To: <1478827480.20881.142.camel-ZPxbGqLxI0U@public.gmane.org>
On 11/10/2016 07:26 PM, Kani, Toshimitsu wrote:
> On Thu, 2016-11-10 at 14:14 +0100, Borislav Petkov wrote:
>> + Toshi.
>>
>> On Wed, Nov 09, 2016 at 06:34:48PM -0600, Tom Lendacky wrote:
>>>
>>> For processors that support PAT, set the write-protect cache mode
>>> (_PAGE_CACHE_MODE_WP) entry to the actual write-protect value
>>> (x05).
>
> Using slot 6 may be more cautious (for the same reason slot 7 was used
> for WT), but I do not have a strong opinion for it.
>
> set_page_memtype() cannot track the use of WP type since there is no
> extra-bit available for WP, but WP is only supported by
> early_memremap_xx() interfaces in this series. So, I think we should
> just document that WP is only intended for temporary mappings at boot-
> time until this issue is resolved. Also, we need to make sure that
> this early_memremap for WP is only called after pat_init() is done.
Sounds good, I'll add documentation to cover these points.
>
> A nit - please add WP to the function header comment below.
> "This function initializes PAT MSR and PAT table with an OS-defined
> value to enable additional cache attributes, WC and WT."
Will do.
Thanks,
Tom
>
> Thanks,
> -Toshi
>
^ permalink raw reply
* Re: [Qemu-devel] [PATCH v6 1/2] block/vxhs.c: Add support for a new block device type called "vxhs"
From: Stefan Hajnoczi @ 2016-11-14 16:50 UTC (permalink / raw)
To: Fam Zheng
Cc: Ashish Mittal, qemu-devel, pbonzini, kwolf, armbru, berrange,
jcody, ashish.mittal, Rakesh.Ranjan, Buddhi.Madhav,
Ketan.Nilangekar, Abhijit.Dey, Venkatesha.Mg
In-Reply-To: <20161114154906.GC2373@lemon>
[-- Attachment #1: Type: text/plain, Size: 1360 bytes --]
On Mon, Nov 14, 2016 at 11:49:06PM +0800, Fam Zheng wrote:
> On Mon, 11/14 15:07, Stefan Hajnoczi wrote:
> > On Mon, Nov 07, 2016 at 04:59:44PM -0800, Ashish Mittal wrote:
> > > diff --git a/block/vxhs.c b/block/vxhs.c
> > > new file mode 100644
> > > index 0000000..8913e8f
> > > --- /dev/null
> > > +++ b/block/vxhs.c
> > > @@ -0,0 +1,689 @@
> > > +/*
> > > + * QEMU Block driver for Veritas HyperScale (VxHS)
> > > + *
> > > + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> > > + * See the COPYING file in the top-level directory.
> > > + *
> > > + */
> > > +
> > > +#include "qemu/osdep.h"
> > > +#include "block/block_int.h"
> > > +#include <qnio/qnio_api.h>
> >
> > Please move system headers (<>) above user headers (""). This way you
> > can be sure the system header isn't affected by any macros defined by
> > user headers.
>
> Yes, but still after "qemu/osdep.h", which prepares necessary bits for any other
> headers.
I disagree. qnio_api.h is a third-party library that doesn't need QEMU
headers to fix up the environment for it.
By including osdep.h first you mask bugs in qnio_api.h. Perhaps
qnio_api.h forgot to include a header and we won't notice because
osdep.h happened to bring in those headers first...
Can you explain the rationale for your statement?
Stefan
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]
^ permalink raw reply
* [U-Boot] [PATCH 1/6][v3] armv8: lsch3: Add generic get_svr() in assembly
From: york sun @ 2016-11-14 16:50 UTC (permalink / raw)
To: u-boot
In-Reply-To: <1478170950-16083-2-git-send-email-priyanka.jain@nxp.com>
On 11/03/2016 04:12 AM, Priyanka Jain wrote:
> Signed-off-by: Priyanka Jain <priyanka.jain@nxp.com>
> ---
> arch/arm/cpu/armv8/fsl-layerscape/cpu.c | 7 -------
> arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S | 9 +++++++++
> .../include/asm/arch-fsl-layerscape/immap_lsch3.h | 6 +++---
> 3 files changed, 12 insertions(+), 10 deletions(-)
>
> diff --git a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
> index b7a2e0c..2863e18 100644
> --- a/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
> +++ b/arch/arm/cpu/armv8/fsl-layerscape/cpu.c
> @@ -305,13 +305,6 @@ u32 fsl_qoriq_core_to_type(unsigned int core)
> return -1; /* cannot identify the cluster */
> }
>
> -uint get_svr(void)
> -{
> - struct ccsr_gur __iomem *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR);
> -
> - return gur_in32(&gur->svr);
> -}
> -
> #ifdef CONFIG_DISPLAY_CPUINFO
> int print_cpuinfo(void)
> {
> diff --git a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
> index 5d0b7a4..ee20c27 100644
> --- a/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
> +++ b/arch/arm/cpu/armv8/fsl-layerscape/lowlevel.S
> @@ -13,6 +13,9 @@
> #ifdef CONFIG_MP
> #include <asm/arch/mp.h>
> #endif
> +#ifdef CONFIG_FSL_LSCH3
> +#include <asm/arch-fsl-layerscape/immap_lsch3.h>
> +#endif
>
> ENTRY(lowlevel_init)
> mov x29, lr /* Save LR */
> @@ -199,6 +202,12 @@ ENTRY(lowlevel_init)
> ENDPROC(lowlevel_init)
>
> #ifdef CONFIG_FSL_LSCH3
> + .globl get_svr
> +get_svr:
> + ldr x1, =FSL_LSCH3_SVR
> + ldr w0, [x1]
> + ret
> +
This has an issue with non_lsch3 SoCs. You will see compiling error on
them, for example ls1012afrdm_qspi.
York
^ permalink raw reply
* Re: [RFC 02/14] SoundWire: Add SoundWire stream documentation
From: Pierre-Louis Bossart @ 2016-11-14 16:50 UTC (permalink / raw)
To: Charles Keepax, Hardik Shah
Cc: alsa-devel, linux-kernel, tiwai, broonie, lgirdwood, plai,
patches.audio, Sanyog Kale
In-Reply-To: <20161114153159.GM1575@localhost.localdomain>
>> +SoundWire stream states
>> +=======================
>> +Below figure shows the SoundWire stream states and possible state
>> +transition diagram.
>> +
>> +|--------------| |-------------| |--------------| |--------------|
>> +| ALLOC |---->| CONFIG |---->| PREPARE |---->| ENABLE |
>> +| STATE | | STATE | | STATE | | STATE |
>> +|--------------| |-------------| |--------------| |--------------|
>> + ^ |
>> + | |
>> + | |
>> + | |
>> + | \/
>> + |--------------| |--------------| |--------------|
>> + | RELEASE |<--------------------| DEPREPARE |<----| DISABLE |
>> + | STATE | | STATE | | STATE |
>> + |--------------| |--------------| |--------------|
>> +
>
> One minor comment, this looks very similar to the clock
> frameworks state model, but the clock framework calls it
> unprepare would there be some milage in aligning to?
The SoundWire spec uses de-prepare, e.g. "De-prepare_Finished"
I'd rather stick to the wording between a spec and the implementation of
said spec, rather than introduce a term/concept from an unrelated framework.
>
>> +
>> +SoundWire Stream State Operations
>> +==================================
>> +Below section explains the operations done by the bus driver on
>> +Master(s) and Slave(s) as part of stream state transitions.
>> +
>> +SDW_STATE_STRM_ALLOC: Allocation state for stream. This is the entry
>> +state of the stream. Operations performed before entering in this
>> +state:
>> +1. An unique stream tag is assigned to stream. This stream tag is used
>
> A unique
ok
>
>> +as a reference for all the operations performed on stream.
>> +
>> +2. The resources required for holding stream runtime information are
>> +allocated and initialized. This holds all stream related information
>> +such as stream type (PCM/PDM) and parameters, Master and Slave interface
>> +associated with the stream, reference counting, stream state etc.
>> +
>> +After all above operations are successful, stream state is set to
>> +SDW_STATE_STRM_ALLOC.
>> +
>> +
>> +SDW_STATE_STRM_CONFIG: Configuration state of stream. Operations
>> +performed before entering in this state:
>> +1. The resources allocated for stream information in
>> +SDW_STATE_STRM_ALLOC state are updated. This includes stream parameters,
>> +Masters and Slaves runtime information associated with the stream.
>> +
>> +2. All the Masters and Slaves associated with the stream updates the
>> +port configuration to bus driver. This includes port numbers allocated
>> +by Master(s) and Slave(s) for this stream.
>> +
>> +After all above operations are successful, stream state is set to
>> +SDW_STATE_STRM_CONFIG.
>> +
>> +
>> +SDW_STATE_STRM_PREPARE: Prepare state of stream. Operations performed
>> +before entering in this state:
>> +1. Bus parameters such as bandwidth, frame shape, clock frequency, SSP
>> +interval are computed based on current stream as well as already active
>> +streams on bus. Re-computation is required to accommodate current stream
>> +on the bus.
>> +
>> +2. Transport parameters of all Master and Slave ports are computed for
>> +the current as well as already active stream based on above calculated
>> +frame shape and clock frequency.
>> +
>> +3. Computed bus and transport parameters are programmed in Master and
>> +Slave registers. The banked registers programming is done on the
>> +alternate bank (bank currently unused). Port channels are enabled for
>> +the already active streams on the alternate bank (bank currently
>> +unused). This is done in order to not to disrupt already active
>> +stream(s).
>> +
>> +4. Once all the new values are programmed, bus initiates switch to
>> +alternate bank. Once switch is successful, the port channels enabled on
>> +previous bank for already active streams are disabled.
This last sentence makes no sense in this context, probably a copy/paste
that shouldn't be there. The previously active streams remain active in
this prepare step.
>> +
>> +5. Ports of Master and Slave for current stream are prepared.
>> +
>> +After all above operations are successful, stream state is set to
>> +SDW_STATE_STRM_PREPARE.
>> +
>> +
>> +SDW_STATE_STRM_ENABLE: Enable state of stream. Operations performed
>> +before entering in this state:
>> +1. All the values computed in SDW_STATE_STRM_PREPARE state are
>> +programmed in alternate bank (bank currently unused). It includes
>> +programming of already active streams as well.
>> +
>> +2. All the Master and Slave port channels for the current stream are
>> +enabled on alternate bank (bank currently unused).
>> +
>
> This could probably use a little more explaination to show how it
> differs from step 3/4 in PREPARE, as it looks like all the
> computed values where applied there. I imagine this is just my lack
> of understanding rather than an actual issue but even looking at
> the code I am having a little difficulty tying up these two.
Yes, see above there was an extra sentence that isn't right.
>
> sdw_prepare_op
> - sdw_compute_params (prepare step 1/2)
> - sdw_program_params (prepare step 3)
> - sdw_update_bus_params (prepare step 4)
>
> sdw_enable_op
> - sdw_program_params (enable step 1)
> - sdw_update_bus_params (enable step 2)
>
> It looks like the params are still basically the same as they
> were when we called sdw_program_params in prepare.
The parameters are the same except for the channel-enable flags which
are only programmed and activated via a bank switch in the enable step.
^ permalink raw reply
* [ovmf baseline-only test] 68035: all pass
From: Platform Team regression test user @ 2016-11-14 16:50 UTC (permalink / raw)
To: xen-devel, osstest-admin
This run is configured for baseline tests only.
flight 68035 ovmf real [real]
http://osstest.xs.citrite.net/~osstest/testlogs/logs/68035/
Perfect :-)
All tests in this flight passed as required
version targeted for testing:
ovmf bab82372a9e6ce066fa725a792e71d07191046ca
baseline version:
ovmf b17d5507cfdfd10c4f1f5911ffe75fdc49fafa37
Last test of basis 68034 2016-11-14 12:18:33 Z 0 days
Testing same since 68035 2016-11-14 14:46:46 Z 0 days 1 attempts
------------------------------------------------------------
People who touched revisions under test:
Hao Wu <hao.a.wu@intel.com>
jobs:
build-amd64-xsm pass
build-i386-xsm pass
build-amd64 pass
build-i386 pass
build-amd64-libvirt pass
build-i386-libvirt pass
build-amd64-pvops pass
build-i386-pvops pass
test-amd64-amd64-xl-qemuu-ovmf-amd64 pass
test-amd64-i386-xl-qemuu-ovmf-amd64 pass
------------------------------------------------------------
sg-report-flight on osstest.xs.citrite.net
logs: /home/osstest/logs
images: /home/osstest/images
Logs, config files, etc. are available at
http://osstest.xs.citrite.net/~osstest/testlogs/logs
Test harness code can be found at
http://xenbits.xensource.com/gitweb?p=osstest.git;a=summary
Push not applicable.
------------------------------------------------------------
commit bab82372a9e6ce066fa725a792e71d07191046ca
Author: Hao Wu <hao.a.wu@intel.com>
Date: Fri Nov 11 16:21:35 2016 +0800
DuetPkg: Add POSTBUILD in DSC files to run post-build automatically
https://bugzilla.tianocore.org/show_bug.cgi?id=220
Currently, the post-build scripts PostBuild.bat/PostBuild.sh in DuetPkg
need to be run manually. Especially for Windows batch script, it also
requires users to set the build options (like tool chain, target and arch)
in file Conf/target.txt. If users using command line options via '-t' or
'-a', the post-build script won't work properly.
The package DSC files now support the feature to execute post-build script
automatically by adding a 'POSTBUILD' definition. This feature also passes
the build options into the post-build script as parameters. This commit
uses this feature to make the post-build works for DuetPkg more
user-friendly. Also, ReadMe.txt is updated to reflect the new steps for
UEFI Emulation (DUET) development.
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
commit ea4511d127f45e5028996aba6613b4807c3c7902
Author: Hao Wu <hao.a.wu@intel.com>
Date: Fri Nov 11 16:15:52 2016 +0800
DuetPkg: Use 'echo off' in BATCH script files
Instead of putting a '@' at the beginning of every command in BATCH script
files, use 'echo off' at the beginning of each file.
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
commit 24476311ed2d92b8ed7040ef101b019b2d3d7991
Author: Hao Wu <hao.a.wu@intel.com>
Date: Fri Nov 11 16:08:35 2016 +0800
DuetPkg: Resolve white-space issues for post-build scripts & ReadMe
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Hao Wu <hao.a.wu@intel.com>
Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel
^ permalink raw reply
* Re: [RFC PATCH v3 14/20] iommu/amd: Disable AMD IOMMU if memory encryption is active
From: Tom Lendacky @ 2016-11-14 16:48 UTC (permalink / raw)
To: Joerg Roedel
Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
kasan-dev, linux-mm, iommu, Rik van Riel,
Radim Krčmář, Arnd Bergmann, Jonathan Corbet,
Matt Fleming, Konrad Rzeszutek Wilk, Paolo Bonzini, Larry Woodman,
Ingo Molnar, Borislav Petkov, Andy Lutomirski, H. Peter Anvin,
Andrey Ryabinin, Alexander Potapenko, Thomas Gleixner,
Dmitry Vyukov
In-Reply-To: <20161114163204.GA2078@8bytes.org>
On 11/14/2016 10:32 AM, Joerg Roedel wrote:
> On Wed, Nov 09, 2016 at 06:37:32PM -0600, Tom Lendacky wrote:
>> + /* For now, disable the IOMMU if SME is active */
>> + if (sme_me_mask)
>> + return -ENODEV;
>> +
>
> Please print a message here telling the user why the IOMMU got disabled.
Will do.
Thanks,
Tom
>
>
> Thanks,
>
> Joerg
>
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH 4.8 00/35] 4.8.8-stable review
From: Shuah Khan @ 2016-11-14 16:48 UTC (permalink / raw)
To: Greg Kroah-Hartman, linux-kernel
Cc: torvalds, akpm, linux, patches, ben.hutchings, stable, Shuah Khan
In-Reply-To: <20161113112420.863033770@linuxfoundation.org>
On 11/13/2016 04:27 AM, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 4.8.8 release.
> There are 35 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Tue Nov 15 11:24:10 UTC 2016.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.8.8-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.8.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
>
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America(Silicon Valley)
shuah.kh@samsung.com
^ permalink raw reply
* Re: [RFC PATCH v3 14/20] iommu/amd: Disable AMD IOMMU if memory encryption is active
From: Tom Lendacky @ 2016-11-14 16:48 UTC (permalink / raw)
To: Joerg Roedel
Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
kasan-dev, linux-mm, iommu, Rik van Riel,
Radim Krčmář, Arnd Bergmann, Jonathan Corbet,
Matt Fleming, Konrad Rzeszutek Wilk, Paolo Bonzini, Larry Woodman,
Ingo Molnar, Borislav Petkov, Andy Lutomirski, H. Peter Anvin,
Andrey Ryabinin, Alexander Potapenko, Thomas Gleixner,
Dmitry Vyukov
In-Reply-To: <20161114163204.GA2078@8bytes.org>
On 11/14/2016 10:32 AM, Joerg Roedel wrote:
> On Wed, Nov 09, 2016 at 06:37:32PM -0600, Tom Lendacky wrote:
>> + /* For now, disable the IOMMU if SME is active */
>> + if (sme_me_mask)
>> + return -ENODEV;
>> +
>
> Please print a message here telling the user why the IOMMU got disabled.
Will do.
Thanks,
Tom
>
>
> Thanks,
>
> Joerg
>
^ permalink raw reply
* Re: [RFC PATCH v3 14/20] iommu/amd: Disable AMD IOMMU if memory encryption is active
From: Tom Lendacky @ 2016-11-14 16:48 UTC (permalink / raw)
To: Joerg Roedel
Cc: linux-arch, linux-efi, kvm, linux-doc, x86, linux-kernel,
kasan-dev, linux-mm, iommu, Rik van Riel,
Radim Krčmář, Arnd Bergmann, Jonathan Corbet,
Matt Fleming, Konrad Rzeszutek Wilk, Paolo Bonzini, Larry Woodman,
Ingo Molnar, Borislav Petkov, Andy Lutomirski, H. Peter Anvin,
Andrey Ryabinin
In-Reply-To: <20161114163204.GA2078@8bytes.org>
On 11/14/2016 10:32 AM, Joerg Roedel wrote:
> On Wed, Nov 09, 2016 at 06:37:32PM -0600, Tom Lendacky wrote:
>> + /* For now, disable the IOMMU if SME is active */
>> + if (sme_me_mask)
>> + return -ENODEV;
>> +
>
> Please print a message here telling the user why the IOMMU got disabled.
Will do.
Thanks,
Tom
>
>
> Thanks,
>
> Joerg
>
^ permalink raw reply
* Re: [PATCH 1/2] NFSv4: Fix CLOSE races with OPEN
From: Trond Myklebust @ 2016-11-14 16:48 UTC (permalink / raw)
To: jlayton@redhat.com, linux-nfs@vger.kernel.org; +Cc: bcodding@redhat.com
In-Reply-To: <1479141648.2510.10.camel@redhat.com>
T24gTW9uLCAyMDE2LTExLTE0IGF0IDExOjQwIC0wNTAwLCBKZWZmIExheXRvbiB3cm90ZToNCj4g
T24gTW9uLCAyMDE2LTExLTE0IGF0IDExOjE5IC0wNTAwLCBUcm9uZCBNeWtsZWJ1c3Qgd3JvdGU6
DQo+ID4gDQo+ID4gSWYgdGhlIHJlcGx5IHRvIGEgc3VjY2Vzc2Z1bCBDTE9TRSBjYWxsIHJhY2Vz
IHdpdGggYW4gT1BFTiB0byB0aGUNCj4gPiBzYW1lDQo+ID4gZmlsZSwgd2UgY2FuIGVuZCB1cCBz
Y3JpYmJsaW5nIG92ZXIgdGhlIHN0YXRlaWQgdGhhdCByZXByZXNlbnRzIHRoZQ0KPiA+IG5ldyBv
cGVuIHN0YXRlLg0KPiA+IFRoZSByYWNlIGxvb2tzIGxpa2U6DQo+ID4gDQo+ID4gwqAgQ2xpZW50
CQkJCVNlcnZlcg0KPiA+IMKgID09PT09PQkJCQk9PT09PT0NCj4gPiANCj4gPiDCoCBDTE9TRSBz
dGF0ZWlkIEEgb24gZmlsZSAiZm9vIg0KPiA+IAkJCQkJQ0xPU0Ugc3RhdGVpZCBBLCByZXR1cm4g
c3RhdGVpZA0KPiA+IEMNCj4gPiDCoCBPUEVOIGZpbGUgImZvbyINCj4gPiAJCQkJCU9QRU4gImZv
byIsIHJldHVybiBzdGF0ZWlkIEINCj4gPiDCoCBSZWNlaXZlIHJlcGx5IHRvIE9QRU4NCj4gPiDC
oCBSZXNldCBvcGVuIHN0YXRlIGZvciAiZm9vIg0KPiA+IMKgIEFzc29jaWF0ZSBzdGF0ZWlkIEIg
dG8gImZvbyINCj4gPiANCj4gPiDCoCBSZWNlaXZlIENMT1NFIGZvciBBDQo+ID4gwqAgUmVzZXQg
b3BlbiBzdGF0ZSBmb3IgImZvbyINCj4gPiDCoCBSZXBsYWNlIHN0YXRlaWQgQiB3aXRoIEMNCj4g
PiANCj4gPiBUaGUgZml4IGlzIHRvIGV4YW1pbmUgdGhlIGFyZ3VtZW50IG9mIHRoZSBDTE9TRSwg
YW5kIGNoZWNrIGZvciBhDQo+ID4gbWF0Y2gNCj4gPiB3aXRoIHRoZSBjdXJyZW50IHN0YXRlaWQg
Im90aGVyIiBmaWVsZC4gSWYgdGhlIHR3byBkbyBub3QgbWF0Y2gsDQo+ID4gdGhlbg0KPiA+IHRo
ZSBhYm92ZSByYWNlIG9jY3VycmVkLCBhbmQgd2Ugc2hvdWxkIGp1c3QgaWdub3JlIHRoZSBDTE9T
RS4NCj4gPiANCj4gPiBSZXBvcnRlZC1ieTogQmVuamFtaW4gQ29kZGluZ3RvbiA8YmNvZGRpbmdA
cmVkaGF0LmNvbT4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBUcm9uZCBNeWtsZWJ1c3QgPHRyb25kLm15
a2xlYnVzdEBwcmltYXJ5ZGF0YS5jb20+DQo+ID4gLS0tDQo+ID4gwqBmcy9uZnMvbmZzNF9mcy5o
wqDCoHzCoMKgNyArKysrKysrDQo+ID4gwqBmcy9uZnMvbmZzNHByb2MuYyB8IDEyICsrKysrKy0t
LS0tLQ0KPiA+IMKgMiBmaWxlcyBjaGFuZ2VkLCAxMyBpbnNlcnRpb25zKCspLCA2IGRlbGV0aW9u
cygtKQ0KPiA+IA0KPiA+IGRpZmYgLS1naXQgYS9mcy9uZnMvbmZzNF9mcy5oIGIvZnMvbmZzL25m
czRfZnMuaA0KPiA+IGluZGV4IDliM2E4MmFiYWIwNy4uMTQ1MjE3N2M4MjJkIDEwMDY0NA0KPiA+
IC0tLSBhL2ZzL25mcy9uZnM0X2ZzLmgNCj4gPiArKysgYi9mcy9uZnMvbmZzNF9mcy5oDQo+ID4g
QEAgLTU0Miw2ICs1NDIsMTMgQEAgc3RhdGljIGlubGluZSBib29sDQo+ID4gbmZzNF92YWxpZF9v
cGVuX3N0YXRlaWQoY29uc3Qgc3RydWN0IG5mczRfc3RhdGUgKnN0YXRlKQ0KPiA+IMKgCXJldHVy
biB0ZXN0X2JpdChORlNfU1RBVEVfUkVDT1ZFUllfRkFJTEVELCAmc3RhdGUtPmZsYWdzKQ0KPiA+
ID09IDA7DQo+ID4gwqB9DQo+ID4gwqANCj4gPiArc3RhdGljIGlubGluZSBib29sIG5mczRfc3Rh
dGVfbWF0Y2hfb3Blbl9zdGF0ZWlkX290aGVyKGNvbnN0DQo+ID4gc3RydWN0IG5mczRfc3RhdGUg
KnN0YXRlLA0KPiA+ICsJCWNvbnN0IG5mczRfc3RhdGVpZCAqc3RhdGVpZCkNCj4gPiArew0KPiA+
ICsJcmV0dXJuIHRlc3RfYml0KE5GU19PUEVOX1NUQVRFLCAmc3RhdGUtPmZsYWdzKSAmJg0KPiA+
ICsJCW5mczRfc3RhdGVpZF9tYXRjaF9vdGhlcigmc3RhdGUtPm9wZW5fc3RhdGVpZCwNCj4gPiBz
dGF0ZWlkKTsNCj4gPiArfQ0KPiA+ICsNCj4gPiDCoCNlbHNlDQo+ID4gwqANCj4gPiDCoCNkZWZp
bmUgbmZzNF9jbG9zZV9zdGF0ZShhLCBiKSBkbyB7IH0gd2hpbGUgKDApDQo+ID4gZGlmZiAtLWdp
dCBhL2ZzL25mcy9uZnM0cHJvYy5jIGIvZnMvbmZzL25mczRwcm9jLmMNCj4gPiBpbmRleCBmNTUw
YWM2OWZmYTAuLmI3YjAwODA5NzdjMCAxMDA2NDQNCj4gPiAtLS0gYS9mcy9uZnMvbmZzNHByb2Mu
Yw0KPiA+ICsrKyBiL2ZzL25mcy9uZnM0cHJvYy5jDQo+ID4gQEAgLTE0NTgsNyArMTQ1OCw2IEBA
IHN0YXRpYyB2b2lkDQo+ID4gbmZzX3Jlc3luY19vcGVuX3N0YXRlaWRfbG9ja2VkKHN0cnVjdCBu
ZnM0X3N0YXRlICpzdGF0ZSkNCj4gPiDCoH0NCj4gPiDCoA0KPiA+IMKgc3RhdGljIHZvaWQgbmZz
X2NsZWFyX29wZW5fc3RhdGVpZF9sb2NrZWQoc3RydWN0IG5mczRfc3RhdGUNCj4gPiAqc3RhdGUs
DQo+ID4gLQkJbmZzNF9zdGF0ZWlkICphcmdfc3RhdGVpZCwNCj4gPiDCoAkJbmZzNF9zdGF0ZWlk
ICpzdGF0ZWlkLCBmbW9kZV90IGZtb2RlKQ0KPiA+IMKgew0KPiA+IMKgCWNsZWFyX2JpdChORlNf
T19SRFdSX1NUQVRFLCAmc3RhdGUtPmZsYWdzKTsNCj4gPiBAQCAtMTQ3NiwxMCArMTQ3NSw5IEBA
IHN0YXRpYyB2b2lkDQo+ID4gbmZzX2NsZWFyX29wZW5fc3RhdGVpZF9sb2NrZWQoc3RydWN0IG5m
czRfc3RhdGUgKnN0YXRlLA0KPiA+IMKgCX0NCj4gPiDCoAlpZiAoc3RhdGVpZCA9PSBOVUxMKQ0K
PiA+IMKgCQlyZXR1cm47DQo+ID4gLQkvKiBIYW5kbGUgcmFjZXMgd2l0aCBPUEVOICovDQo+ID4g
LQlpZiAoIW5mczRfc3RhdGVpZF9tYXRjaF9vdGhlcihhcmdfc3RhdGVpZCwgJnN0YXRlLQ0KPiA+
ID5vcGVuX3N0YXRlaWQpIHx8DQo+ID4gLQnCoMKgwqDCoChuZnM0X3N0YXRlaWRfbWF0Y2hfb3Ro
ZXIoc3RhdGVpZCwgJnN0YXRlLQ0KPiA+ID5vcGVuX3N0YXRlaWQpICYmDQo+ID4gLQnCoMKgwqDC
oCFuZnM0X3N0YXRlaWRfaXNfbmV3ZXIoc3RhdGVpZCwgJnN0YXRlLQ0KPiA+ID5vcGVuX3N0YXRl
aWQpKSkgew0KPiA+ICsJLyogSGFuZGxlIE9QRU4rT1BFTl9ET1dOR1JBREUgcmFjZXMgKi8NCj4g
PiArCWlmIChuZnM0X3N0YXRlaWRfbWF0Y2hfb3RoZXIoc3RhdGVpZCwgJnN0YXRlLQ0KPiA+ID5v
cGVuX3N0YXRlaWQpICYmDQo+ID4gKwnCoMKgwqDCoCFuZnM0X3N0YXRlaWRfaXNfbmV3ZXIoc3Rh
dGVpZCwgJnN0YXRlLT5vcGVuX3N0YXRlaWQpKSANCj4gPiB7DQo+ID4gwqAJCW5mc19yZXN5bmNf
b3Blbl9zdGF0ZWlkX2xvY2tlZChzdGF0ZSk7DQo+ID4gwqAJCXJldHVybjsNCj4gPiDCoAl9DQo+
ID4gQEAgLTE0OTMsNyArMTQ5MSw5IEBAIHN0YXRpYyB2b2lkIG5mc19jbGVhcl9vcGVuX3N0YXRl
aWQoc3RydWN0DQo+ID4gbmZzNF9zdGF0ZSAqc3RhdGUsDQo+ID4gwqAJbmZzNF9zdGF0ZWlkICpz
dGF0ZWlkLCBmbW9kZV90IGZtb2RlKQ0KPiA+IMKgew0KPiA+IMKgCXdyaXRlX3NlcWxvY2soJnN0
YXRlLT5zZXFsb2NrKTsNCj4gPiAtCW5mc19jbGVhcl9vcGVuX3N0YXRlaWRfbG9ja2VkKHN0YXRl
LCBhcmdfc3RhdGVpZCwgc3RhdGVpZCwNCj4gPiBmbW9kZSk7DQo+ID4gKwkvKiBJZ25vcmUsIGlm
IHRoZSBDTE9TRSBhcmdtZW50IGRvZXNuJ3QgbWF0Y2ggdGhlIGN1cnJlbnQNCj4gPiBzdGF0ZWlk
ICovDQo+ID4gKwlpZiAobmZzNF9zdGF0ZV9tYXRjaF9vcGVuX3N0YXRlaWRfb3RoZXIoc3RhdGUs
DQo+ID4gYXJnX3N0YXRlaWQpKQ0KPiA+ICsJCW5mc19jbGVhcl9vcGVuX3N0YXRlaWRfbG9ja2Vk
KHN0YXRlLCBzdGF0ZWlkLA0KPiA+IGZtb2RlKTsNCj4gPiDCoAl3cml0ZV9zZXF1bmxvY2soJnN0
YXRlLT5zZXFsb2NrKTsNCj4gPiDCoAlpZiAodGVzdF9iaXQoTkZTX1NUQVRFX1JFQ0xBSU1fTk9H
UkFDRSwgJnN0YXRlLT5mbGFncykpDQo+ID4gwqAJCW5mczRfc2NoZWR1bGVfc3RhdGVfbWFuYWdl
cihzdGF0ZS0+b3duZXItDQo+ID4gPnNvX3NlcnZlci0+bmZzX2NsaWVudCk7DQo+IA0KPiBJIHN0
aWxsIGRvbid0IHF1aXRlIGdldCBpdC4gV2hhdCdzIHRoZSBwb2ludCBvZiBwYXlpbmcgYW55IGF0
dGVudGlvbg0KPiBhdA0KPiBhbGwgdG8gdGhlIHN0YXRlaWQgcmV0dXJuZWQgYnkgdGhlIHNlcnZl
ciBpbiBhIENMT1NFIHJlc3BvbnNlPyBJdCdzDQo+IGVpdGhlcjoNCj4gDQo+IGEpIGNvbXBsZXRl
bHkgYm9ndXMsIGlmIHRoZSBzZXJ2ZXIgaXMgZm9sbG93aW5nIHRoZSBTSE9VTEQgaW4NCj4gUkZD
NTY2MSwNCj4gc2VjdGlvbiAxOC4yLjQNCj4gDQo+IC4uLm9yLi4uDQo+IA0KPiBiKSByZWZlcnMg
dG8gYSBub3ctZGVmdW5jdCBzdGF0ZWlkIC0tIHByb2JhYmx5IGEgbGF0ZXIgdmVyc2lvbiBvZiB0
aGUNCj4gb25lIHNlbnQgaW4gdGhlIHJlcXVlc3QsIGJ1dCB0aGUgc3BlYyBkb2Vzbid0IHJlYWxs
eSBzcGVsbCB0aGF0IG91dCwNCj4gQUZBSUNULg0KPiANCj4gSW4gZWl0aGVyIGNhc2UsIEkgZG9u
J3QgdGhpbmsgaXQgb3VnaHQgdG8gYmUgdHJ1c3RlZC4gV2h5IG5vdCBqdXN0DQo+IHVzZQ0KPiB0
aGUgYXJnX3N0YXRlaWQgdW5pdmVyc2FsbHkgaGVyZT8NCj4gDQoNClRoZSBjb2RlIHBhdGggYWxz
byBoYXMgdG8gaGFuZGxlIE9QRU5fRE9XTkdSQURFLg==
^ permalink raw reply
* Re: [PATCH 1/6] mm: khugepaged: fix radix tree node leak in shmem collapse error path
From: Johannes Weiner @ 2016-11-14 16:48 UTC (permalink / raw)
To: Kirill A. Shutemov
Cc: Jan Kara, Andrew Morton, Linus Torvalds, linux-mm, linux-kernel,
kernel-team
In-Reply-To: <20161114155250.GB3291@cmpxchg.org>
On Mon, Nov 14, 2016 at 10:52:50AM -0500, Johannes Weiner wrote:
> On Mon, Nov 14, 2016 at 05:29:02PM +0300, Kirill A. Shutemov wrote:
> > @@ -1400,7 +1400,9 @@ static void collapse_shmem(struct mm_struct *mm,
> > PAGE_SIZE, 0);
> >
> > spin_lock_irq(&mapping->tree_lock);
> > -
> > + slot = radix_tree_lookup_slot(&mapping->page_tree, index);
> > + VM_BUG_ON_PAGE(page != radix_tree_deref_slot_protected(slot,
> > + &mapping->tree_lock), page);
> > VM_BUG_ON_PAGE(page_mapped(page), page);
>
> That looks good to me. The slot may get relocated, but the content
> shouldn't change with the page locked.
>
> Are you going to send a full patch with changelog and sign-off? If so,
> please add:
>
> Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Just to clarify, this is in addition to my radix_tree_iter_next()
change. The iterator still needs to be reloaded because the number of
valid slots that come after the current one can change as well.
^ permalink raw reply
* Re: [PATCH 1/6] mm: khugepaged: fix radix tree node leak in shmem collapse error path
From: Johannes Weiner @ 2016-11-14 16:48 UTC (permalink / raw)
To: Kirill A. Shutemov
Cc: Jan Kara, Andrew Morton, Linus Torvalds, linux-mm, linux-kernel,
kernel-team
In-Reply-To: <20161114155250.GB3291@cmpxchg.org>
On Mon, Nov 14, 2016 at 10:52:50AM -0500, Johannes Weiner wrote:
> On Mon, Nov 14, 2016 at 05:29:02PM +0300, Kirill A. Shutemov wrote:
> > @@ -1400,7 +1400,9 @@ static void collapse_shmem(struct mm_struct *mm,
> > PAGE_SIZE, 0);
> >
> > spin_lock_irq(&mapping->tree_lock);
> > -
> > + slot = radix_tree_lookup_slot(&mapping->page_tree, index);
> > + VM_BUG_ON_PAGE(page != radix_tree_deref_slot_protected(slot,
> > + &mapping->tree_lock), page);
> > VM_BUG_ON_PAGE(page_mapped(page), page);
>
> That looks good to me. The slot may get relocated, but the content
> shouldn't change with the page locked.
>
> Are you going to send a full patch with changelog and sign-off? If so,
> please add:
>
> Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Just to clarify, this is in addition to my radix_tree_iter_next()
change. The iterator still needs to be reloaded because the number of
valid slots that come after the current one can change as well.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* Re: [PATCH 4.4 00/34] 4.4.32-stable review
From: Shuah Khan @ 2016-11-14 16:47 UTC (permalink / raw)
To: Greg Kroah-Hartman, linux-kernel
Cc: torvalds, akpm, linux, patches, ben.hutchings, stable, Shuah Khan
In-Reply-To: <20161113112400.008903838@linuxfoundation.org>
On 11/13/2016 04:24 AM, Greg Kroah-Hartman wrote:
> This is the start of the stable review cycle for the 4.4.32 release.
> There are 34 patches in this series, all will be posted as a response
> to this one. If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Tue Nov 15 11:23:42 UTC 2016.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.4.32-rc1.gz
> or in the git tree and branch at:
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-4.4.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
>
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
--
Shuah Khan
Sr. Linux Kernel Developer
Open Source Innovation Group
Samsung Research America(Silicon Valley)
shuah.kh@samsung.com
^ permalink raw reply
* [U-Boot] [PATCH] drivers: SPI: sunxi SPL: fix warning
From: Andre Przywara @ 2016-11-14 16:47 UTC (permalink / raw)
To: u-boot
In-Reply-To: <CAD6G_RTGGsYPd5psMzbDpwsQm2pFbQcL4iEqcPGswxLUP0+ucA@mail.gmail.com>
Hi,
On 14/11/16 16:30, Jagan Teki wrote:
> On Thu, Nov 3, 2016 at 6:28 AM, Andre Przywara <andre.przywara@arm.com> wrote:
>> Somehow an int returning function without a return statement sneaked
>> in. Fix it.
>>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> ---
>> drivers/mtd/spi/sunxi_spi_spl.c | 3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/mtd/spi/sunxi_spi_spl.c b/drivers/mtd/spi/sunxi_spi_spl.c
>> index 67c7edd..7502314 100644
>> --- a/drivers/mtd/spi/sunxi_spi_spl.c
>> +++ b/drivers/mtd/spi/sunxi_spi_spl.c
>> @@ -158,9 +158,10 @@ static void spi0_disable_clock(void)
>> (1 << AHB_RESET_SPI0_SHIFT));
>> }
>>
>> -static int spi0_init(void)
>> +static void spi0_init(void)
>> {
>> unsigned int pin_function = SUNXI_GPC_SPI0;
>> +
>
> Space not needed or unrelated, please remove this.
This is Linux coding style, which U-Boot adheres to.
"WARNING: Missing a blank line after declarations"
I thought I should fix this since this is was in the context of this
very simple patch and it improves readability.
If this is too much, then please remove the line before committing.
Thanks!
Andre.
^ permalink raw reply
* [PATCH tip/core/rcu 1/2] documentation: Present updated RCU guarantee
From: Paul E. McKenney @ 2016-11-14 16:47 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
In-Reply-To: <20161114164649.GA15056@linux.vnet.ibm.com>
Recent memory-model work deduces the relationships of RCU read-side
critical sections and grace periods based on the relationships of
accesses within a critical section and accesses preceding and following
the grace period. This commit therefore adds this viewpoint.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
.../RCU/Design/Requirements/Requirements.html | 25 +++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/Documentation/RCU/Design/Requirements/Requirements.html b/Documentation/RCU/Design/Requirements/Requirements.html
index a4d3838130e4..81b40cb83435 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.html
+++ b/Documentation/RCU/Design/Requirements/Requirements.html
@@ -547,7 +547,7 @@ The <tt>rcu_access_pointer()</tt> on line 6 is similar to
It could reuse a value formerly fetched from this same pointer.
It could also fetch the pointer from <tt>gp</tt> in a byte-at-a-time
manner, resulting in <i>load tearing</i>, in turn resulting a bytewise
- mash-up of two distince pointer values.
+ mash-up of two distinct pointer values.
It might even use value-speculation optimizations, where it makes
a wrong guess, but by the time it gets around to checking the
value, an update has changed the pointer to match the wrong guess.
@@ -659,6 +659,29 @@ systems with more than one CPU:
In other words, a given instance of <tt>synchronize_rcu()</tt>
can avoid waiting on a given RCU read-side critical section only
if it can prove that <tt>synchronize_rcu()</tt> started first.
+
+ <p>
+ A related question is “When <tt>rcu_read_lock()</tt>
+ doesn't generate any code, why does it matter how it relates
+ to a grace period?”
+ The answer if that it is not the relationship of
+ <tt>rcu_read_lock()</tt> itself that is important, but rather
+ the relationship of the code within the enclosed RCU read-side
+ critical section to the code preceding and following the
+ grace period.
+ If we take this viewpoint, then a given RCU read-side critical
+ section begins before a given grace period when some access
+ preceding the grace period observes the effect of some access
+ within the critical section, in which case none of the accesses
+ within the critical section may observe the effects of any
+ access following the grace period.
+
+ <p>
+ As of late 2016, mathematical models of RCU take this
+ viewpoint, for example, see slides 62 and 63
+ of the
+ <a href="http://www2.rdrop.com/users/paulmck/scalability/paper/LinuxMM.2016.10.04c.LCE.pdf">2016 LinuxCon EU</a>
+ presentation.
</font></td></tr>
<tr><td> </td></tr>
</table>
--
2.5.2
^ permalink raw reply related
* [PATCH tip/core/rcu 2/2] Documentation/RCU: Fix minor typo
From: Paul E. McKenney @ 2016-11-14 16:47 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani, Paul E. McKenney
In-Reply-To: <20161114164649.GA15056@linux.vnet.ibm.com>
From: Pranith Kumar <bobby.prani@gmail.com>
deference should actually be dereference.
Signed-off-by: Pranith Kumar <bobby.prani@gmail.com>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
---
Documentation/RCU/whatisRCU.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt
index 204422719197..5cbd8b2395b8 100644
--- a/Documentation/RCU/whatisRCU.txt
+++ b/Documentation/RCU/whatisRCU.txt
@@ -237,7 +237,7 @@ rcu_dereference()
The reader uses rcu_dereference() to fetch an RCU-protected
pointer, which returns a value that may then be safely
- dereferenced. Note that rcu_deference() does not actually
+ dereferenced. Note that rcu_dereference() does not actually
dereference the pointer, instead, it protects the pointer for
later dereferencing. It also executes any needed memory-barrier
instructions for a given CPU architecture. Currently, only Alpha
--
2.5.2
^ permalink raw reply related
* [PATCH tip/core/rcu 0/2] Documenmtation update for 4.10
From: Paul E. McKenney @ 2016-11-14 16:46 UTC (permalink / raw)
To: linux-kernel
Cc: mingo, jiangshanlai, dipankar, akpm, mathieu.desnoyers, josh,
tglx, peterz, rostedt, dhowells, edumazet, dvhart, fweisbec, oleg,
bobby.prani
Hello!
This series provides a couple of documentation updates:
1. Provide an updated description of RCU's grace-period guarantee
based on recent memory-model work. This does not change the
way that RCU behaves, but rather presents a more accurate view
of how it works. The difference is subtle, so most people won't
need to care.
2. Fix a "deference" -> "dereference" typo, courtesy of Pranith
Kumar.
Thanx, Paul
------------------------------------------------------------------------
Design/Requirements/Requirements.html | 25 ++++++++++++++++++++++++-
whatisRCU.txt | 2 +-
2 files changed, 25 insertions(+), 2 deletions(-)
^ permalink raw reply
* [PATCH v2 2/6] mfd: stm32-adc: Add support for stm32 ADC
From: Lee Jones @ 2016-11-14 16:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <9ba617f4-fd3d-2b48-2607-9eec3cc4253a@kernel.org>
On Sat, 12 Nov 2016, Jonathan Cameron wrote:
> On 10/11/16 16:18, Fabrice Gasnier wrote:
> > Add core driver for STMicroelectronics STM32 ADC (Analog to Digital
> > Converter). STM32 ADC can be composed of up to 3 ADCs with shared
> > resources like clock prescaler, common interrupt line and analog
> > reference voltage.
> > This core driver basically manages shared resources.
> >
> > Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
> Looks good to me (other than the build issue obviously ;)
>
> The fun bit will be trying to keep the whole thing this clean as you
> add the more 'interesting' functionality. *fingers crossed*
>
> Acked-by: Jonathan Cameron <jic23@kernel.org>
There isn't anything MFD about this driver.
Please move it into IIO.
> > ---
> > drivers/mfd/Kconfig | 14 ++
> > drivers/mfd/Makefile | 1 +
> > drivers/mfd/stm32-adc-core.c | 301 +++++++++++++++++++++++++++++++++++++
> > include/linux/mfd/stm32-adc-core.h | 52 +++++++
> > 4 files changed, 368 insertions(+)
> > create mode 100644 drivers/mfd/stm32-adc-core.c
> > create mode 100644 include/linux/mfd/stm32-adc-core.h
> >
> > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> > index c6df644..2580cee 100644
> > --- a/drivers/mfd/Kconfig
> > +++ b/drivers/mfd/Kconfig
> > @@ -1152,6 +1152,20 @@ config MFD_PALMAS
> > If you say yes here you get support for the Palmas
> > series of PMIC chips from Texas Instruments.
> >
> > +config MFD_STM32_ADC
> > + tristate "STMicroelectronics STM32 adc"
> > + depends on ARCH_STM32 || COMPILE_TEST
> > + depends on OF
> > + select MFD_CORE
> > + select REGULATOR
> > + select REGULATOR_FIXED_VOLTAGE
> > + help
> > + Select this option to enable the core driver for STMicroelectronics
> > + STM32 analog-to-digital converter (ADC).
> > +
> > + This driver can also be built as a module. If so, the module
> > + will be called stm32-adc-core.
> > +
> > config TPS6105X
> > tristate "TI TPS61050/61052 Boost Converters"
> > depends on I2C
> > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> > index 9834e66..4571506 100644
> > --- a/drivers/mfd/Makefile
> > +++ b/drivers/mfd/Makefile
> > @@ -185,6 +185,7 @@ obj-$(CONFIG_MFD_INTEL_LPSS_PCI) += intel-lpss-pci.o
> > obj-$(CONFIG_MFD_INTEL_LPSS_ACPI) += intel-lpss-acpi.o
> > obj-$(CONFIG_MFD_INTEL_MSIC) += intel_msic.o
> > obj-$(CONFIG_MFD_PALMAS) += palmas.o
> > +obj-$(CONFIG_MFD_STM32_ADC) += stm32-adc-core.o
> > obj-$(CONFIG_MFD_VIPERBOARD) += viperboard.o
> > obj-$(CONFIG_MFD_RC5T583) += rc5t583.o rc5t583-irq.o
> > obj-$(CONFIG_MFD_RK808) += rk808.o
> > diff --git a/drivers/mfd/stm32-adc-core.c b/drivers/mfd/stm32-adc-core.c
> > new file mode 100644
> > index 0000000..bcf52fb
> > --- /dev/null
> > +++ b/drivers/mfd/stm32-adc-core.c
> > @@ -0,0 +1,301 @@
> > +/*
> > + * This file is part of STM32 ADC driver
> > + *
> > + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
> > + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
> > + *
> > + * Inspired from: fsl-imx25-tsadc
> > + *
> > + * License type: GPLv2
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms of the GNU General Public License version 2 as published by
> > + * the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful, but
> > + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> > + * or FITNESS FOR A PARTICULAR PURPOSE.
> > + * See the GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License along with
> > + * this program. If not, see <http://www.gnu.org/licenses/>.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/irqchip/chained_irq.h>
> > +#include <linux/irqdesc.h>
> > +#include <linux/irqdomain.h>
> > +#include <linux/mfd/stm32-adc-core.h>
> > +#include <linux/module.h>
> > +#include <linux/of_device.h>
> > +#include <linux/regulator/consumer.h>
> > +#include <linux/slab.h>
> > +
> > +/* STM32F4 - common registers for all ADC instances: 1, 2 & 3 */
> > +#define STM32F4_ADC_CSR (STM32_ADCX_COMN_OFFSET + 0x00)
> > +#define STM32F4_ADC_CCR (STM32_ADCX_COMN_OFFSET + 0x04)
> > +
> > +/* STM32F4_ADC_CSR - bit fields */
> > +#define STM32F4_EOC3 BIT(17)
> > +#define STM32F4_EOC2 BIT(9)
> > +#define STM32F4_EOC1 BIT(1)
> > +
> > +/* STM32F4_ADC_CCR - bit fields */
> > +#define STM32F4_ADC_ADCPRE_SHIFT 16
> > +#define STM32F4_ADC_ADCPRE_MASK GENMASK(17, 16)
> > +
> > +/* STM32 F4 maximum analog clock rate (from datasheet) */
> > +#define STM32F4_ADC_MAX_CLK_RATE 36000000
> > +
> > +/**
> > + * struct stm32_adc_priv - stm32 ADC core private data
> > + * @irq: irq for ADC block
> > + * @domain: irq domain reference
> > + * @aclk: clock reference for the analog circuitry
> > + * @vref: regulator reference
> > + * @common: common data for all ADC instances
> > + */
> > +struct stm32_adc_priv {
> > + int irq;
> > + struct irq_domain *domain;
> > + struct clk *aclk;
> > + struct regulator *vref;
> > + struct stm32_adc_common common;
> > +};
> > +
> > +static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com)
> > +{
> > + return container_of(com, struct stm32_adc_priv, common);
> > +}
> > +
> > +/* STM32F4 ADC internal common clock prescaler division ratios */
> > +static int stm32f4_pclk_div[] = {2, 4, 6, 8};
> > +
> > +/**
> > + * stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler
> > + * @priv: stm32 ADC core private data
> > + * Select clock prescaler used for analog conversions, before using ADC.
> > + */
> > +static int stm32f4_adc_clk_sel(struct platform_device *pdev,
> > + struct stm32_adc_priv *priv)
> > +{
> > + unsigned long rate;
> > + u32 val;
> > + int i;
> > +
> > + rate = clk_get_rate(priv->aclk);
> > + for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) {
> > + if ((rate / stm32f4_pclk_div[i]) <= STM32F4_ADC_MAX_CLK_RATE)
> > + break;
> > + }
> > + if (i >= ARRAY_SIZE(stm32f4_pclk_div))
> > + return -EINVAL;
> > +
> > + val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR);
> > + val &= ~STM32F4_ADC_ADCPRE_MASK;
> > + val |= i << STM32F4_ADC_ADCPRE_SHIFT;
> > + writel_relaxed(val, priv->common.base + STM32F4_ADC_CCR);
> > +
> > + dev_dbg(&pdev->dev, "Using analog clock source at %ld kHz\n",
> > + rate / (stm32f4_pclk_div[i] * 1000));
> > +
> > + return 0;
> > +}
> > +
> > +/* ADC common interrupt for all instances */
> > +static void stm32_adc_irq_handler(struct irq_desc *desc)
> > +{
> > + struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc);
> > + struct irq_chip *chip = irq_desc_get_chip(desc);
> > + u32 status;
> > +
> > + chained_irq_enter(chip, desc);
> > + status = readl_relaxed(priv->common.base + STM32F4_ADC_CSR);
> > +
> > + if (status & STM32F4_EOC1)
> > + generic_handle_irq(irq_find_mapping(priv->domain, 0));
> > +
> > + if (status & STM32F4_EOC2)
> > + generic_handle_irq(irq_find_mapping(priv->domain, 1));
> > +
> > + if (status & STM32F4_EOC3)
> > + generic_handle_irq(irq_find_mapping(priv->domain, 2));
> > +
> > + chained_irq_exit(chip, desc);
> > +};
> > +
> > +static int stm32_adc_domain_map(struct irq_domain *d, unsigned int irq,
> > + irq_hw_number_t hwirq)
> > +{
> > + irq_set_chip_data(irq, d->host_data);
> > + irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq);
> > +
> > + return 0;
> > +}
> > +
> > +static void stm32_adc_domain_unmap(struct irq_domain *d, unsigned int irq)
> > +{
> > + irq_set_chip_and_handler(irq, NULL, NULL);
> > + irq_set_chip_data(irq, NULL);
> > +}
> > +
> > +static const struct irq_domain_ops stm32_adc_domain_ops = {
> > + .map = stm32_adc_domain_map,
> > + .unmap = stm32_adc_domain_unmap,
> > + .xlate = irq_domain_xlate_onecell,
> > +};
> > +
> > +static int stm32_adc_irq_probe(struct platform_device *pdev,
> > + struct stm32_adc_priv *priv)
> > +{
> > + struct device_node *np = pdev->dev.of_node;
> > +
> > + priv->irq = platform_get_irq(pdev, 0);
> > + if (priv->irq < 0) {
> > + dev_err(&pdev->dev, "failed to get irq\n");
> > + return priv->irq;
> > + }
> > +
> > + priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0,
> > + &stm32_adc_domain_ops,
> > + priv);
> > + if (!priv->domain) {
> > + dev_err(&pdev->dev, "Failed to add irq domain\n");
> > + return -ENOMEM;
> > + }
> > +
> > + irq_set_chained_handler(priv->irq, stm32_adc_irq_handler);
> > + irq_set_handler_data(priv->irq, priv);
> > +
> > + return 0;
> > +}
> > +
> > +static void stm32_adc_irq_remove(struct platform_device *pdev,
> > + struct stm32_adc_priv *priv)
> > +{
> > + int hwirq;
> > +
> > + for (hwirq = 0; hwirq < STM32_ADC_MAX_ADCS; hwirq++)
> > + irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq));
> > + irq_domain_remove(priv->domain);
> > + irq_set_chained_handler(priv->irq, NULL);
> > +}
> > +
> > +static int stm32_adc_probe(struct platform_device *pdev)
> > +{
> > + struct stm32_adc_priv *priv;
> > + struct device_node *np = pdev->dev.of_node;
> > + struct resource *res;
> > + int ret;
> > +
> > + if (!pdev->dev.of_node)
> > + return -ENODEV;
> > +
> > + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
> > + if (!priv)
> > + return -ENOMEM;
> > +
> > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > + priv->common.base = devm_ioremap_resource(&pdev->dev, res);
> > + if (IS_ERR(priv->common.base))
> > + return PTR_ERR(priv->common.base);
> > +
> > + priv->vref = devm_regulator_get(&pdev->dev, "vref");
> > + if (IS_ERR(priv->vref)) {
> > + ret = PTR_ERR(priv->vref);
> > + dev_err(&pdev->dev, "vref get failed, %d\n", ret);
> > + return ret;
> > + }
> > +
> > + ret = regulator_enable(priv->vref);
> > + if (ret < 0) {
> > + dev_err(&pdev->dev, "vref enable failed\n");
> > + return ret;
> > + }
> > +
> > + ret = regulator_get_voltage(priv->vref);
> > + if (ret < 0) {
> > + dev_err(&pdev->dev, "vref get voltage failed, %d\n", ret);
> > + goto err_regulator_disable;
> > + }
> > + priv->common.vref_mv = ret / 1000;
> > + dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv);
> > +
> > + priv->aclk = devm_clk_get(&pdev->dev, "adc");
> > + if (IS_ERR(priv->aclk)) {
> > + ret = PTR_ERR(priv->aclk);
> > + dev_err(&pdev->dev, "Can't get 'adc' clock\n");
> > + goto err_regulator_disable;
> > + }
> > +
> > + ret = clk_prepare_enable(priv->aclk);
> > + if (ret < 0) {
> > + dev_err(&pdev->dev, "adc clk enable failed\n");
> > + goto err_regulator_disable;
> > + }
> > +
> > + ret = stm32f4_adc_clk_sel(pdev, priv);
> > + if (ret < 0) {
> > + dev_err(&pdev->dev, "adc clk selection failed\n");
> > + goto err_clk_disable;
> > + }
> > +
> > + ret = stm32_adc_irq_probe(pdev, priv);
> > + if (ret < 0)
> > + goto err_clk_disable;
> > +
> > + platform_set_drvdata(pdev, &priv->common);
> > +
> > + ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
> > + if (ret < 0) {
> > + dev_err(&pdev->dev, "failed to populate DT children\n");
> > + goto err_irq_remove;
> > + }
> > +
> > + return 0;
> > +
> > +err_irq_remove:
> > + stm32_adc_irq_remove(pdev, priv);
> > +
> > +err_clk_disable:
> > + clk_disable_unprepare(priv->aclk);
> > +
> > +err_regulator_disable:
> > + regulator_disable(priv->vref);
> > +
> > + return ret;
> > +}
> > +
> > +static int stm32_adc_remove(struct platform_device *pdev)
> > +{
> > + struct stm32_adc_common *common = platform_get_drvdata(pdev);
> > + struct stm32_adc_priv *priv = to_stm32_adc_priv(common);
> > +
> > + of_platform_depopulate(&pdev->dev);
> > + stm32_adc_irq_remove(pdev, priv);
> > + clk_disable_unprepare(priv->aclk);
> > + regulator_disable(priv->vref);
> > +
> > + return 0;
> > +}
> > +
> > +static const struct of_device_id stm32_adc_of_match[] = {
> > + { .compatible = "st,stm32f4-adc-core" },
> > +};
> > +MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
> > +
> > +static struct platform_driver stm32_adc_driver = {
> > + .probe = stm32_adc_probe,
> > + .remove = stm32_adc_remove,
> > + .driver = {
> > + .name = "stm32-adc-core",
> > + .of_match_table = stm32_adc_of_match,
> > + },
> > +};
> > +module_platform_driver(stm32_adc_driver);
> > +
> > +MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
> > +MODULE_DESCRIPTION("STMicroelectronics STM32 ADC MFD driver");
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_ALIAS("platform:stm32-adc-core");
> > diff --git a/include/linux/mfd/stm32-adc-core.h b/include/linux/mfd/stm32-adc-core.h
> > new file mode 100644
> > index 0000000..081fa5f
> > --- /dev/null
> > +++ b/include/linux/mfd/stm32-adc-core.h
> > @@ -0,0 +1,52 @@
> > +/*
> > + * This file is part of STM32 ADC driver
> > + *
> > + * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
> > + * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
> > + *
> > + * License type: GPLv2
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms of the GNU General Public License version 2 as published by
> > + * the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful, but
> > + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
> > + * or FITNESS FOR A PARTICULAR PURPOSE.
> > + * See the GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License along with
> > + * this program. If not, see <http://www.gnu.org/licenses/>.
> > + */
> > +
> > +#ifndef __STM32_ADC_H
> > +#define __STM32_ADC_H
> > +
> > +/*
> > + * STM32 - ADC global register map
> > + * ________________________________________________________
> > + * | Offset | Register |
> > + * --------------------------------------------------------
> > + * | 0x000 | Master ADC1 |
> > + * --------------------------------------------------------
> > + * | 0x100 | Slave ADC2 |
> > + * --------------------------------------------------------
> > + * | 0x200 | Slave ADC3 |
> > + * --------------------------------------------------------
> > + * | 0x300 | Master & Slave common regs |
> > + * --------------------------------------------------------
> > + */
> > +#define STM32_ADC_MAX_ADCS 3
> > +#define STM32_ADCX_COMN_OFFSET 0x300
> > +
> > +/**
> > + * struct stm32_adc_common - stm32 ADC driver common data (for all instances)
> > + * @base: control registers base cpu addr
> > + * @vref_mv: vref voltage (mv)
> > + */
> > +struct stm32_adc_common {
> > + void __iomem *base;
> > + int vref_mv;
> > +};
> > +
> > +#endif
> >
>
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
* Re: [RFC] [media] Add Synopsys Designware HDMI RX PHY e405 driver
From: Jose Abreu @ 2016-11-14 16:46 UTC (permalink / raw)
To: Hans Verkuil, Jose Abreu, linux-media
Cc: Carlos Palminha, Mauro Carvalho Chehab, linux-kernel
In-Reply-To: <7f819d27-0d85-ffe0-76cd-e8ffb5a7c680@xs4all.nl>
Hi Hans,
On 11-11-2016 14:52, Hans Verkuil wrote:
> Hi Jose,
>
> On 11/09/2016 06:43 PM, Jose Abreu wrote:
>> Hi All,
>>
>> This is a RFC patch for Synopsys Designware HDMI RX PHY e405.
>> This phy receives and decodes HDMI video that is delivered to
>> a controller. The controller bit is not yet ready for submission
>> but we are planning to submit it as soon as possible.
>>
>> Main included features in this driver are:
>> - Equalizer algorithm that chooses phy best settings
>> according to detected HDMI cable characteristics.
>> - Support for scrambling
>> - Support for HDMI 2.0 modes up to 6G (HDMI 4k@60Hz)
>>
>> The driver was implemented as a V4L2 subdevice and the phy
>> interface with the controller was implemented using V4L2 ioctls.
>> I do not know if this is the best option but it is not possible
>> to use the existing API functions directly as we need specific
>> functions that will be called by the controller at specific
>> configuration stages. For example, we can only set scrambling
>> when the sink detects the corresponding bit set in SCDC.
>>
>> Please notice that we plan to submit more phy drivers as they
>> are released, maintaining the newly created interface
>> (dw-phy-pdata.h) and using only one controller driver.
>>
>> I realize that this code needs a lot of polishment, specially
>> the equalizer part so I would really apreciate some feedback.
>>
>> Looking forward to your comments!
> I looked it over and I didn't see anything alarming :-)
>
> But it is hard to review without seeing the controller driver as well.
> When I can see how it is used by the controller driver then I can see
> if using ioctls here makes sense or not.
>
> Typically ioctls in subdevs are used for very device-specific actions.
> But perhaps what is happening here is required for all HDMI phys, and in
> that case new subdev ops could be added instead.
>
> Or we start with ioctls and later convert it to ops when it is clear that
> other phys need to do the same.
>
> Anyway, I think I'll have to wait until the controller is posted before I
> can do a proper review.
>
> Regards,
>
> Hans
Thanks for your answer! I am not sure about other controllers
phys but ours needs a special configuration when in HDMI 2.0
modes (like 4k@60Hz) and also a special bit set when in
scrambling mode so that the equalizing algorithm stabilizes
faster. Besides this it needs configuration parameters, that in
this case are passed by platform data.
I will then wait until I have the controller driver ready and
send a RFC with these two blocks.
Best regards,
Jose Miguel Abreu
>> Best regards,
>> Jose Miguel Abreu
>>
>> Signed-off-by: Jose Abreu <joabreu@synopsys.com>
>> Cc: Carlos Palminha <palminha@synopsys.com>
>> Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
>> Cc: linux-kernel@vger.kernel.org
>> Cc: linux-media@vger.kernel.org
>> ---
>> drivers/media/platform/Kconfig | 1 +
>> drivers/media/platform/Makefile | 2 +
>> drivers/media/platform/dw/Kconfig | 8 +
>> drivers/media/platform/dw/Makefile | 3 +
>> drivers/media/platform/dw/dw-phy-e405.c | 732 +++++++++++++++++++++++++++++++
>> drivers/media/platform/dw/dw-phy-e405.h | 48 ++
>> drivers/media/platform/dw/dw-phy-pdata.h | 47 ++
>> 7 files changed, 841 insertions(+)
>> create mode 100644 drivers/media/platform/dw/Kconfig
>> create mode 100644 drivers/media/platform/dw/Makefile
>> create mode 100644 drivers/media/platform/dw/dw-phy-e405.c
>> create mode 100644 drivers/media/platform/dw/dw-phy-e405.h
>> create mode 100644 drivers/media/platform/dw/dw-phy-pdata.h
>>
>> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
>> index 754edbf1..9e8e67f 100644
>> --- a/drivers/media/platform/Kconfig
>> +++ b/drivers/media/platform/Kconfig
>> @@ -120,6 +120,7 @@ source "drivers/media/platform/am437x/Kconfig"
>> source "drivers/media/platform/xilinx/Kconfig"
>> source "drivers/media/platform/rcar-vin/Kconfig"
>> source "drivers/media/platform/atmel/Kconfig"
>> +source "drivers/media/platform/dw/Kconfig"
>>
>> config VIDEO_TI_CAL
>> tristate "TI CAL (Camera Adaptation Layer) driver"
>> diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
>> index f842933..fb2cf01 100644
>> --- a/drivers/media/platform/Makefile
>> +++ b/drivers/media/platform/Makefile
>> @@ -68,3 +68,5 @@ obj-$(CONFIG_VIDEO_MEDIATEK_VPU) += mtk-vpu/
>> obj-$(CONFIG_VIDEO_MEDIATEK_VCODEC) += mtk-vcodec/
>>
>> obj-$(CONFIG_VIDEO_MEDIATEK_MDP) += mtk-mdp/
>> +
>> +obj-y += dw/
>> diff --git a/drivers/media/platform/dw/Kconfig b/drivers/media/platform/dw/Kconfig
>> new file mode 100644
>> index 0000000..b3d7044
>> --- /dev/null
>> +++ b/drivers/media/platform/dw/Kconfig
>> @@ -0,0 +1,8 @@
>> +config VIDEO_DW_PHY_E405
>> + tristate "Synopsys Designware HDMI RX PHY e405 driver"
>> + depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
>> + help
>> + Support for Synopsys Designware HDMI RX PHY. Version is e405.
>> +
>> + To compile this driver as a module, choose M here. The module
>> + will be called dw-phy-e405.
>> diff --git a/drivers/media/platform/dw/Makefile b/drivers/media/platform/dw/Makefile
>> new file mode 100644
>> index 0000000..decc494
>> --- /dev/null
>> +++ b/drivers/media/platform/dw/Makefile
>> @@ -0,0 +1,3 @@
>> +# Makefile for Synopsys Designware HDMI RX
>> +
>> +obj-$(CONFIG_VIDEO_DW_PHY_E405) += dw-phy-e405.o
>> diff --git a/drivers/media/platform/dw/dw-phy-e405.c b/drivers/media/platform/dw/dw-phy-e405.c
>> new file mode 100644
>> index 0000000..e9c9cdf
>> --- /dev/null
>> +++ b/drivers/media/platform/dw/dw-phy-e405.c
>> @@ -0,0 +1,732 @@
>> +/*
>> + * Synopsys Designware HDMI RX PHY e405 driver
>> + *
>> + * Copyright (C) 2016 Synopsys, Inc.
>> + * Jose Abreu <joabreu@synopsys.com>
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/types.h>
>> +#include <media/v4l2-subdev.h>
>> +#include "dw-phy-e405.h"
>> +#include "dw-phy-pdata.h"
>> +
>> +MODULE_AUTHOR("Jose Abreu <joabreu@synopsys.com>");
>> +MODULE_DESCRIPTION("Designware HDMI RX PHY e405 driver");
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("platform:dw-phy-e405");
>> +
>> +#define PHY_EQ_WAIT_TIME_START 3
>> +#define PHY_EQ_SLEEP_TIME_CDR 30
>> +#define PHY_EQ_SLEEP_TIME_ACQ 1
>> +#define PHY_EQ_BOUNDSPREAD 20
>> +#define PHY_EQ_MIN_ACQ_STABLE 3
>> +#define PHY_EQ_ACC_LIMIT 360
>> +#define PHY_EQ_ACC_MIN_LIMIT 0
>> +#define PHY_EQ_MAX_SETTING 13
>> +#define PHY_EQ_SHORT_CABLE_SETTING 4
>> +#define PHY_EQ_ERROR_CABLE_SETTING 4
>> +#define PHY_EQ_MIN_SLOPE 50
>> +#define PHY_EQ_AVG_ACQ 5
>> +#define PHY_EQ_MINMAX_NTRIES 3
>> +#define PHY_EQ_EQUALIZED_COUNTER_VAL 512
>> +#define PHY_EQ_EQUALIZED_COUNTER_VAL_HDMI20 512
>> +#define PHY_EQ_MINMAX_MAXDIFF 4
>> +#define PHY_EQ_MINMAX_MAXDIFF_HDMI20 2
>> +#define PHY_EQ_FATBIT_MASK 0x0000
>> +#define PHY_EQ_FATBIT_MASK_4K 0x0c03
>> +#define PHY_EQ_FATBIT_MASK_HDMI20 0x0e03
>> +
>> +struct dw_phy_eq_ch {
>> + u16 best_long_setting;
>> + u8 valid_long_setting;
>> + u16 best_short_setting;
>> + u8 valid_short_setting;
>> + u16 best_setting;
>> + u16 acc;
>> + u16 acq;
>> + u16 last_acq;
>> + u16 upper_bound_acq;
>> + u16 lower_bound_acq;
>> + u16 out_bound_acq;
>> + u16 read_acq;
>> +};
>> +
>> +static const struct dw_phy_mpll_config {
>> + u16 addr;
>> + u16 val;
>> +} dw_phy_e405_mpll_cfg[] = {
>> + { 0x27, 0x1B94 },
>> + { 0x28, 0x16D2 },
>> + { 0x29, 0x12D9 },
>> + { 0x2A, 0x3249 },
>> + { 0x2B, 0x3653 },
>> + { 0x2C, 0x3436 },
>> + { 0x2D, 0x124D },
>> + { 0x2E, 0x0001 },
>> + { 0xCE, 0x0505 },
>> + { 0xCF, 0x0505 },
>> + { 0xD0, 0x0000 },
>> + { 0x00, 0x0000 },
>> +};
>> +
>> +struct dw_phy_dev {
>> + struct device *dev;
>> + struct dw_phy_pdata *config;
>> + bool phy_enabled;
>> + struct v4l2_subdev sd;
>> +};
>> +
>> +static inline struct dw_phy_dev *to_dw_dev(struct v4l2_subdev *sd)
>> +{
>> + return container_of(sd, struct dw_phy_dev, sd);
>> +}
>> +
>> +static void phy_write(struct dw_phy_dev *dw_dev, u16 val, u16 addr)
>> +{
>> + void *arg = dw_dev->config->funcs_arg;
>> +
>> + dw_dev->config->funcs->write(arg, val, addr);
>> +}
>> +
>> +static u16 phy_read(struct dw_phy_dev *dw_dev, u16 addr)
>> +{
>> + void *arg = dw_dev->config->funcs_arg;
>> +
>> + return dw_dev->config->funcs->read(arg, addr);
>> +}
>> +
>> +static void phy_reset(struct dw_phy_dev *dw_dev, int enable)
>> +{
>> + void *arg = dw_dev->config->funcs_arg;
>> +
>> + dw_dev->config->funcs->reset(arg, enable);
>> +}
>> +
>> +static void phy_pddq(struct dw_phy_dev *dw_dev, int enable)
>> +{
>> + void *arg = dw_dev->config->funcs_arg;
>> +
>> + dw_dev->config->funcs->pddq(arg, enable);
>> +}
>> +
>> +static void phy_svsmode(struct dw_phy_dev *dw_dev, int enable)
>> +{
>> + void *arg = dw_dev->config->funcs_arg;
>> +
>> + dw_dev->config->funcs->svsmode(arg, enable);
>> +}
>> +
>> +static void phy_zcal_reset(struct dw_phy_dev *dw_dev)
>> +{
>> + void *arg = dw_dev->config->funcs_arg;
>> +
>> + dw_dev->config->funcs->zcal_reset(arg);
>> +}
>> +
>> +static bool phy_zcal_done(struct dw_phy_dev *dw_dev)
>> +{
>> + void *arg = dw_dev->config->funcs_arg;
>> +
>> + return dw_dev->config->funcs->zcal_done(arg);
>> +}
>> +
>> +static bool phy_tmds_valid(struct dw_phy_dev *dw_dev)
>> +{
>> + void *arg = dw_dev->config->funcs_arg;
>> +
>> + return dw_dev->config->funcs->tmds_valid(arg);
>> +}
>> +
>> +static int dw_phy_eq_test(struct dw_phy_dev *dw_dev,
>> + u16 *fat_bit_mask, int *min_max_length)
>> +{
>> + u16 main_fsm_status, val;
>> + int i;
>> +
>> + for (i = 0; i < PHY_EQ_WAIT_TIME_START; i++) {
>> + main_fsm_status = phy_read(dw_dev, PHY_MAINFSM_STATUS1);
>> + if (main_fsm_status & 0x100)
>> + break;
>> + msleep(PHY_EQ_SLEEP_TIME_CDR);
>> + }
>> +
>> + if (i == PHY_EQ_WAIT_TIME_START) {
>> + dev_err(dw_dev->dev, "phy start conditions not achieved\n");
>> + return -ETIMEDOUT;
>> + }
>> +
>> + if (main_fsm_status & 0x400) {
>> + dev_err(dw_dev->dev, "invalid pll rate\n");
>> + return -EINVAL;
>> + }
>> +
>> + val = (phy_read(dw_dev, PHY_CDR_CTRL_CNT) & 0x300) >> 8;
>> + if (val == 0x1) {
>> + /* HDMI 2.0 */
>> + *fat_bit_mask = PHY_EQ_FATBIT_MASK_HDMI20;
>> + *min_max_length = PHY_EQ_MINMAX_MAXDIFF_HDMI20;
>> + dev_dbg(dw_dev->dev, "[EQUALIZER] using HDMI 2.0 values\n");
>> + } else if (!(main_fsm_status & 0x600)) {
>> + /* HDMI 1.4 (pll rate = 0) */
>> + *fat_bit_mask = PHY_EQ_FATBIT_MASK_4K;
>> + *min_max_length = PHY_EQ_MINMAX_MAXDIFF;
>> + dev_dbg(dw_dev->dev, "[EQUALIZER] using HDMI 1.4@4k values\n");
>> + } else {
>> + /* HDMI 1.4 */
>> + *fat_bit_mask = PHY_EQ_FATBIT_MASK;
>> + *min_max_length = PHY_EQ_MINMAX_MAXDIFF;
>> + dev_dbg(dw_dev->dev, "[EQUALIZER] using HDMI 1.4 values\n");
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static void dw_phy_eq_default(struct dw_phy_dev *dw_dev)
>> +{
>> + phy_write(dw_dev, 0x08A8, PHY_CH0_EQ_CTRL1);
>> + phy_write(dw_dev, 0x0020, PHY_CH0_EQ_CTRL2);
>> + phy_write(dw_dev, 0x08A8, PHY_CH1_EQ_CTRL1);
>> + phy_write(dw_dev, 0x0020, PHY_CH1_EQ_CTRL2);
>> + phy_write(dw_dev, 0x08A8, PHY_CH2_EQ_CTRL1);
>> + phy_write(dw_dev, 0x0020, PHY_CH2_EQ_CTRL2);
>> +}
>> +
>> +static void dw_phy_eq_single(struct dw_phy_dev *dw_dev)
>> +{
>> + phy_write(dw_dev, 0x0211, PHY_CH0_EQ_CTRL1);
>> + phy_write(dw_dev, 0x0211, PHY_CH1_EQ_CTRL1);
>> + phy_write(dw_dev, 0x0211, PHY_CH2_EQ_CTRL1);
>> +}
>> +
>> +static void dw_phy_eq_equal_setting(struct dw_phy_dev *dw_dev,
>> + u16 lock_vector)
>> +{
>> + phy_write(dw_dev, lock_vector, PHY_CH0_EQ_CTRL4);
>> + phy_write(dw_dev, 0x0024, PHY_CH0_EQ_CTRL2);
>> + phy_write(dw_dev, 0x0026, PHY_CH0_EQ_CTRL2);
>> + phy_read(dw_dev, PHY_CH0_EQ_STATUS2);
>> + phy_write(dw_dev, lock_vector, PHY_CH1_EQ_CTRL4);
>> + phy_write(dw_dev, 0x0024, PHY_CH1_EQ_CTRL2);
>> + phy_write(dw_dev, 0x0026, PHY_CH1_EQ_CTRL2);
>> + phy_read(dw_dev, PHY_CH1_EQ_STATUS2);
>> + phy_write(dw_dev, lock_vector, PHY_CH2_EQ_CTRL4);
>> + phy_write(dw_dev, 0x0024, PHY_CH2_EQ_CTRL2);
>> + phy_write(dw_dev, 0x0026, PHY_CH2_EQ_CTRL2);
>> + phy_read(dw_dev, PHY_CH2_EQ_STATUS2);
>> +}
>> +
>> +static void dw_phy_eq_equal_setting_ch0(struct dw_phy_dev *dw_dev,
>> + u16 lock_vector)
>> +{
>> + phy_write(dw_dev, lock_vector, PHY_CH0_EQ_CTRL4);
>> + phy_write(dw_dev, 0x0024, PHY_CH0_EQ_CTRL2);
>> + phy_write(dw_dev, 0x0026, PHY_CH0_EQ_CTRL2);
>> + phy_read(dw_dev, PHY_CH0_EQ_STATUS2);
>> +}
>> +
>> +static void dw_phy_eq_equal_setting_ch1(struct dw_phy_dev *dw_dev,
>> + u16 lock_vector)
>> +{
>> + phy_write(dw_dev, lock_vector, PHY_CH1_EQ_CTRL4);
>> + phy_write(dw_dev, 0x0024, PHY_CH1_EQ_CTRL2);
>> + phy_write(dw_dev, 0x0026, PHY_CH1_EQ_CTRL2);
>> + phy_read(dw_dev, PHY_CH1_EQ_STATUS2);
>> +}
>> +
>> +static void dw_phy_eq_equal_setting_ch2(struct dw_phy_dev *dw_dev,
>> + u16 lock_vector)
>> +{
>> + phy_write(dw_dev, lock_vector, PHY_CH2_EQ_CTRL4);
>> + phy_write(dw_dev, 0x0024, PHY_CH2_EQ_CTRL2);
>> + phy_write(dw_dev, 0x0026, PHY_CH2_EQ_CTRL2);
>> + phy_read(dw_dev, PHY_CH2_EQ_STATUS2);
>> +}
>> +
>> +static void dw_phy_eq_auto_calib(struct dw_phy_dev *dw_dev)
>> +{
>> + phy_write(dw_dev, 0x1809, PHY_MAINFSM_CTRL);
>> + phy_write(dw_dev, 0x1819, PHY_MAINFSM_CTRL);
>> + phy_write(dw_dev, 0x1809, PHY_MAINFSM_CTRL);
>> +}
>> +
>> +static void dw_phy_eq_init_vars(struct dw_phy_eq_ch *ch)
>> +{
>> + ch->acc = 0;
>> + ch->acq = 0;
>> + ch->last_acq = 0;
>> + ch->valid_long_setting = 0;
>> + ch->valid_short_setting = 0;
>> + ch->best_setting = PHY_EQ_SHORT_CABLE_SETTING;
>> +}
>> +
>> +static void dw_phy_eq_acquire_early_cnt(struct dw_phy_dev *dw_dev,
>> + u16 setting, u16 acq, struct dw_phy_eq_ch *ch0,
>> + struct dw_phy_eq_ch *ch1, struct dw_phy_eq_ch *ch2)
>> +{
>> + u16 lock_vector = 0x1;
>> + int i;
>> +
>> + lock_vector <<= setting;
>> + ch0->out_bound_acq = 0;
>> + ch1->out_bound_acq = 0;
>> + ch2->out_bound_acq = 0;
>> + ch0->acq = 0;
>> + ch1->acq = 0;
>> + ch2->acq = 0;
>> +
>> + dw_phy_eq_equal_setting(dw_dev, lock_vector);
>> + dw_phy_eq_auto_calib(dw_dev);
>> +
>> + msleep(PHY_EQ_SLEEP_TIME_CDR);
>> + if (!phy_tmds_valid(dw_dev))
>> + dev_dbg(dw_dev->dev, "TMDS is NOT valid\n");
>> +
>> + ch0->read_acq = phy_read(dw_dev, PHY_CH0_EQ_STATUS3);
>> + ch1->read_acq = phy_read(dw_dev, PHY_CH1_EQ_STATUS3);
>> + ch2->read_acq = phy_read(dw_dev, PHY_CH2_EQ_STATUS3);
>> +
>> + ch0->acq += ch0->read_acq;
>> + ch1->acq += ch1->read_acq;
>> + ch2->acq += ch2->read_acq;
>> +
>> + ch0->upper_bound_acq = ch0->read_acq + PHY_EQ_BOUNDSPREAD;
>> + ch0->lower_bound_acq = ch0->read_acq - PHY_EQ_BOUNDSPREAD;
>> + ch1->upper_bound_acq = ch1->read_acq + PHY_EQ_BOUNDSPREAD;
>> + ch1->lower_bound_acq = ch1->read_acq - PHY_EQ_BOUNDSPREAD;
>> + ch2->upper_bound_acq = ch2->read_acq + PHY_EQ_BOUNDSPREAD;
>> + ch2->lower_bound_acq = ch2->read_acq - PHY_EQ_BOUNDSPREAD;
>> +
>> + for (i = 1; i < acq; i++) {
>> + dw_phy_eq_auto_calib(dw_dev);
>> + mdelay(PHY_EQ_SLEEP_TIME_ACQ);
>> +
>> + if ((ch0->read_acq > ch0->upper_bound_acq) ||
>> + (ch0->read_acq < ch0->lower_bound_acq))
>> + ch0->out_bound_acq++;
>> + if ((ch1->read_acq > ch1->upper_bound_acq) ||
>> + (ch1->read_acq < ch1->lower_bound_acq))
>> + ch1->out_bound_acq++;
>> + if ((ch2->read_acq > ch2->upper_bound_acq) ||
>> + (ch2->read_acq < ch1->lower_bound_acq))
>> + ch2->out_bound_acq++;
>> +
>> + if (i == PHY_EQ_MIN_ACQ_STABLE) {
>> + if ((ch0->out_bound_acq == 0) &&
>> + (ch1->out_bound_acq == 0) &&
>> + (ch2->out_bound_acq == 0)) {
>> + acq = 3;
>> + break;
>> + }
>> + }
>> +
>> + ch0->read_acq = phy_read(dw_dev, PHY_CH0_EQ_STATUS3);
>> + ch1->read_acq = phy_read(dw_dev, PHY_CH1_EQ_STATUS3);
>> + ch2->read_acq = phy_read(dw_dev, PHY_CH2_EQ_STATUS3);
>> +
>> + ch0->acq += ch0->read_acq;
>> + ch1->acq += ch1->read_acq;
>> + ch2->acq += ch2->read_acq;
>> + }
>> +
>> + ch0->acq = ch0->acq / acq;
>> + ch1->acq = ch1->acq / acq;
>> + ch2->acq = ch2->acq / acq;
>> +
>> + dev_dbg(dw_dev->dev, "setting=%d: ch0.acq=%d, ch1.acq=%d, ch2.acq=%d\n",
>> + setting, ch0->acq, ch1->acq, ch2->acq);
>> +}
>> +
>> +static int dw_phy_eq_test_type(u16 setting, struct dw_phy_eq_ch *ch)
>> +{
>> + u16 step_slope = 0;
>> +
>> + if (ch->acq < ch->last_acq) {
>> + /* Long cable equalization */
>> + ch->acc += ch->last_acq - ch->acq;
>> + if ((!ch->valid_long_setting) && (ch->acq < 512) &&
>> + (ch->acc > 0)) {
>> + ch->best_long_setting = setting;
>> + ch->valid_long_setting = 1;
>> + }
>> +
>> + step_slope = ch->last_acq - ch->acq;
>> + }
>> +
>> + if (!ch->valid_short_setting) {
>> + /* Short cable equalization */
>> + if ((setting < PHY_EQ_SHORT_CABLE_SETTING) &&
>> + (ch->acq < PHY_EQ_EQUALIZED_COUNTER_VAL)) {
>> + ch->best_short_setting = setting;
>> + ch->valid_short_setting = 1;
>> + }
>> +
>> + if (setting == PHY_EQ_SHORT_CABLE_SETTING) {
>> + ch->best_short_setting = PHY_EQ_SHORT_CABLE_SETTING;
>> + ch->valid_short_setting = 1;
>> + }
>> + }
>> +
>> + if (ch->valid_long_setting && (ch->acc > PHY_EQ_ACC_LIMIT)) {
>> + ch->best_setting = ch->best_long_setting;
>> + return 1;
>> + }
>> +
>> + if ((setting == PHY_EQ_MAX_SETTING) && (ch->acc < PHY_EQ_ACC_LIMIT) &&
>> + ch->valid_short_setting) {
>> + ch->best_setting = ch->best_short_setting;
>> + return 2;
>> + }
>> +
>> + if ((setting == PHY_EQ_MAX_SETTING) && (ch->acc > PHY_EQ_ACC_LIMIT) &&
>> + (step_slope > PHY_EQ_MIN_SLOPE)) {
>> + ch->best_setting = PHY_EQ_MAX_SETTING;
>> + return 3;
>> + }
>> +
>> + if (setting == PHY_EQ_MAX_SETTING) {
>> + ch->best_setting = PHY_EQ_ERROR_CABLE_SETTING;
>> + return -EINVAL;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static bool dw_phy_eq_setting_finder(struct dw_phy_dev *dw_dev, u16 acq,
>> + struct dw_phy_eq_ch *ch0, struct dw_phy_eq_ch *ch1,
>> + struct dw_phy_eq_ch *ch2)
>> +{
>> + u16 act = 0;
>> + int ret_ch0 = 0, ret_ch1 = 0, ret_ch2 = 0;
>> +
>> + dw_phy_eq_init_vars(ch0);
>> + dw_phy_eq_init_vars(ch1);
>> + dw_phy_eq_init_vars(ch2);
>> +
>> + dw_phy_eq_acquire_early_cnt(dw_dev, act, acq, ch0, ch1, ch2);
>> +
>> + while ((!ret_ch0) || (!ret_ch1) || (!ret_ch2)) {
>> + act++;
>> +
>> + ch0->last_acq = ch0->acq;
>> + ch1->last_acq = ch1->acq;
>> + ch2->last_acq = ch2->acq;
>> +
>> + dw_phy_eq_acquire_early_cnt(dw_dev, act, acq, ch0, ch1, ch2);
>> +
>> + if (!ret_ch0)
>> + ret_ch0 = dw_phy_eq_test_type(act, ch0);
>> + if (!ret_ch1)
>> + ret_ch1 = dw_phy_eq_test_type(act, ch1);
>> + if (!ret_ch2)
>> + ret_ch2 = dw_phy_eq_test_type(act, ch2);
>> + }
>> +
>> + if ((ret_ch0 < 0) || (ret_ch1 < 0) || (ret_ch2 < 0))
>> + return false;
>> + return true;
>> +}
>> +
>> +static bool dw_phy_eq_maxvsmin(u16 ch0_setting, u16 ch1_setting,
>> + u16 ch2_setting, u16 min_max_length)
>> +{
>> + u16 min = ch0_setting, max = ch0_setting;
>> +
>> + if (ch1_setting > max)
>> + max = ch1_setting;
>> + if (ch2_setting > max)
>> + max = ch2_setting;
>> + if (ch1_setting < min)
>> + min = ch1_setting;
>> + if (ch2_setting < min)
>> + min = ch2_setting;
>> +
>> + if ((max - min) > min_max_length)
>> + return false;
>> + return true;
>> +}
>> +
>> +static int dw_phy_eq_init(struct dw_phy_dev *dw_dev, u16 acq)
>> +{
>> + struct dw_phy_pdata *phy = dw_dev->config;
>> + struct dw_phy_eq_ch ch0, ch1, ch2;
>> + u16 fat_bit_mask, lock_vector = 0x1;
>> + int min_max_length, i, ret = 0;
>> +
>> + if (phy->version < 401)
>> + return 0;
>> +
>> + phy_write(dw_dev, 0x00, PHY_MAINFSM_OVR2);
>> + phy_write(dw_dev, 0x00, PHY_CH0_EQ_CTRL3);
>> + phy_write(dw_dev, 0x00, PHY_CH1_EQ_CTRL3);
>> + phy_write(dw_dev, 0x00, PHY_CH2_EQ_CTRL3);
>> +
>> + ret = dw_phy_eq_test(dw_dev, &fat_bit_mask, &min_max_length);
>> + if (ret) {
>> + if (ret == -EINVAL) /* Means equalizer is not needed */
>> + return 0;
>> + dw_phy_eq_default(dw_dev);
>> + phy_pddq(dw_dev, 1);
>> + phy_pddq(dw_dev, 0);
>> + return ret;
>> + }
>> +
>> + dw_phy_eq_single(dw_dev);
>> + dw_phy_eq_equal_setting(dw_dev, 0x0001);
>> + phy_write(dw_dev, fat_bit_mask, PHY_CH0_EQ_CTRL6);
>> + phy_write(dw_dev, fat_bit_mask, PHY_CH0_EQ_CTRL6);
>> + phy_write(dw_dev, fat_bit_mask, PHY_CH0_EQ_CTRL6);
>> +
>> + for (i = 0; i < PHY_EQ_MINMAX_NTRIES; i++) {
>> + if (dw_phy_eq_setting_finder(dw_dev, acq, &ch0, &ch1, &ch2)) {
>> + if (dw_phy_eq_maxvsmin(ch0.best_setting,
>> + ch1.best_setting,
>> + ch2.best_setting,
>> + min_max_length))
>> + break;
>> + }
>> +
>> + ch0.best_setting = PHY_EQ_ERROR_CABLE_SETTING;
>> + ch1.best_setting = PHY_EQ_ERROR_CABLE_SETTING;
>> + ch2.best_setting = PHY_EQ_ERROR_CABLE_SETTING;
>> + }
>> +
>> + dev_dbg(dw_dev->dev, "settings:ch0=0x%x, ch1=0x%x, ch1=0x%x\n",
>> + ch0.best_setting, ch1.best_setting, ch2.best_setting);
>> +
>> + if (i == PHY_EQ_MINMAX_NTRIES)
>> + ret = -EINVAL;
>> +
>> + lock_vector = 0x1;
>> + lock_vector <<= ch0.best_setting;
>> + dw_phy_eq_equal_setting_ch0(dw_dev, lock_vector);
>> +
>> + lock_vector = 0x1;
>> + lock_vector <<= ch1.best_setting;
>> + dw_phy_eq_equal_setting_ch1(dw_dev, lock_vector);
>> +
>> + lock_vector = 0x1;
>> + lock_vector <<= ch2.best_setting;
>> + dw_phy_eq_equal_setting_ch2(dw_dev, lock_vector);
>> +
>> + phy_pddq(dw_dev, 1);
>> + phy_pddq(dw_dev, 0);
>> +
>> + return ret;
>> +}
>> +
>> +static void dw_phy_set_hdmi2(struct dw_phy_dev *dw_dev, bool on)
>> +{
>> + u16 val;
>> +
>> + /* Set phy in configuration mode */
>> + phy_pddq(dw_dev, 1);
>> +
>> + /* Operation for data rates between 3.4Gbps and 6Gbps */
>> + val = phy_read(dw_dev, PHY_CDR_CTRL_CNT);
>> + if (on)
>> + val |= BIT(8);
>> + else
>> + val &= ~BIT(8);
>> + phy_write(dw_dev, val, PHY_CDR_CTRL_CNT);
>> +
>> + /* Enable phy */
>> + phy_pddq(dw_dev, 0);
>> +}
>> +
>> +static void dw_phy_set_scrambling(struct dw_phy_dev *dw_dev, bool on)
>> +{
>> + u16 val;
>> +
>> + val = phy_read(dw_dev, PHY_OVL_PROT_CTRL);
>> + if (on)
>> + val |= GENMASK(7, 6);
>> + else
>> + val &= ~GENMASK(7, 6);
>> + phy_write(dw_dev, val, PHY_OVL_PROT_CTRL);
>> +}
>> +
>> +static int dw_phy_config(struct dw_phy_dev *dw_dev, unsigned char res,
>> + bool data_rate_6g)
>> +{
>> + struct device *dev = dw_dev->dev;
>> + struct dw_phy_pdata *phy = dw_dev->config;
>> + const struct dw_phy_mpll_config *mpll_cfg = dw_phy_e405_mpll_cfg;
>> + bool zcal_done;
>> + u16 val, res_idx;
>> + int timeout = 100;
>> +
>> + dev_dbg(dev, "configuring phy: res=%d, hdmi2=%d\n", res, data_rate_6g);
>> +
>> + switch (res) {
>> + case 8:
>> + res_idx = 0x0;
>> + break;
>> + case 10:
>> + res_idx = 0x1;
>> + break;
>> + case 12:
>> + res_idx = 0x2;
>> + break;
>> + case 16:
>> + res_idx = 0x3;
>> + break;
>> + default:
>> + return -EINVAL;
>> + }
>> +
>> + phy_reset(dw_dev, 1);
>> + phy_pddq(dw_dev, 1);
>> + phy_svsmode(dw_dev, 1);
>> +
>> + phy_zcal_reset(dw_dev);
>> + do {
>> + udelay(1000);
>> + zcal_done = phy_zcal_done(dw_dev);
>> + } while (!zcal_done && timeout--);
>> +
>> + if (!zcal_done) {
>> + dev_err(dw_dev->dev, "Zcal calibration failed\n");
>> + return -ETIMEDOUT;
>> + }
>> +
>> + phy_reset(dw_dev, 0);
>> +
>> + /* CMU */
>> + val = (0x08 << 10) | (0x01 << 9);
>> + val |= (phy->cfg_clk * 4) & GENMASK(8, 0);
>> + phy_write(dw_dev, val, PHY_CMU_CONFIG);
>> +
>> + /* Color Depth and enable fast switching */
>> + val = phy_read(dw_dev, PHY_SYSTEM_CONFIG);
>> + val = (val & ~0x60) | (res_idx << 5) | BIT(11);
>> + phy_write(dw_dev, val, PHY_SYSTEM_CONFIG);
>> +
>> + /* MPLL */
>> + for (; mpll_cfg->addr != 0x0; mpll_cfg++)
>> + phy_write(dw_dev, mpll_cfg->val, mpll_cfg->addr);
>> +
>> + /* Operation for data rates between 3.4Gbps and 6Gbps */
>> + val = phy_read(dw_dev, PHY_CDR_CTRL_CNT);
>> + if (data_rate_6g)
>> + val |= BIT(8);
>> + else
>> + val &= ~BIT(8);
>> + phy_write(dw_dev, val, PHY_CDR_CTRL_CNT);
>> +
>> + /* Enable phy */
>> + phy_pddq(dw_dev, 0);
>> +
>> + dw_dev->phy_enabled = true;
>> + return 0;
>> +}
>> +
>> +static void dw_phy_disable(struct dw_phy_dev *dw_dev)
>> +{
>> + if (!dw_dev->phy_enabled)
>> + return;
>> +
>> + phy_reset(dw_dev, 1);
>> + phy_pddq(dw_dev, 1);
>> + dw_dev->phy_enabled = false;
>> +}
>> +
>> +static long dw_phy_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
>> +{
>> + struct dw_phy_dev *dw_dev = to_dw_dev(sd);
>> + struct dw_phy_command *a = arg;
>> +
>> + dev_dbg(dw_dev->dev, "%s: cmd=%d\n", __func__, cmd);
>> +
>> + switch (cmd) {
>> + case DW_PHY_IOCTL_EQ_INIT:
>> + a->result = dw_phy_eq_init(dw_dev, a->nacq);
>> + break;
>> + case DW_PHY_IOCTL_SET_HDMI2:
>> + dw_phy_set_hdmi2(dw_dev, a->hdmi2);
>> + a->result = 0;
>> + break;
>> + case DW_PHY_IOCTL_SET_SCRAMBLING:
>> + dw_phy_set_scrambling(dw_dev, a->scrambling);
>> + a->result = 0;
>> + break;
>> + case DW_PHY_IOCTL_CONFIG:
>> + a->result = dw_phy_config(dw_dev, a->res, a->hdmi2);
>> + dw_phy_set_scrambling(dw_dev, a->scrambling);
>> + break;
>> + default:
>> + return -ENOIOCTLCMD;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static int dw_phy_s_power(struct v4l2_subdev *sd, int on)
>> +{
>> + struct dw_phy_dev *dw_dev = to_dw_dev(sd);
>> +
>> + dev_dbg(dw_dev->dev, "%s: on=%d\n", __func__, on);
>> +
>> + if (!on)
>> + dw_phy_disable(dw_dev);
>> + return 0;
>> +}
>> +
>> +static const struct v4l2_subdev_core_ops dw_phy_core_ops = {
>> + .ioctl = dw_phy_ioctl,
>> + .s_power = dw_phy_s_power,
>> +};
>> +
>> +static const struct v4l2_subdev_ops dw_phy_sd_ops = {
>> + .core = &dw_phy_core_ops,
>> +};
>> +
>> +static int dw_phy_probe(struct platform_device *pdev)
>> +{
>> + struct device *dev = &pdev->dev;
>> + struct dw_phy_dev *dw_dev;
>> + struct dw_phy_pdata *pdata = pdev->dev.platform_data;
>> + struct v4l2_subdev *sd;
>> +
>> + /* Resource allocation */
>> + dw_dev = devm_kzalloc(dev, sizeof(*dw_dev), GFP_KERNEL);
>> + if (!dw_dev)
>> + return -ENOMEM;
>> +
>> + /* Resource initialization */
>> + if (!pdata)
>> + return -EINVAL;
>> +
>> + dw_dev->dev = dev;
>> + dw_dev->config = pdata;
>> +
>> + /* V4L2 initialization */
>> + sd = &dw_dev->sd;
>> + v4l2_subdev_init(sd, &dw_phy_sd_ops);
>> + strlcpy(sd->name, dev_name(dev), sizeof(sd->name));
>> +
>> + /* All done */
>> + dev_set_drvdata(dev, sd);
>> + return 0;
>> +}
>> +
>> +static int dw_phy_remove(struct platform_device *pdev)
>> +{
>> + return 0;
>> +}
>> +
>> +static struct platform_driver dw_phy_e405_driver = {
>> + .probe = dw_phy_probe,
>> + .remove = dw_phy_remove,
>> + .driver = {
>> + .name = "dw-phy-e405",
>> + }
>> +};
>> +module_platform_driver(dw_phy_e405_driver);
>> +
>> diff --git a/drivers/media/platform/dw/dw-phy-e405.h b/drivers/media/platform/dw/dw-phy-e405.h
>> new file mode 100644
>> index 0000000..a2a9057
>> --- /dev/null
>> +++ b/drivers/media/platform/dw/dw-phy-e405.h
>> @@ -0,0 +1,48 @@
>> +/*
>> + * Synopsys Designware HDMI RX PHY e405 driver
>> + *
>> + * Copyright (C) 2016 Synopsys, Inc.
>> + * Jose Abreu <joabreu@synopsys.com>
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +
>> +#ifndef __DW_PHY_E405_H__
>> +#define __DW_PHY_E405_H__
>> +
>> +#define PHY_CMU_CONFIG 0x02
>> +#define PHY_SYSTEM_CONFIG 0x03
>> +#define PHY_MAINFSM_CTRL 0x05
>> +#define PHY_MAINFSM_OVR2 0x08
>> +#define PHY_MAINFSM_STATUS1 0x09
>> +#define PHY_OVL_PROT_CTRL 0x0D
>> +#define PHY_CDR_CTRL_CNT 0x0E
>> +#define PHY_CH0_EQ_CTRL1 0x32
>> +#define PHY_CH0_EQ_CTRL2 0x33
>> +#define PHY_CH0_EQ_STATUS 0x34
>> +#define PHY_CH0_EQ_CTRL3 0x3E
>> +#define PHY_CH0_EQ_CTRL4 0x3F
>> +#define PHY_CH0_EQ_STATUS2 0x40
>> +#define PHY_CH0_EQ_STATUS3 0x42
>> +#define PHY_CH0_EQ_CTRL6 0x43
>> +#define PHY_CH1_EQ_CTRL1 0x52
>> +#define PHY_CH1_EQ_CTRL2 0x53
>> +#define PHY_CH1_EQ_STATUS 0x54
>> +#define PHY_CH1_EQ_CTRL3 0x5E
>> +#define PHY_CH1_EQ_CTRL4 0x5F
>> +#define PHY_CH1_EQ_STATUS2 0x60
>> +#define PHY_CH1_EQ_STATUS3 0x62
>> +#define PHY_CH1_EQ_CTRL6 0x63
>> +#define PHY_CH2_EQ_CTRL1 0x72
>> +#define PHY_CH2_EQ_CTRL2 0x73
>> +#define PHY_CH2_EQ_STATUS 0x74
>> +#define PHY_CH2_EQ_CTRL3 0x7E
>> +#define PHY_CH2_EQ_CTRL4 0x7F
>> +#define PHY_CH2_EQ_STATUS2 0x80
>> +#define PHY_CH2_EQ_STATUS3 0x82
>> +#define PHY_CH2_EQ_CTRL6 0x83
>> +
>> +#endif /* __DW_PHY_E405_H__ */
>> +
>> diff --git a/drivers/media/platform/dw/dw-phy-pdata.h b/drivers/media/platform/dw/dw-phy-pdata.h
>> new file mode 100644
>> index 0000000..b728a50
>> --- /dev/null
>> +++ b/drivers/media/platform/dw/dw-phy-pdata.h
>> @@ -0,0 +1,47 @@
>> +/*
>> + * Synopsys Designware HDMI RX PHY generic interface
>> + *
>> + * Copyright (C) 2016 Synopsys, Inc.
>> + * Jose Abreu <joabreu@synopsys.com>
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +
>> +#ifndef __DW_PHY_PDATA_H__
>> +#define __DW_PHY_PDATA_H__
>> +
>> +#define DW_PHY_IOCTL_EQ_INIT _IOW('R', 1, int)
>> +#define DW_PHY_IOCTL_SET_HDMI2 _IOW('R', 2, int)
>> +#define DW_PHY_IOCTL_SET_SCRAMBLING _IOW('R', 3, int)
>> +#define DW_PHY_IOCTL_CONFIG _IOW('R', 4, int)
>> +
>> +struct dw_phy_command {
>> + int result;
>> + unsigned char res;
>> + bool hdmi2;
>> + bool nacq;
>> + bool scrambling;
>> +};
>> +
>> +struct dw_phy_funcs {
>> + void (*write)(void *arg, u16 val, u16 addr);
>> + u16 (*read)(void *arg, u16 addr);
>> + void (*reset)(void *arg, int enable);
>> + void (*pddq)(void *arg, int enable);
>> + void (*svsmode)(void *arg, int enable);
>> + void (*zcal_reset)(void *arg);
>> + bool (*zcal_done)(void *arg);
>> + bool (*tmds_valid)(void *arg);
>> +};
>> +
>> +struct dw_phy_pdata {
>> + unsigned int version;
>> + unsigned int cfg_clk;
>> + const struct dw_phy_funcs *funcs;
>> + void *funcs_arg;
>> +};
>> +
>> +#endif /* __DW_PHY_PDATA_H__ */
>> +
>>
^ permalink raw reply
* Re: Linux 4.9-rc4 double free from pp_release()
From: Shuah Khan @ 2016-11-14 16:45 UTC (permalink / raw)
To: Sudip Mukherjee, Shuah Khan, Greg KH; +Cc: LKML, Shuah Khan
In-Reply-To: <5823AA6D.8060501@gmail.com>
On 11/09/2016 03:59 PM, Sudip Mukherjee wrote:
> Hi Shuah
>
> On Wednesday 09 November 2016 10:04 PM, Shuah Khan wrote:
>> Hi Sudip/Greg,
>>
>> I am seeing the following double free from pp_release() in Linux 4.9-rc4
>> Is this a known problem?
>
> Can you please check if the patch at [1] fixes the problem.
>
> [1] https://patchwork.kernel.org/patch/9404815/
>
>
> Regards
> Sudip
>
>
Hi Sudip,
Yes the above patch fixed the problem. I tested it on 4.9-rc5
thanks,
-- Shuah
^ permalink raw reply
* [U-Boot] [ANN] U-Boot v2016.11 is released
From: Tom Rini @ 2016-11-14 16:46 UTC (permalink / raw)
To: u-boot
Hey all,
I've released v2016.11 and it's now live on git and FTP and ACD (along
with PGP sig file).
In many ways it feels good to say that the highlights of the last
release once again apply. We've had more DM conversion work, Kconfig
conversion work and arch / SoC / platform updates. We've also had some
important filesystem fixes come in and equally as important, test cases
added. We also now support the new and default enabled ext4 64bit flag
(thanks again Stefan!).
And what I want to highlight here is going forward both relative ease
of, and expectations on testing. Last time I talked about test.py and
how I'm using it more myself now. This time, I want to talk about
travis-ci support. If you use github you can get a more-or-less world
build and test.py for all of the QEMU targets we support today done in
about 2 and a half hours, wall clock. I don't expect people to do this
for iterative development or "trivial" changes, but if you have a series
that touches a lot of areas I think it's reasonable to expect that
you'll test things out this way. And I'll say now it's not 100%. About
once every 10 builds I'll have to go and re-start a sub-job because it
will fail to fetch one of the PPAs we use for no apparent reason. But
to be clear, it's a few minutes worth of setup and then you push a
change and you get build coverage and test coverage. This is really
awesome and I wish I had been paying more attention to this sooner.
As always, I know I'm missing pointing out a few things that I should
point out and would encourage folks to chime in if there's anything they
would like to highlight.
Thanks again everyone!
--
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20161114/b5f336f9/attachment.sig>
^ permalink raw reply
* Re: [RFC i-g-t 4/4] Add support for hotplug testing with the Chamelium
From: Lyude Paul @ 2016-11-14 16:46 UTC (permalink / raw)
To: Daniel Vetter; +Cc: intel-gfx
In-Reply-To: <20161114070558.xi65rcaljt4lehvz@phenom.ffwll.local>
Well I'm definitely in agreement with the idea of using config files
for this. Would be a lot more reliable then these tricks. Will respin
with this added
On Mon, 2016-11-14 at 08:05 +0100, Daniel Vetter wrote:
> On Mon, Nov 07, 2016 at 07:05:16PM -0500, Lyude wrote:
> >
> > For the purpose of testing things such as hotplugging and bad
> > monitors,
> > the ChromeOS team ended up designing a neat little device known as
> > the
> > Chamelium. More information on this can be found here:
> >
> > https://www.chromium.org/chromium-os/testing/chamelium
> >
> > This adds support for a couple of things to intel-gpu-tools:
> > - igt library functions for connecting to udev and monitoring it
> > for
> > hotplug events, loosely based off of the unfinished hotplugging
> > implementation in testdisplay
> > - Library functions for controlling the chamelium in tests using
> > xmlrpc. A couple of RPC calls were ommitted here, mainly because
> > they
> > didn't seem very useful for our needs or because they're just
> > plain
> > broken
> > - A set of basic tests using the chamelium.
> >
> > Because there's no surefire way that I know of where we can map
> > which
> > chamelium port belongs to which port on the system being tested (we
> > could just use hotplugging, but then we'd be relying on something
> > that
> > might be broken on the machine and potentially give false positives
> > for
> > certain tests), most of the chamelium tests will figure out whether
> > or
> > not a connection happened by counting the number of connectors
> > matching
> > the status we're looking for before hotplugging with the chamelium,
> > vs.
> > after hotplugging it.
> >
> > Tests which require that we know which port belongs to a certain
> > port
> > (such as ones where we actually perform a modeset) will unplug all
> > of
> > the chamelium ports, plug the desired port, then use the first DRM
> > connector with the desired connector type that's marked as
> > connected. In
> > order to ensure we don't end up using the wrong connector, these
> > tests
> > will skip if they find any connectors with the desired type marked
> > as
> > connected before performing the hotplug on the chamelium.
> >
> > Running these tests requires (of course) a working Chamelium, along
> > with
> > the RPC URL for the chamelium being specified in the environment
> > variable CHAMELIUM_HOST. If no URL is specified, the tests will
> > just
> > skip on their own. As well, tests for connectors which are not
> > actually
> > present on the system or the chamelium will skip on their own as
> > well.
> >
> > Signed-off-by: Lyude <lyude@redhat.com>
> > ---
> > configure.ac | 13 +
> > lib/Makefile.am | 10 +-
> > lib/igt.h | 1 +
> > lib/igt_chamelium.c | 628
> > +++++++++++++++++++++++++++++++++++++++++++++++++
> > lib/igt_chamelium.h | 77 ++++++
>
> Since you typed these nice gtkdocs, please also add it to the .xml in
> docs/ and make sure it looks all good (./autogen.sh --enable-gtk-
> docs).
>
> Wrt the api itself I think all we need is agreement from Tomeu that
> this
> is the right thing for his chamelium use-cases, too. And Tomeu has
> commit
> rights, so can push this stuff for you.
> -Daniel
>
>
> >
> > lib/igt_kms.c | 107 +++++++++
> > lib/igt_kms.h | 13 +-
> > scripts/run-tests.sh | 4 +-
> > tests/Makefile.am | 5 +-
> > tests/Makefile.sources | 1 +
> > tests/chamelium.c | 549
> > ++++++++++++++++++++++++++++++++++++++++++
> > 11 files changed, 1403 insertions(+), 5 deletions(-)
> > create mode 100644 lib/igt_chamelium.c
> > create mode 100644 lib/igt_chamelium.h
> > create mode 100644 tests/chamelium.c
> >
> > diff --git a/configure.ac b/configure.ac
> > index 735cfd5..88113b2 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -259,6 +259,18 @@ if test "x$with_libunwind" = xyes; then
> > AC_MSG_ERROR([libunwind not found. Use
> > --without-libunwind to disable libunwind support.]))
> > fi
> >
> > +# enable support for using the chamelium
> > +AC_ARG_ENABLE(chamelium,
> > + AS_HELP_STRING([--without-chamelium],
> > + [Build tests without chamelium
> > support]),
> > + [], [with_chamelium=yes])
> > +
> > +AM_CONDITIONAL(HAVE_CHAMELIUM, [test "x$with_chamelium" = xyes])
> > +if test "x$with_chamelium" = xyes; then
> > + AC_DEFINE(HAVE_CHAMELIUM, 1, [chamelium suport])
> > + PKG_CHECK_MODULES(XMLRPC, xmlrpc_client)
> > +fi
> > +
> > # enable debug symbols
> > AC_ARG_ENABLE(debug,
> > AS_HELP_STRING([--disable-debug],
> > @@ -356,6 +368,7 @@ echo " Assembler :
> > ${enable_assembler}"
> > echo " Debugger : ${enable_debugger}"
> > echo " Overlay : X: ${enable_overlay_xlib}, Xv:
> > ${enable_overlay_xvlib}"
> > echo " x86-specific tools : ${build_x86}"
> > +echo " Chamelium support : ${with_chamelium}"
> > echo ""
> > echo " • API-Documentation : ${enable_gtk_doc}"
> > echo " • Fail on warnings : ${enable_werror}"
> > diff --git a/lib/Makefile.am b/lib/Makefile.am
> > index 4c0893d..aeac43a 100644
> > --- a/lib/Makefile.am
> > +++ b/lib/Makefile.am
> > @@ -22,8 +22,14 @@ if !HAVE_LIBDRM_INTEL
> > stubs/drm/intel_bufmgr.h
> > endif
> >
> > +if HAVE_CHAMELIUM
> > + libintel_tools_la_SOURCES += \
> > + igt_chamelium.c \
> > + igt_chamelium.h
> > +endif
> > +
> > AM_CPPFLAGS = -I$(top_srcdir)
> > -AM_CFLAGS = $(CWARNFLAGS) $(DRM_CFLAGS) $(PCIACCESS_CFLAGS)
> > $(LIBUNWIND_CFLAGS) $(DEBUG_CFLAGS) \
> > +AM_CFLAGS = $(CWARNFLAGS) $(DRM_CFLAGS) $(PCIACCESS_CFLAGS)
> > $(LIBUNWIND_CFLAGS) $(DEBUG_CFLAGS) $(XMLRPC_CFLAGS) $(UDEV_CFLAGS)
> > \
> > -DIGT_SRCDIR=\""$(abs_top_srcdir)/tests"\" \
> > -DIGT_DATADIR=\""$(pkgdatadir)"\" \
> > -DIGT_LOG_DOMAIN=\""$(subst _,-,$*)"\" \
> > @@ -38,5 +44,7 @@ libintel_tools_la_LIBADD = \
> > $(LIBUDEV_LIBS) \
> > $(LIBUNWIND_LIBS) \
> > $(TIMER_LIBS) \
> > + $(XMLRPC_LIBS) \
> > + $(UDEV_LIBS) \
> > -lm
> >
> > diff --git a/lib/igt.h b/lib/igt.h
> > index d751f24..0ea03e4 100644
> > --- a/lib/igt.h
> > +++ b/lib/igt.h
> > @@ -30,6 +30,7 @@
> > #include "igt_aux.h"
> > #include "igt_core.h"
> > #include "igt_core.h"
> > +#include "igt_chamelium.h"
> > #include "igt_debugfs.h"
> > #include "igt_draw.h"
> > #include "igt_fb.h"
> > diff --git a/lib/igt_chamelium.c b/lib/igt_chamelium.c
> > new file mode 100644
> > index 0000000..a281ef6
> > --- /dev/null
> > +++ b/lib/igt_chamelium.c
> > @@ -0,0 +1,628 @@
> > +/*
> > + * Copyright © 2016 Red Hat Inc.
> > + *
> > + * Permission is hereby granted, free of charge, to any person
> > obtaining a
> > + * copy of this software and associated documentation files (the
> > "Software"),
> > + * to deal in the Software without restriction, including without
> > limitation
> > + * the rights to use, copy, modify, merge, publish, distribute,
> > sublicense,
> > + * and/or sell copies of the Software, and to permit persons to
> > whom the
> > + * Software is furnished to do so, subject to the following
> > conditions:
> > + *
> > + * The above copyright notice and this permission notice
> > (including the next
> > + * paragraph) shall be included in all copies or substantial
> > portions of the
> > + * Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> > EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> > MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
> > EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> > DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> > ARISING
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> > OTHER DEALINGS
> > + * IN THE SOFTWARE.
> > + *
> > + * Authors:
> > + * Lyude Paul <lyude@redhat.com>
> > + */
> > +
> > +#include "config.h"
> > +
> > +#include <string.h>
> > +#include <errno.h>
> > +#include <xmlrpc-c/base.h>
> > +#include <xmlrpc-c/client.h>
> > +
> > +#include "igt.h"
> > +
> > +#define check_rpc() \
> > + igt_assert_f(!env.fault_occurred, "Chamelium RPC call
> > failed: %s\n", \
> > + env.fault_string);
> > +
> > +/**
> > + * chamelium_ports:
> > + *
> > + * Contains information on all of the ports that are physically
> > connected from
> > + * the chamelium to the system. This information is initialized
> > when
> > + * #chamelium_init is called.
> > + */
> > +struct chamelium_port *chamelium_ports;
> > +
> > +/**
> > + * chamelium_port_count:
> > + *
> > + * How many ports are physically connected from the chamelium to
> > the system.
> > + */
> > +int chamelium_port_count;
> > +
> > +static const char *chamelium_url;
> > +static xmlrpc_env env;
> > +
> > +struct chamelium_edid {
> > + int id;
> > + struct igt_list link;
> > +};
> > +struct chamelium_edid *allocated_edids;
> > +
> > +/**
> > + * chamelium_plug:
> > + * @id: The ID of the port on the chamelium to plug in
> > + *
> > + * Simulate a display connector being plugged into the system
> > using the
> > + * chamelium.
> > + */
> > +void chamelium_plug(int id)
> > +{
> > + xmlrpc_value *res;
> > +
> > + igt_debug("Plugging port %d\n", id);
> > + res = xmlrpc_client_call(&env, chamelium_url, "Plug",
> > "(i)", id);
> > + check_rpc();
> > +
> > + xmlrpc_DECREF(res);
> > +}
> > +
> > +/**
> > + * chamelium_unplug:
> > + * @id: The ID of the port on the chamelium to unplug
> > + *
> > + * Simulate a display connector being unplugged from the system
> > using the
> > + * chamelium.
> > + */
> > +void chamelium_unplug(int id)
> > +{
> > + xmlrpc_value *res;
> > +
> > + igt_debug("Unplugging port %d\n", id);
> > + res = xmlrpc_client_call(&env, chamelium_url, "Unplug",
> > "(i)", id);
> > + check_rpc();
> > +
> > + xmlrpc_DECREF(res);
> > +}
> > +
> > +/**
> > + * chamelium_is_plugged:
> > + * @id: The ID of the port on the chamelium to check the status of
> > + *
> > + * Check whether or not the given port has been plugged into the
> > system using
> > + * #chamelium_plug.
> > + *
> > + * Returns: True if the connector is set to plugged in, false
> > otherwise.
> > + */
> > +bool chamelium_is_plugged(int id)
> > +{
> > + xmlrpc_value *res;
> > + xmlrpc_bool is_plugged;
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url, "IsPlugged",
> > "(i)", id);
> > + check_rpc();
> > +
> > + xmlrpc_read_bool(&env, res, &is_plugged);
> > + xmlrpc_DECREF(res);
> > +
> > + return is_plugged;
> > +}
> > +
> > +/**
> > + * chamelium_port_wait_video_input_stable:
> > + * @id: The ID of the port on the chamelium to check the status of
> > + * @timeout_secs: How long to wait for a video signal to appear
> > before timing
> > + * out
> > + *
> > + * Waits for a video signal to appear on the given port. This is
> > useful for
> > + * checking whether or not we've setup a monitor correctly.
> > + *
> > + * Returns: True if a video signal was detected, false if we timed
> > out
> > + */
> > +bool chamelium_port_wait_video_input_stable(int id, int
> > timeout_secs)
> > +{
> > + xmlrpc_value *res;
> > + xmlrpc_bool is_on;
> > +
> > + igt_debug("Waiting for video input to stabalize on port
> > %d\n", id);
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url,
> > "WaitVideoInputStable",
> > + "(ii)", id, timeout_secs);
> > + check_rpc();
> > +
> > + xmlrpc_read_bool(&env, res, &is_on);
> > + xmlrpc_DECREF(res);
> > +
> > + return is_on;
> > +}
> > +
> > +/**
> > + * chamelium_fire_hpd_pulses:
> > + * @id: The ID of the port to fire hotplug pulses on
> > + * @width_msec: How long each pulse should last
> > + * @count: The number of pulses to send
> > + *
> > + * A convienence function for sending multiple hotplug pulses to
> > the system.
> > + * The pulses start at low (e.g. connector is disconnected), and
> > then alternate
> > + * from high (e.g. connector is plugged in) to low. This is the
> > equivalent of
> > + * repeatedly calling #chamelium_plug and #chamelium_unplug,
> > waiting
> > + * @width_msec between each call.
> > + *
> > + * If @count is even, the last pulse sent will be high, and if
> > it's odd then it
> > + * will be low. Resetting the HPD line back to it's previous
> > state, if desired,
> > + * is the responsibility of the caller.
> > + */
> > +void chamelium_fire_hpd_pulses(int port, int width_msec, int
> > count)
> > +{
> > + xmlrpc_value *pulse_widths = xmlrpc_array_new(&env),
> > + *width = xmlrpc_int_new(&env, width_msec),
> > *res;
> > + int i;
> > +
> > + igt_debug("Firing %d HPD pulses with width of %d msec on
> > port %d\n",
> > + count, width_msec, port);
> > +
> > + for (i = 0; i < count; i++)
> > + xmlrpc_array_append_item(&env, pulse_widths,
> > width);
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url,
> > "FireMixedHpdPulses",
> > + "(iA)", port, pulse_widths);
> > + check_rpc();
> > +
> > + xmlrpc_DECREF(res);
> > + xmlrpc_DECREF(width);
> > + xmlrpc_DECREF(pulse_widths);
> > +}
> > +
> > +/**
> > + * chamelium_fire_mixed_hpd_pulses:
> > + * @id: The ID of the port to fire hotplug pulses on
> > + * @...: The length of each pulse in milliseconds, terminated with
> > a %0
> > + *
> > + * Does the same thing as #chamelium_fire_hpd_pulses, but allows
> > the caller to
> > + * specify the length of each individual pulse.
> > + */
> > +void chamelium_fire_mixed_hpd_pulses(int id, ...)
> > +{
> > + va_list args;
> > + xmlrpc_value *pulse_widths = xmlrpc_array_new(&env),
> > *width, *res;
> > + int arg;
> > +
> > + igt_debug("Firing mixed HPD pulses on port %d\n", id);
> > +
> > + va_start(args, id);
> > + for (arg = va_arg(args, int); arg; arg = va_arg(args,
> > int)) {
> > + width = xmlrpc_int_new(&env, arg);
> > + xmlrpc_array_append_item(&env, pulse_widths,
> > width);
> > + xmlrpc_DECREF(width);
> > + }
> > + va_end(args);
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url,
> > "FireMixedHpdPulses",
> > + "(iA)", id, pulse_widths);
> > + check_rpc();
> > + xmlrpc_DECREF(res);
> > +
> > + xmlrpc_DECREF(pulse_widths);
> > +}
> > +
> > +static void async_rpc_handler(const char *server_url, const char
> > *method_name,
> > + xmlrpc_value *param_array, void
> > *user_data,
> > + xmlrpc_env *fault, xmlrpc_value
> > *result)
> > +{
> > + /* We don't care about the responses */
> > +}
> > +
> > +/**
> > + * chamelium_async_hpd_pulse_start:
> > + * @id: The ID of the port to fire a hotplug pulse on
> > + * @high: Whether to fire a high pulse (e.g. simulate a connect),
> > or a low
> > + * pulse (e.g. simulate a disconnect)
> > + * @delay_secs: How long to wait before sending the HPD pulse.
> > + *
> > + * Instructs the chamelium to send an hpd pulse after @delay_secs
> > seconds have
> > + * passed, without waiting for the chamelium to finish. This is
> > useful for
> > + * testing things such as hpd after a suspend/resume cycle, since
> > we can't tell
> > + * the chamelium to send a hotplug at the same time that our
> > system is
> > + * suspended.
> > + *
> > + * It is required that the user eventually call
> > + * #chamelium_async_hpd_pulse_finish, to clean up the leftover
> > XML-RPC
> > + * responses from the chamelium.
> > + */
> > +void chamelium_async_hpd_pulse_start(int id, bool high, int
> > delay_secs)
> > +{
> > + xmlrpc_value *pulse_widths = xmlrpc_array_new(&env),
> > *width;
> > +
> > + /* TODO: Actually implement something in the chameleon
> > server to allow
> > + * for delayed actions such as hotplugs. This would work a
> > bit better
> > + * and allow us to test suspend/resume on ports without
> > hpd like VGA
> > + */
> > +
> > + igt_debug("Sending HPD pulse (%s) on port %d with %d
> > second delay\n",
> > + high ? "high->low" : "low->high", id,
> > delay_secs);
> > +
> > + /* If we're starting at high, make the first pulse width 0
> > so we keep
> > + * the port connected */
> > + if (high) {
> > + width = xmlrpc_int_new(&env, 0);
> > + xmlrpc_array_append_item(&env, pulse_widths,
> > width);
> > + xmlrpc_DECREF(width);
> > + }
> > +
> > + width = xmlrpc_int_new(&env, delay_secs * 1000);
> > + xmlrpc_array_append_item(&env, pulse_widths, width);
> > + xmlrpc_DECREF(width);
> > +
> > + xmlrpc_client_call_asynch(chamelium_url,
> > "FireMixedHpdPulses",
> > + async_rpc_handler, NULL, "(iA)",
> > + id, pulse_widths);
> > + xmlrpc_DECREF(pulse_widths);
> > +}
> > +
> > +/**
> > + * chamelium_async_hpd_pulse_finish:
> > + *
> > + * Waits for any asynchronous RPC started by
> > #chamelium_async_hpd_pulse_start
> > + * to complete, and then cleans up any leftover responses from the
> > chamelium.
> > + * If all of the RPC calls have already completed, this function
> > returns
> > + * immediately.
> > + */
> > +void chamelium_async_hpd_pulse_finish(void)
> > +{
> > + xmlrpc_client_event_loop_finish_asynch();
> > +}
> > +
> > +/**
> > + * chamelium_new_edid:
> > + * @edid: The edid blob to upload to the chamelium
> > + *
> > + * Uploads and registers a new EDID with the chamelium. The EDID
> > will be
> > + * destroyed automatically when #chamelium_deinit is called.
> > + *
> > + * Returns: The ID of the EDID uploaded to the chamelium.
> > + */
> > +int chamelium_new_edid(const unsigned char *edid)
> > +{
> > + xmlrpc_value *res;
> > + struct chamelium_edid *allocated_edid;
> > + int edid_id;
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url,
> > "CreateEdid",
> > + "(6)", edid, EDID_LENGTH);
> > + check_rpc();
> > +
> > + xmlrpc_read_int(&env, res, &edid_id);
> > + xmlrpc_DECREF(res);
> > +
> > + allocated_edid = malloc(sizeof(struct chamelium_edid));
> > + igt_assert(allocated_edid);
> > +
> > + allocated_edid->id = edid_id;
> > + if (allocated_edids) {
> > + igt_list_insert(&allocated_edids->link,
> > &allocated_edid->link);
> > + } else {
> > + igt_list_init(&allocated_edid->link);
> > + allocated_edids = allocated_edid;
> > + }
> > +
> > + return edid_id;
> > +}
> > +
> > +static void chamelium_destroy_edid(int edid_id)
> > +{
> > + xmlrpc_value *res;
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url,
> > "DestroyEdid",
> > + "(i)", edid_id);
> > + check_rpc();
> > +
> > + xmlrpc_DECREF(res);
> > +}
> > +
> > +/**
> > + * chamelium_port_set_edid:
> > + * @id: The ID of the port to set the EDID on
> > + * @edid_id: The ID of an EDID on the chamelium created with
> > + * #chamelium_new_edid, or 0 to disable the EDID on the port
> > + *
> > + * Sets a port on the chamelium to use the specified EDID. This
> > does not fire a
> > + * hotplug pulse on it's own, and merely changes what EDID the
> > chamelium port
> > + * will report to us the next time we probe it. Users will need to
> > reprobe the
> > + * connectors themselves if they want to see the EDID reported by
> > the port
> > + * change.
> > + */
> > +void chamelium_port_set_edid(int id, int edid_id)
> > +{
> > + xmlrpc_value *res;
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url, "ApplyEdid",
> > + "(ii)", id, edid_id);
> > + check_rpc();
> > +
> > + xmlrpc_DECREF(res);
> > +}
> > +
> > +/**
> > + * chamelium_port_set_ddc_state:
> > + * @id: The ID of the port whose DDC bus we want to modify
> > + * @enabled: Whether or not to enable the DDC bus
> > + *
> > + * This disables the DDC bus (e.g. the i2c line on the connector
> > that gives us
> > + * an EDID) of the specified port on the chamelium. This is useful
> > for testing
> > + * behavior on legacy connectors such as VGA, where the presence
> > of a DDC bus
> > + * is not always guaranteed.
> > + */
> > +void chamelium_port_set_ddc_state(int port, bool enabled)
> > +{
> > + xmlrpc_value *res;
> > +
> > + igt_debug("%sabling DDC bus on port %d\n",
> > + enabled ? "En" : "Dis", port);
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url,
> > "SetDdcState",
> > + "(ib)", port, enabled);
> > + check_rpc();
> > +
> > + xmlrpc_DECREF(res);
> > +}
> > +
> > +/**
> > + * chamelium_port_get_ddc_state:
> > + * @id: The ID of the port whose DDC bus we want to check the
> > status of
> > + *
> > + * Check whether or not the DDC bus on the specified chamelium
> > port is enabled
> > + * or not.
> > + *
> > + * Returns: True if the DDC bus is enabled, false otherwise.
> > + */
> > +bool chamelium_port_get_ddc_state(int id)
> > +{
> > + xmlrpc_value *res;
> > + xmlrpc_bool enabled;
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url,
> > "IsDdcEnabled",
> > + "(i)", id);
> > + check_rpc();
> > +
> > + xmlrpc_read_bool(&env, res, &enabled);
> > +
> > + xmlrpc_DECREF(res);
> > + return enabled;
> > +}
> > +
> > +/**
> > + * chamelium_port_get_resolution:
> > + * @id: The ID of the port whose display resolution we want to
> > check
> > + * @x: Where to store the horizontal resolution of the port
> > + * @y: Where to store the verical resolution of the port
> > + *
> > + * Check the current reported display resolution of the specified
> > port on the
> > + * chamelium. This information is provided by the chamelium
> > itself, not DRM.
> > + * Useful for verifying that we really are scanning out at the
> > resolution we
> > + * think we are.
> > + */
> > +void chamelium_port_get_resolution(int id, int *x, int *y)
> > +{
> > + xmlrpc_value *res, *res_x, *res_y;
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url,
> > "DetectResolution",
> > + "(i)", id);
> > + check_rpc();
> > +
> > + xmlrpc_array_read_item(&env, res, 0, &res_x);
> > + xmlrpc_array_read_item(&env, res, 1, &res_y);
> > + xmlrpc_read_int(&env, res_x, x);
> > + xmlrpc_read_int(&env, res_y, y);
> > +
> > + xmlrpc_DECREF(res_x);
> > + xmlrpc_DECREF(res_y);
> > + xmlrpc_DECREF(res);
> > +}
> > +
> > +/**
> > + * chamelium_get_crc_for_area:
> > + * @id: The ID of the port from which we want to retrieve the CRC
> > + * @x: The X coordinate on the emulated display to start
> > calculating the CRC
> > + * from
> > + * @y: The Y coordinate on the emulated display to start
> > calculating the CRC
> > + * from
> > + * @w: The width of the area to fetch the CRC from
> > + * @h: The height of the area to fetch the CRC from
> > + *
> > + * Reads back the pixel CRC for an area on the specified chamelium
> > port. This
> > + * is the same as using the CRC readback from a GPU, the main
> > difference being
> > + * the data is provided by the chamelium and also allows us to
> > specify a region
> > + * of the screen to use as opposed to the entire thing.
> > + *
> > + * Returns: The CRC read back from the chamelium
> > + */
> > +unsigned int chamelium_get_crc_for_area(int id, int x, int y, int
> > w, int h)
> > +{
> > + xmlrpc_value *res;
> > + unsigned int crc;
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url,
> > "ComputePixelChecksum",
> > + "(iiiii)", id, x, y, w, h);
> > + check_rpc();
> > +
> > + xmlrpc_read_int(&env, res, (int*)(&crc));
> > +
> > + xmlrpc_DECREF(res);
> > + return crc;
> > +}
> > +
> > +static unsigned int chamelium_get_port_type(int port)
> > +{
> > + xmlrpc_value *res;
> > + const char *port_type_str;
> > + unsigned int port_type;
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url,
> > "GetConnectorType",
> > + "(i)", port);
> > + check_rpc();
> > +
> > + xmlrpc_read_string(&env, res, &port_type_str);
> > + igt_debug("Port %d is of type '%s'\n", port,
> > port_type_str);
> > +
> > + if (strcmp(port_type_str, "DP") == 0)
> > + port_type = DRM_MODE_CONNECTOR_DisplayPort;
> > + else if (strcmp(port_type_str, "HDMI") == 0)
> > + port_type = DRM_MODE_CONNECTOR_HDMIA;
> > + else if (strcmp(port_type_str, "VGA") == 0)
> > + port_type = DRM_MODE_CONNECTOR_VGA;
> > + else
> > + port_type = DRM_MODE_CONNECTOR_Unknown;
> > +
> > + free((void*)port_type_str);
> > + xmlrpc_DECREF(res);
> > +
> > + return port_type;
> > +}
> > +
> > +static void chamelium_probe_ports(void)
> > +{
> > + xmlrpc_value *res, *port_val;
> > + struct chamelium_port *port;
> > + unsigned int port_type;
> > + int id, i, len;
> > +
> > + /* Figure out what ports are connected, along with their
> > types */
> > + res = xmlrpc_client_call(&env, chamelium_url,
> > "ProbeInputs", "()");
> > + check_rpc();
> > +
> > + len = xmlrpc_array_size(&env, res);
> > + chamelium_ports = calloc(sizeof(struct chamelium_port),
> > len);
> > +
> > + igt_assert(chamelium_ports);
> > +
> > + for (i = 0; i < len; i++) {
> > + xmlrpc_array_read_item(&env, res, i, &port_val);
> > + xmlrpc_read_int(&env, port_val, &id);
> > + xmlrpc_DECREF(port_val);
> > +
> > + port_type = chamelium_get_port_type(id);
> > + if (port_type == DRM_MODE_CONNECTOR_Unknown)
> > + continue;
> > +
> > + port = &chamelium_ports[chamelium_port_count];
> > + port->id = id;
> > + port->type = port_type;
> > + port->original_plugged = chamelium_is_plugged(id);
> > + chamelium_port_count++;
> > + }
> > +
> > + chamelium_ports = realloc(chamelium_ports,
> > + sizeof(struct chamelium_port) *
> > + chamelium_port_count);
> > + igt_assert(chamelium_ports);
> > +
> > + xmlrpc_DECREF(res);
> > +}
> > +
> > +/**
> > + * chamelium_reset:
> > + *
> > + * Resets the chamelium's IO board. As well, this also has the
> > effect of
> > + * causing all of the chamelium ports to get set to unplugged
> > + */
> > +void chamelium_reset(void)
> > +{
> > + xmlrpc_value *res;
> > +
> > + igt_debug("Resetting the chamelium\n");
> > +
> > + res = xmlrpc_client_call(&env, chamelium_url, "Reset",
> > "()");
> > + check_rpc();
> > +
> > + xmlrpc_DECREF(res);
> > +}
> > +
> > +static void chamelium_exit_handler(int sig)
> > +{
> > + chamelium_deinit();
> > +}
> > +
> > +/**
> > + * chamelium_init:
> > + *
> > + * Sets up a connection with a chamelium, using the url provided
> > in the
> > + * CHAMELIUM_HOST enviornment variable. This must be called first
> > before trying
> > + * to use the chamelium. When the connection is no longer needed,
> > the user
> > + * should call #chamelium_deinit to free the resources used by the
> > connection.
> > + *
> > + * If we fail to establish a connection with the chamelium, we
> > fail the current
> > + * test.
> > + */
> > +void chamelium_init(void)
> > +{
> > + chamelium_url = getenv("CHAMELIUM_HOST");
> > + igt_assert(chamelium_url != NULL);
> > +
> > + xmlrpc_env_init(&env);
> > +
> > + xmlrpc_client_init2(&env, XMLRPC_CLIENT_NO_FLAGS, PACKAGE,
> > + PACKAGE_VERSION, NULL, 0);
> > + igt_fail_on_f(env.fault_occurred,
> > + "Failed to init xmlrpc: %s\n",
> > + env.fault_string);
> > +
> > + chamelium_probe_ports();
> > + chamelium_reset();
> > +
> > + igt_install_exit_handler(chamelium_exit_handler);
> > +}
> > +
> > +/**
> > + * chamelium_deinit:
> > + *
> > + * Frees the resources used by a connection to the chamelium that
> > was set up
> > + * with #chamelium_init. As well, this function restores the state
> > of the
> > + * chamelium like it was before calling #chamelium_init. This
> > function is also
> > + * called as an exit handler, so users only need to call manually
> > if they don't
> > + * want the chamelium interfering with other tests in the same
> > file.
> > + */
> > +void chamelium_deinit(void)
> > +{
> > + int i;
> > + struct chamelium_edid *pos, *tmp;
> > +
> > + if (!chamelium_url)
> > + return;
> > +
> > + /* Restore the original state of all of the chamelium
> > ports */
> > + igt_debug("Restoring original state of chamelium\n");
> > + chamelium_reset();
> > + for (i = 0; i < chamelium_port_count; i++) {
> > + if (chamelium_ports[i].original_plugged)
> > + chamelium_plug(chamelium_ports[i].id);
> > + }
> > +
> > + /* Destroy any EDIDs we created to make sure we don't leak
> > them */
> > + igt_list_for_each_safe(pos, tmp, &allocated_edids->link,
> > link) {
> > + chamelium_destroy_edid(pos->id);
> > + free(pos);
> > + }
> > +
> > + xmlrpc_client_cleanup();
> > + xmlrpc_env_clean(&env);
> > +
> > + free(chamelium_ports);
> > + allocated_edids = NULL;
> > + chamelium_url = NULL;
> > + chamelium_ports = NULL;
> > + chamelium_port_count = 0;
> > +}
> > +
> > diff --git a/lib/igt_chamelium.h b/lib/igt_chamelium.h
> > new file mode 100644
> > index 0000000..900615c
> > --- /dev/null
> > +++ b/lib/igt_chamelium.h
> > @@ -0,0 +1,77 @@
> > +/*
> > + * Copyright © 2016 Red Hat Inc.
> > + *
> > + * Permission is hereby granted, free of charge, to any person
> > obtaining a
> > + * copy of this software and associated documentation files (the
> > "Software"),
> > + * to deal in the Software without restriction, including without
> > limitation
> > + * the rights to use, copy, modify, merge, publish, distribute,
> > sublicense,
> > + * and/or sell copies of the Software, and to permit persons to
> > whom the
> > + * Software is furnished to do so, subject to the following
> > conditions:
> > + *
> > + * The above copyright notice and this permission notice
> > (including the next
> > + * paragraph) shall be included in all copies or substantial
> > portions of the
> > + * Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> > EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> > MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
> > EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> > DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> > ARISING
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> > OTHER DEALINGS
> > + * IN THE SOFTWARE.
> > + *
> > + * Authors: Lyude Paul <lyude@redhat.com>
> > + */
> > +
> > +#ifndef IGT_CHAMELIUM_H
> > +#define IGT_CHAMELIUM_H
> > +
> > +#include "config.h"
> > +#include "igt.h"
> > +#include <stdbool.h>
> > +
> > +/**
> > + * chamelium_port:
> > + * @type: The DRM connector type of the chamelium port
> > + * @id: The ID of the chamelium port
> > + */
> > +struct chamelium_port {
> > + unsigned int type;
> > + int id;
> > +
> > + /* For restoring the original port state after finishing
> > tests */
> > + bool original_plugged;
> > +};
> > +
> > +extern int chamelium_port_count;
> > +extern struct chamelium_port *chamelium_ports;
> > +
> > +/**
> > + * igt_require_chamelium:
> > + *
> > + * Checks whether or not the environment variable CHAMELIUM_HOST
> > is non-null,
> > + * otherwise skips the current test.
> > + */
> > +#define igt_require_chamelium() \
> > + igt_require(getenv("CHAMELIUM_HOST") != NULL);
> > +
> > +void chamelium_init(void);
> > +void chamelium_deinit(void);
> > +void chamelium_reset(void);
> > +
> > +void chamelium_plug(int id);
> > +void chamelium_unplug(int id);
> > +bool chamelium_is_plugged(int id);
> > +bool chamelium_port_wait_video_input_stable(int id, int
> > timeout_secs);
> > +void chamelium_fire_mixed_hpd_pulses(int id, ...);
> > +void chamelium_fire_hpd_pulses(int id, int width, int count);
> > +void chamelium_async_hpd_pulse_start(int id, bool high, int
> > delay_secs);
> > +void chamelium_async_hpd_pulse_finish(void);
> > +int chamelium_new_edid(const unsigned char *edid);
> > +void chamelium_port_set_edid(int id, int edid_id);
> > +bool chamelium_port_get_ddc_state(int id);
> > +void chamelium_port_set_ddc_state(int id, bool enabled);
> > +void chamelium_port_get_resolution(int id, int *x, int *y);
> > +unsigned int chamelium_get_crc_for_area(int id, int x, int y, int
> > w, int h);
> > +
> > +#endif /* IGT_CHAMELIUM_H */
> > diff --git a/lib/igt_kms.c b/lib/igt_kms.c
> > index 989704e..7768d7b 100644
> > --- a/lib/igt_kms.c
> > +++ b/lib/igt_kms.c
> > @@ -40,6 +40,10 @@
> > #endif
> > #include <errno.h>
> > #include <time.h>
> > +#ifdef HAVE_CHAMELIUM
> > +#include <libudev.h>
> > +#include <poll.h>
> > +#endif
> >
> > #include <i915_drm.h>
> >
> > @@ -2760,6 +2764,109 @@ void igt_reset_connectors(void)
> > "detect");
> > }
> >
> > +#ifdef HAVE_CHAMELIUM
> > +static struct udev_monitor *hotplug_mon;
> > +
> > +/**
> > + * igt_watch_hotplug:
> > + *
> > + * Begin monitoring udev for hotplug events.
> > + */
> > +void igt_watch_hotplug(void)
> > +{
> > + struct udev *udev;
> > + int ret, flags, fd;
> > +
> > + if (hotplug_mon)
> > + igt_cleanup_hotplug();
> > +
> > + udev = udev_new();
> > + igt_assert(udev != NULL);
> > +
> > + hotplug_mon = udev_monitor_new_from_netlink(udev, "udev");
> > + igt_assert(hotplug_mon != NULL);
> > +
> > + ret =
> > udev_monitor_filter_add_match_subsystem_devtype(hotplug_mon,
> > + "drm
> > ",
> > + "drm
> > _minor");
> > + igt_assert_eq(ret, 0);
> > + ret = udev_monitor_filter_update(hotplug_mon);
> > + igt_assert_eq(ret, 0);
> > + ret = udev_monitor_enable_receiving(hotplug_mon);
> > + igt_assert_eq(ret, 0);
> > +
> > + /* Set the fd for udev as non blocking */
> > + fd = udev_monitor_get_fd(hotplug_mon);
> > + flags = fcntl(fd, F_GETFL, 0);
> > + igt_assert(flags);
> > +
> > + flags |= O_NONBLOCK;
> > + igt_assert_neq(fcntl(fd, F_SETFL, flags), -1);
> > +}
> > +
> > +/**
> > + * igt_hotplug_detected:
> > + * @timeout_secs: How long to wait for a hotplug event to occur.
> > + *
> > + * Assert that a hotplug event was received since we last checked
> > the monitor.
> > + */
> > +bool igt_hotplug_detected(int timeout_secs)
> > +{
> > + struct udev_device *dev;
> > + const char *hotplug_val;
> > + struct pollfd fd = {
> > + .fd = udev_monitor_get_fd(hotplug_mon),
> > + .events = POLLIN
> > + };
> > + bool hotplug_received = false;
> > +
> > + /* Go through all of the events pending on the udev
> > monitor. Once we
> > + * receive a hotplug, we continue going through the rest
> > of the events
> > + * so that redundant hotplug events don't change the
> > results of future
> > + * checks
> > + */
> > + while (!hotplug_received && poll(&fd, 1, timeout_secs *
> > 1000)) {
> > + dev = udev_monitor_receive_device(hotplug_mon);
> > +
> > + hotplug_val = udev_device_get_property_value(dev,
> > "HOTPLUG");
> > + if (hotplug_val && atoi(hotplug_val) == 1)
> > + hotplug_received = true;
> > +
> > + udev_device_unref(dev);
> > + }
> > +
> > + return hotplug_received;
> > +}
> > +
> > +/**
> > + * igt_flush_hotplugs:
> > + * @mon: A udev monitor created by #igt_watch_hotplug
> > + *
> > + * Get rid of any pending hotplug events waiting on the udev
> > monitor
> > + */
> > +void igt_flush_hotplugs(void)
> > +{
> > + struct udev_device *dev;
> > +
> > + while ((dev = udev_monitor_receive_device(hotplug_mon)))
> > + udev_device_unref(dev);
> > +}
> > +
> > +/**
> > + * igt_cleanup_hotplug:
> > + *
> > + * Cleanup the resources allocated by #igt_watch_hotplug
> > + */
> > +void igt_cleanup_hotplug(void)
> > +{
> > + struct udev *udev = udev_monitor_get_udev(hotplug_mon);
> > +
> > + udev_monitor_unref(hotplug_mon);
> > + hotplug_mon = NULL;
> > + udev_unref(udev);
> > +}
> > +#endif
> > +
> > /**
> > * kmstest_get_vbl_flag:
> > * @pipe_id: Pipe to convert to flag representation.
> > diff --git a/lib/igt_kms.h b/lib/igt_kms.h
> > index 6422adc..d0b67e0 100644
> > --- a/lib/igt_kms.h
> > +++ b/lib/igt_kms.h
> > @@ -31,6 +31,9 @@
> > #include <stdbool.h>
> > #include <stdint.h>
> > #include <stddef.h>
> > +#ifdef HAVE_CHAMELIUM
> > +#include <libudev.h>
> > +#endif
> >
> > #include <xf86drmMode.h>
> >
> > @@ -333,6 +336,7 @@ igt_plane_t *igt_output_get_plane(igt_output_t
> > *output, enum igt_plane plane);
> > bool igt_pipe_get_property(igt_pipe_t *pipe, const char *name,
> > uint32_t *prop_id, uint64_t *value,
> > drmModePropertyPtr *prop);
> > +void igt_output_get_edid(igt_output_t *output, unsigned char
> > *edid_out);
> >
> > static inline bool igt_plane_supports_rotation(igt_plane_t *plane)
> > {
> > @@ -478,6 +482,13 @@ uint32_t kmstest_get_vbl_flag(uint32_t
> > pipe_id);
> > #define EDID_LENGTH 128
> > const unsigned char* igt_kms_get_base_edid(void);
> > const unsigned char* igt_kms_get_alt_edid(void);
> > -
> > +bool igt_compare_output_edid(igt_output_t *output, const unsigned
> > char *edid);
> > +
> > +#ifdef HAVE_CHAMELIUM
> > +void igt_watch_hotplug(void);
> > +bool igt_hotplug_detected(int timeout_secs);
> > +void igt_flush_hotplugs(void);
> > +void igt_cleanup_hotplug(void);
> > +#endif
> >
> > #endif /* __IGT_KMS_H__ */
> > diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh
> > index 97ba9e5..6539bf9 100755
> > --- a/scripts/run-tests.sh
> > +++ b/scripts/run-tests.sh
> > @@ -122,10 +122,10 @@ if [ ! -x "$PIGLIT" ]; then
> > fi
> >
> > if [ "x$RESUME" != "x" ]; then
> > - sudo IGT_TEST_ROOT="$IGT_TEST_ROOT" "$PIGLIT" resume
> > "$RESULTS" $NORETRY
> > + sudo IGT_TEST_ROOT="$IGT_TEST_ROOT"
> > CHAMELIUM_HOST="$CHAMELIUM_HOST" "$PIGLIT" resume "$RESULTS"
> > $NORETRY
> > else
> > mkdir -p "$RESULTS"
> > - sudo IGT_TEST_ROOT="$IGT_TEST_ROOT" "$PIGLIT" run igt -o
> > "$RESULTS" -s $VERBOSE $EXCLUDE $FILTER
> > + sudo IGT_TEST_ROOT="$IGT_TEST_ROOT"
> > CHAMELIUM_HOST="$CHAMELIUM_HOST" "$PIGLIT" run igt -o "$RESULTS" -s
> > $VERBOSE $EXCLUDE $FILTER
> > fi
> >
> > if [ "$SUMMARY" == "html" ]; then
> > diff --git a/tests/Makefile.am b/tests/Makefile.am
> > index a408126..06a8e6b 100644
> > --- a/tests/Makefile.am
> > +++ b/tests/Makefile.am
> > @@ -63,7 +63,7 @@ AM_CFLAGS = $(DRM_CFLAGS) $(CWARNFLAGS) -Wno-
> > unused-result $(DEBUG_CFLAGS)\
> > $(LIBUNWIND_CFLAGS) $(WERROR_CFLAGS) \
> > $(NULL)
> >
> > -LDADD = ../lib/libintel_tools.la $(GLIB_LIBS)
> > +LDADD = ../lib/libintel_tools.la $(GLIB_LIBS) $(XMLRPC_LIBS)
> >
> > AM_CFLAGS += $(CAIRO_CFLAGS) $(LIBUDEV_CFLAGS) $(GLIB_CFLAGS)
> > AM_LDFLAGS = -Wl,--as-needed
> > @@ -119,5 +119,8 @@ vc4_wait_bo_CFLAGS = $(AM_CFLAGS)
> > $(DRM_VC4_CFLAGS)
> > vc4_wait_bo_LDADD = $(LDADD) $(DRM_VC4_LIBS)
> > vc4_wait_seqno_CFLAGS = $(AM_CFLAGS) $(DRM_VC4_CFLAGS)
> > vc4_wait_seqno_LDADD = $(LDADD) $(DRM_VC4_LIBS)
> > +
> > +chamelium_CFLAGS = $(AM_CFLAGS) $(XMLRPC_CFLAGS) $(UDEV_CFLAGS)
> > +chamelium_LDADD = $(LDADD) $(XMLRPC_LIBS) $(UDEV_LIBS)
> > endif
> >
> > diff --git a/tests/Makefile.sources b/tests/Makefile.sources
> > index 6d081c3..3e01852 100644
> > --- a/tests/Makefile.sources
> > +++ b/tests/Makefile.sources
> > @@ -131,6 +131,7 @@ TESTS_progs_M = \
> > template \
> > vgem_basic \
> > vgem_slow \
> > + chamelium \
> > $(NULL)
> >
> > TESTS_progs_XM = \
> > diff --git a/tests/chamelium.c b/tests/chamelium.c
> > new file mode 100644
> > index 0000000..769cfdc
> > --- /dev/null
> > +++ b/tests/chamelium.c
> > @@ -0,0 +1,549 @@
> > +/*
> > + * Copyright © 2016 Red Hat Inc.
> > + *
> > + * Permission is hereby granted, free of charge, to any person
> > obtaining a
> > + * copy of this software and associated documentation files (the
> > "Software"),
> > + * to deal in the Software without restriction, including without
> > limitation
> > + * the rights to use, copy, modify, merge, publish, distribute,
> > sublicense,
> > + * and/or sell copies of the Software, and to permit persons to
> > whom the
> > + * Software is furnished to do so, subject to the following
> > conditions:
> > + *
> > + * The above copyright notice and this permission notice
> > (including the next
> > + * paragraph) shall be included in all copies or substantial
> > portions of the
> > + * Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> > EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> > MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
> > EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
> > DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> > ARISING
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> > OTHER DEALINGS
> > + * IN THE SOFTWARE.
> > + *
> > + * Authors:
> > + * Lyude Paul <lyude@redhat.com>
> > + */
> > +
> > +#include "config.h"
> > +#include "igt.h"
> > +
> > +#include <fcntl.h>
> > +#include <string.h>
> > +
> > +struct connector_info {
> > + int id;
> > + unsigned int type;
> > +};
> > +
> > +typedef struct {
> > + int drm_fd;
> > + struct connector_info *connectors;
> > + int connector_count;
> > +} data_t;
> > +
> > +#define HOTPLUG_TIMEOUT 30 /* seconds */
> > +
> > +/*
> > + * Since we can't get an exact mapping of which chamelium ports
> > are connected
> > + * to each of the DUT's ports, we have to figure out whether or
> > not the status
> > + * of a port on the chamelium has changed by counting the number
> > of connectors
> > + * with the connector type and status we want, and then comparing
> > the values
> > + * from before hotplugging and after
> > + */
> > +static void
> > +reprobe_connectors(data_t *data, unsigned int type)
> > +{
> > + drmModeConnector *connector;
> > + int i;
> > +
> > + igt_debug("Reprobing %s connectors...\n",
> > + kmstest_connector_type_str(type));
> > +
> > + for (i = 0; i < data->connector_count; i++) {
> > + if (data->connectors[i].type != type)
> > + continue;
> > +
> > + connector = drmModeGetConnector(data->drm_fd,
> > + data-
> > >connectors[i].id);
> > + igt_assert(connector);
> > +
> > + drmModeFreeConnector(connector);
> > + }
> > +}
> > +
> > +static void
> > +reset_chamelium_state(data_t *data)
> > +{
> > + chamelium_reset();
> > + reprobe_connectors(data, DRM_MODE_CONNECTOR_DisplayPort);
> > + reprobe_connectors(data, DRM_MODE_CONNECTOR_HDMIA);
> > + reprobe_connectors(data, DRM_MODE_CONNECTOR_VGA);
> > +}
> > +
> > +static int
> > +connector_status_count(data_t *data, unsigned int type, unsigned
> > int status)
> > +{
> > + struct connector_info *info;
> > + drmModeConnector *connector;
> > + int count = 0;
> > +
> > + for (int i = 0; i < data->connector_count; i++) {
> > + info = &data->connectors[i];
> > + if (info->type != type)
> > + continue;
> > +
> > + connector = drmModeGetConnectorCurrent(data-
> > >drm_fd, info->id);
> > + igt_assert(connector);
> > +
> > + if (connector->connection == status)
> > + count++;
> > +
> > + drmModeFreeConnector(connector);
> > + }
> > +
> > + return count;
> > +}
> > +
> > +static void
> > +require_connector_present(data_t *data, unsigned int type)
> > +{
> > + int i;
> > + bool found = false;
> > +
> > + for (i = 0; i < data->connector_count && !found; i++) {
> > + if (data->connectors[i].type == type)
> > + found = true;
> > + }
> > +
> > + igt_require_f(found, "No port of type %s was found on the
> > system\n",
> > + kmstest_connector_type_str(type));
> > +
> > + for (i = 0, found = false; i < chamelium_port_count &&
> > !found; i++) {
> > + if (chamelium_ports[i].type == type)
> > + found = true;
> > + }
> > +
> > + igt_require_f(found, "No connected port of type %s was
> > found on the chamelium\n",
> > + kmstest_connector_type_str(type));
> > +}
> > +
> > +static drmModeConnector *
> > +find_connected(data_t *data, unsigned int type)
> > +{
> > + drmModeConnector *connector;
> > + int i;
> > +
> > + for (i = 0; i < data->connector_count; i++) {
> > + if (data->connectors[i].type != type)
> > + continue;
> > +
> > + connector = drmModeGetConnector(data->drm_fd,
> > + data-
> > >connectors[i].id);
> > + igt_assert(connector);
> > +
> > + if (connector->connection == DRM_MODE_CONNECTED)
> > + return connector;
> > +
> > + drmModeFreeConnector(connector);
> > + }
> > +
> > + return NULL;
> > +}
> > +
> > +/*
> > + * Skips the test if we find any connectors with a matching type
> > connected.
> > + * This is necessary when we need to identify which port on the
> > machine is
> > + * connected to which port on the chamelium, since any other ports
> > that are
> > + * connected to other displays could cause us to choose the wrong
> > port.
> > + *
> > + * This also has the effect of reprobing all of the connected
> > ports.
> > + */
> > +static void
> > +skip_on_any_connected(data_t *data, unsigned int type)
> > +{
> > + drmModeConnector *connector;
> > +
> > + connector = find_connected(data, type);
> > + if (connector)
> > + drmModeFreeConnector(connector);
> > +
> > + igt_skip_on(connector);
> > +}
> > +
> > +static void
> > +test_basic_hotplug(data_t *data, struct chamelium_port *port)
> > +{
> > + int before, after;
> > + int i;
> > +
> > + reset_chamelium_state(data);
> > + igt_watch_hotplug();
> > +
> > + for (i = 0; i < 15; i++) {
> > + igt_flush_hotplugs();
> > +
> > + /* Check if we get a sysfs hotplug event */
> > + before = connector_status_count(data, port->type,
> > + DRM_MODE_CONNECTED
> > );
> > + chamelium_plug(port->id);
> > + igt_assert(igt_hotplug_detected(HOTPLUG_TIMEOUT));
> > +
> > + /* Now we should have one additional port
> > connected */
> > + reprobe_connectors(data, port->type);
> > + after = connector_status_count(data, port->type,
> > + DRM_MODE_CONNECTED)
> > ;
> > + igt_assert_lt(before, after);
> > +
> > + igt_flush_hotplugs();
> > +
> > + /* Now check if we get a hotplug from
> > disconnection */
> > + before = connector_status_count(data, port->type,
> > + DRM_MODE_DISCONNEC
> > TED);
> > + chamelium_unplug(port->id);
> > + igt_assert(igt_hotplug_detected(HOTPLUG_TIMEOUT));
> > +
> > + /* And make sure we now have one more disconnected
> > port */
> > + reprobe_connectors(data, port->type);
> > + after = connector_status_count(data, port->type,
> > + DRM_MODE_DISCONNECT
> > ED);
> > + igt_assert_lt(before, after);
> > +
> > + /* Sleep so we don't accidentally cause an hpd
> > storm */
> > + sleep(1);
> > + }
> > +}
> > +
> > +static void
> > +test_edid_read(data_t *data, struct chamelium_port *port,
> > + int edid_id, const unsigned char *edid)
> > +{
> > + drmModeConnector *connector;
> > + drmModeObjectProperties *props;
> > + drmModePropertyBlobPtr edid_blob = NULL;
> > + bool edid_found = false;
> > + int i;
> > +
> > + reset_chamelium_state(data);
> > + skip_on_any_connected(data, port->type);
> > +
> > + chamelium_port_set_edid(port->id, edid_id);
> > + chamelium_plug(port->id);
> > + sleep(1);
> > + igt_assert(connector = find_connected(data, port->type));
> > +
> > + props = drmModeObjectGetProperties(data->drm_fd,
> > + connector-
> > >connector_id,
> > + DRM_MODE_OBJECT_CONNECT
> > OR);
> > + igt_assert(props);
> > +
> > + /* Get the edid */
> > + for (i = 0; i < props->count_props && !edid_blob; i++) {
> > + drmModePropertyPtr prop =
> > + drmModeGetProperty(data->drm_fd,
> > + props->props[i]);
> > +
> > + igt_assert(prop);
> > +
> > + if (strcmp(prop->name, "EDID") == 0) {
> > + edid_blob = drmModeGetPropertyBlob(
> > + data->drm_fd, props->prop_values[i]);
> > + }
> > +
> > + drmModeFreeProperty(prop);
> > + }
> > +
> > + /* And make sure it matches to what we expected */
> > + edid_found = memcmp(edid, edid_blob->data, EDID_LENGTH) ==
> > 0;
> > +
> > + drmModeFreePropertyBlob(edid_blob);
> > + drmModeFreeObjectProperties(props);
> > + drmModeFreeConnector(connector);
> > +
> > + igt_assert(edid_found);
> > +}
> > +
> > +static void
> > +test_suspend_resume_hpd(data_t *data, struct chamelium_port *port,
> > + enum igt_suspend_state state,
> > + enum igt_suspend_test test)
> > +{
> > + int before, after;
> > + int delay = 7;
> > +
> > + igt_skip_without_suspend_support(state, test);
> > + reset_chamelium_state(data);
> > + igt_watch_hotplug();
> > +
> > + igt_set_autoresume_delay(15);
> > +
> > + /* Make sure we notice new connectors after resuming */
> > + before = connector_status_count(data, port->type,
> > DRM_MODE_CONNECTED);
> > + sleep(1);
> > + igt_flush_hotplugs();
> > +
> > + chamelium_async_hpd_pulse_start(port->id, false, delay);
> > + igt_system_suspend_autoresume(state, test);
> > + chamelium_async_hpd_pulse_finish();
> > +
> > + igt_assert(igt_hotplug_detected(HOTPLUG_TIMEOUT));
> > +
> > + reprobe_connectors(data, port->type);
> > + after = connector_status_count(data, port->type,
> > DRM_MODE_CONNECTED);
> > + igt_assert_lt(before, after);
> > +
> > + igt_flush_hotplugs();
> > +
> > + /* Now make sure we notice disconnected connectors after
> > resuming */
> > + before = connector_status_count(data, port->type,
> > DRM_MODE_DISCONNECTED);
> > +
> > + chamelium_async_hpd_pulse_start(port->id, true, delay);
> > + igt_system_suspend_autoresume(state, test);
> > + chamelium_async_hpd_pulse_finish();
> > +
> > + igt_assert(igt_hotplug_detected(HOTPLUG_TIMEOUT));
> > +
> > + reprobe_connectors(data, port->type);
> > + after = connector_status_count(data, port->type,
> > DRM_MODE_DISCONNECTED);
> > + igt_assert_lt(before, after);
> > +}
> > +
> > +static void
> > +test_suspend_resume_edid_change(data_t *data, struct
> > chamelium_port *port,
> > + enum igt_suspend_state state,
> > + enum igt_suspend_test test,
> > + int edid_id,
> > + int alt_edid_id)
> > +{
> > + igt_skip_without_suspend_support(state, test);
> > + reset_chamelium_state(data);
> > + igt_watch_hotplug();
> > +
> > + /* First plug in the port */
> > + chamelium_port_set_edid(port->id, edid_id);
> > + chamelium_plug(port->id);
> > +
> > + reprobe_connectors(data, port->type);
> > + sleep(1);
> > + igt_flush_hotplugs();
> > +
> > + /*
> > + * Change the edid before we suspend. On resume, the
> > machine should
> > + * notice the EDID change and fire a hotplug event.
> > + */
> > + chamelium_port_set_edid(port->id, alt_edid_id);
> > +
> > + igt_system_suspend_autoresume(state, test);
> > + igt_assert(igt_hotplug_detected(HOTPLUG_TIMEOUT));
> > +}
> > +
> > +static void
> > +test_display(data_t *data, struct chamelium_port *port)
> > +{
> > + igt_display_t display;
> > + igt_output_t *output;
> > + igt_plane_t *primary;
> > + struct igt_fb fb;
> > + drmModeRes *res;
> > + drmModeModeInfo *mode;
> > + int connector_found = false, fb_id;
> > +
> > + chamelium_plug(port->id);
> > + igt_assert(res = drmModeGetResources(data->drm_fd));
> > + kmstest_unset_all_crtcs(data->drm_fd, res);
> > +
> > + igt_display_init(&display, data->drm_fd);
> > +
> > + /* Find the active connector */
> > + for_each_connected_output(&display, output) {
> > + drmModeConnector *connector = output-
> > >config.connector;
> > +
> > + if (connector && connector->connector_type ==
> > port->type &&
> > + connector->connection == DRM_MODE_CONNECTED) {
> > + connector_found = true;
> > + break;
> > + }
> > + }
> > + igt_assert(connector_found);
> > +
> > + /* Setup the display */
> > + igt_output_set_pipe(output, PIPE_A);
> > + mode = igt_output_get_mode(output);
> > + primary = igt_output_get_plane(output, IGT_PLANE_PRIMARY);
> > + igt_assert(primary);
> > +
> > + fb_id = igt_create_pattern_fb(data->drm_fd,
> > + mode->hdisplay,
> > + mode->vdisplay,
> > + DRM_FORMAT_XRGB8888,
> > + LOCAL_DRM_FORMAT_MOD_NONE,
> > + &fb);
> > + igt_assert(fb_id > 0);
> > + igt_plane_set_fb(primary, &fb);
> > +
> > + igt_display_commit(&display);
> > +
> > + igt_assert(chamelium_port_wait_video_input_stable(port-
> > >id,
> > + HOTPLUG_
> > TIMEOUT));
> > +
> > + drmModeFreeResources(res);
> > + igt_display_fini(&display);
> > +}
> > +
> > +static void
> > +test_hpd_without_ddc(data_t *data, struct chamelium_port *port)
> > +{
> > + reset_chamelium_state(data);
> > + igt_watch_hotplug();
> > +
> > + /* Disable the DDC on the connector and make sure we still
> > get a
> > + * hotplug
> > + */
> > + chamelium_port_set_ddc_state(port->id, false);
> > + chamelium_plug(port->id);
> > +
> > + igt_assert(igt_hotplug_detected(HOTPLUG_TIMEOUT));
> > +}
> > +
> > +static void
> > +cache_connector_info(data_t *data)
> > +{
> > + drmModeRes *res = drmModeGetResources(data->drm_fd);
> > + drmModeConnector *connector;
> > + int i;
> > +
> > + igt_assert(res);
> > +
> > + data->connector_count = res->count_connectors;
> > + data->connectors = calloc(sizeof(struct connector_info),
> > + res->count_connectors);
> > + igt_assert(data->connectors);
> > +
> > + for (i = 0; i < res->count_connectors; i++) {
> > + connector = drmModeGetConnectorCurrent(data-
> > >drm_fd,
> > + res-
> > >connectors[i]);
> > + igt_assert(connector);
> > +
> > + data->connectors[i].id = connector->connector_id;
> > + data->connectors[i].type = connector-
> > >connector_type;
> > +
> > + drmModeFreeConnector(connector);
> > + }
> > +
> > + drmModeFreeResources(res);
> > +}
> > +
> > +#define for_each_port(p, port) \
> > + for (p = 0, port = &chamelium_ports[p]; \
> > + p < chamelium_port_count; \
> > + p++, port = &chamelium_ports[p]) \
> > +
> > +#define connector_subtest(name__, type__) \
> > + igt_subtest(name__) \
> > + for_each_port(p, port) \
> > + if (port->type == DRM_MODE_CONNECTOR_ ##
> > type__)
> > +
> > +#define define_common_connector_tests(type_str__,
> > type__) \
> > + connector_subtest(type_str__ "-hpd",
> > type__) \
> > + test_basic_hotplug(&data,
> > port); \
> > +
> > \
> > + connector_subtest(type_str__ "-edid-read", type__)
> > { \
> > + test_edid_read(&data, port,
> > edid_id, \
> > + igt_kms_get_base_edid());
> > \
> > + test_edid_read(&data, port,
> > alt_edid_id, \
> > + igt_kms_get_alt_edid());
> > \
> > + }
> > \
> > +
> > \
> > + connector_subtest(type_str__ "-hpd-after-suspend",
> > type__) \
> > + test_suspend_resume_hpd(&data,
> > port, \
> > + SUSPEND_STATE_MEM,
> > \
> > + SUSPEND_TEST_NONE);
> > \
> > +
> > \
> > + connector_subtest(type_str__ "-hpd-after-hibernate",
> > type__) \
> > + test_suspend_resume_hpd(&data,
> > port, \
> > + SUSPEND_STATE_DISK,
> > \
> > + SUSPEND_TEST_DEVICES);
> > \
> > +
> > \
> > + connector_subtest(type_str__ "-edid-change-during-
> > suspend", type__) \
> > + test_suspend_resume_edid_change(&data,
> > port, \
> > + SUSPEND_STATE_MEM,
> > \
> > + SUSPEND_TEST_NONE,
> > \
> > + edid_id,
> > alt_edid_id); \
> > +
> > \
> > + connector_subtest(type_str__ "-edid-change-during-
> > hibernate", type__) \
> > + test_suspend_resume_edid_change(&data,
> > port, \
> > + SUSPEND_STATE_DISK
> > , \
> > + SUSPEND_TEST_DEVIC
> > ES, \
> > + edid_id,
> > alt_edid_id); \
> > +
> > \
> > + connector_subtest(type_str__ "-display",
> > type__) \
> > + test_display(&data, port);
> > +
> > +static data_t data;
> > +
> > +igt_main
> > +{
> > + struct chamelium_port *port;
> > + int edid_id, alt_edid_id, p;
> > +
> > + igt_fixture {
> > + igt_require_chamelium();
> > + igt_skip_on_simulation();
> > +
> > + chamelium_init();
> > +
> > + edid_id =
> > chamelium_new_edid(igt_kms_get_base_edid());
> > + alt_edid_id =
> > chamelium_new_edid(igt_kms_get_alt_edid());
> > +
> > + data.drm_fd =
> > drm_open_driver_master(DRIVER_INTEL);
> > + cache_connector_info(&data);
> > +
> > + /* So fbcon doesn't try to reprobe things itself
> > */
> > + kmstest_set_vt_graphics_mode();
> > + }
> > +
> > + igt_subtest_group {
> > + igt_fixture {
> > + require_connector_present(
> > + &data,
> > DRM_MODE_CONNECTOR_DisplayPort);
> > + }
> > +
> > + define_common_connector_tests("dp", DisplayPort);
> > + }
> > +
> > + igt_subtest_group {
> > + igt_fixture {
> > + require_connector_present(
> > + &data, DRM_MODE_CONNECTOR_HDMIA);
> > + }
> > +
> > + define_common_connector_tests("hdmi", HDMIA);
> > + }
> > +
> > + igt_subtest_group {
> > + igt_fixture {
> > + require_connector_present(
> > + &data, DRM_MODE_CONNECTOR_VGA);
> > + }
> > +
> > + connector_subtest("vga-hpd", VGA)
> > + test_basic_hotplug(&data, port);
> > +
> > + connector_subtest("vga-edid-read", VGA) {
> > + test_edid_read(&data, port, edid_id,
> > + igt_kms_get_base_edid());
> > + test_edid_read(&data, port, alt_edid_id,
> > + igt_kms_get_alt_edid());
> > + }
> > +
> > + /* FIXME: Right now there isn't a way to do any
> > sort of delayed
> > + * psuedo-hotplug with VGA, so testing detection
> > after a
> > + * suspend/resume cycle isn't possible yet
> > + */
> > +
> > + connector_subtest("vga-hpd-without-ddc", VGA)
> > + test_hpd_without_ddc(&data, port);
> > +
> > + connector_subtest("vga-display", VGA)
> > + test_display(&data, port);
> > + }
> > +}
> > --
> > 2.7.4
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx@lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
--
Cheers,
Lyude
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply
* RE: [PATCH v5 3/3] clocksource: Add clockevent support to NPS400 driver
From: Noam Camus @ 2016-11-14 16:45 UTC (permalink / raw)
To: Daniel Lezcano
Cc: robh+dt@kernel.org, mark.rutland@arm.com, tglx@linutronix.de,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20161114154154.GF2016@mai>
> From: Daniel Lezcano [mailto:daniel.lezcano@linaro.org]
> Sent: Monday, November 14, 2016 5:42 PM
>> When you are saying "we have a framework" do you mean to some generic
>> framework in the kernel?
> Yes, IIRC it is regmap but I'm not sure.
Indeed regmap is a generic framework and it primarily meant for registers which can be mapped to our virtual/logical address space which is not the case here. For our auxiliary registers access we use dedicated instructions (lr/sr) and not LOAD/STORE like GCC produce.
It is possible to use such regmap but this driver will be filled with all regmap handling just to hide couple of lines. This will not serve this driver readability well.
>I think there is something I am missing with this HW scheduling thing. Why are these hw_schd_save/hw_schd_restore functions needed to be called from the timer driver ? Regarding the explanation, the HW scheduling can happen everywhere at any time, not only in the timer code but this one is the only one which need the hw_schd_save/hw_schd_restore calls, why ?
I use them not just here they are also serve to protect our L1 cache and TLB which are also shared within same core. You can't see this yet since patch are not still push to arch/arc tree.
>Why,
>spin_lock(&lock);
>write_aux_reg(...)
>spin_unlock(&lock);
>can't work ?
Because I can't use spinlock in interrupt context (I call to nps_clkevent_rm_thread() in irq_handler).
>IIUC, there can be more than 16 cpus/threads, so calling hw_schd_save / hw_schd_restore will disable the HW scheduling for the entire system while one cpu is processing something with these couple of registers, no ?
NO, HW scheduling will be disabled only for this specific core, all other cores will not be affected since they got their own private registers.
...
>> >And tick_resume. Perhaps, that is the reason why NO_HZ hangs.
>> What NO_HZ hang are you referring to in this case? How calling
>> nps_clkevent_rm_thread() explain such hang? Anyway I agree, and will
>> add
>> nps_clkevent_rm_thread() to tick_resume.
>Actually I meant NOHZ_FULL.
Still got no clue what hang we are talking about here!
Note:
I looked at arch/tile timer driver again and noticed that I can work without periodic mode. This is exactly what I need here (pure oneshot mode).
With this fact I can define
Static void nps_clkevent_rm_thread(void)
Static void nps_clkevent_add_thread(void)
Also HW scheduling save/restore is only used in *rm_thread/*add_thread since I can now remove nps_clkevent_set_periodic() and nps_clkevent_timer_event_setup().
This way clockevent driver seem much simpler and it is clearer to understanding.
I hope that this approach of not having periodic mode is acceptable.
-Noam
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.