Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 3/4] gpio: raspberrypi-exp: Driver for RPi3 GPIO expander via mailbox service
From: Baruch Siach @ 2018-01-14  6:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1313448378.43279.1515839595810@email.1und1.de>

Hi Stefan,

Thanks for reviewing. Please find below a few questions.

On Sat, Jan 13, 2018 at 11:33:15AM +0100, Stefan Wahren wrote: 
> > +	default RASPBERRYPI_FIRMWARE
> > +	depends on OF_GPIO && RASPBERRYPI_FIRMWARE && \
> > +		(ARCH_BCM2835 || COMPILE_TEST)
> 
> Since this is default on RASPBERRYPI_FIRMWARE, we could remove it from the dependencies.

This driver does not work when RASPBERRYPI_FIRMWARE is not enabled. So the 
driver should not be selectable, regardless of its default enable/disable 
state.

> > +	help
> > +	  Turn on GPIO support for the expander on Raspberry Pi 3 boards, using
> > +	  the firmware mailbox to communicate with VideoCore on BCM283x chips.
> > +

[...]

> > --- /dev/null
> > +++ b/drivers/gpio/gpio-raspberrypi-exp.c
> > @@ -0,0 +1,258 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + *  Raspberry Pi 3 expander GPIO driver
> > + *
> > + *  Uses the firmware mailbox service to communicate with the
> > + *  GPIO expander on the VPU.
> > + *
> > + *  Copyright (C) 2017 Raspberry Pi Trading Ltd.
> 
> 2018?

Why? Raspberry Pi Trading Ltd added no code to this driver in 2018.

[...]

> > +static struct platform_driver rpi_exp_gpio_driver = {
> > +	.driver	= {
> > +		.name		= MODULE_NAME,
> > +		.owner		= THIS_MODULE,
> 
> Please drop this, too.

Why? Recent GPIO drivers include this line. I have seen no commits removing 
.owner from GPIO drivers in mainline or in current development tree.

baruch

-- 
     http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -

^ permalink raw reply

* [PATCH v1 4/4] ARM: dts: add pwm node for r40.
From: Hao Zhang @ 2018-01-14  6:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180111124752.2ljspnaclwgz2s62@flea.lan>

2018-01-11 20:47 GMT+08:00 Maxime Ripard <maxime.ripard@free-electrons.com>:
> Hi,
>
> On Thu, Jan 11, 2018 at 07:34:12PM +0800, hao_zhang wrote:
>> This patch add pwm node for r40.
>>
>> Signed-off-by: hao_zhang <hao5781286@gmail.com>
>> ---
>>  arch/arm/boot/dts/sun8i-r40.dtsi | 13 +++++++++++++
>>  1 file changed, 13 insertions(+)
>>
>> diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
>> index 173dcc1..84c963c 100644
>> --- a/arch/arm/boot/dts/sun8i-r40.dtsi
>> +++ b/arch/arm/boot/dts/sun8i-r40.dtsi
>> @@ -295,6 +295,11 @@
>>                               bias-pull-up;
>>                       };
>>
>> +                     pwm_pins: pwm-pins {
>> +                             pins = "PB2", "PB3";
>> +                             function = "pwm";
>> +                     };
>> +
>
> Is it the only combination of pins that is usable?
>
> If so, you can add the pinctrl-0 property directly in the pwm nodes.
>

There are 8 channel pwm of R40/V40/T3, the pins that can be configed to pwm are:
PB2, PB3, PI20, PI21, PB20, PB21, PB9, PB10

PB2, PB3 can be configed on bananapi-m2-ultra and on my T3 board, but
the other pins
is not exist on the board or some pin is confilct with other
functions, so i just add
PB2, PB3. but i think split it is better, just like this :

pwm0_pin: pwm0-pin {
    pins = "PB2";
    function = "pwm";
};

pwm1_pin: pwm1-pin {
    pins = "PB3";
    function = "pwm";
};

the node of pwm2~7 should also be added here?

On sun8i-r40-bananapi-m2-ultra.dts:
because of the special customize board, i think just add pinctrl-0 = <&pwm0_pin>
(PB3 I just use to test pwm channel 1)for bananapi-m2-ultra board is enough.

&pwm {
    pinctrl-names = "default";
    pinctrl-0 = <&pwm0_pin>;
    status = "okay";
};

Thanks ;-)
Hao Zhang


> Thanks!
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com

^ permalink raw reply

* [PATCH v1 3/4] ARM: dts: add pwm pins for r40.
From: Hao Zhang @ 2018-01-14  7:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180111124701.g52kjm3hozn72je5@flea.lan>

2018-01-11 20:47 GMT+08:00 Maxime Ripard <maxime.ripard@free-electrons.com>:
> Hi,
>
> On Thu, Jan 11, 2018 at 07:33:23PM +0800, hao_zhang wrote:
>> This patch add pwm pins for r40.
>>
>> Signed-off-by: hao_zhang <hao5781286@gmail.com>
>
> You should order your patches differently. We try to be as bisectable
> as possible, and if we just apply this patch the DT will not compile
> anymore.
>
> Your patch 4 should come before this one.
>

Do you mean that the order of patch be applied is from the first to
the last in the patch set ?
because you apply the last patch first also break the DT compile...

Thinks :)
Hao Zhang

> Your commit title and log doesn't seem to match the content of the
> patch either.
>
> Thanks!
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com

^ permalink raw reply

* [arm-soc:xlnx/soc 3/3] collect2: error: ld returned 1 exit status
From: kbuild test robot @ 2018-01-14  9:09 UTC (permalink / raw)
  To: linux-arm-kernel

tree:   https://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git xlnx/soc
head:   cee8113a295acfc4cd25728d7c3d44e6bc3bbff9
commit: cee8113a295acfc4cd25728d7c3d44e6bc3bbff9 [3/3] soc: xilinx: xlnx_vcu: Add Xilinx ZYNQMP VCU logicoreIP init driver
config: um-allyesconfig (attached as .config)
compiler: gcc-7 (Debian 7.2.0-12) 7.2.1 20171025
reproduce:
        git checkout cee8113a295acfc4cd25728d7c3d44e6bc3bbff9
        # save the attached .config to linux build tree
        make ARCH=um 

