Re: [git pull] drm fixes for 5.11-rc1

2020-12-29 Thread Rodrigo Siqueira
Hi,

This patch should fix the issue:

 https://patchwork.freedesktop.org/patch/410754/?series=85303=1

Thanks

On 12/29, R, Bindu wrote:
>[AMD Official Use Only - Internal Distribution Only]
> 
>++Siqueira.
>Regards,
>Bindu
> 
>══
> 
>From: Alex Deucher 
>Sent: Tuesday, December 29, 2020 10:07 AM
>To: Linus Torvalds ; Wentland, Harry
>; Kazlauskas, Nicholas
>; Wu, Hersen 
>Cc: Dave Airlie ; Pavic, Josip ;
>R, Bindu ; Deucher, Alexander
>; Daniel Vetter ; LKML
>; dri-devel
>
>Subject: Re: [git pull] drm fixes for 5.11-rc1
> 
>On Thu, Dec 24, 2020 at 5:28 PM Linus Torvalds
> wrote:
>>
>> On Wed, Dec 23, 2020 at 6:29 PM Dave Airlie  wrote:
>> >
>> > Xmas eve pull request present. Just some fixes that trickled in this
>> > past week. Mostly amdgpu fixes, with a dma-buf/mips build fix and some
>> > misc komeda fixes.
>>
>> Well, I already pulled and pushed out my merge, but only noticed
>> afterwards that clang complains about this, and I think it's a real
>> bug:
>>
>>   drivers/gpu/drm/amd/amdgpu/../display/dc/dcn10/dcn10_mpc.c:475:6:
>warning:
>>  variable 'val' is used uninitialized whenever 'if' condition is
>> false [-Wsometimes-uninitialized]
>>
>> and it sure is true: the code literally does
>>
>> uint32_t val;
>>
>> if (opp_id < MAX_OPP && REG(MUX[opp_id]))
>> REG_GET(MUX[opp_id], MPC_OUT_MUX, );
>>
>> return val;
>>
>> so clearly 'val' isn't initialized if that if-statement isn't true.
>>
>> I assume 'opp_id' is always presumed to be valid, but that code really
>> is disgusting.
>>
>> Just make it return 0 (or whatever) for invalid, possibly together
>> with a WARN_ON_ONCE(). Ok?
> 
>Harry, Nick, Hersen,
> 
>Can you take a look?
> 
>Thanks,
> 
>Alex
> 
>>
>>  Linus
>> ___
>> dri-devel mailing list
>> dri-de...@lists.freedesktop.org
>>
>
> [1]https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Fdri-develdata=04%7C01%7Cbindu.r%40amd.com%7Cae8f547c9287426b9b9408d8ac0b7b73%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637448512618562550%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=4gcQRS3HI4u1UEWu35Ze1w5CLWmAof5nouCFQoKEQD0%3Dreserved=0
> 
> References
> 
>Visible links
>1. 
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Fdri-develdata=04%7C01%7Cbindu.r%40amd.com%7Cae8f547c9287426b9b9408d8ac0b7b73%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637448512618562550%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=4gcQRS3HI4u1UEWu35Ze1w5CLWmAof5nouCFQoKEQD0%3Dreserved=0

-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


[PATCH] drm/amd/display: Initialize stack variable

2020-12-29 Thread Rodrigo Siqueira
From: Wesley Chalmers 

The stack variable "val" is potentially unpopulate it, so initialize it
with the value 0xf (indicating an invalid mux).

Cc: Alex Deucher 
Cc: Alex Deucher 
Cc: Harry Wentland 
Cc: Nicholas Kazlauskas 
Cc: Hersen Wu 
Cc: Dave Airlie 
Cc: Josip Pavic 
Cc: Bindu Ramamurthy 
Signed-off-by: Wesley Chalmers 
Reviewed-by: Martin Leung 
Reviewed-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c
index a46cb20596fe..b096011acb49 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_mpc.c
@@ -470,7 +470,7 @@ void mpc1_cursor_lock(struct mpc *mpc, int opp_id, bool 
lock)
 unsigned int mpc1_get_mpc_out_mux(struct mpc *mpc, int opp_id)
 {
struct dcn10_mpc *mpc10 = TO_DCN10_MPC(mpc);
-   uint32_t val;
+   uint32_t val = 0xf;
 
if (opp_id < MAX_OPP && REG(MUX[opp_id]))
REG_GET(MUX[opp_id], MPC_OUT_MUX, );
-- 
2.30.0.rc2



Re: 8353d30e747f ("drm/amd/display: disable stream if pixel clock changed with link active")

2020-12-15 Thread Rodrigo Siqueira
On 12/15, Borislav Petkov wrote:
> On Tue, Dec 15, 2020 at 12:04:23PM -0500, Alex Deucher wrote:
> > That patch trivially backports to 5.10.  See attached backported
> > patch.  @Borislav Petkov does the attached patch fix 5.10 for you?
> 
> Yes, thanks.
> 
> Reported-and-tested-by: Borislav Petkov 

Thanks for reporting this issue and test the fix.
 
> -- 
> Regards/Gruss,
> Boris.
> 
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpeople.kernel.org%2Ftglx%2Fnotes-about-netiquettedata=04%7C01%7CRodrigo.Siqueira%40amd.com%7C08fad887df0d48130c5008d8a12943dc%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637436546148511884%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=RSzl0BfkNzJy%2BJwphMSgwX1u9cehN%2FW2fTML3VnfTQY%3Dreserved=0

-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


Re: 8353d30e747f ("drm/amd/display: disable stream if pixel clock changed with link active")

2020-12-15 Thread Rodrigo Siqueira
On 12/15, Alex Deucher wrote:
> On Tue, Dec 15, 2020 at 11:07 AM Rodrigo Siqueira
>  wrote:
> >
> > Hi,
> >
> > Could you try on Alex's repo?
> >
> >  git://people.freedesktop.org/~agd5f/linux
> >  branch: amd-staging-drm-next
> >
> > My patch should apply without any issue on top of this branch.
> 
> Can you help me identify what patches we need to backport to 5.10?

If we have this patch in 5.10:

 drm/amd/display: disable stream if pixel clock changed with link active

We need to backport:

 1. drm/amd/display: Fix module load hangs when connected to an eDP (for
DCN)
 2. drm/amd/display: Add get_dig_frontend implementation for DCEx (for
DCEx - we still need Boris feedback)


> Depending on the patches, it might be easier to just revert this for
> 5.10 and apply the proper fix for 5.11.

I like this approach; we can apply the proper fix on 5.11.

Thanks
 
> Alex
> 
> 
> >
> > Thanks
> >
> > On 12/15, Borislav Petkov wrote:
> > > On Tue, Dec 15, 2020 at 10:47:03AM -0500, Rodrigo Siqueira wrote:
> > > > Hi Boris,
> > > >
> > > > Could you check if your branch has this commit:
> > > >
> > > >  drm/amd/display: Fix module load hangs when connected to an eDP
> > > >
> > > > If so, could you try this patch:
> > > >
> > > >  
> > > > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.freedesktop.org%2Fseries%2F84965%2Fdata=04%7C01%7CRodrigo.Siqueira%40amd.com%7C3b8b84a3815d4a3cc67e08d8a1152189%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637436459421073301%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=mcdJ1E3tJc%2FK%2Bnf2phU2CFDQ2wp5zrMcRbxdLxQdo3I%3Dreserved=0
> > >
> > > So I did a bisection between
> > >
> > > git bisect start
> > > # bad: [3650b228f83adda7e5ee532e2b90429c03f7b9ec] Linux 5.10-rc1
> > > git bisect bad 3650b228f83adda7e5ee532e2b90429c03f7b9ec
> > > # good: [bbf5c979011a099af5dc76498918ed7df445635b] Linux 5.9
> > >
> > > and the patch in $Subject came in in 5.10-rc1.
> > >
> > > I can test any tree you want me to so just tell me on which tree to
> > > apply this patch and I'll run it.
> > >
> > > In any case, it doesn't apply on v5.10 though:
> > >
> > > $ test-apply.sh /tmp/rodrigo.siqueira
> > > checking file drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
> > > Hunk #1 FAILED at 120
> > >
> > > You can push a tree of yours somewhere which I can try directly,
> > > alternatively.
> > >
> > > Lemme know.
> > >
> > > Thx.
> > >
> > > --
> > > Regards/Gruss,
> > > Boris.
> > >
> > > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpeople.kernel.org%2Ftglx%2Fnotes-about-netiquettedata=04%7C01%7CRodrigo.Siqueira%40amd.com%7C3b8b84a3815d4a3cc67e08d8a1152189%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637436459421073301%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=bHJQuQqFRTA2SU6Va9gt4lvnogZUeYRujeQj4fIXBsE%3Dreserved=0
> >
> > --
> > Rodrigo Siqueira
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fsiqueira.tech%2Fdata=04%7C01%7CRodrigo.Siqueira%40amd.com%7C3b8b84a3815d4a3cc67e08d8a1152189%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637436459421073301%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=bZvusCFfCrWSitpFa%2BmWyg%2BAbJ04ybnlUMQiEB3m5OY%3Dreserved=0
> > ___
> > amd-gfx mailing list
> > amd-...@lists.freedesktop.org
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfxdata=04%7C01%7CRodrigo.Siqueira%40amd.com%7C3b8b84a3815d4a3cc67e08d8a1152189%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637436459421083297%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=3K1EuoePhkVVVT7JvPUeKuJW5RIGiHC9LNoqI9ZiTHc%3Dreserved=0

-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


Re: 8353d30e747f ("drm/amd/display: disable stream if pixel clock changed with link active")

2020-12-15 Thread Rodrigo Siqueira
Hi,

Could you try on Alex's repo?

 git://people.freedesktop.org/~agd5f/linux
 branch: amd-staging-drm-next

My patch should apply without any issue on top of this branch.

Thanks

On 12/15, Borislav Petkov wrote:
> On Tue, Dec 15, 2020 at 10:47:03AM -0500, Rodrigo Siqueira wrote:
> > Hi Boris,
> > 
> > Could you check if your branch has this commit:
> > 
> >  drm/amd/display: Fix module load hangs when connected to an eDP
> > 
> > If so, could you try this patch:
> > 
> >  
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.freedesktop.org%2Fseries%2F84965%2Fdata=04%7C01%7CRodrigo.Siqueira%40amd.com%7C1f7ff595746543f597a708d8a111fbdd%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637436445910587407%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=PESE3uBZeNjdWtIFRP6l07AyfhASpXCfaZa03l%2FFi6s%3Dreserved=0
> 
> So I did a bisection between
> 
> git bisect start
> # bad: [3650b228f83adda7e5ee532e2b90429c03f7b9ec] Linux 5.10-rc1
> git bisect bad 3650b228f83adda7e5ee532e2b90429c03f7b9ec
> # good: [bbf5c979011a099af5dc76498918ed7df445635b] Linux 5.9
> 
> and the patch in $Subject came in in 5.10-rc1.
> 
> I can test any tree you want me to so just tell me on which tree to
> apply this patch and I'll run it.
> 
> In any case, it doesn't apply on v5.10 though:
> 
> $ test-apply.sh /tmp/rodrigo.siqueira 
> checking file drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
> Hunk #1 FAILED at 120
> 
> You can push a tree of yours somewhere which I can try directly,
> alternatively.
> 
> Lemme know.
> 
> Thx.
> 
> -- 
> Regards/Gruss,
> Boris.
> 
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpeople.kernel.org%2Ftglx%2Fnotes-about-netiquettedata=04%7C01%7CRodrigo.Siqueira%40amd.com%7C1f7ff595746543f597a708d8a111fbdd%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637436445910587407%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=kiGm0%2B2d2nXiEwUs0omOYv3ZtyfwTtoD9OhrT59Dv5c%3Dreserved=0

-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


Re: 8353d30e747f ("drm/amd/display: disable stream if pixel clock changed with link active")

2020-12-15 Thread Rodrigo Siqueira
14745600
> > [2.206654] [drm] fb depth is 24
> > [2.206760] [drm]pitch is 10240
> > [2.207123] fbcon: amdgpudrmfb (fb0) is primary device
> > [2.301263] amdgpu :00:01.0: [drm] fb0: amdgpudrmfb frame buffer 
> > device
> > [2.320735] [drm] Initialized amdgpu 3.40.0 20150101 for :00:01.0 on 
> > minor 0
> >
> >
> > --
> > Regards/Gruss,
> > Boris.
> >
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpeople.kernel.org%2Ftglx%2Fnotes-about-netiquettedata=04%7C01%7CRodrigo.Siqueira%40amd.com%7C36709b101b6e4c353e7e08d8a07a1d89%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637435793657547591%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=Cpb2l3OjKBeFwx%2FHIf%2F0d%2BSFiJL46p7Bct3JAIThSZ8%3Dreserved=0
> > ___
> > amd-gfx mailing list
> > amd-...@lists.freedesktop.org
> > https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.freedesktop.org%2Fmailman%2Flistinfo%2Famd-gfxdata=04%7C01%7CRodrigo.Siqueira%40amd.com%7C36709b101b6e4c353e7e08d8a07a1d89%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637435793657547591%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=XdoPAac6FCjulOvtOsdzO4rh5Qd9wwNIi%2B%2F5lvkaUoI%3Dreserved=0

-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


Re: 8353d30e747f ("drm/amd/display: disable stream if pixel clock changed with link active")

2020-12-15 Thread Rodrigo Siqueira
Hi Boris,

Could you check if your branch has this commit:

 drm/amd/display: Fix module load hangs when connected to an eDP

If so, could you try this patch:

 https://patchwork.freedesktop.org/series/84965/

Thanks

On 12/11, Borislav Petkov wrote:
> Hi,
> 
> patch in $Subject breaks booting on a laptop here, GPU details are
> below. The machine stops booting right when it attempts to switch modes
> during boot, to a higher mode than the default VGA one. Machine doesn't
> ping and is otherwise unresponsive so that a hard reset is the only
> thing that helps.
> 
> Reverting that patch ontop of -rc7 fixes it and the machine boots just fine.
> 
> Thx.
> 
> [1.628086] ata1.00: supports DRM functions and may not be fully accessible
> [1.632050] ata1.00: supports DRM functions and may not be fully accessible
> [1.895818] [drm] amdgpu kernel modesetting enabled.
> [1.897628] [drm] initializing kernel modesetting (CARRIZO 0x1002:0x9874 
> 0x103C:0x807E 0xC4).
> [1.898256] [drm] register mmio base: 0xD0C0
> [1.898422] [drm] register mmio size: 262144
> [1.898583] [drm] add ip block number 0 
> [1.898759] [drm] add ip block number 1 
> [1.898931] [drm] add ip block number 2 
> [1.899082] [drm] add ip block number 3 
> [1.899241] [drm] add ip block number 4 
> [1.899439] [drm] add ip block number 5 
> [1.899573] [drm] add ip block number 6 
> [1.899693] [drm] add ip block number 7 
> [1.899827] [drm] add ip block number 8 
> [1.911458] [drm] BIOS signature incorrect 5b 7
> [1.912551] [drm] UVD is enabled in physical mode
> [1.912707] [drm] VCE enabled in physical mode
> [1.912921] [drm] vm size is 64 GB, 2 levels, block size is 10-bit, 
> fragment size is 9-bit
> [1.913837] [drm] Detected VRAM RAM=512M, BAR=512M
> [1.913998] [drm] RAM width 128bits UNKNOWN
> [1.915149] [drm] amdgpu: 512M of VRAM memory ready
> [1.915306] [drm] amdgpu: 3072M of GTT memory ready.
> [1.915468] [drm] GART: num cpu pages 262144, num gpu pages 262144
> [1.916139] [drm] PCIE GART of 1024M enabled (table at 0x00F40090).
> [1.918733] [drm] Found UVD firmware Version: 1.91 Family ID: 11
> [1.918950] [drm] UVD ENC is disabled
> [1.919680] [drm] Found VCE firmware Version: 52.4 Binary ID: 3
> [1.925963] [drm] DM_PPLIB: values for Engine clock
> [1.926106] [drm] DM_PPLIB:   30
> [1.926205] [drm] DM_PPLIB:   36
> [1.926304] [drm] DM_PPLIB:   423530
> [1.926404] [drm] DM_PPLIB:   514290
> [1.926516] [drm] DM_PPLIB:   626090
> [1.926629] [drm] DM_PPLIB:   72
> [1.926743] [drm] DM_PPLIB: Validation clocks:
> [1.926952] [drm] DM_PPLIB:engine_max_clock: 72000
> [1.927117] [drm] DM_PPLIB:memory_max_clock: 8
> [1.927281] [drm] DM_PPLIB:level   : 8
> [1.927435] [drm] DM_PPLIB: values for Display clock
> [1.927594] [drm] DM_PPLIB:   30
> [1.927708] [drm] DM_PPLIB:   40
> [1.927822] [drm] DM_PPLIB:   496560
> [1.927936] [drm] DM_PPLIB:   626090
> [1.928048] [drm] DM_PPLIB:   685720
> [1.928161] [drm] DM_PPLIB:   757900
> [1.928275] [drm] DM_PPLIB: Validation clocks:
> [1.928419] [drm] DM_PPLIB:engine_max_clock: 72000
> [1.928584] [drm] DM_PPLIB:memory_max_clock: 8
> [1.928748] [drm] DM_PPLIB:level   : 8
> [1.928901] [drm] DM_PPLIB: values for Memory clock
> [1.929058] [drm] DM_PPLIB:   333000
> [1.929172] [drm] DM_PPLIB:   80
> [1.929403] [drm] DM_PPLIB: Validation clocks:
> [1.929549] [drm] DM_PPLIB:engine_max_clock: 72000
> [1.929716] [drm] DM_PPLIB:memory_max_clock: 8
> [1.929919] [drm] DM_PPLIB:level   : 8
> [1.930148] [drm] Display Core initialized with v3.2.104!
> [2.003938] [drm] UVD initialized successfully.
> [2.204023] [drm] VCE initialized successfully.
> [2.206228] [drm] fb mappable at 0xA0EE4000
> [2.206375] [drm] vram apper at 0xA000
> [2.206514] [drm] size 14745600
> [2.206654] [drm] fb depth is 24
> [2.206760] [drm]pitch is 10240
> [2.207123] fbcon: amdgpudrmfb (fb0) is primary device
> [2.301263] amdgpu :00:01.0: [drm] fb0: amdgpudrmfb frame buffer device
> [2.320735] [drm] Initialized amdgpu 3.40.0 20150101 for :00:01.0 on 
> minor 0
> 
> 
> -- 
> Regards/Gruss,
> Boris.
> 
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpeople.kernel.org%2Ftglx%2Fnotes-about-netiquettedata=04%7C01%7CRodrigo.Siqueira%40amd.com%7C9c55e386aad44fc9531608d89ded4100%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637432989642100749%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000sdata=WVk3xRmBn3A75KLQKaBG7FzktecRG6GS7rXJE7bEPBg%3Dreserved=0

-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


[PATCH v2 0/4] Enlarge tracepoints in the display component

2020-09-11 Thread Rodrigo Siqueira
Debug issues related to display can be a challenge due to the complexity
around this topic and different source of information might help in this
process. We already have support for tracepoints inside the display
component, i.e., we have the basic functionalities available and we just
need to expand it in order to make it more valuable for debugging. For
this reason, this patchset reworks part of the current tracepoint
options and add different sets of tracing inside amdgpu_dm, display
core, and DCN10. The first patch of this series just rework part of the
current tracepoints and the last set of patches introduces new
tracepoints.

This first patchset version is functional. Please, let me know what I
can improve in the current version but also let me know what kind of
tracepoint I can add for the next version. 

Finally, I want to highlight that this work is based on a set of patches
originally made by Nicholas Kazlauskas.

Change in V2:
- I added another patch for capturing the clock state for different display
  architecture.

Rodrigo Siqueira (4):
  drm/amd/display: Rework registers tracepoint
  drm/amd/display: Add tracepoint for amdgpu_dm
  drm/amd/display: Add pipe_state tracepoint
  drm/amd/display: Add tracepoint for capturing clocks state

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  17 +
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 712 +-
 .../dc/clk_mgr/dce112/dce112_clk_mgr.c|   5 +
 .../display/dc/clk_mgr/dcn10/rv1_clk_mgr.c|   4 +
 .../display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c  |   4 +
 .../amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c |   4 +
 .../display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c  |   4 +
 drivers/gpu/drm/amd/display/dc/core/dc.c  |  11 +
 .../gpu/drm/amd/display/dc/dce/dce_clk_mgr.c  |   5 +
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c |  17 +-
 10 files changed, 747 insertions(+), 36 deletions(-)

-- 
2.28.0



[PATCH v2 2/4] drm/amd/display: Add tracepoint for amdgpu_dm

2020-09-11 Thread Rodrigo Siqueira
Debug amdgpu_dm could be a complicated task, therefore, this commit adds
tracepoints in some convenient functions such as plane and connector
check inside amdgpu_dm.

Co-developed-by: Nicholas Kazlauskas 
Signed-off-by: Nicholas Kazlauskas 
Signed-off-by: Rodrigo Siqueira 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  17 ++
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 287 ++
 2 files changed, 304 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index cb624ee70545..552ca67c2a71 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5424,6 +5424,8 @@ amdgpu_dm_connector_atomic_check(struct drm_connector 
*conn,
struct drm_crtc_state *new_crtc_state;
int ret;
 
+   trace_amdgpu_dm_connector_atomic_check(new_con_state);
+
if (!crtc)
return 0;
 
@@ -5542,6 +5544,8 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc 
*crtc,
struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state);
int ret = -EINVAL;
 
+   trace_amdgpu_dm_crtc_atomic_check(state);
+
dm_update_crtc_active_planes(crtc, state);
 
if (unlikely(!dm_crtc_state->stream &&
@@ -5916,6 +5920,8 @@ static int dm_plane_atomic_check(struct drm_plane *plane,
struct drm_crtc_state *new_crtc_state;
int ret;
 
+   trace_amdgpu_dm_plane_atomic_check(state);
+
dm_plane_state = to_dm_plane_state(state);
 
if (!dm_plane_state->dc_state)
@@ -5956,6 +5962,8 @@ static void dm_plane_atomic_async_update(struct drm_plane 
*plane,
struct drm_plane_state *old_state =
drm_atomic_get_old_plane_state(new_state->state, plane);
 
+   trace_amdgpu_dm_atomic_update_cursor(new_state);
+
swap(plane->state->fb, new_state->fb);
 
plane->state->src_x = new_state->src_x;
@@ -7546,6 +7554,8 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
int crtc_disable_count = 0;
bool mode_set_reset_required = false;
 
+   trace_amdgpu_dm_atomic_commit_tail_begin(state);
+
drm_atomic_helper_update_legacy_modeset_state(dev, state);
 
dm_state = dm_atomic_get_new_state(state);
@@ -8616,6 +8626,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
int ret, i;
bool lock_and_validation_needed = false;
 
+   trace_amdgpu_dm_atomic_check_begin(state);
+
ret = drm_atomic_helper_check_modeset(dev, state);
if (ret)
goto fail;
@@ -8912,6 +8924,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 
/* Must be success */
WARN_ON(ret);
+
+   trace_amdgpu_dm_atomic_check_finish(state, ret);
+
return ret;
 
 fail:
@@ -8922,6 +8937,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
else
DRM_DEBUG_DRIVER("Atomic check failed with err: %d \n", ret);
 
+   trace_amdgpu_dm_atomic_check_finish(state, ret);
+
return ret;
 }
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index dd34e11b1079..5fb4c4a5c349 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -30,6 +30,12 @@
 #define _AMDGPU_DM_TRACE_H_
 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 DECLARE_EVENT_CLASS(amdgpu_dc_reg_template,
TP_PROTO(unsigned long *count, uint32_t reg, uint32_t 
value),
@@ -89,6 +95,287 @@ TRACE_EVENT(amdgpu_dc_performance,
(unsigned long)__entry->write_delta,
(unsigned long)__entry->writes)
 );
+
+TRACE_EVENT(amdgpu_dm_connector_atomic_check,
+   TP_PROTO(const struct drm_connector_state *state),
+   TP_ARGS(state),
+
+   TP_STRUCT__entry(
+__field(uint32_t, conn_id)
+__field(const struct drm_connector_state *, 
conn_state)
+__field(const struct drm_atomic_state *, state)
+__field(const struct drm_crtc_commit *, commit)
+__field(uint32_t, crtc_id)
+__field(uint32_t, best_encoder_id)
+__field(enum drm_link_status, link_status)
+__field(bool, self_refresh_aware)
+__field(enum hdmi_picture_aspect, 
picture_aspect_ratio)
+__field(unsigned int, content_type)
+__field(unsigned int, hdcp_content_type)
+__field(unsigned int, content_protection)
+__field(unsigned int, scaling_mode)
+

[PATCH v2 3/4] drm/amd/display: Add pipe_state tracepoint

2020-09-11 Thread Rodrigo Siqueira
This commit introduces a trace mechanism for struct pipe_ctx by adding a
middle layer struct in the amdgpu_dm_trace.h for capturing the most
important data from struct pipe_ctx and showing its data via tracepoint.
This tracepoint was added to dc.c and dcn10_hw_sequencer, however, it
can be added to other DCN architecture.

Co-developed-by: Nicholas Kazlauskas 
Signed-off-by: Nicholas Kazlauskas 
Signed-off-by: Rodrigo Siqueira 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 172 ++
 drivers/gpu/drm/amd/display/dc/core/dc.c  |  11 ++
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c |  17 +-
 3 files changed, 195 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index 5fb4c4a5c349..53f62506e17c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -376,6 +376,178 @@ TRACE_EVENT(amdgpu_dm_atomic_check_finish,
  __entry->async_update, __entry->allow_modeset)
 );
 
+#ifndef _AMDGPU_DM_TRACE_STRUCTS_DEFINED_
+#define _AMDGPU_DM_TRACE_STRUCTS_DEFINED_
+
+struct amdgpu_dm_trace_pipe_state {
+   int pipe_idx;
+   const void *stream;
+   int stream_w;
+   int stream_h;
+   int dst_x;
+   int dst_y;
+   int dst_w;
+   int dst_h;
+   int src_x;
+   int src_y;
+   int src_w;
+   int src_h;
+   int clip_x;
+   int clip_y;
+   int clip_w;
+   int clip_h;
+   int recout_x;
+   int recout_y;
+   int recout_w;
+   int recout_h;
+   int viewport_x;
+   int viewport_y;
+   int viewport_w;
+   int viewport_h;
+   int flip_immediate;
+   int surface_pitch;
+   int format;
+   int swizzle;
+   unsigned int update_flags;
+};
+
+#define fill_out_trace_pipe_state(trace_pipe_state, pipe_ctx) \
+   do { \
+   trace_pipe_state.pipe_idx   = (pipe_ctx)->pipe_idx; \
+   trace_pipe_state.stream = (pipe_ctx)->stream; \
+   trace_pipe_state.stream_w   = 
(pipe_ctx)->stream->timing.h_addressable; \
+   trace_pipe_state.stream_h   = 
(pipe_ctx)->stream->timing.v_addressable; \
+   trace_pipe_state.dst_x  = 
(pipe_ctx)->plane_state->dst_rect.x; \
+   trace_pipe_state.dst_y  = 
(pipe_ctx)->plane_state->dst_rect.y; \
+   trace_pipe_state.dst_w  = 
(pipe_ctx)->plane_state->dst_rect.width; \
+   trace_pipe_state.dst_h  = 
(pipe_ctx)->plane_state->dst_rect.height; \
+   trace_pipe_state.src_x  = 
(pipe_ctx)->plane_state->src_rect.x; \
+   trace_pipe_state.src_y  = 
(pipe_ctx)->plane_state->src_rect.y; \
+   trace_pipe_state.src_w  = 
(pipe_ctx)->plane_state->src_rect.width; \
+   trace_pipe_state.src_h  = 
(pipe_ctx)->plane_state->src_rect.height; \
+   trace_pipe_state.clip_x = 
(pipe_ctx)->plane_state->clip_rect.x; \
+   trace_pipe_state.clip_y = 
(pipe_ctx)->plane_state->clip_rect.y; \
+   trace_pipe_state.clip_w = 
(pipe_ctx)->plane_state->clip_rect.width; \
+   trace_pipe_state.clip_h = 
(pipe_ctx)->plane_state->clip_rect.height; \
+   trace_pipe_state.recout_x   = 
(pipe_ctx)->plane_res.scl_data.recout.x; \
+   trace_pipe_state.recout_y   = 
(pipe_ctx)->plane_res.scl_data.recout.y; \
+   trace_pipe_state.recout_w   = 
(pipe_ctx)->plane_res.scl_data.recout.width; \
+   trace_pipe_state.recout_h   = 
(pipe_ctx)->plane_res.scl_data.recout.height; \
+   trace_pipe_state.viewport_x = 
(pipe_ctx)->plane_res.scl_data.viewport.x; \
+   trace_pipe_state.viewport_y = 
(pipe_ctx)->plane_res.scl_data.viewport.y; \
+   trace_pipe_state.viewport_w = 
(pipe_ctx)->plane_res.scl_data.viewport.width; \
+   trace_pipe_state.viewport_h = 
(pipe_ctx)->plane_res.scl_data.viewport.height; \
+   trace_pipe_state.flip_immediate = 
(pipe_ctx)->plane_state->flip_immediate; \
+   trace_pipe_state.surface_pitch  = 
(pipe_ctx)->plane_state->plane_size.surface_pitch; \
+   trace_pipe_state.format = 
(pipe_ctx)->plane_state->format; \
+   trace_pipe_state.swizzle= 
(pipe_ctx)->plane_state->tiling_info.gfx9.swizzle; \
+   trace_pipe_state.update_flags   = (pipe_ctx)->update_flags.raw; 
\
+   } while (0)
+
+#endif /* _AMDGPU_DM_TRACE_STRUCTS_DEFINED_ */
+
+TRACE_EVENT(amdgpu_dm_dc_pipe_state,
+   TP_PROTO(const struct amdgpu_dm_trace_pipe_state *pipe_state),
+ 

[PATCH v2 1/4] drm/amd/display: Rework registers tracepoint

2020-09-11 Thread Rodrigo Siqueira
amdgpu_dc_rreg and amdgpu_dc_wreg are very similar, for this reason,
this commits abstract these two events by using DECLARE_EVENT_CLASS and
create an instance of it for each one of these events.

Signed-off-by: Rodrigo Siqueira 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 55 ---
 1 file changed, 24 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index d898981684d5..dd34e11b1079 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -31,40 +31,33 @@
 
 #include 
 
-TRACE_EVENT(amdgpu_dc_rreg,
-   TP_PROTO(unsigned long *read_count, uint32_t reg, uint32_t value),
-   TP_ARGS(read_count, reg, value),
-   TP_STRUCT__entry(
-   __field(uint32_t, reg)
-   __field(uint32_t, value)
-   ),
-   TP_fast_assign(
-   __entry->reg = reg;
-   __entry->value = value;
-   *read_count = *read_count + 1;
-   ),
-   TP_printk("reg=0x%08lx, value=0x%08lx",
-   (unsigned long)__entry->reg,
-   (unsigned long)__entry->value)
-);
+DECLARE_EVENT_CLASS(amdgpu_dc_reg_template,
+   TP_PROTO(unsigned long *count, uint32_t reg, uint32_t 
value),
+   TP_ARGS(count, reg, value),
 
-TRACE_EVENT(amdgpu_dc_wreg,
-   TP_PROTO(unsigned long *write_count, uint32_t reg, uint32_t value),
-   TP_ARGS(write_count, reg, value),
-   TP_STRUCT__entry(
-   __field(uint32_t, reg)
-   __field(uint32_t, value)
-   ),
-   TP_fast_assign(
-   __entry->reg = reg;
-   __entry->value = value;
-   *write_count = *write_count + 1;
-   ),
-   TP_printk("reg=0x%08lx, value=0x%08lx",
-   (unsigned long)__entry->reg,
-   (unsigned long)__entry->value)
+   TP_STRUCT__entry(
+__field(uint32_t, reg)
+__field(uint32_t, value)
+   ),
+
+   TP_fast_assign(
+  __entry->reg = reg;
+  __entry->value = value;
+  *count = *count + 1;
+   ),
+
+   TP_printk("reg=0x%08lx, value=0x%08lx",
+ (unsigned long)__entry->reg,
+ (unsigned long)__entry->value)
 );
 
+DEFINE_EVENT(amdgpu_dc_reg_template, amdgpu_dc_rreg,
+TP_PROTO(unsigned long *count, uint32_t reg, uint32_t value),
+TP_ARGS(count, reg, value));
+
+DEFINE_EVENT(amdgpu_dc_reg_template, amdgpu_dc_wreg,
+TP_PROTO(unsigned long *count, uint32_t reg, uint32_t value),
+TP_ARGS(count, reg, value));
 
 TRACE_EVENT(amdgpu_dc_performance,
TP_PROTO(unsigned long read_count, unsigned long write_count,
-- 
2.28.0



[PATCH v2 4/4] drm/amd/display: Add tracepoint for capturing clocks state

2020-09-11 Thread Rodrigo Siqueira
The clock state update is the source of many problems, and capturing
this sort of information helps debug. This commit introduces tracepoints
for capturing clock values and also add traces in DCE, DCN1, DCN2x, and
DCN3.

Co-developed-by: Nicholas Kazlauskas 
Signed-off-by: Nicholas Kazlauskas 
Signed-off-by: Rodrigo Siqueira 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 198 ++
 .../dc/clk_mgr/dce112/dce112_clk_mgr.c|   5 +
 .../display/dc/clk_mgr/dcn10/rv1_clk_mgr.c|   4 +
 .../display/dc/clk_mgr/dcn20/dcn20_clk_mgr.c  |   4 +
 .../amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c |   4 +
 .../display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c  |   4 +
 .../gpu/drm/amd/display/dc/dce/dce_clk_mgr.c  |   5 +
 7 files changed, 224 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index 53f62506e17c..fb22b233224a 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -411,6 +411,42 @@ struct amdgpu_dm_trace_pipe_state {
unsigned int update_flags;
 };
 
+struct amdgpu_dm_trace_dc_clocks_state {
+   int dispclk_khz;
+   int dppclk_khz;
+   int disp_dpp_voltage_level_khz;
+   int dcfclk_khz;
+   int socclk_khz;
+   int dcfclk_deep_sleep_khz;
+   int fclk_khz;
+   int phyclk_khz;
+   int dramclk_khz;
+   bool p_state_change_support;
+   int pwr_state;
+   bool prev_p_state_change_support;
+   int dtm_level;
+   int max_supported_dppclk_khz;
+   int max_supported_dispclk_khz;
+   int bw_dppclk_khz;
+   int bw_dispclk_khz;
+   int safe_to_lower;
+};
+
+struct amdgpu_dm_trace_dce_clocks_state {
+   bool cpuc_state_change_enable;
+   bool cpup_state_change_enable;
+   bool stutter_mode_enable;
+   bool nbp_state_change_enable;
+   bool all_displays_in_sync;
+   int sclk_khz;
+   int sclk_deep_sleep_khz;
+   int yclk_khz;
+   int dispclk_khz;
+   int blackout_recovery_time_us;
+   int patched_disp_clk;
+   int safe_to_lower;
+};
+
 #define fill_out_trace_pipe_state(trace_pipe_state, pipe_ctx) \
do { \
trace_pipe_state.pipe_idx   = (pipe_ctx)->pipe_idx; \
@@ -444,6 +480,44 @@ struct amdgpu_dm_trace_pipe_state {
trace_pipe_state.update_flags   = (pipe_ctx)->update_flags.raw; 
\
} while (0)
 
+#define fill_out_trace_clock_state(trace_clock_state, clocks, safe_to_lower) \
+   do { \
+   trace_clock_state.dispclk_khz = (clocks)->dispclk_khz; \
+   trace_clock_state.dppclk_khz = (clocks)->dppclk_khz; \
+   trace_clock_state.disp_dpp_voltage_level_khz = 
(clocks)->disp_dpp_voltage_level_khz; \
+   trace_clock_state.dcfclk_khz = (clocks)->dcfclk_khz; \
+   trace_clock_state.socclk_khz = (clocks)->socclk_khz; \
+   trace_clock_state.dcfclk_deep_sleep_khz = 
(clocks)->dcfclk_deep_sleep_khz; \
+   trace_clock_state.fclk_khz = (clocks)->fclk_khz; \
+   trace_clock_state.phyclk_khz = (clocks)->phyclk_khz; \
+   trace_clock_state.dramclk_khz = (clocks)->dramclk_khz; \
+   trace_clock_state.p_state_change_support = 
(clocks)->p_state_change_support; \
+   trace_clock_state.pwr_state = (clocks)->pwr_state; \
+   trace_clock_state.prev_p_state_change_support = 
(clocks)->prev_p_state_change_support; \
+   trace_clock_state.dtm_level = (clocks)->dtm_level; \
+   trace_clock_state.max_supported_dppclk_khz = 
(clocks)->max_supported_dppclk_khz; \
+   trace_clock_state.max_supported_dispclk_khz = 
(clocks)->max_supported_dispclk_khz; \
+   trace_clock_state.bw_dppclk_khz = (clocks)->bw_dppclk_khz; \
+   trace_clock_state.bw_dispclk_khz = (clocks)->bw_dispclk_khz; \
+   trace_clock_state.safe_to_lower = safe_to_lower; \
+   } while (0)
+
+#define fill_out_trace_dce_clock_state(trace_clock_state, clocks, 
patched_disp_clk, safe_to_lower) \
+   do { \
+   trace_clock_state.cpuc_state_change_enable = 
(clocks)->cpuc_state_change_enable; \
+   trace_clock_state.cpup_state_change_enable = 
(clocks)->cpup_state_change_enable; \
+   trace_clock_state.stutter_mode_enable = 
(clocks)->stutter_mode_enable; \
+   trace_clock_state.nbp_state_change_enable = 
(clocks)->nbp_state_change_enable; \
+   trace_clock_state.all_displays_in_sync = 
(clocks)->all_displays_in_sync; \
+   trace_clock_state.sclk_khz = (clocks)->sclk_khz; \
+   trace_clock_state.sclk_deep_sleep_khz = 
(clocks)->sclk_deep_sleep_khz; \
+   trace_clock_state.yclk_khz = (clocks)->

[PATCH 2/3] drm/amd/display: Add tracepoint for amdgpu_dm

2020-09-09 Thread Rodrigo Siqueira
Debug amdgpu_dm could be a complicated task, therefore, this commit adds
tracepoints in some convenient functions such as plane and connector
check inside amdgpu_dm.

Co-developed-by: Nicholas Kazlauskas 
Signed-off-by: Nicholas Kazlauskas 
Signed-off-by: Rodrigo Siqueira 
---
 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  17 ++
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 287 ++
 2 files changed, 304 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index cb624ee70545..552ca67c2a71 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -5424,6 +5424,8 @@ amdgpu_dm_connector_atomic_check(struct drm_connector 
*conn,
struct drm_crtc_state *new_crtc_state;
int ret;
 
+   trace_amdgpu_dm_connector_atomic_check(new_con_state);
+
if (!crtc)
return 0;
 
@@ -5542,6 +5544,8 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc 
*crtc,
struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state);
int ret = -EINVAL;
 
+   trace_amdgpu_dm_crtc_atomic_check(state);
+
dm_update_crtc_active_planes(crtc, state);
 
if (unlikely(!dm_crtc_state->stream &&
@@ -5916,6 +5920,8 @@ static int dm_plane_atomic_check(struct drm_plane *plane,
struct drm_crtc_state *new_crtc_state;
int ret;
 
+   trace_amdgpu_dm_plane_atomic_check(state);
+
dm_plane_state = to_dm_plane_state(state);
 
if (!dm_plane_state->dc_state)
@@ -5956,6 +5962,8 @@ static void dm_plane_atomic_async_update(struct drm_plane 
*plane,
struct drm_plane_state *old_state =
drm_atomic_get_old_plane_state(new_state->state, plane);
 
+   trace_amdgpu_dm_atomic_update_cursor(new_state);
+
swap(plane->state->fb, new_state->fb);
 
plane->state->src_x = new_state->src_x;
@@ -7546,6 +7554,8 @@ static void amdgpu_dm_atomic_commit_tail(struct 
drm_atomic_state *state)
int crtc_disable_count = 0;
bool mode_set_reset_required = false;
 
+   trace_amdgpu_dm_atomic_commit_tail_begin(state);
+
drm_atomic_helper_update_legacy_modeset_state(dev, state);
 
dm_state = dm_atomic_get_new_state(state);
@@ -8616,6 +8626,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
int ret, i;
bool lock_and_validation_needed = false;
 
+   trace_amdgpu_dm_atomic_check_begin(state);
+
ret = drm_atomic_helper_check_modeset(dev, state);
if (ret)
goto fail;
@@ -8912,6 +8924,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
 
/* Must be success */
WARN_ON(ret);
+
+   trace_amdgpu_dm_atomic_check_finish(state, ret);
+
return ret;
 
 fail:
@@ -8922,6 +8937,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
else
DRM_DEBUG_DRIVER("Atomic check failed with err: %d \n", ret);
 
+   trace_amdgpu_dm_atomic_check_finish(state, ret);
+
return ret;
 }
 
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index dd34e11b1079..5fb4c4a5c349 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -30,6 +30,12 @@
 #define _AMDGPU_DM_TRACE_H_
 
 #include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 DECLARE_EVENT_CLASS(amdgpu_dc_reg_template,
TP_PROTO(unsigned long *count, uint32_t reg, uint32_t 
value),
@@ -89,6 +95,287 @@ TRACE_EVENT(amdgpu_dc_performance,
(unsigned long)__entry->write_delta,
(unsigned long)__entry->writes)
 );
+
+TRACE_EVENT(amdgpu_dm_connector_atomic_check,
+   TP_PROTO(const struct drm_connector_state *state),
+   TP_ARGS(state),
+
+   TP_STRUCT__entry(
+__field(uint32_t, conn_id)
+__field(const struct drm_connector_state *, 
conn_state)
+__field(const struct drm_atomic_state *, state)
+__field(const struct drm_crtc_commit *, commit)
+__field(uint32_t, crtc_id)
+__field(uint32_t, best_encoder_id)
+__field(enum drm_link_status, link_status)
+__field(bool, self_refresh_aware)
+__field(enum hdmi_picture_aspect, 
picture_aspect_ratio)
+__field(unsigned int, content_type)
+__field(unsigned int, hdcp_content_type)
+__field(unsigned int, content_protection)
+__field(unsigned int, scaling_mode)
+

[PATCH 0/3] Enlarge tracepoints in the display component

2020-09-09 Thread Rodrigo Siqueira
Debug issues related to display can be a challenge due to the complexity
around this topic and different source of information might help in this
process. We already have support for tracepoints inside the display
component, i.e., we have the basic functionalities available and we just
need to expand it in order to make it more valuable for debugging. For
this reason, this patchset reworks part of the current tracepoint
options and add different sets of tracing inside amdgpu_dm, display
core, and DCN10. The first patch of this series just rework part of the
current tracepoints and the last set of patches introduces new
tracepoints.

This first patchset version is functional. Please, let me know what I
can improve in the current version but also let me know what kind of
tracepoint I can add for the next version. 

Finally, I want to highlight that this work is based on a set of patches
originally made by Nicholas Kazlauskas.

Rodrigo Siqueira (3):
  drm/amd/display: Rework registers tracepoint
  drm/amd/display: Add tracepoint for amdgpu_dm
  drm/amd/display: Add pipe_state tracepoint

 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  17 +
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 514 --
 drivers/gpu/drm/amd/display/dc/core/dc.c  |  11 +
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c |  17 +-
 4 files changed, 523 insertions(+), 36 deletions(-)

-- 
2.28.0



[PATCH 3/3] drm/amd/display: Add pipe_state tracepoint

2020-09-09 Thread Rodrigo Siqueira
This commit introduces a trace mechanism for struct pipe_ctx by adding a
middle layer struct in the amdgpu_dm_trace.h for capturing the most
important data from struct pipe_ctx and showing its data via tracepoint.
This tracepoint was added to dc.c and dcn10_hw_sequencer, however, it
can be added to other DCN architecture.

Co-developed-by: Nicholas Kazlauskas 
Signed-off-by: Nicholas Kazlauskas 
Signed-off-by: Rodrigo Siqueira 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 172 ++
 drivers/gpu/drm/amd/display/dc/core/dc.c  |  11 ++
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c |  17 +-
 3 files changed, 195 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index 5fb4c4a5c349..53f62506e17c 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -376,6 +376,178 @@ TRACE_EVENT(amdgpu_dm_atomic_check_finish,
  __entry->async_update, __entry->allow_modeset)
 );
 
+#ifndef _AMDGPU_DM_TRACE_STRUCTS_DEFINED_
+#define _AMDGPU_DM_TRACE_STRUCTS_DEFINED_
+
+struct amdgpu_dm_trace_pipe_state {
+   int pipe_idx;
+   const void *stream;
+   int stream_w;
+   int stream_h;
+   int dst_x;
+   int dst_y;
+   int dst_w;
+   int dst_h;
+   int src_x;
+   int src_y;
+   int src_w;
+   int src_h;
+   int clip_x;
+   int clip_y;
+   int clip_w;
+   int clip_h;
+   int recout_x;
+   int recout_y;
+   int recout_w;
+   int recout_h;
+   int viewport_x;
+   int viewport_y;
+   int viewport_w;
+   int viewport_h;
+   int flip_immediate;
+   int surface_pitch;
+   int format;
+   int swizzle;
+   unsigned int update_flags;
+};
+
+#define fill_out_trace_pipe_state(trace_pipe_state, pipe_ctx) \
+   do { \
+   trace_pipe_state.pipe_idx   = (pipe_ctx)->pipe_idx; \
+   trace_pipe_state.stream = (pipe_ctx)->stream; \
+   trace_pipe_state.stream_w   = 
(pipe_ctx)->stream->timing.h_addressable; \
+   trace_pipe_state.stream_h   = 
(pipe_ctx)->stream->timing.v_addressable; \
+   trace_pipe_state.dst_x  = 
(pipe_ctx)->plane_state->dst_rect.x; \
+   trace_pipe_state.dst_y  = 
(pipe_ctx)->plane_state->dst_rect.y; \
+   trace_pipe_state.dst_w  = 
(pipe_ctx)->plane_state->dst_rect.width; \
+   trace_pipe_state.dst_h  = 
(pipe_ctx)->plane_state->dst_rect.height; \
+   trace_pipe_state.src_x  = 
(pipe_ctx)->plane_state->src_rect.x; \
+   trace_pipe_state.src_y  = 
(pipe_ctx)->plane_state->src_rect.y; \
+   trace_pipe_state.src_w  = 
(pipe_ctx)->plane_state->src_rect.width; \
+   trace_pipe_state.src_h  = 
(pipe_ctx)->plane_state->src_rect.height; \
+   trace_pipe_state.clip_x = 
(pipe_ctx)->plane_state->clip_rect.x; \
+   trace_pipe_state.clip_y = 
(pipe_ctx)->plane_state->clip_rect.y; \
+   trace_pipe_state.clip_w = 
(pipe_ctx)->plane_state->clip_rect.width; \
+   trace_pipe_state.clip_h = 
(pipe_ctx)->plane_state->clip_rect.height; \
+   trace_pipe_state.recout_x   = 
(pipe_ctx)->plane_res.scl_data.recout.x; \
+   trace_pipe_state.recout_y   = 
(pipe_ctx)->plane_res.scl_data.recout.y; \
+   trace_pipe_state.recout_w   = 
(pipe_ctx)->plane_res.scl_data.recout.width; \
+   trace_pipe_state.recout_h   = 
(pipe_ctx)->plane_res.scl_data.recout.height; \
+   trace_pipe_state.viewport_x = 
(pipe_ctx)->plane_res.scl_data.viewport.x; \
+   trace_pipe_state.viewport_y = 
(pipe_ctx)->plane_res.scl_data.viewport.y; \
+   trace_pipe_state.viewport_w = 
(pipe_ctx)->plane_res.scl_data.viewport.width; \
+   trace_pipe_state.viewport_h = 
(pipe_ctx)->plane_res.scl_data.viewport.height; \
+   trace_pipe_state.flip_immediate = 
(pipe_ctx)->plane_state->flip_immediate; \
+   trace_pipe_state.surface_pitch  = 
(pipe_ctx)->plane_state->plane_size.surface_pitch; \
+   trace_pipe_state.format = 
(pipe_ctx)->plane_state->format; \
+   trace_pipe_state.swizzle= 
(pipe_ctx)->plane_state->tiling_info.gfx9.swizzle; \
+   trace_pipe_state.update_flags   = (pipe_ctx)->update_flags.raw; 
\
+   } while (0)
+
+#endif /* _AMDGPU_DM_TRACE_STRUCTS_DEFINED_ */
+
+TRACE_EVENT(amdgpu_dm_dc_pipe_state,
+   TP_PROTO(const struct amdgpu_dm_trace_pipe_state *pipe_state),
+ 

[PATCH 1/3] drm/amd/display: Rework registers tracepoint

2020-09-09 Thread Rodrigo Siqueira
amdgpu_dc_rreg and amdgpu_dc_wreg are very similar, for this reason,
this commits abstract these two events by using DECLARE_EVENT_CLASS and
create an instance of it for each one of these events.

Signed-off-by: Rodrigo Siqueira 
---
 .../amd/display/amdgpu_dm/amdgpu_dm_trace.h   | 55 ---
 1 file changed, 24 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index d898981684d5..dd34e11b1079 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -31,40 +31,33 @@
 
 #include 
 
-TRACE_EVENT(amdgpu_dc_rreg,
-   TP_PROTO(unsigned long *read_count, uint32_t reg, uint32_t value),
-   TP_ARGS(read_count, reg, value),
-   TP_STRUCT__entry(
-   __field(uint32_t, reg)
-   __field(uint32_t, value)
-   ),
-   TP_fast_assign(
-   __entry->reg = reg;
-   __entry->value = value;
-   *read_count = *read_count + 1;
-   ),
-   TP_printk("reg=0x%08lx, value=0x%08lx",
-   (unsigned long)__entry->reg,
-   (unsigned long)__entry->value)
-);
+DECLARE_EVENT_CLASS(amdgpu_dc_reg_template,
+   TP_PROTO(unsigned long *count, uint32_t reg, uint32_t 
value),
+   TP_ARGS(count, reg, value),
 
-TRACE_EVENT(amdgpu_dc_wreg,
-   TP_PROTO(unsigned long *write_count, uint32_t reg, uint32_t value),
-   TP_ARGS(write_count, reg, value),
-   TP_STRUCT__entry(
-   __field(uint32_t, reg)
-   __field(uint32_t, value)
-   ),
-   TP_fast_assign(
-   __entry->reg = reg;
-   __entry->value = value;
-   *write_count = *write_count + 1;
-   ),
-   TP_printk("reg=0x%08lx, value=0x%08lx",
-   (unsigned long)__entry->reg,
-   (unsigned long)__entry->value)
+   TP_STRUCT__entry(
+__field(uint32_t, reg)
+__field(uint32_t, value)
+   ),
+
+   TP_fast_assign(
+  __entry->reg = reg;
+  __entry->value = value;
+  *count = *count + 1;
+   ),
+
+   TP_printk("reg=0x%08lx, value=0x%08lx",
+ (unsigned long)__entry->reg,
+ (unsigned long)__entry->value)
 );
 
+DEFINE_EVENT(amdgpu_dc_reg_template, amdgpu_dc_rreg,
+TP_PROTO(unsigned long *count, uint32_t reg, uint32_t value),
+TP_ARGS(count, reg, value));
+
+DEFINE_EVENT(amdgpu_dc_reg_template, amdgpu_dc_wreg,
+TP_PROTO(unsigned long *count, uint32_t reg, uint32_t value),
+TP_ARGS(count, reg, value));
 
 TRACE_EVENT(amdgpu_dc_performance,
TP_PROTO(unsigned long read_count, unsigned long write_count,
-- 
2.28.0



Re: [PATCH] MAINTAINERS: add entry for VKMS

2020-09-04 Thread Rodrigo Siqueira
On 09/04, Melissa Wen wrote:
> Add myself as maintainer of VKMS driver
> 
> Signed-off-by: Melissa Wen 
> ---
>  MAINTAINERS | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 01fb9ee6b951..d4277824a01c 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -5640,6 +5640,7 @@ F:  drivers/gpu/drm/udl/
>  
>  DRM DRIVER FOR VIRTUAL KERNEL MODESETTING (VKMS)
>  M:   Rodrigo Siqueira 
> +M:   Melissa Wen 
>  R:   Haneen Mohammed 
>  R:   Daniel Vetter 
>  L:   dri-de...@lists.freedesktop.org
> -- 
> 2.28.0
> 

Acked-by: Rodrigo Siqueira 

-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


[PATCH v6 0/3] drm/vkms: Introduces writeback support

2020-08-30 Thread Rodrigo Siqueira
This is the V5 version of a series that introduces the writeback support
to VKMS. The first two patches of this series are a pre-work for the
latest patch that adds the writeback connector, this patchset can be seen
in two parts:

* A pre-work that aims to make vkms composer operations a little bit more
  generic; these patches try to centralize the vkms framebuffer operations.
* The final patch enables the support for writeback in vkms.

In the previous review, Emil suggested multiple changes in the series. I
tried to apply most of the recommendations except for some suggestions
which I was not able to incorporate due to compilation issues, or other
suggestions that may complicate this series review. I left some changes
for future patches for keeping this patchset simple with the hope of
landing this feature soon in order to support VKMS user's requirements.
Emil, let me know if you want me to change any other thing.

It is important to highlight that from the previous series to the
current version of this patchset we had some changes in the VKMS that
made it unstable.  In particular, our previous writeback series stopped
working properly due to changes in our commit tail.  Thanks to Melissa
working in the instability issue and her latest fixes to VKMS, I finally
could update writeback and make it work again. The main update in the
latest patch is the use of vkms_set_composer when the writeback work
starts (enable composer) and after the writeback end (disable composer).

V6:
- Rebase and tiny fixes

Best regards

Rodrigo Siqueira (3):
  drm/vkms: Decouple crc operations from composer
  drm/vkms: Compute CRC without change input data
  drm/vkms: Add support for writeback

 drivers/gpu/drm/vkms/Makefile |   9 +-
 drivers/gpu/drm/vkms/vkms_composer.c  |  98 --
 drivers/gpu/drm/vkms/vkms_drv.h   |  11 +-
 drivers/gpu/drm/vkms/vkms_output.c|   4 +
 drivers/gpu/drm/vkms/vkms_writeback.c | 142 ++
 5 files changed, 228 insertions(+), 36 deletions(-)
 create mode 100644 drivers/gpu/drm/vkms/vkms_writeback.c

-- 
2.28.0



[PATCH v6 3/3] drm/vkms: Add support for writeback

2020-08-30 Thread Rodrigo Siqueira
This patch implements the necessary functions to add writeback support
for vkms. This feature is useful for testing compositors if you don't
have hardware with writeback support.

Change in V4 (Emil and Melissa):
- Move signal completion above drm_crtc_add_crc_entry()
- Make writeback always available
- Use appropriate namespace
- Drop fb check in vkms_wb_atomic_commit
- Make vkms_set_composer visible for writeback code
- Enable composer operation on prepare_job and disable it on cleanup_job
- Drop extra space at the end of the file
- Rebase

Change in V3 (Daniel):
- If writeback is enabled, compose everything into the writeback buffer
instead of CRC private buffer
- Guarantees that the CRC will match exactly what we have in the
writeback buffer.

Change in V2:
- Rework signal completion (Brian)
- Integrates writeback with active_planes (Daniel)
- Compose cursor (Daniel)

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/Makefile |   9 +-
 drivers/gpu/drm/vkms/vkms_composer.c  |  21 +++-
 drivers/gpu/drm/vkms/vkms_drv.h   |  11 +-
 drivers/gpu/drm/vkms/vkms_output.c|   4 +
 drivers/gpu/drm/vkms/vkms_writeback.c | 142 ++
 5 files changed, 180 insertions(+), 7 deletions(-)
 create mode 100644 drivers/gpu/drm/vkms/vkms_writeback.c

diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
index 0b767d7efa24..333d3cead0e3 100644
--- a/drivers/gpu/drm/vkms/Makefile
+++ b/drivers/gpu/drm/vkms/Makefile
@@ -1,4 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0-only
-vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o 
vkms_composer.o
+vkms-y := \
+   vkms_drv.o \
+   vkms_plane.o \
+   vkms_output.o \
+   vkms_crtc.o \
+   vkms_gem.o \
+   vkms_composer.o \
+   vkms_writeback.o
 
 obj-$(CONFIG_DRM_VKMS) += vkms.o
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index c5b32fe5870f..33c031f27c2c 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -186,16 +186,17 @@ void vkms_composer_worker(struct work_struct *work)
struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
struct vkms_composer *primary_composer = NULL;
struct vkms_composer *cursor_composer = NULL;
+   bool crc_pending, wb_pending;
void *vaddr_out = NULL;
u32 crc32 = 0;
u64 frame_start, frame_end;
-   bool crc_pending;
int ret;
 
spin_lock_irq(>composer_lock);
frame_start = crtc_state->frame_start;
frame_end = crtc_state->frame_end;
crc_pending = crtc_state->crc_pending;
+   wb_pending = crtc_state->wb_pending;
crtc_state->frame_start = 0;
crtc_state->frame_end = 0;
crtc_state->crc_pending = false;
@@ -217,22 +218,32 @@ void vkms_composer_worker(struct work_struct *work)
if (!primary_composer)
return;
 
+   if (wb_pending)
+   vaddr_out = crtc_state->active_writeback;
+
ret = compose_planes(_out, primary_composer, cursor_composer);
if (ret) {
-   if (ret == -EINVAL)
+   if (ret == -EINVAL && !wb_pending)
kfree(vaddr_out);
return;
}
 
crc32 = compute_crc(vaddr_out, primary_composer);
 
+   if (wb_pending) {
+   drm_writeback_signal_completion(>wb_connector, 0);
+   spin_lock_irq(>composer_lock);
+   crtc_state->wb_pending = false;
+   spin_unlock_irq(>composer_lock);
+   } else {
+   kfree(vaddr_out);
+   }
+
/*
 * The worker can fall behind the vblank hrtimer, make sure we catch up.
 */
while (frame_start <= frame_end)
drm_crtc_add_crc_entry(crtc, true, frame_start++, );
-
-   kfree(vaddr_out);
 }
 
 static const char * const pipe_crc_sources[] = {"auto"};
@@ -275,7 +286,7 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const 
char *src_name,
return 0;
 }
 
-static void vkms_set_composer(struct vkms_output *out, bool enabled)
+void vkms_set_composer(struct vkms_output *out, bool enabled)
 {
bool old_enabled;
 
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index f4036bb0b9a8..641d8bc52a3a 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define XRES_MIN20
 #define YRES_MIN20
@@ -19,6 +20,7 @@
 #define YRES_MAX  8192
 
 extern bool enable_cursor;
+extern bool enable_writeback;
 
 struct vkms_composer {
struct drm_framebuffer fb;
@@ -52,9 +54,11 @@ struct vkms_crtc_state {
int num_active_planes;
/* stack of active planes for crc computation, should be in z order */
struct vkms_plane_state **active_planes;
+   vo

[PATCH v6 2/3] drm/vkms: Compute CRC without change input data

2020-08-30 Thread Rodrigo Siqueira
The compute_crc() function is responsible for calculating the
framebuffer CRC value; due to the XRGB format, this function has to
ignore the alpha channel during the CRC computation. Therefore,
compute_crc() set zero to the alpha channel directly in the input
framebuffer, which is not a problem since this function receives a copy
of the original buffer. However, if we want to use this function in a
context without a buffer copy, it will change the initial value. This
patch makes compute_crc() calculate the CRC value without modifying the
input framebuffer.

Change in V5 (Melissa):
- Rebase and drop bitmap for alpha
Change in V4 (Emil):
- Move bitmap_clear operation and comments to get_pixel function

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/vkms_composer.c | 34 ++--
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index f67d1baf1942..c5b32fe5870f 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -9,31 +9,41 @@
 
 #include "vkms_drv.h"
 
+static u32 get_pixel_from_buffer(int x, int y, const u8 *buffer,
+const struct vkms_composer *composer)
+{
+   u32 pixel;
+   int src_offset = composer->offset + (y * composer->pitch)
+ + (x * composer->cpp);
+
+   pixel = *(u32 *)[src_offset];
+
+   return pixel;
+}
+
 /**
  * compute_crc - Compute CRC value on output frame
  *
- * @vaddr_out: address to final framebuffer
+ * @vaddr: address to final framebuffer
  * @composer: framebuffer's metadata
  *
  * returns CRC value computed using crc32 on the visible portion of
  * the final framebuffer at vaddr_out
  */
-static uint32_t compute_crc(void *vaddr_out, struct vkms_composer *composer)
+static uint32_t compute_crc(const u8 *vaddr,
+   const struct vkms_composer *composer)
 {
-   int i, j, src_offset;
+   int x, y;
+   u32 crc = 0, pixel = 0;
int x_src = composer->src.x1 >> 16;
int y_src = composer->src.y1 >> 16;
int h_src = drm_rect_height(>src) >> 16;
int w_src = drm_rect_width(>src) >> 16;
-   u32 crc = 0;
-
-   for (i = y_src; i < y_src + h_src; ++i) {
-   for (j = x_src; j < x_src + w_src; ++j) {
-   src_offset = composer->offset
-+ (i * composer->pitch)
-+ (j * composer->cpp);
-   crc = crc32_le(crc, vaddr_out + src_offset,
-  sizeof(u32));
+
+   for (y = y_src; y < y_src + h_src; ++y) {
+   for (x = x_src; x < x_src + w_src; ++x) {
+   pixel = get_pixel_from_buffer(x, y, vaddr, composer);
+   crc = crc32_le(crc, (void *), sizeof(u32));
}
}
 
-- 
2.28.0



[PATCH v6 1/3] drm/vkms: Decouple crc operations from composer

2020-08-30 Thread Rodrigo Siqueira
In the vkms_composer.c, some of the functions related to CRC and compose
have interdependence between each other. This patch reworks some
functions inside vkms_composer to make crc and composer computation
decoupled.

This patch is preparation work for making vkms able to support new
features.

Tested-by: Melissa Wen 
Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/vkms_composer.c | 49 
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index eaecc5a6c5db..f67d1baf1942 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -131,35 +131,31 @@ static void compose_cursor(struct vkms_composer 
*cursor_composer,
  primary_composer, cursor_composer);
 }
 
-static uint32_t _vkms_get_crc(struct vkms_composer *primary_composer,
- struct vkms_composer *cursor_composer)
+static int compose_planes(void **vaddr_out,
+ struct vkms_composer *primary_composer,
+ struct vkms_composer *cursor_composer)
 {
struct drm_framebuffer *fb = _composer->fb;
struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0);
struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj);
-   void *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL);
-   u32 crc = 0;
 
-   if (!vaddr_out) {
-   DRM_ERROR("Failed to allocate memory for output frame.");
-   return 0;
+   if (!*vaddr_out) {
+   *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL);
+   if (!*vaddr_out) {
+   DRM_ERROR("Cannot allocate memory for output frame.");
+   return -ENOMEM;
+   }
}
 
-   if (WARN_ON(!vkms_obj->vaddr)) {
-   kfree(vaddr_out);
-   return crc;
-   }
+   if (WARN_ON(!vkms_obj->vaddr))
+   return -EINVAL;
 
-   memcpy(vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size);
+   memcpy(*vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size);
 
if (cursor_composer)
-   compose_cursor(cursor_composer, primary_composer, vaddr_out);
+   compose_cursor(cursor_composer, primary_composer, *vaddr_out);
 
-   crc = compute_crc(vaddr_out, primary_composer);
-
-   kfree(vaddr_out);
-
-   return crc;
+   return 0;
 }
 
 /**
@@ -180,9 +176,11 @@ void vkms_composer_worker(struct work_struct *work)
struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
struct vkms_composer *primary_composer = NULL;
struct vkms_composer *cursor_composer = NULL;
+   void *vaddr_out = NULL;
u32 crc32 = 0;
u64 frame_start, frame_end;
bool crc_pending;
+   int ret;
 
spin_lock_irq(>composer_lock);
frame_start = crtc_state->frame_start;
@@ -206,14 +204,25 @@ void vkms_composer_worker(struct work_struct *work)
if (crtc_state->num_active_planes == 2)
cursor_composer = crtc_state->active_planes[1]->composer;
 
-   if (primary_composer)
-   crc32 = _vkms_get_crc(primary_composer, cursor_composer);
+   if (!primary_composer)
+   return;
+
+   ret = compose_planes(_out, primary_composer, cursor_composer);
+   if (ret) {
+   if (ret == -EINVAL)
+   kfree(vaddr_out);
+   return;
+   }
+
+   crc32 = compute_crc(vaddr_out, primary_composer);
 
/*
 * The worker can fall behind the vblank hrtimer, make sure we catch up.
 */
while (frame_start <= frame_end)
drm_crtc_add_crc_entry(crtc, true, frame_start++, );
+
+   kfree(vaddr_out);
 }
 
 static const char * const pipe_crc_sources[] = {"auto"};
-- 
2.28.0



Re: [PATCH v2] drm/vkms: add alpha-premultiplied color blending

2020-08-30 Thread Rodrigo Siqueira
Reviewed-by: Rodrigo Siqueira 

On 08/25, Melissa Wen wrote:
> The VKMS blend function was ignoring the alpha channel and just
> overwriting vaddr_src with vaddr_dst. This XRGB approach triggers a
> warning when running the kms_cursor_crc/cursor-alpha-transparent test
> case. In IGT, cairo_format_argb32 uses premultiplied alpha (according to
> documentation). Also current DRM assumption is that alpha is
> premultiplied. Therefore, this patch considers premultiplied alpha
> blending eq to compose vaddr_src with vaddr_dst.
> 
> This change removes the following cursor-alpha-transparent warning:
> "Suspicious CRC: All values are 0."
> 
> --
> 
> v2:
> - static for local functions
> - const for the read-only variable argb_src
> - replaces variable names
> - drops unnecessary comment
> 
> --
> 
> Cc: Daniel Vetter 
> Cc: Rodrigo Siqueira 
> Cc: Haneen Mohammed 
> 
> Signed-off-by: Melissa Wen 
> ---
>  drivers/gpu/drm/vkms/vkms_composer.c | 55 
>  1 file changed, 39 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
> b/drivers/gpu/drm/vkms/vkms_composer.c
> index 4f3b07a32b60..eaecc5a6c5db 100644
> --- a/drivers/gpu/drm/vkms/vkms_composer.c
> +++ b/drivers/gpu/drm/vkms/vkms_composer.c
> @@ -32,8 +32,6 @@ static uint32_t compute_crc(void *vaddr_out, struct 
> vkms_composer *composer)
>   src_offset = composer->offset
>+ (i * composer->pitch)
>+ (j * composer->cpp);
> - /* XRGB format ignores Alpha channel */
> - bitmap_clear(vaddr_out + src_offset, 24, 8);
>   crc = crc32_le(crc, vaddr_out + src_offset,
>  sizeof(u32));
>   }
> @@ -42,27 +40,51 @@ static uint32_t compute_crc(void *vaddr_out, struct 
> vkms_composer *composer)
>   return crc;
>  }
>  
> +static u8 blend_channel(u8 src, u8 dst, u8 alpha)
> +{
> + u32 pre_blend;
> + u8 new_color;
> +
> + pre_blend = (src * 255 + dst * (255 - alpha));
> +
> + /* Faster div by 255 */
> + new_color = ((pre_blend + ((pre_blend + 257) >> 8)) >> 8);
> +
> + return new_color;
> +}
> +
> +static void alpha_blending(const u8 *argb_src, u8 *argb_dst)
> +{
> + u8 alpha;
> +
> + alpha = argb_src[3];
> + argb_dst[0] = blend_channel(argb_src[0], argb_dst[0], alpha);
> + argb_dst[1] = blend_channel(argb_src[1], argb_dst[1], alpha);
> + argb_dst[2] = blend_channel(argb_src[2], argb_dst[2], alpha);
> + /* Opaque primary */
> + argb_dst[3] = 0xFF;
> +}
> +
>  /**
>   * blend - blend value at vaddr_src with value at vaddr_dst
>   * @vaddr_dst: destination address
>   * @vaddr_src: source address
> - * @dest_composer: destination framebuffer's metadata
> + * @dst_composer: destination framebuffer's metadata
>   * @src_composer: source framebuffer's metadata
>   *
> - * Blend value at vaddr_src with value at vaddr_dst.
> - * Currently, this function write value of vaddr_src on value
> - * at vaddr_dst using buffer's metadata to locate the new values
> - * from vaddr_src and their destination at vaddr_dst.
> - *
> - * TODO: Use the alpha value to blend vaddr_src with vaddr_dst
> - *instead of overwriting it.
> + * Blend the vaddr_src value with the vaddr_dst value using the 
> pre-multiplied
> + * alpha blending equation, since DRM currently assumes that the pixel color
> + * values have already been pre-multiplied with the alpha channel values. See
> + * more drm_plane_create_blend_mode_property(). This function uses buffer's
> + * metadata to locate the new composite values at vaddr_dst.
>   */
>  static void blend(void *vaddr_dst, void *vaddr_src,
> -   struct vkms_composer *dest_composer,
> +   struct vkms_composer *dst_composer,
> struct vkms_composer *src_composer)
>  {
>   int i, j, j_dst, i_dst;
>   int offset_src, offset_dst;
> + u8 *pixel_dst, *pixel_src;
>  
>   int x_src = src_composer->src.x1 >> 16;
>   int y_src = src_composer->src.y1 >> 16;
> @@ -77,15 +99,16 @@ static void blend(void *vaddr_dst, void *vaddr_src,
>  
>   for (i = y_src, i_dst = y_dst; i < y_limit; ++i) {
>   for (j = x_src, j_dst = x_dst; j < x_limit; ++j) {
> - offset_dst = dest_composer->offset
> -  + (i_dst * dest_composer->pitch)
> -  + (j_dst++ * dest_composer->cpp);
> + offse

Re: [PATCH] drm/vkms: Use alpha value to blend values.

2020-08-24 Thread Rodrigo Siqueira
Hi Sidong,

Thanks a lot for your patch and effort to improve VKMS.

On 08/18, Sidong Yang wrote:
> I wrote this patch for TODO list in vkms documentation.
> 
> Use alpha value to blend source value and destination value Instead of
> just overwrite with source value.
> 
> Cc: Rodrigo Siqueira 
> Cc: Haneen Mohammed 
> 
> Signed-off-by: Sidong Yang 
> ---
>  drivers/gpu/drm/vkms/vkms_composer.c | 14 --
>  1 file changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
> b/drivers/gpu/drm/vkms/vkms_composer.c
> index 4f3b07a32b60..e3230e2a99af 100644
> --- a/drivers/gpu/drm/vkms/vkms_composer.c
> +++ b/drivers/gpu/drm/vkms/vkms_composer.c
> @@ -77,6 +77,9 @@ static void blend(void *vaddr_dst, void *vaddr_src,
>  
>   for (i = y_src, i_dst = y_dst; i < y_limit; ++i) {
>   for (j = x_src, j_dst = x_dst; j < x_limit; ++j) {
> + u8 *src, *dst;
> + u32 alpha, inv_alpha;
> +
>   offset_dst = dest_composer->offset
>+ (i_dst * dest_composer->pitch)
>+ (j_dst++ * dest_composer->cpp);
> @@ -84,8 +87,15 @@ static void blend(void *vaddr_dst, void *vaddr_src,
>+ (i * src_composer->pitch)
>+ (j * src_composer->cpp);
>  
> - memcpy(vaddr_dst + offset_dst,
> -vaddr_src + offset_src, sizeof(u32));
> + src = vaddr_src + offset_src;
> + dst = vaddr_dst + offset_dst;
> + alpha = src[3] + 1;
> + inv_alpha = 256 - src[3];
> + dst[0] = (alpha * src[0] + inv_alpha * dst[0]) >> 8;
> + dst[1] = (alpha * src[1] + inv_alpha * dst[1]) >> 8;
> + dst[2] = (alpha * src[2] + inv_alpha * dst[2]) >> 8;

Did you test your change with IGT? Maybe I missed something but looks
like that you're applying the alpha value but the value that we get is
already pre-multiplied.

Btw, It looks like that you and Melissa are working in the same feature,
maybe you two could try to sync for avoiding overlapping.

Finally, do you have plans to send your fix for
vkms_get_vblank_timestamp() function? That patch was really good and
removes a lot of warning generated during the IGT test.

Best Regards

> + dst[3] = 0xff;
> +
>   }
>   i_dst++;
>   }
> -- 
> 2.17.1
> 

-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


Re: [PATCH] drm/vkms: add alpha-premultiplied color blending

2020-08-24 Thread Rodrigo Siqueira
Hi Melissa,

First of all, thanks a lot for your patch!

Follows my inline comments.

On 08/19, Melissa Wen wrote:
> The current VKMS blend function ignores alpha channel and just overwrites
> vaddr_src with vaddr_dst. This XRGB approach triggers a warning when
> running the kms_cursor_crc/cursor-alpha-transparent test case. In IGT
> tests, cairo_format_argb32 uses premultiplied alpha (according to
> documentation), so this patch considers premultiplied alpha colors to
> compose vaddr_src with vaddr_dst.
> 
> This change removes the following cursor-alpha-transparent warning:
> Suspicious CRC: All values are 0.
> 
> Cc: Daniel Vetter 
> Cc: Rodrigo Siqueira 
> Cc: Haneen Mohammed 
> 
> Signed-off-by: Melissa Wen 
> ---
>  drivers/gpu/drm/vkms/vkms_composer.c | 43 +---
>  1 file changed, 33 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
> b/drivers/gpu/drm/vkms/vkms_composer.c
> index 4f3b07a32b60..6aac962d3e2e 100644
> --- a/drivers/gpu/drm/vkms/vkms_composer.c
> +++ b/drivers/gpu/drm/vkms/vkms_composer.c
> @@ -32,8 +32,6 @@ static uint32_t compute_crc(void *vaddr_out, struct 
> vkms_composer *composer)
>   src_offset = composer->offset
>+ (i * composer->pitch)
>+ (j * composer->cpp);
> - /* XRGB format ignores Alpha channel */
> - bitmap_clear(vaddr_out + src_offset, 24, 8);
>   crc = crc32_le(crc, vaddr_out + src_offset,
>  sizeof(u32));
>   }
> @@ -42,6 +40,32 @@ static uint32_t compute_crc(void *vaddr_out, struct 
> vkms_composer *composer)
>   return crc;
>  }
>  
> +u8 blend_channel(u8 c_src, u8 c_dst, u8 a_src)

Use static here.

Also, replace c_src to src, c_dst to dst, and a_src to alpha.

> +{
> + u32 pre_blend;
> + u8 new_color;
> +
> + /* Premultiplied alpha blending - IGT + cairo context */

You can drop the part that says "IGT + cairo context", this explanation
better suit the commit message.

> + pre_blend = (c_src * 255 + c_dst * (255 - a_src));
> +
> + /* Faster div by 255 */
> + new_color = ((pre_blend + ((pre_blend + 257) >> 8)) >> 8);
> +
> + return new_color;
> +}
> +
> +void alpha_blending(u8 *argb_src, u8 *argb_dst)

Use static.

Looks like that argb_src is a read-only variable, in this sense add
const.

> +{
> + u8 a_src;
> +
> + a_src = argb_src[3];

change a_src to alpha.

> + argb_dst[0] = blend_channel(argb_src[0], argb_dst[0], a_src);
> + argb_dst[1] = blend_channel(argb_src[1], argb_dst[1], a_src);
> + argb_dst[2] = blend_channel(argb_src[2], argb_dst[2], a_src);
> + /* Opaque primary */
> + argb_dst[3] = 0xFF;
> +}
> +
>  /**
>   * blend - blend value at vaddr_src with value at vaddr_dst
>   * @vaddr_dst: destination address
> @@ -50,12 +74,9 @@ static uint32_t compute_crc(void *vaddr_out, struct 
> vkms_composer *composer)
>   * @src_composer: source framebuffer's metadata
>   *
>   * Blend value at vaddr_src with value at vaddr_dst.
> - * Currently, this function write value of vaddr_src on value
> - * at vaddr_dst using buffer's metadata to locate the new values
> - * from vaddr_src and their destination at vaddr_dst.
> - *
> - * TODO: Use the alpha value to blend vaddr_src with vaddr_dst
> - *instead of overwriting it.
> + * Currently, this function considers premultiplied alpha for blending, as 
> used
> + * by Cairo. It uses buffer's metadata to locate the new composite values at
> + * vaddr_dst.
>   */
>  static void blend(void *vaddr_dst, void *vaddr_src,
> struct vkms_composer *dest_composer,
> @@ -63,6 +84,7 @@ static void blend(void *vaddr_dst, void *vaddr_src,
>  {
>   int i, j, j_dst, i_dst;
>   int offset_src, offset_dst;
> + u8 *p_dst, *p_src;

I suppose that p stands for "pixel", right? In this case how about use
pixel?

Best Regards
Rodrigo Siqueira

>  
>   int x_src = src_composer->src.x1 >> 16;
>   int y_src = src_composer->src.y1 >> 16;
> @@ -84,8 +106,9 @@ static void blend(void *vaddr_dst, void *vaddr_src,
>+ (i * src_composer->pitch)
>+ (j * src_composer->cpp);
>  
> - memcpy(vaddr_dst + offset_dst,
> -vaddr_src + offset_src, sizeof(u32));
> + p_src = (u8 *)(vaddr_src + offset_src);
> + p_dst = (u8 *)(vaddr_dst + offset_dst);
> + alpha_blending(p_src, p_dst);
>   }
>   i_dst++;
>   }
> -- 
> 2.28.0
> 

-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


[PATCH v5 2/3] drm/vkms: Compute CRC without change input data

2020-08-24 Thread Rodrigo Siqueira
The compute_crc() function is responsible for calculating the
framebuffer CRC value; due to the XRGB format, this function has to
ignore the alpha channel during the CRC computation. Therefore,
compute_crc() set zero to the alpha channel directly in the input
framebuffer, which is not a problem since this function receives a copy
of the original buffer. However, if we want to use this function in a
context without a buffer copy, it will change the initial value. This
patch makes compute_crc() calculate the CRC value without modifying the
input framebuffer.

Change in V4 (Emil):
- Move bitmap_clear operation and comments to get_pixel function

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/vkms_composer.c | 38 ++--
 1 file changed, 24 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index 4d8bc04bb6ee..387b0690a64a 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -9,33 +9,43 @@
 
 #include "vkms_drv.h"
 
+static u32 get_pixel_from_buffer(int x, int y, const u8 *buffer,
+const struct vkms_composer *composer)
+{
+   u32 pixel;
+   int src_offset = composer->offset + (y * composer->pitch)
+ + (x * composer->cpp);
+
+   pixel = *(u32 *)[src_offset];
+   /* XRGB format ignores Alpha channel */
+   bitmap_clear((void *), 0, 8);
+
+   return pixel;
+}
+
 /**
  * compute_crc - Compute CRC value on output frame
  *
- * @vaddr_out: address to final framebuffer
+ * @vaddr: address to final framebuffer
  * @composer: framebuffer's metadata
  *
  * returns CRC value computed using crc32 on the visible portion of
  * the final framebuffer at vaddr_out
  */
-static uint32_t compute_crc(void *vaddr_out, struct vkms_composer *composer)
+static uint32_t compute_crc(const u8 *vaddr,
+   const struct vkms_composer *composer)
 {
-   int i, j, src_offset;
+   int x, y;
+   u32 crc = 0, pixel = 0;
int x_src = composer->src.x1 >> 16;
int y_src = composer->src.y1 >> 16;
int h_src = drm_rect_height(>src) >> 16;
int w_src = drm_rect_width(>src) >> 16;
-   u32 crc = 0;
-
-   for (i = y_src; i < y_src + h_src; ++i) {
-   for (j = x_src; j < x_src + w_src; ++j) {
-   src_offset = composer->offset
-+ (i * composer->pitch)
-+ (j * composer->cpp);
-   /* XRGB format ignores Alpha channel */
-   bitmap_clear(vaddr_out + src_offset, 24, 8);
-   crc = crc32_le(crc, vaddr_out + src_offset,
-  sizeof(u32));
+
+   for (y = y_src; y < y_src + h_src; ++y) {
+   for (x = x_src; x < x_src + w_src; ++x) {
+   pixel = get_pixel_from_buffer(x, y, vaddr, composer);
+   crc = crc32_le(crc, (void *), sizeof(u32));
}
}
 
-- 
2.28.0



[PATCH v5 3/3] drm/vkms: Add support for writeback

2020-08-24 Thread Rodrigo Siqueira
This patch implements the necessary functions to add writeback support
for vkms. This feature is useful for testing compositors if you don't
have hardware with writeback support.

Change in V4 (Emil and Melissa):
- Move signal completion above drm_crtc_add_crc_entry()
- Make writeback always available
- Use appropriate namespace
- Drop fb check in vkms_wb_atomic_commit
- Make vkms_set_composer visible for writeback code
- Enable composer operation on prepare_job and disable it on cleanup_job

Change in V3 (Daniel):
- If writeback is enabled, compose everything into the writeback buffer
instead of CRC private buffer
- Guarantees that the CRC will match exactly what we have in the
writeback buffer.

Change in V2:
- Rework signal completion (Brian)
- Integrates writeback with active_planes (Daniel)
- Compose cursor (Daniel)

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/Makefile |   9 +-
 drivers/gpu/drm/vkms/vkms_composer.c  |  21 +++-
 drivers/gpu/drm/vkms/vkms_drv.h   |  11 +-
 drivers/gpu/drm/vkms/vkms_output.c|   4 +
 drivers/gpu/drm/vkms/vkms_writeback.c | 143 ++
 5 files changed, 181 insertions(+), 7 deletions(-)
 create mode 100644 drivers/gpu/drm/vkms/vkms_writeback.c

diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
index 0b767d7efa24..333d3cead0e3 100644
--- a/drivers/gpu/drm/vkms/Makefile
+++ b/drivers/gpu/drm/vkms/Makefile
@@ -1,4 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0-only
-vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o 
vkms_composer.o
+vkms-y := \
+   vkms_drv.o \
+   vkms_plane.o \
+   vkms_output.o \
+   vkms_crtc.o \
+   vkms_gem.o \
+   vkms_composer.o \
+   vkms_writeback.o
 
 obj-$(CONFIG_DRM_VKMS) += vkms.o
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index 387b0690a64a..656085c4ebf3 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -163,16 +163,17 @@ void vkms_composer_worker(struct work_struct *work)
struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
struct vkms_composer *primary_composer = NULL;
struct vkms_composer *cursor_composer = NULL;
+   bool crc_pending, wb_pending;
void *vaddr_out = NULL;
u32 crc32 = 0;
u64 frame_start, frame_end;
-   bool crc_pending;
int ret;
 
spin_lock_irq(>composer_lock);
frame_start = crtc_state->frame_start;
frame_end = crtc_state->frame_end;
crc_pending = crtc_state->crc_pending;
+   wb_pending = crtc_state->wb_pending;
crtc_state->frame_start = 0;
crtc_state->frame_end = 0;
crtc_state->crc_pending = false;
@@ -194,22 +195,32 @@ void vkms_composer_worker(struct work_struct *work)
if (!primary_composer)
return;
 
+   if (wb_pending)
+   vaddr_out = crtc_state->active_writeback;
+
ret = compose_planes(_out, primary_composer, cursor_composer);
if (ret) {
-   if (ret == -EINVAL)
+   if (ret == -EINVAL && !wb_pending)
kfree(vaddr_out);
return;
}
 
crc32 = compute_crc(vaddr_out, primary_composer);
 
+   if (wb_pending) {
+   drm_writeback_signal_completion(>wb_connector, 0);
+   spin_lock_irq(>composer_lock);
+   crtc_state->wb_pending = false;
+   spin_unlock_irq(>composer_lock);
+   } else {
+   kfree(vaddr_out);
+   }
+
/*
 * The worker can fall behind the vblank hrtimer, make sure we catch up.
 */
while (frame_start <= frame_end)
drm_crtc_add_crc_entry(crtc, true, frame_start++, );
-
-   kfree(vaddr_out);
 }
 
 static const char * const pipe_crc_sources[] = {"auto"};
@@ -252,7 +263,7 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const 
char *src_name,
return 0;
 }
 
-static void vkms_set_composer(struct vkms_output *out, bool enabled)
+void vkms_set_composer(struct vkms_output *out, bool enabled)
 {
bool old_enabled;
 
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index f4036bb0b9a8..641d8bc52a3a 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define XRES_MIN20
 #define YRES_MIN20
@@ -19,6 +20,7 @@
 #define YRES_MAX  8192
 
 extern bool enable_cursor;
+extern bool enable_writeback;
 
 struct vkms_composer {
struct drm_framebuffer fb;
@@ -52,9 +54,11 @@ struct vkms_crtc_state {
int num_active_planes;
/* stack of active planes for crc computation, should be in z order */
struct vkms_plane_state **active_planes;
+   void *active_writeback;
 
-   /* below three are protected by vkms

[PATCH v5 1/3] drm/vkms: Decouple crc operations from composer

2020-08-24 Thread Rodrigo Siqueira
In the vkms_composer.c, some of the functions related to CRC and compose
have interdependence between each other. This patch reworks some
functions inside vkms_composer to make crc and composer computation
decoupled.

This patch is preparation work for making vkms able to support new
features.

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/vkms_composer.c | 49 
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index 4f3b07a32b60..4d8bc04bb6ee 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -108,35 +108,31 @@ static void compose_cursor(struct vkms_composer 
*cursor_composer,
  primary_composer, cursor_composer);
 }
 
-static uint32_t _vkms_get_crc(struct vkms_composer *primary_composer,
- struct vkms_composer *cursor_composer)
+static int compose_planes(void **vaddr_out,
+ struct vkms_composer *primary_composer,
+ struct vkms_composer *cursor_composer)
 {
struct drm_framebuffer *fb = _composer->fb;
struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0);
struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj);
-   void *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL);
-   u32 crc = 0;
 
-   if (!vaddr_out) {
-   DRM_ERROR("Failed to allocate memory for output frame.");
-   return 0;
+   if (!*vaddr_out) {
+   *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL);
+   if (!*vaddr_out) {
+   DRM_ERROR("Cannot allocate memory for output frame.");
+   return -ENOMEM;
+   }
}
 
-   if (WARN_ON(!vkms_obj->vaddr)) {
-   kfree(vaddr_out);
-   return crc;
-   }
+   if (WARN_ON(!vkms_obj->vaddr))
+   return -EINVAL;
 
-   memcpy(vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size);
+   memcpy(*vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size);
 
if (cursor_composer)
-   compose_cursor(cursor_composer, primary_composer, vaddr_out);
+   compose_cursor(cursor_composer, primary_composer, *vaddr_out);
 
-   crc = compute_crc(vaddr_out, primary_composer);
-
-   kfree(vaddr_out);
-
-   return crc;
+   return 0;
 }
 
 /**
@@ -157,9 +153,11 @@ void vkms_composer_worker(struct work_struct *work)
struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
struct vkms_composer *primary_composer = NULL;
struct vkms_composer *cursor_composer = NULL;
+   void *vaddr_out = NULL;
u32 crc32 = 0;
u64 frame_start, frame_end;
bool crc_pending;
+   int ret;
 
spin_lock_irq(>composer_lock);
frame_start = crtc_state->frame_start;
@@ -183,14 +181,25 @@ void vkms_composer_worker(struct work_struct *work)
if (crtc_state->num_active_planes == 2)
cursor_composer = crtc_state->active_planes[1]->composer;
 
-   if (primary_composer)
-   crc32 = _vkms_get_crc(primary_composer, cursor_composer);
+   if (!primary_composer)
+   return;
+
+   ret = compose_planes(_out, primary_composer, cursor_composer);
+   if (ret) {
+   if (ret == -EINVAL)
+   kfree(vaddr_out);
+   return;
+   }
+
+   crc32 = compute_crc(vaddr_out, primary_composer);
 
/*
 * The worker can fall behind the vblank hrtimer, make sure we catch up.
 */
while (frame_start <= frame_end)
drm_crtc_add_crc_entry(crtc, true, frame_start++, );
+
+   kfree(vaddr_out);
 }
 
 static const char * const pipe_crc_sources[] = {"auto"};
-- 
2.28.0



[PATCH v5 0/3] drm/vkms: Introduces writeback support

2020-08-24 Thread Rodrigo Siqueira
This is the V5 version of a series that introduces the writeback support
to VKMS. The first two patches of this series are a pre-work for the
latest patch that adds the writeback connector, this patchset can be seen
in two parts: 

* A pre-work that aims to make vkms composer operations a little bit more
  generic; these patches try to centralize the vkms framebuffer operations.
* The final patch enables the support for writeback in vkms.

In the previous review, Emil suggested multiple changes in the series. I
tried to apply most of the recommendations except for some suggestions
which I was not able to incorporate due to compilation issues, or other
suggestions that may complicate this series review. I left some changes
for future patches for keeping this patchset simple with the hope of
landing this feature soon in order to support VKMS user's requirements.
Emil, let me know if you want me to change any other thing.

It is important to highlight that from the previous series to the
current version of this patchset we had some changes in the VKMS that
made it unstable.  In particular, our previous writeback series stopped
working properly due to changes in our commit tail.  Thanks to Melissa
working in the instability issue and her latest fixes to VKMS, I finally
could update writeback and make it work again. The main update in the
latest patch is the use of vkms_set_composer when the writeback work
starts (enable composer) and after the writeback end (disable composer).

Best Regard

Rodrigo Siqueira (3):
  drm/vkms: Decouple crc operations from composer
  drm/vkms: Compute CRC without change input data
  drm/vkms: Add support for writeback

 drivers/gpu/drm/vkms/Makefile |   9 +-
 drivers/gpu/drm/vkms/vkms_composer.c  | 102 +++---
 drivers/gpu/drm/vkms/vkms_drv.h   |  11 +-
 drivers/gpu/drm/vkms/vkms_output.c|   4 +
 drivers/gpu/drm/vkms/vkms_writeback.c | 143 ++
 5 files changed, 231 insertions(+), 38 deletions(-)
 create mode 100644 drivers/gpu/drm/vkms/vkms_writeback.c

-- 
2.28.0



Re: [PATCH] drm/vkms: change the max cursor width/height

2020-07-12 Thread Rodrigo Siqueira
Applied to drm-misc-next.

Thanks

On 07/12, Rodrigo Siqueira wrote:
> Hi Melissa,
> 
> First of all, thanks a lot for your patch! This is a nice change since
> it increases the code coverage.
> 
> Reviewed-by: Rodrigo Siqueira 
> 
> On 07/10, Melissa Wen wrote:
> > This change expands the coverage for the IGT kms_cursor_crc test, where
> > the size varies between 64 and 512 for a square cursor. With this, in
> > addition to the cursor 64x64, this patch enables the test of cursors with
> > sizes: 128x128, 256x256, and 512x512.
> > 
> > Signed-off-by: Melissa Wen 
> > ---
> >  drivers/gpu/drm/vkms/vkms_drv.c | 2 ++
> >  1 file changed, 2 insertions(+)
> > 
> > diff --git a/drivers/gpu/drm/vkms/vkms_drv.c 
> > b/drivers/gpu/drm/vkms/vkms_drv.c
> > index 1e8b2169d834..57a8a397d5e8 100644
> > --- a/drivers/gpu/drm/vkms/vkms_drv.c
> > +++ b/drivers/gpu/drm/vkms/vkms_drv.c
> > @@ -133,6 +133,8 @@ static int vkms_modeset_init(struct vkms_device 
> > *vkmsdev)
> > dev->mode_config.min_height = YRES_MIN;
> > dev->mode_config.max_width = XRES_MAX;
> > dev->mode_config.max_height = YRES_MAX;
> > +   dev->mode_config.cursor_width = 512;
> > +   dev->mode_config.cursor_height = 512;
> > dev->mode_config.preferred_depth = 24;
> > dev->mode_config.helper_private = _mode_config_helpers;
> >  
> > -- 
> > 2.27.0
> > 
> 
> -- 
> Rodrigo Siqueira
> https://siqueira.tech



-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


Re: [PATCH] drm/vkms: change the max cursor width/height

2020-07-12 Thread Rodrigo Siqueira
Hi Melissa,

First of all, thanks a lot for your patch! This is a nice change since
it increases the code coverage.

Reviewed-by: Rodrigo Siqueira 

On 07/10, Melissa Wen wrote:
> This change expands the coverage for the IGT kms_cursor_crc test, where
> the size varies between 64 and 512 for a square cursor. With this, in
> addition to the cursor 64x64, this patch enables the test of cursors with
> sizes: 128x128, 256x256, and 512x512.
> 
> Signed-off-by: Melissa Wen 
> ---
>  drivers/gpu/drm/vkms/vkms_drv.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
> index 1e8b2169d834..57a8a397d5e8 100644
> --- a/drivers/gpu/drm/vkms/vkms_drv.c
> +++ b/drivers/gpu/drm/vkms/vkms_drv.c
> @@ -133,6 +133,8 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev)
>   dev->mode_config.min_height = YRES_MIN;
>   dev->mode_config.max_width = XRES_MAX;
>   dev->mode_config.max_height = YRES_MAX;
> + dev->mode_config.cursor_width = 512;
> + dev->mode_config.cursor_height = 512;
>   dev->mode_config.preferred_depth = 24;
>   dev->mode_config.helper_private = _mode_config_helpers;
>  
> -- 
> 2.27.0
> 

-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


Re: [PATCH] drm/vkms: Optimize compute_crc(), blend()

2020-05-31 Thread Rodrigo Siqueira
Hi,

First of all, thanks a lot for all your patch. And thanks Emil for your
feedback.

I have a suggestion here:

Emil:
Could you give me your Acked-by or maybe Reviewed-by for the writeback
series? With that, I can finally apply the series.

Sidong:
Secondly, after applying the writeback series, I would suggest you to
understand Emil's comments (he already provides the link) and prepare a
new patch based on that. Before you submit your patch, I recommend you
to test it with https://patchwork.freedesktop.org/series/68352/ and
kms_flip.

How about that?

Best Regards

On 05/31, Emil Velikov wrote:
> On Sun, 31 May 2020 at 14:12, Sidong Yang  wrote:
> >
> > Optimize looping pixels in compute_crc() and blend(). Calculate
> > src_offset in start of looping horizontally and increase it.
> > It's better than calculating in every pixels.
> >
> When you say "optimize" have you observed any actual benefits of the
> patch - be that smaller binary, faster execution time, etc?
> If there are - mentioned them in the commit message. Otherwise, it
> doesn't optimise anything.
> 
> A while back, I've suggested something similar [1] mostly for cosmetic
> purposes - doubt there's much benefits beyond that.
> 
> HTH
> -Emil
> [1] https://patchwork.freedesktop.org/patch/365177/#comment_674314

-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


[PATCH V4 1/3] drm/vkms: Decouple crc operations from composer

2020-05-11 Thread Rodrigo Siqueira
From: Rodrigo Siqueira 

In the vkms_composer.c, some of the functions related to CRC and compose
have interdependence between each other. This patch reworks some
functions inside vkms_composer to make crc and composer computation
decoupled.

This patch is preparation work for making vkms able to support new
features.

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/vkms_composer.c | 49 
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index 4af2f19480f4..258e659ecfba 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -108,35 +108,31 @@ static void compose_cursor(struct vkms_composer 
*cursor_composer,
  primary_composer, cursor_composer);
 }
 
-static uint32_t _vkms_get_crc(struct vkms_composer *primary_composer,
- struct vkms_composer *cursor_composer)
+static int compose_planes(void **vaddr_out,
+ struct vkms_composer *primary_composer,
+ struct vkms_composer *cursor_composer)
 {
struct drm_framebuffer *fb = _composer->fb;
struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0);
struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj);
-   void *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL);
-   u32 crc = 0;
 
-   if (!vaddr_out) {
-   DRM_ERROR("Failed to allocate memory for output frame.");
-   return 0;
+   if (!*vaddr_out) {
+   *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL);
+   if (!*vaddr_out) {
+   DRM_ERROR("Cannot allocate memory for output frame.");
+   return -ENOMEM;
+   }
}
 
-   if (WARN_ON(!vkms_obj->vaddr)) {
-   kfree(vaddr_out);
-   return crc;
-   }
+   if (WARN_ON(!vkms_obj->vaddr))
+   return -EINVAL;
 
-   memcpy(vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size);
+   memcpy(*vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size);
 
if (cursor_composer)
-   compose_cursor(cursor_composer, primary_composer, vaddr_out);
+   compose_cursor(cursor_composer, primary_composer, *vaddr_out);
 
-   crc = compute_crc(vaddr_out, primary_composer);
-
-   kfree(vaddr_out);
-
-   return crc;
+   return 0;
 }
 
 /**
@@ -157,9 +153,11 @@ void vkms_composer_worker(struct work_struct *work)
struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
struct vkms_composer *primary_composer = NULL;
struct vkms_composer *cursor_composer = NULL;
+   void *vaddr_out = NULL;
u32 crc32 = 0;
u64 frame_start, frame_end;
bool crc_pending;
+   int ret;
 
spin_lock_irq(>composer_lock);
frame_start = crtc_state->frame_start;
@@ -183,14 +181,25 @@ void vkms_composer_worker(struct work_struct *work)
if (crtc_state->num_active_planes == 2)
cursor_composer = crtc_state->active_planes[1]->composer;
 
-   if (primary_composer)
-   crc32 = _vkms_get_crc(primary_composer, cursor_composer);
+   if (!primary_composer)
+   return;
+
+   ret = compose_planes(_out, primary_composer, cursor_composer);
+   if (ret) {
+   if (ret == -EINVAL)
+   kfree(vaddr_out);
+   return;
+   }
+
+   crc32 = compute_crc(vaddr_out, primary_composer);
 
/*
 * The worker can fall behind the vblank hrtimer, make sure we catch up.
 */
while (frame_start <= frame_end)
drm_crtc_add_crc_entry(crtc, true, frame_start++, );
+
+   kfree(vaddr_out);
 }
 
 static const char * const pipe_crc_sources[] = {"auto"};
-- 
2.26.2



[PATCH V4 2/3] drm/vkms: Compute CRC without change input data

2020-05-11 Thread Rodrigo Siqueira
From: Rodrigo Siqueira 

The compute_crc() function is responsible for calculating the
framebuffer CRC value; due to the XRGB format, this function has to
ignore the alpha channel during the CRC computation. Therefore,
compute_crc() set zero to the alpha channel directly in the input
framebuffer, which is not a problem since this function receives a copy
of the original buffer. However, if we want to use this function in a
context without a buffer copy, it will change the initial value. This
patch makes compute_crc() calculate the CRC value without modifying the
input framebuffer.

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/vkms_composer.c | 31 +---
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index 258e659ecfba..686d25e7b01d 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -9,33 +9,40 @@
 
 #include "vkms_drv.h"
 
+static u32 get_pixel_from_buffer(int x, int y, const u8 *buffer,
+const struct vkms_composer *composer)
+{
+   int src_offset = composer->offset + (y * composer->pitch)
+ + (x * composer->cpp);
+
+   return *(u32 *)[src_offset];
+}
+
 /**
  * compute_crc - Compute CRC value on output frame
  *
- * @vaddr_out: address to final framebuffer
+ * @vaddr: address to final framebuffer
  * @composer: framebuffer's metadata
  *
  * returns CRC value computed using crc32 on the visible portion of
  * the final framebuffer at vaddr_out
  */
-static uint32_t compute_crc(void *vaddr_out, struct vkms_composer *composer)
+static uint32_t compute_crc(const u8 *vaddr,
+   const struct vkms_composer *composer)
 {
-   int i, j, src_offset;
+   int x, y;
int x_src = composer->src.x1 >> 16;
int y_src = composer->src.y1 >> 16;
int h_src = drm_rect_height(>src) >> 16;
int w_src = drm_rect_width(>src) >> 16;
-   u32 crc = 0;
+   u32 crc = 0, pixel = 0;
 
-   for (i = y_src; i < y_src + h_src; ++i) {
-   for (j = x_src; j < x_src + w_src; ++j) {
-   src_offset = composer->offset
-+ (i * composer->pitch)
-+ (j * composer->cpp);
+   for (y = y_src; y < y_src + h_src; ++y) {
+   for (x = x_src; x < x_src + w_src; ++x) {
/* XRGB format ignores Alpha channel */
-   memset(vaddr_out + src_offset + 24, 0,  8);
-   crc = crc32_le(crc, vaddr_out + src_offset,
-  sizeof(u32));
+   pixel = get_pixel_from_buffer(x, y, vaddr, composer);
+   bitmap_clear((void *), 0, 8);
+   crc = crc32_le(crc, (void *), sizeof(u32));
}
}
 
-- 
2.26.2



[PATCH V4 3/3] drm/vkms: Add support for writeback

2020-05-11 Thread Rodrigo Siqueira
From: Rodrigo Siqueira 

This patch implements the necessary functions to add writeback support
for vkms. This feature is useful for testing compositors if you don't
have hardware with writeback support.

Change in V3 (Daniel):
- If writeback is enabled, compose everything into the writeback buffer
instead of CRC private buffer.
- Guarantees that the CRC will match exactly what we have in the
writeback buffer.

Change in V2:
- Rework signal completion (Brian)
- Integrates writeback with active_planes (Daniel)
- Compose cursor (Daniel)

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/Makefile |   9 +-
 drivers/gpu/drm/vkms/vkms_composer.c  |  16 ++-
 drivers/gpu/drm/vkms/vkms_drv.c   |   4 +
 drivers/gpu/drm/vkms/vkms_drv.h   |   8 ++
 drivers/gpu/drm/vkms/vkms_output.c|  10 ++
 drivers/gpu/drm/vkms/vkms_writeback.c | 142 ++
 6 files changed, 186 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/vkms/vkms_writeback.c

diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
index 0b767d7efa24..333d3cead0e3 100644
--- a/drivers/gpu/drm/vkms/Makefile
+++ b/drivers/gpu/drm/vkms/Makefile
@@ -1,4 +1,11 @@
 # SPDX-License-Identifier: GPL-2.0-only
-vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o 
vkms_composer.o
+vkms-y := \
+   vkms_drv.o \
+   vkms_plane.o \
+   vkms_output.o \
+   vkms_crtc.o \
+   vkms_gem.o \
+   vkms_composer.o \
+   vkms_writeback.o
 
 obj-$(CONFIG_DRM_VKMS) += vkms.o
diff --git a/drivers/gpu/drm/vkms/vkms_composer.c 
b/drivers/gpu/drm/vkms/vkms_composer.c
index 686d25e7b01d..19849e39f8b9 100644
--- a/drivers/gpu/drm/vkms/vkms_composer.c
+++ b/drivers/gpu/drm/vkms/vkms_composer.c
@@ -160,16 +160,17 @@ void vkms_composer_worker(struct work_struct *work)
struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
struct vkms_composer *primary_composer = NULL;
struct vkms_composer *cursor_composer = NULL;
+   bool crc_pending, wb_pending;
void *vaddr_out = NULL;
u32 crc32 = 0;
u64 frame_start, frame_end;
-   bool crc_pending;
int ret;
 
spin_lock_irq(>composer_lock);
frame_start = crtc_state->frame_start;
frame_end = crtc_state->frame_end;
crc_pending = crtc_state->crc_pending;
+   wb_pending = crtc_state->wb_pending;
crtc_state->frame_start = 0;
crtc_state->frame_end = 0;
crtc_state->crc_pending = false;
@@ -191,9 +192,12 @@ void vkms_composer_worker(struct work_struct *work)
if (!primary_composer)
return;
 
+   if (wb_pending)
+   vaddr_out = crtc_state->active_writeback;
+
ret = compose_planes(_out, primary_composer, cursor_composer);
if (ret) {
-   if (ret == -EINVAL)
+   if (ret == -EINVAL && !wb_pending)
kfree(vaddr_out);
return;
}
@@ -206,6 +210,14 @@ void vkms_composer_worker(struct work_struct *work)
while (frame_start <= frame_end)
drm_crtc_add_crc_entry(crtc, true, frame_start++, );
 
+   if (wb_pending) {
+   drm_writeback_signal_completion(>wb_connector, 0);
+   spin_lock_irq(>composer_lock);
+   crtc_state->wb_pending = false;
+   spin_unlock_irq(>composer_lock);
+   return;
+   }
+
kfree(vaddr_out);
 }
 
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index 1e8b2169d834..34dd74dc8eb0 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -39,6 +39,10 @@ bool enable_cursor = true;
 module_param_named(enable_cursor, enable_cursor, bool, 0444);
 MODULE_PARM_DESC(enable_cursor, "Enable/Disable cursor support");
 
+bool enable_writeback;
+module_param_named(enable_writeback, enable_writeback, bool, 0444);
+MODULE_PARM_DESC(enable_writeback, "Enable/Disable writeback connector");
+
 static const struct file_operations vkms_driver_fops = {
.owner  = THIS_MODULE,
.open   = drm_open,
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index f4036bb0b9a8..35f0b71413c9 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -8,6 +8,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define XRES_MIN20
 #define YRES_MIN20
@@ -19,6 +20,7 @@
 #define YRES_MAX  8192
 
 extern bool enable_cursor;
+extern bool enable_writeback;
 
 struct vkms_composer {
struct drm_framebuffer fb;
@@ -52,9 +54,11 @@ struct vkms_crtc_state {
int num_active_planes;
/* stack of active planes for crc computation, should be in z order */
struct vkms_plane_state **active_planes;
+   void *active_writeback;
 
/* below three are protected by vkms_output.composer_

[PATCH V4 0/3] drm/vkms: Introduces writeback support

2020-05-11 Thread Rodrigo Siqueira
This is the V4 version of a series that introduces basic writeback
support to VKMS. This patchset starts with a pre-work that aims to make
VKMS composer operations ready for getting the writeback support; it has
updates on the CRC functions and reworks a small part of the VKMS
framebuffer operations. Finally, the latest patch introduces the
writeback support in VKMS.

The previous series was reviewed and tested, this patchset only rebases
the code on the latest version of drm-misc-next (I also tested it). It
is important to highlight, that we have an IGT test for validating
writeback feature as can be seen at:

IGT writeback tests: https://patchwork.freedesktop.org/series/68352/

Best Regards

Rodrigo Siqueira (3):
  drm/vkms: Decouple crc operations from composer
  drm/vkms: Compute CRC without change input data
  drm/vkms: Add support for writeback

 drivers/gpu/drm/vkms/Makefile |   9 +-
 drivers/gpu/drm/vkms/vkms_composer.c  |  94 +++--
 drivers/gpu/drm/vkms/vkms_drv.c   |   4 +
 drivers/gpu/drm/vkms/vkms_drv.h   |   8 ++
 drivers/gpu/drm/vkms/vkms_output.c|  10 ++
 drivers/gpu/drm/vkms/vkms_writeback.c | 142 ++
 6 files changed, 233 insertions(+), 34 deletions(-)
 create mode 100644 drivers/gpu/drm/vkms/vkms_writeback.c

-- 
2.26.2


Re: [PATCH] drm/vkms: enable cursor by default

2020-05-06 Thread Rodrigo Siqueira
Applied to drm-misc-next.

On 03/24, Rodrigo Siqueira wrote:
> Hi Melissa,
> 
> First of all, thanks for your patch.
> 
> I agree with you, it makes more sense to me if we enable cursors by
> default. I don't remember why we decided to add it as a disabled by
> default.
> 
> Reviewed-by: Rodrigo Siqueira 
> 
> On 03/21, Melissa Wen wrote:
> > This patch proposes a change in the behavior of the cursor to enable it as
> > soon as the vkms module is added. Enabling the cursor by default appears
> > to be an expected and more friendly behavior, especially when running IGT
> > tests.
> > 
> > Signed-off-by: Melissa Wen 
> > ---
> >  drivers/gpu/drm/vkms/vkms_drv.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/gpu/drm/vkms/vkms_drv.c 
> > b/drivers/gpu/drm/vkms/vkms_drv.c
> > index 860de052e820..6e6feecf7f20 100644
> > --- a/drivers/gpu/drm/vkms/vkms_drv.c
> > +++ b/drivers/gpu/drm/vkms/vkms_drv.c
> > @@ -34,7 +34,7 @@
> >  
> >  static struct vkms_device *vkms_device;
> >  
> > -bool enable_cursor;
> > +bool enable_cursor = true;
> >  module_param_named(enable_cursor, enable_cursor, bool, 0444);
> >  MODULE_PARM_DESC(enable_cursor, "Enable/Disable cursor support");
> >  
> > -- 
> > 2.25.1
> > 
> 
> -- 
> Rodrigo Siqueira
> https://siqueira.tech



-- 
Rodrigo Siqueira
https://siqueira.tech


signature.asc
Description: PGP signature


Re: [PATCH] amdgpu: fix gcc-4.8 build warnings

2020-04-28 Thread Rodrigo Siqueira
Thanks for your patch.

Reviewed-by: Rodrigo Siqueira 

On 04/28, Arnd Bergmann wrote:
> Older compilers warn about initializers with incorrect curly
> braces:
> 
> drivers/gpu/drm/drm_dp_mst_topology.c: In function 
> 'drm_dp_mst_dsc_aux_for_port':
> drivers/gpu/drm/drm_dp_mst_topology.c:5497:9: error: missing braces around 
> initializer [-Werror=missing-braces]
>   struct drm_dp_desc desc = { 0 };
>  ^
> 
> Change all instances in the amd gpu driver to using the GNU empty
> initializer extension.
> 
> Signed-off-by: Arnd Bergmann 
> ---
>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +-
>  drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c| 2 +-
>  drivers/gpu/drm/amd/display/dc/bios/command_table2.c  | 4 ++--
>  drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 2 +-
>  drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c  | 6 +++---
>  drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hubp.c | 6 +++---
>  drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +-
>  drivers/gpu/drm/amd/display/dc/dcn21/dcn21_hubp.c | 8 
>  8 files changed, 16 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index 7f4417981bff..81ce3103d751 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -8695,7 +8695,7 @@ bool amdgpu_dm_psr_enable(struct dc_stream_state 
> *stream)
>  {
>   struct dc_link *link = stream->link;
>   unsigned int vsync_rate_hz = 0;
> - struct dc_static_screen_params params = {0};
> + struct dc_static_screen_params params = { };
>   /* Calculate number of static frames before generating interrupt to
>* enter PSR.
>*/
> diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c 
> b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
> index 37fa7b48250e..5484a316eaa8 100644
> --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
> +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
> @@ -294,7 +294,7 @@ static enum bp_result bios_parser_get_i2c_info(struct 
> dc_bios *dcb,
>   struct atom_display_object_path_v2 *object;
>   struct atom_common_record_header *header;
>   struct atom_i2c_record *record;
> - struct atom_i2c_record dummy_record = {0};
> + struct atom_i2c_record dummy_record = { };
>   struct bios_parser *bp = BP_FROM_DCB(dcb);
>  
>   if (!info)
> diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c 
> b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
> index 8edc2506d49e..5e186c135921 100644
> --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
> +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c
> @@ -113,7 +113,7 @@ static void encoder_control_dmcub(
>   struct dc_dmub_srv *dmcub,
>   struct dig_encoder_stream_setup_parameters_v1_5 *dig)
>  {
> - struct dmub_rb_cmd_digx_encoder_control encoder_control = { 0 };
> + struct dmub_rb_cmd_digx_encoder_control encoder_control = { };
>  
>   encoder_control.header.type = DMUB_CMD__VBIOS;
>   encoder_control.header.sub_type = DMUB_CMD__VBIOS_DIGX_ENCODER_CONTROL;
> @@ -339,7 +339,7 @@ static void set_pixel_clock_dmcub(
>   struct dc_dmub_srv *dmcub,
>   struct set_pixel_clock_parameter_v1_7 *clk)
>  {
> - struct dmub_rb_cmd_set_pixel_clock pixel_clock = { 0 };
> + struct dmub_rb_cmd_set_pixel_clock pixel_clock = { };
>  
>   pixel_clock.header.type = DMUB_CMD__VBIOS;
>   pixel_clock.header.sub_type = DMUB_CMD__VBIOS_SET_PIXEL_CLOCK;
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c 
> b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> index 24c5765890fa..ee3ef5094fd1 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
> @@ -698,7 +698,7 @@ void rn_clk_mgr_construct(
>   struct dccg *dccg)
>  {
>   struct dc_debug_options *debug = >dc->debug;
> - struct dpm_clocks clock_table = { 0 };
> + struct dpm_clocks clock_table = { };
>  
>   clk_mgr->base.ctx = ctx;
>   clk_mgr->base.funcs = _funcs;
> diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c 
> b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
> index 9ef9e50a34fa..7cbfe740a947 100644
> --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
> +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
> @@ -2683,9 +2683,9 @@ static void dp_test_send_link_test_pattern(struct 
> dc_link *link

[PATCH 1/2] drm/vkms: Add enable/disable functions per connector

2019-06-30 Thread Rodrigo Siqueira
Currently, virtual and writeback connectors have the code responsible
for initialization and cleanup spread around different places in vkms.
This patch creates an enable and disable function per connector which
allows vkms to hotplug connectors easily.

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/vkms_drv.h   |  5 ++
 drivers/gpu/drm/vkms/vkms_output.c| 84 +--
 drivers/gpu/drm/vkms/vkms_writeback.c | 31 --
 3 files changed, 83 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index 9ff2cd4ebf81..a1ca5c658355 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -152,7 +152,12 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const 
char *source_name,
 /* Composer Support */
 void vkms_composer_worker(struct work_struct *work);
 
+/* Virtual connector */
+int enable_virtual_connector(struct vkms_device *vkmsdev);
+void disable_virtual_connector(struct vkms_device *vkmsdev);
+
 /* Writeback */
 int enable_writeback_connector(struct vkms_device *vkmsdev);
+void disable_writeback_connector(struct vkms_device *connector);
 
 #endif /* _VKMS_DRV_H_ */
diff --git a/drivers/gpu/drm/vkms/vkms_output.c 
b/drivers/gpu/drm/vkms/vkms_output.c
index aea1d4410864..26ecab52e82e 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -6,6 +6,7 @@
 
 static void vkms_connector_destroy(struct drm_connector *connector)
 {
+   drm_connector_unregister(connector);
drm_connector_cleanup(connector);
 }
 
@@ -35,37 +36,19 @@ static const struct drm_connector_helper_funcs 
vkms_conn_helper_funcs = {
.get_modes= vkms_conn_get_modes,
 };
 
-int vkms_output_init(struct vkms_device *vkmsdev, int index)
+int enable_virtual_connector(struct vkms_device *vkmsdev)
 {
struct vkms_output *output = >output;
-   struct drm_device *dev = >drm;
struct drm_connector *connector = >connector;
struct drm_encoder *encoder = >encoder;
-   struct drm_crtc *crtc = >crtc;
-   struct drm_plane *primary, *cursor = NULL;
+   struct drm_device *dev = >drm;
int ret;
 
-   primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index);
-   if (IS_ERR(primary))
-   return PTR_ERR(primary);
-
-   if (enable_cursor) {
-   cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index);
-   if (IS_ERR(cursor)) {
-   ret = PTR_ERR(cursor);
-   goto err_cursor;
-   }
-   }
-
-   ret = vkms_crtc_init(dev, crtc, primary, cursor);
-   if (ret)
-   goto err_crtc;
-
ret = drm_connector_init(dev, connector, _connector_funcs,
 DRM_MODE_CONNECTOR_VIRTUAL);
if (ret) {
DRM_ERROR("Failed to init connector\n");
-   goto err_connector;
+   return ret;
}
 
drm_connector_helper_add(connector, _conn_helper_funcs);
@@ -84,17 +67,7 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index)
goto err_attach;
}
 
-   if (enable_writeback) {
-   ret = enable_writeback_connector(vkmsdev);
-   if (!ret) {
-   output->composer_enabled = true;
-   DRM_INFO("Writeback connector enabled");
-   } else {
-   DRM_ERROR("Failed to init writeback connector\n");
-   }
-   }
-
-   drm_mode_config_reset(dev);
+   drm_connector_register(connector);
 
return 0;
 
@@ -104,6 +77,53 @@ int vkms_output_init(struct vkms_device *vkmsdev, int index)
 err_encoder:
drm_connector_cleanup(connector);
 
+   return ret;
+}
+
+void disable_virtual_connector(struct vkms_device *vkmsdev)
+{
+   struct vkms_output *output = >output;
+
+   drm_connector_unregister(>connector);
+   drm_connector_cleanup(>connector);
+   drm_encoder_cleanup(>encoder);
+}
+
+int vkms_output_init(struct vkms_device *vkmsdev, int index)
+{
+   struct vkms_output *output = >output;
+   struct drm_device *dev = >drm;
+   struct drm_crtc *crtc = >crtc;
+   struct drm_plane *primary, *cursor = NULL;
+   int ret;
+
+   primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index);
+   if (IS_ERR(primary))
+   return PTR_ERR(primary);
+
+   if (enable_cursor) {
+   cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index);
+   if (IS_ERR(cursor)) {
+   ret = PTR_ERR(cursor);
+   goto err_cursor;
+   }
+   }
+
+   ret = vkms_crtc_init(dev, crtc, primary, cursor);
+   if (ret)
+   goto err_crtc;
+
+   ret = enable_virtual_connector(vkmsdev);
+   if 

[PATCH 2/2] drm/vkms: Introduce configfs for enabling/disabling connectors

2019-06-30 Thread Rodrigo Siqueira
This patch introduces an implementation of vkms subsystems through
configfs; we want to be able to reconfigure vkms instance without having
to reload the module. This commit adds the primary support for configfs
by allowing vkms to expose the ability to enable/disable its connectors.

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/Makefile|   3 +-
 drivers/gpu/drm/vkms/vkms_configfs.c | 229 +++
 drivers/gpu/drm/vkms/vkms_drv.c  |   6 +
 drivers/gpu/drm/vkms/vkms_drv.h  |  12 ++
 4 files changed, 249 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/vkms/vkms_configfs.c

diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile
index 333d3cead0e3..f90c016cd9fe 100644
--- a/drivers/gpu/drm/vkms/Makefile
+++ b/drivers/gpu/drm/vkms/Makefile
@@ -6,6 +6,7 @@ vkms-y := \
vkms_crtc.o \
vkms_gem.o \
vkms_composer.o \
-   vkms_writeback.o
+   vkms_writeback.o \
+   vkms_configfs.o
 
 obj-$(CONFIG_DRM_VKMS) += vkms.o
diff --git a/drivers/gpu/drm/vkms/vkms_configfs.c 
b/drivers/gpu/drm/vkms/vkms_configfs.c
new file mode 100644
index ..5d1a30517cca
--- /dev/null
+++ b/drivers/gpu/drm/vkms/vkms_configfs.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include "vkms_drv.h"
+
+static struct config_group *connector_group;
+static struct vkms_device *vkms_device;
+
+static char *available_connectors[] = {
+   "Virtual",
+   "Writeback",
+};
+
+struct connectors_fs {
+   struct config_item item;
+   bool enable;
+};
+
+static int enable_connector(const char *name)
+{
+   int ret = 0;
+
+   if (!strcmp(name, "Writeback"))
+   ret = enable_writeback_connector(vkms_device);
+   else if (!strcmp(name, "Virtual"))
+   ret = enable_virtual_connector(vkms_device);
+
+   if (ret)
+   return ret;
+
+   drm_mode_config_reset(_device->drm);
+   return 0;
+}
+
+static void disable_connector(const char *name)
+{
+   if (!strcmp(name, "Writeback"))
+   disable_writeback_connector(vkms_device);
+   else if (!strcmp(name, "Virtual"))
+   disable_virtual_connector(vkms_device);
+}
+
+static inline struct connectors_fs *to_conn_item(struct config_item *item)
+{
+   return item ? container_of(item, struct connectors_fs, item) : NULL;
+}
+
+static ssize_t conn_fs_enable_show(struct config_item *item, char *page)
+{
+   struct connectors_fs *conn_item = to_conn_item(item);
+
+   return sprintf(page, "%d\n", conn_item->enable);
+}
+
+static ssize_t conn_fs_enable_store(struct config_item *item,
+   const char *page, size_t count)
+{
+   struct connectors_fs *conn_item = to_conn_item(item);
+   char *p = (char *)page;
+   unsigned int enable;
+   int ret;
+
+   ret = kstrtouint(p, 10, );
+   if (ret)
+   return -EINVAL;
+
+   if (enable > 1)
+   return -EINVAL;
+
+   if (enable == conn_item->enable)
+   return count;
+
+   if (enable) {
+   ret = enable_connector(item->ci_name);
+   if (ret)
+   return ret;
+   } else {
+   disable_connector(item->ci_name);
+   }
+
+   conn_item->enable = enable ? true : false;
+   return count;
+}
+
+CONFIGFS_ATTR(conn_fs_, enable);
+
+static struct configfs_attribute *connectors_fs_attrs[] = {
+   _fs_attr_enable,
+   NULL,
+};
+
+static void connectors_fs_release(struct config_item *item)
+{
+   kfree(to_conn_item(item));
+}
+
+static struct configfs_item_operations connectors_fs_ops = {
+   .release = connectors_fs_release,
+};
+
+static const struct config_item_type connectors_fs_type = {
+   .ct_item_ops= _fs_ops,
+   .ct_attrs   = connectors_fs_attrs,
+   .ct_owner   = THIS_MODULE,
+};
+
+static struct config_item *make_connector_item(struct config_group *group,
+  const char *name)
+{
+   struct connectors_fs *conn_item;
+   int i, ret, total_conn = ARRAY_SIZE(available_connectors);
+
+   for (i = 0; i < total_conn; i++)
+   if (!strcmp(name, available_connectors[i]))
+   break;
+
+   if (i == total_conn)
+   return ERR_PTR(-EINVAL);
+
+   ret = enable_connector(name);
+   if (ret)
+   return ERR_PTR(ret);
+
+   conn_item = kzalloc(sizeof(*conn_item), GFP_KERNEL);
+   if (!conn_item)
+   return ERR_PTR(-ENOMEM);
+
+   config_item_init_type_name(_item->item, name,
+  _fs_type);
+
+   conn_item->enable = true;
+
+   return _item->item;
+}
+
+static void drop_connector_item(struct config_group *group,
+   

[PATCH 0/2] drm/vkms: Introduce basic support for configfs

2019-06-30 Thread Rodrigo Siqueira
This patchset introduces the support for configfs in vkms by adding a
primary structure for handling the vkms subsystem and exposing
connectors as a use case.  This series allows enabling/disabling virtual
and writeback connectors on the fly. The first patch of this series
reworks the initialization and cleanup code of each type of connector,
with this change, the second patch adds the configfs support for vkms.
It is important to highlight that this patchset depends on
https://patchwork.freedesktop.org/series/61738/.

After applying this series, the user can utilize these features with the
following steps:

1. Load vkms without parameter

  modprobe vkms

2. Mount a configfs filesystem

  mount -t configfs none /mnt/

After that, the vkms subsystem will look like this:

vkms/
 |__connectors
|__Virtual
|__ enable

The connectors directories have information related to connectors, and
as can be seen, the virtual connector is enabled by default. Inside a
connector directory (e.g., Virtual) has an attribute named ‘enable’
which is used to enable and disable the target connector. For example,
the Virtual connector has the enable attribute set to 1. If the user
wants to enable the writeback connector it is required to use the mkdir
command, as follows:

  cd /mnt/vkms/connectors
  mkdir Writeback

After the above command, the writeback connector will be enabled, and
the user could see the following tree:

vkms/
 |__connectors
|__Virtual
|   |__ enable
|__Writeback
|__ enable

If the user wants to remove the writeback connector, it is required to
use the command rmdir, for example

  rmdir Writeback

Another way to enable and disable a connector it is by using the enable
attribute, for example, we can disable the Virtual connector with:

  echo 0 > /mnt/vkms/connectors/Virtual/enable

And enable it again with:

  echo 1 > /mnt/vkms/connectors/Virtual/enable

It is important to highlight that configfs 'obey' the parameters used
during the vkms load and does not allow users to remove a connector
directory if it was load via module parameter. For example:

  modprobe vkms enable_writeback=1

vkms/
 |__connectors
|__Virtual
|   |__ enable
|__Writeback
|__ enable

If the user tries to remove the Writeback connector with “rmdir
Writeback”, the operation will be not permitted because the Writeback
connector was loaded with the modules. However, the user may disable the
writeback connector with:

  echo 0 > /mnt/vkms/connectors/Writeback/enable


Rodrigo Siqueira (2):
  drm/vkms: Add enable/disable functions per connector
  drm/vkms: Introduce configfs for enabling/disabling connectors

 drivers/gpu/drm/vkms/Makefile |   3 +-
 drivers/gpu/drm/vkms/vkms_configfs.c  | 229 ++
 drivers/gpu/drm/vkms/vkms_drv.c   |   6 +
 drivers/gpu/drm/vkms/vkms_drv.h   |  17 ++
 drivers/gpu/drm/vkms/vkms_output.c|  84 ++
 drivers/gpu/drm/vkms/vkms_writeback.c |  31 +++-
 6 files changed, 332 insertions(+), 38 deletions(-)
 create mode 100644 drivers/gpu/drm/vkms/vkms_configfs.c

-- 
2.21.0


-- 
Rodrigo Siqueira
https://siqueira.tech


Re: [Intel-gfx] [PATCH V4] drm/drm_vblank: Change EINVAL by the correct errno

2019-06-26 Thread Rodrigo Siqueira
On Wed, Jun 26, 2019 at 4:53 AM Daniel Vetter  wrote:
>
> On Wed, Jun 26, 2019 at 4:00 AM Rodrigo Siqueira
>  wrote:
> >
> > On 06/19, Daniel Vetter wrote:
> > > On Wed, Jun 19, 2019 at 09:48:56AM +0200, Daniel Vetter wrote:
> > > > On Tue, Jun 18, 2019 at 11:07:50PM -0300, Rodrigo Siqueira wrote:
> > > > > For historical reason, the function drm_wait_vblank_ioctl always 
> > > > > return
> > > > > -EINVAL if something gets wrong. This scenario limits the flexibility
> > > > > for the userspace make detailed verification of the problem and take
> > > > > some action. In particular, the validation of “if (!dev->irq_enabled)”
> > > > > in the drm_wait_vblank_ioctl is responsible for checking if the driver
> > > > > support vblank or not. If the driver does not support VBlank, the
> > > > > function drm_wait_vblank_ioctl returns EINVAL which does not represent
> > > > > the real issue; this patch changes this behavior by return EOPNOTSUPP.
> > > > > Additionally, some operations are unsupported by this function, and
> > > > > returns EINVAL; this patch also changes the return value to EOPNOTSUPP
> > > > > in this case. Lastly, the function drm_wait_vblank_ioctl is invoked by
> > > > > libdrm, which is used by many compositors; because of this, it is
> > > > > important to check if this change breaks any compositor. In this 
> > > > > sense,
> > > > > the following projects were examined:
> > > > >
> > > > > * Drm-hwcomposer
> > > > > * Kwin
> > > > > * Sway
> > > > > * Wlroots
> > > > > * Wayland-core
> > > > > * Weston
> > > > > * Xorg (67 different drivers)
> > > > >
> > > > > For each repository the verification happened in three steps:
> > > > >
> > > > > * Update the main branch
> > > > > * Look for any occurrence "drmWaitVBlank" with the command:
> > > > >   git grep -n "drmWaitVBlank"
> > > > > * Look in the git history of the project with the command:
> > > > >   git log -SdrmWaitVBlank
> > > > >
> > > > > Finally, none of the above projects validate the use of EINVAL which
> > > > > make safe, at least for these projects, to change the return values.
> > > > >
> > > > > Change since V3:
> > > > >  - Return EINVAL for _DRM_VBLANK_SIGNAL (Daniel)
> > > > >
> > > > > Change since V2:
> > > > >  Daniel Vetter and Chris Wilson
> > > > >  - Replace ENOTTY by EOPNOTSUPP
> > > > >  - Return EINVAL if the parameters are wrong
> > > > >
> > > >
> > > > Reviewed-by: Daniel Vetter 
> > > >
> > > > Apologies for the confusion on the last time around. btw if someone 
> > > > tells
> > > > you "r-b (or a-b) with these changes", then just apply the r-b/a-b tag
> > > > next time around. Otherwise people will re-review the same thing over 
> > > > and
> > > > over again.
> > >
> > > btw when resending patches it's good practice to add anyone who commented
> > > on it (or who commented on the igt test for the same patch and other way
> > > round) onto the explicit Cc: list of the patch. That way it's easier for
> > > them to follow the patch evolution and do a quick r-b once they're happy.
> >
> > Thanks for these valuable tips.
> > Do you think that is a good idea to resend this patch CC's everybody? Or
> > is it ok if I just apply it?
>
> Hm I thought I answered that on irc ... but just today I realized that
> we missed 2 ioctls. There's also drm_crtc_get_sequence_ioctl and
> drm_crtc_queue_sequence_ioctl which have the same dev->irq_enabled
> check and I think should be treated the same.

Hi,

I reexamined all the composers described in the commit message (latest
versions) to check if any project use and validate the return value
from  drm_crtc_get_sequence_ioctl and drm_crtc_queue_sequence_ioctl. I
noticed that mesa and xserver use them. FWIU replace EINVAL by
EOPNOTSUPP is harmless for mesa project, however it is not the same
for xserver.

Take a look at line 189 and 238 of hw/xfree86/drivers/modesetting/vblank.c

* 
https://gitlab.freedesktop.org/xorg/xserver/blob/master/hw/xfree86/drivers/modesetting/vblank.c#L238
* 
https://gitlab.freedesktop.org/xorg/xserver/blob/master/hw/xfree86/drivers/modeset

[RESEND PATCH V3] drm/drm_vblank: Change EINVAL by the correct errno

2019-06-13 Thread Rodrigo Siqueira
For historical reason, the function drm_wait_vblank_ioctl always return
-EINVAL if something gets wrong. This scenario limits the flexibility
for the userspace make detailed verification of the problem and take
some action. In particular, the validation of “if (!dev->irq_enabled)”
in the drm_wait_vblank_ioctl is responsible for checking if the driver
support vblank or not. If the driver does not support VBlank, the
function drm_wait_vblank_ioctl returns EINVAL which does not represent
the real issue; this patch changes this behavior by return EOPNOTSUPP.
Additionally, some operations are unsupported by this function, and
returns EINVAL; this patch also changes the return value to EOPNOTSUPP
in this case. Lastly, the function drm_wait_vblank_ioctl is invoked by
libdrm, which is used by many compositors; because of this, it is
important to check if this change breaks any compositor. In this sense,
the following projects were examined:

* Drm-hwcomposer
* Kwin
* Sway
* Wlroots
* Wayland-core
* Weston
* Xorg (67 different drivers)

For each repository the verification happened in three steps:

* Update the main branch
* Look for any occurrence "drmWaitVBlank" with the command:
  git grep -n "drmWaitVBlank"
* Look in the git history of the project with the command:
  git log -SdrmWaitVBlank

Finally, none of the above projects validate the use of EINVAL which
make safe, at least for these projects, to change the return values.

Change since V2:
 Daniel Vetter and Chris Wilson
 - Replace ENOTTY by EOPNOTSUPP
 - Return EINVAL if the parameters are wrong

Signed-off-by: Rodrigo Siqueira 
---
Update:
  Now IGT has a way to validate if a driver has vblank support or not.
  See: 
https://gitlab.freedesktop.org/drm/igt-gpu-tools/commit/2d244aed69165753f3adbbd6468db073dc1acf9A

 drivers/gpu/drm/drm_vblank.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 0d704bddb1a6..d76a783a7d4b 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -1578,10 +1578,10 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void 
*data,
unsigned int flags, pipe, high_pipe;
 
if (!dev->irq_enabled)
-   return -EINVAL;
+   return -EOPNOTSUPP;
 
if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
-   return -EINVAL;
+   return -EOPNOTSUPP;
 
if (vblwait->request.type &
~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
-- 
2.21.0


signature.asc
Description: PGP signature


[PATCH] drm/vkms: Remove useless call to drm_connector_register()

2019-03-10 Thread Rodrigo Siqueira
The function vkms_output_init() is invoked during the module
initialization, and it handles the creation/configuration of the vkms
essential elements (e.g., connectors, encoder, etc). Among the
initializations, this function tries to initialize a connector and
register it by calling drm_connector_register(). However, inside the
drm_connector_register(), at the beginning of this function there is the
following validation:

 if (!connector->dev->registered)
   return 0;

In this sense, invoke drm_connector_register() after initializing the
connector has no effect because the register field is false. The
connector register happens when drm_dev_register() is invoked.
Therefore, this commit removes the drm_connector_register() from
vkms_output_init().

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/vkms_output.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_output.c 
b/drivers/gpu/drm/vkms/vkms_output.c
index 3b162b25312e..a6cee4c279c2 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -71,12 +71,6 @@ int vkms_output_init(struct vkms_device *vkmsdev)
 
drm_connector_helper_add(connector, _conn_helper_funcs);
 
-   ret = drm_connector_register(connector);
-   if (ret) {
-   DRM_ERROR("Failed to register connector\n");
-   goto err_connector_register;
-   }
-
ret = drm_encoder_init(dev, encoder, _encoder_funcs,
   DRM_MODE_ENCODER_VIRTUAL, NULL);
if (ret) {
-- 
2.21.0


[PATCH] drm/bochs: Fix NULL dereference on atomic_disable helper

2019-03-10 Thread Rodrigo Siqueira
When the subtest basic-plain-flip from IGT project was executed on Bochs
driver, the following bug appears:

BUG: unable to handle kernel NULL pointer dereference at 
PGD 0 P4D 0
Oops: 0010 [#1] PREEMPT SMP PTI
CPU: 0 PID: 423 Comm: kms_flip Not tainted 5.0.0-VM+ #102
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 
1.12.0-20181126_142135-anatol 04/01/2014
RIP: 0010:  (null)
Code: Bad RIP value.
RSP: 0018:b6a6c0bdfb70 EFLAGS: 00010246
RAX:  RBX: 90467940bf00 RCX: 90467a730318
RDX: 001f RSI: 0003 RDI: 90467bf94050
RBP: 90467bf94050 R08: 904679424e00 R09: 0001
R10: 0001 R11: 0001 R12: 
R13: 90467a46 R14: 90467946d400 R15: c080d460
FS:  7f259c1990c0() GS:90467c80() knlGS:
CS:  0010 DS:  ES:  CR0: 80050033
CR2: ffd6 CR3: b97ec000 CR4: 06f0
Call Trace:
 ? drm_atomic_helper_commit_modeset_disables+0x396/0x3e0 [drm_kms_helper]
 ? drm_atomic_helper_commit_tail+0x19/0x60 [drm_kms_helper]
 ? commit_tail+0x58/0x70 [drm_kms_helper]
 ? drm_atomic_helper_commit+0x103/0x110 [drm_kms_helper]
 ? drm_atomic_helper_set_config+0x80/0x90 [drm_kms_helper]
 ? drm_mode_setcrtc+0x18d/0x690 [drm]
 ? tty_insert_flip_string_fixed_flag+0x85/0xe0
 ? drm_mode_getcrtc+0x180/0x180 [drm]
 ? drm_ioctl_kernel+0xb2/0xf0 [drm]
 ? drm_ioctl+0x25f/0x3f0 [drm]
 ? drm_mode_getcrtc+0x180/0x180 [drm]
 ? do_vfs_ioctl+0xa4/0x630
 ? ksys_ioctl+0x60/0x90
 ? ksys_write+0x4f/0xb0
 ? __x64_sys_ioctl+0x16/0x20
 ? do_syscall_64+0x5b/0x170
 ? entry_SYSCALL_64_after_hwframe+0x44/0xa9

This commit adds an entry to atomic_disable in the drm_crtc_helper_funcs
to avoid the NULL pointer dereference.

Fixes: 0f0eb98e33c6 ("drm/bochs: atomic: add atomic_flush+atomic_enable 
callbacks")

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/bochs/bochs_kms.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/bochs/bochs_kms.c 
b/drivers/gpu/drm/bochs/bochs_kms.c
index 9e7cd6b34106..7e821776727f 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -35,6 +35,11 @@ static void bochs_crtc_atomic_enable(struct drm_crtc *crtc,
 {
 }
 
+static void  bochs_crtc_atomic_disable(struct drm_crtc *crtc,
+  struct drm_crtc_state *old_state)
+{
+}
+
 static void bochs_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
 {
@@ -66,6 +71,7 @@ static const struct drm_crtc_funcs bochs_crtc_funcs = {
 static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
.mode_set_nofb = bochs_crtc_mode_set_nofb,
.atomic_enable = bochs_crtc_atomic_enable,
+   .atomic_disable = bochs_crtc_atomic_disable,
.atomic_flush = bochs_crtc_atomic_flush,
 };
 
-- 
2.21.0


Re: [PATCH] drm/vkms: Solve bug on kms_crc_cursor tests

2019-03-10 Thread Rodrigo Siqueira
vkms_vblank_simulate() we call drm_crtc_accurate_vblank_count()
> > 2. In its turn, drm_crtc_accurate_vblank_count() calls the function
> >drm_update_vblank_count(dev, pipe, false).  /* This false is default */
> > 3. Finally, the “false” used in drm_update_vblank_count(), will be
> >   passed to vkms_get_vblank_timestamp() and the condition “if
> >   (!in_vblank_irq)” will be executed multiple times (we don’t want it).
> > 
> >  - Inside vkms_crc, the issue is that the returned frame value change for
> > every call of drm_crtc_accurate_vblank_count() because
> > in_vblank_irq == false.

Hi Ville,
 
> OK. So why is it changing? AFAICS it should not change unless the
> timer was moved forward in between the calls.

Yes Ville, you’re right. We have to update it only when the function
vkms_vblank_simulate() is invoked (timer move forward), and FWIU we do
it when we call drm_crtc_handle_vblank(). However, the current
implementation of vkms, has a call to drm_crtc_accurate_vblank_count()
inside the vkms_vblank_simulate() which is a problem because it also
update the vblank value. FWIU, this patch fixes this issue by taking the
count value in the data struct instead of call
drm_crtc_accurate_vblank_count() which will avoid the extra update.

Thanks,
Best Regards
 
> > 
> >  - To solve this, I used the value already calculated on vblank->count,
> > instead of using the helper function that updates the value.
> > 
> > Shayenne
> > 
> > > >
> > > > Does it make sense? I am not sure about this crc code behavior.
> > > >
> > > > Shayenne
> > > >
> > > > > > -Daniel
> > > > > >
> > > > > > > ---
> > > > > > >  drivers/gpu/drm/vkms/vkms_crc.c  | 4 +++-
> > > > > > >  drivers/gpu/drm/vkms/vkms_crtc.c | 4 +++-
> > > > > > >  2 files changed, 6 insertions(+), 2 deletions(-)
> > > > > > >
> > > > > > > diff --git a/drivers/gpu/drm/vkms/vkms_crc.c 
> > > > > > > b/drivers/gpu/drm/vkms/vkms_crc.c
> > > > > > > index d7b409a3c0f8..09a8b00ef1f1 100644
> > > > > > > --- a/drivers/gpu/drm/vkms/vkms_crc.c
> > > > > > > +++ b/drivers/gpu/drm/vkms/vkms_crc.c
> > > > > > > @@ -161,6 +161,8 @@ void vkms_crc_work_handle(struct work_struct 
> > > > > > > *work)
> > > > > > > struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
> > > > > > > struct vkms_device *vdev = container_of(out, struct 
> > > > > > > vkms_device,
> > > > > > > output);
> > > > > > > +   unsigned int pipe = drm_crtc_index(crtc);
> > > > > > > +   struct drm_vblank_crtc *vblank = >dev->vblank[pipe];
> > > > > > > struct vkms_crc_data *primary_crc = NULL;
> > > > > > > struct vkms_crc_data *cursor_crc = NULL;
> > > > > > > struct drm_plane *plane;
> > > > > > > @@ -196,7 +198,7 @@ void vkms_crc_work_handle(struct work_struct 
> > > > > > > *work)
> > > > > > > if (primary_crc)
> > > > > > > crc32 = _vkms_get_crc(primary_crc, cursor_crc);
> > > > > > >
> > > > > > > -   frame_end = drm_crtc_accurate_vblank_count(crtc);
> > > > > > > +   frame_end = vblank->count;
> > > > > > >
> > > > > > > /* queue_work can fail to schedule crc_work; add crc for
> > > > > > >  * missing frames
> > > > > > > diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c 
> > > > > > > b/drivers/gpu/drm/vkms/vkms_crtc.c
> > > > > > > index 8a9aeb0a9ea8..9bf3268e2e92 100644
> > > > > > > --- a/drivers/gpu/drm/vkms/vkms_crtc.c
> > > > > > > +++ b/drivers/gpu/drm/vkms/vkms_crtc.c
> > > > > > > @@ -10,6 +10,8 @@ static enum hrtimer_restart 
> > > > > > > vkms_vblank_simulate(struct hrtimer *timer)
> > > > > > >   vblank_hrtimer);
> > > > > > > struct drm_crtc *crtc = >crtc;
> > > > > > > struct vkms_crtc_state *state = 
> > > > > > > to_vkms_crtc_state(crtc->state);
> > > > > > > +   unsigned int pipe = drm_crtc_index(crtc);
> > > > > > > +   struct drm_vblank_crtc *vblank = >dev->vblank[pipe];
> > > > > > > u64 ret_overrun;
> > > > > > > bool ret;
> > > > > > >
> > > > > > > @@ -20,7 +22,7 @@ static enum hrtimer_restart 
> > > > > > > vkms_vblank_simulate(struct hrtimer *timer)
> > > > > > > DRM_ERROR("vkms failure on handling vblank");
> > > > > > >
> > > > > > > if (state && output->crc_enabled) {
> > > > > > > -   u64 frame = drm_crtc_accurate_vblank_count(crtc);
> > > > > > > +   u64 frame = vblank->count;
> > > > > > >
> > > > > > > /* update frame_start only if a queued 
> > > > > > > vkms_crc_work_handle()
> > > > > > >  * has read the data
> > > > > > > --
> > > > > > > 2.17.1
> > > > > > >
> > > > > >
> > > > > > --
> > > > > > Daniel Vetter
> > > > > > Software Engineer, Intel Corporation
> > > > > > http://blog.ffwll.ch
> > > > > > ___
> > > > > > dri-devel mailing list
> > > > > > dri-de...@lists.freedesktop.org
> > > > > > https://lists.freedesktop.org/mailman/listinfo/dri-devel
> > > > >
> > > > > --
> > > > > Ville Syrjälä
> > > > > Intel
> > >
> > > --
> > > Ville Syrjälä
> > > Intel
> 
> -- 
> Ville Syrjälä
> Intel

-- 
Rodrigo Siqueira
https://siqueira.tech
Graduate Student
Department of Computer Science
University of São Paulo


Re: [PATCH] drm/vkms: fix use-after-free when drm_gem_handle_create() fails

2019-03-10 Thread Rodrigo Siqueira
On 03/05, Dmitry Vyukov wrote:
> On Tue, Mar 5, 2019 at 12:23 AM Rodrigo Siqueira
>  wrote:
> >
> > On 02/28, Dmitry Vyukov wrote:
> > > On Thu, Feb 28, 2019 at 12:12 AM Rodrigo Siqueira
> > >  wrote:
> > > >
> > > > On 02/26, Eric Biggers wrote:
> > > > > From: Eric Biggers 
> > > > >
> > > > > If drm_gem_handle_create() fails in vkms_gem_create(), then the
> > > > > vkms_gem_object is freed twice: once when the reference is dropped by
> > > > > drm_gem_object_put_unlocked(), and again by the extra calls to
> > > > > drm_gem_object_release() and kfree().
> > > > >
> > > > > Fix it by skipping the second release and free.
> > > > >
> > > > > This bug was originally found in the vgem driver by syzkaller using
> > > > > fault injection, but I noticed it's also present in the vkms driver.
> > > > >
> > > > > Fixes: 559e50fd34d1 ("drm/vkms: Add dumb operations")
> > > > > Cc: Rodrigo Siqueira 
> > > > > Cc: Haneen Mohammed 
> > > > > Cc: Daniel Vetter 
> > > > > Cc: Chris Wilson 
> > > > > Cc: sta...@vger.kernel.org
> > > > > Signed-off-by: Eric Biggers 
> > > > > ---
> > > > >  drivers/gpu/drm/vkms/vkms_gem.c | 5 +
> > > > >  1 file changed, 1 insertion(+), 4 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/vkms/vkms_gem.c 
> > > > > b/drivers/gpu/drm/vkms/vkms_gem.c
> > > > > index 138b0bb325cf9..69048e73377dc 100644
> > > > > --- a/drivers/gpu/drm/vkms/vkms_gem.c
> > > > > +++ b/drivers/gpu/drm/vkms/vkms_gem.c
> > > > > @@ -111,11 +111,8 @@ struct drm_gem_object *vkms_gem_create(struct 
> > > > > drm_device *dev,
> > > > >
> > > > >   ret = drm_gem_handle_create(file, >gem, handle);
> > > > >   drm_gem_object_put_unlocked(>gem);
> > > > > - if (ret) {
> > > > > - drm_gem_object_release(>gem);
> > > > > - kfree(obj);
> > > > > + if (ret)
> > > > >   return ERR_PTR(ret);
> > > > > - }
> > > > >
> > > > >   return >gem;
> > > > >  }
> > > > > --
> > > > > 2.21.0.rc2.261.ga7da99ff1b-goog
> > > > >
> > > >
> > > > Hi,
> > > >
> > > > Thanks for your patch! :)
> > > >
> > > > The patch looks good for me. I also tested it under the IGT tests on my
> > > > local VM and everything was fine.
> >
> > Hi,
> >
> > Patch applied to drm-misc-fixes.
> >
> > > Hi Rodrigo,
> > >
> > > What are IGT tests? How can I run them?
> >
> > Hi Dmitry,
> >
> > IGT is a test suite focused on DRM drivers.
> >
> > You can clone the project using the link below:
> >
> >   https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
> >
> > In the README, you will find the software dependencies. After you
> > install all the required package, just use:
> >
> >  mkdir build && meson build && cd build && ninja
> 
> Hi Rodrigo,
> 
> Thanks for the info, but this did not work for me.
> I installed all recommended packages (including libdw-dev), but then got:

Hi Dmitry,

I would like to recommend you to join the dri-devel channel (Freenode).
There you can quickly get help from me and others ;)

My nick in the dri-devel is 'siqueira'.

Best Regards
 
> igt-gpu-tools$ mkdir -p build && meson build && cd build && ninja
> The Meson build system
> Version: 0.46.1
> Source dir: /src/igt-gpu-tools
> Build dir: /src/igt-gpu-tools/build
> Build type: native build
> Project name: igt-gpu-tools
> Native C compiler: ccache cc (gcc 7.3.0 "cc (Debian 7.3.0-5) 7.3.0")
> Build machine cpu family: x86_64
> Build machine cpu: x86_64
> Compiler for C supports arguments -Wbad-function-cast: YES
> Compiler for C supports arguments -Wdeclaration-after-statement: YES
> Compiler for C supports arguments -Wformat=2: YES
> Compiler for C supports arguments -Wimplicit-fallthrough=0: YES
> Compiler for C supports arguments -Wlogical-op: YES
> Compiler for C supports arguments -Wmissing-declarations: YES
> Compiler for C supports arguments -Wmissing-format-attribute: YES
> Compiler for C supports arguments -Wmissi

Re: [PATCH v2] drm/vgem: fix use-after-free when drm_gem_handle_create() fails

2019-03-04 Thread Rodrigo Siqueira
On 02/26, Eric Biggers wrote:
> From: Eric Biggers 
> 
> If drm_gem_handle_create() fails in vgem_gem_create(), then the
> drm_vgem_gem_object is freed twice: once when the reference is dropped
> by drm_gem_object_put_unlocked(), and again by __vgem_gem_destroy().
> 
> This was hit by syzkaller using fault injection.
> 
> Fix it by skipping the second free.
> 
> Reported-by: syzbot+e73f2fb5ed5a5df36...@syzkaller.appspotmail.com
> Fixes: af33a9190d02 ("drm/vgem: Enable dmabuf import interfaces")
> Reviewed-by: Chris Wilson 
> Cc: Laura Abbott 
> Cc: Daniel Vetter 
> Cc: sta...@vger.kernel.org
> Signed-off-by: Eric Biggers 
> ---
>  drivers/gpu/drm/vgem/vgem_drv.c | 6 +-
>  1 file changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c
> index 5930facd6d2d8..11a8f99ba18c5 100644
> --- a/drivers/gpu/drm/vgem/vgem_drv.c
> +++ b/drivers/gpu/drm/vgem/vgem_drv.c
> @@ -191,13 +191,9 @@ static struct drm_gem_object *vgem_gem_create(struct 
> drm_device *dev,
>   ret = drm_gem_handle_create(file, >base, handle);
>   drm_gem_object_put_unlocked(>base);
>   if (ret)
> - goto err;
> + return ERR_PTR(ret);
>  
>   return >base;
> -
> -err:
> - __vgem_gem_destroy(obj);
> - return ERR_PTR(ret);
>  }
>  
>  static int vgem_gem_dumb_create(struct drm_file *file, struct drm_device 
> *dev,
> -- 
> 2.21.0.rc2.261.ga7da99ff1b-goog
> 
> ___
> dri-devel mailing list
> dri-de...@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel

Applied to drm-misc-fixes.

Thanks

-- 
Rodrigo Siqueira
https://siqueira.tech
Graduate Student
Department of Computer Science
University of São Paulo


signature.asc
Description: PGP signature


Re: [PATCH] drm/vkms: fix use-after-free when drm_gem_handle_create() fails

2019-03-04 Thread Rodrigo Siqueira
On 02/28, Dmitry Vyukov wrote:
> On Thu, Feb 28, 2019 at 12:12 AM Rodrigo Siqueira
>  wrote:
> >
> > On 02/26, Eric Biggers wrote:
> > > From: Eric Biggers 
> > >
> > > If drm_gem_handle_create() fails in vkms_gem_create(), then the
> > > vkms_gem_object is freed twice: once when the reference is dropped by
> > > drm_gem_object_put_unlocked(), and again by the extra calls to
> > > drm_gem_object_release() and kfree().
> > >
> > > Fix it by skipping the second release and free.
> > >
> > > This bug was originally found in the vgem driver by syzkaller using
> > > fault injection, but I noticed it's also present in the vkms driver.
> > >
> > > Fixes: 559e50fd34d1 ("drm/vkms: Add dumb operations")
> > > Cc: Rodrigo Siqueira 
> > > Cc: Haneen Mohammed 
> > > Cc: Daniel Vetter 
> > > Cc: Chris Wilson 
> > > Cc: sta...@vger.kernel.org
> > > Signed-off-by: Eric Biggers 
> > > ---
> > >  drivers/gpu/drm/vkms/vkms_gem.c | 5 +
> > >  1 file changed, 1 insertion(+), 4 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/vkms/vkms_gem.c 
> > > b/drivers/gpu/drm/vkms/vkms_gem.c
> > > index 138b0bb325cf9..69048e73377dc 100644
> > > --- a/drivers/gpu/drm/vkms/vkms_gem.c
> > > +++ b/drivers/gpu/drm/vkms/vkms_gem.c
> > > @@ -111,11 +111,8 @@ struct drm_gem_object *vkms_gem_create(struct 
> > > drm_device *dev,
> > >
> > >   ret = drm_gem_handle_create(file, >gem, handle);
> > >   drm_gem_object_put_unlocked(>gem);
> > > - if (ret) {
> > > - drm_gem_object_release(>gem);
> > > - kfree(obj);
> > > + if (ret)
> > >   return ERR_PTR(ret);
> > > - }
> > >
> > >   return >gem;
> > >  }
> > > --
> > > 2.21.0.rc2.261.ga7da99ff1b-goog
> > >
> >
> > Hi,
> >
> > Thanks for your patch! :)
> >
> > The patch looks good for me. I also tested it under the IGT tests on my
> > local VM and everything was fine.

Hi,

Patch applied to drm-misc-fixes.
 
> Hi Rodrigo,
> 
> What are IGT tests? How can I run them?

Hi Dmitry,

IGT is a test suite focused on DRM drivers.

You can clone the project using the link below:

  https://gitlab.freedesktop.org/drm/igt-gpu-tools.git

In the README, you will find the software dependencies. After you
install all the required package, just use:

 mkdir build && meson build && cd build && ninja

Finally, if you want to test VKMS, I recommend you to do it inside a VM.

Best Regards
Rodrigo Siqueira

> >
> > Reviewed-by: Rodrigo Siqueira 
> >
> > --
> > Rodrigo Siqueira
> > https://siqueira.tech
> > Graduate Student
> > Department of Computer Science
> > University of São Paulo
> >
> > --
> > You received this message because you are subscribed to the Google Groups 
> > "syzkaller-bugs" group.
> > To unsubscribe from this group and stop receiving emails from it, send an 
> > email to syzkaller-bugs+unsubscr...@googlegroups.com.
> > To view this discussion on the web visit 
> > https://groups.google.com/d/msgid/syzkaller-bugs/20190227231202.tycdbcqtk5ylwp4k%40smtp.gmail.com.
> > For more options, visit https://groups.google.com/d/optout.

-- 
Rodrigo Siqueira
https://siqueira.tech
Graduate Student
Department of Computer Science
University of São Paulo


signature.asc
Description: PGP signature


Re: [PATCH] drm/vkms: fix use-after-free when drm_gem_handle_create() fails

2019-02-27 Thread Rodrigo Siqueira
On 02/26, Eric Biggers wrote:
> From: Eric Biggers 
> 
> If drm_gem_handle_create() fails in vkms_gem_create(), then the
> vkms_gem_object is freed twice: once when the reference is dropped by
> drm_gem_object_put_unlocked(), and again by the extra calls to
> drm_gem_object_release() and kfree().
> 
> Fix it by skipping the second release and free.
> 
> This bug was originally found in the vgem driver by syzkaller using
> fault injection, but I noticed it's also present in the vkms driver.
> 
> Fixes: 559e50fd34d1 ("drm/vkms: Add dumb operations")
> Cc: Rodrigo Siqueira 
> Cc: Haneen Mohammed 
> Cc: Daniel Vetter 
> Cc: Chris Wilson 
> Cc: sta...@vger.kernel.org
> Signed-off-by: Eric Biggers 
> ---
>  drivers/gpu/drm/vkms/vkms_gem.c | 5 +
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c
> index 138b0bb325cf9..69048e73377dc 100644
> --- a/drivers/gpu/drm/vkms/vkms_gem.c
> +++ b/drivers/gpu/drm/vkms/vkms_gem.c
> @@ -111,11 +111,8 @@ struct drm_gem_object *vkms_gem_create(struct drm_device 
> *dev,
>  
>   ret = drm_gem_handle_create(file, >gem, handle);
>   drm_gem_object_put_unlocked(>gem);
> - if (ret) {
> - drm_gem_object_release(>gem);
> - kfree(obj);
> + if (ret)
>   return ERR_PTR(ret);
> - }
>  
>   return >gem;
>  }
> -- 
> 2.21.0.rc2.261.ga7da99ff1b-goog
> 

Hi,

Thanks for your patch! :)

The patch looks good for me. I also tested it under the IGT tests on my
local VM and everything was fine.

Reviewed-by: Rodrigo Siqueira 

-- 
Rodrigo Siqueira
https://siqueira.tech
Graduate Student
Department of Computer Science
University of São Paulo


signature.asc
Description: PGP signature


Re: [PATCH] drm/vkms: Solve bug on kms_crc_cursor tests

2019-02-25 Thread Rodrigo Siqueira
Hi,

First of all, thanks for your patch!

I think you figured out the reason for the extra frame problems :)

The patch worked like a charm. Almost all of the tests in kms_flip are
passing, and the tests related to kms_cursor_crc are working again \o/

I just have some cosmetic comments inline.

On 02/25, Shayenne Moura wrote:
> vkms_crc_work_handle needs the value of the actual frame to
> schedule the workqueue that calls periodically the vblank
> handler and the destroy state functions. However, the frame
> value returned from vkms_vblank_simulate is updated and
> diminished in vblank_get_timestamp because it is not in a
> vblank interrupt, and return an inaccurate value.
> 
> Solve this getting the actual vblank frame directly from the
> vblank->count inside the `struct drm_crtc`, instead of using
> the `drm_accurate_vblank_count` function.

AFAIU, I think the problem that you describe happens when
vkms_vblank_simulate() execute, because of the following steps:

1. Inside vkms_vblank_simulate() we call drm_crtc_accurate_vblank_count()
2. In its turn, drm_crtc_accurate_vblank_count() calls the function
   drm_update_vblank_count(dev, pipe, false).
3. Finally, the “false” used in drm_update_vblank_count(), will be
  passed to vkms_get_vblank_timestamp() and the condition “if
  (!in_vblank_irq)” will be executed multiple times (we don’t want it).

Am I correct? If so, I recommend you to add this level of detail about
the problem and the solution. Finally, IMHO you could change the commit
message for something that describes the problem related to the extra
decrement made by drm_crtc_accurate_vblank_count() inside
vkms_vblank_simulate().
 
> Signed-off-by: Shayenne Moura 
> ---
>  drivers/gpu/drm/vkms/vkms_crc.c  | 4 +++-
>  drivers/gpu/drm/vkms/vkms_crtc.c | 4 +++-
>  2 files changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_crc.c
> index d7b409a3c0f8..09a8b00ef1f1 100644
> --- a/drivers/gpu/drm/vkms/vkms_crc.c
> +++ b/drivers/gpu/drm/vkms/vkms_crc.c
> @@ -161,6 +161,8 @@ void vkms_crc_work_handle(struct work_struct *work)
>   struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
>   struct vkms_device *vdev = container_of(out, struct vkms_device,
>   output);
> + unsigned int pipe = drm_crtc_index(crtc);
> + struct drm_vblank_crtc *vblank = >dev->vblank[pipe];
>   struct vkms_crc_data *primary_crc = NULL;
>   struct vkms_crc_data *cursor_crc = NULL;
>   struct drm_plane *plane;
> @@ -196,7 +198,7 @@ void vkms_crc_work_handle(struct work_struct *work)
>   if (primary_crc)
>   crc32 = _vkms_get_crc(primary_crc, cursor_crc);
>  
> - frame_end = drm_crtc_accurate_vblank_count(crtc);
> + frame_end = vblank->count;
>  
>   /* queue_work can fail to schedule crc_work; add crc for
>* missing frames
> diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c 
> b/drivers/gpu/drm/vkms/vkms_crtc.c
> index 8a9aeb0a9ea8..9bf3268e2e92 100644
> --- a/drivers/gpu/drm/vkms/vkms_crtc.c
> +++ b/drivers/gpu/drm/vkms/vkms_crtc.c
> @@ -10,6 +10,8 @@ static enum hrtimer_restart vkms_vblank_simulate(struct 
> hrtimer *timer)
> vblank_hrtimer);
>   struct drm_crtc *crtc = >crtc;
>   struct vkms_crtc_state *state = to_vkms_crtc_state(crtc->state);
> + unsigned int pipe = drm_crtc_index(crtc);
> + struct drm_vblank_crtc *vblank = >dev->vblank[pipe];

How about have have a function for this operation?

Perhaps, someone here or in the dri-devel channel knows any helper
already available to get this information, try to ask in the channel.

Thanks

>   u64 ret_overrun;
>   bool ret;
>  
> @@ -20,7 +22,7 @@ static enum hrtimer_restart vkms_vblank_simulate(struct 
> hrtimer *timer)
>   DRM_ERROR("vkms failure on handling vblank");
>  
>   if (state && output->crc_enabled) {
> - u64 frame = drm_crtc_accurate_vblank_count(crtc);
> + u64 frame = vblank->count;
>  
>   /* update frame_start only if a queued vkms_crc_work_handle()
>* has read the data
> -- 
> 2.17.1
> 

-- 
Rodrigo Siqueira
https://siqueira.tech
Graduate Student
Department of Computer Science
University of São Paulo


signature.asc
Description: PGP signature


Re: [PATCH] drm/vkms: WARN when hrtimer_forward_now fails

2019-02-10 Thread Rodrigo Siqueira
On 02/06, Shayenne Moura wrote:
> Make the variable have the same type of function hrtimer_forward_now
> return.

Hi,

First of all, thanks for your patch.

Applied to the drm-misc-misc branch of drm-misc.git.

P.s.: I made a tiny change in the commit message.

Best Regards

> Add a warn to verify the hrtimer_forward_now return.
> 
> Signed-off-by: Shayenne Moura 
> ---
>  drivers/gpu/drm/vkms/vkms_crtc.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c 
> b/drivers/gpu/drm/vkms/vkms_crtc.c
> index 5a095610726b..734a3e197df8 100644
> --- a/drivers/gpu/drm/vkms/vkms_crtc.c
> +++ b/drivers/gpu/drm/vkms/vkms_crtc.c
> @@ -16,7 +16,7 @@ static enum hrtimer_restart vkms_vblank_simulate(struct 
> hrtimer *timer)
> vblank_hrtimer);
>   struct drm_crtc *crtc = >crtc;
>   struct vkms_crtc_state *state = to_vkms_crtc_state(crtc->state);
> - int ret_overrun;
> + u64 ret_overrun;
>   bool ret;
>  
>   spin_lock(>lock);
> @@ -43,6 +43,8 @@ static enum hrtimer_restart vkms_vblank_simulate(struct 
> hrtimer *timer)
>  
>   ret_overrun = hrtimer_forward_now(>vblank_hrtimer,
> output->period_ns);
> + WARN_ON(ret_overrun != 1);
> +
>   spin_unlock(>lock);
>  
>   return HRTIMER_RESTART;
> -- 
> 2.17.1
> 

-- 
Rodrigo Siqueira
https://siqueira.tech
Graduate Student
Department of Computer Science
University of São Paulo


signature.asc
Description: PGP signature


Re: [PATCH V2] drm/vkms: Fix license inconsistent

2019-02-10 Thread Rodrigo Siqueira
On 02/06, Daniel Vetter wrote:
> On Wed, Feb 06, 2019 at 12:01:16PM -0200, Rodrigo Siqueira wrote:
> > Fixes license inconsistent related to the VKMS driver and remove the
> > redundant boilerplate comment.
> > 
> > Fixes: 854502fa0a38 ("drm/vkms: Add basic CRTC initialization")
> > 
> > Cc: sta...@vger.kernel.org
> > Signed-off-by: Rodrigo Siqueira 
> > ---
> > Changes in V2:
> >   - Add "Cc: sta...@vger.kernel.org" tag
> 
> Since cc: stable please apply this patch to drm-misc-fixes, not
> drm-misc-next like usual.

Hi,

Applied to the drm-misc-fixes branch of drm-misc.git as Daniel suggested
in the previous message.

Thanks.
 
> Acked-by: Daniel Vetter 
> > 
> >  drivers/gpu/drm/vkms/vkms_crc.c| 3 ++-
> >  drivers/gpu/drm/vkms/vkms_crtc.c   | 8 +---
> >  drivers/gpu/drm/vkms/vkms_drv.c| 7 +--
> >  drivers/gpu/drm/vkms/vkms_drv.h| 2 ++
> >  drivers/gpu/drm/vkms/vkms_gem.c| 8 +---
> >  drivers/gpu/drm/vkms/vkms_output.c | 8 +---
> >  drivers/gpu/drm/vkms/vkms_plane.c  | 8 +---
> >  7 files changed, 9 insertions(+), 35 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/vkms/vkms_crc.c 
> > b/drivers/gpu/drm/vkms/vkms_crc.c
> > index 9d9e8146db90..d7b409a3c0f8 100644
> > --- a/drivers/gpu/drm/vkms/vkms_crc.c
> > +++ b/drivers/gpu/drm/vkms/vkms_crc.c
> > @@ -1,4 +1,5 @@
> > -// SPDX-License-Identifier: GPL-2.0
> > +// SPDX-License-Identifier: GPL-2.0+
> > +
> >  #include "vkms_drv.h"
> >  #include 
> >  #include 
> > diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c 
> > b/drivers/gpu/drm/vkms/vkms_crtc.c
> > index 5a095610726b..6ddaa1610807 100644
> > --- a/drivers/gpu/drm/vkms/vkms_crtc.c
> > +++ b/drivers/gpu/drm/vkms/vkms_crtc.c
> > @@ -1,10 +1,4 @@
> > -// SPDX-License-Identifier: GPL-2.0
> > -/*
> > - * This program is free software; you can redistribute it and/or modify
> > - * it under the terms of the GNU General Public License as published by
> > - * the Free Software Foundation; either version 2 of the License, or
> > - * (at your option) any later version.
> > - */
> > +// SPDX-License-Identifier: GPL-2.0+
> >  
> >  #include "vkms_drv.h"
> >  #include 
> > diff --git a/drivers/gpu/drm/vkms/vkms_drv.c 
> > b/drivers/gpu/drm/vkms/vkms_drv.c
> > index b13f99a5c849..738dd6206d85 100644
> > --- a/drivers/gpu/drm/vkms/vkms_drv.c
> > +++ b/drivers/gpu/drm/vkms/vkms_drv.c
> > @@ -1,9 +1,4 @@
> > -/*
> > - * This program is free software; you can redistribute it and/or modify
> > - * it under the terms of the GNU General Public License as published by
> > - * the Free Software Foundation; either version 2 of the License, or
> > - * (at your option) any later version.
> > - */
> > +// SPDX-License-Identifier: GPL-2.0+
> >  
> >  /**
> >   * DOC: vkms (Virtual Kernel Modesetting)
> > diff --git a/drivers/gpu/drm/vkms/vkms_drv.h 
> > b/drivers/gpu/drm/vkms/vkms_drv.h
> > index e4469cd3d254..81f1cfbeb936 100644
> > --- a/drivers/gpu/drm/vkms/vkms_drv.h
> > +++ b/drivers/gpu/drm/vkms/vkms_drv.h
> > @@ -1,3 +1,5 @@
> > +/* SPDX-License-Identifier: GPL-2.0+ */
> > +
> >  #ifndef _VKMS_DRV_H_
> >  #define _VKMS_DRV_H_
> >  
> > diff --git a/drivers/gpu/drm/vkms/vkms_gem.c 
> > b/drivers/gpu/drm/vkms/vkms_gem.c
> > index 80311daed47a..138b0bb325cf 100644
> > --- a/drivers/gpu/drm/vkms/vkms_gem.c
> > +++ b/drivers/gpu/drm/vkms/vkms_gem.c
> > @@ -1,10 +1,4 @@
> > -// SPDX-License-Identifier: GPL-2.0
> > -/*
> > - * This program is free software; you can redistribute it and/or modify
> > - * it under the terms of the GNU General Public License as published by
> > - * the Free Software Foundation; either version 2 of the License, or
> > - * (at your option) any later version.
> > - */
> > +// SPDX-License-Identifier: GPL-2.0+
> >  
> >  #include 
> >  
> > diff --git a/drivers/gpu/drm/vkms/vkms_output.c 
> > b/drivers/gpu/drm/vkms/vkms_output.c
> > index c5b16efed51a..3b162b25312e 100644
> > --- a/drivers/gpu/drm/vkms/vkms_output.c
> > +++ b/drivers/gpu/drm/vkms/vkms_output.c
> > @@ -1,10 +1,4 @@
> > -// SPDX-License-Identifier: GPL-2.0
> > -/*
> > - * This program is free software; you can redistribute it and/or modify
> > - * it under the terms of the GNU General Public License as published by
> > - * the Free Software Foundation; either version 2 of the License, or
> > - * (at your option) any later version.
&

[PATCH V2] drm/vkms: Fix license inconsistent

2019-02-06 Thread Rodrigo Siqueira
Fixes license inconsistent related to the VKMS driver and remove the
redundant boilerplate comment.

Fixes: 854502fa0a38 ("drm/vkms: Add basic CRTC initialization")

Cc: sta...@vger.kernel.org
Signed-off-by: Rodrigo Siqueira 
---
Changes in V2:
  - Add "Cc: sta...@vger.kernel.org" tag

 drivers/gpu/drm/vkms/vkms_crc.c| 3 ++-
 drivers/gpu/drm/vkms/vkms_crtc.c   | 8 +---
 drivers/gpu/drm/vkms/vkms_drv.c| 7 +--
 drivers/gpu/drm/vkms/vkms_drv.h| 2 ++
 drivers/gpu/drm/vkms/vkms_gem.c| 8 +---
 drivers/gpu/drm/vkms/vkms_output.c | 8 +---
 drivers/gpu/drm/vkms/vkms_plane.c  | 8 +---
 7 files changed, 9 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_crc.c
index 9d9e8146db90..d7b409a3c0f8 100644
--- a/drivers/gpu/drm/vkms/vkms_crc.c
+++ b/drivers/gpu/drm/vkms/vkms_crc.c
@@ -1,4 +1,5 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
+
 #include "vkms_drv.h"
 #include 
 #include 
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index 5a095610726b..6ddaa1610807 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include 
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index b13f99a5c849..738dd6206d85 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -1,9 +1,4 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 /**
  * DOC: vkms (Virtual Kernel Modesetting)
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index e4469cd3d254..81f1cfbeb936 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
 #ifndef _VKMS_DRV_H_
 #define _VKMS_DRV_H_
 
diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c
index 80311daed47a..138b0bb325cf 100644
--- a/drivers/gpu/drm/vkms/vkms_gem.c
+++ b/drivers/gpu/drm/vkms/vkms_gem.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include 
 
diff --git a/drivers/gpu/drm/vkms/vkms_output.c 
b/drivers/gpu/drm/vkms/vkms_output.c
index c5b16efed51a..3b162b25312e 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include 
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c 
b/drivers/gpu/drm/vkms/vkms_plane.c
index 418817600ad1..0e67d2d42f0c 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include 
-- 
2.20.1


-- 
Rodrigo Siqueira
https://siqueira.tech
Graduate Student
Department of Computer Science
University of São Paulo


signature.asc
Description: PGP signature


Re: [PATCH 1/2] drm/vkms: Bugfix extra vblank frame

2019-02-03 Thread Rodrigo Siqueira
On 01/30, Shayenne Moura wrote:
> kms_flip tests are breaking on vkms when simulate vblank because vblank
> event sequence count returns one extra frame after arm vblank event to
> make a page flip.
> 
> When vblank interrupt happens, userspace processes the vblank event and
> issues the next page flip command. Kernel calls queue_work to call
> commit_planes and arm the new page flip. The next vblank picks up the
> newly armed vblank event and vblank interrupt happens again.
> 
> The arm and vblank event are asynchronous, then, on the next vblank, we
> receive x+2 from `get_vblank_timestamp`, instead x+1, although timestamp
> and vblank seqno matches.
> 
> Function `get_vblank_timestamp` is reached by 2 ways:
> 
>   - from `drm_mode_page_flip_ioctl`: driver is doing one atomic operation
> to synchronize planes in the same output. There is no vblank simulation,
> the `drm_crtc_arm_vblank_event` function adds 1 on vblank count, and the
> variable in_vblank_irq is false
>   - from `vkms_vblank_simulate`: since the driver is doing a vblank 
> simulation,
> the variable in_vblank_irq is true.
> 
> Fix this problem subtracting one vblank period from vblank_time when
> `get_vblank_timestamp` is called from trace `drm_mode_page_flip_ioctl`,
> i.e., is not a real vblank interrupt, and getting the timestamp and vblank
> seqno when it is a real vblank interrupt.
> 
> The reason for all this is that get_vblank_timestamp always supplies the
> timestamp for the next vblank event. The hrtimer is the vblank simulator,
> and it needs the correct previous value to present the next vblank. Since
> this is how hw timestamp registers work and what the vblank core expects.
> 
> Signed-off-by: Shayenne Moura 
> Signed-off-by: Daniel Vetter 
> 
> ---
>  drivers/gpu/drm/vkms/vkms_crtc.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c 
> b/drivers/gpu/drm/vkms/vkms_crtc.c
> index d44bfc392491..23146ff2a25b 100644
> --- a/drivers/gpu/drm/vkms/vkms_crtc.c
> +++ b/drivers/gpu/drm/vkms/vkms_crtc.c
> @@ -87,6 +87,9 @@ bool vkms_get_vblank_timestamp(struct drm_device *dev, 
> unsigned int pipe,
>  
>   *vblank_time = output->vblank_hrtimer.node.expires;
>  
> +     if (!in_vblank_irq)
> + *vblank_time -= output->period_ns;
> +
>   return true;
>  }
>  
> -- 
> 2.17.1
> 

Reviewed-by: Rodrigo Siqueira 

-- 
Rodrigo Siqueira
https://siqueira.tech
Graduate Student
Department of Computer Science
University of São Paulo


signature.asc
Description: PGP signature


Re: [PATCH 2/2] drm: vkms: Bugfix racing hrtimer vblank handle

2019-02-03 Thread Rodrigo Siqueira
On 01/30, Shayenne Moura wrote:
> When the vblank irq happens, kernel time subsystem executes
> `vkms_vblank_simulate`. In parallel or not, it prepares all stuff
> necessary to the next vblank with arm, and it must flush these
> stuff before the next vblank irq. However, vblank counter is ahead
> when arm is executed in parallel with handle vblank.
> 
> CPU 0:CPU 1:
>  | |
> atomic_commit_tail is ongoing  |
>  | |
>  |hrtimer: vkms_vblank_simulate()
>  | |
>  |drm_crtc_handle_vblank()
>  | |
> drm_crtc_arm_vblank()  |
>  | |
> ->get_vblank_timestamp()   |
>  | |
>  |hrtimer_forward_now()
> 
> Then, we should guarantee that the vblank interval time is correct
> (not changed) before finish the vblank handle.
> 
> Fix the bug including the call to `hrtimer_forward_now()` in the same
> lock of `drm_crtc_handle_vblank()` to ensure that the timestamp update
> is correct when finish the vblank handle.
> 
> Signed-off-by: Shayenne Moura 
> Signed-off-by: Daniel Vetter 
> ---
>  drivers/gpu/drm/vkms/vkms_crtc.c | 18 ++
>  1 file changed, 6 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c 
> b/drivers/gpu/drm/vkms/vkms_crtc.c
> index 23146ff2a25b..5a095610726b 100644
> --- a/drivers/gpu/drm/vkms/vkms_crtc.c
> +++ b/drivers/gpu/drm/vkms/vkms_crtc.c
> @@ -10,13 +10,17 @@
>  #include 
>  #include 
>  
> -static void _vblank_handle(struct vkms_output *output)
> +static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
>  {
> + struct vkms_output *output = container_of(timer, struct vkms_output,
> +   vblank_hrtimer);
>   struct drm_crtc *crtc = >crtc;
>   struct vkms_crtc_state *state = to_vkms_crtc_state(crtc->state);
> + int ret_overrun;
>   bool ret;
>  
>   spin_lock(>lock);
> +
>   ret = drm_crtc_handle_vblank(crtc);
>   if (!ret)
>   DRM_ERROR("vkms failure on handling vblank");
> @@ -37,19 +41,9 @@ static void _vblank_handle(struct vkms_output *output)
>   DRM_WARN("failed to queue vkms_crc_work_handle");
>   }
>  
> - spin_unlock(>lock);
> -}
> -
> -static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer)
> -{
> - struct vkms_output *output = container_of(timer, struct vkms_output,
> -   vblank_hrtimer);
> - int ret_overrun;
> -
> - _vblank_handle(output);
> -
>   ret_overrun = hrtimer_forward_now(>vblank_hrtimer,
> output->period_ns);
> + spin_unlock(>lock);
>  
>   return HRTIMER_RESTART;
>  }
> -- 
> 2.17.1
> 

Reviewed-by: Rodrigo Siqueira 

-- 
Rodrigo Siqueira
https://siqueira.tech
Graduate Student
Department of Computer Science
University of São Paulo


signature.asc
Description: PGP signature


Re: [PATCH 0/2] drm/vkms: Bugfix for igt-tests

2019-02-03 Thread Rodrigo Siqueira
On 01/30, Shayenne Moura wrote:
> This patchset contains patches to fix the extra frame bug on kms_flip 
> igt-test. First patch solves the extra vblank frame that breaks many
> tests on kms_flip and second patch solves the race condition caused
> by the solution added in the first one.
> 
> Shayenne Moura (2):
>   drm/vkms: Bugfix extra vblank frame
>   drm/vkms: Bugfix racing hrtimer vblank handle
> 
>  drivers/gpu/drm/vkms/vkms_crtc.c | 21 +
>  1 file changed, 9 insertions(+), 12 deletions(-)
> 
> -- 
> 2.17.1
> 

Hi,

Thanks for the patchset :)

The patchset worked like a charm; it fixes many of the tests in the
kms_flip. \o/

I'll apply it.

Thanks!

Reviewed-by: Rodrigo Siqueira 

-- 
Rodrigo Siqueira
https://siqueira.tech
Graduate Student
Department of Computer Science
University of São Paulo


signature.asc
Description: PGP signature


[PATCH] drm/vkms: Fix license inconsistent

2019-01-21 Thread Rodrigo Siqueira
Fixes license inconsistent related to the VKMS driver and remove the
redundant boilerplate comment.

Fixes: 854502fa0a38 ("drm/vkms: Add basic CRTC initialization")

Signed-off-by: Rodrigo Siqueira 
---
 drivers/gpu/drm/vkms/vkms_crc.c| 3 ++-
 drivers/gpu/drm/vkms/vkms_crtc.c   | 8 +---
 drivers/gpu/drm/vkms/vkms_drv.c| 7 +--
 drivers/gpu/drm/vkms/vkms_drv.h| 2 ++
 drivers/gpu/drm/vkms/vkms_gem.c| 8 +---
 drivers/gpu/drm/vkms/vkms_output.c | 8 +---
 drivers/gpu/drm/vkms/vkms_plane.c  | 8 +---
 7 files changed, 9 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_crc.c
index 9d9e8146db90..d7b409a3c0f8 100644
--- a/drivers/gpu/drm/vkms/vkms_crc.c
+++ b/drivers/gpu/drm/vkms/vkms_crc.c
@@ -1,4 +1,5 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
+
 #include "vkms_drv.h"
 #include 
 #include 
diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c
index 177bbcb38306..eb56ee893761 100644
--- a/drivers/gpu/drm/vkms/vkms_crtc.c
+++ b/drivers/gpu/drm/vkms/vkms_crtc.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include 
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index 2a16b86196dc..944908c486f3 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -1,9 +1,4 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 /**
  * DOC: vkms (Virtual Kernel Modesetting)
diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
index e4469cd3d254..81f1cfbeb936 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.h
+++ b/drivers/gpu/drm/vkms/vkms_drv.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
 #ifndef _VKMS_DRV_H_
 #define _VKMS_DRV_H_
 
diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c
index 80311daed47a..138b0bb325cf 100644
--- a/drivers/gpu/drm/vkms/vkms_gem.c
+++ b/drivers/gpu/drm/vkms/vkms_gem.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include 
 
diff --git a/drivers/gpu/drm/vkms/vkms_output.c 
b/drivers/gpu/drm/vkms/vkms_output.c
index 271a0eb9042c..4173e4f48334 100644
--- a/drivers/gpu/drm/vkms/vkms_output.c
+++ b/drivers/gpu/drm/vkms/vkms_output.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include 
diff --git a/drivers/gpu/drm/vkms/vkms_plane.c 
b/drivers/gpu/drm/vkms/vkms_plane.c
index 418817600ad1..0e67d2d42f0c 100644
--- a/drivers/gpu/drm/vkms/vkms_plane.c
+++ b/drivers/gpu/drm/vkms/vkms_plane.c
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include 
-- 
2.20.1



Re: [PATCH v2] drm/drm_vblank: Change EINVAL by the correct errno

2019-01-14 Thread Rodrigo Siqueira
On 01/14, Maarten Lankhorst wrote:
> Op 13-01-2019 om 21:23 schreef Rodrigo Siqueira:
> > Hi,
> >
> > I resend this patch for CI via “intel-...@lists.freedesktop.org” as
> > Daniel suggested, and I got a feedback that reported an issue as can be
> > seen here:
> >
> >https://patchwork.freedesktop.org/series/51147/
> >
> > After a careful analysis of what happened, I concluded that the problem
> > is related to the function “igt_wait_for_vblank_count()” in “igt_kms.c”.
> > This function has the following assert:
> >
> >igt_assert(drmWaitVBlank(drm_fd, _vbl) == 0)
> >
> > This function only checks if everything went well with the
> > drmWaitVBlank() operation and does not make any other validation. IMHO
> > the patch is correct, and the problem pointed out by CI is not related
> > to this change.
> 
> Hey,

Hi,

Thanks for the feedback :)

> Thanks for finding the root cause. Before upstreaming can you send a fix for 
> i-g-t so we don't lose CI coverage after changing the behavior?

I'm just confused on my next step, should I fix the IGT test and then
resend the patch? Additionally, I noticed that tests related to vblank
wait have others issues as I pointed out here (see my last message):

https://patchwork.freedesktop.org/patch/245784/

Is it enough if I handling EINVAL and EOPNOTSUPP in the tests?  I'm
afraid, that the tests will still fail if I consider these two case;
however, I suppose that handling only EOPNOTSUPP can fix the problem,
but I'm not sure if it is the best solution.

Best Regards
 
> ~Maarten
> 


[RESEND] MAINTAINERS: Add entry for VKMS

2019-01-13 Thread Rodrigo Siqueira
Add maintainers and reviewers for VKMS driver

Signed-off-by: Rodrigo Siqueira 
---
Changes in v2:
  - Insert the section in alphabetical order

Resend:
  - Update patch due to changes in MAINTAINER file

 MAINTAINERS | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 163c8f76a1c8..6e1cef2f21d9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4925,6 +4925,16 @@ S:   Odd Fixes
 F: drivers/gpu/drm/udl/
 T: git git://anongit.freedesktop.org/drm/drm-misc
 
+DRM DRIVER FOR VIRTUAL KERNEL MODESETTING (VKMS)
+M: Rodrigo Siqueira 
+R: Haneen Mohammed 
+R: Daniel Vetter 
+T: git git://anongit.freedesktop.org/drm/drm-misc
+S: Maintained
+L: dri-de...@lists.freedesktop.org
+F: drivers/gpu/drm/vkms/
+F: Documentation/gpu/vkms.rst
+
 DRM DRIVER FOR VMWARE VIRTUAL GPU
 M: "VMware Graphics" 
 M: Thomas Hellstrom 
-- 
2.20.1


Re: [PATCH v2] drm/drm_vblank: Change EINVAL by the correct errno

2019-01-13 Thread Rodrigo Siqueira
Hi,

I resend this patch for CI via “intel-...@lists.freedesktop.org” as
Daniel suggested, and I got a feedback that reported an issue as can be
seen here:

   https://patchwork.freedesktop.org/series/51147/

After a careful analysis of what happened, I concluded that the problem
is related to the function “igt_wait_for_vblank_count()” in “igt_kms.c”.
This function has the following assert:

   igt_assert(drmWaitVBlank(drm_fd, _vbl) == 0)

This function only checks if everything went well with the
drmWaitVBlank() operation and does not make any other validation. IMHO
the patch is correct, and the problem pointed out by CI is not related
to this change.

Make sense?

Best Regards

On 10/17, Daniel Vetter wrote:
> On Wed, Oct 17, 2018 at 2:43 PM Rodrigo Siqueira
>  wrote:
> >
> > Hi,
> >
> > First of all, thanks to all for the reviewers and feedbacks.
> >
> > On 10/16, Daniel Vetter wrote:
> > > On Mon, Oct 15, 2018 at 02:05:29PM -0300, Rodrigo Siqueira wrote:
> > > > For historical reason, the function drm_wait_vblank_ioctl always return
> > > > -EINVAL if something gets wrong. This scenario limits the flexibility
> > > > for the userspace make detailed verification of the problem and take
> > > > some action. In particular, the validation of “if (!dev->irq_enabled)”
> > > > in the drm_wait_vblank_ioctl is responsible for checking if the driver
> > > > support vblank or not. If the driver does not support VBlank, the
> > > > function drm_wait_vblank_ioctl returns EINVAL which does not represent
> > > > the real issue; this patch changes this behavior by return EOPNOTSUPP.
> > > > Additionally, some operations are unsupported by this function, and
> > > > returns EINVAL; this patch also changes the return value to EOPNOTSUPP
> > > > in this case. Lastly, the function drm_wait_vblank_ioctl is invoked by
> > > > libdrm, which is used by many compositors; because of this, it is
> > > > important to check if this change breaks any compositor. In this sense,
> > > > the following projects were examined:
> > > >
> > > > * Drm-hwcomposer
> > > > * Kwin
> > > > * Sway
> > > > * Wlroots
> > > > * Wayland-core
> > > > * Weston
> > > > * Xorg (67 different drivers)
> > > >
> > > > For each repository the verification happened in three steps:
> > > >
> > > > * Update the main branch
> > > > * Look for any occurrence "drmWaitVBlank" with the command:
> > > >   git grep -n "drmWaitVBlank"
> > > > * Look in the git history of the project with the command:
> > > >   git log -SdrmWaitVBlank
> > > >
> > > > Finally, none of the above projects validate the use of EINVAL which
> > > > make safe, at least for these projects, to change the return values.
> > > >
> > > > Change since V1:
> > > >  Daniel Vetter and Chris Wilson
> > > >  - Replace ENOTTY by EOPNOTSUPP
> > > >  - Return EINVAL if the parameters are wrong
> > > >
> > > > Signed-off-by: Rodrigo Siqueira 
> > >
> > > Reviewed-by: Daniel Vetter 
> > >
> > > Can you pls also let intel-gfx-ci test this patch? You just need to
> > > include intel-...@lists.freedesktop.org in your recipient list.
> >
> > I did know about intel-gfx-ci, really nice:)
> >
> > Should I CC this mailing list if I send patches to the DRM core, amdgpu,
> > i915, vc4, vgem, and virtio-gpu? I suppose that IGT is running on the
> > CI, right?
> 
> It's only intel gpus (well and one special amd one) running igt on a
> _lot_ of different machines.
> 
> > Another question, do I need to send a V3 with intel-gfx-ci?
> 
> If the patch-set is unchanged people use the "FOR CI" subject prefix
> when resending, instead of incrementing the version number.
> 
> > > For merging, since you plan to stick around doing kms stuff a bit: Want
> > > commit rights for drm-misc?
> > >
> > > https://drm.pages.freedesktop.org/maintainer-tools/getting-started.html
> >
> > Yes, I want :)
> > I will need some guidance, in the beginning, to get confident about the
> > processes. If you can help me with this, I will be glad to play around
> > with 'dim' and the merging tasks.
> 
> Sure, just ping me on irc. First you need a freedesktop.org ssh account:
> 
> https://www.freedesktop.org/wiki/AccountRequests/
> 
> You need to request access to the drm-misc group. Once you have th

Re: [PATCH] staging: iio: ad5933: finalized device-tree support

2018-11-23 Thread Rodrigo Siqueira
Hi Marcelo,

I believe that a proper commit message for this patch could be something
like "Add device tree support".

On 11/23, Marcelo Schmitt wrote:
> Added a of_device_id struct variable and subsequent call to
> MODULE_DEVICE_TABLE macro to complete device-tree support for this
> driver.
> 
> Signed-off-by: Marcelo Schmitt 
> ---
>  drivers/staging/iio/impedance-analyzer/ad5933.c | 9 +
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c 
> b/drivers/staging/iio/impedance-analyzer/ad5933.c
> index edb8b540bbf1..19e8b6d2865c 100644
> --- a/drivers/staging/iio/impedance-analyzer/ad5933.c
> +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
> @@ -771,9 +771,18 @@ static const struct i2c_device_id ad5933_id[] = {
>  
>  MODULE_DEVICE_TABLE(i2c, ad5933_id);
>  
> +static const struct of_device_id ad5933_of_match[] = {
> + { .compatible = "analog-devices,ad5933" },
> + { .compatible = "analog-devices,ad5934" },
> + { },
> +};
> +
> +MODULE_DEVICE_TABLE(of, ad5933_of_match);
> +
>  static struct i2c_driver ad5933_driver = {
>   .driver = {
>   .name = "ad5933",
> + .of_match_table = ad5933_of_match,
>   },
>   .probe = ad5933_probe,
>   .remove = ad5933_remove,
> -- 
> 2.17.1
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Kernel USP" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to kernel-usp+unsubscr...@googlegroups.com.
> To post to this group, send email to kernel-...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/kernel-usp/20181123235159.hh43xnvvwsil4on2%40smtp.gmail.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
Rodrigo Siqueira
https://siqueira.tech
https://twitter.com/siqueirajordao
Graduate Student
Department of Computer Science
University of São Paulo


signature.asc
Description: PGP signature


Re: [PATCH] staging: iio: ad5933: finalized device-tree support

2018-11-23 Thread Rodrigo Siqueira
Hi Marcelo,

I believe that a proper commit message for this patch could be something
like "Add device tree support".

On 11/23, Marcelo Schmitt wrote:
> Added a of_device_id struct variable and subsequent call to
> MODULE_DEVICE_TABLE macro to complete device-tree support for this
> driver.
> 
> Signed-off-by: Marcelo Schmitt 
> ---
>  drivers/staging/iio/impedance-analyzer/ad5933.c | 9 +
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c 
> b/drivers/staging/iio/impedance-analyzer/ad5933.c
> index edb8b540bbf1..19e8b6d2865c 100644
> --- a/drivers/staging/iio/impedance-analyzer/ad5933.c
> +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
> @@ -771,9 +771,18 @@ static const struct i2c_device_id ad5933_id[] = {
>  
>  MODULE_DEVICE_TABLE(i2c, ad5933_id);
>  
> +static const struct of_device_id ad5933_of_match[] = {
> + { .compatible = "analog-devices,ad5933" },
> + { .compatible = "analog-devices,ad5934" },
> + { },
> +};
> +
> +MODULE_DEVICE_TABLE(of, ad5933_of_match);
> +
>  static struct i2c_driver ad5933_driver = {
>   .driver = {
>   .name = "ad5933",
> + .of_match_table = ad5933_of_match,
>   },
>   .probe = ad5933_probe,
>   .remove = ad5933_remove,
> -- 
> 2.17.1
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Kernel USP" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to kernel-usp+unsubscr...@googlegroups.com.
> To post to this group, send email to kernel-...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/kernel-usp/20181123235159.hh43xnvvwsil4on2%40smtp.gmail.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
Rodrigo Siqueira
https://siqueira.tech
https://twitter.com/siqueirajordao
Graduate Student
Department of Computer Science
University of São Paulo


signature.asc
Description: PGP signature


Re: [PATCH] gpu/drm/vkms: Use new return type vm_fault_t

2018-07-25 Thread Rodrigo Siqueira
Hi,

Thanks for the patch,

I reviewed and tested it; everything is fine. I only suggest removing
the "gpu" part from the patch title (i.e., "drm/vkms: Use new return
type vm_fault_t").

On 07/23, Souptick Joarder wrote:
> Use new return type vm_fault_t for fault handler.
> 
> Signed-off-by: Souptick Joarder 
> ---
>  drivers/gpu/drm/vkms/vkms_drv.h | 2 +-
>  drivers/gpu/drm/vkms/vkms_gem.c | 5 ++---
>  2 files changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
> index 07be29f..d5d04a8 100644
> --- a/drivers/gpu/drm/vkms/vkms_drv.h
> +++ b/drivers/gpu/drm/vkms/vkms_drv.h
> @@ -65,7 +65,7 @@ struct drm_gem_object *vkms_gem_create(struct drm_device 
> *dev,
>  u32 *handle,
>  u64 size);
>  
> -int vkms_gem_fault(struct vm_fault *vmf);
> +vm_fault_t vkms_gem_fault(struct vm_fault *vmf);
>  
>  int vkms_dumb_create(struct drm_file *file, struct drm_device *dev,
>struct drm_mode_create_dumb *args);
> diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c
> index c7e3836..62e05dc 100644
> --- a/drivers/gpu/drm/vkms/vkms_gem.c
> +++ b/drivers/gpu/drm/vkms/vkms_gem.c
> @@ -43,14 +43,14 @@ void vkms_gem_free_object(struct drm_gem_object *obj)
>   kfree(gem);
>  }
>  
> -int vkms_gem_fault(struct vm_fault *vmf)
> +vm_fault_t vkms_gem_fault(struct vm_fault *vmf)
>  {
>   struct vm_area_struct *vma = vmf->vma;
>   struct vkms_gem_object *obj = vma->vm_private_data;
>   unsigned long vaddr = vmf->address;
>   pgoff_t page_offset;
>   loff_t num_pages;
> - int ret;
> + vm_fault_t ret = VM_FAULT_SIGBUS;
>  
>   page_offset = (vaddr - vma->vm_start) >> PAGE_SHIFT;
>   num_pages = DIV_ROUND_UP(obj->gem.size, PAGE_SIZE);
> @@ -58,7 +58,6 @@ int vkms_gem_fault(struct vm_fault *vmf)
>   if (page_offset > num_pages)
>   return VM_FAULT_SIGBUS;
>  
> - ret = -ENOENT;
>   mutex_lock(>pages_lock);
>   if (obj->pages) {
>   get_page(obj->pages[page_offset]);
> -- 
> 1.9.1
> 


Re: [PATCH] gpu/drm/vkms: Use new return type vm_fault_t

2018-07-25 Thread Rodrigo Siqueira
Hi,

Thanks for the patch,

I reviewed and tested it; everything is fine. I only suggest removing
the "gpu" part from the patch title (i.e., "drm/vkms: Use new return
type vm_fault_t").

On 07/23, Souptick Joarder wrote:
> Use new return type vm_fault_t for fault handler.
> 
> Signed-off-by: Souptick Joarder 
> ---
>  drivers/gpu/drm/vkms/vkms_drv.h | 2 +-
>  drivers/gpu/drm/vkms/vkms_gem.c | 5 ++---
>  2 files changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h
> index 07be29f..d5d04a8 100644
> --- a/drivers/gpu/drm/vkms/vkms_drv.h
> +++ b/drivers/gpu/drm/vkms/vkms_drv.h
> @@ -65,7 +65,7 @@ struct drm_gem_object *vkms_gem_create(struct drm_device 
> *dev,
>  u32 *handle,
>  u64 size);
>  
> -int vkms_gem_fault(struct vm_fault *vmf);
> +vm_fault_t vkms_gem_fault(struct vm_fault *vmf);
>  
>  int vkms_dumb_create(struct drm_file *file, struct drm_device *dev,
>struct drm_mode_create_dumb *args);
> diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c
> index c7e3836..62e05dc 100644
> --- a/drivers/gpu/drm/vkms/vkms_gem.c
> +++ b/drivers/gpu/drm/vkms/vkms_gem.c
> @@ -43,14 +43,14 @@ void vkms_gem_free_object(struct drm_gem_object *obj)
>   kfree(gem);
>  }
>  
> -int vkms_gem_fault(struct vm_fault *vmf)
> +vm_fault_t vkms_gem_fault(struct vm_fault *vmf)
>  {
>   struct vm_area_struct *vma = vmf->vma;
>   struct vkms_gem_object *obj = vma->vm_private_data;
>   unsigned long vaddr = vmf->address;
>   pgoff_t page_offset;
>   loff_t num_pages;
> - int ret;
> + vm_fault_t ret = VM_FAULT_SIGBUS;
>  
>   page_offset = (vaddr - vma->vm_start) >> PAGE_SHIFT;
>   num_pages = DIV_ROUND_UP(obj->gem.size, PAGE_SIZE);
> @@ -58,7 +58,6 @@ int vkms_gem_fault(struct vm_fault *vmf)
>   if (page_offset > num_pages)
>   return VM_FAULT_SIGBUS;
>  
> - ret = -ENOENT;
>   mutex_lock(>pages_lock);
>   if (obj->pages) {
>   get_page(obj->pages[page_offset]);
> -- 
> 1.9.1
> 


Re: [PATCH 0/3] stagging:iio:meter: Add essential IIO API structures for ADE7854

2018-04-23 Thread Rodrigo Siqueira
Hi Jonathan,

Thanks for all the feedbacks and sorry for some basic mistakes, I will
work on the second version based on all your comments.

Best Regards
Rodrigo Siqueira

On 04/21, Jonathan Cameron wrote:
> On Sat, 21 Apr 2018 08:54:45 -0300
> Rodrigo Siqueira <rodrigosiqueiram...@gmail.com> wrote:
> 
> > This patchset aims to update ADE7854 by adding the required IIO API
> > components. The first patch adds the iio_chan_spec for handling seven
> > different registers (all of them with a similar behavior). The second
> > patch appends the read_raw function defined by the IIO API. Finally, the
> > third patch adds the write_raw function and remove the attributes used
> > for handling the seven registers. This patchset has the contribution of
> > John Syne, which was responsible for mapping the correct ABI name per
> > element in the ADE7854; additionally, John provided codes that helped to
> > shape these patches.
> > 
> > Rodrigo Siqueira (3):
> >   stagging:iio:meter: Add iio_chan_spec
> >   stagging:iio:meter: Add ade7854_read_raw function
> >   stagging:iio:meter: Add ade7854_write_raw function
> > 
> >  drivers/staging/iio/meter/ade7854.c | 129 
> >  1 file changed, 94 insertions(+), 35 deletions(-)
> > 
> Hi Rodrigo,
> 
> Please don't do it like this.   The original discussion with John
> involved the addition of an extra chunk of core logic so we would have
> the ability to specify the channel without using extended_name.
> 
> Extended name is not intended to differentiate between channels (it
> isn't in general enough to do so - though it works in this little
> corner case of sysfs attributes like you have here).
> 
> So the plan is to add another field to the iio_chan_spec structure
> to allow for the complexity we need.  See the long discussions
> over how we represent the myriad of channels in here.
> 
> If you need some pointers, feel free to ask but it may take
> me a little while to put together a full description of what needs
> doing.
> 
> I'll put a few more direct comments in the individual patches.
> 
> Thanks,
> 
> Jonathan
> 


Re: [PATCH 0/3] stagging:iio:meter: Add essential IIO API structures for ADE7854

2018-04-23 Thread Rodrigo Siqueira
Hi Jonathan,

Thanks for all the feedbacks and sorry for some basic mistakes, I will
work on the second version based on all your comments.

Best Regards
Rodrigo Siqueira

On 04/21, Jonathan Cameron wrote:
> On Sat, 21 Apr 2018 08:54:45 -0300
> Rodrigo Siqueira  wrote:
> 
> > This patchset aims to update ADE7854 by adding the required IIO API
> > components. The first patch adds the iio_chan_spec for handling seven
> > different registers (all of them with a similar behavior). The second
> > patch appends the read_raw function defined by the IIO API. Finally, the
> > third patch adds the write_raw function and remove the attributes used
> > for handling the seven registers. This patchset has the contribution of
> > John Syne, which was responsible for mapping the correct ABI name per
> > element in the ADE7854; additionally, John provided codes that helped to
> > shape these patches.
> > 
> > Rodrigo Siqueira (3):
> >   stagging:iio:meter: Add iio_chan_spec
> >   stagging:iio:meter: Add ade7854_read_raw function
> >   stagging:iio:meter: Add ade7854_write_raw function
> > 
> >  drivers/staging/iio/meter/ade7854.c | 129 
> >  1 file changed, 94 insertions(+), 35 deletions(-)
> > 
> Hi Rodrigo,
> 
> Please don't do it like this.   The original discussion with John
> involved the addition of an extra chunk of core logic so we would have
> the ability to specify the channel without using extended_name.
> 
> Extended name is not intended to differentiate between channels (it
> isn't in general enough to do so - though it works in this little
> corner case of sysfs attributes like you have here).
> 
> So the plan is to add another field to the iio_chan_spec structure
> to allow for the complexity we need.  See the long discussions
> over how we represent the myriad of channels in here.
> 
> If you need some pointers, feel free to ask but it may take
> me a little while to put together a full description of what needs
> doing.
> 
> I'll put a few more direct comments in the individual patches.
> 
> Thanks,
> 
> Jonathan
> 


[PATCH 3/3] stagging:iio:meter: Add ade7854_write_raw function

2018-04-21 Thread Rodrigo Siqueira
This patch adds the ade7854_write_raw() function which is responsible
for handling the write operation for registers: AIGAIN, BIGAIN, CIGAIN,
NIGAIN, AVGAIN, BVGAIN, and CVGAIN. Finally, this patch completely
removes the old ABI used for handling the registers mentioned above.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
---
 drivers/staging/iio/meter/ade7854.c | 60 -
 1 file changed, 25 insertions(+), 35 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854.c 
b/drivers/staging/iio/meter/ade7854.c
index 242ecde75900..df19c8b4b5d7 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -228,34 +228,6 @@ static int ade7854_reset(struct device *dev)
return st->write_reg(dev, ADE7854_CONFIG, val, 16);
 }
 
-static IIO_DEV_ATTR_AIGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_AIGAIN);
-static IIO_DEV_ATTR_BIGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_BIGAIN);
-static IIO_DEV_ATTR_CIGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_CIGAIN);
-static IIO_DEV_ATTR_NIGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_NIGAIN);
-static IIO_DEV_ATTR_AVGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_AVGAIN);
-static IIO_DEV_ATTR_BVGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_BVGAIN);
-static IIO_DEV_ATTR_CVGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_CVGAIN);
 static IIO_DEV_ATTR_APPARENT_POWER_A_GAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
@@ -497,6 +469,30 @@ static int ade7854_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
 }
 
+static int ade7854_write_raw(struct iio_dev *indio_dev,
+struct iio_chan_spec const *chan,
+int val, int val2, long mask)
+{
+   struct ade7854_state *st = iio_priv(indio_dev);
+   int ret;
+
+   if (mask != IIO_CHAN_INFO_SCALE)
+   return -EINVAL;
+
+   switch (chan->type) {
+   case IIO_CURRENT:
+   case IIO_VOLTAGE:
+   ret = st->write_reg(_dev->dev, chan->address, val, 24);
+   if (ret < 0)
+   return ret;
+   return 0;
+   default:
+   break;
+   }
+
+   return -EINVAL;
+}
+
 static int ade7854_initial_setup(struct iio_dev *indio_dev)
 {
int ret;
@@ -521,13 +517,6 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("8000");
 static IIO_CONST_ATTR(name, "ade7854");
 
 static struct attribute *ade7854_attributes[] = {
-   _dev_attr_aigain.dev_attr.attr,
-   _dev_attr_bigain.dev_attr.attr,
-   _dev_attr_cigain.dev_attr.attr,
-   _dev_attr_nigain.dev_attr.attr,
-   _dev_attr_avgain.dev_attr.attr,
-   _dev_attr_bvgain.dev_attr.attr,
-   _dev_attr_cvgain.dev_attr.attr,
_dev_attr_linecyc.dev_attr.attr,
_dev_attr_sagcyc.dev_attr.attr,
_dev_attr_cfcyc.dev_attr.attr,
@@ -599,6 +588,7 @@ static const struct attribute_group ade7854_attribute_group 
= {
 static const struct iio_info ade7854_info = {
.attrs = _attribute_group,
.read_raw = _read_raw,
+   .write_raw = _write_raw,
 };
 
 int ade7854_probe(struct iio_dev *indio_dev, struct device *dev)
-- 
2.17.0



[PATCH 3/3] stagging:iio:meter: Add ade7854_write_raw function

2018-04-21 Thread Rodrigo Siqueira
This patch adds the ade7854_write_raw() function which is responsible
for handling the write operation for registers: AIGAIN, BIGAIN, CIGAIN,
NIGAIN, AVGAIN, BVGAIN, and CVGAIN. Finally, this patch completely
removes the old ABI used for handling the registers mentioned above.

Signed-off-by: Rodrigo Siqueira 
---
 drivers/staging/iio/meter/ade7854.c | 60 -
 1 file changed, 25 insertions(+), 35 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854.c 
b/drivers/staging/iio/meter/ade7854.c
index 242ecde75900..df19c8b4b5d7 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -228,34 +228,6 @@ static int ade7854_reset(struct device *dev)
return st->write_reg(dev, ADE7854_CONFIG, val, 16);
 }
 
-static IIO_DEV_ATTR_AIGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_AIGAIN);
-static IIO_DEV_ATTR_BIGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_BIGAIN);
-static IIO_DEV_ATTR_CIGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_CIGAIN);
-static IIO_DEV_ATTR_NIGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_NIGAIN);
-static IIO_DEV_ATTR_AVGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_AVGAIN);
-static IIO_DEV_ATTR_BVGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_BVGAIN);
-static IIO_DEV_ATTR_CVGAIN(0644,
-   NULL,
-   ade7854_write_24bit,
-   ADE7854_CVGAIN);
 static IIO_DEV_ATTR_APPARENT_POWER_A_GAIN(0644,
ade7854_read_24bit,
ade7854_write_24bit,
@@ -497,6 +469,30 @@ static int ade7854_read_raw(struct iio_dev *indio_dev,
return -EINVAL;
 }
 
+static int ade7854_write_raw(struct iio_dev *indio_dev,
+struct iio_chan_spec const *chan,
+int val, int val2, long mask)
+{
+   struct ade7854_state *st = iio_priv(indio_dev);
+   int ret;
+
+   if (mask != IIO_CHAN_INFO_SCALE)
+   return -EINVAL;
+
+   switch (chan->type) {
+   case IIO_CURRENT:
+   case IIO_VOLTAGE:
+   ret = st->write_reg(_dev->dev, chan->address, val, 24);
+   if (ret < 0)
+   return ret;
+   return 0;
+   default:
+   break;
+   }
+
+   return -EINVAL;
+}
+
 static int ade7854_initial_setup(struct iio_dev *indio_dev)
 {
int ret;
@@ -521,13 +517,6 @@ static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("8000");
 static IIO_CONST_ATTR(name, "ade7854");
 
 static struct attribute *ade7854_attributes[] = {
-   _dev_attr_aigain.dev_attr.attr,
-   _dev_attr_bigain.dev_attr.attr,
-   _dev_attr_cigain.dev_attr.attr,
-   _dev_attr_nigain.dev_attr.attr,
-   _dev_attr_avgain.dev_attr.attr,
-   _dev_attr_bvgain.dev_attr.attr,
-   _dev_attr_cvgain.dev_attr.attr,
_dev_attr_linecyc.dev_attr.attr,
_dev_attr_sagcyc.dev_attr.attr,
_dev_attr_cfcyc.dev_attr.attr,
@@ -599,6 +588,7 @@ static const struct attribute_group ade7854_attribute_group 
= {
 static const struct iio_info ade7854_info = {
.attrs = _attribute_group,
.read_raw = _read_raw,
+   .write_raw = _write_raw,
 };
 
 int ade7854_probe(struct iio_dev *indio_dev, struct device *dev)
-- 
2.17.0



[PATCH 2/3] stagging:iio:meter: Add ade7854_read_raw function

2018-04-21 Thread Rodrigo Siqueira
This patch adds the ade7854_read_raw() function which is responsible for
handling the read operation for registers: AIGAIN, BIGAIN, CIGAIN,
NIGAIN, AVGAIN, BVGAIN, and CVGAIN. For the sake of simplicity, this
patch only adds basic manipulation for current and voltage channels.
Finally, this patch disables the old approach for reading data.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
---
 drivers/staging/iio/meter/ade7854.c | 41 -
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854.c 
b/drivers/staging/iio/meter/ade7854.c
index 2fbb2570ba54..242ecde75900 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -229,31 +229,31 @@ static int ade7854_reset(struct device *dev)
 }
 
 static IIO_DEV_ATTR_AIGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_AIGAIN);
 static IIO_DEV_ATTR_BIGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_BIGAIN);
 static IIO_DEV_ATTR_CIGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_CIGAIN);
 static IIO_DEV_ATTR_NIGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_NIGAIN);
 static IIO_DEV_ATTR_AVGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_AVGAIN);
 static IIO_DEV_ATTR_BVGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_BVGAIN);
 static IIO_DEV_ATTR_CVGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_CVGAIN);
 static IIO_DEV_ATTR_APPARENT_POWER_A_GAIN(0644,
@@ -471,6 +471,32 @@ static int ade7854_set_irq(struct device *dev, bool enable)
return st->write_reg(dev, ADE7854_MASK0, irqen, 32);
 }
 
+static int ade7854_read_raw(struct iio_dev *indio_dev,
+   struct iio_chan_spec const *chan,
+   int *val,
+   int *val2,
+   long mask)
+{
+   struct ade7854_state *st = iio_priv(indio_dev);
+   int ret;
+
+   if (mask != IIO_CHAN_INFO_SCALE)
+   return -EINVAL;
+
+   switch (chan->type) {
+   case IIO_CURRENT:
+   case IIO_VOLTAGE:
+   ret = st->read_reg(_dev->dev, chan->address, val, 24);
+   if (ret < 0)
+   return ret;
+   return IIO_VAL_INT;
+   default:
+   break;
+   }
+
+   return -EINVAL;
+}
+
 static int ade7854_initial_setup(struct iio_dev *indio_dev)
 {
int ret;
@@ -572,6 +598,7 @@ static const struct attribute_group ade7854_attribute_group 
= {
 
 static const struct iio_info ade7854_info = {
.attrs = _attribute_group,
+   .read_raw = _read_raw,
 };
 
 int ade7854_probe(struct iio_dev *indio_dev, struct device *dev)
-- 
2.17.0



[PATCH 1/3] stagging:iio:meter: Add iio_chan_spec

2018-04-21 Thread Rodrigo Siqueira
This patch adds iio_chan_spec struct. Additionally, the channel adds the
support for handling AIGAIN, BIGAIN, CIGAIN, NIGAIN, AVGAIN, BVGAIN, and
CVGAIN.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
---
 drivers/staging/iio/meter/ade7854.c | 42 +
 1 file changed, 42 insertions(+)

diff --git a/drivers/staging/iio/meter/ade7854.c 
b/drivers/staging/iio/meter/ade7854.c
index 029c3bf42d4d..2fbb2570ba54 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -22,6 +22,48 @@
 #include "meter.h"
 #include "ade7854.h"
 
+#define PHASEA "phaseA"
+#define PHASEB "phaseB"
+#define PHASEC "phaseC"
+#define NEUTRAL "neutral"
+
+#define ADE7854_CHANNEL(_type, _name, _mask, _reg) {   \
+   .type = _type,  \
+   .indexed = 1,   \
+   .channel = 0,   \
+   .extend_name = _name,   \
+   .info_mask_separate = _mask,\
+   .address = _reg,\
+   .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+   .scan_index = -1,   \
+}
+
+static const struct iio_chan_spec ade7854_channels[] = {
+   /* Current */
+   ADE7854_CHANNEL(IIO_CURRENT, PHASEA,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_AIGAIN),
+   ADE7854_CHANNEL(IIO_CURRENT, PHASEB,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_BIGAIN),
+   ADE7854_CHANNEL(IIO_CURRENT, PHASEC,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_CIGAIN),
+   ADE7854_CHANNEL(IIO_CURRENT, NEUTRAL,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_NIGAIN),
+   /* Voltage */
+   ADE7854_CHANNEL(IIO_VOLTAGE, PHASEA,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_AVGAIN),
+   ADE7854_CHANNEL(IIO_VOLTAGE, PHASEB,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_BVGAIN),
+   ADE7854_CHANNEL(IIO_VOLTAGE, PHASEC,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_CVGAIN),
+};
+
 static ssize_t ade7854_read_8bit(struct device *dev,
 struct device_attribute *attr,
 char *buf)
-- 
2.17.0



[PATCH 2/3] stagging:iio:meter: Add ade7854_read_raw function

2018-04-21 Thread Rodrigo Siqueira
This patch adds the ade7854_read_raw() function which is responsible for
handling the read operation for registers: AIGAIN, BIGAIN, CIGAIN,
NIGAIN, AVGAIN, BVGAIN, and CVGAIN. For the sake of simplicity, this
patch only adds basic manipulation for current and voltage channels.
Finally, this patch disables the old approach for reading data.

Signed-off-by: Rodrigo Siqueira 
---
 drivers/staging/iio/meter/ade7854.c | 41 -
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854.c 
b/drivers/staging/iio/meter/ade7854.c
index 2fbb2570ba54..242ecde75900 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -229,31 +229,31 @@ static int ade7854_reset(struct device *dev)
 }
 
 static IIO_DEV_ATTR_AIGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_AIGAIN);
 static IIO_DEV_ATTR_BIGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_BIGAIN);
 static IIO_DEV_ATTR_CIGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_CIGAIN);
 static IIO_DEV_ATTR_NIGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_NIGAIN);
 static IIO_DEV_ATTR_AVGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_AVGAIN);
 static IIO_DEV_ATTR_BVGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_BVGAIN);
 static IIO_DEV_ATTR_CVGAIN(0644,
-   ade7854_read_24bit,
+   NULL,
ade7854_write_24bit,
ADE7854_CVGAIN);
 static IIO_DEV_ATTR_APPARENT_POWER_A_GAIN(0644,
@@ -471,6 +471,32 @@ static int ade7854_set_irq(struct device *dev, bool enable)
return st->write_reg(dev, ADE7854_MASK0, irqen, 32);
 }
 
+static int ade7854_read_raw(struct iio_dev *indio_dev,
+   struct iio_chan_spec const *chan,
+   int *val,
+   int *val2,
+   long mask)
+{
+   struct ade7854_state *st = iio_priv(indio_dev);
+   int ret;
+
+   if (mask != IIO_CHAN_INFO_SCALE)
+   return -EINVAL;
+
+   switch (chan->type) {
+   case IIO_CURRENT:
+   case IIO_VOLTAGE:
+   ret = st->read_reg(_dev->dev, chan->address, val, 24);
+   if (ret < 0)
+   return ret;
+   return IIO_VAL_INT;
+   default:
+   break;
+   }
+
+   return -EINVAL;
+}
+
 static int ade7854_initial_setup(struct iio_dev *indio_dev)
 {
int ret;
@@ -572,6 +598,7 @@ static const struct attribute_group ade7854_attribute_group 
= {
 
 static const struct iio_info ade7854_info = {
.attrs = _attribute_group,
+   .read_raw = _read_raw,
 };
 
 int ade7854_probe(struct iio_dev *indio_dev, struct device *dev)
-- 
2.17.0



[PATCH 1/3] stagging:iio:meter: Add iio_chan_spec

2018-04-21 Thread Rodrigo Siqueira
This patch adds iio_chan_spec struct. Additionally, the channel adds the
support for handling AIGAIN, BIGAIN, CIGAIN, NIGAIN, AVGAIN, BVGAIN, and
CVGAIN.

Signed-off-by: Rodrigo Siqueira 
---
 drivers/staging/iio/meter/ade7854.c | 42 +
 1 file changed, 42 insertions(+)

diff --git a/drivers/staging/iio/meter/ade7854.c 
b/drivers/staging/iio/meter/ade7854.c
index 029c3bf42d4d..2fbb2570ba54 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -22,6 +22,48 @@
 #include "meter.h"
 #include "ade7854.h"
 
+#define PHASEA "phaseA"
+#define PHASEB "phaseB"
+#define PHASEC "phaseC"
+#define NEUTRAL "neutral"
+
+#define ADE7854_CHANNEL(_type, _name, _mask, _reg) {   \
+   .type = _type,  \
+   .indexed = 1,   \
+   .channel = 0,   \
+   .extend_name = _name,   \
+   .info_mask_separate = _mask,\
+   .address = _reg,\
+   .info_mask_shared_by_dir = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+   .scan_index = -1,   \
+}
+
+static const struct iio_chan_spec ade7854_channels[] = {
+   /* Current */
+   ADE7854_CHANNEL(IIO_CURRENT, PHASEA,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_AIGAIN),
+   ADE7854_CHANNEL(IIO_CURRENT, PHASEB,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_BIGAIN),
+   ADE7854_CHANNEL(IIO_CURRENT, PHASEC,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_CIGAIN),
+   ADE7854_CHANNEL(IIO_CURRENT, NEUTRAL,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_NIGAIN),
+   /* Voltage */
+   ADE7854_CHANNEL(IIO_VOLTAGE, PHASEA,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_AVGAIN),
+   ADE7854_CHANNEL(IIO_VOLTAGE, PHASEB,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_BVGAIN),
+   ADE7854_CHANNEL(IIO_VOLTAGE, PHASEC,
+   BIT(IIO_CHAN_INFO_SCALE),
+   ADE7854_CVGAIN),
+};
+
 static ssize_t ade7854_read_8bit(struct device *dev,
 struct device_attribute *attr,
 char *buf)
-- 
2.17.0



[PATCH 0/3] stagging:iio:meter: Add essential IIO API structures for ADE7854

2018-04-21 Thread Rodrigo Siqueira
This patchset aims to update ADE7854 by adding the required IIO API
components. The first patch adds the iio_chan_spec for handling seven
different registers (all of them with a similar behavior). The second
patch appends the read_raw function defined by the IIO API. Finally, the
third patch adds the write_raw function and remove the attributes used
for handling the seven registers. This patchset has the contribution of
John Syne, which was responsible for mapping the correct ABI name per
element in the ADE7854; additionally, John provided codes that helped to
shape these patches.

Rodrigo Siqueira (3):
  stagging:iio:meter: Add iio_chan_spec
  stagging:iio:meter: Add ade7854_read_raw function
  stagging:iio:meter: Add ade7854_write_raw function

 drivers/staging/iio/meter/ade7854.c | 129 
 1 file changed, 94 insertions(+), 35 deletions(-)

-- 
2.17.0



[PATCH 0/3] stagging:iio:meter: Add essential IIO API structures for ADE7854

2018-04-21 Thread Rodrigo Siqueira
This patchset aims to update ADE7854 by adding the required IIO API
components. The first patch adds the iio_chan_spec for handling seven
different registers (all of them with a similar behavior). The second
patch appends the read_raw function defined by the IIO API. Finally, the
third patch adds the write_raw function and remove the attributes used
for handling the seven registers. This patchset has the contribution of
John Syne, which was responsible for mapping the correct ABI name per
element in the ADE7854; additionally, John provided codes that helped to
shape these patches.

Rodrigo Siqueira (3):
  stagging:iio:meter: Add iio_chan_spec
  stagging:iio:meter: Add ade7854_read_raw function
  stagging:iio:meter: Add ade7854_write_raw function

 drivers/staging/iio/meter/ade7854.c | 129 
 1 file changed, 94 insertions(+), 35 deletions(-)

-- 
2.17.0



[PATCH v3 8/8] staging:iio:ade7854: Remove read_reg_* duplications

2018-03-23 Thread Rodrigo Siqueira
The original code had a read function per data size; after updates, all
read functions tasks were centralized in a single function, but the old
signature was kept to maintain the module working without problems. This
patch removes a set of duplications associated with read_reg_*, and
update the areas that calling the old interface by the new one.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
---
Changes in v3:
 - Update commit message

 drivers/staging/iio/meter/ade7854-i2c.c | 33 +--
 drivers/staging/iio/meter/ade7854-spi.c | 35 ++---
 drivers/staging/iio/meter/ade7854.c | 18 -
 drivers/staging/iio/meter/ade7854.h |  7 +++
 4 files changed, 15 insertions(+), 78 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index 63793f9664c7..c3aa6ea9d036 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -110,34 +110,6 @@ static int ade7854_i2c_read_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_i2c_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 8);
-}
-
-static int ade7854_i2c_read_reg_16(struct device *dev,
-  u16 reg_address,
-  u16 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 16);
-}
-
-static int ade7854_i2c_read_reg_24(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 24);
-}
-
-static int ade7854_i2c_read_reg_32(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 32);
-}
-
 static int ade7854_i2c_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
@@ -149,10 +121,7 @@ static int ade7854_i2c_probe(struct i2c_client *client,
return -ENOMEM;
st = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
-   st->read_reg_8 = ade7854_i2c_read_reg_8;
-   st->read_reg_16 = ade7854_i2c_read_reg_16;
-   st->read_reg_24 = ade7854_i2c_read_reg_24;
-   st->read_reg_32 = ade7854_i2c_read_reg_32;
+   st->read_reg = ade7854_i2c_read_reg;
st->write_reg = ade7854_i2c_write_reg;
st->i2c = client;
st->irq = client->irq;
diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index ee6e4d166ece..fc9146757283 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -94,7 +94,7 @@ static int ade7854_spi_read_reg(struct device *dev,
st->tx[2] = reg_address & 0xFF;
 
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
-   if (ret) {
+   if (ret < 0) {
dev_err(>spi->dev, "problem when reading register 0x%02X",
reg_address);
goto unlock;
@@ -120,34 +120,6 @@ static int ade7854_spi_read_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_spi_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 8);
-}
-
-static int ade7854_spi_read_reg_16(struct device *dev,
-  u16 reg_address,
-  u16 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 16);
-}
-
-static int ade7854_spi_read_reg_24(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 24);
-}
-
-static int ade7854_spi_read_reg_32(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 32);
-}
-
 static int ade7854_spi_probe(struct spi_device *spi)
 {
struct ade7854_state *st;
@@ -158,10 +130,7 @@ static int ade7854_spi_probe(struct spi_device *spi)
return -ENOMEM;
st = iio_priv(indio_dev);
spi_set_drvdata(spi, indio_dev);
-   st->read_reg_8 = ade7854_spi_read_reg_8;
-   st->read_reg_16 = ade7854_spi_read_reg_16;
-   st->read_reg_24 = ade7854_spi_read_reg_24;
-   st->read_reg_32 = ade7854_spi_read_reg_32;
+   st->read_reg = ade7854_spi_read_reg;
st->write_reg = ade7854_spi_write_reg;
st->irq = spi->irq;

[PATCH v3 8/8] staging:iio:ade7854: Remove read_reg_* duplications

2018-03-23 Thread Rodrigo Siqueira
The original code had a read function per data size; after updates, all
read functions tasks were centralized in a single function, but the old
signature was kept to maintain the module working without problems. This
patch removes a set of duplications associated with read_reg_*, and
update the areas that calling the old interface by the new one.

Signed-off-by: Rodrigo Siqueira 
---
Changes in v3:
 - Update commit message

 drivers/staging/iio/meter/ade7854-i2c.c | 33 +--
 drivers/staging/iio/meter/ade7854-spi.c | 35 ++---
 drivers/staging/iio/meter/ade7854.c | 18 -
 drivers/staging/iio/meter/ade7854.h |  7 +++
 4 files changed, 15 insertions(+), 78 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index 63793f9664c7..c3aa6ea9d036 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -110,34 +110,6 @@ static int ade7854_i2c_read_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_i2c_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 8);
-}
-
-static int ade7854_i2c_read_reg_16(struct device *dev,
-  u16 reg_address,
-  u16 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 16);
-}
-
-static int ade7854_i2c_read_reg_24(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 24);
-}
-
-static int ade7854_i2c_read_reg_32(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 32);
-}
-
 static int ade7854_i2c_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
@@ -149,10 +121,7 @@ static int ade7854_i2c_probe(struct i2c_client *client,
return -ENOMEM;
st = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
-   st->read_reg_8 = ade7854_i2c_read_reg_8;
-   st->read_reg_16 = ade7854_i2c_read_reg_16;
-   st->read_reg_24 = ade7854_i2c_read_reg_24;
-   st->read_reg_32 = ade7854_i2c_read_reg_32;
+   st->read_reg = ade7854_i2c_read_reg;
st->write_reg = ade7854_i2c_write_reg;
st->i2c = client;
st->irq = client->irq;
diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index ee6e4d166ece..fc9146757283 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -94,7 +94,7 @@ static int ade7854_spi_read_reg(struct device *dev,
st->tx[2] = reg_address & 0xFF;
 
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
-   if (ret) {
+   if (ret < 0) {
dev_err(>spi->dev, "problem when reading register 0x%02X",
reg_address);
goto unlock;
@@ -120,34 +120,6 @@ static int ade7854_spi_read_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_spi_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 8);
-}
-
-static int ade7854_spi_read_reg_16(struct device *dev,
-  u16 reg_address,
-  u16 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 16);
-}
-
-static int ade7854_spi_read_reg_24(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 24);
-}
-
-static int ade7854_spi_read_reg_32(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 32);
-}
-
 static int ade7854_spi_probe(struct spi_device *spi)
 {
struct ade7854_state *st;
@@ -158,10 +130,7 @@ static int ade7854_spi_probe(struct spi_device *spi)
return -ENOMEM;
st = iio_priv(indio_dev);
spi_set_drvdata(spi, indio_dev);
-   st->read_reg_8 = ade7854_spi_read_reg_8;
-   st->read_reg_16 = ade7854_spi_read_reg_16;
-   st->read_reg_24 = ade7854_spi_read_reg_24;
-   st->read_reg_32 = ade7854_spi_read_reg_32;
+   st->read_reg = ade7854_spi_read_reg;
st->write_reg = ade7854_spi_write_reg;
st->irq = spi->irq;
st->spi = spi;
diff --git

[PATCH v3 7/8] staging:iio:ade7854: Rework SPI read function

2018-03-23 Thread Rodrigo Siqueira
Rework read SPI function to reduce the code duplication and centralizes
all the task in a single function.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
---
Changes in v3:
 - Remove the use of defines that not improve the readability
 - Replace variable name "bytes" for "bits"
 - Update commit message

 drivers/staging/iio/meter/ade7854-spi.c | 136 
 1 file changed, 33 insertions(+), 103 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index be7397042850..ee6e4d166ece 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -67,9 +67,10 @@ static int ade7854_spi_write_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_spi_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
+static int ade7854_spi_read_reg(struct device *dev,
+   u16 reg_address,
+   u32 *val,
+   int bits)
 {
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
@@ -82,7 +83,7 @@ static int ade7854_spi_read_reg_8(struct device *dev,
}, {
.rx_buf = st->rx,
.bits_per_word = 8,
-   .len = 1,
+   .len = bits,
}
};
 
@@ -94,128 +95,57 @@ static int ade7854_spi_read_reg_8(struct device *dev,
 
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
if (ret) {
-   dev_err(>spi->dev, "problem when reading 8 bit register 
0x%02X",
+   dev_err(>spi->dev, "problem when reading register 0x%02X",
reg_address);
-   goto error_ret;
+   goto unlock;
+   }
+
+   switch (bits) {
+   case 8:
+   *val = st->rx[0];
+   break;
+   case 16:
+   *val = be16_to_cpup((const __be16 *)st->rx);
+   break;
+   case 24:
+   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
+   break;
+   case 32:
+   *val = be32_to_cpup((const __be32 *)st->rx);
+   break;
}
-   *val = st->rx[0];
 
-error_ret:
+unlock:
mutex_unlock(>buf_lock);
return ret;
 }
 
+static int ade7854_spi_read_reg_8(struct device *dev,
+ u16 reg_address,
+ u8 *val)
+{
+   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 8);
+}
+
 static int ade7854_spi_read_reg_16(struct device *dev,
   u16 reg_address,
   u16 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-   struct spi_transfer xfers[] = {
-   {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 3,
-   }, {
-   .rx_buf = st->rx,
-   .bits_per_word = 8,
-   .len = 2,
-   }
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_READ_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
-   if (ret) {
-   dev_err(>spi->dev, "problem when reading 16 bit register 
0x%02X",
-   reg_address);
-   goto error_ret;
-   }
-   *val = be16_to_cpup((const __be16 *)st->rx);
-
-error_ret:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 16);
 }
 
 static int ade7854_spi_read_reg_24(struct device *dev,
   u16 reg_address,
   u32 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-   struct spi_transfer xfers[] = {
-   {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 3,
-   }, {
-   .rx_buf = st->rx,
-   .bits_per_word = 8,
-   .len = 3,
-   }
-   };
-
-   mutex_lock(>buf_lock);
-
-   st->tx[0] = ADE7854_READ_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, xfers

[PATCH v3 7/8] staging:iio:ade7854: Rework SPI read function

2018-03-23 Thread Rodrigo Siqueira
Rework read SPI function to reduce the code duplication and centralizes
all the task in a single function.

Signed-off-by: Rodrigo Siqueira 
---
Changes in v3:
 - Remove the use of defines that not improve the readability
 - Replace variable name "bytes" for "bits"
 - Update commit message

 drivers/staging/iio/meter/ade7854-spi.c | 136 
 1 file changed, 33 insertions(+), 103 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index be7397042850..ee6e4d166ece 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -67,9 +67,10 @@ static int ade7854_spi_write_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_spi_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
+static int ade7854_spi_read_reg(struct device *dev,
+   u16 reg_address,
+   u32 *val,
+   int bits)
 {
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
@@ -82,7 +83,7 @@ static int ade7854_spi_read_reg_8(struct device *dev,
}, {
.rx_buf = st->rx,
.bits_per_word = 8,
-   .len = 1,
+   .len = bits,
}
};
 
@@ -94,128 +95,57 @@ static int ade7854_spi_read_reg_8(struct device *dev,
 
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
if (ret) {
-   dev_err(>spi->dev, "problem when reading 8 bit register 
0x%02X",
+   dev_err(>spi->dev, "problem when reading register 0x%02X",
reg_address);
-   goto error_ret;
+   goto unlock;
+   }
+
+   switch (bits) {
+   case 8:
+   *val = st->rx[0];
+   break;
+   case 16:
+   *val = be16_to_cpup((const __be16 *)st->rx);
+   break;
+   case 24:
+   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
+   break;
+   case 32:
+   *val = be32_to_cpup((const __be32 *)st->rx);
+   break;
}
-   *val = st->rx[0];
 
-error_ret:
+unlock:
mutex_unlock(>buf_lock);
return ret;
 }
 
+static int ade7854_spi_read_reg_8(struct device *dev,
+ u16 reg_address,
+ u8 *val)
+{
+   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 8);
+}
+
 static int ade7854_spi_read_reg_16(struct device *dev,
   u16 reg_address,
   u16 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-   struct spi_transfer xfers[] = {
-   {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 3,
-   }, {
-   .rx_buf = st->rx,
-   .bits_per_word = 8,
-   .len = 2,
-   }
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_READ_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
-   if (ret) {
-   dev_err(>spi->dev, "problem when reading 16 bit register 
0x%02X",
-   reg_address);
-   goto error_ret;
-   }
-   *val = be16_to_cpup((const __be16 *)st->rx);
-
-error_ret:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val, 16);
 }
 
 static int ade7854_spi_read_reg_24(struct device *dev,
   u16 reg_address,
   u32 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-   struct spi_transfer xfers[] = {
-   {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 3,
-   }, {
-   .rx_buf = st->rx,
-   .bits_per_word = 8,
-   .len = 3,
-   }
-   };
-
-   mutex_lock(>buf_lock);
-
-   st->tx[0] = ADE7854_READ_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
-   if (ret) {
-   dev

[PATCH v3 6/8] staging:iio:ade7854: Rework I2C read function

2018-03-23 Thread Rodrigo Siqueira
The read operation for the I2C function has many duplications that can
be generalized into a single function. This patch reworks the read
operation for I2C to centralizes all similar code in a single function.

It is possible to remove all the old interface to use the new one,
however, for keeping the things simple and working this patch maintain
legacy interface.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
---
Changes in v3:
 - Remove the use of defines that not improve the readability
 - Replace variable name "bytes" for "bits"
 - Update commit message

 drivers/staging/iio/meter/ade7854-i2c.c | 106 +++-
 1 file changed, 37 insertions(+), 69 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index 29e959fdb932..63793f9664c7 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -65,9 +65,10 @@ static int ade7854_i2c_write_reg(struct device *dev,
return ret < 0 ? ret : 0;
 }
 
-static int ade7854_i2c_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
+static int ade7854_i2c_read_reg(struct device *dev,
+   u16 reg_address,
+   u32 *val,
+   int bits)
 {
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
@@ -79,95 +80,62 @@ static int ade7854_i2c_read_reg_8(struct device *dev,
 
ret = i2c_master_send(st->i2c, st->tx, 2);
if (ret < 0)
-   goto out;
+   goto unlock;
 
-   ret = i2c_master_recv(st->i2c, st->rx, 1);
+   ret = i2c_master_recv(st->i2c, st->rx, bits);
if (ret < 0)
-   goto out;
+   goto unlock;
+
+   switch (bits) {
+   case 8:
+   *val = st->rx[0];
+   break;
+   case 16:
+   *val = (st->rx[0] << 8) | st->rx[1];
+   break;
+   case 24:
+   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
+   break;
+   case 32:
+   *val = (st->rx[0] << 24) | (st->rx[1] << 16) |
+   (st->rx[2] << 8) | st->rx[3];
+   break;
+   default:
+   ret = -EINVAL;
+   goto unlock;
+   }
 
-   *val = st->rx[0];
-out:
+unlock:
mutex_unlock(>buf_lock);
return ret;
 }
 
+static int ade7854_i2c_read_reg_8(struct device *dev,
+ u16 reg_address,
+ u8 *val)
+{
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 8);
+}
+
 static int ade7854_i2c_read_reg_16(struct device *dev,
   u16 reg_address,
   u16 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 2);
-   if (ret < 0)
-   goto out;
-
-   ret = i2c_master_recv(st->i2c, st->rx, 2);
-   if (ret < 0)
-   goto out;
-
-   *val = (st->rx[0] << 8) | st->rx[1];
-out:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 16);
 }
 
 static int ade7854_i2c_read_reg_24(struct device *dev,
   u16 reg_address,
   u32 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 2);
-   if (ret < 0)
-   goto out;
-
-   ret = i2c_master_recv(st->i2c, st->rx, 3);
-   if (ret < 0)
-   goto out;
-
-   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
-out:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 24);
 }
 
 static int ade7854_i2c_read_reg_32(struct device *dev,
   u16 reg_address,
   u32 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   

[PATCH v3 6/8] staging:iio:ade7854: Rework I2C read function

2018-03-23 Thread Rodrigo Siqueira
The read operation for the I2C function has many duplications that can
be generalized into a single function. This patch reworks the read
operation for I2C to centralizes all similar code in a single function.

It is possible to remove all the old interface to use the new one,
however, for keeping the things simple and working this patch maintain
legacy interface.

Signed-off-by: Rodrigo Siqueira 
---
Changes in v3:
 - Remove the use of defines that not improve the readability
 - Replace variable name "bytes" for "bits"
 - Update commit message

 drivers/staging/iio/meter/ade7854-i2c.c | 106 +++-
 1 file changed, 37 insertions(+), 69 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index 29e959fdb932..63793f9664c7 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -65,9 +65,10 @@ static int ade7854_i2c_write_reg(struct device *dev,
return ret < 0 ? ret : 0;
 }
 
-static int ade7854_i2c_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
+static int ade7854_i2c_read_reg(struct device *dev,
+   u16 reg_address,
+   u32 *val,
+   int bits)
 {
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
@@ -79,95 +80,62 @@ static int ade7854_i2c_read_reg_8(struct device *dev,
 
ret = i2c_master_send(st->i2c, st->tx, 2);
if (ret < 0)
-   goto out;
+   goto unlock;
 
-   ret = i2c_master_recv(st->i2c, st->rx, 1);
+   ret = i2c_master_recv(st->i2c, st->rx, bits);
if (ret < 0)
-   goto out;
+   goto unlock;
+
+   switch (bits) {
+   case 8:
+   *val = st->rx[0];
+   break;
+   case 16:
+   *val = (st->rx[0] << 8) | st->rx[1];
+   break;
+   case 24:
+   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
+   break;
+   case 32:
+   *val = (st->rx[0] << 24) | (st->rx[1] << 16) |
+   (st->rx[2] << 8) | st->rx[3];
+   break;
+   default:
+   ret = -EINVAL;
+   goto unlock;
+   }
 
-   *val = st->rx[0];
-out:
+unlock:
mutex_unlock(>buf_lock);
return ret;
 }
 
+static int ade7854_i2c_read_reg_8(struct device *dev,
+ u16 reg_address,
+ u8 *val)
+{
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 8);
+}
+
 static int ade7854_i2c_read_reg_16(struct device *dev,
   u16 reg_address,
   u16 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 2);
-   if (ret < 0)
-   goto out;
-
-   ret = i2c_master_recv(st->i2c, st->rx, 2);
-   if (ret < 0)
-   goto out;
-
-   *val = (st->rx[0] << 8) | st->rx[1];
-out:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 16);
 }
 
 static int ade7854_i2c_read_reg_24(struct device *dev,
   u16 reg_address,
   u32 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 2);
-   if (ret < 0)
-   goto out;
-
-   ret = i2c_master_recv(st->i2c, st->rx, 3);
-   if (ret < 0)
-   goto out;
-
-   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
-out:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val, 24);
 }
 
 static int ade7854_i2c_read_reg_32(struct device *dev,
   u16 reg_address,
   u32 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address &a

[PATCH v3 5/8] staging:iio:ade7854: Remove write_reg_* duplications

2018-03-23 Thread Rodrigo Siqueira
This patch removes code duplications related to the write_reg_*
functions and centralizes them in a single function. Also, it eliminates
the legacy functions and replaces them by a unique signature that is
used by SPI and I2C.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
---
Changes in v3:
 - Update commit message

 drivers/staging/iio/meter/ade7854-i2c.c | 33 +
 drivers/staging/iio/meter/ade7854-spi.c | 33 +
 drivers/staging/iio/meter/ade7854.c | 12 ++--
 drivers/staging/iio/meter/ade7854.h |  9 -
 4 files changed, 12 insertions(+), 75 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index c9f46d26b752..29e959fdb932 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -65,34 +65,6 @@ static int ade7854_i2c_write_reg(struct device *dev,
return ret < 0 ? ret : 0;
 }
 
-static int ade7854_i2c_write_reg_8(struct device *dev,
-  u16 reg_address,
-  u8 val)
-{
-   return ade7854_i2c_write_reg(dev, reg_address, val, 8);
-}
-
-static int ade7854_i2c_write_reg_16(struct device *dev,
-   u16 reg_address,
-   u16 val)
-{
-   return ade7854_i2c_write_reg(dev, reg_address, val, 16);
-}
-
-static int ade7854_i2c_write_reg_24(struct device *dev,
-   u16 reg_address,
-   u32 val)
-{
-   return ade7854_i2c_write_reg(dev, reg_address, val, 24);
-}
-
-static int ade7854_i2c_write_reg_32(struct device *dev,
-   u16 reg_address,
-   u32 val)
-{
-   return ade7854_i2c_write_reg(dev, reg_address, val, 32);
-}
-
 static int ade7854_i2c_read_reg_8(struct device *dev,
  u16 reg_address,
  u8 *val)
@@ -213,10 +185,7 @@ static int ade7854_i2c_probe(struct i2c_client *client,
st->read_reg_16 = ade7854_i2c_read_reg_16;
st->read_reg_24 = ade7854_i2c_read_reg_24;
st->read_reg_32 = ade7854_i2c_read_reg_32;
-   st->write_reg_8 = ade7854_i2c_write_reg_8;
-   st->write_reg_16 = ade7854_i2c_write_reg_16;
-   st->write_reg_24 = ade7854_i2c_write_reg_24;
-   st->write_reg_32 = ade7854_i2c_write_reg_32;
+   st->write_reg = ade7854_i2c_write_reg;
st->i2c = client;
st->irq = client->irq;
 
diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index 9c5c16c4d6e0..be7397042850 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -67,34 +67,6 @@ static int ade7854_spi_write_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_spi_write_reg_8(struct device *dev,
-  u16 reg_address,
-  u8 val)
-{
-   return ade7854_spi_write_reg(dev, reg_address, val, 8);
-}
-
-static int ade7854_spi_write_reg_16(struct device *dev,
-   u16 reg_address,
-   u16 val)
-{
-   return ade7854_spi_write_reg(dev, reg_address, val, 16);
-}
-
-static int ade7854_spi_write_reg_24(struct device *dev,
-   u16 reg_address,
-   u32 val)
-{
-   return ade7854_spi_write_reg(dev, reg_address, val, 24);
-}
-
-static int ade7854_spi_write_reg_32(struct device *dev,
-   u16 reg_address,
-   u32 val)
-{
-   return ade7854_spi_write_reg(dev, reg_address, val, 32);
-}
-
 static int ade7854_spi_read_reg_8(struct device *dev,
  u16 reg_address,
  u8 *val)
@@ -260,10 +232,7 @@ static int ade7854_spi_probe(struct spi_device *spi)
st->read_reg_16 = ade7854_spi_read_reg_16;
st->read_reg_24 = ade7854_spi_read_reg_24;
st->read_reg_32 = ade7854_spi_read_reg_32;
-   st->write_reg_8 = ade7854_spi_write_reg_8;
-   st->write_reg_16 = ade7854_spi_write_reg_16;
-   st->write_reg_24 = ade7854_spi_write_reg_24;
-   st->write_reg_32 = ade7854_spi_write_reg_32;
+   st->write_reg = ade7854_spi_write_reg;
st->irq = spi->irq;
st->spi = spi;
 
diff --git a/drivers/staging/iio/meter/ade7854.c 
b/drivers/staging/iio/meter/ade7854.c
index 0193ae3aae29..45984b9a2bee 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -105,7 +105,7 @@ static ssize_t ade7854_write_8bit(struct device *dev,
ret = kstrtou8(buf, 10, );
if (ret)
goto error_ret;
-   ret = st->write_r

[PATCH v3 5/8] staging:iio:ade7854: Remove write_reg_* duplications

2018-03-23 Thread Rodrigo Siqueira
This patch removes code duplications related to the write_reg_*
functions and centralizes them in a single function. Also, it eliminates
the legacy functions and replaces them by a unique signature that is
used by SPI and I2C.

Signed-off-by: Rodrigo Siqueira 
---
Changes in v3:
 - Update commit message

 drivers/staging/iio/meter/ade7854-i2c.c | 33 +
 drivers/staging/iio/meter/ade7854-spi.c | 33 +
 drivers/staging/iio/meter/ade7854.c | 12 ++--
 drivers/staging/iio/meter/ade7854.h |  9 -
 4 files changed, 12 insertions(+), 75 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index c9f46d26b752..29e959fdb932 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -65,34 +65,6 @@ static int ade7854_i2c_write_reg(struct device *dev,
return ret < 0 ? ret : 0;
 }
 
-static int ade7854_i2c_write_reg_8(struct device *dev,
-  u16 reg_address,
-  u8 val)
-{
-   return ade7854_i2c_write_reg(dev, reg_address, val, 8);
-}
-
-static int ade7854_i2c_write_reg_16(struct device *dev,
-   u16 reg_address,
-   u16 val)
-{
-   return ade7854_i2c_write_reg(dev, reg_address, val, 16);
-}
-
-static int ade7854_i2c_write_reg_24(struct device *dev,
-   u16 reg_address,
-   u32 val)
-{
-   return ade7854_i2c_write_reg(dev, reg_address, val, 24);
-}
-
-static int ade7854_i2c_write_reg_32(struct device *dev,
-   u16 reg_address,
-   u32 val)
-{
-   return ade7854_i2c_write_reg(dev, reg_address, val, 32);
-}
-
 static int ade7854_i2c_read_reg_8(struct device *dev,
  u16 reg_address,
  u8 *val)
@@ -213,10 +185,7 @@ static int ade7854_i2c_probe(struct i2c_client *client,
st->read_reg_16 = ade7854_i2c_read_reg_16;
st->read_reg_24 = ade7854_i2c_read_reg_24;
st->read_reg_32 = ade7854_i2c_read_reg_32;
-   st->write_reg_8 = ade7854_i2c_write_reg_8;
-   st->write_reg_16 = ade7854_i2c_write_reg_16;
-   st->write_reg_24 = ade7854_i2c_write_reg_24;
-   st->write_reg_32 = ade7854_i2c_write_reg_32;
+   st->write_reg = ade7854_i2c_write_reg;
st->i2c = client;
st->irq = client->irq;
 
diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index 9c5c16c4d6e0..be7397042850 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -67,34 +67,6 @@ static int ade7854_spi_write_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_spi_write_reg_8(struct device *dev,
-  u16 reg_address,
-  u8 val)
-{
-   return ade7854_spi_write_reg(dev, reg_address, val, 8);
-}
-
-static int ade7854_spi_write_reg_16(struct device *dev,
-   u16 reg_address,
-   u16 val)
-{
-   return ade7854_spi_write_reg(dev, reg_address, val, 16);
-}
-
-static int ade7854_spi_write_reg_24(struct device *dev,
-   u16 reg_address,
-   u32 val)
-{
-   return ade7854_spi_write_reg(dev, reg_address, val, 24);
-}
-
-static int ade7854_spi_write_reg_32(struct device *dev,
-   u16 reg_address,
-   u32 val)
-{
-   return ade7854_spi_write_reg(dev, reg_address, val, 32);
-}
-
 static int ade7854_spi_read_reg_8(struct device *dev,
  u16 reg_address,
  u8 *val)
@@ -260,10 +232,7 @@ static int ade7854_spi_probe(struct spi_device *spi)
st->read_reg_16 = ade7854_spi_read_reg_16;
st->read_reg_24 = ade7854_spi_read_reg_24;
st->read_reg_32 = ade7854_spi_read_reg_32;
-   st->write_reg_8 = ade7854_spi_write_reg_8;
-   st->write_reg_16 = ade7854_spi_write_reg_16;
-   st->write_reg_24 = ade7854_spi_write_reg_24;
-   st->write_reg_32 = ade7854_spi_write_reg_32;
+   st->write_reg = ade7854_spi_write_reg;
st->irq = spi->irq;
st->spi = spi;
 
diff --git a/drivers/staging/iio/meter/ade7854.c 
b/drivers/staging/iio/meter/ade7854.c
index 0193ae3aae29..45984b9a2bee 100644
--- a/drivers/staging/iio/meter/ade7854.c
+++ b/drivers/staging/iio/meter/ade7854.c
@@ -105,7 +105,7 @@ static ssize_t ade7854_write_8bit(struct device *dev,
ret = kstrtou8(buf, 10, );
if (ret)
goto error_ret;
-   ret = st->write_reg_8(dev, this_attr->address, val);

[PATCH v3 4/8] staging:iio:ade7854: Rework SPI write function

2018-03-23 Thread Rodrigo Siqueira
The write operation using SPI has a many code duplications (similar to
I2C) and four different interfaces per data size. This patch introduces
a single function that centralizes the main task related to SPI.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
---
Changes in v3:
 - Remove the use of defines that not improve the readability
 - Replace variable name "bytes" for "bits"

 drivers/staging/iio/meter/ade7854-spi.c | 108 
 1 file changed, 41 insertions(+), 67 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index 4419b8f06197..9c5c16c4d6e0 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -15,9 +15,10 @@
 #include 
 #include "ade7854.h"
 
-static int ade7854_spi_write_reg_8(struct device *dev,
-  u16 reg_address,
-  u8 val)
+static int ade7854_spi_write_reg(struct device *dev,
+u16 reg_address,
+u32 val,
+int bits)
 {
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
@@ -32,93 +33,66 @@ static int ade7854_spi_write_reg_8(struct device *dev,
st->tx[0] = ADE7854_WRITE_REG;
st->tx[1] = (reg_address >> 8) & 0xFF;
st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = val & 0xFF;
+   switch (bits) {
+   case 8:
+   st->tx[3] = val & 0xFF;
+   break;
+   case 16:
+   xfer.len = 5;
+   st->tx[3] = (val >> 8) & 0xFF;
+   st->tx[4] = val & 0xFF;
+   break;
+   case 24:
+   xfer.len = 6;
+   st->tx[3] = (val >> 16) & 0xFF;
+   st->tx[4] = (val >> 8) & 0xFF;
+   st->tx[5] = val & 0xFF;
+   break;
+   case 32:
+   xfer.len = 7;
+   st->tx[3] = (val >> 24) & 0xFF;
+   st->tx[4] = (val >> 16) & 0xFF;
+   st->tx[5] = (val >> 8) & 0xFF;
+   st->tx[6] = val & 0xFF;
+   break;
+   default:
+   ret = -EINVAL;
+   goto unlock;
+   }
 
ret = spi_sync_transfer(st->spi, , 1);
+unlock:
mutex_unlock(>buf_lock);
 
return ret;
 }
 
+static int ade7854_spi_write_reg_8(struct device *dev,
+  u16 reg_address,
+  u8 val)
+{
+   return ade7854_spi_write_reg(dev, reg_address, val, 8);
+}
+
 static int ade7854_spi_write_reg_16(struct device *dev,
u16 reg_address,
u16 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 5,
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_WRITE_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = (val >> 8) & 0xFF;
-   st->tx[4] = val & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, , 1);
-   mutex_unlock(>buf_lock);
-
-   return ret;
+   return ade7854_spi_write_reg(dev, reg_address, val, 16);
 }
 
 static int ade7854_spi_write_reg_24(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 6,
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_WRITE_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = (val >> 16) & 0xFF;
-   st->tx[4] = (val >> 8) & 0xFF;
-   st->tx[5] = val & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, , 1);
-   mutex_unlock(>buf_lock);
-
-   return ret;
+   return ade7854_spi_write_reg(dev, reg_address, val, 24);
 }
 
 static int ade7854_spi_write_reg_32(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
- 

[PATCH v3 4/8] staging:iio:ade7854: Rework SPI write function

2018-03-23 Thread Rodrigo Siqueira
The write operation using SPI has a many code duplications (similar to
I2C) and four different interfaces per data size. This patch introduces
a single function that centralizes the main task related to SPI.

Signed-off-by: Rodrigo Siqueira 
---
Changes in v3:
 - Remove the use of defines that not improve the readability
 - Replace variable name "bytes" for "bits"

 drivers/staging/iio/meter/ade7854-spi.c | 108 
 1 file changed, 41 insertions(+), 67 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index 4419b8f06197..9c5c16c4d6e0 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -15,9 +15,10 @@
 #include 
 #include "ade7854.h"
 
-static int ade7854_spi_write_reg_8(struct device *dev,
-  u16 reg_address,
-  u8 val)
+static int ade7854_spi_write_reg(struct device *dev,
+u16 reg_address,
+u32 val,
+int bits)
 {
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
@@ -32,93 +33,66 @@ static int ade7854_spi_write_reg_8(struct device *dev,
st->tx[0] = ADE7854_WRITE_REG;
st->tx[1] = (reg_address >> 8) & 0xFF;
st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = val & 0xFF;
+   switch (bits) {
+   case 8:
+   st->tx[3] = val & 0xFF;
+   break;
+   case 16:
+   xfer.len = 5;
+   st->tx[3] = (val >> 8) & 0xFF;
+   st->tx[4] = val & 0xFF;
+   break;
+   case 24:
+   xfer.len = 6;
+   st->tx[3] = (val >> 16) & 0xFF;
+   st->tx[4] = (val >> 8) & 0xFF;
+   st->tx[5] = val & 0xFF;
+   break;
+   case 32:
+   xfer.len = 7;
+   st->tx[3] = (val >> 24) & 0xFF;
+   st->tx[4] = (val >> 16) & 0xFF;
+   st->tx[5] = (val >> 8) & 0xFF;
+   st->tx[6] = val & 0xFF;
+   break;
+   default:
+   ret = -EINVAL;
+   goto unlock;
+   }
 
ret = spi_sync_transfer(st->spi, , 1);
+unlock:
mutex_unlock(>buf_lock);
 
return ret;
 }
 
+static int ade7854_spi_write_reg_8(struct device *dev,
+  u16 reg_address,
+  u8 val)
+{
+   return ade7854_spi_write_reg(dev, reg_address, val, 8);
+}
+
 static int ade7854_spi_write_reg_16(struct device *dev,
u16 reg_address,
u16 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 5,
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_WRITE_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = (val >> 8) & 0xFF;
-   st->tx[4] = val & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, , 1);
-   mutex_unlock(>buf_lock);
-
-   return ret;
+   return ade7854_spi_write_reg(dev, reg_address, val, 16);
 }
 
 static int ade7854_spi_write_reg_24(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 6,
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_WRITE_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = (val >> 16) & 0xFF;
-   st->tx[4] = (val >> 8) & 0xFF;
-   st->tx[5] = val & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, , 1);
-   mutex_unlock(>buf_lock);
-
-   return ret;
+   return ade7854_spi_write_reg(dev, reg_address, val, 24);
 }
 
 static int ade7854_spi_write_reg_32(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-  

[PATCH v3 3/8] staging:iio:ade7854: Rework I2C write function

2018-03-23 Thread Rodrigo Siqueira
The write operation using I2C has many code duplications and four
different interfaces per data size. This patch introduces a single
function that centralizes the main tasks.

The central function inserted by this patch can easily replace all the
four functions related to the data size. However, this patch does not
remove any code signature for keeping the meter module work and make
easier to review this patch.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
---
Changes in v3:
 - Remove the use of defines that not improve the readability
 - Replace variable name "bytes" for "bits"

 drivers/staging/iio/meter/ade7854-i2c.c | 96 -
 1 file changed, 46 insertions(+), 50 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index 37c957482493..c9f46d26b752 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -15,86 +15,82 @@
 #include 
 #include "ade7854.h"
 
-static int ade7854_i2c_write_reg_8(struct device *dev,
-  u16 reg_address,
-  u8 val)
+static int ade7854_i2c_write_reg(struct device *dev,
+u16 reg_address,
+u32 val,
+int bits)
 {
int ret;
+   int count;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
 
mutex_lock(>buf_lock);
st->tx[0] = (reg_address >> 8) & 0xFF;
st->tx[1] = reg_address & 0xFF;
-   st->tx[2] = val;
 
-   ret = i2c_master_send(st->i2c, st->tx, 3);
+   switch (bits) {
+   case 8:
+   st->tx[2] = val & 0xFF;
+   count = 3;
+   break;
+   case 16:
+   st->tx[2] = (val >> 8) & 0xFF;
+   st->tx[3] = val & 0xFF;
+   count = 4;
+   break;
+   case 24:
+   st->tx[2] = (val >> 16) & 0xFF;
+   st->tx[3] = (val >> 8) & 0xFF;
+   st->tx[4] = val & 0xFF;
+   count = 5;
+   break;
+   case 32:
+   st->tx[2] = (val >> 24) & 0xFF;
+   st->tx[3] = (val >> 16) & 0xFF;
+   st->tx[4] = (val >> 8) & 0xFF;
+   st->tx[5] = val & 0xFF;
+   count = 6;
+   break;
+   default:
+   ret = -EINVAL;
+   goto unlock;
+   }
+
+   ret = i2c_master_send(st->i2c, st->tx, count);
+
+unlock:
mutex_unlock(>buf_lock);
 
return ret < 0 ? ret : 0;
 }
 
+static int ade7854_i2c_write_reg_8(struct device *dev,
+  u16 reg_address,
+  u8 val)
+{
+   return ade7854_i2c_write_reg(dev, reg_address, val, 8);
+}
+
 static int ade7854_i2c_write_reg_16(struct device *dev,
u16 reg_address,
u16 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-   st->tx[2] = (val >> 8) & 0xFF;
-   st->tx[3] = val & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 4);
-   mutex_unlock(>buf_lock);
-
-   return ret < 0 ? ret : 0;
+   return ade7854_i2c_write_reg(dev, reg_address, val, 16);
 }
 
 static int ade7854_i2c_write_reg_24(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-   st->tx[2] = (val >> 16) & 0xFF;
-   st->tx[3] = (val >> 8) & 0xFF;
-   st->tx[4] = val & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 5);
-   mutex_unlock(>buf_lock);
-
-   return ret < 0 ? ret : 0;
+   return ade7854_i2c_write_reg(dev, reg_address, val, 24);
 }
 
 static int ade7854_i2c_write_reg_32(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = r

[PATCH v3 3/8] staging:iio:ade7854: Rework I2C write function

2018-03-23 Thread Rodrigo Siqueira
The write operation using I2C has many code duplications and four
different interfaces per data size. This patch introduces a single
function that centralizes the main tasks.

The central function inserted by this patch can easily replace all the
four functions related to the data size. However, this patch does not
remove any code signature for keeping the meter module work and make
easier to review this patch.

Signed-off-by: Rodrigo Siqueira 
---
Changes in v3:
 - Remove the use of defines that not improve the readability
 - Replace variable name "bytes" for "bits"

 drivers/staging/iio/meter/ade7854-i2c.c | 96 -
 1 file changed, 46 insertions(+), 50 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index 37c957482493..c9f46d26b752 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -15,86 +15,82 @@
 #include 
 #include "ade7854.h"
 
-static int ade7854_i2c_write_reg_8(struct device *dev,
-  u16 reg_address,
-  u8 val)
+static int ade7854_i2c_write_reg(struct device *dev,
+u16 reg_address,
+u32 val,
+int bits)
 {
int ret;
+   int count;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
 
mutex_lock(>buf_lock);
st->tx[0] = (reg_address >> 8) & 0xFF;
st->tx[1] = reg_address & 0xFF;
-   st->tx[2] = val;
 
-   ret = i2c_master_send(st->i2c, st->tx, 3);
+   switch (bits) {
+   case 8:
+   st->tx[2] = val & 0xFF;
+   count = 3;
+   break;
+   case 16:
+   st->tx[2] = (val >> 8) & 0xFF;
+   st->tx[3] = val & 0xFF;
+   count = 4;
+   break;
+   case 24:
+   st->tx[2] = (val >> 16) & 0xFF;
+   st->tx[3] = (val >> 8) & 0xFF;
+   st->tx[4] = val & 0xFF;
+   count = 5;
+   break;
+   case 32:
+   st->tx[2] = (val >> 24) & 0xFF;
+   st->tx[3] = (val >> 16) & 0xFF;
+   st->tx[4] = (val >> 8) & 0xFF;
+   st->tx[5] = val & 0xFF;
+   count = 6;
+   break;
+   default:
+   ret = -EINVAL;
+   goto unlock;
+   }
+
+   ret = i2c_master_send(st->i2c, st->tx, count);
+
+unlock:
mutex_unlock(>buf_lock);
 
return ret < 0 ? ret : 0;
 }
 
+static int ade7854_i2c_write_reg_8(struct device *dev,
+  u16 reg_address,
+  u8 val)
+{
+   return ade7854_i2c_write_reg(dev, reg_address, val, 8);
+}
+
 static int ade7854_i2c_write_reg_16(struct device *dev,
u16 reg_address,
u16 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-   st->tx[2] = (val >> 8) & 0xFF;
-   st->tx[3] = val & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 4);
-   mutex_unlock(>buf_lock);
-
-   return ret < 0 ? ret : 0;
+   return ade7854_i2c_write_reg(dev, reg_address, val, 16);
 }
 
 static int ade7854_i2c_write_reg_24(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-   st->tx[2] = (val >> 16) & 0xFF;
-   st->tx[3] = (val >> 8) & 0xFF;
-   st->tx[4] = val & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 5);
-   mutex_unlock(>buf_lock);
-
-   return ret < 0 ? ret : 0;
+   return ade7854_i2c_write_reg(dev, reg_address, val, 24);
 }
 
 static int ade7854_i2c_write_reg_32(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-   s

[PATCH v3 0/8] Cleanup on I2C/SPI code

2018-03-23 Thread Rodrigo Siqueira
This patchset reworks the I2C/SPI code from meter module. The set of
patches try to reduce the code duplication and make the communication
reliable. The current version of the module had many code duplications,
which make the code more error-prone and hard to read. Jonh Syne
identified some wrong error handling and fixed it in his patches; in
this series of patches I analyzed Jonh's fixes, and use it in the new
code.

It is important to highlight that meter module is under observation, due
to the lack of hardware and the old design of the chip. However, John
has the hardware for testing and interest to help to update the code
[1]. As a result, this patchset represents the first work effort to
update the meter module in the staging.

1 - https://marc.info/?l=linux-iio=152046885922153=2

Changes in V2:
 - Reorganize the patchset to make easier to backport fixes.
 - Adds two commits at the beginning of the patchset. First, fixes bugs
   related to wrong verification in read/write I2C operations. Second,
   adjust the incorrect amount of data read.
 - Removes unnecessary code in read/write functions for SPI and I2C
   during the rework.

Changes in V3:
 - Adds clarifications related to authorship.
 - Adds 'fixes' tag on the first two patches message.
 - Removes unnecessary defines.
 - Updates commit messages to better describe changes.

John Syne (2):
  staging:iio:ade7854: Fix error handling on read/write
  staging:iio:ade7854: Fix the wrong number of bits to read

Rodrigo Siqueira (6):
  staging:iio:ade7854: Rework I2C write function
  staging:iio:ade7854: Rework SPI write function
  staging:iio:ade7854: Remove write_reg_* duplications
  staging:iio:ade7854: Rework I2C read function
  staging:iio:ade7854: Rework SPI read function
  staging:iio:ade7854: Remove read_reg_* duplications

 drivers/staging/iio/meter/ade7854-i2c.c | 238 +---
 drivers/staging/iio/meter/ade7854-spi.c | 268 +++-
 drivers/staging/iio/meter/ade7854.c |  40 ++---
 drivers/staging/iio/meter/ade7854.h |  16 +-
 4 files changed, 152 insertions(+), 410 deletions(-)

-- 
2.16.2



[PATCH v3 0/8] Cleanup on I2C/SPI code

2018-03-23 Thread Rodrigo Siqueira
This patchset reworks the I2C/SPI code from meter module. The set of
patches try to reduce the code duplication and make the communication
reliable. The current version of the module had many code duplications,
which make the code more error-prone and hard to read. Jonh Syne
identified some wrong error handling and fixed it in his patches; in
this series of patches I analyzed Jonh's fixes, and use it in the new
code.

It is important to highlight that meter module is under observation, due
to the lack of hardware and the old design of the chip. However, John
has the hardware for testing and interest to help to update the code
[1]. As a result, this patchset represents the first work effort to
update the meter module in the staging.

1 - https://marc.info/?l=linux-iio=152046885922153=2

Changes in V2:
 - Reorganize the patchset to make easier to backport fixes.
 - Adds two commits at the beginning of the patchset. First, fixes bugs
   related to wrong verification in read/write I2C operations. Second,
   adjust the incorrect amount of data read.
 - Removes unnecessary code in read/write functions for SPI and I2C
   during the rework.

Changes in V3:
 - Adds clarifications related to authorship.
 - Adds 'fixes' tag on the first two patches message.
 - Removes unnecessary defines.
 - Updates commit messages to better describe changes.

John Syne (2):
  staging:iio:ade7854: Fix error handling on read/write
  staging:iio:ade7854: Fix the wrong number of bits to read

Rodrigo Siqueira (6):
  staging:iio:ade7854: Rework I2C write function
  staging:iio:ade7854: Rework SPI write function
  staging:iio:ade7854: Remove write_reg_* duplications
  staging:iio:ade7854: Rework I2C read function
  staging:iio:ade7854: Rework SPI read function
  staging:iio:ade7854: Remove read_reg_* duplications

 drivers/staging/iio/meter/ade7854-i2c.c | 238 +---
 drivers/staging/iio/meter/ade7854-spi.c | 268 +++-
 drivers/staging/iio/meter/ade7854.c |  40 ++---
 drivers/staging/iio/meter/ade7854.h |  16 +-
 4 files changed, 152 insertions(+), 410 deletions(-)

-- 
2.16.2



Re: [PATCH v2 1/8] staging:iio:ade7854: Fix error handling on read/write

2018-03-19 Thread Rodrigo Siqueira
On 03/18, Jonathan Cameron wrote:
> On Fri, 16 Mar 2018 19:48:33 -0300
> Rodrigo Siqueira <rodrigosiqueiram...@gmail.com> wrote:
> 
> > The original code does not correctly handle the error related to I2C
> > read and write. This patch fixes the error handling related to all
> > read/write functions for I2C. This patch is an adaptation of the John
> > Syne patches.
> > 
> > Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
> > Signed-off-by: John Syne <john3...@gmail.com>
> Hi Rodrigo,
> 
> I'm not sure what the chain of authorship was here.  If this is fundamentally
> John's original patch he should still be the author and his sign off should be
> first.  You then sign off afterwards to indicate that you 'handled' the patch
> and believe the work to be John's (you are trusting his sign off).  This
> is 'fun' legal stuff - read the docs on developers certificate of origin.
> 
> If the patch has changed 'enough' (where that is a fuzzy definition)
> then you should as you have here take the authorship, but John's sign off is
> no longer true (it's a different patch).  If John has reviewed the code
> it is fine to have a reviewed-by or acked-by from John there to reflect
> that.
> 
> Anyhow, please clarify the situation as I shouldn't take a patch where
> I'm applying my sign-off without knowing the origins etc.

Hi Jonathan,

Just for clarification, this is fundamentally John's original patch with
some changes on the way that write_reg operation returns the error. I
should ask for someone else, how to correctly handle this situation
since I did not have experience with this situation.

Actually, when I worked on this patch, I was confused about using
different authorship from the email. I got confused because of the
following statement:

"Make sure that the email you specify here is the same email you used to
set up sending mail. The Linux kernel developers will not accept a patch
where the "From" email differs from the "Signed-off-by" line, which is
what will happen if these two emails do not match." [1]

Anyway, I think this is not a newbie issue, and I should asked first.
Thanks for the great explanation, I will not make this kind of mistake
again.

Thanks

[1] - https://kernelnewbies.org/FirstKernelPatch
 
> > ---
> >  drivers/staging/iio/meter/ade7854-i2c.c | 24 
> >  drivers/staging/iio/meter/ade7854.c | 10 +-
> >  2 files changed, 17 insertions(+), 17 deletions(-)
> > 
> > diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
> > b/drivers/staging/iio/meter/ade7854-i2c.c
> > index 317e4f0d8176..4437f1e33261 100644
> > --- a/drivers/staging/iio/meter/ade7854-i2c.c
> > +++ b/drivers/staging/iio/meter/ade7854-i2c.c
> > @@ -31,7 +31,7 @@ static int ade7854_i2c_write_reg_8(struct device *dev,
> > ret = i2c_master_send(st->i2c, st->tx, 3);
> > mutex_unlock(>buf_lock);
> >  
> > -   return ret;
> > +   return ret < 0 ? ret : 0;
> >  }
> >  
> >  static int ade7854_i2c_write_reg_16(struct device *dev,
> > @@ -51,7 +51,7 @@ static int ade7854_i2c_write_reg_16(struct device *dev,
> > ret = i2c_master_send(st->i2c, st->tx, 4);
> > mutex_unlock(>buf_lock);
> >  
> > -   return ret;
> > +   return ret < 0 ? ret : 0;
> >  }
> >  
> >  static int ade7854_i2c_write_reg_24(struct device *dev,
> > @@ -72,7 +72,7 @@ static int ade7854_i2c_write_reg_24(struct device *dev,
> > ret = i2c_master_send(st->i2c, st->tx, 5);
> > mutex_unlock(>buf_lock);
> >  
> > -   return ret;
> > +   return ret < 0 ? ret : 0;
> >  }
> >  
> >  static int ade7854_i2c_write_reg_32(struct device *dev,
> > @@ -94,7 +94,7 @@ static int ade7854_i2c_write_reg_32(struct device *dev,
> > ret = i2c_master_send(st->i2c, st->tx, 6);
> > mutex_unlock(>buf_lock);
> >  
> > -   return ret;
> > +   return ret < 0 ? ret : 0;
> >  }
> So for write cases you are flattening to 0 for good and < 0 for bad.
> good.
> >  
> >  static int ade7854_i2c_read_reg_8(struct device *dev,
> > @@ -110,11 +110,11 @@ static int ade7854_i2c_read_reg_8(struct device *dev,
> > st->tx[1] = reg_address & 0xFF;
> >  
> > ret = i2c_master_send(st->i2c, st->tx, 2);
> > -   if (ret)
> > +   if (ret < 0)
> > goto out;
> >  
> > ret = i2c_master_recv(st->i2c, st->rx, 1);
> > -   if (ret)
> > +   if (ret < 0)
> > goto out;
> >  
> > *val = st->rx[0];
> But in read cases you are return

Re: [PATCH v2 1/8] staging:iio:ade7854: Fix error handling on read/write

2018-03-19 Thread Rodrigo Siqueira
On 03/18, Jonathan Cameron wrote:
> On Fri, 16 Mar 2018 19:48:33 -0300
> Rodrigo Siqueira  wrote:
> 
> > The original code does not correctly handle the error related to I2C
> > read and write. This patch fixes the error handling related to all
> > read/write functions for I2C. This patch is an adaptation of the John
> > Syne patches.
> > 
> > Signed-off-by: Rodrigo Siqueira 
> > Signed-off-by: John Syne 
> Hi Rodrigo,
> 
> I'm not sure what the chain of authorship was here.  If this is fundamentally
> John's original patch he should still be the author and his sign off should be
> first.  You then sign off afterwards to indicate that you 'handled' the patch
> and believe the work to be John's (you are trusting his sign off).  This
> is 'fun' legal stuff - read the docs on developers certificate of origin.
> 
> If the patch has changed 'enough' (where that is a fuzzy definition)
> then you should as you have here take the authorship, but John's sign off is
> no longer true (it's a different patch).  If John has reviewed the code
> it is fine to have a reviewed-by or acked-by from John there to reflect
> that.
> 
> Anyhow, please clarify the situation as I shouldn't take a patch where
> I'm applying my sign-off without knowing the origins etc.

Hi Jonathan,

Just for clarification, this is fundamentally John's original patch with
some changes on the way that write_reg operation returns the error. I
should ask for someone else, how to correctly handle this situation
since I did not have experience with this situation.

Actually, when I worked on this patch, I was confused about using
different authorship from the email. I got confused because of the
following statement:

"Make sure that the email you specify here is the same email you used to
set up sending mail. The Linux kernel developers will not accept a patch
where the "From" email differs from the "Signed-off-by" line, which is
what will happen if these two emails do not match." [1]

Anyway, I think this is not a newbie issue, and I should asked first.
Thanks for the great explanation, I will not make this kind of mistake
again.

Thanks

[1] - https://kernelnewbies.org/FirstKernelPatch
 
> > ---
> >  drivers/staging/iio/meter/ade7854-i2c.c | 24 
> >  drivers/staging/iio/meter/ade7854.c | 10 +-
> >  2 files changed, 17 insertions(+), 17 deletions(-)
> > 
> > diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
> > b/drivers/staging/iio/meter/ade7854-i2c.c
> > index 317e4f0d8176..4437f1e33261 100644
> > --- a/drivers/staging/iio/meter/ade7854-i2c.c
> > +++ b/drivers/staging/iio/meter/ade7854-i2c.c
> > @@ -31,7 +31,7 @@ static int ade7854_i2c_write_reg_8(struct device *dev,
> > ret = i2c_master_send(st->i2c, st->tx, 3);
> > mutex_unlock(>buf_lock);
> >  
> > -   return ret;
> > +   return ret < 0 ? ret : 0;
> >  }
> >  
> >  static int ade7854_i2c_write_reg_16(struct device *dev,
> > @@ -51,7 +51,7 @@ static int ade7854_i2c_write_reg_16(struct device *dev,
> > ret = i2c_master_send(st->i2c, st->tx, 4);
> > mutex_unlock(>buf_lock);
> >  
> > -   return ret;
> > +   return ret < 0 ? ret : 0;
> >  }
> >  
> >  static int ade7854_i2c_write_reg_24(struct device *dev,
> > @@ -72,7 +72,7 @@ static int ade7854_i2c_write_reg_24(struct device *dev,
> > ret = i2c_master_send(st->i2c, st->tx, 5);
> > mutex_unlock(>buf_lock);
> >  
> > -   return ret;
> > +   return ret < 0 ? ret : 0;
> >  }
> >  
> >  static int ade7854_i2c_write_reg_32(struct device *dev,
> > @@ -94,7 +94,7 @@ static int ade7854_i2c_write_reg_32(struct device *dev,
> > ret = i2c_master_send(st->i2c, st->tx, 6);
> > mutex_unlock(>buf_lock);
> >  
> > -   return ret;
> > +   return ret < 0 ? ret : 0;
> >  }
> So for write cases you are flattening to 0 for good and < 0 for bad.
> good.
> >  
> >  static int ade7854_i2c_read_reg_8(struct device *dev,
> > @@ -110,11 +110,11 @@ static int ade7854_i2c_read_reg_8(struct device *dev,
> > st->tx[1] = reg_address & 0xFF;
> >  
> > ret = i2c_master_send(st->i2c, st->tx, 2);
> > -   if (ret)
> > +   if (ret < 0)
> > goto out;
> >  
> > ret = i2c_master_recv(st->i2c, st->rx, 1);
> > -   if (ret)
> > +   if (ret < 0)
> > goto out;
> >  
> > *val = st->rx[0];
> But in read cases you are returning the number of bytes read...
> Given these functions can know the 'right' answer to that wh

Re: [PATCH v2 1/3] staging:iio:ad2s1210: Add channel for fclkin and fexcit

2018-03-19 Thread Rodrigo Siqueira
Hi,

On 03/17, Jonathan Cameron wrote:
> On Tue, 13 Mar 2018 13:05:28 -0300
> Rodrigo Siqueira <rodrigosiqueiram...@gmail.com> wrote:
> 
> > The ad2s1210 does not contain any channel for the fclkin and fexcit. As
> > a result, it uses IIO_DEVICE_ATTR to expose this information. This patch
> > adds one channel for fclkin and another for fexcit. It also adds an enum
> > to easily address the correct channel.
> > 
> > Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
> Take a step back.  What are these new channels actually for?
> We aren't looking at a general purpose frequency input and output.
> (mind you they are both currently inputs which makes even less sense!)
> 
> These are controls for the excitation frequency for a resolver.
> What is userspace going to do with them?  Nothing of any use certainly.
> 
> So what do they actually change that matters to an application?
> 1) The speed at which we can detect a loss of signal condition.
> 2) The achievable resolution of the sensor.
> 
> So how would userspace know how to configure it?  I'm not sure it
> would, but it is these things that should be driving the choice
> not the actual value of the frequency (which is really just
> a weird internal value in the way the resolver system works).
> 
> There is a pretty strong argument that we should leave the excitation
> frequency alone at 10kHz unless the platform designer knows better,
> in which case they should supply it via devicetree rather than
> from userspace.
> 
> Anyhow, it needs a rethink - exposing these as channels is not
> the way to go!
> 
> Jonathan

Thanks for the feedback.
Now I am thinking about this module (and IIO subsystem) from another
perspective :)

I will rethink and came with another approach. 
 
> 
> > ---
> >  drivers/staging/iio/resolver/ad2s1210.c | 43 
> > ++---
> >  1 file changed, 29 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/staging/iio/resolver/ad2s1210.c 
> > b/drivers/staging/iio/resolver/ad2s1210.c
> > index ac13b99bd9cb..28c3fd439663 100644
> > --- a/drivers/staging/iio/resolver/ad2s1210.c
> > +++ b/drivers/staging/iio/resolver/ad2s1210.c
> > @@ -67,6 +67,11 @@ enum ad2s1210_mode {
> > MOD_RESERVED,
> >  };
> >  
> > +enum ad2s1210_frequency_channel {
> > +   FCLKIN = 0,
> > +   FEXCIT,
> > +};
> > +
> >  static const unsigned int ad2s1210_resolution_value[] = { 10, 12, 14, 16 };
> >  
> >  struct ad2s1210_state {
> > @@ -88,6 +93,30 @@ static const int ad2s1210_mode_vals[4][2] = {
> > [MOD_CONFIG] = { 1, 0 },
> >  };
> >  
> > +static const struct iio_chan_spec ad2s1210_channels[] = {
> > +   {
> > +   .type = IIO_ANGL,
> > +   .indexed = 1,
> > +   .channel = 0,
> > +   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > +   }, {
> > +   .type = IIO_ANGL_VEL,
> > +   .indexed = 1,
> > +   .channel = 0,
> > +   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > +   }, {
> > +   .type = IIO_CHAN_INFO_FREQUENCY,
> > +   .indexed = 1,
> > +   .channel = FCLKIN,
> > +   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > +   }, {
> > +   .type = IIO_CHAN_INFO_FREQUENCY,
> > +   .indexed = 1,
> > +   .channel = FEXCIT,
> > +   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > +   },
> > +};
> > +
> This seems broken, you can't just add a channel and not support
> it until the following patches.
> 
> >  static inline void ad2s1210_set_mode(enum ad2s1210_mode mode,
> >  struct ad2s1210_state *st)
> >  {
> > @@ -552,20 +581,6 @@ static IIO_DEVICE_ATTR(lot_low_thrd, 0644,
> >ad2s1210_show_reg, ad2s1210_store_reg,
> >AD2S1210_REG_LOT_LOW_THRD);
> >  
> > -static const struct iio_chan_spec ad2s1210_channels[] = {
> > -   {
> > -   .type = IIO_ANGL,
> > -   .indexed = 1,
> > -   .channel = 0,
> > -   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > -   }, {
> > -   .type = IIO_ANGL_VEL,
> > -   .indexed = 1,
> > -   .channel = 0,
> > -   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > -   }
> > -};
> > -
> >  static struct attribute *ad2s1210_attributes[] = {
> > _dev_attr_fclkin.dev_attr.attr,
> > _dev_attr_fexcit.dev_attr.attr,
> 


Re: [PATCH v2 1/3] staging:iio:ad2s1210: Add channel for fclkin and fexcit

2018-03-19 Thread Rodrigo Siqueira
Hi,

On 03/17, Jonathan Cameron wrote:
> On Tue, 13 Mar 2018 13:05:28 -0300
> Rodrigo Siqueira  wrote:
> 
> > The ad2s1210 does not contain any channel for the fclkin and fexcit. As
> > a result, it uses IIO_DEVICE_ATTR to expose this information. This patch
> > adds one channel for fclkin and another for fexcit. It also adds an enum
> > to easily address the correct channel.
> > 
> > Signed-off-by: Rodrigo Siqueira 
> Take a step back.  What are these new channels actually for?
> We aren't looking at a general purpose frequency input and output.
> (mind you they are both currently inputs which makes even less sense!)
> 
> These are controls for the excitation frequency for a resolver.
> What is userspace going to do with them?  Nothing of any use certainly.
> 
> So what do they actually change that matters to an application?
> 1) The speed at which we can detect a loss of signal condition.
> 2) The achievable resolution of the sensor.
> 
> So how would userspace know how to configure it?  I'm not sure it
> would, but it is these things that should be driving the choice
> not the actual value of the frequency (which is really just
> a weird internal value in the way the resolver system works).
> 
> There is a pretty strong argument that we should leave the excitation
> frequency alone at 10kHz unless the platform designer knows better,
> in which case they should supply it via devicetree rather than
> from userspace.
> 
> Anyhow, it needs a rethink - exposing these as channels is not
> the way to go!
> 
> Jonathan

Thanks for the feedback.
Now I am thinking about this module (and IIO subsystem) from another
perspective :)

I will rethink and came with another approach. 
 
> 
> > ---
> >  drivers/staging/iio/resolver/ad2s1210.c | 43 
> > ++---
> >  1 file changed, 29 insertions(+), 14 deletions(-)
> > 
> > diff --git a/drivers/staging/iio/resolver/ad2s1210.c 
> > b/drivers/staging/iio/resolver/ad2s1210.c
> > index ac13b99bd9cb..28c3fd439663 100644
> > --- a/drivers/staging/iio/resolver/ad2s1210.c
> > +++ b/drivers/staging/iio/resolver/ad2s1210.c
> > @@ -67,6 +67,11 @@ enum ad2s1210_mode {
> > MOD_RESERVED,
> >  };
> >  
> > +enum ad2s1210_frequency_channel {
> > +   FCLKIN = 0,
> > +   FEXCIT,
> > +};
> > +
> >  static const unsigned int ad2s1210_resolution_value[] = { 10, 12, 14, 16 };
> >  
> >  struct ad2s1210_state {
> > @@ -88,6 +93,30 @@ static const int ad2s1210_mode_vals[4][2] = {
> > [MOD_CONFIG] = { 1, 0 },
> >  };
> >  
> > +static const struct iio_chan_spec ad2s1210_channels[] = {
> > +   {
> > +   .type = IIO_ANGL,
> > +   .indexed = 1,
> > +   .channel = 0,
> > +   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > +   }, {
> > +   .type = IIO_ANGL_VEL,
> > +   .indexed = 1,
> > +   .channel = 0,
> > +   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > +   }, {
> > +   .type = IIO_CHAN_INFO_FREQUENCY,
> > +   .indexed = 1,
> > +   .channel = FCLKIN,
> > +   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > +   }, {
> > +   .type = IIO_CHAN_INFO_FREQUENCY,
> > +   .indexed = 1,
> > +   .channel = FEXCIT,
> > +   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > +   },
> > +};
> > +
> This seems broken, you can't just add a channel and not support
> it until the following patches.
> 
> >  static inline void ad2s1210_set_mode(enum ad2s1210_mode mode,
> >  struct ad2s1210_state *st)
> >  {
> > @@ -552,20 +581,6 @@ static IIO_DEVICE_ATTR(lot_low_thrd, 0644,
> >ad2s1210_show_reg, ad2s1210_store_reg,
> >AD2S1210_REG_LOT_LOW_THRD);
> >  
> > -static const struct iio_chan_spec ad2s1210_channels[] = {
> > -   {
> > -   .type = IIO_ANGL,
> > -   .indexed = 1,
> > -   .channel = 0,
> > -   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > -   }, {
> > -   .type = IIO_ANGL_VEL,
> > -   .indexed = 1,
> > -   .channel = 0,
> > -   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > -   }
> > -};
> > -
> >  static struct attribute *ad2s1210_attributes[] = {
> > _dev_attr_fclkin.dev_attr.attr,
> > _dev_attr_fexcit.dev_attr.attr,
> 


[PATCH v2 8/8] staging:iio:ade7854: Remove read_reg_* duplications

2018-03-16 Thread Rodrigo Siqueira
The original code had a read function per data size; after updates, all
read functions tasks were centralized in a single function, but the old
signature was kept to maintain the module working without problems. This
patch removes a set of duplications associated with read_reg_*, and
update the areas that calling the old interface by the new one. During
the update for use a single function, some errors handlings were updated
based on the John Syne patches.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
Signed-off-by: John Syne <john3...@gmail.com>
---
 drivers/staging/iio/meter/ade7854-i2c.c | 37 +--
 drivers/staging/iio/meter/ade7854-spi.c | 39 ++---
 drivers/staging/iio/meter/ade7854.c | 18 +++
 drivers/staging/iio/meter/ade7854.h |  7 +++---
 4 files changed, 15 insertions(+), 86 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index 20db8eedb84a..162c171a8851 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -110,38 +110,6 @@ static int ade7854_i2c_read_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_i2c_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_8_BITS);
-}
-
-static int ade7854_i2c_read_reg_16(struct device *dev,
-  u16 reg_address,
-  u16 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_16_BITS);
-}
-
-static int ade7854_i2c_read_reg_24(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_24_BITS);
-}
-
-static int ade7854_i2c_read_reg_32(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_32_BITS);
-}
-
 static int ade7854_i2c_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
@@ -153,10 +121,7 @@ static int ade7854_i2c_probe(struct i2c_client *client,
return -ENOMEM;
st = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
-   st->read_reg_8 = ade7854_i2c_read_reg_8;
-   st->read_reg_16 = ade7854_i2c_read_reg_16;
-   st->read_reg_24 = ade7854_i2c_read_reg_24;
-   st->read_reg_32 = ade7854_i2c_read_reg_32;
+   st->read_reg = ade7854_i2c_read_reg;
st->write_reg = ade7854_i2c_write_reg;
st->i2c = client;
st->irq = client->irq;
diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index 964d6c6e76d1..66b8a8767a26 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -94,7 +94,7 @@ static int ade7854_spi_read_reg(struct device *dev,
st->tx[2] = reg_address & 0xFF;
 
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
-   if (ret) {
+   if (ret < 0) {
dev_err(>spi->dev, "problem when reading register 0x%02X",
reg_address);
goto unlock;
@@ -120,38 +120,6 @@ static int ade7854_spi_read_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_spi_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_8_BITS);
-}
-
-static int ade7854_spi_read_reg_16(struct device *dev,
-  u16 reg_address,
-  u16 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_16_BITS);
-}
-
-static int ade7854_spi_read_reg_24(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_24_BITS);
-}
-
-static int ade7854_spi_read_reg_32(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_32_BITS);
-}
-
 static int ade7854_spi_probe(struct spi_device *spi)
 {
struct ade7854_state *st;
@@ -

[PATCH v2 6/8] staging:iio:ade7854: Rework I2C read function

2018-03-16 Thread Rodrigo Siqueira
The read operation for the I2C function has many duplications that can
be generalized into a single function. This patch reworks the read
operation for I2C to centralizes all similar code in a single function.
Part of the rework includes a proper error handling and a fix on the
i2c_master_recv for 32 bits as pointed by John Syne patches.

It is possible to remove all the old interface to use the new one,
however, for keeping the things simple and working this patch maintain
legacy interface.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
Signed-off-by: John Syne <john3...@gmail.com>
---
 drivers/staging/iio/meter/ade7854-i2c.c | 110 
 1 file changed, 41 insertions(+), 69 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index e95147a1bac1..20db8eedb84a 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -65,9 +65,10 @@ static int ade7854_i2c_write_reg(struct device *dev,
return ret < 0 ? ret : 0;
 }
 
-static int ade7854_i2c_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
+static int ade7854_i2c_read_reg(struct device *dev,
+   u16 reg_address,
+   u32 *val,
+   int bytes)
 {
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
@@ -79,95 +80,66 @@ static int ade7854_i2c_read_reg_8(struct device *dev,
 
ret = i2c_master_send(st->i2c, st->tx, 2);
if (ret < 0)
-   goto out;
+   goto unlock;
 
-   ret = i2c_master_recv(st->i2c, st->rx, 1);
+   ret = i2c_master_recv(st->i2c, st->rx, bytes);
if (ret < 0)
-   goto out;
+   goto unlock;
+
+   switch (bytes) {
+   case DATA_SIZE_8_BITS:
+   *val = st->rx[0];
+   break;
+   case DATA_SIZE_16_BITS:
+   *val = (st->rx[0] << 8) | st->rx[1];
+   break;
+   case DATA_SIZE_24_BITS:
+   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
+   break;
+   case DATA_SIZE_32_BITS:
+   *val = (st->rx[0] << 24) | (st->rx[1] << 16) |
+   (st->rx[2] << 8) | st->rx[3];
+   break;
+   default:
+   ret = -EINVAL;
+   goto unlock;
+   }
 
-   *val = st->rx[0];
-out:
+unlock:
mutex_unlock(>buf_lock);
return ret;
 }
 
+static int ade7854_i2c_read_reg_8(struct device *dev,
+ u16 reg_address,
+ u8 *val)
+{
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
+   DATA_SIZE_8_BITS);
+}
+
 static int ade7854_i2c_read_reg_16(struct device *dev,
   u16 reg_address,
   u16 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 2);
-   if (ret < 0)
-   goto out;
-
-   ret = i2c_master_recv(st->i2c, st->rx, 2);
-   if (ret < 0)
-   goto out;
-
-   *val = (st->rx[0] << 8) | st->rx[1];
-out:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
+   DATA_SIZE_16_BITS);
 }
 
 static int ade7854_i2c_read_reg_24(struct device *dev,
   u16 reg_address,
   u32 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 2);
-   if (ret < 0)
-   goto out;
-
-   ret = i2c_master_recv(st->i2c, st->rx, 3);
-   if (ret < 0)
-   goto out;
-
-   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
-out:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
+   DATA_SIZE_24_BITS);
 }
 
 static int ade7854_i2c_read_reg_32(struct device *dev,
   u16 reg_address,
   u32 *va

[PATCH v2 6/8] staging:iio:ade7854: Rework I2C read function

2018-03-16 Thread Rodrigo Siqueira
The read operation for the I2C function has many duplications that can
be generalized into a single function. This patch reworks the read
operation for I2C to centralizes all similar code in a single function.
Part of the rework includes a proper error handling and a fix on the
i2c_master_recv for 32 bits as pointed by John Syne patches.

It is possible to remove all the old interface to use the new one,
however, for keeping the things simple and working this patch maintain
legacy interface.

Signed-off-by: Rodrigo Siqueira 
Signed-off-by: John Syne 
---
 drivers/staging/iio/meter/ade7854-i2c.c | 110 
 1 file changed, 41 insertions(+), 69 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index e95147a1bac1..20db8eedb84a 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -65,9 +65,10 @@ static int ade7854_i2c_write_reg(struct device *dev,
return ret < 0 ? ret : 0;
 }
 
-static int ade7854_i2c_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
+static int ade7854_i2c_read_reg(struct device *dev,
+   u16 reg_address,
+   u32 *val,
+   int bytes)
 {
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
@@ -79,95 +80,66 @@ static int ade7854_i2c_read_reg_8(struct device *dev,
 
ret = i2c_master_send(st->i2c, st->tx, 2);
if (ret < 0)
-   goto out;
+   goto unlock;
 
-   ret = i2c_master_recv(st->i2c, st->rx, 1);
+   ret = i2c_master_recv(st->i2c, st->rx, bytes);
if (ret < 0)
-   goto out;
+   goto unlock;
+
+   switch (bytes) {
+   case DATA_SIZE_8_BITS:
+   *val = st->rx[0];
+   break;
+   case DATA_SIZE_16_BITS:
+   *val = (st->rx[0] << 8) | st->rx[1];
+   break;
+   case DATA_SIZE_24_BITS:
+   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
+   break;
+   case DATA_SIZE_32_BITS:
+   *val = (st->rx[0] << 24) | (st->rx[1] << 16) |
+   (st->rx[2] << 8) | st->rx[3];
+   break;
+   default:
+   ret = -EINVAL;
+   goto unlock;
+   }
 
-   *val = st->rx[0];
-out:
+unlock:
mutex_unlock(>buf_lock);
return ret;
 }
 
+static int ade7854_i2c_read_reg_8(struct device *dev,
+ u16 reg_address,
+ u8 *val)
+{
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
+   DATA_SIZE_8_BITS);
+}
+
 static int ade7854_i2c_read_reg_16(struct device *dev,
   u16 reg_address,
   u16 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 2);
-   if (ret < 0)
-   goto out;
-
-   ret = i2c_master_recv(st->i2c, st->rx, 2);
-   if (ret < 0)
-   goto out;
-
-   *val = (st->rx[0] << 8) | st->rx[1];
-out:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
+   DATA_SIZE_16_BITS);
 }
 
 static int ade7854_i2c_read_reg_24(struct device *dev,
   u16 reg_address,
   u32 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = (reg_address >> 8) & 0xFF;
-   st->tx[1] = reg_address & 0xFF;
-
-   ret = i2c_master_send(st->i2c, st->tx, 2);
-   if (ret < 0)
-   goto out;
-
-   ret = i2c_master_recv(st->i2c, st->rx, 3);
-   if (ret < 0)
-   goto out;
-
-   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
-out:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
+   DATA_SIZE_24_BITS);
 }
 
 static int ade7854_i2c_read_reg_32(struct device *dev,
   u16 reg_address,
   u32 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-  

[PATCH v2 8/8] staging:iio:ade7854: Remove read_reg_* duplications

2018-03-16 Thread Rodrigo Siqueira
The original code had a read function per data size; after updates, all
read functions tasks were centralized in a single function, but the old
signature was kept to maintain the module working without problems. This
patch removes a set of duplications associated with read_reg_*, and
update the areas that calling the old interface by the new one. During
the update for use a single function, some errors handlings were updated
based on the John Syne patches.

Signed-off-by: Rodrigo Siqueira 
Signed-off-by: John Syne 
---
 drivers/staging/iio/meter/ade7854-i2c.c | 37 +--
 drivers/staging/iio/meter/ade7854-spi.c | 39 ++---
 drivers/staging/iio/meter/ade7854.c | 18 +++
 drivers/staging/iio/meter/ade7854.h |  7 +++---
 4 files changed, 15 insertions(+), 86 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-i2c.c 
b/drivers/staging/iio/meter/ade7854-i2c.c
index 20db8eedb84a..162c171a8851 100644
--- a/drivers/staging/iio/meter/ade7854-i2c.c
+++ b/drivers/staging/iio/meter/ade7854-i2c.c
@@ -110,38 +110,6 @@ static int ade7854_i2c_read_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_i2c_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_8_BITS);
-}
-
-static int ade7854_i2c_read_reg_16(struct device *dev,
-  u16 reg_address,
-  u16 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_16_BITS);
-}
-
-static int ade7854_i2c_read_reg_24(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_24_BITS);
-}
-
-static int ade7854_i2c_read_reg_32(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_i2c_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_32_BITS);
-}
-
 static int ade7854_i2c_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
@@ -153,10 +121,7 @@ static int ade7854_i2c_probe(struct i2c_client *client,
return -ENOMEM;
st = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
-   st->read_reg_8 = ade7854_i2c_read_reg_8;
-   st->read_reg_16 = ade7854_i2c_read_reg_16;
-   st->read_reg_24 = ade7854_i2c_read_reg_24;
-   st->read_reg_32 = ade7854_i2c_read_reg_32;
+   st->read_reg = ade7854_i2c_read_reg;
st->write_reg = ade7854_i2c_write_reg;
st->i2c = client;
st->irq = client->irq;
diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index 964d6c6e76d1..66b8a8767a26 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -94,7 +94,7 @@ static int ade7854_spi_read_reg(struct device *dev,
st->tx[2] = reg_address & 0xFF;
 
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
-   if (ret) {
+   if (ret < 0) {
dev_err(>spi->dev, "problem when reading register 0x%02X",
reg_address);
goto unlock;
@@ -120,38 +120,6 @@ static int ade7854_spi_read_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_spi_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_8_BITS);
-}
-
-static int ade7854_spi_read_reg_16(struct device *dev,
-  u16 reg_address,
-  u16 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_16_BITS);
-}
-
-static int ade7854_spi_read_reg_24(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_24_BITS);
-}
-
-static int ade7854_spi_read_reg_32(struct device *dev,
-  u16 reg_address,
-  u32 *val)
-{
-   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
-   DATA_SIZE_32_BITS);
-}
-
 static int ade7854_spi_probe(struct spi_device *spi)
 {
struct ade7854_state *st;
@@ -162,10 +130,7 @@ static int ade7854_spi_probe(struct spi

[PATCH v2 7/8] staging:iio:ade7854: Rework SPI read function

2018-03-16 Thread Rodrigo Siqueira
Rework read SPI function to reduce the code duplication and centralizes
all the task in a single function.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
---
 drivers/staging/iio/meter/ade7854-spi.c | 140 +---
 1 file changed, 37 insertions(+), 103 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index 1eba3044b86f..964d6c6e76d1 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -67,9 +67,10 @@ static int ade7854_spi_write_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_spi_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
+static int ade7854_spi_read_reg(struct device *dev,
+   u16 reg_address,
+   u32 *val,
+   int bytes)
 {
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
@@ -82,7 +83,7 @@ static int ade7854_spi_read_reg_8(struct device *dev,
}, {
.rx_buf = st->rx,
.bits_per_word = 8,
-   .len = 1,
+   .len = bytes,
}
};
 
@@ -94,128 +95,61 @@ static int ade7854_spi_read_reg_8(struct device *dev,
 
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
if (ret) {
-   dev_err(>spi->dev, "problem when reading 8 bit register 
0x%02X",
+   dev_err(>spi->dev, "problem when reading register 0x%02X",
reg_address);
-   goto error_ret;
+   goto unlock;
+   }
+
+   switch (bytes) {
+   case DATA_SIZE_8_BITS:
+   *val = st->rx[0];
+   break;
+   case DATA_SIZE_16_BITS:
+   *val = be16_to_cpup((const __be16 *)st->rx);
+   break;
+   case DATA_SIZE_24_BITS:
+   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
+   break;
+   case DATA_SIZE_32_BITS:
+   *val = be32_to_cpup((const __be32 *)st->rx);
+   break;
}
-   *val = st->rx[0];
 
-error_ret:
+unlock:
mutex_unlock(>buf_lock);
return ret;
 }
 
+static int ade7854_spi_read_reg_8(struct device *dev,
+ u16 reg_address,
+ u8 *val)
+{
+   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
+   DATA_SIZE_8_BITS);
+}
+
 static int ade7854_spi_read_reg_16(struct device *dev,
   u16 reg_address,
   u16 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-   struct spi_transfer xfers[] = {
-   {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 3,
-   }, {
-   .rx_buf = st->rx,
-   .bits_per_word = 8,
-   .len = 2,
-   }
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_READ_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
-   if (ret) {
-   dev_err(>spi->dev, "problem when reading 16 bit register 
0x%02X",
-   reg_address);
-   goto error_ret;
-   }
-   *val = be16_to_cpup((const __be16 *)st->rx);
-
-error_ret:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
+   DATA_SIZE_16_BITS);
 }
 
 static int ade7854_spi_read_reg_24(struct device *dev,
   u16 reg_address,
   u32 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-   struct spi_transfer xfers[] = {
-   {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 3,
-   }, {
-   .rx_buf = st->rx,
-   .bits_per_word = 8,
-   .len = 3,
-   }
-   };
-
-   mutex_lock(>buf_lock);
-
-   st->tx[0] = ADE7854_READ_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers))

[PATCH v2 7/8] staging:iio:ade7854: Rework SPI read function

2018-03-16 Thread Rodrigo Siqueira
Rework read SPI function to reduce the code duplication and centralizes
all the task in a single function.

Signed-off-by: Rodrigo Siqueira 
---
 drivers/staging/iio/meter/ade7854-spi.c | 140 +---
 1 file changed, 37 insertions(+), 103 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index 1eba3044b86f..964d6c6e76d1 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -67,9 +67,10 @@ static int ade7854_spi_write_reg(struct device *dev,
return ret;
 }
 
-static int ade7854_spi_read_reg_8(struct device *dev,
- u16 reg_address,
- u8 *val)
+static int ade7854_spi_read_reg(struct device *dev,
+   u16 reg_address,
+   u32 *val,
+   int bytes)
 {
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ade7854_state *st = iio_priv(indio_dev);
@@ -82,7 +83,7 @@ static int ade7854_spi_read_reg_8(struct device *dev,
}, {
.rx_buf = st->rx,
.bits_per_word = 8,
-   .len = 1,
+   .len = bytes,
}
};
 
@@ -94,128 +95,61 @@ static int ade7854_spi_read_reg_8(struct device *dev,
 
ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
if (ret) {
-   dev_err(>spi->dev, "problem when reading 8 bit register 
0x%02X",
+   dev_err(>spi->dev, "problem when reading register 0x%02X",
reg_address);
-   goto error_ret;
+   goto unlock;
+   }
+
+   switch (bytes) {
+   case DATA_SIZE_8_BITS:
+   *val = st->rx[0];
+   break;
+   case DATA_SIZE_16_BITS:
+   *val = be16_to_cpup((const __be16 *)st->rx);
+   break;
+   case DATA_SIZE_24_BITS:
+   *val = (st->rx[0] << 16) | (st->rx[1] << 8) | st->rx[2];
+   break;
+   case DATA_SIZE_32_BITS:
+   *val = be32_to_cpup((const __be32 *)st->rx);
+   break;
}
-   *val = st->rx[0];
 
-error_ret:
+unlock:
mutex_unlock(>buf_lock);
return ret;
 }
 
+static int ade7854_spi_read_reg_8(struct device *dev,
+ u16 reg_address,
+ u8 *val)
+{
+   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
+   DATA_SIZE_8_BITS);
+}
+
 static int ade7854_spi_read_reg_16(struct device *dev,
   u16 reg_address,
   u16 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-   struct spi_transfer xfers[] = {
-   {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 3,
-   }, {
-   .rx_buf = st->rx,
-   .bits_per_word = 8,
-   .len = 2,
-   }
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_READ_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
-   if (ret) {
-   dev_err(>spi->dev, "problem when reading 16 bit register 
0x%02X",
-   reg_address);
-   goto error_ret;
-   }
-   *val = be16_to_cpup((const __be16 *)st->rx);
-
-error_ret:
-   mutex_unlock(>buf_lock);
-   return ret;
+   return ade7854_spi_read_reg(dev, reg_address, (u32 *)val,
+   DATA_SIZE_16_BITS);
 }
 
 static int ade7854_spi_read_reg_24(struct device *dev,
   u16 reg_address,
   u32 *val)
 {
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   int ret;
-   struct spi_transfer xfers[] = {
-   {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 3,
-   }, {
-   .rx_buf = st->rx,
-   .bits_per_word = 8,
-   .len = 3,
-   }
-   };
-
-   mutex_lock(>buf_lock);
-
-   st->tx[0] = ADE7854_READ_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, xfers, ARRAY_SIZE(xfers));
-   if (ret) {
-   dev_e

[PATCH v2 4/8] staging:iio:ade7854: Rework SPI write function

2018-03-16 Thread Rodrigo Siqueira
The write operation using SPI has a many code duplications (similar to
I2C) and four different interfaces per data size. This patch introduces
a single function that centralizes the main task related to SPI.

Signed-off-by: Rodrigo Siqueira <rodrigosiqueiram...@gmail.com>
---
 drivers/staging/iio/meter/ade7854-spi.c | 108 
 1 file changed, 41 insertions(+), 67 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index 4419b8f06197..f21dc24194fb 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -15,9 +15,10 @@
 #include 
 #include "ade7854.h"
 
-static int ade7854_spi_write_reg_8(struct device *dev,
-  u16 reg_address,
-  u8 val)
+static int ade7854_spi_write_reg(struct device *dev,
+u16 reg_address,
+u32 val,
+int bytes)
 {
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
@@ -32,93 +33,66 @@ static int ade7854_spi_write_reg_8(struct device *dev,
st->tx[0] = ADE7854_WRITE_REG;
st->tx[1] = (reg_address >> 8) & 0xFF;
st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = val & 0xFF;
+   switch (bytes) {
+   case DATA_SIZE_8_BITS:
+   st->tx[3] = val & 0xFF;
+   break;
+   case DATA_SIZE_16_BITS:
+   xfer.len = 5;
+   st->tx[3] = (val >> 8) & 0xFF;
+   st->tx[4] = val & 0xFF;
+   break;
+   case DATA_SIZE_24_BITS:
+   xfer.len = 6;
+   st->tx[3] = (val >> 16) & 0xFF;
+   st->tx[4] = (val >> 8) & 0xFF;
+   st->tx[5] = val & 0xFF;
+   break;
+   case DATA_SIZE_32_BITS:
+   xfer.len = 7;
+   st->tx[3] = (val >> 24) & 0xFF;
+   st->tx[4] = (val >> 16) & 0xFF;
+   st->tx[5] = (val >> 8) & 0xFF;
+   st->tx[6] = val & 0xFF;
+   break;
+   default:
+   ret = -EINVAL;
+   goto unlock;
+   }
 
ret = spi_sync_transfer(st->spi, , 1);
+unlock:
mutex_unlock(>buf_lock);
 
return ret;
 }
 
+static int ade7854_spi_write_reg_8(struct device *dev,
+  u16 reg_address,
+  u8 val)
+{
+   return ade7854_spi_write_reg(dev, reg_address, val, DATA_SIZE_8_BITS);
+}
+
 static int ade7854_spi_write_reg_16(struct device *dev,
u16 reg_address,
u16 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 5,
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_WRITE_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = (val >> 8) & 0xFF;
-   st->tx[4] = val & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, , 1);
-   mutex_unlock(>buf_lock);
-
-   return ret;
+   return ade7854_spi_write_reg(dev, reg_address, val, DATA_SIZE_16_BITS);
 }
 
 static int ade7854_spi_write_reg_24(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 6,
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_WRITE_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = (val >> 16) & 0xFF;
-   st->tx[4] = (val >> 8) & 0xFF;
-   st->tx[5] = val & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, , 1);
-   mutex_unlock(>buf_lock);
-
-   return ret;
+   return ade7854_spi_write_reg(dev, reg_address, val, DATA_SIZE_24_BITS);
 }
 
 static int ade7854_spi_write_reg_32(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   

[PATCH v2 4/8] staging:iio:ade7854: Rework SPI write function

2018-03-16 Thread Rodrigo Siqueira
The write operation using SPI has a many code duplications (similar to
I2C) and four different interfaces per data size. This patch introduces
a single function that centralizes the main task related to SPI.

Signed-off-by: Rodrigo Siqueira 
---
 drivers/staging/iio/meter/ade7854-spi.c | 108 
 1 file changed, 41 insertions(+), 67 deletions(-)

diff --git a/drivers/staging/iio/meter/ade7854-spi.c 
b/drivers/staging/iio/meter/ade7854-spi.c
index 4419b8f06197..f21dc24194fb 100644
--- a/drivers/staging/iio/meter/ade7854-spi.c
+++ b/drivers/staging/iio/meter/ade7854-spi.c
@@ -15,9 +15,10 @@
 #include 
 #include "ade7854.h"
 
-static int ade7854_spi_write_reg_8(struct device *dev,
-  u16 reg_address,
-  u8 val)
+static int ade7854_spi_write_reg(struct device *dev,
+u16 reg_address,
+u32 val,
+int bytes)
 {
int ret;
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
@@ -32,93 +33,66 @@ static int ade7854_spi_write_reg_8(struct device *dev,
st->tx[0] = ADE7854_WRITE_REG;
st->tx[1] = (reg_address >> 8) & 0xFF;
st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = val & 0xFF;
+   switch (bytes) {
+   case DATA_SIZE_8_BITS:
+   st->tx[3] = val & 0xFF;
+   break;
+   case DATA_SIZE_16_BITS:
+   xfer.len = 5;
+   st->tx[3] = (val >> 8) & 0xFF;
+   st->tx[4] = val & 0xFF;
+   break;
+   case DATA_SIZE_24_BITS:
+   xfer.len = 6;
+   st->tx[3] = (val >> 16) & 0xFF;
+   st->tx[4] = (val >> 8) & 0xFF;
+   st->tx[5] = val & 0xFF;
+   break;
+   case DATA_SIZE_32_BITS:
+   xfer.len = 7;
+   st->tx[3] = (val >> 24) & 0xFF;
+   st->tx[4] = (val >> 16) & 0xFF;
+   st->tx[5] = (val >> 8) & 0xFF;
+   st->tx[6] = val & 0xFF;
+   break;
+   default:
+   ret = -EINVAL;
+   goto unlock;
+   }
 
ret = spi_sync_transfer(st->spi, , 1);
+unlock:
mutex_unlock(>buf_lock);
 
return ret;
 }
 
+static int ade7854_spi_write_reg_8(struct device *dev,
+  u16 reg_address,
+  u8 val)
+{
+   return ade7854_spi_write_reg(dev, reg_address, val, DATA_SIZE_8_BITS);
+}
+
 static int ade7854_spi_write_reg_16(struct device *dev,
u16 reg_address,
u16 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 5,
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_WRITE_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = (val >> 8) & 0xFF;
-   st->tx[4] = val & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, , 1);
-   mutex_unlock(>buf_lock);
-
-   return ret;
+   return ade7854_spi_write_reg(dev, reg_address, val, DATA_SIZE_16_BITS);
 }
 
 static int ade7854_spi_write_reg_24(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 6,
-   };
-
-   mutex_lock(>buf_lock);
-   st->tx[0] = ADE7854_WRITE_REG;
-   st->tx[1] = (reg_address >> 8) & 0xFF;
-   st->tx[2] = reg_address & 0xFF;
-   st->tx[3] = (val >> 16) & 0xFF;
-   st->tx[4] = (val >> 8) & 0xFF;
-   st->tx[5] = val & 0xFF;
-
-   ret = spi_sync_transfer(st->spi, , 1);
-   mutex_unlock(>buf_lock);
-
-   return ret;
+   return ade7854_spi_write_reg(dev, reg_address, val, DATA_SIZE_24_BITS);
 }
 
 static int ade7854_spi_write_reg_32(struct device *dev,
u16 reg_address,
u32 val)
 {
-   int ret;
-   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-   struct ade7854_state *st = iio_priv(indio_dev);
-   struct spi_transfer xfer = {
-   .tx_buf = st->tx,
-   .bits_per_word = 8,
-   .len = 7,
-   };
-
-   

  1   2   3   >