All errors (new ones prefixed by >>):

   arch/um/drivers/vde.o: In function `vde_open_real':
   (.text+0x951): warning: Using 'getgrnam' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   (.text+0x79c): warning: Using 'getpwuid' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   (.text+0xab5): warning: Using 'getaddrinfo' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   arch/um/drivers/pcap.o: In function `pcap_nametoaddr':
   (.text+0xdee5): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   arch/um/drivers/pcap.o: In function `pcap_nametonetaddr':
   (.text+0xdf85): warning: Using 'getnetbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   arch/um/drivers/pcap.o: In function `pcap_nametoproto':
   (.text+0xe1a5): warning: Using 'getprotobyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   arch/um/drivers/pcap.o: In function `pcap_nametoport':
   (.text+0xdfd7): warning: Using 'getservbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
   drivers/soc/xilinx/xlnx_vcu.o: In function `xvcu_probe':
   xlnx_vcu.c:(.text+0x116): undefined reference to `devm_ioremap_nocache'
   xlnx_vcu.c:(.text+0x1ae): undefined reference to `devm_ioremap_nocache'
>> collect2: error: ld returned 1 exit status

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 19866 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180114/7a8275cf/attachment-0001.gz>

^ permalink raw reply

* [PATCH v2 3/4] gpio: raspberrypi-exp: Driver for RPi3 GPIO expander via mailbox service
From: Stefan Wahren @ 2018-01-14 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180114060840.ychhndc7ukulrbpe@sapphire.tkos.co.il>

Hi Baruch,

> Baruch Siach <baruch@tkos.co.il> hat am 14. Januar 2018 um 07:08 geschrieben:
> 
> 
> Hi Stefan,
> 
> Thanks for reviewing. Please find below a few questions.
> 
> On Sat, Jan 13, 2018 at 11:33:15AM +0100, Stefan Wahren wrote: 
> > > +	default RASPBERRYPI_FIRMWARE
> > > +	depends on OF_GPIO && RASPBERRYPI_FIRMWARE && \
> > > +		(ARCH_BCM2835 || COMPILE_TEST)
> > 
> > Since this is default on RASPBERRYPI_FIRMWARE, we could remove it from the dependencies.
> 
> This driver does not work when RASPBERRYPI_FIRMWARE is not enabled. So the 
> driver should not be selectable, regardless of its default enable/disable 
> state.

I know. My idea was to increase build test coverage. Nevertheless the more common style would be:

depends on ARCH_BCM2835 || COMPILE_TEST
depends on OF_GPIO && RASPBERRYPI_FIRMWARE

> 
> > > +	help
> > > +	  Turn on GPIO support for the expander on Raspberry Pi 3 boards, using
> > > +	  the firmware mailbox to communicate with VideoCore on BCM283x chips.
> > > +
> 
> [...]
> 
> > > --- /dev/null
> > > +++ b/drivers/gpio/gpio-raspberrypi-exp.c
> > > @@ -0,0 +1,258 @@
> > > +// SPDX-License-Identifier: GPL-2.0+
> > > +/*
> > > + *  Raspberry Pi 3 expander GPIO driver
> > > + *
> > > + *  Uses the firmware mailbox service to communicate with the
> > > + *  GPIO expander on the VPU.
> > > + *
> > > + *  Copyright (C) 2017 Raspberry Pi Trading Ltd.
> > 
> > 2018?
> 
> Why? Raspberry Pi Trading Ltd added no code to this driver in 2018.

Sure. Don't you want to add your copyright?

> 
> [...]
> 
> > > +static struct platform_driver rpi_exp_gpio_driver = {
> > > +	.driver	= {
> > > +		.name		= MODULE_NAME,
> > > +		.owner		= THIS_MODULE,
> > 
> > Please drop this, too.
> 
> Why? Recent GPIO drivers include this line.

I don't know which driver your are referring to, but platform driver doesn't need this.

Please grep for all platform_driver in gpio and you won't see any setting of ownership. I'm not speaking about the gpiochip.

Btw my replies to #2 and #4 got blocked, should i try to resend it to you.

Thanks
Stefan

> I have seen no commits removing 
> .owner from GPIO drivers in mainline or in current development tree.
> 
> baruch
> 
> -- 
>      http://baruch.siach.name/blog/                  ~. .~   Tk Open Systems
> =}------------------------------------------------ooO--U--Ooo------------{=
>    - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 12/14] iio: adc: at91-sama5d2_adc: support for position and pressure channels
From: Jonathan Cameron @ 2018-01-14 10:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108141252.GC2425@rfolt0960.corp.atmel.com>

On Mon, 8 Jan 2018 15:12:52 +0100
Ludovic Desroches <ludovic.desroches@microchip.com> wrote:

> Hi Jonathan, Eugen,
> 
> On Sat, Jan 06, 2018 at 03:05:37PM +0000, Jonathan Cameron wrote:
> > On Thu, 4 Jan 2018 17:17:54 +0200
> > Eugen Hristev <eugen.hristev@microchip.com> wrote:
> >   
> > > On 29.12.2017 19:02, Jonathan Cameron wrote:  
> > > > On Fri, 22 Dec 2017 17:07:19 +0200
> > > > Eugen Hristev <eugen.hristev@microchip.com> wrote:
> > > >     
> > > >> The ADC IP supports position and pressure measurements for a touchpad
> > > >> connected on channels 0,1,2,3 for a 4-wire touchscreen with pressure
> > > >> measurement support.
> > > >> Using the inkern API, a driver can request a trigger and read the
> > > >> channel values from the ADC.
> > > >> The implementation provides a trigger named "touch" which can be
> > > >> connected to a consumer driver.
> > > >> Once a driver connects and attaches a pollfunc to this trigger, the
> > > >> configure trigger callback is called, and then the ADC driver will
> > > >> initialize pad measurement.
> > > >> First step is to enable touchscreen 4wire support and enable
> > > >> pen detect IRQ.
> > > >> Once a pen is detected, a periodic trigger is setup to trigger every
> > > >> 2 ms (e.g.) and sample the resistive touchscreen values. The trigger poll
> > > >> is called, and the consumer driver is then woke up, and it can read the
> > > >> respective channels for the values : X, and Y for position and pressure
> > > >> channel.
> > > >> Because only one trigger can be active in hardware in the same time,
> > > >> while touching the pad, the ADC will block any attempt to use the
> > > >> triggered buffer. Same, conversions using the software trigger are also
> > > >> impossible (since the periodic trigger is setup).
> > > >> If some driver wants to attach while the trigger is in use, it will
> > > >> also fail.
> > > >> Once the pen is not detected anymore, the trigger is free for use (hardware
> > > >> or software trigger, with or without DMA).
> > > >> Channels 0,1,2 and 3 are unavailable if a touchscreen is enabled.
> > > >>
> > > >> Some parts of this patch are based on initial original work by
> > > >> Mohamed Jamsheeth Hajanajubudeen and Bandaru Venkateswara Swamy
> > > >>    
> > > > OK, so comments inline.
> > > > 
> > > > What I'm missing currently though is an explanation of why the slightly
> > > > more standard arrangement of using a callback buffer doesn't work here.
> > > > The only addition I think you need to do that is to allow a consumer to
> > > > request a particular trigger.  I also think some of the other provisions
> > > > could be handled using standard features and slightly reducing the flexibility.
> > > > I don't know for example if it's useful to allow other channels to be
> > > > read when touch is not in progress or not.
> > > > 
> > > > So restrictions:
> > > > 
> > > > 1. Touch screen channels can only be read when touch is enabled.
> > > >   - use the available_scan_masks to control this. Or the callback that lets
> > > >     you do the same dynamically.
> > > > 2. You need to push these channels to your consumer driver.
> > > >   - register a callback buffer rather than jumping through the hoops to
> > > >     insert your own pollfunc.  That will call a function in your
> > > >     consumer, providing the data from the 3 channels directly.
> > > > 3. You need to make sure it is using the right driver.  For that you
> > > >     will I think need a new interface.
> > > > 
> > > > Various other comments inline. I may well be missing something as this is
> > > > a fair bit of complex code to read - if so then next version should have
> > > > a clear cover letter describing why this more standard approach can't be
> > > > used.    
> > > 
> > > Hello Jonathan and thanks for the review of my patch series,
> > > 
> > > before starting and working over the required modifications and 
> > > suggestions that you sent me, I want to be a little more explicit about 
> > > the design of my implementation.
> > > Hope this will clarify some things, and maybe I can as well understand 
> > > better what you have in mind to support this feature set.
> > > 
> > > Why have I picked a pollfunction: We discussed a while back on the 
> > > mailing list that you do not have an inkern mechanism to expose the 
> > > triggers to other drivers, and that it may be a good idea to have it for 
> > > such kind of actually multi function device, instead of having a MFD 
> > > driver, an ADC driver, and an Input driver, all sharing the same 
> > > register map, the same IRQ , etc, with some kind of synchronization to 
> > > avoid stepping on each other for the hardware resource.  
> > 
> > No disagreement with that principle.
> >   
> > > So I considered to expose the trigger by attaching and detaching 
> > > pollfunctions to it. Which is the main thing what we use a trigger for.  
> > 
> > Hmm. It's definitely one approach. But we do already have other drivers
> > where the trigger is controlled by a consumer and to my mind that
> > is a cleaner approach as it doesn't short cut the equivalent of
> > doing it from userspace.
> > 
> > drivers/iio/potentiostat/lmp91000.c does something similar though
> > for a rather different use. You need your consumer interface
> > to get the handle to the trigger in this case
> > (the lmp91000 is actually providing the trigger rather than
> > consuming it).
> > 
> >   
> > > 
> > > So, what I had in mind, was to create a consumer driver that will 
> > > request triggers from the IIO device just like other drivers request 
> > > channels (part which is already done in IIO).
> > > In order to do this I had to somehow wake up the consumer driver when 
> > > new data was available from the touchscreen. So, having the IRQ only in 
> > > the ADC device, and then on Pen detect and No pen detect just start or 
> > > stop the periodic trigger, which needs to be polled. The magic part is 
> > > that the consumer driver has a poll function already attached to this 
> > > trigger, so the poll function is just called every time we have new 
> > > data. The poll function is attached as an irq handler, and then we can 
> > > reuse all the read_raw data by using a scheduled work from the consumer 
> > > driver, to read the channels.  
> > 
> > If you had done this via a callback buffer the only difference is that
> > the pollfunc would have been a standard one pulling the relevant channels
> > and passing them on down to the buffer interface which could then decide
> > what to do with them.
> >   
> > > To do this, the ADC registers a special trigger named "touch trigger" 
> > > which is never enabled by the ADC driver. Instead, when a pollfunc is 
> > > attached to it, the attach function will also configure it with enabled 
> > > state.  
> > 
> > Whilst it might not make sense to enable it in the touch screen driver
> > I'm not sure there is strictly any reason to prevent it being so used.
> >   
> > > In the ADC, this means to start the touchscreen functionality. If 
> > > the touch is requested, it will standby and wait for pen detect IRQ.
> > > Once we have pen detect, we can use a periodic trigger to sample the 
> > > touch data, and poll the "touch" trigger. The consumer driver will wake 
> > > up and schedule a work , that will use the standard read raw interface 
> > > (inkern) that will read three virtual channels (position + pressure). 
> > > They are not actual hardware channels, as the touch information is being 
> > > received on channels 0,1,2,3, but reading these virtual channels will 
> > > read from different registers inside the ADC IP ( x position, y 
> > > position, pressure), do some computations on the data, and feed the 
> > > consumer with the values , hiding the behind the scenes hardware 
> > > specific calculations.  
> > 
> > I wouldn't worry about whether they are real channels or not. This
> > is really similar to a differential ADC (some of those do the differential
> > digitally). Light sensors often have a number of 'real' channels used
> > to derive (via hideous non linear calculations) the illuminance as
> > it's hard to build a light sensor with the same sensitivity as the human
> > eye.  We have worse 'non real' channels as well such as activity channels
> > on some the accelerometers that report if it thinks you are walking /
> > running etc.
> >    
> > > After trigger is polled , the ADC will resume normal functionality, and 
> > > the consumer driver will continue to sleep.  
> > 
> > So this is where I'm unsure.  Do you actually have a usecase where it
> > makes the sense to read from the ADC only when there is no touch?  Any
> > system doing that has an obvious denial of service attack - touch the
> > screen.
> >   
> 
> You're right. We have an issue in this case due to the hardware. Using
> touchscreen has side effects on other channels. We can use only one
> trigger for all the channels. The situation would have been better with
> a trigger dedicated to the touchscreen.
> 
> At the moment, we have not really stated about the exclusive use or not
> of the touchscreen. We suppose we can get some customers wanting to use
> both touchscreen and ADC. Eugen tried to deal with this case but, as you
> noticed, it can lead to DoS.

It's a restriction people aren't going to expect unfortunately...

> 
> > > We need to have a periodic trigger to sample the data because the actual 
> > > analog to digital conversion inside the IP block needs to be triggered. 
> > > The touchscreen data measurements cannot happen in hardware without 
> > > being triggered. If I try with a hrtimer to get a periodic IRQ to just 
> > > read the data, it will never be ready. The datasheet states that the 
> > > touchscreen measurements "will be attached to the conversion sequence". 
> > > So the periodic trigger is forcing a conversion sequence. This could be 
> > > done with a software trigger as well, but why the hassle to start it 
> > > every 2 milliseconds (or other time interval), if we can do it by 
> > > periodic trigger ?  
> > 
> > Ah, one reason here would be to allow separate consumers to use the
> > device. In that case you'd run with a periodic trigger all the time
> > and have two buffers attached, the buffer_cb that is feeding your
> > touchscreen and another buffer to deal with the other channels
> > (presumably the standard one an IIO device has when using buffered
> > interfaces).  
> 
> The issue is that we are sharing the periodic trigger so we have to use
> the same period for both usage.

Whilst a somewhat irritating restriction, it's probably not disastrous for
most ADC uses.

Jonathan
> 
> Regards
> 
> Ludovic
> 
> > 
> > The buffer demux would ensure the data from the right channels
> > ends up in the right place.  It makes it look to the buffer
> > consumer like it is the only thing using / controlling the data
> > flow.
> >   
> > > Once we get the No pen IRQ, we stop the periodic trigger and it can be 
> > > used in another purpose (software or external as of now in the driver, 
> > > in the future we can add PWM trigger and Timer trigger)  
> > 
> > This case isn't really useful though as any other use is denied
> > access when touch occurs.
> > 
> > I'll summarise what I think would work for this below.
> >   
> > > 
> > > In short, the ADC in Sama5D2 also supports touchscreen, and in 
> > > touchscreen mode , 4 of the channels are being used for this purpose. 
> > > This however, doesn't stop the ADC to use the other channels . The 
> > > hardware has 12 total single channels and they can be paired to have 6 
> > > more differential channels. The only thing that is blocked is the 
> > > trigger, but only if the pen is touching (when we start the periodic 
> > > trigger to sample the touchscreen). If the pen is not touching, an 
> > > external trigger or software trigger can be used without any issues (so 
> > > why limit the functionality, if this is available from hardware ?). 
> > > Because of the reason I discussed above (touchscreen sequence must be 
> > > triggered), we cannot use another trigger in the same time.
> > > 
> > > 
> > > I see your idea with the callback buffer and it's worth exploring. 
> > > Mainly this series was to actually show you what I had in mind about 
> > > supporting the resistive touchscreen, and to give you some actually 
> > > working code/patch, so we can discuss based on real implementation, not 
> > > just suppositions.  
> > 
> > That side of things is fine.
> >   
> > > 
> > > You are right in many of the other comments that you said, and I will 
> > > come up with a v2 to this series. For now, I need to know if this is a 
> > > good or right direction in which I am going, or I should try to change 
> > > all the mechanism to callback buffer ? Or maybe I am totally in a bad 
> > > direction ?
> > > The requirements are that the consumer driver needs to be somehow woke 
> > > up for every new touch data available, and report to the input 
> > > subsystem. As it was done before, the at91 old driver, just creates and 
> > > registers an input device by itself, and then reports the position and 
> > > touches. I was thinking that with this trigger consumer implementation, 
> > > things can be better in terms of subsystem separation and support.
> > > 
> > > Thanks again and let me know of your thoughts,
> > > 
> > > Eugen  
> > 
> > So a couple of things come to mind on how I'd structure this.
> > So what we have (very briefly)
> > 
> > No touch screen case:
> > * Generic ADC using all sorts of different triggers
> > 
> > Touch screen only case:
> > * Interrupt to indicate pen on / off
> > * A need to do a periodic trigger of the device but only
> > useful when touch is in progress.
> > 
> > Touch screen and other users:
> > * Interrupt to indicate pen on / off
> > * Periodic trigger needed for touchscreen when touch in progress.
> > * Do not have denial of service on other channels.
> > 
> > First two cases are easy enough by having a magic trigger, third
> > case is harder.
> > If we have the touchscreen then I would drop support for direct access to
> > to ADC channels whilst it's in use (so no sysfs - or emulate it if you
> > really want it by stashing results from scans done when touch is in
> > progress).
> > 
> > Have your touch screen channels just as normal additional channels,
> > but only via the buffered interface (no _RAW attribute).
> > If someone sets up to read them via buffered interface with
> > a different trigger I think they'll get values - whether they
> > are right is dependent (if I understand correctly) on whether
> > there is a touch in progress.  So no harm done and it'll make
> > the logic simpler.
> > 
> > The moment touch is opened and acquires the IIO channels
> > fix the trigger (may need new interface) to the periodic one
> > that you were enabling and disabling on touch.
> > Things get dicey if there is an existing user so you may
> > have to do it on driver probe rather than open of the input
> > device if we effectively want touch to have the highest
> > priority use of the ADC.
> > 
> > If other channels are enabled for buffered mode then note
> > this in the driver and have the periodic trigger on all the
> > time (to ensure they keep getting read)  This will pass
> > garbage to your touch screen driver, but it'll remove it due
> > to the pressure value being too low so no harm there.
> > 
> > Normal path will work for non touch channels (and in theory
> > the touch ones if they are turned on) via IIO buffer
> > interface.  It'll be restricted in form due to the needs of
> > the touch driver, but better than nothing and should cover
> > most usecases.
> > 
> > Now the interrupt on / off on touch bit becomes an optimization
> > in the case of only the buffer_cb being attached.
> > 
> > I think that fits cleanly in the current IIO framework and
> > looks more similar to our existing provider consumer approaches.
> > 
> > Still needs the hooks to get hold of the trigger though so
> > as to be able to tell the ADC which one to use. So rather
> > than being a trigger consumer interface, it's more of a trigger
> > configuration interface..  Exact term doesn't matter though.
> > 
> > Jonathan
> >   
> > > 
> > > 
> > > 
> > > [...]
> > > --
> > > To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> > > the body of a message to majordomo at vger.kernel.org
> > > More majordomo info at  http://vger.kernel.org/majordomo-info.html  
> >   
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH 1/3] arm: spear600: Add missing interrupt-parent of rtc
From: Linus Walleij @ 2018-01-14 11:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180112020711.6gp2pnsxxjzelidq@localhost>

On Fri, Jan 12, 2018 at 3:07 AM, Olof Johansson <olof@lixom.net> wrote:
> On Thu, Jan 11, 2018 at 11:28:51AM +0530, Viresh Kumar wrote:
>> The interrupt-parent of rtc was missing, add it.
>>
>> Fixes: 8113ba917dfa ("ARM: SPEAr: DT: Update device nodes")
>> Cc: stable at vger.kernel.org # v3.8+
>> Reported-by: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
>
> Applied to next/dt. Is stable really needed on this? It's been broken since
> pretty much forever, and nobody has complained... :)

The SPEAr architecture is widely used (in modified variants) by
a large industrial automation company, 20+ years of support cycle.

However I think they have a forked both kernel and hardware, so they
will not notice any time soon, and when they eventually upgrade they
can simply pick the latest I guess.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH 1/3] arm: spear600: Add missing interrupt-parent of rtc
From: Linus Walleij @ 2018-01-14 11:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAK8P3a3MZX-ZsxX9h1-8kVQhn9hqY=c8L1+=e3uTfjEjBCYuPg@mail.gmail.com>

On Fri, Jan 12, 2018 at 11:05 PM, Arnd Bergmann <arnd@arndb.de> wrote:

>      arch/arm/boot/dts/ste-nomadik-nhk15.dtb: Warning
> (interrupts_property): Missing interrupt-parent for
> /amba/clcd at 10120000
>      arch/arm/boot/dts/ste-nomadik-s8815.dtb: Warning
> (interrupts_property): Missing interrupt-parent for
> /amba/clcd at 10120000
(...)
> I hope Linus Walleij can find out what the right interrupt-parent
> should be on the
> nomadik machine, that is otherwise the last remaining warning.

OK I will look into it.

> Apparently the
> clcd driver doesn't actually need its interrupt, so we could decide to
> just comment
> out that line if we don't know which controller it's connected to.

I am migrating it to the new DRM driver which uses the IRQ to
sync screen output to avoid tearing so it would be unfortunate.

I will look into it.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH] IIO: ADC: stm32-dfsdm: avoid unused-variable warning
From: Jonathan Cameron @ 2018-01-14 12:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <838ace12-2722-33aa-0ed8-2e8e7494b2ae@st.com>

On Thu, 11 Jan 2018 18:38:49 +0100
Arnaud Pouliquen <arnaud.pouliquen@st.com> wrote:

> On 01/11/2018 03:27 PM, Robin Murphy wrote:
> > On 11/01/18 10:34, Arnd Bergmann wrote:  
> >> Building with CONFIG_OF disabled produces a compiler warning:
> >>
> >> drivers/iio/adc/stm32-dfsdm-core.c: In function 'stm32_dfsdm_probe':
> >> drivers/iio/adc/stm32-dfsdm-core.c:245:22: error: unused variable
> >> 'pnode' [-Werror=unused-variable]
> >>
> >> This removes the variable and open-codes it in the only place
> >> it gets used to avoid that warning.
> >>
> >> Fixes: bed73904e76f ("IIO: ADC: add stm32 DFSDM core support")
> >> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> >> ---
> >> ? drivers/iio/adc/stm32-dfsdm-core.c | 3 +--
> >> ? 1 file changed, 1 insertion(+), 2 deletions(-)
> >>
> >> diff --git a/drivers/iio/adc/stm32-dfsdm-core.c
> >> b/drivers/iio/adc/stm32-dfsdm-core.c
> >> index 72427414db7f..6cd655f8239b 100644
> >> --- a/drivers/iio/adc/stm32-dfsdm-core.c
> >> +++ b/drivers/iio/adc/stm32-dfsdm-core.c
> >> @@ -242,7 +242,6 @@ MODULE_DEVICE_TABLE(of, stm32_dfsdm_of_match);
> >> ? static int stm32_dfsdm_probe(struct platform_device *pdev)
> >> ? {
> >> ????? struct dfsdm_priv *priv;
> >> -??? struct device_node *pnode = pdev->dev.of_node;
> >> ????? const struct of_device_id *of_id;
> >> ????? const struct stm32_dfsdm_dev_data *dev_data;
> >> ????? struct stm32_dfsdm *dfsdm;
> >> @@ -254,7 +253,7 @@ static int stm32_dfsdm_probe(struct
> >> platform_device *pdev)
> >> ? ????? priv->pdev = pdev;
> >> ? -??? of_id = of_match_node(stm32_dfsdm_of_match, pnode);
> >> +??? of_id = of_match_node(stm32_dfsdm_of_match, pdev->dev.of_node);
> >> ????? if (!of_id->data) {
> >> ????????? dev_err(&pdev->dev, "Data associated to device is missing\n");
> >> ????????? return -EINVAL;  
> > 
> > FWIW, it looks like this whole lot could be cleaned up by using
> > of_device_get_match_data().
> >   
> Right, and test of the return now seems to me an overprotection as data
> structure is defined in the driver...
> 
> Same optimization could be applied to stm32_dfsdm_adc_probe function.
> 
> Here is the patch I tested:

This looks like a good solution to me.

Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

(given this should probably go on Mark's immutable branch).

Jonathan

> 
> ---
>  drivers/iio/adc/stm32-dfsdm-adc.c  | 9 +--------
>  drivers/iio/adc/stm32-dfsdm-core.c | 9 +--------
>  2 files changed, 2 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c
> b/drivers/iio/adc/stm32-dfsdm-adc.c
> index b03ca3f..01836c9 100644
> --- a/drivers/iio/adc/stm32-dfsdm-adc.c
> +++ b/drivers/iio/adc/stm32-dfsdm-adc.c
> @@ -1087,18 +1087,11 @@ static int stm32_dfsdm_adc_probe(struct
> platform_device *pdev)
>  	struct device_node *np = dev->of_node;
>  	const struct stm32_dfsdm_dev_data *dev_data;
>  	struct iio_dev *iio;
> -	const struct of_device_id *of_id;
>  	char *name;
>  	int ret, irq, val;
> 
> -	of_id = of_match_node(stm32_dfsdm_adc_match, np);
> -	if (!of_id->data) {
> -		dev_err(&pdev->dev, "Data associated to device is missing\n");
> -		return -EINVAL;
> -	}
> -
> -	dev_data = (const struct stm32_dfsdm_dev_data *)of_id->data;
> 
> +	dev_data = of_device_get_match_data(dev);
>  	iio = devm_iio_device_alloc(dev, sizeof(*adc));
>  	if (IS_ERR(iio)) {
>  		dev_err(dev, "%s: Failed to allocate IIO\n", __func__);
> diff --git a/drivers/iio/adc/stm32-dfsdm-core.c
> b/drivers/iio/adc/stm32-dfsdm-core.c
> index 7242741..6290332 100644
> --- a/drivers/iio/adc/stm32-dfsdm-core.c
> +++ b/drivers/iio/adc/stm32-dfsdm-core.c
> @@ -242,8 +242,6 @@ MODULE_DEVICE_TABLE(of, stm32_dfsdm_of_match);
>  static int stm32_dfsdm_probe(struct platform_device *pdev)
>  {
>  	struct dfsdm_priv *priv;
> -	struct device_node *pnode = pdev->dev.of_node;
> -	const struct of_device_id *of_id;
>  	const struct stm32_dfsdm_dev_data *dev_data;
>  	struct stm32_dfsdm *dfsdm;
>  	int ret;
> @@ -254,13 +252,8 @@ static int stm32_dfsdm_probe(struct platform_device
> *pdev)
> 
>  	priv->pdev = pdev;
> 
> -	of_id = of_match_node(stm32_dfsdm_of_match, pnode);
> -	if (!of_id->data) {
> -		dev_err(&pdev->dev, "Data associated to device is missing\n");
> -		return -EINVAL;
> -	}
> +	dev_data = of_device_get_match_data(&pdev->dev);
> 
> -	dev_data = (const struct stm32_dfsdm_dev_data *)of_id->data;
>  	dfsdm = &priv->dfsdm;
>  	dfsdm->fl_list = devm_kcalloc(&pdev->dev, dev_data->num_filters,
>  				      sizeof(*dfsdm->fl_list), GFP_KERNEL);

^ permalink raw reply

* [PATCH v6 11/16] firmware: arm_sdei: Add support for CPU and system power states
From: Lorenzo Pieralisi @ 2018-01-14 12:20 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180113120031.5m6eykwzqnioyb33@armageddon.cambridge.arm.com>

On Sat, Jan 13, 2018 at 12:00:31PM +0000, Catalin Marinas wrote:
> On Mon, Jan 08, 2018 at 05:22:26PM +0000, Lorenzo Pieralisi wrote:
> > On Mon, Jan 08, 2018 at 03:38:13PM +0000, James Morse wrote:
> > 
> > [...]
> > 
> > > +/* When entering idle, mask/unmask events for this cpu */
> > 
> > Just mentioning (since I know you know), this notifier is called also
> > through syscore_ops so it is not just idle (CPUidle or Suspend-to-idle).
> > 
> > > +static int sdei_pm_notifier(struct notifier_block *nb, unsigned long action,
> > > +			    void *data)
> > > +{
> > > +	int rv;
> > > +
> > > +	switch (action) {
> > > +	case CPU_PM_ENTER:
> > > +		rv = sdei_mask_local_cpu();
> > > +		break;
> > > +	case CPU_PM_EXIT:
> > > +		rv = sdei_unmask_local_cpu();
> > 
> > You should handle CPU_PM_ENTER_FAILED here for correctness,
> > in case the notifier chain fails.
> 
> So, just to confirm, the CPU_PM_ENTER_FAILED case goes together with
> CPU_PM_EXIT so that we unmask the SDE again for the CPU.

Yes, that's correct (I do not think that's a problem with current
mainline but that ought to be handled correctly anyway).

Lorenzo

^ permalink raw reply

* [PATCH 1/3] arm: spear600: Add missing interrupt-parent of rtc
From: Alexandre Belloni @ 2018-01-14 13:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACRpkdYtzWewTWrtWTaPWspHzRY6Y7MBNfm1wmy6yvLD_J8hFg@mail.gmail.com>

Hi,

On 14/01/2018 at 12:17:23 +0100, Linus Walleij wrote:
> On Fri, Jan 12, 2018 at 3:07 AM, Olof Johansson <olof@lixom.net> wrote:
> > On Thu, Jan 11, 2018 at 11:28:51AM +0530, Viresh Kumar wrote:
> >> The interrupt-parent of rtc was missing, add it.
> >>
> >> Fixes: 8113ba917dfa ("ARM: SPEAr: DT: Update device nodes")
> >> Cc: stable at vger.kernel.org # v3.8+
> >> Reported-by: Arnd Bergmann <arnd@arndb.de>
> >> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> >
> > Applied to next/dt. Is stable really needed on this? It's been broken since
> > pretty much forever, and nobody has complained... :)
> 
> The SPEAr architecture is widely used (in modified variants) by
> a large industrial automation company, 20+ years of support cycle.
> 
> However I think they have a forked both kernel and hardware, so they
> will not notice any time soon, and when they eventually upgrade they
> can simply pick the latest I guess.
> 

We have a customer using mainline v4.14 on their Spear600 based
products.

I guess the reason why nobody complained is simply because nobody is
using the SoC RTC ;)


-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

^ permalink raw reply

* [RESEND PATCH 0/2] selftests: ftrace: Fix multiple-kprobe testcase
From: Masami Hiramatsu @ 2018-01-14 13:49 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

These patches are fixing a bug and improve testcase to
ensure adding 256 kprobe events for test.

I've just updated to the latest kselftest/master branch.

Thank you,

---

Masami Hiramatsu (2):
      [BUGFIX] selftest: ftrace: Fix to pick text symbols for kprobes
      selftest: ftrace: Fix to add 256 kprobe events correctly


 .../ftrace/test.d/kprobe/multiple_kprobes.tc       |   21 +++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

--
Masami Hiramatsu (Linaro) <mhiramat@kernel.org>

^ permalink raw reply

* [RESEND PATCH 1/2] [BUGFIX] selftest: ftrace: Fix to pick text symbols for kprobes
From: Masami Hiramatsu @ 2018-01-14 13:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <151593777761.23875.10360397710751679883.stgit@devbox>

Fix to pick text symbols for multiple kprobe testcase.
kallsyms shows text symbols with " t " or " T " but
current testcase picks all symbols including "t",
so it picks data symbols if it includes 't' (e.g. "str").

This fixes it to find symbol lines with " t " or " T "
(including spaces).

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Reported-by: Russell King <linux@armlinux.org.uk>
---
 .../ftrace/test.d/kprobe/multiple_kprobes.tc       |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
index bb16cf91f1b5..e297bd7a2e79 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
@@ -12,8 +12,8 @@ case `uname -m` in
   *) OFFS=0;;
 esac
 
-echo "Setup up to 256 kprobes"
-grep t /proc/kallsyms | cut -f3 -d" " | grep -v .*\\..* | \
+echo "Setup up kprobes on first 256 text symbols"
+grep -i " t " /proc/kallsyms | cut -f3 -d" " | grep -v .*\\..* | \
 head -n 256 | while read i; do echo p ${i}+${OFFS} ; done > kprobe_events ||:
 
 echo 1 > events/kprobes/enable

^ permalink raw reply related

* [RESEND PATCH 2/2] selftest: ftrace: Fix to add 256 kprobe events correctly
From: Masami Hiramatsu @ 2018-01-14 13:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <151593777761.23875.10360397710751679883.stgit@devbox>

Current multiple-kprobe testcase only tries to add
kprobe events on first 256 text symbols. However
kprobes fails to probe on some text symbols (like
blacklisted symbols). Thus in the worst case,
the test can not add any kprobe events.

To avoid that, continue to try adding kprobe events
until 256 events. Also it confirms the number of
registered kprobe events.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
---
 .../ftrace/test.d/kprobe/multiple_kprobes.tc       |   19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
index e297bd7a2e79..ce361b9d62cf 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
@@ -12,9 +12,24 @@ case `uname -m` in
   *) OFFS=0;;
 esac
 
-echo "Setup up kprobes on first 256 text symbols"
+if [ -d events/kprobes ]; then
+  echo 0 > events/kprobes/enable
+  echo > kprobe_events
+fi
+
+N=0
+echo "Setup up kprobes on first available 256 text symbols"
 grep -i " t " /proc/kallsyms | cut -f3 -d" " | grep -v .*\\..* | \
-head -n 256 | while read i; do echo p ${i}+${OFFS} ; done > kprobe_events ||:
+while read i; do
+  echo p ${i}+${OFFS} >> kprobe_events && N=$((N+1)) ||:
+  test $N -eq 256 && break
+done
+
+L=`wc -l kprobe_events`
+if [ $L -ne $N ]; then
+  echo "The number of kprobes events ($L) is not $N"
+  exit_fail
+fi
 
 echo 1 > events/kprobes/enable
 echo 0 > events/kprobes/enable

^ permalink raw reply related

* [PATCH v2 00/16] add support for AXP813 ADC and battery power supply
From: Jonathan Cameron @ 2018-01-14 13:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.1e46d70f7931be8154b450a2fcdf066450a1aa6f.1515486346.git-series.quentin.schulz@free-electrons.com>

On Tue,  9 Jan 2018 10:33:31 +0100
Quentin Schulz <quentin.schulz@free-electrons.com> wrote:

> The AXP813 PMIC is relatively close to the already supported AXP20X and
> AXP22X. It provides three different power outputs: battery, AC and USB, and
> measures a few different things: temperature, power supply status, current
> current and voltage supplied, maximum current limit, battery capacity, min
> and max voltage limits.
> 
> One of its two GPIOs can be used as an ADC.
> 
> There are a few differences with AXP20X/AXP22X PMICs though:
>   - a different constant charge current formula,
>   - battery temperature, GPIO0 and battery voltages are the only voltages
>   measurable,
>   - all data are stored on 12 bits (AXP20X/AXP22X had one type of data that
>   was stored on 13 bits),
>   - different scales and offsets,
>   - a different ADC rate formula and register,
> 
> This patch series adds support for the PMIC's ADC and battery power supply
> in the existing drivers.
> 
> Make the axp20x MFD automatically probe the ADC driver, add the battery
> power supply node in axp81x node and enable it for the TBS A711 since it
> has a soldered battery.
> 
> v2:
>   - introduce data structure instead of ID for variant specific code in
>   battery driver,
>   - add DT binding for ADC driver,
>   - make mfd probe the ADC driver via DT as well so that its IIO channels
>   can be consumed by other drivers via DT mapping,
Other than that minor comment on V1 about churn risk in the dt binding
that Rob pointed out hadn't been addressed (I'd completely forgotten about it :)

I'm happy once the points others have raised have been addressed.

My assumption is that this will ultimately go through the IIO tree so
I'll be needing a good selection of Acks to take it.

The dts bits should be fine to go via normal paths though once the
driver is in place.

If it's going via mfd which might make sense in a 'logical' way rather
than amount of code, let me know and I'll give tags for v3 iio parts.

Jonathan

> 
> Thanks,
> Quentin
> 
> Quentin Schulz (16):
>   iio: adc: axp20x_adc: put ADC rate setting in a per-variant function
>   dt-bindings: iio: adc: add binding for X-Powers AXP PMICs ADC
>   iio: adc: axp20x_adc: make it possible to probe from DT
>   ARM: dtsi: axp209: add node for ADC
>   ARM: dtsi: axp22x: add node for ADC
>   mfd: axp20x: make AXP209/22x cells probe their ADC via DT
>   dt-bindings: iio: adc: axp20x_adc: add AXP813 variant
>   iio: adc: axp20x_adc: add support for AXP813 ADC
>   ARM: dtsi: axp81x: add node for ADC
>   mfd: axp20x: probe axp20x_adc driver for AXP813
>   power: supply: axp20x_battery: use data structure instead of ID for variant specific code
>   dt-bindings: power: supply: axp20x: add AXP813 battery DT binding
>   power: supply: axp20x_battery: add support for AXP813
>   mfd: axp20x: add battery power supply cell for AXP813
>   ARM: dtsi: axp81x: add battery power supply subnode
>   ARM: dtsi: sun8i: a711: enable battery power supply subnode
> 
>  Documentation/devicetree/bindings/iio/adc/axp20x_adc.txt          |  48 ++++++++++++++++++++++-
>  Documentation/devicetree/bindings/power/supply/axp20x_battery.txt |   8 ++--
>  arch/arm/boot/dts/axp209.dtsi                                     |   5 ++-
>  arch/arm/boot/dts/axp22x.dtsi                                     |   5 ++-
>  arch/arm/boot/dts/axp81x.dtsi                                     |  10 +++++-
>  arch/arm/boot/dts/sun8i-a83t-tbs-a711.dts                         |   4 ++-
>  drivers/iio/adc/axp20x_adc.c                                      | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
>  drivers/mfd/axp20x.c                                              |  13 +++++-
>  drivers/power/supply/axp20x_battery.c                             | 134 ++++++++++++++++++++++++++++++++++++++++++++++--------------
>  include/linux/mfd/axp20x.h                                        |   2 +-
>  10 files changed, 345 insertions(+), 44 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/axp20x_adc.txt
> 
> base-commit: 895c0dde398510a5b5ded60e5064c11b94bd30ca

^ permalink raw reply

* [PATCH] mtd: mtk-nor: modify functions' name more generally
From: Cyrille Pitchen @ 2018-01-14 15:23 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513561655-10570-2-git-send-email-guochun.mao@mediatek.com>

Le 18/12/2017 ? 02:47, Guochun Mao a ?crit?:
> Since more and more Mediatek's SoC can use this driver to
> control spi-nor flash, functions' name with "mt8173_" is
> no longer properly. Replacing "mt8173_" with "mtk_" will
> be more accurate to describe these functions' usable scope.
> 
> Signed-off-by: Guochun Mao <guochun.mao@mediatek.com>

Applied to the spi-nor/next branch of linux-mtd

Thanks!

> ---
>  drivers/mtd/spi-nor/mtk-quadspi.c |  240 ++++++++++++++++++-------------------
>  1 file changed, 120 insertions(+), 120 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/mtk-quadspi.c
> index abe455c..5442993 100644
> --- a/drivers/mtd/spi-nor/mtk-quadspi.c
> +++ b/drivers/mtd/spi-nor/mtk-quadspi.c
> @@ -110,7 +110,7 @@
>  #define MTK_NOR_PRG_REG(n)		(MTK_NOR_PRGDATA0_REG + 4 * (n))
>  #define MTK_NOR_SHREG(n)		(MTK_NOR_SHREG0_REG + 4 * (n))
>  
> -struct mt8173_nor {
> +struct mtk_nor {
>  	struct spi_nor nor;
>  	struct device *dev;
>  	void __iomem *base;	/* nor flash base address */
> @@ -118,48 +118,48 @@ struct mt8173_nor {
>  	struct clk *nor_clk;
>  };
>  
> -static void mt8173_nor_set_read_mode(struct mt8173_nor *mt8173_nor)
> +static void mtk_nor_set_read_mode(struct mtk_nor *mtk_nor)
>  {
> -	struct spi_nor *nor = &mt8173_nor->nor;
> +	struct spi_nor *nor = &mtk_nor->nor;
>  
>  	switch (nor->read_proto) {
>  	case SNOR_PROTO_1_1_1:
> -		writeb(nor->read_opcode, mt8173_nor->base +
> +		writeb(nor->read_opcode, mtk_nor->base +
>  		       MTK_NOR_PRGDATA3_REG);
> -		writeb(MTK_NOR_FAST_READ, mt8173_nor->base +
> +		writeb(MTK_NOR_FAST_READ, mtk_nor->base +
>  		       MTK_NOR_CFG1_REG);
>  		break;
>  	case SNOR_PROTO_1_1_2:
> -		writeb(nor->read_opcode, mt8173_nor->base +
> +		writeb(nor->read_opcode, mtk_nor->base +
>  		       MTK_NOR_PRGDATA3_REG);
> -		writeb(MTK_NOR_DUAL_READ_EN, mt8173_nor->base +
> +		writeb(MTK_NOR_DUAL_READ_EN, mtk_nor->base +
>  		       MTK_NOR_DUAL_REG);
>  		break;
>  	case SNOR_PROTO_1_1_4:
> -		writeb(nor->read_opcode, mt8173_nor->base +
> +		writeb(nor->read_opcode, mtk_nor->base +
>  		       MTK_NOR_PRGDATA4_REG);
> -		writeb(MTK_NOR_QUAD_READ_EN, mt8173_nor->base +
> +		writeb(MTK_NOR_QUAD_READ_EN, mtk_nor->base +
>  		       MTK_NOR_DUAL_REG);
>  		break;
>  	default:
> -		writeb(MTK_NOR_DUAL_DISABLE, mt8173_nor->base +
> +		writeb(MTK_NOR_DUAL_DISABLE, mtk_nor->base +
>  		       MTK_NOR_DUAL_REG);
>  		break;
>  	}
>  }
>  
> -static int mt8173_nor_execute_cmd(struct mt8173_nor *mt8173_nor, u8 cmdval)
> +static int mtk_nor_execute_cmd(struct mtk_nor *mtk_nor, u8 cmdval)
>  {
>  	int reg;
>  	u8 val = cmdval & 0x1f;
>  
> -	writeb(cmdval, mt8173_nor->base + MTK_NOR_CMD_REG);
> -	return readl_poll_timeout(mt8173_nor->base + MTK_NOR_CMD_REG, reg,
> +	writeb(cmdval, mtk_nor->base + MTK_NOR_CMD_REG);
> +	return readl_poll_timeout(mtk_nor->base + MTK_NOR_CMD_REG, reg,
>  				  !(reg & val), 100, 10000);
>  }
>  
> -static int mt8173_nor_do_tx_rx(struct mt8173_nor *mt8173_nor, u8 op,
> -			       u8 *tx, int txlen, u8 *rx, int rxlen)
> +static int mtk_nor_do_tx_rx(struct mtk_nor *mtk_nor, u8 op,
> +			    u8 *tx, int txlen, u8 *rx, int rxlen)
>  {
>  	int len = 1 + txlen + rxlen;
>  	int i, ret, idx;
> @@ -167,26 +167,26 @@ static int mt8173_nor_do_tx_rx(struct mt8173_nor *mt8173_nor, u8 op,
>  	if (len > MTK_NOR_MAX_SHIFT)
>  		return -EINVAL;
>  
> -	writeb(len * 8, mt8173_nor->base + MTK_NOR_CNT_REG);
> +	writeb(len * 8, mtk_nor->base + MTK_NOR_CNT_REG);
>  
>  	/* start at PRGDATA5, go down to PRGDATA0 */
>  	idx = MTK_NOR_MAX_RX_TX_SHIFT - 1;
>  
>  	/* opcode */
> -	writeb(op, mt8173_nor->base + MTK_NOR_PRG_REG(idx));
> +	writeb(op, mtk_nor->base + MTK_NOR_PRG_REG(idx));
>  	idx--;
>  
>  	/* program TX data */
>  	for (i = 0; i < txlen; i++, idx--)
> -		writeb(tx[i], mt8173_nor->base + MTK_NOR_PRG_REG(idx));
> +		writeb(tx[i], mtk_nor->base + MTK_NOR_PRG_REG(idx));
>  
>  	/* clear out rest of TX registers */
>  	while (idx >= 0) {
> -		writeb(0, mt8173_nor->base + MTK_NOR_PRG_REG(idx));
> +		writeb(0, mtk_nor->base + MTK_NOR_PRG_REG(idx));
>  		idx--;
>  	}
>  
> -	ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PRG_CMD);
> +	ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_PRG_CMD);
>  	if (ret)
>  		return ret;
>  
> @@ -195,20 +195,20 @@ static int mt8173_nor_do_tx_rx(struct mt8173_nor *mt8173_nor, u8 op,
>  
>  	/* read out RX data */
>  	for (i = 0; i < rxlen; i++, idx--)
> -		rx[i] = readb(mt8173_nor->base + MTK_NOR_SHREG(idx));
> +		rx[i] = readb(mtk_nor->base + MTK_NOR_SHREG(idx));
>  
>  	return 0;
>  }
>  
>  /* Do a WRSR (Write Status Register) command */
> -static int mt8173_nor_wr_sr(struct mt8173_nor *mt8173_nor, u8 sr)
> +static int mtk_nor_wr_sr(struct mtk_nor *mtk_nor, u8 sr)
>  {
> -	writeb(sr, mt8173_nor->base + MTK_NOR_PRGDATA5_REG);
> -	writeb(8, mt8173_nor->base + MTK_NOR_CNT_REG);
> -	return mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_WRSR_CMD);
> +	writeb(sr, mtk_nor->base + MTK_NOR_PRGDATA5_REG);
> +	writeb(8, mtk_nor->base + MTK_NOR_CNT_REG);
> +	return mtk_nor_execute_cmd(mtk_nor, MTK_NOR_WRSR_CMD);
>  }
>  
> -static int mt8173_nor_write_buffer_enable(struct mt8173_nor *mt8173_nor)
> +static int mtk_nor_write_buffer_enable(struct mtk_nor *mtk_nor)
>  {
>  	u8 reg;
>  
> @@ -216,27 +216,27 @@ static int mt8173_nor_write_buffer_enable(struct mt8173_nor *mt8173_nor)
>  	 * 0: pre-fetch buffer use for read
>  	 * 1: pre-fetch buffer use for page program
>  	 */
> -	writel(MTK_NOR_WR_BUF_ENABLE, mt8173_nor->base + MTK_NOR_CFG2_REG);
> -	return readb_poll_timeout(mt8173_nor->base + MTK_NOR_CFG2_REG, reg,
> +	writel(MTK_NOR_WR_BUF_ENABLE, mtk_nor->base + MTK_NOR_CFG2_REG);
> +	return readb_poll_timeout(mtk_nor->base + MTK_NOR_CFG2_REG, reg,
>  				  0x01 == (reg & 0x01), 100, 10000);
>  }
>  
> -static int mt8173_nor_write_buffer_disable(struct mt8173_nor *mt8173_nor)
> +static int mtk_nor_write_buffer_disable(struct mtk_nor *mtk_nor)
>  {
>  	u8 reg;
>  
> -	writel(MTK_NOR_WR_BUF_DISABLE, mt8173_nor->base + MTK_NOR_CFG2_REG);
> -	return readb_poll_timeout(mt8173_nor->base + MTK_NOR_CFG2_REG, reg,
> +	writel(MTK_NOR_WR_BUF_DISABLE, mtk_nor->base + MTK_NOR_CFG2_REG);
> +	return readb_poll_timeout(mtk_nor->base + MTK_NOR_CFG2_REG, reg,
>  				  MTK_NOR_WR_BUF_DISABLE == (reg & 0x1), 100,
>  				  10000);
>  }
>  
> -static void mt8173_nor_set_addr_width(struct mt8173_nor *mt8173_nor)
> +static void mtk_nor_set_addr_width(struct mtk_nor *mtk_nor)
>  {
>  	u8 val;
> -	struct spi_nor *nor = &mt8173_nor->nor;
> +	struct spi_nor *nor = &mtk_nor->nor;
>  
> -	val = readb(mt8173_nor->base + MTK_NOR_DUAL_REG);
> +	val = readb(mtk_nor->base + MTK_NOR_DUAL_REG);
>  
>  	switch (nor->addr_width) {
>  	case 3:
> @@ -246,115 +246,115 @@ static void mt8173_nor_set_addr_width(struct mt8173_nor *mt8173_nor)
>  		val |= MTK_NOR_4B_ADDR_EN;
>  		break;
>  	default:
> -		dev_warn(mt8173_nor->dev, "Unexpected address width %u.\n",
> +		dev_warn(mtk_nor->dev, "Unexpected address width %u.\n",
>  			 nor->addr_width);
>  		break;
>  	}
>  
> -	writeb(val, mt8173_nor->base + MTK_NOR_DUAL_REG);
> +	writeb(val, mtk_nor->base + MTK_NOR_DUAL_REG);
>  }
>  
> -static void mt8173_nor_set_addr(struct mt8173_nor *mt8173_nor, u32 addr)
> +static void mtk_nor_set_addr(struct mtk_nor *mtk_nor, u32 addr)
>  {
>  	int i;
>  
> -	mt8173_nor_set_addr_width(mt8173_nor);
> +	mtk_nor_set_addr_width(mtk_nor);
>  
>  	for (i = 0; i < 3; i++) {
> -		writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR0_REG + i * 4);
> +		writeb(addr & 0xff, mtk_nor->base + MTK_NOR_RADR0_REG + i * 4);
>  		addr >>= 8;
>  	}
>  	/* Last register is non-contiguous */
> -	writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR3_REG);
> +	writeb(addr & 0xff, mtk_nor->base + MTK_NOR_RADR3_REG);
>  }
>  
> -static ssize_t mt8173_nor_read(struct spi_nor *nor, loff_t from, size_t length,
> -			       u_char *buffer)
> +static ssize_t mtk_nor_read(struct spi_nor *nor, loff_t from, size_t length,
> +			    u_char *buffer)
>  {
>  	int i, ret;
>  	int addr = (int)from;
>  	u8 *buf = (u8 *)buffer;
> -	struct mt8173_nor *mt8173_nor = nor->priv;
> +	struct mtk_nor *mtk_nor = nor->priv;
>  
>  	/* set mode for fast read mode ,dual mode or quad mode */
> -	mt8173_nor_set_read_mode(mt8173_nor);
> -	mt8173_nor_set_addr(mt8173_nor, addr);
> +	mtk_nor_set_read_mode(mtk_nor);
> +	mtk_nor_set_addr(mtk_nor, addr);
>  
>  	for (i = 0; i < length; i++) {
> -		ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PIO_READ_CMD);
> +		ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_PIO_READ_CMD);
>  		if (ret < 0)
>  			return ret;
> -		buf[i] = readb(mt8173_nor->base + MTK_NOR_RDATA_REG);
> +		buf[i] = readb(mtk_nor->base + MTK_NOR_RDATA_REG);
>  	}
>  	return length;
>  }
>  
> -static int mt8173_nor_write_single_byte(struct mt8173_nor *mt8173_nor,
> -					int addr, int length, u8 *data)
> +static int mtk_nor_write_single_byte(struct mtk_nor *mtk_nor,
> +				     int addr, int length, u8 *data)
>  {
>  	int i, ret;
>  
> -	mt8173_nor_set_addr(mt8173_nor, addr);
> +	mtk_nor_set_addr(mtk_nor, addr);
>  
>  	for (i = 0; i < length; i++) {
> -		writeb(*data++, mt8173_nor->base + MTK_NOR_WDATA_REG);
> -		ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_PIO_WR_CMD);
> +		writeb(*data++, mtk_nor->base + MTK_NOR_WDATA_REG);
> +		ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_PIO_WR_CMD);
>  		if (ret < 0)
>  			return ret;
>  	}
>  	return 0;
>  }
>  
> -static int mt8173_nor_write_buffer(struct mt8173_nor *mt8173_nor, int addr,
> -				   const u8 *buf)
> +static int mtk_nor_write_buffer(struct mtk_nor *mtk_nor, int addr,
> +				const u8 *buf)
>  {
>  	int i, bufidx, data;
>  
> -	mt8173_nor_set_addr(mt8173_nor, addr);
> +	mtk_nor_set_addr(mtk_nor, addr);
>  
>  	bufidx = 0;
>  	for (i = 0; i < SFLASH_WRBUF_SIZE; i += 4) {
>  		data = buf[bufidx + 3]<<24 | buf[bufidx + 2]<<16 |
>  		       buf[bufidx + 1]<<8 | buf[bufidx];
>  		bufidx += 4;
> -		writel(data, mt8173_nor->base + MTK_NOR_PP_DATA_REG);
> +		writel(data, mtk_nor->base + MTK_NOR_PP_DATA_REG);
>  	}
> -	return mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_WR_CMD);
> +	return mtk_nor_execute_cmd(mtk_nor, MTK_NOR_WR_CMD);
>  }
>  
> -static ssize_t mt8173_nor_write(struct spi_nor *nor, loff_t to, size_t len,
> -				const u_char *buf)
> +static ssize_t mtk_nor_write(struct spi_nor *nor, loff_t to, size_t len,
> +			     const u_char *buf)
>  {
>  	int ret;
> -	struct mt8173_nor *mt8173_nor = nor->priv;
> +	struct mtk_nor *mtk_nor = nor->priv;
>  	size_t i;
>  
> -	ret = mt8173_nor_write_buffer_enable(mt8173_nor);
> +	ret = mtk_nor_write_buffer_enable(mtk_nor);
>  	if (ret < 0) {
> -		dev_warn(mt8173_nor->dev, "write buffer enable failed!\n");
> +		dev_warn(mtk_nor->dev, "write buffer enable failed!\n");
>  		return ret;
>  	}
>  
>  	for (i = 0; i + SFLASH_WRBUF_SIZE <= len; i += SFLASH_WRBUF_SIZE) {
> -		ret = mt8173_nor_write_buffer(mt8173_nor, to, buf);
> +		ret = mtk_nor_write_buffer(mtk_nor, to, buf);
>  		if (ret < 0) {
> -			dev_err(mt8173_nor->dev, "write buffer failed!\n");
> +			dev_err(mtk_nor->dev, "write buffer failed!\n");
>  			return ret;
>  		}
>  		to += SFLASH_WRBUF_SIZE;
>  		buf += SFLASH_WRBUF_SIZE;
>  	}
> -	ret = mt8173_nor_write_buffer_disable(mt8173_nor);
> +	ret = mtk_nor_write_buffer_disable(mtk_nor);
>  	if (ret < 0) {
> -		dev_warn(mt8173_nor->dev, "write buffer disable failed!\n");
> +		dev_warn(mtk_nor->dev, "write buffer disable failed!\n");
>  		return ret;
>  	}
>  
>  	if (i < len) {
> -		ret = mt8173_nor_write_single_byte(mt8173_nor, to,
> -						   (int)(len - i), (u8 *)buf);
> +		ret = mtk_nor_write_single_byte(mtk_nor, to,
> +						(int)(len - i), (u8 *)buf);
>  		if (ret < 0) {
> -			dev_err(mt8173_nor->dev, "write single byte failed!\n");
> +			dev_err(mtk_nor->dev, "write single byte failed!\n");
>  			return ret;
>  		}
>  	}
> @@ -362,72 +362,72 @@ static ssize_t mt8173_nor_write(struct spi_nor *nor, loff_t to, size_t len,
>  	return len;
>  }
>  
> -static int mt8173_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
> +static int mtk_nor_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
>  {
>  	int ret;
> -	struct mt8173_nor *mt8173_nor = nor->priv;
> +	struct mtk_nor *mtk_nor = nor->priv;
>  
>  	switch (opcode) {
>  	case SPINOR_OP_RDSR:
> -		ret = mt8173_nor_execute_cmd(mt8173_nor, MTK_NOR_RDSR_CMD);
> +		ret = mtk_nor_execute_cmd(mtk_nor, MTK_NOR_RDSR_CMD);
>  		if (ret < 0)
>  			return ret;
>  		if (len == 1)
> -			*buf = readb(mt8173_nor->base + MTK_NOR_RDSR_REG);
> +			*buf = readb(mtk_nor->base + MTK_NOR_RDSR_REG);
>  		else
> -			dev_err(mt8173_nor->dev, "len should be 1 for read status!\n");
> +			dev_err(mtk_nor->dev, "len should be 1 for read status!\n");
>  		break;
>  	default:
> -		ret = mt8173_nor_do_tx_rx(mt8173_nor, opcode, NULL, 0, buf, len);
> +		ret = mtk_nor_do_tx_rx(mtk_nor, opcode, NULL, 0, buf, len);
>  		break;
>  	}
>  	return ret;
>  }
>  
> -static int mt8173_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
> -				int len)
> +static int mtk_nor_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
> +			     int len)
>  {
>  	int ret;
> -	struct mt8173_nor *mt8173_nor = nor->priv;
> +	struct mtk_nor *mtk_nor = nor->priv;
>  
>  	switch (opcode) {
>  	case SPINOR_OP_WRSR:
>  		/* We only handle 1 byte */
> -		ret = mt8173_nor_wr_sr(mt8173_nor, *buf);
> +		ret = mtk_nor_wr_sr(mtk_nor, *buf);
>  		break;
>  	default:
> -		ret = mt8173_nor_do_tx_rx(mt8173_nor, opcode, buf, len, NULL, 0);
> +		ret = mtk_nor_do_tx_rx(mtk_nor, opcode, buf, len, NULL, 0);
>  		if (ret)
> -			dev_warn(mt8173_nor->dev, "write reg failure!\n");
> +			dev_warn(mtk_nor->dev, "write reg failure!\n");
>  		break;
>  	}
>  	return ret;
>  }
>  
> -static void mt8173_nor_disable_clk(struct mt8173_nor *mt8173_nor)
> +static void mtk_nor_disable_clk(struct mtk_nor *mtk_nor)
>  {
> -	clk_disable_unprepare(mt8173_nor->spi_clk);
> -	clk_disable_unprepare(mt8173_nor->nor_clk);
> +	clk_disable_unprepare(mtk_nor->spi_clk);
> +	clk_disable_unprepare(mtk_nor->nor_clk);
>  }
>  
> -static int mt8173_nor_enable_clk(struct mt8173_nor *mt8173_nor)
> +static int mtk_nor_enable_clk(struct mtk_nor *mtk_nor)
>  {
>  	int ret;
>  
> -	ret = clk_prepare_enable(mt8173_nor->spi_clk);
> +	ret = clk_prepare_enable(mtk_nor->spi_clk);
>  	if (ret)
>  		return ret;
>  
> -	ret = clk_prepare_enable(mt8173_nor->nor_clk);
> +	ret = clk_prepare_enable(mtk_nor->nor_clk);
>  	if (ret) {
> -		clk_disable_unprepare(mt8173_nor->spi_clk);
> +		clk_disable_unprepare(mtk_nor->spi_clk);
>  		return ret;
>  	}
>  
>  	return 0;
>  }
>  
> -static int mtk_nor_init(struct mt8173_nor *mt8173_nor,
> +static int mtk_nor_init(struct mtk_nor *mtk_nor,
>  			struct device_node *flash_node)
>  {
>  	const struct spi_nor_hwcaps hwcaps = {
> @@ -439,18 +439,18 @@ static int mtk_nor_init(struct mt8173_nor *mt8173_nor,
>  	struct spi_nor *nor;
>  
>  	/* initialize controller to accept commands */
> -	writel(MTK_NOR_ENABLE_SF_CMD, mt8173_nor->base + MTK_NOR_WRPROT_REG);
> +	writel(MTK_NOR_ENABLE_SF_CMD, mtk_nor->base + MTK_NOR_WRPROT_REG);
>  
> -	nor = &mt8173_nor->nor;
> -	nor->dev = mt8173_nor->dev;
> -	nor->priv = mt8173_nor;
> +	nor = &mtk_nor->nor;
> +	nor->dev = mtk_nor->dev;
> +	nor->priv = mtk_nor;
>  	spi_nor_set_flash_node(nor, flash_node);
>  
>  	/* fill the hooks to spi nor */
> -	nor->read = mt8173_nor_read;
> -	nor->read_reg = mt8173_nor_read_reg;
> -	nor->write = mt8173_nor_write;
> -	nor->write_reg = mt8173_nor_write_reg;
> +	nor->read = mtk_nor_read;
> +	nor->read_reg = mtk_nor_read_reg;
> +	nor->write = mtk_nor_write;
> +	nor->write_reg = mtk_nor_write_reg;
>  	nor->mtd.name = "mtk_nor";
>  	/* initialized with NULL */
>  	ret = spi_nor_scan(nor, NULL, &hwcaps);
> @@ -465,34 +465,34 @@ static int mtk_nor_drv_probe(struct platform_device *pdev)
>  	struct device_node *flash_np;
>  	struct resource *res;
>  	int ret;
> -	struct mt8173_nor *mt8173_nor;
> +	struct mtk_nor *mtk_nor;
>  
>  	if (!pdev->dev.of_node) {
>  		dev_err(&pdev->dev, "No DT found\n");
>  		return -EINVAL;
>  	}
>  
> -	mt8173_nor = devm_kzalloc(&pdev->dev, sizeof(*mt8173_nor), GFP_KERNEL);
> -	if (!mt8173_nor)
> +	mtk_nor = devm_kzalloc(&pdev->dev, sizeof(*mtk_nor), GFP_KERNEL);
> +	if (!mtk_nor)
>  		return -ENOMEM;
> -	platform_set_drvdata(pdev, mt8173_nor);
> +	platform_set_drvdata(pdev, mtk_nor);
>  
>  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	mt8173_nor->base = devm_ioremap_resource(&pdev->dev, res);
> -	if (IS_ERR(mt8173_nor->base))
> -		return PTR_ERR(mt8173_nor->base);
> +	mtk_nor->base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(mtk_nor->base))
> +		return PTR_ERR(mtk_nor->base);
>  
> -	mt8173_nor->spi_clk = devm_clk_get(&pdev->dev, "spi");
> -	if (IS_ERR(mt8173_nor->spi_clk))
> -		return PTR_ERR(mt8173_nor->spi_clk);
> +	mtk_nor->spi_clk = devm_clk_get(&pdev->dev, "spi");
> +	if (IS_ERR(mtk_nor->spi_clk))
> +		return PTR_ERR(mtk_nor->spi_clk);
>  
> -	mt8173_nor->nor_clk = devm_clk_get(&pdev->dev, "sf");
> -	if (IS_ERR(mt8173_nor->nor_clk))
> -		return PTR_ERR(mt8173_nor->nor_clk);
> +	mtk_nor->nor_clk = devm_clk_get(&pdev->dev, "sf");
> +	if (IS_ERR(mtk_nor->nor_clk))
> +		return PTR_ERR(mtk_nor->nor_clk);
>  
> -	mt8173_nor->dev = &pdev->dev;
> +	mtk_nor->dev = &pdev->dev;
>  
> -	ret = mt8173_nor_enable_clk(mt8173_nor);
> +	ret = mtk_nor_enable_clk(mtk_nor);
>  	if (ret)
>  		return ret;
>  
> @@ -503,20 +503,20 @@ static int mtk_nor_drv_probe(struct platform_device *pdev)
>  		ret = -ENODEV;
>  		goto nor_free;
>  	}
> -	ret = mtk_nor_init(mt8173_nor, flash_np);
> +	ret = mtk_nor_init(mtk_nor, flash_np);
>  
>  nor_free:
>  	if (ret)
> -		mt8173_nor_disable_clk(mt8173_nor);
> +		mtk_nor_disable_clk(mtk_nor);
>  
>  	return ret;
>  }
>  
>  static int mtk_nor_drv_remove(struct platform_device *pdev)
>  {
> -	struct mt8173_nor *mt8173_nor = platform_get_drvdata(pdev);
> +	struct mtk_nor *mtk_nor = platform_get_drvdata(pdev);
>  
> -	mt8173_nor_disable_clk(mt8173_nor);
> +	mtk_nor_disable_clk(mtk_nor);
>  
>  	return 0;
>  }
> @@ -524,18 +524,18 @@ static int mtk_nor_drv_remove(struct platform_device *pdev)
>  #ifdef CONFIG_PM_SLEEP
>  static int mtk_nor_suspend(struct device *dev)
>  {
> -	struct mt8173_nor *mt8173_nor = dev_get_drvdata(dev);
> +	struct mtk_nor *mtk_nor = dev_get_drvdata(dev);
>  
> -	mt8173_nor_disable_clk(mt8173_nor);
> +	mtk_nor_disable_clk(mtk_nor);
>  
>  	return 0;
>  }
>  
>  static int mtk_nor_resume(struct device *dev)
>  {
> -	struct mt8173_nor *mt8173_nor = dev_get_drvdata(dev);
> +	struct mtk_nor *mtk_nor = dev_get_drvdata(dev);
>  
> -	return mt8173_nor_enable_clk(mt8173_nor);
> +	return mtk_nor_enable_clk(mtk_nor);
>  }
>  
>  static const struct dev_pm_ops mtk_nor_dev_pm_ops = {
> 

^ permalink raw reply

* [PATCH v2 0/3] sha3 fixes and new implementation for arm64
From: Ard Biesheuvel @ 2018-01-14 16:41 UTC (permalink / raw)
  To: linux-arm-kernel

Add an implementation of SHA3 to arm64 using the new special instructions,
and another one using scalar instructions but coded in assembler (#2)

In preparation of that, fix a bug in the SHA3 (#1) and add some new test
vectors to get better test coverage (#3).

v2: Drop generic SHA3 as a fallback for the arm64 module. Instead, provide
    a special arm64 version to use as a fallback when the instructions are
    not available or when executing in a context that does not allow SIMD

    Drop patches that simplify the generic SHA3 and make it reusable by
    other modules.

Ard Biesheuvel (3):
  crypto/generic: sha3 - fixes for alignment and big endian operation
  crypto/arm64: sha3 - new scalar + v8.2 Crypto Extensions
    implementation
  crypto/testmgr: sha3 - add new testcases

 arch/arm64/crypto/Kconfig           |   4 +
 arch/arm64/crypto/Makefile          |   3 +
 arch/arm64/crypto/sha3-arm64-core.S | 512 ++++++++++++++++++
 arch/arm64/crypto/sha3-arm64-glue.c | 192 +++++++
 crypto/sha3_generic.c               |   5 +-
 crypto/testmgr.h                    | 550 ++++++++++++++++++++
 6 files changed, 1264 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/crypto/sha3-arm64-core.S
 create mode 100644 arch/arm64/crypto/sha3-arm64-glue.c

-- 
2.11.0

^ permalink raw reply

* [PATCH v2 1/3] crypto/generic: sha3 - fixes for alignment and big endian operation
From: Ard Biesheuvel @ 2018-01-14 16:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180114164118.18330-1-ard.biesheuvel@linaro.org>

Ensure that the input is byte swabbed before injecting it into the
SHA3 transform. Use the get_unaligned() accessor for this so that
we don't perform unaligned access inadvertently on architectures
that do not support that.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 crypto/sha3_generic.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/crypto/sha3_generic.c b/crypto/sha3_generic.c
index 7e8ed96236ce..a68be626017c 100644
--- a/crypto/sha3_generic.c
+++ b/crypto/sha3_generic.c
@@ -18,6 +18,7 @@
 #include <linux/types.h>
 #include <crypto/sha3.h>
 #include <asm/byteorder.h>
+#include <asm/unaligned.h>
 
 #define KECCAK_ROUNDS 24
 
@@ -149,7 +150,7 @@ static int sha3_update(struct shash_desc *desc, const u8 *data,
 			unsigned int i;
 
 			for (i = 0; i < sctx->rsizw; i++)
-				sctx->st[i] ^= ((u64 *) src)[i];
+				sctx->st[i] ^= get_unaligned_le64(src + 8 * i);
 			keccakf(sctx->st);
 
 			done += sctx->rsiz;
@@ -174,7 +175,7 @@ static int sha3_final(struct shash_desc *desc, u8 *out)
 	sctx->buf[sctx->rsiz - 1] |= 0x80;
 
 	for (i = 0; i < sctx->rsizw; i++)
-		sctx->st[i] ^= ((u64 *) sctx->buf)[i];
+		sctx->st[i] ^= get_unaligned_le64(sctx->buf + 8 * i);
 
 	keccakf(sctx->st);
 
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 2/3] crypto/arm64: sha3 - new scalar + v8.2 Crypto Extensions implementation
From: Ard Biesheuvel @ 2018-01-14 16:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180114164118.18330-1-ard.biesheuvel@linaro.org>

Implement the various flavours of SHA3 using scalar instructions, and
using the new optional EOR3/RAX1/XAR/BCAX instructions introduced by
ARMv8.2.

Note that the scalar asm version is *much* faster than the C based
generic implementation: the SHA3 state matrix already occupies 25
registers, leaving very little to perform the computation, and the
compiler appears to give up and spill the state to memory.

  Performance comparison of SHA3-256 (cycles per byte)

                        generic     scalar arm64     speedup
  Cortex-A53 @ 1GHz    224.4 cpb      12.4 cpb        18.1x
  Cortex-A57 @ 2GHz    101.6 cpb      11.8 cpb         8.6x

The ARMv8.2 version has only been tested against emulators, so no
performance data is available yet.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm64/crypto/Kconfig           |   4 +
 arch/arm64/crypto/Makefile          |   3 +
 arch/arm64/crypto/sha3-arm64-core.S | 512 ++++++++++++++++++++
 arch/arm64/crypto/sha3-arm64-glue.c | 192 ++++++++
 4 files changed, 711 insertions(+)

diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig
index aad288f4b9de..71293e049a5d 100644
--- a/arch/arm64/crypto/Kconfig
+++ b/arch/arm64/crypto/Kconfig
@@ -35,6 +35,10 @@ config CRYPTO_SHA512_ARM64_CE
 	select CRYPTO_HASH
 	select CRYPTO_SHA512_ARM64
 
+config CRYPTO_SHA3_ARM64
+	tristate "SHA3 digest algorithm (scalar + ARMv8.2 Crypto Extensions)"
+	select CRYPTO_HASH
+
 config CRYPTO_GHASH_ARM64_CE
 	tristate "GHASH/AES-GCM using ARMv8 Crypto Extensions"
 	depends on KERNEL_MODE_NEON
diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
index d7573d31d397..267764473ef6 100644
--- a/arch/arm64/crypto/Makefile
+++ b/arch/arm64/crypto/Makefile
@@ -17,6 +17,9 @@ sha2-ce-y := sha2-ce-glue.o sha2-ce-core.o
 obj-$(CONFIG_CRYPTO_SHA512_ARM64_CE) += sha512-ce.o
 sha512-ce-y := sha512-ce-glue.o sha512-ce-core.o
 
+obj-$(CONFIG_CRYPTO_SHA3_ARM64) += sha3-arm64.o
+sha3-arm64-y := sha3-arm64-glue.o sha3-arm64-core.o
+
 obj-$(CONFIG_CRYPTO_GHASH_ARM64_CE) += ghash-ce.o
 ghash-ce-y := ghash-ce-glue.o ghash-ce-core.o
 
diff --git a/arch/arm64/crypto/sha3-arm64-core.S b/arch/arm64/crypto/sha3-arm64-core.S
new file mode 100644
index 000000000000..e32f1e3e5b42
--- /dev/null
+++ b/arch/arm64/crypto/sha3-arm64-core.S
@@ -0,0 +1,512 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * sha3-arm64-core.S - core SHA-3 transform using scalar or v8.2 Crypto
+ *                     Extensions instructions
+ *
+ * Copyright (C) 2018 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+	/*
+	 * sha3_arm64_transform(u64 *st, const u8 *data, int blocks, int dg_size)
+	 */
+	.align		4
+ENTRY(sha3_arm64_transform)
+	/* preserve callee save registers - no room for a frame pointer! */
+	stp		x29, x30, [sp, #-144]!
+	stp		x19, x20, [sp, #16]
+	stp		x21, x22, [sp, #32]
+	stp		x23, x24, [sp, #48]
+	stp		x25, x26, [sp, #64]
+	stp		x27, x28, [sp, #80]
+
+	stp		 x0, x1, [sp, #96]	// preserve st, data
+	str		 x3, [sp, #112]		// preserve dg_size
+	mov		x30, x2			// preserve #blocks
+
+	/* load state */
+	mov		x25,  x0
+	ldp		 x0,  x1, [x0]
+	ldp		 x2,  x3, [x25, #16]
+	ldp		 x4,  x5, [x25, #32]
+	ldp		 x6,  x7, [x25, #48]
+	ldp		 x8,  x9, [x25, #64]
+	ldp		x10, x11, [x25, #80]
+	ldp		x12, x13, [x25, #96]
+	ldp		x14, x15, [x25, #112]
+	ldp		x16, x17, [x25, #128]
+	ldp		x18, x19, [x25, #144]
+	ldp		x20, x21, [x25, #160]
+	ldp		x22, x23, [x25, #176]
+	ldr		x24, [x25, #192]
+
+0:	adr_l		x29, .Lsha3_rcon + 72
+	stp		x29, x30, [sp, #120]	// preserve rc pointer, #blocks
+	ldp		x29, x30, [sp, #104]	// load data, dg_size
+
+	/* load input */
+	ldp		x25, x26, [x29], #32
+	ldp		x27, x28, [x29, #-16]
+CPU_BE(	rev		x25, x25		)
+CPU_BE(	rev		x26, x26		)
+CPU_BE(	rev		x27, x27		)
+CPU_BE(	rev		x28, x28		)
+	eor		 x0,  x0, x25
+	eor		 x1,  x1, x26
+	eor		 x2,  x2, x27
+	eor		 x3,  x3, x28
+
+	ldp		x25, x26, [x29], #24
+	ldr		x27, [x29, #-8]
+CPU_BE(	rev		x25, x25		)
+CPU_BE(	rev		x26, x26		)
+CPU_BE(	rev		x27, x27		)
+	eor		 x4,  x4, x25
+	eor		 x5,  x5, x26
+	eor		 x6,  x6, x27
+
+	tbnz		x30, #6, 2f		// SHA3-512
+
+	ldp		x25, x26, [x29], #32
+	ldp		x27, x28, [x29, #-16]
+CPU_BE(	rev		x25, x25		)
+CPU_BE(	rev		x26, x26		)
+CPU_BE(	rev		x27, x27		)
+CPU_BE(	rev		x28, x28		)
+	eor		 x7,  x7, x25
+	eor		 x8,  x8, x26
+	eor		 x9,  x9, x27
+	eor		x10, x10, x28
+
+	ldp		x25, x26, [x29], #16
+CPU_BE(	rev		x25, x25		)
+CPU_BE(	rev		x26, x26		)
+	eor		x11, x11, x25
+	eor		x12, x12, x26
+
+	tbnz		x30, #4, 1f		// SHA3-384 or SHA3-224
+
+	// SHA3-256
+	ldp		x25, x26, [x29], #32
+	ldp		x27, x28, [x29, #-16]
+CPU_BE(	rev		x25, x25		)
+CPU_BE(	rev		x26, x26		)
+CPU_BE(	rev		x27, x27		)
+CPU_BE(	rev		x28, x28		)
+	eor		x13, x13, x25
+	eor		x14, x14, x26
+	eor		x15, x15, x27
+	eor		x16, x16, x28
+	b		3f
+
+1:	tbz		x30, #2, 3f		// bit 2 cleared? SHA-384
+
+	// SHA3-224
+	ldp		x25, x26, [x29], #40
+	ldp		x27, x28, [x29, #-24]
+	ldr		x30, [x29, #-8]
+CPU_BE(	rev		x25, x25		)
+CPU_BE(	rev		x26, x26		)
+CPU_BE(	rev		x27, x27		)
+CPU_BE(	rev		x28, x28		)
+CPU_BE(	rev		x30, x30		)
+	eor		x13, x13, x25
+	eor		x14, x14, x26
+	eor		x15, x15, x27
+	eor		x16, x16, x28
+	eor		x17, x17, x30
+	b		3f
+
+	// SHA3-512
+2:	ldp		x25, x26, [x29], #16
+CPU_BE(	rev		x25, x25		)
+CPU_BE(	rev		x26, x26		)
+	eor		 x7,  x7, x25
+	eor		 x8,  x8, x26
+
+3:	str		x29, [sp, #104]		// preserve data pointer
+
+	/* inner loop */
+4:	eor		x29,  x4,  x9
+	eor		x26,  x1,  x6
+	eor		x28,  x3,  x8
+	eor		x25,  x0,  x5
+	eor		x27,  x2,  x7
+	eor		x29, x29, x14
+	eor		x26, x26, x11
+	eor		x28, x28, x13
+	eor		x25, x25, x10
+	eor		x27, x27, x12
+	eor		x29, x29, x19
+	eor		x26, x26, x16
+	eor		x28, x28, x18
+	eor		x25, x25, x15
+	eor		x27, x27, x17
+	eor		x29, x29, x24
+	eor		x26, x26, x21
+	eor		x28, x28, x23
+	eor		x25, x25, x20
+	eor		x27, x27, x22
+
+	eor		x30, x29, x26, ror #63	// bc[0]
+	eor		x26, x26, x28, ror #63	// bc[2]
+	eor		x28, x28, x25, ror #63	// bc[4]
+	eor		x25, x25, x27, ror #63	// bc[1]
+	eor		x27, x27, x29, ror #63	// bc[3]
+
+	eor		 x0,  x0, x30
+	eor		x29,  x6, x25
+	eor		 x6,  x9, x28
+	eor		 x9, x22, x26
+	eor		x22, x14, x28
+	eor		x14, x20, x30
+	eor		x20,  x2, x26
+	eor		 x2, x12, x26
+	eor		x12, x13, x27
+	eor		x13, x19, x28
+	eor		x19, x23, X27
+	eor		x23, x15, x30
+	eor		x15,  x4, x28
+	eor		 x4, x24, x28
+	eor		x24, x21, x25
+	eor		x21,  x8, x27
+	eor		 x8, x16, x25
+	eor		x16,  x5, x30
+	eor		 x5,  x3, x27
+	eor		 x3, x18, x27
+	eor		x18, x17, x26
+	eor		x17, x11, x25
+	eor		x11,  x7, x26
+	eor		 x7, x10, x30
+	eor		x10,  x1, x25
+
+	ldr		x30, [sp, #120]		// load rc pointer
+
+	ror		 x1, x29, #(64 - 44)
+	ror		 x6,  x6, #(64 - 20)
+	ror		 x9,  x9, #(64 - 61)
+	ror		x22, x22, #(64 - 39)
+	ror		x14, x14, #(64 - 18)
+	ror		x20, x20, #(64 - 62)
+	ror		 x2,  x2, #(64 - 43)
+	ror		x12, x12, #(64 - 25)
+	ror		x13, x13, #(64 - 8)
+	ror		x19, x19, #(64 - 56)
+	ror		x23, x23, #(64 - 41)
+	ror		x15, x15, #(64 - 27)
+	ror		 x4,  x4, #(64 - 14)
+	ror		x24, x24, #(64 - 2)
+	ror		x21, x21, #(64 - 55)
+	ror		 x8,  x8, #(64 - 45)
+	ror		x16, x16, #(64 - 36)
+	ror		 x5,  x5, #(64 - 28)
+	ror		 x3,  x3, #(64 - 21)
+	ror		x18, x18, #(64 - 15)
+	ror		x17, x17, #(64 - 10)
+	ror		x11, x11, #(64 - 6)
+	ror		 x7,  x7, #(64 - 3)
+	ror		x10, x10, #(64 - 1)
+
+	add		x29, x30, #8		// advance rc pointer
+	tst		x30, #0xff		// last round?
+	ldr		x30, [x30, #-72]	// load rc
+	str		x29, [sp, #120]		// store rc pointer
+
+	bic		x25,  x2,  x1
+	bic		x26,  x3,  x2
+	bic		x27,  x4,  x3
+	bic		x28,  x0,  x4
+	bic		x29,  x1,  x0
+	eor		 x0,  x0, x25
+	eor		 x1,  x1, x26
+	eor		 x2,  x2, x27
+	eor		 x3,  x3, x28
+	eor		 x4,  x4, x29
+
+	bic		x25,  x7,  x6
+	bic		x26,  x8,  x7
+	bic		x27,  x9,  x8
+	bic		x28,  x5,  x9
+	bic		x29,  x6,  x5
+	eor		 x5,  x5, x25
+	eor		 x6,  x6, x26
+	eor		 x7,  x7, x27
+	eor		 x8,  x8, x28
+	eor		 x9,  x9, x29
+
+	bic		x25, x12, x11
+	bic		x26, x13, x12
+	bic		x27, x14, x13
+	bic		x28, x10, x14
+	bic		x29, x11, x10
+	eor		x10, x10, x25
+	eor		x11, x11, x26
+	eor		x12, x12, x27
+	eor		x13, x13, x28
+	eor		x14, x14, x29
+
+	eor		 x0,  x0, x30		// iota
+	ldr		x30, [sp, #128]		// preload #blocks
+
+	bic		x25, x17, x16
+	bic		x26, x18, x17
+	bic		x27, x19, x18
+	bic		x28, x15, x19
+	bic		x29, x16, x15
+	eor		x15, x15, x25
+	eor		x16, x16, x26
+	eor		x17, x17, x27
+	eor		x18, x18, x28
+	eor		x19, x19, x29
+
+	bic		x25, x22, x21
+	bic		x26, x23, x22
+	bic		x27, x24, x23
+	bic		x28, x20, x24
+	bic		x29, x21, x20
+	eor		x20, x20, x25
+	eor		x21, x21, x26
+	eor		x22, x22, x27
+	eor		x23, x23, x28
+	eor		x24, x24, x29
+
+	b.ne		4b
+
+	subs		x30, x30, #1
+	b.ne		0b
+
+	/* save state */
+	ldr		x25, [sp, #96]
+	stp		 x0,  x1, [x25]
+	stp		 x2,  x3, [x25, #16]
+	stp		 x4,  x5, [x25, #32]
+	stp		 x6,  x7, [x25, #48]
+	stp		 x8,  x9, [x25, #64]
+	stp		x10, x11, [x25, #80]
+	stp		x12, x13, [x25, #96]
+	stp		x14, x15, [x25, #112]
+	stp		x16, x17, [x25, #128]
+	stp		x18, x19, [x25, #144]
+	stp		x20, x21, [x25, #160]
+	stp		x22, x23, [x25, #176]
+	str		x24, [x25, #192]
+
+	/* restore callee save registers */
+	ldp		x19, x20, [sp, #16]
+	ldp		x21, x22, [sp, #32]
+	ldp		x23, x24, [sp, #48]
+	ldp		x25, x26, [sp, #64]
+	ldp		x27, x28, [sp, #80]
+	ldp		x29, x30, [sp], #144
+	ret
+ENDPROC(sha3_arm64_transform)
+
+	.irp		b,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+	.set		.Lv\b\().2d, \b
+	.set		.Lv\b\().16b, \b
+	.endr
+
+	/*
+	 * ARMv8.2 Crypto Extensions instructions
+	 */
+	.macro		eor3, rd, rn, rm, ra
+	.inst		0xce000000 | .L\rd | (.L\rn << 5) | (.L\ra << 10) | (.L\rm << 16)
+	.endm
+
+	.macro		rax1, rd, rn, rm
+	.inst		0xce608c00 | .L\rd | (.L\rn << 5) | (.L\rm << 16)
+	.endm
+
+	.macro		bcax, rd, rn, rm, ra
+	.inst		0xce200000 | .L\rd | (.L\rn << 5) | (.L\ra << 10) | (.L\rm << 16)
+	.endm
+
+	.macro		xar, rd, rn, rm, imm6
+	.inst		0xce800000 | .L\rd | (.L\rn << 5) | ((\imm6) << 10) | (.L\rm << 16)
+	.endm
+
+#ifdef CONFIG_KERNEL_MODE_NEON
+	/*
+	 * sha3_ce_transform(u64 *st, const u8 *data, int blocks, int dg_size)
+	 */
+	.text
+	.align		4
+ENTRY(sha3_ce_transform)
+	/* load state */
+	add		x8, x0, #32
+	ld1		{ v0.1d- v3.1d}, [x0]
+	ld1		{ v4.1d- v7.1d}, [x8], #32
+	ld1		{ v8.1d-v11.1d}, [x8], #32
+	ld1		{v12.1d-v15.1d}, [x8], #32
+	ld1		{v16.1d-v19.1d}, [x8], #32
+	ld1		{v20.1d-v23.1d}, [x8], #32
+	ld1		{v24.1d}, [x8]
+
+0:	sub		w2, w2, #1
+	mov		w8, #24
+	adr_l		x9, .Lsha3_rcon
+
+	/* load input */
+	ld1		{v25.8b-v28.8b}, [x1], #32
+	ld1		{v29.8b-v31.8b}, [x1], #24
+	eor		v0.8b, v0.8b, v25.8b
+	eor		v1.8b, v1.8b, v26.8b
+	eor		v2.8b, v2.8b, v27.8b
+	eor		v3.8b, v3.8b, v28.8b
+	eor		v4.8b, v4.8b, v29.8b
+	eor		v5.8b, v5.8b, v30.8b
+	eor		v6.8b, v6.8b, v31.8b
+
+	tbnz		x3, #6, 2f		// SHA3-512
+
+	ld1		{v25.8b-v28.8b}, [x1], #32
+	ld1		{v29.8b-v30.8b}, [x1], #16
+	eor		 v7.8b,  v7.8b, v25.8b
+	eor		 v8.8b,  v8.8b, v26.8b
+	eor		 v9.8b,  v9.8b, v27.8b
+	eor		v10.8b, v10.8b, v28.8b
+	eor		v11.8b, v11.8b, v29.8b
+	eor		v12.8b, v12.8b, v30.8b
+
+	tbnz		x3, #4, 1f		// SHA3-384 or SHA3-224
+
+	// SHA3-256
+	ld1		{v25.8b-v28.8b}, [x1], #32
+	eor		v13.8b, v13.8b, v25.8b
+	eor		v14.8b, v14.8b, v26.8b
+	eor		v15.8b, v15.8b, v27.8b
+	eor		v16.8b, v16.8b, v28.8b
+	b		3f
+
+1:	tbz		x3, #2, 3f		// bit 2 cleared? SHA-384
+
+	// SHA3-224
+	ld1		{v25.8b-v28.8b}, [x1], #32
+	ld1		{v29.8b}, [x1], #8
+	eor		v13.8b, v13.8b, v25.8b
+	eor		v14.8b, v14.8b, v26.8b
+	eor		v15.8b, v15.8b, v27.8b
+	eor		v16.8b, v16.8b, v28.8b
+	eor		v17.8b, v17.8b, v29.8b
+	b		3f
+
+	// SHA3-512
+2:	ld1		{v25.8b-v26.8b}, [x1], #16
+	eor		 v7.8b,  v7.8b, v25.8b
+	eor		 v8.8b,  v8.8b, v26.8b
+
+3:	sub		w8, w8, #1
+
+	eor3		v29.16b,  v4.16b,  v9.16b, v14.16b
+	eor3		v26.16b,  v1.16b,  v6.16b, v11.16b
+	eor3		v28.16b,  v3.16b,  v8.16b, v13.16b
+	eor3		v25.16b,  v0.16b,  v5.16b, v10.16b
+	eor3		v27.16b,  v2.16b,  v7.16b, v12.16b
+	eor3		v29.16b, v29.16b, v19.16b, v24.16b
+	eor3		v26.16b, v26.16b, v16.16b, v21.16b
+	eor3		v28.16b, v28.16b, v18.16b, v23.16b
+	eor3		v25.16b, v25.16b, v15.16b, v20.16b
+	eor3		v27.16b, v27.16b, v17.16b, v22.16b
+
+	rax1		v30.2d, v29.2d, v26.2d	// bc[0]
+	rax1		v26.2d, v26.2d, v28.2d	// bc[2]
+	rax1		v28.2d, v28.2d, v25.2d	// bc[4]
+	rax1		v25.2d, v25.2d, v27.2d	// bc[1]
+	rax1		v27.2d, v27.2d, v29.2d	// bc[3]
+
+	eor		 v0.16b,  v0.16b, v30.16b
+	xar		 v29.2d,   v1.2d,  v25.2d, (64 - 1)
+	xar		  v1.2d,   v6.2d,  v25.2d, (64 - 44)
+	xar		  v6.2d,   v9.2d,  v28.2d, (64 - 20)
+	xar		  v9.2d,  v22.2d,  v26.2d, (64 - 61)
+	xar		 v22.2d,  v14.2d,  v28.2d, (64 - 39)
+	xar		 v14.2d,  v20.2d,  v30.2d, (64 - 18)
+	xar		 v31.2d,   v2.2d,  v26.2d, (64 - 62)
+	xar		  v2.2d,  v12.2d,  v26.2d, (64 - 43)
+	xar		 v12.2d,  v13.2d,  v27.2d, (64 - 25)
+	xar		 v13.2d,  v19.2d,  v28.2d, (64 - 8)
+	xar		 v19.2d,  v23.2d,  v27.2d, (64 - 56)
+	xar		 v23.2d,  v15.2d,  v30.2d, (64 - 41)
+	xar		 v15.2d,   v4.2d,  v28.2d, (64 - 27)
+	xar		 v28.2d,  v24.2d,  v28.2d, (64 - 14)
+	xar		 v24.2d,  v21.2d,  v25.2d, (64 - 2)
+	xar		  v8.2d,   v8.2d,  v27.2d, (64 - 55)
+	xar		  v4.2d,  v16.2d,  v25.2d, (64 - 45)
+	xar		 v16.2d,   v5.2d,  v30.2d, (64 - 36)
+	xar		  v5.2d,   v3.2d,  v27.2d, (64 - 28)
+	xar		 v27.2d,  v18.2d,  v27.2d, (64 - 21)
+	xar		  v3.2d,  v17.2d,  v26.2d, (64 - 15)
+	xar		 v25.2d,  v11.2d,  v25.2d, (64 - 10)
+	xar		 v26.2d,   v7.2d,  v26.2d, (64 - 6)
+	xar		 v30.2d,  v10.2d,  v30.2d, (64 - 3)
+
+	bcax		v20.16b, v31.16b, v22.16b,  v8.16b
+	bcax		v21.16b,  v8.16b, v23.16b, v22.16b
+	bcax		v22.16b, v22.16b, v24.16b, v23.16b
+	bcax		v23.16b, v23.16b, v31.16b, v24.16b
+	bcax		v24.16b, v24.16b,  v8.16b, v31.16b
+
+	ld1r		{v31.2d}, [x9], #8
+
+	bcax		v17.16b, v25.16b, v19.16b,  v3.16b
+	bcax		v18.16b,  v3.16b, v15.16b, v19.16b
+	bcax		v19.16b, v19.16b, v16.16b, v15.16b
+	bcax		v15.16b, v15.16b, v25.16b, v16.16b
+	bcax		v16.16b, v16.16b,  v3.16b, v25.16b
+
+	bcax		v10.16b, v29.16b, v12.16b, v26.16b
+	bcax		v11.16b, v26.16b, v13.16b, v12.16b
+	bcax		v12.16b, v12.16b, v14.16b, v13.16b
+	bcax		v13.16b, v13.16b, v29.16b, v14.16b
+	bcax		v14.16b, v14.16b, v26.16b, v29.16b
+
+	bcax		 v7.16b, v30.16b,  v9.16b,  v4.16b
+	bcax		 v8.16b,  v4.16b,  v5.16b,  v9.16b
+	bcax		 v9.16b,  v9.16b,  v6.16b,  v5.16b
+	bcax		 v5.16b,  v5.16b, v30.16b,  v6.16b
+	bcax		 v6.16b,  v6.16b,  v4.16b, v30.16b
+
+	bcax		 v3.16b, v27.16b,  v0.16b, v28.16b
+	bcax		 v4.16b, v28.16b,  v1.16b,  v0.16b
+	bcax		 v0.16b,  v0.16b,  v2.16b,  v1.16b
+	bcax		 v1.16b,  v1.16b, v27.16b,  v2.16b
+	bcax		 v2.16b,  v2.16b, v28.16b, v27.16b
+
+	eor		 v0.16b,  v0.16b, v31.16b
+
+	cbnz		w8, 3b
+	cbnz		w2, 0b
+
+	/* save state */
+	st1		{ v0.1d- v3.1d}, [x0], #32
+	st1		{ v4.1d- v7.1d}, [x0], #32
+	st1		{ v8.1d-v11.1d}, [x0], #32
+	st1		{v12.1d-v15.1d}, [x0], #32
+	st1		{v16.1d-v19.1d}, [x0], #32
+	st1		{v20.1d-v23.1d}, [x0], #32
+	st1		{v24.1d}, [x0]
+	ret
+ENDPROC(sha3_ce_transform)
+#endif
+
+	.section	".rodata", "a"
+	.align		8
+.Lsha3_rcon:
+	.quad		0x0000000000000001, 0x0000000000008082
+	.quad		0x800000000000808a, 0x8000000080008000
+	.quad		0x000000000000808b, 0x0000000080000001
+	.quad		0x8000000080008081, 0x8000000000008009
+	.quad		0x000000000000008a, 0x0000000000000088
+	.quad		0x0000000080008009, 0x000000008000000a
+	.quad		0x000000008000808b, 0x800000000000008b
+	.quad		0x8000000000008089, 0x8000000000008003
+	.quad		0x8000000000008002, 0x8000000000000080
+	.quad		0x000000000000800a, 0x800000008000000a
+	.quad		0x8000000080008081, 0x8000000000008080
+	.quad		0x0000000080000001, 0x8000000080008008
diff --git a/arch/arm64/crypto/sha3-arm64-glue.c b/arch/arm64/crypto/sha3-arm64-glue.c
new file mode 100644
index 000000000000..c4297bab23f0
--- /dev/null
+++ b/arch/arm64/crypto/sha3-arm64-glue.c
@@ -0,0 +1,192 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * sha3-arm64-glue.c - core SHA-3 transform using scalar or v8.2 Crypto
+ *                     Extensions instructions
+ *
+ * Copyright (C) 2018 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+#include <asm/unaligned.h>
+#include <crypto/internal/hash.h>
+#include <crypto/sha3.h>
+#include <linux/cpufeature.h>
+#include <linux/crypto.h>
+#include <linux/module.h>
+
+MODULE_DESCRIPTION("SHA3 secure hash for arm64 (scalar + v8.2 Crypto Extensions)");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL v2");
+
+asmlinkage void sha3_ce_transform(u64 *st, const u8 *data, int blocks,
+				  int md_len);
+
+asmlinkage void sha3_arm64_transform(u64 *st, const u8 *data, int blocks,
+				     int md_len);
+
+static void __ro_after_init
+	(*sha3_transform)(u64 *, const u8 *, int, int) = sha3_arm64_transform;
+
+static void sha3_neon_transform(u64 *st, const u8 *data, int blocks, int md_len)
+{
+	if (may_use_simd()) {
+		kernel_neon_begin();
+		sha3_ce_transform(st, data, blocks, md_len);
+		kernel_neon_end();
+	} else {
+		sha3_arm64_transform(st, data, blocks, md_len);
+	}
+}
+
+static int sha3_init(struct shash_desc *desc)
+{
+	struct sha3_state *sctx = shash_desc_ctx(desc);
+	unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
+
+	sctx->rsiz = 200 - 2 * digest_size;
+	sctx->rsizw = sctx->rsiz / 8;
+	sctx->partial = 0;
+
+	memset(sctx->st, 0, sizeof(sctx->st));
+	return 0;
+}
+
+static int sha3_update(struct shash_desc *desc, const u8 *data,
+		       unsigned int len)
+{
+	struct sha3_state *sctx = shash_desc_ctx(desc);
+	unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
+
+	if ((sctx->partial + len) >= sctx->rsiz) {
+		int blocks;
+
+		if (sctx->partial) {
+			int p = sctx->rsiz - sctx->partial;
+
+			memcpy(sctx->buf + sctx->partial, data, p);
+			sha3_transform(sctx->st, sctx->buf, 1, digest_size);
+
+			data += p;
+			len -= p;
+			sctx->partial = 0;
+		}
+
+		blocks = len / sctx->rsiz;
+		len %= sctx->rsiz;
+
+		if (blocks) {
+			sha3_transform(sctx->st, data, blocks, digest_size);
+			data += blocks * sctx->rsiz;
+		}
+	}
+
+	if (len) {
+		memcpy(sctx->buf + sctx->partial, data, len);
+		sctx->partial += len;
+	}
+	return 0;
+}
+
+static int sha3_final(struct shash_desc *desc, u8 *out)
+{
+	struct sha3_state *sctx = shash_desc_ctx(desc);
+	unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
+	__le64 *digest = (__le64 *)out;
+	int i;
+
+	sctx->buf[sctx->partial++] = 0x06;
+	memset(sctx->buf + sctx->partial, 0, sctx->rsiz - sctx->partial);
+	sctx->buf[sctx->rsiz - 1] |= 0x80;
+
+	sha3_transform(sctx->st, sctx->buf, 1, digest_size);
+
+	for (i = 0; i < digest_size / 8; i++)
+		put_unaligned_le64(sctx->st[i], digest++);
+
+	if (digest_size & 4)
+		put_unaligned_le32(sctx->st[i], (__le32 *)digest);
+
+	*sctx = (struct sha3_state){};
+	return 0;
+}
+
+static struct shash_alg algs[] = { {
+	.digestsize		= SHA3_224_DIGEST_SIZE,
+	.init			= sha3_init,
+	.update			= sha3_update,
+	.final			= sha3_final,
+	.descsize		= sizeof(struct sha3_state),
+	.base.cra_name		= "sha3-224",
+	.base.cra_driver_name	= "sha3-224-arm64",
+	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+	.base.cra_blocksize	= SHA3_224_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+	.base.cra_priority	= 200,
+}, {
+	.digestsize		= SHA3_256_DIGEST_SIZE,
+	.init			= sha3_init,
+	.update			= sha3_update,
+	.final			= sha3_final,
+	.descsize		= sizeof(struct sha3_state),
+	.base.cra_name		= "sha3-256",
+	.base.cra_driver_name	= "sha3-256-arm64",
+	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+	.base.cra_blocksize	= SHA3_256_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+	.base.cra_priority	= 200,
+}, {
+	.digestsize		= SHA3_384_DIGEST_SIZE,
+	.init			= sha3_init,
+	.update			= sha3_update,
+	.final			= sha3_final,
+	.descsize		= sizeof(struct sha3_state),
+	.base.cra_name		= "sha3-384",
+	.base.cra_driver_name	= "sha3-384-arm64",
+	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+	.base.cra_blocksize	= SHA3_384_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+	.base.cra_priority	= 200,
+}, {
+	.digestsize		= SHA3_512_DIGEST_SIZE,
+	.init			= sha3_init,
+	.update			= sha3_update,
+	.final			= sha3_final,
+	.descsize		= sizeof(struct sha3_state),
+	.base.cra_name		= "sha3-512",
+	.base.cra_driver_name	= "sha3-512-arm64",
+	.base.cra_flags		= CRYPTO_ALG_TYPE_SHASH,
+	.base.cra_blocksize	= SHA3_512_BLOCK_SIZE,
+	.base.cra_module	= THIS_MODULE,
+	.base.cra_priority	= 200,
+} };
+
+static int __init sha3_neon_mod_init(void)
+{
+	if (IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && (elf_hwcap & HWCAP_SHA3))
+		sha3_transform = sha3_neon_transform;
+
+	return crypto_register_shashes(algs, ARRAY_SIZE(algs));
+}
+
+static void __exit sha3_neon_mod_fini(void)
+{
+	crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+}
+
+module_init(sha3_neon_mod_init);
+module_exit(sha3_neon_mod_fini);
+
+MODULE_ALIAS_CRYPTO("sha3-224");
+MODULE_ALIAS_CRYPTO("sha3-224-arm64");
+MODULE_ALIAS_CRYPTO("sha3-256");
+MODULE_ALIAS_CRYPTO("sha3-256-arm64");
+MODULE_ALIAS_CRYPTO("sha3-384");
+MODULE_ALIAS_CRYPTO("sha3-384-arm64");
+MODULE_ALIAS_CRYPTO("sha3-512");
+MODULE_ALIAS_CRYPTO("sha3-512-arm64");
-- 
2.11.0

^ permalink raw reply related

* [PATCH v2 3/3] crypto/testmgr: sha3 - add new testcases
From: Ard Biesheuvel @ 2018-01-14 16:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180114164118.18330-1-ard.biesheuvel@linaro.org>

All current SHA3 test cases are smaller than the SHA3 block size, which
means not all code paths are being exercised. So add a new test case to
each variant, and make one of the existing test cases chunked.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 crypto/testmgr.h | 550 ++++++++++++++++++++
 1 file changed, 550 insertions(+)

diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index a714b6293959..6044f6906bd6 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -1052,6 +1052,142 @@ static const struct hash_testvec sha3_224_tv_template[] = {
 				"\xc9\xfd\x55\x74\x49\x44\x79\xba"
 				"\x5c\x7e\x7a\xb7\x6e\xf2\x64\xea"
 				"\xd0\xfc\xce\x33",
+		.np	= 2,
+		.tap	= { 28, 28 },
+	}, {
+		.plaintext = "\x08\x9f\x13\xaa\x41\xd8\x4c\xe3"
+			     "\x7a\x11\x85\x1c\xb3\x27\xbe\x55"
+			     "\xec\x60\xf7\x8e\x02\x99\x30\xc7"
+			     "\x3b\xd2\x69\x00\x74\x0b\xa2\x16"
+			     "\xad\x44\xdb\x4f\xe6\x7d\x14\x88"
+			     "\x1f\xb6\x2a\xc1\x58\xef\x63\xfa"
+			     "\x91\x05\x9c\x33\xca\x3e\xd5\x6c"
+			     "\x03\x77\x0e\xa5\x19\xb0\x47\xde"
+			     "\x52\xe9\x80\x17\x8b\x22\xb9\x2d"
+			     "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f"
+			     "\x36\xcd\x41\xd8\x6f\x06\x7a\x11"
+			     "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83"
+			     "\x1a\x8e\x25\xbc\x30\xc7\x5e\xf5"
+			     "\x69\x00\x97\x0b\xa2\x39\xd0\x44"
+			     "\xdb\x72\x09\x7d\x14\xab\x1f\xb6"
+			     "\x4d\xe4\x58\xef\x86\x1d\x91\x28"
+			     "\xbf\x33\xca\x61\xf8\x6c\x03\x9a"
+			     "\x0e\xa5\x3c\xd3\x47\xde\x75\x0c"
+			     "\x80\x17\xae\x22\xb9\x50\xe7\x5b"
+			     "\xf2\x89\x20\x94\x2b\xc2\x36\xcd"
+			     "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f"
+			     "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1"
+			     "\x25\xbc\x53\xea\x5e\xf5\x8c\x00"
+			     "\x97\x2e\xc5\x39\xd0\x67\xfe\x72"
+			     "\x09\xa0\x14\xab\x42\xd9\x4d\xe4"
+			     "\x7b\x12\x86\x1d\xb4\x28\xbf\x56"
+			     "\xed\x61\xf8\x8f\x03\x9a\x31\xc8"
+			     "\x3c\xd3\x6a\x01\x75\x0c\xa3\x17"
+			     "\xae\x45\xdc\x50\xe7\x7e\x15\x89"
+			     "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb"
+			     "\x92\x06\x9d\x34\xcb\x3f\xd6\x6d"
+			     "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf"
+			     "\x53\xea\x81\x18\x8c\x23\xba\x2e"
+			     "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0"
+			     "\x37\xce\x42\xd9\x70\x07\x7b\x12"
+			     "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84"
+			     "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6"
+			     "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45"
+			     "\xdc\x73\x0a\x7e\x15\xac\x20\xb7"
+			     "\x4e\xe5\x59\xf0\x87\x1e\x92\x29"
+			     "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b"
+			     "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d"
+			     "\x81\x18\xaf\x23\xba\x51\xe8\x5c"
+			     "\xf3\x8a\x21\x95\x2c\xc3\x37\xce"
+			     "\x65\xfc\x70\x07\x9e\x12\xa9\x40"
+			     "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2"
+			     "\x26\xbd\x54\xeb\x5f\xf6\x8d\x01"
+			     "\x98\x2f\xc6\x3a\xd1\x68\xff\x73"
+			     "\x0a\xa1\x15\xac\x43\xda\x4e\xe5"
+			     "\x7c\x13\x87\x1e\xb5\x29\xc0\x57"
+			     "\xee\x62\xf9\x90\x04\x9b\x32\xc9"
+			     "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18"
+			     "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a"
+			     "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc"
+			     "\x93\x07\x9e\x35\xcc\x40\xd7\x6e"
+			     "\x05\x79\x10\xa7\x1b\xb2\x49\xe0"
+			     "\x54\xeb\x82\x19\x8d\x24\xbb\x2f"
+			     "\xc6\x5d\xf4\x68\xff\x96\x0a\xa1"
+			     "\x38\xcf\x43\xda\x71\x08\x7c\x13"
+			     "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85"
+			     "\x1c\x90\x27\xbe\x32\xc9\x60\xf7"
+			     "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46"
+			     "\xdd\x74\x0b\x7f\x16\xad\x21\xb8"
+			     "\x4f\xe6\x5a\xf1\x88\x1f\x93\x2a"
+			     "\xc1\x35\xcc\x63\xfa\x6e\x05\x9c"
+			     "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e"
+			     "\x82\x19\xb0\x24\xbb\x52\xe9\x5d"
+			     "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf"
+			     "\x66\xfd\x71\x08\x9f\x13\xaa\x41"
+			     "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3"
+			     "\x27\xbe\x55\xec\x60\xf7\x8e\x02"
+			     "\x99\x30\xc7\x3b\xd2\x69\x00\x74"
+			     "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6"
+			     "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58"
+			     "\xef\x63\xfa\x91\x05\x9c\x33\xca"
+			     "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19"
+			     "\xb0\x47\xde\x52\xe9\x80\x17\x8b"
+			     "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd"
+			     "\x94\x08\x9f\x36\xcd\x41\xd8\x6f"
+			     "\x06\x7a\x11\xa8\x1c\xb3\x4a\xe1"
+			     "\x55\xec\x83\x1a\x8e\x25\xbc\x30"
+			     "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2"
+			     "\x39\xd0\x44\xdb\x72\x09\x7d\x14"
+			     "\xab\x1f\xb6\x4d\xe4\x58\xef\x86"
+			     "\x1d\x91\x28\xbf\x33\xca\x61\xf8"
+			     "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47"
+			     "\xde\x75\x0c\x80\x17\xae\x22\xb9"
+			     "\x50\xe7\x5b\xf2\x89\x20\x94\x2b"
+			     "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d"
+			     "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f"
+			     "\x83\x1a\xb1\x25\xbc\x53\xea\x5e"
+			     "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0"
+			     "\x67\xfe\x72\x09\xa0\x14\xab\x42"
+			     "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4"
+			     "\x28\xbf\x56\xed\x61\xf8\x8f\x03"
+			     "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75"
+			     "\x0c\xa3\x17\xae\x45\xdc\x50\xe7"
+			     "\x7e\x15\x89\x20\xb7\x2b\xc2\x59"
+			     "\xf0\x64\xfb\x92\x06\x9d\x34\xcb"
+			     "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a"
+			     "\xb1\x48\xdf\x53\xea\x81\x18\x8c"
+			     "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe"
+			     "\x95\x09\xa0\x37\xce\x42\xd9\x70"
+			     "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2"
+			     "\x56\xed\x84\x1b\x8f\x26\xbd\x31"
+			     "\xc8\x5f\xf6\x6a\x01\x98\x0c\xa3"
+			     "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15"
+			     "\xac\x20\xb7\x4e\xe5\x59\xf0\x87"
+			     "\x1e\x92\x29\xc0\x34\xcb\x62\xf9"
+			     "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48"
+			     "\xdf\x76\x0d\x81\x18\xaf\x23\xba"
+			     "\x51\xe8\x5c\xf3\x8a\x21\x95\x2c"
+			     "\xc3\x37\xce\x65\xfc\x70\x07\x9e"
+			     "\x12\xa9\x40\xd7\x4b\xe2\x79\x10"
+			     "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f"
+			     "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1"
+			     "\x68\xff\x73\x0a\xa1\x15\xac\x43"
+			     "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5"
+			     "\x29\xc0\x57\xee\x62\xf9\x90\x04"
+			     "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76"
+			     "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8"
+			     "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a"
+			     "\xf1\x65\xfc\x93\x07\x9e\x35\xcc"
+			     "\x40\xd7\x6e\x05\x79\x10\xa7\x1b"
+			     "\xb2\x49\xe0\x54\xeb\x82\x19\x8d"
+			     "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff"
+			     "\x96\x0a\xa1\x38\xcf\x43\xda\x71"
+			     "\x08\x7c\x13\xaa\x1e\xb5\x4c",
+		.psize     = 1023,
+		.digest    = "\x7d\x0f\x2f\xb7\x65\x3b\xa7\x26"
+			     "\xc3\x88\x20\x71\x15\x06\xe8\x2d"
+			     "\xa3\x92\x44\xab\x3e\xe7\xff\x86"
+			     "\xb6\x79\x10\x72",
 	},
 };
 
@@ -1077,6 +1213,142 @@ static const struct hash_testvec sha3_256_tv_template[] = {
 				"\x49\x10\x03\x76\xa8\x23\x5e\x2c"
 				"\x82\xe1\xb9\x99\x8a\x99\x9e\x21"
 				"\xdb\x32\xdd\x97\x49\x6d\x33\x76",
+		.np	= 2,
+		.tap	= { 28, 28 },
+	}, {
+		.plaintext = "\x08\x9f\x13\xaa\x41\xd8\x4c\xe3"
+			     "\x7a\x11\x85\x1c\xb3\x27\xbe\x55"
+			     "\xec\x60\xf7\x8e\x02\x99\x30\xc7"
+			     "\x3b\xd2\x69\x00\x74\x0b\xa2\x16"
+			     "\xad\x44\xdb\x4f\xe6\x7d\x14\x88"
+			     "\x1f\xb6\x2a\xc1\x58\xef\x63\xfa"
+			     "\x91\x05\x9c\x33\xca\x3e\xd5\x6c"
+			     "\x03\x77\x0e\xa5\x19\xb0\x47\xde"
+			     "\x52\xe9\x80\x17\x8b\x22\xb9\x2d"
+			     "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f"
+			     "\x36\xcd\x41\xd8\x6f\x06\x7a\x11"
+			     "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83"
+			     "\x1a\x8e\x25\xbc\x30\xc7\x5e\xf5"
+			     "\x69\x00\x97\x0b\xa2\x39\xd0\x44"
+			     "\xdb\x72\x09\x7d\x14\xab\x1f\xb6"
+			     "\x4d\xe4\x58\xef\x86\x1d\x91\x28"
+			     "\xbf\x33\xca\x61\xf8\x6c\x03\x9a"
+			     "\x0e\xa5\x3c\xd3\x47\xde\x75\x0c"
+			     "\x80\x17\xae\x22\xb9\x50\xe7\x5b"
+			     "\xf2\x89\x20\x94\x2b\xc2\x36\xcd"
+			     "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f"
+			     "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1"
+			     "\x25\xbc\x53\xea\x5e\xf5\x8c\x00"
+			     "\x97\x2e\xc5\x39\xd0\x67\xfe\x72"
+			     "\x09\xa0\x14\xab\x42\xd9\x4d\xe4"
+			     "\x7b\x12\x86\x1d\xb4\x28\xbf\x56"
+			     "\xed\x61\xf8\x8f\x03\x9a\x31\xc8"
+			     "\x3c\xd3\x6a\x01\x75\x0c\xa3\x17"
+			     "\xae\x45\xdc\x50\xe7\x7e\x15\x89"
+			     "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb"
+			     "\x92\x06\x9d\x34\xcb\x3f\xd6\x6d"
+			     "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf"
+			     "\x53\xea\x81\x18\x8c\x23\xba\x2e"
+			     "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0"
+			     "\x37\xce\x42\xd9\x70\x07\x7b\x12"
+			     "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84"
+			     "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6"
+			     "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45"
+			     "\xdc\x73\x0a\x7e\x15\xac\x20\xb7"
+			     "\x4e\xe5\x59\xf0\x87\x1e\x92\x29"
+			     "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b"
+			     "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d"
+			     "\x81\x18\xaf\x23\xba\x51\xe8\x5c"
+			     "\xf3\x8a\x21\x95\x2c\xc3\x37\xce"
+			     "\x65\xfc\x70\x07\x9e\x12\xa9\x40"
+			     "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2"
+			     "\x26\xbd\x54\xeb\x5f\xf6\x8d\x01"
+			     "\x98\x2f\xc6\x3a\xd1\x68\xff\x73"
+			     "\x0a\xa1\x15\xac\x43\xda\x4e\xe5"
+			     "\x7c\x13\x87\x1e\xb5\x29\xc0\x57"
+			     "\xee\x62\xf9\x90\x04\x9b\x32\xc9"
+			     "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18"
+			     "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a"
+			     "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc"
+			     "\x93\x07\x9e\x35\xcc\x40\xd7\x6e"
+			     "\x05\x79\x10\xa7\x1b\xb2\x49\xe0"
+			     "\x54\xeb\x82\x19\x8d\x24\xbb\x2f"
+			     "\xc6\x5d\xf4\x68\xff\x96\x0a\xa1"
+			     "\x38\xcf\x43\xda\x71\x08\x7c\x13"
+			     "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85"
+			     "\x1c\x90\x27\xbe\x32\xc9\x60\xf7"
+			     "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46"
+			     "\xdd\x74\x0b\x7f\x16\xad\x21\xb8"
+			     "\x4f\xe6\x5a\xf1\x88\x1f\x93\x2a"
+			     "\xc1\x35\xcc\x63\xfa\x6e\x05\x9c"
+			     "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e"
+			     "\x82\x19\xb0\x24\xbb\x52\xe9\x5d"
+			     "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf"
+			     "\x66\xfd\x71\x08\x9f\x13\xaa\x41"
+			     "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3"
+			     "\x27\xbe\x55\xec\x60\xf7\x8e\x02"
+			     "\x99\x30\xc7\x3b\xd2\x69\x00\x74"
+			     "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6"
+			     "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58"
+			     "\xef\x63\xfa\x91\x05\x9c\x33\xca"
+			     "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19"
+			     "\xb0\x47\xde\x52\xe9\x80\x17\x8b"
+			     "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd"
+			     "\x94\x08\x9f\x36\xcd\x41\xd8\x6f"
+			     "\x06\x7a\x11\xa8\x1c\xb3\x4a\xe1"
+			     "\x55\xec\x83\x1a\x8e\x25\xbc\x30"
+			     "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2"
+			     "\x39\xd0\x44\xdb\x72\x09\x7d\x14"
+			     "\xab\x1f\xb6\x4d\xe4\x58\xef\x86"
+			     "\x1d\x91\x28\xbf\x33\xca\x61\xf8"
+			     "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47"
+			     "\xde\x75\x0c\x80\x17\xae\x22\xb9"
+			     "\x50\xe7\x5b\xf2\x89\x20\x94\x2b"
+			     "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d"
+			     "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f"
+			     "\x83\x1a\xb1\x25\xbc\x53\xea\x5e"
+			     "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0"
+			     "\x67\xfe\x72\x09\xa0\x14\xab\x42"
+			     "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4"
+			     "\x28\xbf\x56\xed\x61\xf8\x8f\x03"
+			     "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75"
+			     "\x0c\xa3\x17\xae\x45\xdc\x50\xe7"
+			     "\x7e\x15\x89\x20\xb7\x2b\xc2\x59"
+			     "\xf0\x64\xfb\x92\x06\x9d\x34\xcb"
+			     "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a"
+			     "\xb1\x48\xdf\x53\xea\x81\x18\x8c"
+			     "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe"
+			     "\x95\x09\xa0\x37\xce\x42\xd9\x70"
+			     "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2"
+			     "\x56\xed\x84\x1b\x8f\x26\xbd\x31"
+			     "\xc8\x5f\xf6\x6a\x01\x98\x0c\xa3"
+			     "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15"
+			     "\xac\x20\xb7\x4e\xe5\x59\xf0\x87"
+			     "\x1e\x92\x29\xc0\x34\xcb\x62\xf9"
+			     "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48"
+			     "\xdf\x76\x0d\x81\x18\xaf\x23\xba"
+			     "\x51\xe8\x5c\xf3\x8a\x21\x95\x2c"
+			     "\xc3\x37\xce\x65\xfc\x70\x07\x9e"
+			     "\x12\xa9\x40\xd7\x4b\xe2\x79\x10"
+			     "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f"
+			     "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1"
+			     "\x68\xff\x73\x0a\xa1\x15\xac\x43"
+			     "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5"
+			     "\x29\xc0\x57\xee\x62\xf9\x90\x04"
+			     "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76"
+			     "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8"
+			     "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a"
+			     "\xf1\x65\xfc\x93\x07\x9e\x35\xcc"
+			     "\x40\xd7\x6e\x05\x79\x10\xa7\x1b"
+			     "\xb2\x49\xe0\x54\xeb\x82\x19\x8d"
+			     "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff"
+			     "\x96\x0a\xa1\x38\xcf\x43\xda\x71"
+			     "\x08\x7c\x13\xaa\x1e\xb5\x4c",
+		.psize     = 1023,
+		.digest    = "\xde\x41\x04\xbd\xda\xda\xd9\x71"
+			     "\xf7\xfa\x80\xf5\xea\x11\x03\xb1"
+			     "\x3b\x6a\xbc\x5f\xb9\x66\x26\xf7"
+			     "\x8a\x97\xbb\xf2\x07\x08\x38\x30",
 	},
 };
 
@@ -1109,6 +1381,144 @@ static const struct hash_testvec sha3_384_tv_template[] = {
 				"\x9b\xfd\xbc\x32\xb9\xd4\xad\x5a"
 				"\xa0\x4a\x1f\x07\x6e\x62\xfe\xa1"
 				"\x9e\xef\x51\xac\xd0\x65\x7c\x22",
+		.np	= 2,
+		.tap	= { 28, 28 },
+	}, {
+		.plaintext = "\x08\x9f\x13\xaa\x41\xd8\x4c\xe3"
+			     "\x7a\x11\x85\x1c\xb3\x27\xbe\x55"
+			     "\xec\x60\xf7\x8e\x02\x99\x30\xc7"
+			     "\x3b\xd2\x69\x00\x74\x0b\xa2\x16"
+			     "\xad\x44\xdb\x4f\xe6\x7d\x14\x88"
+			     "\x1f\xb6\x2a\xc1\x58\xef\x63\xfa"
+			     "\x91\x05\x9c\x33\xca\x3e\xd5\x6c"
+			     "\x03\x77\x0e\xa5\x19\xb0\x47\xde"
+			     "\x52\xe9\x80\x17\x8b\x22\xb9\x2d"
+			     "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f"
+			     "\x36\xcd\x41\xd8\x6f\x06\x7a\x11"
+			     "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83"
+			     "\x1a\x8e\x25\xbc\x30\xc7\x5e\xf5"
+			     "\x69\x00\x97\x0b\xa2\x39\xd0\x44"
+			     "\xdb\x72\x09\x7d\x14\xab\x1f\xb6"
+			     "\x4d\xe4\x58\xef\x86\x1d\x91\x28"
+			     "\xbf\x33\xca\x61\xf8\x6c\x03\x9a"
+			     "\x0e\xa5\x3c\xd3\x47\xde\x75\x0c"
+			     "\x80\x17\xae\x22\xb9\x50\xe7\x5b"
+			     "\xf2\x89\x20\x94\x2b\xc2\x36\xcd"
+			     "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f"
+			     "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1"
+			     "\x25\xbc\x53\xea\x5e\xf5\x8c\x00"
+			     "\x97\x2e\xc5\x39\xd0\x67\xfe\x72"
+			     "\x09\xa0\x14\xab\x42\xd9\x4d\xe4"
+			     "\x7b\x12\x86\x1d\xb4\x28\xbf\x56"
+			     "\xed\x61\xf8\x8f\x03\x9a\x31\xc8"
+			     "\x3c\xd3\x6a\x01\x75\x0c\xa3\x17"
+			     "\xae\x45\xdc\x50\xe7\x7e\x15\x89"
+			     "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb"
+			     "\x92\x06\x9d\x34\xcb\x3f\xd6\x6d"
+			     "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf"
+			     "\x53\xea\x81\x18\x8c\x23\xba\x2e"
+			     "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0"
+			     "\x37\xce\x42\xd9\x70\x07\x7b\x12"
+			     "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84"
+			     "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6"
+			     "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45"
+			     "\xdc\x73\x0a\x7e\x15\xac\x20\xb7"
+			     "\x4e\xe5\x59\xf0\x87\x1e\x92\x29"
+			     "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b"
+			     "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d"
+			     "\x81\x18\xaf\x23\xba\x51\xe8\x5c"
+			     "\xf3\x8a\x21\x95\x2c\xc3\x37\xce"
+			     "\x65\xfc\x70\x07\x9e\x12\xa9\x40"
+			     "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2"
+			     "\x26\xbd\x54\xeb\x5f\xf6\x8d\x01"
+			     "\x98\x2f\xc6\x3a\xd1\x68\xff\x73"
+			     "\x0a\xa1\x15\xac\x43\xda\x4e\xe5"
+			     "\x7c\x13\x87\x1e\xb5\x29\xc0\x57"
+			     "\xee\x62\xf9\x90\x04\x9b\x32\xc9"
+			     "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18"
+			     "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a"
+			     "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc"
+			     "\x93\x07\x9e\x35\xcc\x40\xd7\x6e"
+			     "\x05\x79\x10\xa7\x1b\xb2\x49\xe0"
+			     "\x54\xeb\x82\x19\x8d\x24\xbb\x2f"
+			     "\xc6\x5d\xf4\x68\xff\x96\x0a\xa1"
+			     "\x38\xcf\x43\xda\x71\x08\x7c\x13"
+			     "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85"
+			     "\x1c\x90\x27\xbe\x32\xc9\x60\xf7"
+			     "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46"
+			     "\xdd\x74\x0b\x7f\x16\xad\x21\xb8"
+			     "\x4f\xe6\x5a\xf1\x88\x1f\x93\x2a"
+			     "\xc1\x35\xcc\x63\xfa\x6e\x05\x9c"
+			     "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e"
+			     "\x82\x19\xb0\x24\xbb\x52\xe9\x5d"
+			     "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf"
+			     "\x66\xfd\x71\x08\x9f\x13\xaa\x41"
+			     "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3"
+			     "\x27\xbe\x55\xec\x60\xf7\x8e\x02"
+			     "\x99\x30\xc7\x3b\xd2\x69\x00\x74"
+			     "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6"
+			     "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58"
+			     "\xef\x63\xfa\x91\x05\x9c\x33\xca"
+			     "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19"
+			     "\xb0\x47\xde\x52\xe9\x80\x17\x8b"
+			     "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd"
+			     "\x94\x08\x9f\x36\xcd\x41\xd8\x6f"
+			     "\x06\x7a\x11\xa8\x1c\xb3\x4a\xe1"
+			     "\x55\xec\x83\x1a\x8e\x25\xbc\x30"
+			     "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2"
+			     "\x39\xd0\x44\xdb\x72\x09\x7d\x14"
+			     "\xab\x1f\xb6\x4d\xe4\x58\xef\x86"
+			     "\x1d\x91\x28\xbf\x33\xca\x61\xf8"
+			     "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47"
+			     "\xde\x75\x0c\x80\x17\xae\x22\xb9"
+			     "\x50\xe7\x5b\xf2\x89\x20\x94\x2b"
+			     "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d"
+			     "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f"
+			     "\x83\x1a\xb1\x25\xbc\x53\xea\x5e"
+			     "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0"
+			     "\x67\xfe\x72\x09\xa0\x14\xab\x42"
+			     "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4"
+			     "\x28\xbf\x56\xed\x61\xf8\x8f\x03"
+			     "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75"
+			     "\x0c\xa3\x17\xae\x45\xdc\x50\xe7"
+			     "\x7e\x15\x89\x20\xb7\x2b\xc2\x59"
+			     "\xf0\x64\xfb\x92\x06\x9d\x34\xcb"
+			     "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a"
+			     "\xb1\x48\xdf\x53\xea\x81\x18\x8c"
+			     "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe"
+			     "\x95\x09\xa0\x37\xce\x42\xd9\x70"
+			     "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2"
+			     "\x56\xed\x84\x1b\x8f\x26\xbd\x31"
+			     "\xc8\x5f\xf6\x6a\x01\x98\x0c\xa3"
+			     "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15"
+			     "\xac\x20\xb7\x4e\xe5\x59\xf0\x87"
+			     "\x1e\x92\x29\xc0\x34\xcb\x62\xf9"
+			     "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48"
+			     "\xdf\x76\x0d\x81\x18\xaf\x23\xba"
+			     "\x51\xe8\x5c\xf3\x8a\x21\x95\x2c"
+			     "\xc3\x37\xce\x65\xfc\x70\x07\x9e"
+			     "\x12\xa9\x40\xd7\x4b\xe2\x79\x10"
+			     "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f"
+			     "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1"
+			     "\x68\xff\x73\x0a\xa1\x15\xac\x43"
+			     "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5"
+			     "\x29\xc0\x57\xee\x62\xf9\x90\x04"
+			     "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76"
+			     "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8"
+			     "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a"
+			     "\xf1\x65\xfc\x93\x07\x9e\x35\xcc"
+			     "\x40\xd7\x6e\x05\x79\x10\xa7\x1b"
+			     "\xb2\x49\xe0\x54\xeb\x82\x19\x8d"
+			     "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff"
+			     "\x96\x0a\xa1\x38\xcf\x43\xda\x71"
+			     "\x08\x7c\x13\xaa\x1e\xb5\x4c",
+		.psize     = 1023,
+		.digest    = "\x1b\x19\x4d\x8f\xd5\x36\x87\x71"
+			     "\xcf\xca\x30\x85\x9b\xc1\x25\xc7"
+			     "\x00\xcb\x73\x8a\x8e\xd4\xfe\x2b"
+			     "\x1a\xa2\xdc\x2e\x41\xfd\x52\x51"
+			     "\xd2\x21\xae\x2d\xc7\xae\x8c\x40"
+			     "\xb9\xe6\x56\x48\x03\xcd\x88\x6b",
 	},
 };
 
@@ -1147,6 +1557,146 @@ static const struct hash_testvec sha3_512_tv_template[] = {
 				"\xba\x1b\x0d\x8d\xc7\x8c\x08\x63"
 				"\x46\xb5\x33\xb4\x9c\x03\x0d\x99"
 				"\xa2\x7d\xaf\x11\x39\xd6\xe7\x5e",
+		.np	= 2,
+		.tap	= { 28, 28 },
+	}, {
+		.plaintext = "\x08\x9f\x13\xaa\x41\xd8\x4c\xe3"
+			     "\x7a\x11\x85\x1c\xb3\x27\xbe\x55"
+			     "\xec\x60\xf7\x8e\x02\x99\x30\xc7"
+			     "\x3b\xd2\x69\x00\x74\x0b\xa2\x16"
+			     "\xad\x44\xdb\x4f\xe6\x7d\x14\x88"
+			     "\x1f\xb6\x2a\xc1\x58\xef\x63\xfa"
+			     "\x91\x05\x9c\x33\xca\x3e\xd5\x6c"
+			     "\x03\x77\x0e\xa5\x19\xb0\x47\xde"
+			     "\x52\xe9\x80\x17\x8b\x22\xb9\x2d"
+			     "\xc4\x5b\xf2\x66\xfd\x94\x08\x9f"
+			     "\x36\xcd\x41\xd8\x6f\x06\x7a\x11"
+			     "\xa8\x1c\xb3\x4a\xe1\x55\xec\x83"
+			     "\x1a\x8e\x25\xbc\x30\xc7\x5e\xf5"
+			     "\x69\x00\x97\x0b\xa2\x39\xd0\x44"
+			     "\xdb\x72\x09\x7d\x14\xab\x1f\xb6"
+			     "\x4d\xe4\x58\xef\x86\x1d\x91\x28"
+			     "\xbf\x33\xca\x61\xf8\x6c\x03\x9a"
+			     "\x0e\xa5\x3c\xd3\x47\xde\x75\x0c"
+			     "\x80\x17\xae\x22\xb9\x50\xe7\x5b"
+			     "\xf2\x89\x20\x94\x2b\xc2\x36\xcd"
+			     "\x64\xfb\x6f\x06\x9d\x11\xa8\x3f"
+			     "\xd6\x4a\xe1\x78\x0f\x83\x1a\xb1"
+			     "\x25\xbc\x53\xea\x5e\xf5\x8c\x00"
+			     "\x97\x2e\xc5\x39\xd0\x67\xfe\x72"
+			     "\x09\xa0\x14\xab\x42\xd9\x4d\xe4"
+			     "\x7b\x12\x86\x1d\xb4\x28\xbf\x56"
+			     "\xed\x61\xf8\x8f\x03\x9a\x31\xc8"
+			     "\x3c\xd3\x6a\x01\x75\x0c\xa3\x17"
+			     "\xae\x45\xdc\x50\xe7\x7e\x15\x89"
+			     "\x20\xb7\x2b\xc2\x59\xf0\x64\xfb"
+			     "\x92\x06\x9d\x34\xcb\x3f\xd6\x6d"
+			     "\x04\x78\x0f\xa6\x1a\xb1\x48\xdf"
+			     "\x53\xea\x81\x18\x8c\x23\xba\x2e"
+			     "\xc5\x5c\xf3\x67\xfe\x95\x09\xa0"
+			     "\x37\xce\x42\xd9\x70\x07\x7b\x12"
+			     "\xa9\x1d\xb4\x4b\xe2\x56\xed\x84"
+			     "\x1b\x8f\x26\xbd\x31\xc8\x5f\xf6"
+			     "\x6a\x01\x98\x0c\xa3\x3a\xd1\x45"
+			     "\xdc\x73\x0a\x7e\x15\xac\x20\xb7"
+			     "\x4e\xe5\x59\xf0\x87\x1e\x92\x29"
+			     "\xc0\x34\xcb\x62\xf9\x6d\x04\x9b"
+			     "\x0f\xa6\x3d\xd4\x48\xdf\x76\x0d"
+			     "\x81\x18\xaf\x23\xba\x51\xe8\x5c"
+			     "\xf3\x8a\x21\x95\x2c\xc3\x37\xce"
+			     "\x65\xfc\x70\x07\x9e\x12\xa9\x40"
+			     "\xd7\x4b\xe2\x79\x10\x84\x1b\xb2"
+			     "\x26\xbd\x54\xeb\x5f\xf6\x8d\x01"
+			     "\x98\x2f\xc6\x3a\xd1\x68\xff\x73"
+			     "\x0a\xa1\x15\xac\x43\xda\x4e\xe5"
+			     "\x7c\x13\x87\x1e\xb5\x29\xc0\x57"
+			     "\xee\x62\xf9\x90\x04\x9b\x32\xc9"
+			     "\x3d\xd4\x6b\x02\x76\x0d\xa4\x18"
+			     "\xaf\x46\xdd\x51\xe8\x7f\x16\x8a"
+			     "\x21\xb8\x2c\xc3\x5a\xf1\x65\xfc"
+			     "\x93\x07\x9e\x35\xcc\x40\xd7\x6e"
+			     "\x05\x79\x10\xa7\x1b\xb2\x49\xe0"
+			     "\x54\xeb\x82\x19\x8d\x24\xbb\x2f"
+			     "\xc6\x5d\xf4\x68\xff\x96\x0a\xa1"
+			     "\x38\xcf\x43\xda\x71\x08\x7c\x13"
+			     "\xaa\x1e\xb5\x4c\xe3\x57\xee\x85"
+			     "\x1c\x90\x27\xbe\x32\xc9\x60\xf7"
+			     "\x6b\x02\x99\x0d\xa4\x3b\xd2\x46"
+			     "\xdd\x74\x0b\x7f\x16\xad\x21\xb8"
+			     "\x4f\xe6\x5a\xf1\x88\x1f\x93\x2a"
+			     "\xc1\x35\xcc\x63\xfa\x6e\x05\x9c"
+			     "\x10\xa7\x3e\xd5\x49\xe0\x77\x0e"
+			     "\x82\x19\xb0\x24\xbb\x52\xe9\x5d"
+			     "\xf4\x8b\x22\x96\x2d\xc4\x38\xcf"
+			     "\x66\xfd\x71\x08\x9f\x13\xaa\x41"
+			     "\xd8\x4c\xe3\x7a\x11\x85\x1c\xb3"
+			     "\x27\xbe\x55\xec\x60\xf7\x8e\x02"
+			     "\x99\x30\xc7\x3b\xd2\x69\x00\x74"
+			     "\x0b\xa2\x16\xad\x44\xdb\x4f\xe6"
+			     "\x7d\x14\x88\x1f\xb6\x2a\xc1\x58"
+			     "\xef\x63\xfa\x91\x05\x9c\x33\xca"
+			     "\x3e\xd5\x6c\x03\x77\x0e\xa5\x19"
+			     "\xb0\x47\xde\x52\xe9\x80\x17\x8b"
+			     "\x22\xb9\x2d\xc4\x5b\xf2\x66\xfd"
+			     "\x94\x08\x9f\x36\xcd\x41\xd8\x6f"
+			     "\x06\x7a\x11\xa8\x1c\xb3\x4a\xe1"
+			     "\x55\xec\x83\x1a\x8e\x25\xbc\x30"
+			     "\xc7\x5e\xf5\x69\x00\x97\x0b\xa2"
+			     "\x39\xd0\x44\xdb\x72\x09\x7d\x14"
+			     "\xab\x1f\xb6\x4d\xe4\x58\xef\x86"
+			     "\x1d\x91\x28\xbf\x33\xca\x61\xf8"
+			     "\x6c\x03\x9a\x0e\xa5\x3c\xd3\x47"
+			     "\xde\x75\x0c\x80\x17\xae\x22\xb9"
+			     "\x50\xe7\x5b\xf2\x89\x20\x94\x2b"
+			     "\xc2\x36\xcd\x64\xfb\x6f\x06\x9d"
+			     "\x11\xa8\x3f\xd6\x4a\xe1\x78\x0f"
+			     "\x83\x1a\xb1\x25\xbc\x53\xea\x5e"
+			     "\xf5\x8c\x00\x97\x2e\xc5\x39\xd0"
+			     "\x67\xfe\x72\x09\xa0\x14\xab\x42"
+			     "\xd9\x4d\xe4\x7b\x12\x86\x1d\xb4"
+			     "\x28\xbf\x56\xed\x61\xf8\x8f\x03"
+			     "\x9a\x31\xc8\x3c\xd3\x6a\x01\x75"
+			     "\x0c\xa3\x17\xae\x45\xdc\x50\xe7"
+			     "\x7e\x15\x89\x20\xb7\x2b\xc2\x59"
+			     "\xf0\x64\xfb\x92\x06\x9d\x34\xcb"
+			     "\x3f\xd6\x6d\x04\x78\x0f\xa6\x1a"
+			     "\xb1\x48\xdf\x53\xea\x81\x18\x8c"
+			     "\x23\xba\x2e\xc5\x5c\xf3\x67\xfe"
+			     "\x95\x09\xa0\x37\xce\x42\xd9\x70"
+			     "\x07\x7b\x12\xa9\x1d\xb4\x4b\xe2"
+			     "\x56\xed\x84\x1b\x8f\x26\xbd\x31"
+			     "\xc8\x5f\xf6\x6a\x01\x98\x0c\xa3"
+			     "\x3a\xd1\x45\xdc\x73\x0a\x7e\x15"
+			     "\xac\x20\xb7\x4e\xe5\x59\xf0\x87"
+			     "\x1e\x92\x29\xc0\x34\xcb\x62\xf9"
+			     "\x6d\x04\x9b\x0f\xa6\x3d\xd4\x48"
+			     "\xdf\x76\x0d\x81\x18\xaf\x23\xba"
+			     "\x51\xe8\x5c\xf3\x8a\x21\x95\x2c"
+			     "\xc3\x37\xce\x65\xfc\x70\x07\x9e"
+			     "\x12\xa9\x40\xd7\x4b\xe2\x79\x10"
+			     "\x84\x1b\xb2\x26\xbd\x54\xeb\x5f"
+			     "\xf6\x8d\x01\x98\x2f\xc6\x3a\xd1"
+			     "\x68\xff\x73\x0a\xa1\x15\xac\x43"
+			     "\xda\x4e\xe5\x7c\x13\x87\x1e\xb5"
+			     "\x29\xc0\x57\xee\x62\xf9\x90\x04"
+			     "\x9b\x32\xc9\x3d\xd4\x6b\x02\x76"
+			     "\x0d\xa4\x18\xaf\x46\xdd\x51\xe8"
+			     "\x7f\x16\x8a\x21\xb8\x2c\xc3\x5a"
+			     "\xf1\x65\xfc\x93\x07\x9e\x35\xcc"
+			     "\x40\xd7\x6e\x05\x79\x10\xa7\x1b"
+			     "\xb2\x49\xe0\x54\xeb\x82\x19\x8d"
+			     "\x24\xbb\x2f\xc6\x5d\xf4\x68\xff"
+			     "\x96\x0a\xa1\x38\xcf\x43\xda\x71"
+			     "\x08\x7c\x13\xaa\x1e\xb5\x4c",
+		.psize     = 1023,
+		.digest    = "\x59\xda\x30\xe3\x90\xe4\x3d\xde"
+			     "\xf0\xc6\x42\x17\xd7\xb2\x26\x47"
+			     "\x90\x28\xa6\x84\xe8\x49\x7a\x86"
+			     "\xd6\xb8\x9e\xf8\x07\x59\x21\x03"
+			     "\xad\xd2\xed\x48\xa3\xb9\xa5\xf0"
+			     "\xb3\xae\x02\x2b\xb8\xaf\xc3\x3b"
+			     "\xd6\xb0\x8f\xcb\x76\x8b\xa7\x41"
+			     "\x32\xc2\x8e\x50\x91\x86\x90\xfb",
 	},
 };
 
-- 
2.11.0

^ permalink raw reply related

* Iphone ios
From: 森尚友前 @ 2018-01-14 19:04 UTC (permalink / raw)
  To: linux-arm-kernel



??? iPhone ??

^ permalink raw reply

* [PATCH v6] perf tools: Add ARM Statistical Profiling Extensions (SPE) support
From: Kim Phillips @ 2018-01-14 19:28 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180113184234.GK9655@kernel.org>

'perf record' and 'perf report --dump-raw-trace' supported in this
release.

Example usage:

 # perf record -e arm_spe/ts_enable=1,pa_enable=1/ dd if=/dev/zero of=/dev/null count=10000
 # perf report --dump-raw-trace

Note that the perf.data file is portable, so the report can be run on
another architecture host if necessary.

Output will contain raw SPE data and its textual representation, such
as:

0x5c8 [0x30]: PERF_RECORD_AUXTRACE size: 0x200000  offset: 0  ref: 0x1891ad0e  idx: 1  tid: 2227  cpu: 1
.
. ... ARM SPE data: size 2097152 bytes
.  00000000:  49 00                                           LD
.  00000002:  b2 c0 3b 29 0f 00 00 ff ff                      VA 0xffff00000f293bc0
.  0000000b:  b3 c0 eb 24 fb 00 00 00 80                      PA 0xfb24ebc0 ns=1
.  00000014:  9a 00 00                                        LAT 0 XLAT
.  00000017:  42 16                                           EV RETIRED L1D-ACCESS TLB-ACCESS
.  00000019:  b0 00 c4 15 08 00 00 ff ff                      PC 0xff00000815c400 el3 ns=1
.  00000022:  98 00 00                                        LAT 0 TOT
.  00000025:  71 36 6c 21 2c 09 00 00 00                      TS 39395093558
.  0000002e:  49 00                                           LD
.  00000030:  b2 80 3c 29 0f 00 00 ff ff                      VA 0xffff00000f293c80
.  00000039:  b3 80 ec 24 fb 00 00 00 80                      PA 0xfb24ec80 ns=1
.  00000042:  9a 00 00                                        LAT 0 XLAT
.  00000045:  42 16                                           EV RETIRED L1D-ACCESS TLB-ACCESS
.  00000047:  b0 f4 11 16 08 00 00 ff ff                      PC 0xff0000081611f4 el3 ns=1
.  00000050:  98 00 00                                        LAT 0 TOT
.  00000053:  71 36 6c 21 2c 09 00 00 00                      TS 39395093558
.  0000005c:  48 00                                           INSN-OTHER
.  0000005e:  42 02                                           EV RETIRED
.  00000060:  b0 2c ef 7f 08 00 00 ff ff                      PC 0xff0000087fef2c el3 ns=1
.  00000069:  98 00 00                                        LAT 0 TOT
.  0000006c:  71 d1 6f 21 2c 09 00 00 00                      TS 39395094481
...

Other release notes:

- applies to acme's perf/{core,urgent} branches, likely elsewhere

- Report is self-contained within the tool.
  Record requires enabling the kernel SPE driver by
  setting CONFIG_ARM_SPE_PMU.

- The intel-bts implementation was used as a starting point; its
  min/default/max buffer sizes and power of 2 pages granularity need to be
  revisited for ARM SPE

- Recording across multiple SPE clusters/domains not supported

- Snapshot support (record -S), and conversion to native perf events
  (e.g., via 'perf inject --itrace'), are also not supported

- Technically both cs-etm and spe can be used simultaneously, however
  disabled for simplicity in this release

Reviewed-by: Dongjiu Geng <gengdongjiu@huawei.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Signed-off-by: Kim Phillips <kim.phillips@arm.com>
---
v6: - removed unused arm_spe_update_queues() (not used in raw dump)
    - renamed 'index' to 'idx' in arm_spe_pkt_desc() to fix ubuntu 12.04.5 build.
    - used C style comments for SPDX identifier in new header files,
      as prescribed in the upcoming Documentation/process/license-rules.rst

v5: added Dongjiu's reviewed-by, addressed Adrian's comments:
    - Codingstyle fix for perf_pmu__get_default_config()
    - fixed building for aarch32 (arch=arm):
      - protected arm_spe_pmu_default_config and arm_spe_pmu_default_config
        callsites with __aarch64__ (SPE is not architecturally defined for
	Aarch32).
      - changed arm_spe_get_alignment()'s uint64_t cast to uintptr_t
    - SPDX License identifiers for new files
    - removed unneeded #include tsc.h
    - removed unused struct auxtrace_record and struct perf_tool decls

v4: rebased onto acme's perf/core, whitespace fixes.

v3: trying to address comments from v2:

- despite adding a find_all_arm_spe_pmus() function to scan for all
  arm_spe_<n> device instances, in order to ensure auxtrace_record__init
  successfully matches the evsel type with the correct arm_spe_pmu type,
  I am still having trouble running in multi-SPE PPI (heterogeneous)
  environments (mmap fails with EOPNOTSUPP, as does running with
  --per-thread on homogeneous systems).

- arm_spe_reference: use gettime instead of direct cntvct register access

- spe-decoder: add a comment for why SPE_EVENTS code sets packet->index.

- added arm_spe_pmu_default_config that accesses the driver
  caps/min_interval and sets the default sampling period to it.  This way
  users don't have to specify -c explicitly.  Also set is_uncore to false.

- set more sampling bits in the arm_spe and its tracking evsel.  Still
  unsure if too liberal, and not sure whether it needs another context
  switch tracking evsel.  Comments welcome!

- https://www.spinics.net/lists/arm-kernel/msg614361.html

v2: mostly addressing Mark Rutland's comments as much as possible without his
feedback to my feedback:

- decoder refactored with a get_payload, not extended to with-ext_len ones like
  get_addr,  named the constants

- 0x-ified %x output formats, but decided to not sign extend the addresses in
  the raw dump, rather do so if necessary in the synthesis stage:
  SPE implementations differ in this area, and raw dump should reflect that.

- CPU mask / new record behaviour bisected to commit e3ba76deef23064 "perf
  tools: Force uncore events to system wide monitoring".  Waiting to hear back
  on why driver can't do system wide monitoring, even across PPIs, by e.g.,
  sharing the SPE interrupts in one handler (SPE's don't differ in this record
  regard).

- addressed off-list comment from M. Williams:
  "Instruction Type" packet was renamed as "Operation Type".
   so in the spe packet decoder: INSN_TYPE -> OP_TYPE

- do_get_packet fixed to handle excessive, successive PADding from a new source
  of raw SPE data, so instead of:

	.  000011ae:  00                                              PAD
	.  000011af:  00                                              PAD
	.  000011b0:  00                                              PAD
	.  000011b1:  00                                              PAD
	.  000011b2:  00                                              PAD
	.  000011b3:  00                                              PAD
	.  000011b4:  00                                              PAD
	.  000011b5:  00                                              PAD
	.  000011b6:  00                                              PAD

  we now get:

	.  000011ae:  00 00 00 00 00 00 00 00 00                      PAD

- fixed 52 00 00 decoded with an empty events clause, adding 'EV' for all events
  clauses now.  parser writers can detect for empty event clauses by finding
  nothing after it.

 tools/perf/arch/arm/util/auxtrace.c   |  77 +++++-
 tools/perf/arch/arm/util/pmu.c        |   6 +
 tools/perf/arch/arm64/util/Build      |   3 +-
 tools/perf/arch/arm64/util/arm-spe.c  | 225 +++++++++++++++++
 tools/perf/util/Build                 |   2 +
 tools/perf/util/arm-spe-pkt-decoder.c | 462 ++++++++++++++++++++++++++++++++++
 tools/perf/util/arm-spe-pkt-decoder.h |  43 ++++
 tools/perf/util/arm-spe.c             | 231 +++++++++++++++++
 tools/perf/util/arm-spe.h             |  31 +++
 tools/perf/util/auxtrace.c            |   3 +
 tools/perf/util/auxtrace.h            |   1 +
 11 files changed, 1077 insertions(+), 7 deletions(-)
 create mode 100644 tools/perf/arch/arm64/util/arm-spe.c
 create mode 100644 tools/perf/util/arm-spe-pkt-decoder.c
 create mode 100644 tools/perf/util/arm-spe-pkt-decoder.h
 create mode 100644 tools/perf/util/arm-spe.c
 create mode 100644 tools/perf/util/arm-spe.h

diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c
index 8edf2cb71564..2323581b157d 100644
--- a/tools/perf/arch/arm/util/auxtrace.c
+++ b/tools/perf/arch/arm/util/auxtrace.c
@@ -22,6 +22,42 @@
 #include "../../util/evlist.h"
 #include "../../util/pmu.h"
 #include "cs-etm.h"
+#include "arm-spe.h"
+
+static struct perf_pmu **find_all_arm_spe_pmus(int *nr_spes, int *err)
+{
+	struct perf_pmu **arm_spe_pmus = NULL;
+	int ret, i, nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
+	/* arm_spe_xxxxxxxxx\0 */
+	char arm_spe_pmu_name[sizeof(ARM_SPE_PMU_NAME) + 10];
+
+	arm_spe_pmus = zalloc(sizeof(struct perf_pmu *) * nr_cpus);
+	if (!arm_spe_pmus) {
+		pr_err("spes alloc failed\n");
+		*err = -ENOMEM;
+		return NULL;
+	}
+
+	for (i = 0; i < nr_cpus; i++) {
+		ret = sprintf(arm_spe_pmu_name, "%s%d", ARM_SPE_PMU_NAME, i);
+		if (ret < 0) {
+			pr_err("sprintf failed\n");
+			*err = -ENOMEM;
+			return NULL;
+		}
+
+		arm_spe_pmus[*nr_spes] = perf_pmu__find(arm_spe_pmu_name);
+		if (arm_spe_pmus[*nr_spes]) {
+			pr_debug2("%s %d: arm_spe_pmu %d type %d name %s\n",
+				 __func__, __LINE__, *nr_spes,
+				 arm_spe_pmus[*nr_spes]->type,
+				 arm_spe_pmus[*nr_spes]->name);
+			(*nr_spes)++;
+		}
+	}
+
+	return arm_spe_pmus;
+}
 
 struct auxtrace_record
 *auxtrace_record__init(struct perf_evlist *evlist, int *err)
@@ -29,22 +65,51 @@ struct auxtrace_record
 	struct perf_pmu	*cs_etm_pmu;
 	struct perf_evsel *evsel;
 	bool found_etm = false;
+	bool found_spe = false;
+	static struct perf_pmu **arm_spe_pmus = NULL;
+	static int nr_spes = 0;
+	int i;
+
+	if (!evlist)
+		return NULL;
 
 	cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
 
-	if (evlist) {
-		evlist__for_each_entry(evlist, evsel) {
-			if (cs_etm_pmu &&
-			    evsel->attr.type == cs_etm_pmu->type)
-				found_etm = true;
+	if (!arm_spe_pmus)
+		arm_spe_pmus = find_all_arm_spe_pmus(&nr_spes, err);
+
+	evlist__for_each_entry(evlist, evsel) {
+		if (cs_etm_pmu &&
+		    evsel->attr.type == cs_etm_pmu->type)
+			found_etm = true;
+
+		if (!nr_spes)
+			continue;
+
+		for (i = 0; i < nr_spes; i++) {
+			if (evsel->attr.type == arm_spe_pmus[i]->type) {
+				found_spe = true;
+				break;
+			}
 		}
 	}
 
+	if (found_etm && found_spe) {
+		pr_err("Concurrent ARM Coresight ETM and SPE operation not currently supported\n");
+		*err = -EOPNOTSUPP;
+		return NULL;
+	}
+
 	if (found_etm)
 		return cs_etm_record_init(err);
 
+#if defined(__aarch64__)
+	if (found_spe)
+		return arm_spe_recording_init(err, arm_spe_pmus[i]);
+#endif
+
 	/*
-	 * Clear 'err' even if we haven't found a cs_etm event - that way perf
+	 * Clear 'err' even if we haven't found an event - that way perf
 	 * record can still be used even if tracers aren't present.  The NULL
 	 * return value will take care of telling the infrastructure HW tracing
 	 * isn't available.
diff --git a/tools/perf/arch/arm/util/pmu.c b/tools/perf/arch/arm/util/pmu.c
index 98d67399a0d6..ac4dffc807b8 100644
--- a/tools/perf/arch/arm/util/pmu.c
+++ b/tools/perf/arch/arm/util/pmu.c
@@ -20,6 +20,7 @@
 #include <linux/perf_event.h>
 
 #include "cs-etm.h"
+#include "arm-spe.h"
 #include "../../util/pmu.h"
 
 struct perf_event_attr
@@ -30,7 +31,12 @@ struct perf_event_attr
 		/* add ETM default config here */
 		pmu->selectable = true;
 		pmu->set_drv_config = cs_etm_set_drv_config;
+#if defined(__aarch64__)
+	} else if (strstarts(pmu->name, ARM_SPE_PMU_NAME)) {
+		return arm_spe_pmu_default_config(pmu);
+#endif
 	}
+
 #endif
 	return NULL;
 }
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
index cef6fb38d17e..f9969bb88ccb 100644
--- a/tools/perf/arch/arm64/util/Build
+++ b/tools/perf/arch/arm64/util/Build
@@ -3,4 +3,5 @@ libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
 
 libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
 			      ../../arm/util/auxtrace.o \
-			      ../../arm/util/cs-etm.o
+			      ../../arm/util/cs-etm.o \
+			      arm-spe.o
diff --git a/tools/perf/arch/arm64/util/arm-spe.c b/tools/perf/arch/arm64/util/arm-spe.c
new file mode 100644
index 000000000000..1120e39c1b00
--- /dev/null
+++ b/tools/perf/arch/arm64/util/arm-spe.c
@@ -0,0 +1,225 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Arm Statistical Profiling Extensions (SPE) support
+ * Copyright (c) 2017-2018, Arm Ltd.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/log2.h>
+#include <time.h>
+
+#include "../../util/cpumap.h"
+#include "../../util/evsel.h"
+#include "../../util/evlist.h"
+#include "../../util/session.h"
+#include "../../util/util.h"
+#include "../../util/pmu.h"
+#include "../../util/debug.h"
+#include "../../util/auxtrace.h"
+#include "../../util/arm-spe.h"
+
+#define KiB(x) ((x) * 1024)
+#define MiB(x) ((x) * 1024 * 1024)
+
+struct arm_spe_recording {
+	struct auxtrace_record		itr;
+	struct perf_pmu			*arm_spe_pmu;
+	struct perf_evlist		*evlist;
+};
+
+static size_t
+arm_spe_info_priv_size(struct auxtrace_record *itr __maybe_unused,
+		       struct perf_evlist *evlist __maybe_unused)
+{
+	return ARM_SPE_AUXTRACE_PRIV_SIZE;
+}
+
+static int arm_spe_info_fill(struct auxtrace_record *itr,
+			     struct perf_session *session,
+			     struct auxtrace_info_event *auxtrace_info,
+			     size_t priv_size)
+{
+	struct arm_spe_recording *sper =
+			container_of(itr, struct arm_spe_recording, itr);
+	struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu;
+
+	if (priv_size != ARM_SPE_AUXTRACE_PRIV_SIZE)
+		return -EINVAL;
+
+	if (!session->evlist->nr_mmaps)
+		return -EINVAL;
+
+	auxtrace_info->type = PERF_AUXTRACE_ARM_SPE;
+	auxtrace_info->priv[ARM_SPE_PMU_TYPE] = arm_spe_pmu->type;
+
+	return 0;
+}
+
+static int arm_spe_recording_options(struct auxtrace_record *itr,
+				     struct perf_evlist *evlist,
+				     struct record_opts *opts)
+{
+	struct arm_spe_recording *sper =
+			container_of(itr, struct arm_spe_recording, itr);
+	struct perf_pmu *arm_spe_pmu = sper->arm_spe_pmu;
+	struct perf_evsel *evsel, *arm_spe_evsel = NULL;
+	bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
+	struct perf_evsel *tracking_evsel;
+	int err;
+
+	sper->evlist = evlist;
+
+	evlist__for_each_entry(evlist, evsel) {
+		if (evsel->attr.type == arm_spe_pmu->type) {
+			if (arm_spe_evsel) {
+				pr_err("There may be only one " ARM_SPE_PMU_NAME "x event\n");
+				return -EINVAL;
+			}
+			evsel->attr.freq = 0;
+			evsel->attr.sample_period = 1;
+			arm_spe_evsel = evsel;
+			opts->full_auxtrace = true;
+		}
+	}
+
+	if (!opts->full_auxtrace)
+		return 0;
+
+	/* We are in full trace mode but '-m,xyz' wasn't specified */
+	if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) {
+		if (privileged) {
+			opts->auxtrace_mmap_pages = MiB(4) / page_size;
+		} else {
+			opts->auxtrace_mmap_pages = KiB(128) / page_size;
+			if (opts->mmap_pages == UINT_MAX)
+				opts->mmap_pages = KiB(256) / page_size;
+		}
+	}
+
+	/* Validate auxtrace_mmap_pages */
+	if (opts->auxtrace_mmap_pages) {
+		size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size;
+		size_t min_sz = KiB(8);
+
+		if (sz < min_sz || !is_power_of_2(sz)) {
+			pr_err("Invalid mmap size for ARM SPE: must be@least %zuKiB and a power of 2\n",
+			       min_sz / 1024);
+			return -EINVAL;
+		}
+	}
+
+
+	/*
+	 * To obtain the auxtrace buffer file descriptor, the auxtrace event
+	 * must come first.
+	 */
+	perf_evlist__to_front(evlist, arm_spe_evsel);
+
+	perf_evsel__set_sample_bit(arm_spe_evsel, CPU);
+	perf_evsel__set_sample_bit(arm_spe_evsel, TIME);
+	perf_evsel__set_sample_bit(arm_spe_evsel, TID);
+
+	/* Add dummy event to keep tracking */
+	err = parse_events(evlist, "dummy:u", NULL);
+	if (err)
+		return err;
+
+	tracking_evsel = perf_evlist__last(evlist);
+	perf_evlist__set_tracking_event(evlist, tracking_evsel);
+
+	tracking_evsel->attr.freq = 0;
+	tracking_evsel->attr.sample_period = 1;
+	perf_evsel__set_sample_bit(tracking_evsel, TIME);
+	perf_evsel__set_sample_bit(tracking_evsel, CPU);
+	perf_evsel__reset_sample_bit(tracking_evsel, BRANCH_STACK);
+
+	return 0;
+}
+
+static u64 arm_spe_reference(struct auxtrace_record *itr __maybe_unused)
+{
+	struct timespec ts;
+
+	clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+
+	return ts.tv_sec ^ ts.tv_nsec;
+}
+
+static void arm_spe_recording_free(struct auxtrace_record *itr)
+{
+	struct arm_spe_recording *sper =
+			container_of(itr, struct arm_spe_recording, itr);
+
+	free(sper);
+}
+
+static int arm_spe_read_finish(struct auxtrace_record *itr, int idx)
+{
+	struct arm_spe_recording *sper =
+			container_of(itr, struct arm_spe_recording, itr);
+	struct perf_evsel *evsel;
+
+	evlist__for_each_entry(sper->evlist, evsel) {
+		if (evsel->attr.type == sper->arm_spe_pmu->type)
+			return perf_evlist__enable_event_idx(sper->evlist,
+							     evsel, idx);
+	}
+	return -EINVAL;
+}
+
+struct auxtrace_record *arm_spe_recording_init(int *err,
+					       struct perf_pmu *arm_spe_pmu)
+{
+	struct arm_spe_recording *sper;
+
+	if (!arm_spe_pmu) {
+		*err = -ENODEV;
+		return NULL;
+	}
+
+	sper = zalloc(sizeof(struct arm_spe_recording));
+	if (!sper) {
+		*err = -ENOMEM;
+		return NULL;
+	}
+
+	sper->arm_spe_pmu = arm_spe_pmu;
+	sper->itr.recording_options = arm_spe_recording_options;
+	sper->itr.info_priv_size = arm_spe_info_priv_size;
+	sper->itr.info_fill = arm_spe_info_fill;
+	sper->itr.free = arm_spe_recording_free;
+	sper->itr.reference = arm_spe_reference;
+	sper->itr.read_finish = arm_spe_read_finish;
+	sper->itr.alignment = 0;
+
+	return &sper->itr;
+}
+
+struct perf_event_attr
+*arm_spe_pmu_default_config(struct perf_pmu *arm_spe_pmu)
+{
+	struct perf_event_attr *attr;
+
+	attr = zalloc(sizeof(struct perf_event_attr));
+	if (!attr) {
+		pr_err("arm_spe default config cannot allocate a perf_event_attr\n");
+		return NULL;
+	}
+
+	/*
+	 * If kernel driver doesn't advertise a minimum,
+	 * use max allowable by PMSIDR_EL1.INTERVAL
+	 */
+	if (perf_pmu__scan_file(arm_spe_pmu, "caps/min_interval", "%llu",
+				  &attr->sample_period) != 1) {
+		pr_debug("arm_spe driver doesn't advertise a min. interval. Using 4096\n");
+		attr->sample_period = 4096;
+	}
+
+	arm_spe_pmu->selectable = true;
+	arm_spe_pmu->is_uncore = false;
+
+	return attr;
+}
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index a3de7916fe63..7c6a8b461e24 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -86,6 +86,8 @@ libperf-$(CONFIG_AUXTRACE) += auxtrace.o
 libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
 libperf-$(CONFIG_AUXTRACE) += intel-pt.o
 libperf-$(CONFIG_AUXTRACE) += intel-bts.o
+libperf-$(CONFIG_AUXTRACE) += arm-spe.o
+libperf-$(CONFIG_AUXTRACE) += arm-spe-pkt-decoder.o
 libperf-y += parse-branch-options.o
 libperf-y += dump-insn.o
 libperf-y += parse-regs-options.o
diff --git a/tools/perf/util/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-pkt-decoder.c
new file mode 100644
index 000000000000..b94001b756c7
--- /dev/null
+++ b/tools/perf/util/arm-spe-pkt-decoder.c
@@ -0,0 +1,462 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Arm Statistical Profiling Extensions (SPE) support
+ * Copyright (c) 2017-2018, Arm Ltd.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <endian.h>
+#include <byteswap.h>
+
+#include "arm-spe-pkt-decoder.h"
+
+#define BIT(n)		(1ULL << (n))
+
+#define NS_FLAG		BIT(63)
+#define EL_FLAG		(BIT(62) | BIT(61))
+
+#define SPE_HEADER0_PAD			0x0
+#define SPE_HEADER0_END			0x1
+#define SPE_HEADER0_ADDRESS		0x30 /* address packet (short) */
+#define SPE_HEADER0_ADDRESS_MASK	0x38
+#define SPE_HEADER0_COUNTER		0x18 /* counter packet (short) */
+#define SPE_HEADER0_COUNTER_MASK	0x38
+#define SPE_HEADER0_TIMESTAMP		0x71
+#define SPE_HEADER0_TIMESTAMP		0x71
+#define SPE_HEADER0_EVENTS		0x2
+#define SPE_HEADER0_EVENTS_MASK		0xf
+#define SPE_HEADER0_SOURCE		0x3
+#define SPE_HEADER0_SOURCE_MASK		0xf
+#define SPE_HEADER0_CONTEXT		0x24
+#define SPE_HEADER0_CONTEXT_MASK	0x3c
+#define SPE_HEADER0_OP_TYPE		0x8
+#define SPE_HEADER0_OP_TYPE_MASK	0x3c
+#define SPE_HEADER1_ALIGNMENT		0x0
+#define SPE_HEADER1_ADDRESS		0xb0 /* address packet (extended) */
+#define SPE_HEADER1_ADDRESS_MASK	0xf8
+#define SPE_HEADER1_COUNTER		0x98 /* counter packet (extended) */
+#define SPE_HEADER1_COUNTER_MASK	0xf8
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define le16_to_cpu bswap_16
+#define le32_to_cpu bswap_32
+#define le64_to_cpu bswap_64
+#define memcpy_le64(d, s, n) do { \
+	memcpy((d), (s), (n));    \
+	*(d) = le64_to_cpu(*(d)); \
+} while (0)
+#else
+#define le16_to_cpu
+#define le32_to_cpu
+#define le64_to_cpu
+#define memcpy_le64 memcpy
+#endif
+
+static const char * const arm_spe_packet_name[] = {
+	[ARM_SPE_PAD]		= "PAD",
+	[ARM_SPE_END]		= "END",
+	[ARM_SPE_TIMESTAMP]	= "TS",
+	[ARM_SPE_ADDRESS]	= "ADDR",
+	[ARM_SPE_COUNTER]	= "LAT",
+	[ARM_SPE_CONTEXT]	= "CONTEXT",
+	[ARM_SPE_OP_TYPE]	= "OP-TYPE",
+	[ARM_SPE_EVENTS]	= "EVENTS",
+	[ARM_SPE_DATA_SOURCE]	= "DATA-SOURCE",
+};
+
+const char *arm_spe_pkt_name(enum arm_spe_pkt_type type)
+{
+	return arm_spe_packet_name[type];
+}
+
+/* return ARM SPE payload size from its encoding,
+ * which is in bits 5:4 of the byte.
+ * 00 : byte
+ * 01 : halfword (2)
+ * 10 : word (4)
+ * 11 : doubleword (8)
+ */
+static int payloadlen(unsigned char byte)
+{
+	return 1 << ((byte & 0x30) >> 4);
+}
+
+static int arm_spe_get_payload(const unsigned char *buf, size_t len,
+			       struct arm_spe_pkt *packet)
+{
+	size_t payload_len = payloadlen(buf[0]);
+
+	if (len < 1 + payload_len)
+		return ARM_SPE_NEED_MORE_BYTES;
+
+	buf++;
+
+	switch (payload_len) {
+	case 1: packet->payload = *(uint8_t *)buf; break;
+	case 2: packet->payload = le16_to_cpu(*(uint16_t *)buf); break;
+	case 4: packet->payload = le32_to_cpu(*(uint32_t *)buf); break;
+	case 8: packet->payload = le64_to_cpu(*(uint64_t *)buf); break;
+	default: return ARM_SPE_BAD_PACKET;
+	}
+
+	return 1 + payload_len;
+}
+
+static int arm_spe_get_pad(struct arm_spe_pkt *packet)
+{
+	packet->type = ARM_SPE_PAD;
+	return 1;
+}
+
+static int arm_spe_get_alignment(const unsigned char *buf, size_t len,
+				 struct arm_spe_pkt *packet)
+{
+	unsigned int alignment = 1 << ((buf[0] & 0xf) + 1);
+
+	if (len < alignment)
+		return ARM_SPE_NEED_MORE_BYTES;
+
+	packet->type = ARM_SPE_PAD;
+	return alignment - (((uintptr_t)buf) & (alignment - 1));
+}
+
+static int arm_spe_get_end(struct arm_spe_pkt *packet)
+{
+	packet->type = ARM_SPE_END;
+	return 1;
+}
+
+static int arm_spe_get_timestamp(const unsigned char *buf, size_t len,
+				 struct arm_spe_pkt *packet)
+{
+	packet->type = ARM_SPE_TIMESTAMP;
+	return arm_spe_get_payload(buf, len, packet);
+}
+
+static int arm_spe_get_events(const unsigned char *buf, size_t len,
+			      struct arm_spe_pkt *packet)
+{
+	int ret = arm_spe_get_payload(buf, len, packet);
+
+	packet->type = ARM_SPE_EVENTS;
+
+	/* we use index to identify Events with a less number of
+	 * comparisons in arm_spe_pkt_desc(): E.g., the LLC-ACCESS,
+	 * LLC-REFILL, and REMOTE-ACCESS events are identified iff
+	 * index > 1.
+	 */
+	packet->index = ret - 1;
+
+	return ret;
+}
+
+static int arm_spe_get_data_source(const unsigned char *buf, size_t len,
+				   struct arm_spe_pkt *packet)
+{
+	packet->type = ARM_SPE_DATA_SOURCE;
+	return arm_spe_get_payload(buf, len, packet);
+}
+
+static int arm_spe_get_context(const unsigned char *buf, size_t len,
+			       struct arm_spe_pkt *packet)
+{
+	packet->type = ARM_SPE_CONTEXT;
+	packet->index = buf[0] & 0x3;
+
+	return arm_spe_get_payload(buf, len, packet);
+}
+
+static int arm_spe_get_op_type(const unsigned char *buf, size_t len,
+			       struct arm_spe_pkt *packet)
+{
+	packet->type = ARM_SPE_OP_TYPE;
+	packet->index = buf[0] & 0x3;
+	return arm_spe_get_payload(buf, len, packet);
+}
+
+static int arm_spe_get_counter(const unsigned char *buf, size_t len,
+			       const unsigned char ext_hdr, struct arm_spe_pkt *packet)
+{
+	if (len < 2)
+		return ARM_SPE_NEED_MORE_BYTES;
+
+	packet->type = ARM_SPE_COUNTER;
+	if (ext_hdr)
+		packet->index = ((buf[0] & 0x3) << 3) | (buf[1] & 0x7);
+	else
+		packet->index = buf[0] & 0x7;
+
+	packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
+
+	return 1 + ext_hdr + 2;
+}
+
+static int arm_spe_get_addr(const unsigned char *buf, size_t len,
+			    const unsigned char ext_hdr, struct arm_spe_pkt *packet)
+{
+	if (len < 8)
+		return ARM_SPE_NEED_MORE_BYTES;
+
+	packet->type = ARM_SPE_ADDRESS;
+	if (ext_hdr)
+		packet->index = ((buf[0] & 0x3) << 3) | (buf[1] & 0x7);
+	else
+		packet->index = buf[0] & 0x7;
+
+	memcpy_le64(&packet->payload, buf + 1, 8);
+
+	return 1 + ext_hdr + 8;
+}
+
+static int arm_spe_do_get_packet(const unsigned char *buf, size_t len,
+				 struct arm_spe_pkt *packet)
+{
+	unsigned int byte;
+
+	memset(packet, 0, sizeof(struct arm_spe_pkt));
+
+	if (!len)
+		return ARM_SPE_NEED_MORE_BYTES;
+
+	byte = buf[0];
+	if (byte == SPE_HEADER0_PAD)
+		return arm_spe_get_pad(packet);
+	else if (byte == SPE_HEADER0_END) /* no timestamp at end of record */
+		return arm_spe_get_end(packet);
+	else if (byte & 0xc0 /* 0y11xxxxxx */) {
+		if (byte & 0x80) {
+			if ((byte & SPE_HEADER0_ADDRESS_MASK) == SPE_HEADER0_ADDRESS)
+				return arm_spe_get_addr(buf, len, 0, packet);
+			if ((byte & SPE_HEADER0_COUNTER_MASK) == SPE_HEADER0_COUNTER)
+				return arm_spe_get_counter(buf, len, 0, packet);
+		} else
+			if (byte == SPE_HEADER0_TIMESTAMP)
+				return arm_spe_get_timestamp(buf, len, packet);
+			else if ((byte & SPE_HEADER0_EVENTS_MASK) == SPE_HEADER0_EVENTS)
+				return arm_spe_get_events(buf, len, packet);
+			else if ((byte & SPE_HEADER0_SOURCE_MASK) == SPE_HEADER0_SOURCE)
+				return arm_spe_get_data_source(buf, len, packet);
+			else if ((byte & SPE_HEADER0_CONTEXT_MASK) == SPE_HEADER0_CONTEXT)
+				return arm_spe_get_context(buf, len, packet);
+			else if ((byte & SPE_HEADER0_OP_TYPE_MASK) == SPE_HEADER0_OP_TYPE)
+				return arm_spe_get_op_type(buf, len, packet);
+	} else if ((byte & 0xe0) == 0x20 /* 0y001xxxxx */) {
+		/* 16-bit header */
+		byte = buf[1];
+		if (byte == SPE_HEADER1_ALIGNMENT)
+			return arm_spe_get_alignment(buf, len, packet);
+		else if ((byte & SPE_HEADER1_ADDRESS_MASK) == SPE_HEADER1_ADDRESS)
+			return arm_spe_get_addr(buf, len, 1, packet);
+		else if ((byte & SPE_HEADER1_COUNTER_MASK) == SPE_HEADER1_COUNTER)
+			return arm_spe_get_counter(buf, len, 1, packet);
+	}
+
+	return ARM_SPE_BAD_PACKET;
+}
+
+int arm_spe_get_packet(const unsigned char *buf, size_t len,
+		       struct arm_spe_pkt *packet)
+{
+	int ret;
+
+	ret = arm_spe_do_get_packet(buf, len, packet);
+	/* put multiple consecutive PADs on the same line, up to
+	 * the fixed-width output format of 16 bytes per line.
+	 */
+	if (ret > 0 && packet->type == ARM_SPE_PAD) {
+		while (ret < 16 && len > (size_t)ret && !buf[ret])
+			ret += 1;
+	}
+	return ret;
+}
+
+int arm_spe_pkt_desc(const struct arm_spe_pkt *packet, char *buf,
+		     size_t buf_len)
+{
+	int ret, ns, el, idx = packet->index;
+	unsigned long long payload = packet->payload;
+	const char *name = arm_spe_pkt_name(packet->type);
+
+	switch (packet->type) {
+	case ARM_SPE_BAD:
+	case ARM_SPE_PAD:
+	case ARM_SPE_END:
+		return snprintf(buf, buf_len, "%s", name);
+	case ARM_SPE_EVENTS: {
+		size_t blen = buf_len;
+
+		ret = 0;
+		ret = snprintf(buf, buf_len, "EV");
+		buf += ret;
+		blen -= ret;
+		if (payload & 0x1) {
+			ret = snprintf(buf, buf_len, " EXCEPTION-GEN");
+			buf += ret;
+			blen -= ret;
+		}
+		if (payload & 0x2) {
+			ret = snprintf(buf, buf_len, " RETIRED");
+			buf += ret;
+			blen -= ret;
+		}
+		if (payload & 0x4) {
+			ret = snprintf(buf, buf_len, " L1D-ACCESS");
+			buf += ret;
+			blen -= ret;
+		}
+		if (payload & 0x8) {
+			ret = snprintf(buf, buf_len, " L1D-REFILL");
+			buf += ret;
+			blen -= ret;
+		}
+		if (payload & 0x10) {
+			ret = snprintf(buf, buf_len, " TLB-ACCESS");
+			buf += ret;
+			blen -= ret;
+		}
+		if (payload & 0x20) {
+			ret = snprintf(buf, buf_len, " TLB-REFILL");
+			buf += ret;
+			blen -= ret;
+		}
+		if (payload & 0x40) {
+			ret = snprintf(buf, buf_len, " NOT-TAKEN");
+			buf += ret;
+			blen -= ret;
+		}
+		if (payload & 0x80) {
+			ret = snprintf(buf, buf_len, " MISPRED");
+			buf += ret;
+			blen -= ret;
+		}
+		if (idx > 1) {
+			if (payload & 0x100) {
+				ret = snprintf(buf, buf_len, " LLC-ACCESS");
+				buf += ret;
+				blen -= ret;
+			}
+			if (payload & 0x200) {
+				ret = snprintf(buf, buf_len, " LLC-REFILL");
+				buf += ret;
+				blen -= ret;
+			}
+			if (payload & 0x400) {
+				ret = snprintf(buf, buf_len, " REMOTE-ACCESS");
+				buf += ret;
+				blen -= ret;
+			}
+		}
+		if (ret < 0)
+			return ret;
+		blen -= ret;
+		return buf_len - blen;
+	}
+	case ARM_SPE_OP_TYPE:
+		switch (idx) {
+		case 0:	return snprintf(buf, buf_len, "%s", payload & 0x1 ?
+					"COND-SELECT" : "INSN-OTHER");
+		case 1:	{
+			size_t blen = buf_len;
+
+			if (payload & 0x1)
+				ret = snprintf(buf, buf_len, "ST");
+			else
+				ret = snprintf(buf, buf_len, "LD");
+			buf += ret;
+			blen -= ret;
+			if (payload & 0x2) {
+				if (payload & 0x4) {
+					ret = snprintf(buf, buf_len, " AT");
+					buf += ret;
+					blen -= ret;
+				}
+				if (payload & 0x8) {
+					ret = snprintf(buf, buf_len, " EXCL");
+					buf += ret;
+					blen -= ret;
+				}
+				if (payload & 0x10) {
+					ret = snprintf(buf, buf_len, " AR");
+					buf += ret;
+					blen -= ret;
+				}
+			} else if (payload & 0x4) {
+				ret = snprintf(buf, buf_len, " SIMD-FP");
+				buf += ret;
+				blen -= ret;
+			}
+			if (ret < 0)
+				return ret;
+			blen -= ret;
+			return buf_len - blen;
+		}
+		case 2:	{
+			size_t blen = buf_len;
+
+			ret = snprintf(buf, buf_len, "B");
+			buf += ret;
+			blen -= ret;
+			if (payload & 0x1) {
+				ret = snprintf(buf, buf_len, " COND");
+				buf += ret;
+				blen -= ret;
+			}
+			if (payload & 0x2) {
+				ret = snprintf(buf, buf_len, " IND");
+				buf += ret;
+				blen -= ret;
+			}
+			if (ret < 0)
+				return ret;
+			blen -= ret;
+			return buf_len - blen;
+			}
+		default: return 0;
+		}
+	case ARM_SPE_DATA_SOURCE:
+	case ARM_SPE_TIMESTAMP:
+		return snprintf(buf, buf_len, "%s %lld", name, payload);
+	case ARM_SPE_ADDRESS:
+		switch (idx) {
+		case 0:
+		case 1: ns = !!(packet->payload & NS_FLAG);
+			el = (packet->payload & EL_FLAG) >> 61;
+			payload &= ~(0xffULL << 56);
+			return snprintf(buf, buf_len, "%s 0x%llx el%d ns=%d",
+				        (idx == 1) ? "TGT" : "PC", payload, el, ns);
+		case 2:	return snprintf(buf, buf_len, "VA 0x%llx", payload);
+		case 3:	ns = !!(packet->payload & NS_FLAG);
+			payload &= ~(0xffULL << 56);
+			return snprintf(buf, buf_len, "PA 0x%llx ns=%d",
+					payload, ns);
+		default: return 0;
+		}
+	case ARM_SPE_CONTEXT:
+		return snprintf(buf, buf_len, "%s 0x%lx el%d", name,
+				(unsigned long)payload, idx + 1);
+	case ARM_SPE_COUNTER: {
+		size_t blen = buf_len;
+
+		ret = snprintf(buf, buf_len, "%s %d ", name,
+			       (unsigned short)payload);
+		buf += ret;
+		blen -= ret;
+		switch (idx) {
+		case 0:	ret = snprintf(buf, buf_len, "TOT"); break;
+		case 1:	ret = snprintf(buf, buf_len, "ISSUE"); break;
+		case 2:	ret = snprintf(buf, buf_len, "XLAT"); break;
+		default: ret = 0;
+		}
+		if (ret < 0)
+			return ret;
+		blen -= ret;
+		return buf_len - blen;
+	}
+	default:
+		break;
+	}
+
+	return snprintf(buf, buf_len, "%s 0x%llx (%d)",
+			name, payload, packet->index);
+}
diff --git a/tools/perf/util/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-pkt-decoder.h
new file mode 100644
index 000000000000..d786ef65113f
--- /dev/null
+++ b/tools/perf/util/arm-spe-pkt-decoder.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Arm Statistical Profiling Extensions (SPE) support
+ * Copyright (c) 2017-2018, Arm Ltd.
+ */
+
+#ifndef INCLUDE__ARM_SPE_PKT_DECODER_H__
+#define INCLUDE__ARM_SPE_PKT_DECODER_H__
+
+#include <stddef.h>
+#include <stdint.h>
+
+#define ARM_SPE_PKT_DESC_MAX		256
+
+#define ARM_SPE_NEED_MORE_BYTES		-1
+#define ARM_SPE_BAD_PACKET		-2
+
+enum arm_spe_pkt_type {
+	ARM_SPE_BAD,
+	ARM_SPE_PAD,
+	ARM_SPE_END,
+	ARM_SPE_TIMESTAMP,
+	ARM_SPE_ADDRESS,
+	ARM_SPE_COUNTER,
+	ARM_SPE_CONTEXT,
+	ARM_SPE_OP_TYPE,
+	ARM_SPE_EVENTS,
+	ARM_SPE_DATA_SOURCE,
+};
+
+struct arm_spe_pkt {
+	enum arm_spe_pkt_type	type;
+	unsigned char		index;
+	uint64_t		payload;
+};
+
+const char *arm_spe_pkt_name(enum arm_spe_pkt_type);
+
+int arm_spe_get_packet(const unsigned char *buf, size_t len,
+		       struct arm_spe_pkt *packet);
+
+int arm_spe_pkt_desc(const struct arm_spe_pkt *packet, char *buf, size_t len);
+#endif
diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
new file mode 100644
index 000000000000..6067267cc76c
--- /dev/null
+++ b/tools/perf/util/arm-spe.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Arm Statistical Profiling Extensions (SPE) support
+ * Copyright (c) 2017-2018, Arm Ltd.
+ */
+
+#include <endian.h>
+#include <errno.h>
+#include <byteswap.h>
+#include <inttypes.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/log2.h>
+
+#include "cpumap.h"
+#include "color.h"
+#include "evsel.h"
+#include "evlist.h"
+#include "machine.h"
+#include "session.h"
+#include "util.h"
+#include "thread.h"
+#include "debug.h"
+#include "auxtrace.h"
+#include "arm-spe.h"
+#include "arm-spe-pkt-decoder.h"
+
+struct arm_spe {
+	struct auxtrace			auxtrace;
+	struct auxtrace_queues		queues;
+	struct auxtrace_heap		heap;
+	u32				auxtrace_type;
+	struct perf_session		*session;
+	struct machine			*machine;
+	u32				pmu_type;
+};
+
+struct arm_spe_queue {
+	struct arm_spe		*spe;
+	unsigned int		queue_nr;
+	struct auxtrace_buffer	*buffer;
+	bool			on_heap;
+	bool			done;
+	pid_t			pid;
+	pid_t			tid;
+	int			cpu;
+};
+
+static void arm_spe_dump(struct arm_spe *spe __maybe_unused,
+			 unsigned char *buf, size_t len)
+{
+	struct arm_spe_pkt packet;
+	size_t pos = 0;
+	int ret, pkt_len, i;
+	char desc[ARM_SPE_PKT_DESC_MAX];
+	const char *color = PERF_COLOR_BLUE;
+
+	color_fprintf(stdout, color,
+		      ". ... ARM SPE data: size %zu bytes\n",
+		      len);
+
+	while (len) {
+		ret = arm_spe_get_packet(buf, len, &packet);
+		if (ret > 0)
+			pkt_len = ret;
+		else
+			pkt_len = 1;
+		printf(".");
+		color_fprintf(stdout, color, "  %08x: ", pos);
+		for (i = 0; i < pkt_len; i++)
+			color_fprintf(stdout, color, " %02x", buf[i]);
+		for (; i < 16; i++)
+			color_fprintf(stdout, color, "   ");
+		if (ret > 0) {
+			ret = arm_spe_pkt_desc(&packet, desc,
+					       ARM_SPE_PKT_DESC_MAX);
+			if (ret > 0)
+				color_fprintf(stdout, color, " %s\n", desc);
+		} else {
+			color_fprintf(stdout, color, " Bad packet!\n");
+		}
+		pos += pkt_len;
+		buf += pkt_len;
+		len -= pkt_len;
+	}
+}
+
+static void arm_spe_dump_event(struct arm_spe *spe, unsigned char *buf,
+			       size_t len)
+{
+	printf(".\n");
+	arm_spe_dump(spe, buf, len);
+}
+
+static int arm_spe_process_event(struct perf_session *session __maybe_unused,
+				 union perf_event *event __maybe_unused,
+				 struct perf_sample *sample __maybe_unused,
+				 struct perf_tool *tool __maybe_unused)
+{
+	return 0;
+}
+
+static int arm_spe_process_auxtrace_event(struct perf_session *session,
+					  union perf_event *event,
+					  struct perf_tool *tool __maybe_unused)
+{
+	struct arm_spe *spe = container_of(session->auxtrace, struct arm_spe,
+					     auxtrace);
+	struct auxtrace_buffer *buffer;
+	off_t data_offset;
+	int fd = perf_data__fd(session->data);
+	int err;
+
+	if (perf_data__is_pipe(session->data)) {
+		data_offset = 0;
+	} else {
+		data_offset = lseek(fd, 0, SEEK_CUR);
+		if (data_offset == -1)
+			return -errno;
+	}
+
+	err = auxtrace_queues__add_event(&spe->queues, session, event,
+					 data_offset, &buffer);
+	if (err)
+		return err;
+
+	/* Dump here now we have copied a piped trace out of the pipe */
+	if (dump_trace) {
+		if (auxtrace_buffer__get_data(buffer, fd)) {
+			arm_spe_dump_event(spe, buffer->data,
+					     buffer->size);
+			auxtrace_buffer__put_data(buffer);
+		}
+	}
+
+	return 0;
+}
+
+static int arm_spe_flush(struct perf_session *session __maybe_unused,
+			 struct perf_tool *tool __maybe_unused)
+{
+	return 0;
+}
+
+static void arm_spe_free_queue(void *priv)
+{
+	struct arm_spe_queue *speq = priv;
+
+	if (!speq)
+		return;
+	free(speq);
+}
+
+static void arm_spe_free_events(struct perf_session *session)
+{
+	struct arm_spe *spe = container_of(session->auxtrace, struct arm_spe,
+					     auxtrace);
+	struct auxtrace_queues *queues = &spe->queues;
+	unsigned int i;
+
+	for (i = 0; i < queues->nr_queues; i++) {
+		arm_spe_free_queue(queues->queue_array[i].priv);
+		queues->queue_array[i].priv = NULL;
+	}
+	auxtrace_queues__free(queues);
+}
+
+static void arm_spe_free(struct perf_session *session)
+{
+	struct arm_spe *spe = container_of(session->auxtrace, struct arm_spe,
+					     auxtrace);
+
+	auxtrace_heap__free(&spe->heap);
+	arm_spe_free_events(session);
+	session->auxtrace = NULL;
+	free(spe);
+}
+
+static const char * const arm_spe_info_fmts[] = {
+	[ARM_SPE_PMU_TYPE]		= "  PMU Type           %"PRId64"\n",
+};
+
+static void arm_spe_print_info(u64 *arr)
+{
+	if (!dump_trace)
+		return;
+
+	fprintf(stdout, arm_spe_info_fmts[ARM_SPE_PMU_TYPE], arr[ARM_SPE_PMU_TYPE]);
+}
+
+int arm_spe_process_auxtrace_info(union perf_event *event,
+				  struct perf_session *session)
+{
+	struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
+	size_t min_sz = sizeof(u64) * ARM_SPE_PMU_TYPE;
+	struct arm_spe *spe;
+	int err;
+
+	if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
+					min_sz)
+		return -EINVAL;
+
+	spe = zalloc(sizeof(struct arm_spe));
+	if (!spe)
+		return -ENOMEM;
+
+	err = auxtrace_queues__init(&spe->queues);
+	if (err)
+		goto err_free;
+
+	spe->session = session;
+	spe->machine = &session->machines.host; /* No kvm support */
+	spe->auxtrace_type = auxtrace_info->type;
+	spe->pmu_type = auxtrace_info->priv[ARM_SPE_PMU_TYPE];
+
+	spe->auxtrace.process_event = arm_spe_process_event;
+	spe->auxtrace.process_auxtrace_event = arm_spe_process_auxtrace_event;
+	spe->auxtrace.flush_events = arm_spe_flush;
+	spe->auxtrace.free_events = arm_spe_free_events;
+	spe->auxtrace.free = arm_spe_free;
+	session->auxtrace = &spe->auxtrace;
+
+	arm_spe_print_info(&auxtrace_info->priv[0]);
+
+	return 0;
+
+err_free:
+	free(spe);
+	return err;
+}
diff --git a/tools/perf/util/arm-spe.h b/tools/perf/util/arm-spe.h
new file mode 100644
index 000000000000..98d3235781c3
--- /dev/null
+++ b/tools/perf/util/arm-spe.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Arm Statistical Profiling Extensions (SPE) support
+ * Copyright (c) 2017-2018, Arm Ltd.
+ */
+
+#ifndef INCLUDE__PERF_ARM_SPE_H__
+#define INCLUDE__PERF_ARM_SPE_H__
+
+#define ARM_SPE_PMU_NAME "arm_spe_"
+
+enum {
+	ARM_SPE_PMU_TYPE,
+	ARM_SPE_PER_CPU_MMAPS,
+	ARM_SPE_AUXTRACE_PRIV_MAX,
+};
+
+#define ARM_SPE_AUXTRACE_PRIV_SIZE (ARM_SPE_AUXTRACE_PRIV_MAX * sizeof(u64))
+
+union perf_event;
+struct perf_session;
+struct perf_pmu;
+
+struct auxtrace_record *arm_spe_recording_init(int *err,
+					       struct perf_pmu *arm_spe_pmu);
+
+int arm_spe_process_auxtrace_info(union perf_event *event,
+				  struct perf_session *session);
+
+struct perf_event_attr *arm_spe_pmu_default_config(struct perf_pmu *arm_spe_pmu);
+#endif
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index a33491416400..f682f7a58a02 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -57,6 +57,7 @@
 
 #include "intel-pt.h"
 #include "intel-bts.h"
+#include "arm-spe.h"
 
 #include "sane_ctype.h"
 #include "symbol/kallsyms.h"
@@ -913,6 +914,8 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
 		return intel_pt_process_auxtrace_info(event, session);
 	case PERF_AUXTRACE_INTEL_BTS:
 		return intel_bts_process_auxtrace_info(event, session);
+	case PERF_AUXTRACE_ARM_SPE:
+		return arm_spe_process_auxtrace_info(event, session);
 	case PERF_AUXTRACE_CS_ETM:
 	case PERF_AUXTRACE_UNKNOWN:
 	default:
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index d19e11b68de7..453c148d2158 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -43,6 +43,7 @@ enum auxtrace_type {
 	PERF_AUXTRACE_INTEL_PT,
 	PERF_AUXTRACE_INTEL_BTS,
 	PERF_AUXTRACE_CS_ETM,
+	PERF_AUXTRACE_ARM_SPE,
 };
 
 enum itrace_period_type {
-- 
2.15.1

^ permalink raw reply related

* [PATCH 0/3] mfd/abx500-core: Adjustments for eight function implementations
From: SF Markus Elfring @ 2018-01-14 20:40 UTC (permalink / raw)
  To: linux-arm-kernel

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sun, 14 Jan 2018 21:38:42 +0100

Three update suggestions were taken into account
from static source code analysis.

Markus Elfring (3):
  Delete an error message for a failed memory allocation
    in abx500_register_ops()
  Improve two size determinations in abx500_register_ops()
  Adjust 14 checks for null pointers

 drivers/mfd/abx500-core.c | 25 +++++++++++--------------
 1 file changed, 11 insertions(+), 14 deletions(-)

-- 
2.15.1

^ permalink raw reply

* [PATCH 1/3] mfd/abx500-core: Delete an error message for a failed memory allocation in abx500_register_ops()
From: SF Markus Elfring @ 2018-01-14 20:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <d1862d7a-412e-9aaf-8200-bb2070ee402a@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sun, 14 Jan 2018 21:08:27 +0100

Omit an extra message for a memory allocation failure in this function.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/mfd/abx500-core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c
index 0d3846a4767c..c8c9d41abcaa 100644
--- a/drivers/mfd/abx500-core.c
+++ b/drivers/mfd/abx500-core.c
@@ -40,10 +40,9 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops)
 	dev_entry = devm_kzalloc(dev,
 				 sizeof(struct abx500_device_entry),
 				 GFP_KERNEL);
-	if (!dev_entry) {
-		dev_err(dev, "register_ops kzalloc failed");
+	if (!dev_entry)
 		return -ENOMEM;
-	}
+
 	dev_entry->dev = dev;
 	memcpy(&dev_entry->ops, ops, sizeof(struct abx500_ops));
 
-- 
2.15.1

^ permalink raw reply related

* [PATCH 2/3] mfd/abx500-core: Improve two size determinations in abx500_register_ops()
From: SF Markus Elfring @ 2018-01-14 20:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <d1862d7a-412e-9aaf-8200-bb2070ee402a@users.sourceforge.net>

From: Markus Elfring <elfring@users.sourceforge.net>
Date: Sun, 14 Jan 2018 21:19:10 +0100

Replace the specification of two data structures by pointer dereferences
as the parameter for the operator "sizeof" to make the corresponding size
determination a bit safer according to the Linux coding style convention.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring <elfring@users.sourceforge.net>
---
 drivers/mfd/abx500-core.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c
index c8c9d41abcaa..17176e91cbd0 100644
--- a/drivers/mfd/abx500-core.c
+++ b/drivers/mfd/abx500-core.c
@@ -37,14 +37,12 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops)
 {
 	struct abx500_device_entry *dev_entry;
 
-	dev_entry = devm_kzalloc(dev,
-				 sizeof(struct abx500_device_entry),
-				 GFP_KERNEL);
+	dev_entry = devm_kzalloc(dev, sizeof(*dev_entry), GFP_KERNEL);
 	if (!dev_entry)
 		return -ENOMEM;
 
 	dev_entry->dev = dev;
-	memcpy(&dev_entry->ops, ops, sizeof(struct abx500_ops));
+	memcpy(&dev_entry->ops, ops, sizeof(*ops));
 
 	list_add_tail(&dev_entry->list, &abx500_list);
 	return 0;
-- 
2.15.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox