]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Nov 2015 17:11:12 +0000 (09:11 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Nov 2015 17:11:12 +0000 (09:11 -0800)
Pull crypto update from Herbert Xu:
 "API:

   - Add support for cipher output IVs in testmgr
   - Add missing crypto_ahash_blocksize helper
   - Mark authenc and des ciphers as not allowed under FIPS.

Algorithms:

   - Add CRC support to 842 compression
   - Add keywrap algorithm
   - A number of changes to the akcipher interface:
      + Separate functions for setting public/private keys.
      + Use SG lists.

Drivers:

   - Add Intel SHA Extension optimised SHA1 and SHA256
   - Use dma_map_sg instead of custom functions in crypto drivers
   - Add support for STM32 RNG
   - Add support for ST RNG
   - Add Device Tree support to exynos RNG driver
   - Add support for mxs-dcp crypto device on MX6SL
   - Add xts(aes) support to caam
   - Add ctr(aes) and xts(aes) support to qat
   - A large set of fixes from Russell King for the marvell/cesa driver"

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6: (115 commits)
  crypto: asymmetric_keys - Fix unaligned access in x509_get_sig_params()
  crypto: akcipher - Don't #include crypto/public_key.h as the contents aren't used
  hwrng: exynos - Add Device Tree support
  hwrng: exynos - Fix missing configuration after suspend to RAM
  hwrng: exynos - Add timeout for waiting on init done
  dt-bindings: rng: Describe Exynos4 PRNG bindings
  crypto: marvell/cesa - use __le32 for hardware descriptors
  crypto: marvell/cesa - fix missing cpu_to_le32() in mv_cesa_dma_add_op()
  crypto: marvell/cesa - use memcpy_fromio()/memcpy_toio()
  crypto: marvell/cesa - use gfp_t for gfp flags
  crypto: marvell/cesa - use dma_addr_t for cur_dma
  crypto: marvell/cesa - use readl_relaxed()/writel_relaxed()
  crypto: caam - fix indentation of close braces
  crypto: caam - only export the state we really need to export
  crypto: caam - fix non-block aligned hash calculation
  crypto: caam - avoid needlessly saving and restoring caam_hash_ctx
  crypto: caam - print errno code when hash registration fails
  crypto: marvell/cesa - fix memory leak
  crypto: marvell/cesa - fix first-fragment handling in mv_cesa_ahash_dma_last_req()
  crypto: marvell/cesa - rearrange handling for sw padded hashes
  ...

1  2 
MAINTAINERS
arch/x86/Makefile
arch/x86/crypto/sha1_ssse3_glue.c
arch/x86/crypto/sha256_ssse3_glue.c
arch/x86/crypto/sha512_ssse3_glue.c
crypto/asymmetric_keys/x509_public_key.c
drivers/crypto/marvell/cesa.h
drivers/crypto/marvell/cipher.c
drivers/crypto/marvell/hash.c

diff --combined MAINTAINERS
index dcc8ed6fccde769c3f2c44a4e6be5701fc33a74e,e037c66b3d0d3266fb54a96fa1ea7c432d29201e..3036f5a02107385b07141c8ebe8e343182ec37cb
@@@ -240,12 -240,6 +240,12 @@@ L:       lm-sensors@lm-sensors.or
  S:    Maintained
  F:    drivers/hwmon/abituguru3.c
  
 +ACCES 104-IDIO-16 GPIO DRIVER
 +M:    "William Breathitt Gray" <vilhelm.gray@gmail.com>
 +L:    linux-gpio@vger.kernel.org
 +S:    Maintained
 +F:    drivers/gpio/gpio-104-idio-16.c
 +
  ACENIC DRIVER
  M:    Jes Sorensen <jes@trained-monkey.org>
  L:    linux-acenic@sunsite.dk
@@@ -621,8 -615,9 +621,8 @@@ F: Documentation/hwmon/fam15h_powe
  F:    drivers/hwmon/fam15h_power.c
  
  AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER
 -M:    Thomas Dahlmann <dahlmann.thomas@arcor.de>
  L:    linux-geode@lists.infradead.org (moderated for non-subscribers)
 -S:    Supported
 +S:    Orphan
  F:    drivers/usb/gadget/udc/amd5536udc.*
  
  AMD GEODE PROCESSOR/CHIPSET SUPPORT
@@@ -660,6 -655,11 +660,6 @@@ F:        drivers/gpu/drm/radeon/radeon_kfd.
  F:    drivers/gpu/drm/radeon/radeon_kfd.h
  F:    include/uapi/linux/kfd_ioctl.h
  
 -AMD MICROCODE UPDATE SUPPORT
 -M:    Borislav Petkov <bp@alien8.de>
 -S:    Maintained
 -F:    arch/x86/kernel/cpu/microcode/amd*
 -
  AMD XGBE DRIVER
  M:    Tom Lendacky <thomas.lendacky@amd.com>
  L:    netdev@vger.kernel.org
@@@ -808,13 -808,6 +808,13 @@@ S:       Maintaine
  F:    drivers/video/fbdev/arcfb.c
  F:    drivers/video/fbdev/core/fb_defio.c
  
 +ARCNET NETWORK LAYER
 +M:    Michael Grzeschik <m.grzeschik@pengutronix.de>
 +L:    netdev@vger.kernel.org
 +S:    Maintained
 +F:    drivers/net/arcnet/
 +F:    include/uapi/linux/if_arcnet.h
 +
  ARM MFM AND FLOPPY DRIVERS
  M:    Ian Molton <spyro@f2s.com>
  S:    Maintained
@@@ -895,12 -888,11 +895,12 @@@ M:      Lennert Buytenhek <kernel@wantstofly
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
  
 -ARM/Allwinner A1X SoC support
 +ARM/Allwinner sunXi SoC support
  M:    Maxime Ripard <maxime.ripard@free-electrons.com>
 +M:    Chen-Yu Tsai <wens@csie.org>
  L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
  S:    Maintained
 -N:    sun[x4567]i
 +N:    sun[x456789]i
  
  ARM/Allwinner SoC Clock Support
  M:    Emilio López <emilio@elopez.com.ar>
@@@ -1529,6 -1521,7 +1529,7 @@@ W:      http://www.stlinux.co
  S:    Maintained
  F:    arch/arm/mach-sti/
  F:    arch/arm/boot/dts/sti*
+ F:    drivers/char/hw_random/st-rng.c
  F:    drivers/clocksource/arm_global_timer.c
  F:    drivers/clocksource/clksrc_st_lpc.c
  F:    drivers/i2c/busses/i2c-st.c
@@@ -1781,14 -1774,6 +1782,14 @@@ S:    Supporte
  F:    Documentation/aoe/
  F:    drivers/block/aoe/
  
 +ATHEROS 71XX/9XXX GPIO DRIVER
 +M:    Alban Bedel <albeu@free.fr>
 +W:    https://github.com/AlbanBedel/linux
 +T:    git git://github.com/AlbanBedel/linux
 +S:    Maintained
 +F:    drivers/gpio/gpio-ath79.c
 +F:    Documentation/devicetree/bindings/gpio/gpio-ath79.txt
 +
  ATHEROS ATH GENERIC UTILITIES
  M:    "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
  L:    linux-wireless@vger.kernel.org
@@@ -3410,6 -3395,7 +3411,6 @@@ F:      drivers/staging/dgnc
  
  DIGI EPCA PCI PRODUCTS
  M:    Lidza Louina <lidza.louina@gmail.com>
 -M:    Mark Hounschell <markh@compro.net>
  M:    Daeseok Youn <daeseok.youn@gmail.com>
  L:    driverdev-devel@linuxdriverproject.org
  S:    Maintained
@@@ -3601,13 -3587,6 +3602,13 @@@ F:    drivers/gpu/drm/i915
  F:    include/drm/i915*
  F:    include/uapi/drm/i915*
  
 +DRM DRIVERS FOR ATMEL HLCDC
 +M:    Boris Brezillon <boris.brezillon@free-electrons.com>
 +L:    dri-devel@lists.freedesktop.org
 +S:    Supported
 +F:    drivers/gpu/drm/atmel-hlcdc/
 +F:    Documentation/devicetree/bindings/drm/atmel/
 +
  DRM DRIVERS FOR EXYNOS
  M:    Inki Dae <inki.dae@samsung.com>
  M:    Joonyoung Shim <jy0922.shim@samsung.com>
@@@ -3636,14 -3615,6 +3637,14 @@@ S:    Maintaine
  F:    drivers/gpu/drm/imx/
  F:    Documentation/devicetree/bindings/drm/imx/
  
 +DRM DRIVERS FOR GMA500 (Poulsbo, Moorestown and derivative chipsets)
 +M:    Patrik Jakobsson <patrik.r.jakobsson@gmail.com>
 +L:    dri-devel@lists.freedesktop.org
 +T:    git git://github.com/patjak/drm-gma500
 +S:    Maintained
 +F:    drivers/gpu/drm/gma500
 +F:    include/drm/gma500*
 +
  DRM DRIVERS FOR NVIDIA TEGRA
  M:    Thierry Reding <thierry.reding@gmail.com>
  M:    Terje Bergström <tbergstrom@nvidia.com>
@@@ -4028,7 -3999,7 +4029,7 @@@ S:      Maintaine
  F:    sound/usb/misc/ua101.c
  
  EXTENSIBLE FIRMWARE INTERFACE (EFI)
 -M:    Matt Fleming <matt.fleming@intel.com>
 +M:    Matt Fleming <matt@codeblueprint.co.uk>
  L:    linux-efi@vger.kernel.org
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
  S:    Maintained
@@@ -4043,7 -4014,7 +4044,7 @@@ F:      include/linux/efi*.
  EFI VARIABLE FILESYSTEM
  M:    Matthew Garrett <matthew.garrett@nebula.com>
  M:    Jeremy Kerr <jk@ozlabs.org>
 -M:    Matt Fleming <matt.fleming@intel.com>
 +M:    Matt Fleming <matt@codeblueprint.co.uk>
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
  L:    linux-efi@vger.kernel.org
  S:    Maintained
@@@ -4437,14 -4408,6 +4438,14 @@@ L:    linuxppc-dev@lists.ozlabs.or
  S:    Maintained
  F:    drivers/net/ethernet/freescale/ucc_geth*
  
 +FREESCALE eTSEC ETHERNET DRIVER (GIANFAR)
 +M:    Claudiu Manoil <claudiu.manoil@freescale.com>
 +L:    netdev@vger.kernel.org
 +S:    Maintained
 +F:    drivers/net/ethernet/freescale/gianfar*
 +X:    drivers/net/ethernet/freescale/gianfar_ptp.c
 +F:    Documentation/devicetree/bindings/net/fsl-tsec-phy.txt
 +
  FREESCALE QUICC ENGINE UCC UART DRIVER
  M:    Timur Tabi <timur@tabi.org>
  L:    linuxppc-dev@lists.ozlabs.org
@@@ -5463,6 -5426,12 +5464,6 @@@ W:     https://01.org/linux-acp
  S:    Supported
  F:    drivers/platform/x86/intel_menlow.c
  
 -INTEL IA32 MICROCODE UPDATE SUPPORT
 -M:    Borislav Petkov <bp@alien8.de>
 -S:    Maintained
 -F:    arch/x86/kernel/cpu/microcode/core*
 -F:    arch/x86/kernel/cpu/microcode/intel*
 -
  INTEL I/OAT DMA DRIVER
  M:    Dave Jiang <dave.jiang@intel.com>
  R:    Dan Williams <dan.j.williams@intel.com>
@@@ -5984,7 -5953,7 +5985,7 @@@ F:      virt/kvm
  KERNEL VIRTUAL MACHINE (KVM) FOR AMD-V
  M:    Joerg Roedel <joro@8bytes.org>
  L:    kvm@vger.kernel.org
 -W:    http://kvm.qumranet.com
 +W:    http://www.linux-kvm.org/
  S:    Maintained
  F:    arch/x86/include/asm/svm.h
  F:    arch/x86/kvm/svm.c
  KERNEL VIRTUAL MACHINE (KVM) FOR POWERPC
  M:    Alexander Graf <agraf@suse.com>
  L:    kvm-ppc@vger.kernel.org
 -W:    http://kvm.qumranet.com
 +W:    http://www.linux-kvm.org/
  T:    git git://github.com/agraf/linux-2.6.git
  S:    Supported
  F:    arch/powerpc/include/asm/kvm*
@@@ -6587,6 -6556,13 +6588,13 @@@ M:    Guenter Roeck <linux@roeck-us.net
  S:    Maintained
  F:    drivers/net/dsa/mv88e6352.c
  
+ MARVELL CRYPTO DRIVER
+ M:    Boris Brezillon <boris.brezillon@free-electrons.com>
+ M:    Arnaud Ebalard <arno@natisbad.org>
+ F:    drivers/crypto/marvell/
+ S:    Maintained
+ L:    linux-crypto@vger.kernel.org
  MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
  M:    Mirko Lindner <mlindner@marvell.com>
  M:    Stephen Hemminger <stephen@networkplumber.org>
@@@ -6805,6 -6781,7 +6813,6 @@@ F:      drivers/scsi/megaraid
  
  MELLANOX ETHERNET DRIVER (mlx4_en)
  M:    Amir Vadai <amirv@mellanox.com>
 -M:    Ido Shamay <idos@mellanox.com>
  L:    netdev@vger.kernel.org
  S:    Supported
  W:    http://www.mellanox.com
@@@ -8184,13 -8161,6 +8192,13 @@@ L:    linux-arm-kernel@lists.infradead.or
  S:    Maintained
  F:    drivers/pinctrl/pinctrl-at91.*
  
 +PIN CONTROLLER - ATMEL AT91 PIO4
 +M:    Ludovic Desroches <ludovic.desroches@atmel.com>
 +L:    linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 +L:    linux-gpio@vger.kernel.org
 +S:    Supported
 +F:    drivers/pinctrl/pinctrl-at91-pio4.*
 +
  PIN CONTROLLER - INTEL
  M:    Mika Westerberg <mika.westerberg@linux.intel.com>
  M:    Heikki Krogerus <heikki.krogerus@linux.intel.com>
@@@ -8538,6 -8508,7 +8546,6 @@@ F:      Documentation/networking/LICENSE.qla
  F:    drivers/net/ethernet/qlogic/qla3xxx.*
  
  QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
 -M:    Shahed Shaikh <shahed.shaikh@qlogic.com>
  M:    Dept-GELinuxNICDev@qlogic.com
  L:    netdev@vger.kernel.org
  S:    Supported
@@@ -9134,15 -9105,6 +9142,15 @@@ S: Supporte
  F: Documentation/devicetree/bindings/net/snps,dwc-qos-ethernet.txt
  F: drivers/net/ethernet/synopsys/dwc_eth_qos.c
  
 +SYNOPSYS DESIGNWARE I2C DRIVER
 +M:    Andy Shevchenko <andriy.shevchenko@linux.intel.com>
 +M:    Jarkko Nikula <jarkko.nikula@linux.intel.com>
 +M:    Mika Westerberg <mika.westerberg@linux.intel.com>
 +L:    linux-i2c@vger.kernel.org
 +S:    Maintained
 +F:    drivers/i2c/busses/i2c-designware-*
 +F:    include/linux/platform_data/i2c-designware.h
 +
  SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER
  M:    Seungwon Jeon <tgih.jun@samsung.com>
  M:    Jaehoon Chung <jh80.chung@samsung.com>
@@@ -9950,12 -9912,13 +9958,12 @@@ F:   drivers/staging/media/lirc
  STAGING - LUSTRE PARALLEL FILESYSTEM
  M:    Oleg Drokin <oleg.drokin@intel.com>
  M:    Andreas Dilger <andreas.dilger@intel.com>
 -L:    HPDD-discuss@lists.01.org (moderated for non-subscribers)
 -W:    http://lustre.opensfs.org/
 +L:    lustre-devel@lists.lustre.org (moderated for non-subscribers)
 +W:    http://wiki.lustre.org/
  S:    Maintained
  F:    drivers/staging/lustre
  
  STAGING - NVIDIA COMPLIANT EMBEDDED CONTROLLER INTERFACE (nvec)
 -M:    Julian Andres Klode <jak@jak-linux.org>
  M:    Marc Dietrich <marvin24@gmx.de>
  L:    ac100@lists.launchpad.net (moderated for non-subscribers)
  L:    linux-tegra@vger.kernel.org
@@@ -10110,7 -10073,6 +10118,7 @@@ F:   include/net/switchdev.
  
  SYNOPSYS ARC ARCHITECTURE
  M:    Vineet Gupta <vgupta@synopsys.com>
 +L:    linux-snps-arc@lists.infraded.org
  S:    Supported
  F:    arch/arc/
  F:    Documentation/devicetree/bindings/arc/*
@@@ -10384,16 -10346,6 +10392,16 @@@ F: include/uapi/linux/thermal.
  F:    include/linux/cpu_cooling.h
  F:    Documentation/devicetree/bindings/thermal/
  
 +THERMAL/CPU_COOLING
 +M:    Amit Daniel Kachhap <amit.kachhap@gmail.com>
 +M:    Viresh Kumar <viresh.kumar@linaro.org>
 +M:    Javi Merino <javi.merino@arm.com>
 +L:    linux-pm@vger.kernel.org
 +S:    Supported
 +F:    Documentation/thermal/cpu-cooling-api.txt
 +F:    drivers/thermal/cpu_cooling.c
 +F:    include/linux/cpu_cooling.h
 +
  THINGM BLINK(1) USB RGB LED DRIVER
  M:    Vivien Didelot <vivien.didelot@savoirfairelinux.com>
  S:    Maintained
@@@ -11243,7 -11195,7 +11251,7 @@@ F:   drivers/vlynq/vlynq.
  F:    include/linux/vlynq.h
  
  VME SUBSYSTEM
 -M:    Martyn Welch <martyn.welch@ge.com>
 +M:    Martyn Welch <martyn@welchs.me.uk>
  M:    Manohar Vanga <manohar.vanga@gmail.com>
  M:    Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  L:    devel@driverdev.osuosl.org
@@@ -11295,6 -11247,7 +11303,6 @@@ VOLTAGE AND CURRENT REGULATOR FRAMEWOR
  M:    Liam Girdwood <lgirdwood@gmail.com>
  M:    Mark Brown <broonie@kernel.org>
  L:    linux-kernel@vger.kernel.org
 -W:    http://opensource.wolfsonmicro.com/node/15
  W:    http://www.slimlogic.co.uk/?p=48
  T:    git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git
  S:    Supported
@@@ -11308,7 -11261,6 +11316,7 @@@ L:   netdev@vger.kernel.or
  S:    Maintained
  F:    drivers/net/vrf.c
  F:    include/net/vrf.h
 +F:    Documentation/networking/vrf.txt
  
  VT1211 HARDWARE MONITOR DRIVER
  M:    Juerg Haefliger <juergh@gmail.com>
@@@ -11420,10 -11372,21 +11428,10 @@@ W:        http://oops.ghostprotocols.net:81/bl
  S:    Maintained
  F:    drivers/net/wireless/wl3501*
  
 -WM97XX TOUCHSCREEN DRIVERS
 -M:    Mark Brown <broonie@kernel.org>
 -M:    Liam Girdwood <lrg@slimlogic.co.uk>
 -L:    linux-input@vger.kernel.org
 -T:    git git://opensource.wolfsonmicro.com/linux-2.6-touch
 -W:    http://opensource.wolfsonmicro.com/node/7
 -S:    Supported
 -F:    drivers/input/touchscreen/*wm97*
 -F:    include/linux/wm97xx.h
 -
  WOLFSON MICROELECTRONICS DRIVERS
  L:    patches@opensource.wolfsonmicro.com
 -T:    git git://opensource.wolfsonmicro.com/linux-2.6-asoc
 -T:    git git://opensource.wolfsonmicro.com/linux-2.6-audioplus
 -W:    http://opensource.wolfsonmicro.com/content/linux-drivers-wolfson-devices
 +T:    git https://github.com/CirrusLogic/linux-drivers.git
 +W:    https://github.com/CirrusLogic/linux-drivers/wiki
  S:    Supported
  F:    Documentation/hwmon/wm83??
  F:    arch/arm/mach-s3c64xx/mach-crag6410*
@@@ -11494,11 -11457,6 +11502,11 @@@ L: linux-edac@vger.kernel.or
  S:    Maintained
  F:    arch/x86/kernel/cpu/mcheck/*
  
 +X86 MICROCODE UPDATE SUPPORT
 +M:    Borislav Petkov <bp@alien8.de>
 +S:    Maintained
 +F:    arch/x86/kernel/cpu/microcode/*
 +
  X86 VDSO
  M:    Andy Lutomirski <luto@amacapital.net>
  L:    linux-kernel@vger.kernel.org
@@@ -11699,7 -11657,6 +11707,7 @@@ F:   drivers/tty/serial/zs.
  ZSMALLOC COMPRESSED SLAB MEMORY ALLOCATOR
  M:    Minchan Kim <minchan@kernel.org>
  M:    Nitin Gupta <ngupta@vflare.org>
 +R:    Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
  L:    linux-mm@kvack.org
  S:    Maintained
  F:    mm/zsmalloc.c
diff --combined arch/x86/Makefile
index 2dfaa72260b41fcb3c9ef528ceffa9840cfc691d,a8009c77918a7340193d6991b5a1db0dbb3532e6..4086abca0b32345c92207fa75468cc98ebe97da4
@@@ -159,21 -159,17 +159,23 @@@ endi
  sp-$(CONFIG_X86_32) := esp
  sp-$(CONFIG_X86_64) := rsp
  
 +# do binutils support CFI?
 +cfi := $(call as-instr,.cfi_startproc\n.cfi_rel_offset $(sp-y)$(comma)0\n.cfi_endproc,-DCONFIG_AS_CFI=1)
 +# is .cfi_signal_frame supported too?
 +cfi-sigframe := $(call as-instr,.cfi_startproc\n.cfi_signal_frame\n.cfi_endproc,-DCONFIG_AS_CFI_SIGNAL_FRAME=1)
 +cfi-sections := $(call as-instr,.cfi_sections .debug_frame,-DCONFIG_AS_CFI_SECTIONS=1)
 +
  # does binutils support specific instructions?
  asinstr := $(call as-instr,fxsaveq (%rax),-DCONFIG_AS_FXSAVEQ=1)
  asinstr += $(call as-instr,pshufb %xmm0$(comma)%xmm0,-DCONFIG_AS_SSSE3=1)
  asinstr += $(call as-instr,crc32l %eax$(comma)%eax,-DCONFIG_AS_CRC32=1)
  avx_instr := $(call as-instr,vxorps %ymm0$(comma)%ymm1$(comma)%ymm2,-DCONFIG_AS_AVX=1)
  avx2_instr :=$(call as-instr,vpbroadcastb %xmm0$(comma)%ymm1,-DCONFIG_AS_AVX2=1)
+ sha1_ni_instr :=$(call as-instr,sha1msg1 %xmm0$(comma)%xmm1,-DCONFIG_AS_SHA1_NI=1)
+ sha256_ni_instr :=$(call as-instr,sha256msg1 %xmm0$(comma)%xmm1,-DCONFIG_AS_SHA256_NI=1)
  
- KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr)
- KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr)
 -KBUILD_AFLAGS += $(asinstr) $(avx_instr) $(avx2_instr) $(sha1_ni_instr) $(sha256_ni_instr)
 -KBUILD_CFLAGS += $(asinstr) $(avx_instr) $(avx2_instr) $(sha1_ni_instr) $(sha256_ni_instr)
++KBUILD_AFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(sha1_ni_instr) $(sha256_ni_instr)
++KBUILD_CFLAGS += $(cfi) $(cfi-sigframe) $(cfi-sections) $(asinstr) $(avx_instr) $(avx2_instr) $(sha1_ni_instr) $(sha256_ni_instr)
  
  LDFLAGS := -m elf_$(UTS_MACHINE)
  
index 00212c32d4db289a2fb2937241a39be917738889,c934197fe84ae05b07a2e8a1196a6d74f581807b..dd14616b773970d13c2886f255c0f76b4eb58450
  #include <crypto/sha1_base.h>
  #include <asm/fpu/api.h>
  
+ typedef void (sha1_transform_fn)(u32 *digest, const char *data,
+                               unsigned int rounds);
  
- asmlinkage void sha1_transform_ssse3(u32 *digest, const char *data,
-                                    unsigned int rounds);
- #ifdef CONFIG_AS_AVX
- asmlinkage void sha1_transform_avx(u32 *digest, const char *data,
-                                  unsigned int rounds);
- #endif
- #ifdef CONFIG_AS_AVX2
- #define SHA1_AVX2_BLOCK_OPTSIZE       4       /* optimal 4*64 bytes of SHA1 blocks */
- asmlinkage void sha1_transform_avx2(u32 *digest, const char *data,
-                                   unsigned int rounds);
- #endif
- static void (*sha1_transform_asm)(u32 *, const char *, unsigned int);
- static int sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
-                            unsigned int len)
+ static int sha1_update(struct shash_desc *desc, const u8 *data,
+                            unsigned int len, sha1_transform_fn *sha1_xform)
  {
        struct sha1_state *sctx = shash_desc_ctx(desc);
  
  
        kernel_fpu_begin();
        sha1_base_do_update(desc, data, len,
-                           (sha1_block_fn *)sha1_transform_asm);
+                           (sha1_block_fn *)sha1_xform);
        kernel_fpu_end();
  
        return 0;
  }
  
- static int sha1_ssse3_finup(struct shash_desc *desc, const u8 *data,
-                             unsigned int len, u8 *out)
+ static int sha1_finup(struct shash_desc *desc, const u8 *data,
+                     unsigned int len, u8 *out, sha1_transform_fn *sha1_xform)
  {
        if (!irq_fpu_usable())
                return crypto_sha1_finup(desc, data, len, out);
        kernel_fpu_begin();
        if (len)
                sha1_base_do_update(desc, data, len,
-                                   (sha1_block_fn *)sha1_transform_asm);
-       sha1_base_do_finalize(desc, (sha1_block_fn *)sha1_transform_asm);
+                                   (sha1_block_fn *)sha1_xform);
+       sha1_base_do_finalize(desc, (sha1_block_fn *)sha1_xform);
        kernel_fpu_end();
  
        return sha1_base_finish(desc, out);
  }
  
- /* Add padding and return the message digest. */
- static int sha1_ssse3_final(struct shash_desc *desc, u8 *out)
+ asmlinkage void sha1_transform_ssse3(u32 *digest, const char *data,
+                                    unsigned int rounds);
+ static int sha1_ssse3_update(struct shash_desc *desc, const u8 *data,
+                            unsigned int len)
  {
-       return sha1_ssse3_finup(desc, NULL, 0, out);
+       return sha1_update(desc, data, len,
+                       (sha1_transform_fn *) sha1_transform_ssse3);
  }
  
- #ifdef CONFIG_AS_AVX2
- static void sha1_apply_transform_avx2(u32 *digest, const char *data,
-                               unsigned int rounds)
+ static int sha1_ssse3_finup(struct shash_desc *desc, const u8 *data,
+                             unsigned int len, u8 *out)
  {
-       /* Select the optimal transform based on data block size */
-       if (rounds >= SHA1_AVX2_BLOCK_OPTSIZE)
-               sha1_transform_avx2(digest, data, rounds);
-       else
-               sha1_transform_avx(digest, data, rounds);
+       return sha1_finup(desc, data, len, out,
+                       (sha1_transform_fn *) sha1_transform_ssse3);
+ }
+ /* Add padding and return the message digest. */
+ static int sha1_ssse3_final(struct shash_desc *desc, u8 *out)
+ {
+       return sha1_ssse3_finup(desc, NULL, 0, out);
  }
- #endif
  
- static struct shash_alg alg = {
+ static struct shash_alg sha1_ssse3_alg = {
        .digestsize     =       SHA1_DIGEST_SIZE,
        .init           =       sha1_base_init,
        .update         =       sha1_ssse3_update,
        .descsize       =       sizeof(struct sha1_state),
        .base           =       {
                .cra_name       =       "sha1",
-               .cra_driver_name      "sha1-ssse3",
+               .cra_driver_name =      "sha1-ssse3",
                .cra_priority   =       150,
                .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
                .cra_blocksize  =       SHA1_BLOCK_SIZE,
        }
  };
  
+ static int register_sha1_ssse3(void)
+ {
+       if (boot_cpu_has(X86_FEATURE_SSSE3))
+               return crypto_register_shash(&sha1_ssse3_alg);
+       return 0;
+ }
+ static void unregister_sha1_ssse3(void)
+ {
+       if (boot_cpu_has(X86_FEATURE_SSSE3))
+               crypto_unregister_shash(&sha1_ssse3_alg);
+ }
  #ifdef CONFIG_AS_AVX
- static bool __init avx_usable(void)
+ asmlinkage void sha1_transform_avx(u32 *digest, const char *data,
+                                  unsigned int rounds);
+ static int sha1_avx_update(struct shash_desc *desc, const u8 *data,
+                            unsigned int len)
+ {
+       return sha1_update(desc, data, len,
+                       (sha1_transform_fn *) sha1_transform_avx);
+ }
+ static int sha1_avx_finup(struct shash_desc *desc, const u8 *data,
+                             unsigned int len, u8 *out)
+ {
+       return sha1_finup(desc, data, len, out,
+                       (sha1_transform_fn *) sha1_transform_avx);
+ }
+ static int sha1_avx_final(struct shash_desc *desc, u8 *out)
+ {
+       return sha1_avx_finup(desc, NULL, 0, out);
+ }
+ static struct shash_alg sha1_avx_alg = {
+       .digestsize     =       SHA1_DIGEST_SIZE,
+       .init           =       sha1_base_init,
+       .update         =       sha1_avx_update,
+       .final          =       sha1_avx_final,
+       .finup          =       sha1_avx_finup,
+       .descsize       =       sizeof(struct sha1_state),
+       .base           =       {
+               .cra_name       =       "sha1",
+               .cra_driver_name =      "sha1-avx",
+               .cra_priority   =       160,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA1_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
+       }
+ };
+ static bool avx_usable(void)
  {
 -      if (!cpu_has_xfeatures(XSTATE_SSE | XSTATE_YMM, NULL)) {
 +      if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) {
                if (cpu_has_avx)
                        pr_info("AVX detected but unusable.\n");
                return false;
        return true;
  }
  
- #ifdef CONFIG_AS_AVX2
- static bool __init avx2_usable(void)
+ static int register_sha1_avx(void)
+ {
+       if (avx_usable())
+               return crypto_register_shash(&sha1_avx_alg);
+       return 0;
+ }
+ static void unregister_sha1_avx(void)
  {
-       if (avx_usable() && cpu_has_avx2 && boot_cpu_has(X86_FEATURE_BMI1) &&
-           boot_cpu_has(X86_FEATURE_BMI2))
+       if (avx_usable())
+               crypto_unregister_shash(&sha1_avx_alg);
+ }
+ #else  /* CONFIG_AS_AVX */
+ static inline int register_sha1_avx(void) { return 0; }
+ static inline void unregister_sha1_avx(void) { }
+ #endif /* CONFIG_AS_AVX */
+ #if defined(CONFIG_AS_AVX2) && (CONFIG_AS_AVX)
+ #define SHA1_AVX2_BLOCK_OPTSIZE       4       /* optimal 4*64 bytes of SHA1 blocks */
+ asmlinkage void sha1_transform_avx2(u32 *digest, const char *data,
+                                   unsigned int rounds);
+ static bool avx2_usable(void)
+ {
+       if (avx_usable() && boot_cpu_has(X86_FEATURE_AVX2)
+               && boot_cpu_has(X86_FEATURE_BMI1)
+               && boot_cpu_has(X86_FEATURE_BMI2))
                return true;
  
        return false;
  }
+ static void sha1_apply_transform_avx2(u32 *digest, const char *data,
+                               unsigned int rounds)
+ {
+       /* Select the optimal transform based on data block size */
+       if (rounds >= SHA1_AVX2_BLOCK_OPTSIZE)
+               sha1_transform_avx2(digest, data, rounds);
+       else
+               sha1_transform_avx(digest, data, rounds);
+ }
+ static int sha1_avx2_update(struct shash_desc *desc, const u8 *data,
+                            unsigned int len)
+ {
+       return sha1_update(desc, data, len,
+               (sha1_transform_fn *) sha1_apply_transform_avx2);
+ }
+ static int sha1_avx2_finup(struct shash_desc *desc, const u8 *data,
+                             unsigned int len, u8 *out)
+ {
+       return sha1_finup(desc, data, len, out,
+               (sha1_transform_fn *) sha1_apply_transform_avx2);
+ }
+ static int sha1_avx2_final(struct shash_desc *desc, u8 *out)
+ {
+       return sha1_avx2_finup(desc, NULL, 0, out);
+ }
+ static struct shash_alg sha1_avx2_alg = {
+       .digestsize     =       SHA1_DIGEST_SIZE,
+       .init           =       sha1_base_init,
+       .update         =       sha1_avx2_update,
+       .final          =       sha1_avx2_final,
+       .finup          =       sha1_avx2_finup,
+       .descsize       =       sizeof(struct sha1_state),
+       .base           =       {
+               .cra_name       =       "sha1",
+               .cra_driver_name =      "sha1-avx2",
+               .cra_priority   =       170,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA1_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
+       }
+ };
+ static int register_sha1_avx2(void)
+ {
+       if (avx2_usable())
+               return crypto_register_shash(&sha1_avx2_alg);
+       return 0;
+ }
+ static void unregister_sha1_avx2(void)
+ {
+       if (avx2_usable())
+               crypto_unregister_shash(&sha1_avx2_alg);
+ }
+ #else
+ static inline int register_sha1_avx2(void) { return 0; }
+ static inline void unregister_sha1_avx2(void) { }
  #endif
+ #ifdef CONFIG_AS_SHA1_NI
+ asmlinkage void sha1_ni_transform(u32 *digest, const char *data,
+                                  unsigned int rounds);
+ static int sha1_ni_update(struct shash_desc *desc, const u8 *data,
+                            unsigned int len)
+ {
+       return sha1_update(desc, data, len,
+               (sha1_transform_fn *) sha1_ni_transform);
+ }
+ static int sha1_ni_finup(struct shash_desc *desc, const u8 *data,
+                             unsigned int len, u8 *out)
+ {
+       return sha1_finup(desc, data, len, out,
+               (sha1_transform_fn *) sha1_ni_transform);
+ }
+ static int sha1_ni_final(struct shash_desc *desc, u8 *out)
+ {
+       return sha1_ni_finup(desc, NULL, 0, out);
+ }
+ static struct shash_alg sha1_ni_alg = {
+       .digestsize     =       SHA1_DIGEST_SIZE,
+       .init           =       sha1_base_init,
+       .update         =       sha1_ni_update,
+       .final          =       sha1_ni_final,
+       .finup          =       sha1_ni_finup,
+       .descsize       =       sizeof(struct sha1_state),
+       .base           =       {
+               .cra_name       =       "sha1",
+               .cra_driver_name =      "sha1-ni",
+               .cra_priority   =       250,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA1_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
+       }
+ };
+ static int register_sha1_ni(void)
+ {
+       if (boot_cpu_has(X86_FEATURE_SHA_NI))
+               return crypto_register_shash(&sha1_ni_alg);
+       return 0;
+ }
+ static void unregister_sha1_ni(void)
+ {
+       if (boot_cpu_has(X86_FEATURE_SHA_NI))
+               crypto_unregister_shash(&sha1_ni_alg);
+ }
+ #else
+ static inline int register_sha1_ni(void) { return 0; }
+ static inline void unregister_sha1_ni(void) { }
  #endif
  
  static int __init sha1_ssse3_mod_init(void)
  {
-       char *algo_name;
+       if (register_sha1_ssse3())
+               goto fail;
  
-       /* test for SSSE3 first */
-       if (cpu_has_ssse3) {
-               sha1_transform_asm = sha1_transform_ssse3;
-               algo_name = "SSSE3";
+       if (register_sha1_avx()) {
+               unregister_sha1_ssse3();
+               goto fail;
        }
  
- #ifdef CONFIG_AS_AVX
-       /* allow AVX to override SSSE3, it's a little faster */
-       if (avx_usable()) {
-               sha1_transform_asm = sha1_transform_avx;
-               algo_name = "AVX";
- #ifdef CONFIG_AS_AVX2
-               /* allow AVX2 to override AVX, it's a little faster */
-               if (avx2_usable()) {
-                       sha1_transform_asm = sha1_apply_transform_avx2;
-                       algo_name = "AVX2";
-               }
- #endif
+       if (register_sha1_avx2()) {
+               unregister_sha1_avx();
+               unregister_sha1_ssse3();
+               goto fail;
        }
- #endif
  
-       if (sha1_transform_asm) {
-               pr_info("Using %s optimized SHA-1 implementation\n", algo_name);
-               return crypto_register_shash(&alg);
+       if (register_sha1_ni()) {
+               unregister_sha1_avx2();
+               unregister_sha1_avx();
+               unregister_sha1_ssse3();
+               goto fail;
        }
-       pr_info("Neither AVX nor AVX2 nor SSSE3 is available/usable.\n");
  
+       return 0;
+ fail:
        return -ENODEV;
  }
  
  static void __exit sha1_ssse3_mod_fini(void)
  {
-       crypto_unregister_shash(&alg);
+       unregister_sha1_ni();
+       unregister_sha1_avx2();
+       unregister_sha1_avx();
+       unregister_sha1_ssse3();
  }
  
  module_init(sha1_ssse3_mod_init);
index 0e0e85aea63418fefb54e2d377c86bcebdf1c795,863e2f6aad135e1bf436d0374abce8f1d2eb3a5e..5f4d6086dc5913be7d680882ab94d2286ad3e230
  
  asmlinkage void sha256_transform_ssse3(u32 *digest, const char *data,
                                       u64 rounds);
- #ifdef CONFIG_AS_AVX
- asmlinkage void sha256_transform_avx(u32 *digest, const char *data,
-                                    u64 rounds);
- #endif
- #ifdef CONFIG_AS_AVX2
- asmlinkage void sha256_transform_rorx(u32 *digest, const char *data,
-                                     u64 rounds);
- #endif
- static void (*sha256_transform_asm)(u32 *, const char *, u64);
+ typedef void (sha256_transform_fn)(u32 *digest, const char *data, u64 rounds);
  
- static int sha256_ssse3_update(struct shash_desc *desc, const u8 *data,
-                            unsigned int len)
+ static int sha256_update(struct shash_desc *desc, const u8 *data,
+                        unsigned int len, sha256_transform_fn *sha256_xform)
  {
        struct sha256_state *sctx = shash_desc_ctx(desc);
  
  
        kernel_fpu_begin();
        sha256_base_do_update(desc, data, len,
-                             (sha256_block_fn *)sha256_transform_asm);
+                             (sha256_block_fn *)sha256_xform);
        kernel_fpu_end();
  
        return 0;
  }
  
- static int sha256_ssse3_finup(struct shash_desc *desc, const u8 *data,
-                             unsigned int len, u8 *out)
+ static int sha256_finup(struct shash_desc *desc, const u8 *data,
+             unsigned int len, u8 *out, sha256_transform_fn *sha256_xform)
  {
        if (!irq_fpu_usable())
                return crypto_sha256_finup(desc, data, len, out);
        kernel_fpu_begin();
        if (len)
                sha256_base_do_update(desc, data, len,
-                                     (sha256_block_fn *)sha256_transform_asm);
-       sha256_base_do_finalize(desc, (sha256_block_fn *)sha256_transform_asm);
+                                     (sha256_block_fn *)sha256_xform);
+       sha256_base_do_finalize(desc, (sha256_block_fn *)sha256_xform);
        kernel_fpu_end();
  
        return sha256_base_finish(desc, out);
  }
  
+ static int sha256_ssse3_update(struct shash_desc *desc, const u8 *data,
+                        unsigned int len)
+ {
+       return sha256_update(desc, data, len, sha256_transform_ssse3);
+ }
+ static int sha256_ssse3_finup(struct shash_desc *desc, const u8 *data,
+             unsigned int len, u8 *out)
+ {
+       return sha256_finup(desc, data, len, out, sha256_transform_ssse3);
+ }
  /* Add padding and return the message digest. */
  static int sha256_ssse3_final(struct shash_desc *desc, u8 *out)
  {
        return sha256_ssse3_finup(desc, NULL, 0, out);
  }
  
- static struct shash_alg algs[] = { {
+ static struct shash_alg sha256_ssse3_algs[] = { {
        .digestsize     =       SHA256_DIGEST_SIZE,
        .init           =       sha256_base_init,
        .update         =       sha256_ssse3_update,
        }
  } };
  
+ static int register_sha256_ssse3(void)
+ {
+       if (boot_cpu_has(X86_FEATURE_SSSE3))
+               return crypto_register_shashes(sha256_ssse3_algs,
+                               ARRAY_SIZE(sha256_ssse3_algs));
+       return 0;
+ }
+ static void unregister_sha256_ssse3(void)
+ {
+       if (boot_cpu_has(X86_FEATURE_SSSE3))
+               crypto_unregister_shashes(sha256_ssse3_algs,
+                               ARRAY_SIZE(sha256_ssse3_algs));
+ }
  #ifdef CONFIG_AS_AVX
- static bool __init avx_usable(void)
+ asmlinkage void sha256_transform_avx(u32 *digest, const char *data,
+                                    u64 rounds);
+ static int sha256_avx_update(struct shash_desc *desc, const u8 *data,
+                        unsigned int len)
+ {
+       return sha256_update(desc, data, len, sha256_transform_avx);
+ }
+ static int sha256_avx_finup(struct shash_desc *desc, const u8 *data,
+                     unsigned int len, u8 *out)
+ {
+       return sha256_finup(desc, data, len, out, sha256_transform_avx);
+ }
+ static int sha256_avx_final(struct shash_desc *desc, u8 *out)
+ {
+       return sha256_avx_finup(desc, NULL, 0, out);
+ }
+ static struct shash_alg sha256_avx_algs[] = { {
+       .digestsize     =       SHA256_DIGEST_SIZE,
+       .init           =       sha256_base_init,
+       .update         =       sha256_avx_update,
+       .final          =       sha256_avx_final,
+       .finup          =       sha256_avx_finup,
+       .descsize       =       sizeof(struct sha256_state),
+       .base           =       {
+               .cra_name       =       "sha256",
+               .cra_driver_name =      "sha256-avx",
+               .cra_priority   =       160,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA256_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
+       }
+ }, {
+       .digestsize     =       SHA224_DIGEST_SIZE,
+       .init           =       sha224_base_init,
+       .update         =       sha256_avx_update,
+       .final          =       sha256_avx_final,
+       .finup          =       sha256_avx_finup,
+       .descsize       =       sizeof(struct sha256_state),
+       .base           =       {
+               .cra_name       =       "sha224",
+               .cra_driver_name =      "sha224-avx",
+               .cra_priority   =       160,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA224_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
+       }
+ } };
+ static bool avx_usable(void)
  {
 -      if (!cpu_has_xfeatures(XSTATE_SSE | XSTATE_YMM, NULL)) {
 +      if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) {
                if (cpu_has_avx)
                        pr_info("AVX detected but unusable.\n");
                return false;
  
        return true;
  }
- #endif
  
- static int __init sha256_ssse3_mod_init(void)
+ static int register_sha256_avx(void)
  {
-       /* test for SSSE3 first */
-       if (cpu_has_ssse3)
-               sha256_transform_asm = sha256_transform_ssse3;
+       if (avx_usable())
+               return crypto_register_shashes(sha256_avx_algs,
+                               ARRAY_SIZE(sha256_avx_algs));
+       return 0;
+ }
  
- #ifdef CONFIG_AS_AVX
-       /* allow AVX to override SSSE3, it's a little faster */
-       if (avx_usable()) {
- #ifdef CONFIG_AS_AVX2
-               if (boot_cpu_has(X86_FEATURE_AVX2) && boot_cpu_has(X86_FEATURE_BMI2))
-                       sha256_transform_asm = sha256_transform_rorx;
-               else
+ static void unregister_sha256_avx(void)
+ {
+       if (avx_usable())
+               crypto_unregister_shashes(sha256_avx_algs,
+                               ARRAY_SIZE(sha256_avx_algs));
+ }
+ #else
+ static inline int register_sha256_avx(void) { return 0; }
+ static inline void unregister_sha256_avx(void) { }
  #endif
-                       sha256_transform_asm = sha256_transform_avx;
+ #if defined(CONFIG_AS_AVX2) && defined(CONFIG_AS_AVX)
+ asmlinkage void sha256_transform_rorx(u32 *digest, const char *data,
+                                     u64 rounds);
+ static int sha256_avx2_update(struct shash_desc *desc, const u8 *data,
+                        unsigned int len)
+ {
+       return sha256_update(desc, data, len, sha256_transform_rorx);
+ }
+ static int sha256_avx2_finup(struct shash_desc *desc, const u8 *data,
+                     unsigned int len, u8 *out)
+ {
+       return sha256_finup(desc, data, len, out, sha256_transform_rorx);
+ }
+ static int sha256_avx2_final(struct shash_desc *desc, u8 *out)
+ {
+       return sha256_avx2_finup(desc, NULL, 0, out);
+ }
+ static struct shash_alg sha256_avx2_algs[] = { {
+       .digestsize     =       SHA256_DIGEST_SIZE,
+       .init           =       sha256_base_init,
+       .update         =       sha256_avx2_update,
+       .final          =       sha256_avx2_final,
+       .finup          =       sha256_avx2_finup,
+       .descsize       =       sizeof(struct sha256_state),
+       .base           =       {
+               .cra_name       =       "sha256",
+               .cra_driver_name =      "sha256-avx2",
+               .cra_priority   =       170,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA256_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
        }
- #endif
+ }, {
+       .digestsize     =       SHA224_DIGEST_SIZE,
+       .init           =       sha224_base_init,
+       .update         =       sha256_avx2_update,
+       .final          =       sha256_avx2_final,
+       .finup          =       sha256_avx2_finup,
+       .descsize       =       sizeof(struct sha256_state),
+       .base           =       {
+               .cra_name       =       "sha224",
+               .cra_driver_name =      "sha224-avx2",
+               .cra_priority   =       170,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA224_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
+       }
+ } };
  
-       if (sha256_transform_asm) {
- #ifdef CONFIG_AS_AVX
-               if (sha256_transform_asm == sha256_transform_avx)
-                       pr_info("Using AVX optimized SHA-256 implementation\n");
- #ifdef CONFIG_AS_AVX2
-               else if (sha256_transform_asm == sha256_transform_rorx)
-                       pr_info("Using AVX2 optimized SHA-256 implementation\n");
+ static bool avx2_usable(void)
+ {
+       if (avx_usable() && boot_cpu_has(X86_FEATURE_AVX2) &&
+                   boot_cpu_has(X86_FEATURE_BMI2))
+               return true;
+       return false;
+ }
+ static int register_sha256_avx2(void)
+ {
+       if (avx2_usable())
+               return crypto_register_shashes(sha256_avx2_algs,
+                               ARRAY_SIZE(sha256_avx2_algs));
+       return 0;
+ }
+ static void unregister_sha256_avx2(void)
+ {
+       if (avx2_usable())
+               crypto_unregister_shashes(sha256_avx2_algs,
+                               ARRAY_SIZE(sha256_avx2_algs));
+ }
+ #else
+ static inline int register_sha256_avx2(void) { return 0; }
+ static inline void unregister_sha256_avx2(void) { }
  #endif
-               else
+ #ifdef CONFIG_AS_SHA256_NI
+ asmlinkage void sha256_ni_transform(u32 *digest, const char *data,
+                                  u64 rounds); /*unsigned int rounds);*/
+ static int sha256_ni_update(struct shash_desc *desc, const u8 *data,
+                        unsigned int len)
+ {
+       return sha256_update(desc, data, len, sha256_ni_transform);
+ }
+ static int sha256_ni_finup(struct shash_desc *desc, const u8 *data,
+                     unsigned int len, u8 *out)
+ {
+       return sha256_finup(desc, data, len, out, sha256_ni_transform);
+ }
+ static int sha256_ni_final(struct shash_desc *desc, u8 *out)
+ {
+       return sha256_ni_finup(desc, NULL, 0, out);
+ }
+ static struct shash_alg sha256_ni_algs[] = { {
+       .digestsize     =       SHA256_DIGEST_SIZE,
+       .init           =       sha256_base_init,
+       .update         =       sha256_ni_update,
+       .final          =       sha256_ni_final,
+       .finup          =       sha256_ni_finup,
+       .descsize       =       sizeof(struct sha256_state),
+       .base           =       {
+               .cra_name       =       "sha256",
+               .cra_driver_name =      "sha256-ni",
+               .cra_priority   =       250,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA256_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
+       }
+ }, {
+       .digestsize     =       SHA224_DIGEST_SIZE,
+       .init           =       sha224_base_init,
+       .update         =       sha256_ni_update,
+       .final          =       sha256_ni_final,
+       .finup          =       sha256_ni_finup,
+       .descsize       =       sizeof(struct sha256_state),
+       .base           =       {
+               .cra_name       =       "sha224",
+               .cra_driver_name =      "sha224-ni",
+               .cra_priority   =       250,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA224_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
+       }
+ } };
+ static int register_sha256_ni(void)
+ {
+       if (boot_cpu_has(X86_FEATURE_SHA_NI))
+               return crypto_register_shashes(sha256_ni_algs,
+                               ARRAY_SIZE(sha256_ni_algs));
+       return 0;
+ }
+ static void unregister_sha256_ni(void)
+ {
+       if (boot_cpu_has(X86_FEATURE_SHA_NI))
+               crypto_unregister_shashes(sha256_ni_algs,
+                               ARRAY_SIZE(sha256_ni_algs));
+ }
+ #else
+ static inline int register_sha256_ni(void) { return 0; }
+ static inline void unregister_sha256_ni(void) { }
  #endif
-                       pr_info("Using SSSE3 optimized SHA-256 implementation\n");
-               return crypto_register_shashes(algs, ARRAY_SIZE(algs));
+ static int __init sha256_ssse3_mod_init(void)
+ {
+       if (register_sha256_ssse3())
+               goto fail;
+       if (register_sha256_avx()) {
+               unregister_sha256_ssse3();
+               goto fail;
        }
-       pr_info("Neither AVX nor SSSE3 is available/usable.\n");
  
+       if (register_sha256_avx2()) {
+               unregister_sha256_avx();
+               unregister_sha256_ssse3();
+               goto fail;
+       }
+       if (register_sha256_ni()) {
+               unregister_sha256_avx2();
+               unregister_sha256_avx();
+               unregister_sha256_ssse3();
+               goto fail;
+       }
+       return 0;
+ fail:
        return -ENODEV;
  }
  
  static void __exit sha256_ssse3_mod_fini(void)
  {
-       crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+       unregister_sha256_ni();
+       unregister_sha256_avx2();
+       unregister_sha256_avx();
+       unregister_sha256_ssse3();
  }
  
  module_init(sha256_ssse3_mod_init);
index 0c8c38c101acda77c3bf67af0639a75451360ce8,0dfe9a2ba64bc275432a01e717141694749a7439..34e5083d6f36540e967dc755384012ca35afd714
  
  asmlinkage void sha512_transform_ssse3(u64 *digest, const char *data,
                                       u64 rounds);
- #ifdef CONFIG_AS_AVX
- asmlinkage void sha512_transform_avx(u64 *digest, const char *data,
-                                    u64 rounds);
- #endif
- #ifdef CONFIG_AS_AVX2
- asmlinkage void sha512_transform_rorx(u64 *digest, const char *data,
-                                     u64 rounds);
- #endif
  
static void (*sha512_transform_asm)(u64 *, const char *, u64);
typedef void (sha512_transform_fn)(u64 *digest, const char *data, u64 rounds);
  
- static int sha512_ssse3_update(struct shash_desc *desc, const u8 *data,
-                              unsigned int len)
+ static int sha512_update(struct shash_desc *desc, const u8 *data,
+                      unsigned int len, sha512_transform_fn *sha512_xform)
  {
        struct sha512_state *sctx = shash_desc_ctx(desc);
  
  
        kernel_fpu_begin();
        sha512_base_do_update(desc, data, len,
-                             (sha512_block_fn *)sha512_transform_asm);
+                             (sha512_block_fn *)sha512_xform);
        kernel_fpu_end();
  
        return 0;
  }
  
- static int sha512_ssse3_finup(struct shash_desc *desc, const u8 *data,
-                             unsigned int len, u8 *out)
+ static int sha512_finup(struct shash_desc *desc, const u8 *data,
+             unsigned int len, u8 *out, sha512_transform_fn *sha512_xform)
  {
        if (!irq_fpu_usable())
                return crypto_sha512_finup(desc, data, len, out);
        kernel_fpu_begin();
        if (len)
                sha512_base_do_update(desc, data, len,
-                                     (sha512_block_fn *)sha512_transform_asm);
-       sha512_base_do_finalize(desc, (sha512_block_fn *)sha512_transform_asm);
+                                     (sha512_block_fn *)sha512_xform);
+       sha512_base_do_finalize(desc, (sha512_block_fn *)sha512_xform);
        kernel_fpu_end();
  
        return sha512_base_finish(desc, out);
  }
  
+ static int sha512_ssse3_update(struct shash_desc *desc, const u8 *data,
+                      unsigned int len)
+ {
+       return sha512_update(desc, data, len, sha512_transform_ssse3);
+ }
+ static int sha512_ssse3_finup(struct shash_desc *desc, const u8 *data,
+             unsigned int len, u8 *out)
+ {
+       return sha512_finup(desc, data, len, out, sha512_transform_ssse3);
+ }
  /* Add padding and return the message digest. */
  static int sha512_ssse3_final(struct shash_desc *desc, u8 *out)
  {
        return sha512_ssse3_finup(desc, NULL, 0, out);
  }
  
- static struct shash_alg algs[] = { {
+ static struct shash_alg sha512_ssse3_algs[] = { {
        .digestsize     =       SHA512_DIGEST_SIZE,
        .init           =       sha512_base_init,
        .update         =       sha512_ssse3_update,
        }
  } };
  
+ static int register_sha512_ssse3(void)
+ {
+       if (boot_cpu_has(X86_FEATURE_SSSE3))
+               return crypto_register_shashes(sha512_ssse3_algs,
+                       ARRAY_SIZE(sha512_ssse3_algs));
+       return 0;
+ }
+ static void unregister_sha512_ssse3(void)
+ {
+       if (boot_cpu_has(X86_FEATURE_SSSE3))
+               crypto_unregister_shashes(sha512_ssse3_algs,
+                       ARRAY_SIZE(sha512_ssse3_algs));
+ }
  #ifdef CONFIG_AS_AVX
- static bool __init avx_usable(void)
+ asmlinkage void sha512_transform_avx(u64 *digest, const char *data,
+                                    u64 rounds);
+ static bool avx_usable(void)
  {
 -      if (!cpu_has_xfeatures(XSTATE_SSE | XSTATE_YMM, NULL)) {
 +      if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM, NULL)) {
                if (cpu_has_avx)
                        pr_info("AVX detected but unusable.\n");
                return false;
  
        return true;
  }
- #endif
  
- static int __init sha512_ssse3_mod_init(void)
+ static int sha512_avx_update(struct shash_desc *desc, const u8 *data,
+                      unsigned int len)
  {
-       /* test for SSSE3 first */
-       if (cpu_has_ssse3)
-               sha512_transform_asm = sha512_transform_ssse3;
+       return sha512_update(desc, data, len, sha512_transform_avx);
+ }
  
- #ifdef CONFIG_AS_AVX
-       /* allow AVX to override SSSE3, it's a little faster */
-       if (avx_usable()) {
- #ifdef CONFIG_AS_AVX2
-               if (boot_cpu_has(X86_FEATURE_AVX2))
-                       sha512_transform_asm = sha512_transform_rorx;
-               else
- #endif
-                       sha512_transform_asm = sha512_transform_avx;
+ static int sha512_avx_finup(struct shash_desc *desc, const u8 *data,
+             unsigned int len, u8 *out)
+ {
+       return sha512_finup(desc, data, len, out, sha512_transform_avx);
+ }
+ /* Add padding and return the message digest. */
+ static int sha512_avx_final(struct shash_desc *desc, u8 *out)
+ {
+       return sha512_avx_finup(desc, NULL, 0, out);
+ }
+ static struct shash_alg sha512_avx_algs[] = { {
+       .digestsize     =       SHA512_DIGEST_SIZE,
+       .init           =       sha512_base_init,
+       .update         =       sha512_avx_update,
+       .final          =       sha512_avx_final,
+       .finup          =       sha512_avx_finup,
+       .descsize       =       sizeof(struct sha512_state),
+       .base           =       {
+               .cra_name       =       "sha512",
+               .cra_driver_name =      "sha512-avx",
+               .cra_priority   =       160,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA512_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
        }
- #endif
+ },  {
+       .digestsize     =       SHA384_DIGEST_SIZE,
+       .init           =       sha384_base_init,
+       .update         =       sha512_avx_update,
+       .final          =       sha512_avx_final,
+       .finup          =       sha512_avx_finup,
+       .descsize       =       sizeof(struct sha512_state),
+       .base           =       {
+               .cra_name       =       "sha384",
+               .cra_driver_name =      "sha384-avx",
+               .cra_priority   =       160,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA384_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
+       }
+ } };
  
-       if (sha512_transform_asm) {
- #ifdef CONFIG_AS_AVX
-               if (sha512_transform_asm == sha512_transform_avx)
-                       pr_info("Using AVX optimized SHA-512 implementation\n");
- #ifdef CONFIG_AS_AVX2
-               else if (sha512_transform_asm == sha512_transform_rorx)
-                       pr_info("Using AVX2 optimized SHA-512 implementation\n");
+ static int register_sha512_avx(void)
+ {
+       if (avx_usable())
+               return crypto_register_shashes(sha512_avx_algs,
+                       ARRAY_SIZE(sha512_avx_algs));
+       return 0;
+ }
+ static void unregister_sha512_avx(void)
+ {
+       if (avx_usable())
+               crypto_unregister_shashes(sha512_avx_algs,
+                       ARRAY_SIZE(sha512_avx_algs));
+ }
+ #else
+ static inline int register_sha512_avx(void) { return 0; }
+ static inline void unregister_sha512_avx(void) { }
  #endif
-               else
+ #if defined(CONFIG_AS_AVX2) && defined(CONFIG_AS_AVX)
+ asmlinkage void sha512_transform_rorx(u64 *digest, const char *data,
+                                     u64 rounds);
+ static int sha512_avx2_update(struct shash_desc *desc, const u8 *data,
+                      unsigned int len)
+ {
+       return sha512_update(desc, data, len, sha512_transform_rorx);
+ }
+ static int sha512_avx2_finup(struct shash_desc *desc, const u8 *data,
+             unsigned int len, u8 *out)
+ {
+       return sha512_finup(desc, data, len, out, sha512_transform_rorx);
+ }
+ /* Add padding and return the message digest. */
+ static int sha512_avx2_final(struct shash_desc *desc, u8 *out)
+ {
+       return sha512_avx2_finup(desc, NULL, 0, out);
+ }
+ static struct shash_alg sha512_avx2_algs[] = { {
+       .digestsize     =       SHA512_DIGEST_SIZE,
+       .init           =       sha512_base_init,
+       .update         =       sha512_avx2_update,
+       .final          =       sha512_avx2_final,
+       .finup          =       sha512_avx2_finup,
+       .descsize       =       sizeof(struct sha512_state),
+       .base           =       {
+               .cra_name       =       "sha512",
+               .cra_driver_name =      "sha512-avx2",
+               .cra_priority   =       170,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA512_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
+       }
+ },  {
+       .digestsize     =       SHA384_DIGEST_SIZE,
+       .init           =       sha384_base_init,
+       .update         =       sha512_avx2_update,
+       .final          =       sha512_avx2_final,
+       .finup          =       sha512_avx2_finup,
+       .descsize       =       sizeof(struct sha512_state),
+       .base           =       {
+               .cra_name       =       "sha384",
+               .cra_driver_name =      "sha384-avx2",
+               .cra_priority   =       170,
+               .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
+               .cra_blocksize  =       SHA384_BLOCK_SIZE,
+               .cra_module     =       THIS_MODULE,
+       }
+ } };
+ static bool avx2_usable(void)
+ {
+       if (avx_usable() && boot_cpu_has(X86_FEATURE_AVX2) &&
+                   boot_cpu_has(X86_FEATURE_BMI2))
+               return true;
+       return false;
+ }
+ static int register_sha512_avx2(void)
+ {
+       if (avx2_usable())
+               return crypto_register_shashes(sha512_avx2_algs,
+                       ARRAY_SIZE(sha512_avx2_algs));
+       return 0;
+ }
+ static void unregister_sha512_avx2(void)
+ {
+       if (avx2_usable())
+               crypto_unregister_shashes(sha512_avx2_algs,
+                       ARRAY_SIZE(sha512_avx2_algs));
+ }
+ #else
+ static inline int register_sha512_avx2(void) { return 0; }
+ static inline void unregister_sha512_avx2(void) { }
  #endif
-                       pr_info("Using SSSE3 optimized SHA-512 implementation\n");
-               return crypto_register_shashes(algs, ARRAY_SIZE(algs));
+ static int __init sha512_ssse3_mod_init(void)
+ {
+       if (register_sha512_ssse3())
+               goto fail;
+       if (register_sha512_avx()) {
+               unregister_sha512_ssse3();
+               goto fail;
        }
-       pr_info("Neither AVX nor SSSE3 is available/usable.\n");
  
+       if (register_sha512_avx2()) {
+               unregister_sha512_avx();
+               unregister_sha512_ssse3();
+               goto fail;
+       }
+       return 0;
+ fail:
        return -ENODEV;
  }
  
  static void __exit sha512_ssse3_mod_fini(void)
  {
-       crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
+       unregister_sha512_avx2();
+       unregister_sha512_avx();
+       unregister_sha512_ssse3();
  }
  
  module_init(sha512_ssse3_mod_init);
index 19709663241223968ee73f3d1847be9e253969f7,6451d1848a7d0e19b621157159c01abe130076cf..68c3c40501ab058e7d0d1a6c13fc630d0d542c9d
@@@ -194,14 -194,15 +194,15 @@@ int x509_get_sig_params(struct x509_cer
         * digest storage space.
         */
        ret = -ENOMEM;
-       digest = kzalloc(digest_size + desc_size, GFP_KERNEL);
+       digest = kzalloc(ALIGN(digest_size, __alignof__(*desc)) + desc_size,
+                        GFP_KERNEL);
        if (!digest)
                goto error;
  
        cert->sig.digest = digest;
        cert->sig.digest_size = digest_size;
  
-       desc = digest + digest_size;
+       desc = PTR_ALIGN(digest + digest_size, __alignof__(*desc));
        desc->tfm = tfm;
        desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
  
@@@ -332,6 -333,10 +333,6 @@@ static int x509_key_preparse(struct key
                srlen = cert->raw_serial_size;
                q = cert->raw_serial;
        }
 -      if (srlen > 1 && *q == 0) {
 -              srlen--;
 -              q++;
 -      }
  
        ret = -ENOMEM;
        desc = kmalloc(sulen + 2 + srlen * 2 + 1, GFP_KERNEL);
index bc2a55bc35e4727290319b462008c695b7e2923e,186868e54ebc1438cb16995e45e1081c9ab63a6e..bd985e72520b56428af796e1531cfb8771099a9c
  
  #define CESA_SA_DESC_MAC_DATA(offset)                                 \
        cpu_to_le32(CESA_SA_DATA_SRAM_OFFSET + (offset))
- #define CESA_SA_DESC_MAC_DATA_MSK             GENMASK(15, 0)
+ #define CESA_SA_DESC_MAC_DATA_MSK             cpu_to_le32(GENMASK(15, 0))
  
  #define CESA_SA_DESC_MAC_TOTAL_LEN(total_len) cpu_to_le32((total_len) << 16)
- #define CESA_SA_DESC_MAC_TOTAL_LEN_MSK                GENMASK(31, 16)
+ #define CESA_SA_DESC_MAC_TOTAL_LEN_MSK                cpu_to_le32(GENMASK(31, 16))
  
  #define CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX    0xffff
  
  #define CESA_SA_DESC_MAC_DIGEST(offset)                                       \
        cpu_to_le32(CESA_SA_MAC_DIG_SRAM_OFFSET + (offset))
- #define CESA_SA_DESC_MAC_DIGEST_MSK           GENMASK(15, 0)
+ #define CESA_SA_DESC_MAC_DIGEST_MSK           cpu_to_le32(GENMASK(15, 0))
  
  #define CESA_SA_DESC_MAC_FRAG_LEN(frag_len)   cpu_to_le32((frag_len) << 16)
- #define CESA_SA_DESC_MAC_FRAG_LEN_MSK         GENMASK(31, 16)
+ #define CESA_SA_DESC_MAC_FRAG_LEN_MSK         cpu_to_le32(GENMASK(31, 16))
  
  #define CESA_SA_DESC_MAC_IV(offset)                                   \
        cpu_to_le32((CESA_SA_MAC_IIV_SRAM_OFFSET + (offset)) |          \
   * to be executed.
   */
  struct mv_cesa_sec_accel_desc {
-       u32 config;
-       u32 enc_p;
-       u32 enc_len;
-       u32 enc_key_p;
-       u32 enc_iv;
-       u32 mac_src_p;
-       u32 mac_digest;
-       u32 mac_iv;
+       __le32 config;
+       __le32 enc_p;
+       __le32 enc_len;
+       __le32 enc_key_p;
+       __le32 enc_iv;
+       __le32 mac_src_p;
+       __le32 mac_digest;
+       __le32 mac_iv;
  };
  
  /**
@@@ -293,11 -293,13 +293,13 @@@ struct mv_cesa_op_ctx 
   * operation.
   */
  struct mv_cesa_tdma_desc {
-       u32 byte_cnt;
-       u32 src;
-       u32 dst;
-       u32 next_dma;
-       u32 cur_dma;
+       __le32 byte_cnt;
+       __le32 src;
+       __le32 dst;
+       __le32 next_dma;
+       /* Software state */
+       dma_addr_t cur_dma;
        struct mv_cesa_tdma_desc *next;
        union {
                struct mv_cesa_op_ctx *op;
@@@ -612,7 -614,8 +614,8 @@@ struct mv_cesa_ahash_req 
        u64 len;
        int src_nents;
        bool last_req;
-       __be32 state[8];
+       bool algo_le;
+       u32 state[8];
  };
  
  /* CESA functions */
@@@ -626,7 -629,7 +629,7 @@@ static inline void mv_cesa_update_op_cf
        op->desc.config |= cpu_to_le32(cfg);
  }
  
- static inline u32 mv_cesa_get_op_cfg(struct mv_cesa_op_ctx *op)
+ static inline u32 mv_cesa_get_op_cfg(const struct mv_cesa_op_ctx *op)
  {
        return le32_to_cpu(op->desc.config);
  }
@@@ -676,7 -679,7 +679,7 @@@ static inline void mv_cesa_set_int_mask
        if (int_mask == engine->int_mask)
                return;
  
-       writel(int_mask, engine->regs + CESA_SA_INT_MSK);
+       writel_relaxed(int_mask, engine->regs + CESA_SA_INT_MSK);
        engine->int_mask = int_mask;
  }
  
@@@ -685,35 -688,14 +688,41 @@@ static inline u32 mv_cesa_get_int_mask(
        return engine->int_mask;
  }
  
+ static inline bool mv_cesa_mac_op_is_first_frag(const struct mv_cesa_op_ctx *op)
+ {
+       return (mv_cesa_get_op_cfg(op) & CESA_SA_DESC_CFG_FRAG_MSK) ==
+               CESA_SA_DESC_CFG_FIRST_FRAG;
+ }
  int mv_cesa_queue_req(struct crypto_async_request *req);
  
 +/*
 + * Helper function that indicates whether a crypto request needs to be
 + * cleaned up or not after being enqueued using mv_cesa_queue_req().
 + */
 +static inline int mv_cesa_req_needs_cleanup(struct crypto_async_request *req,
 +                                          int ret)
 +{
 +      /*
 +       * The queue still had some space, the request was queued
 +       * normally, so there's no need to clean it up.
 +       */
 +      if (ret == -EINPROGRESS)
 +              return false;
 +
 +      /*
 +       * The queue had not space left, but since the request is
 +       * flagged with CRYPTO_TFM_REQ_MAY_BACKLOG, it was added to
 +       * the backlog and will be processed later. There's no need to
 +       * clean it up.
 +       */
 +      if (ret == -EBUSY && req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG)
 +              return false;
 +
 +      /* Request wasn't queued, we need to clean it up */
 +      return true;
 +}
 +
  /* TDMA functions */
  
  static inline void mv_cesa_req_dma_iter_init(struct mv_cesa_dma_iter *iter,
@@@ -789,10 -771,8 +798,8 @@@ int mv_cesa_dma_add_data_transfer(struc
                                  dma_addr_t dst, dma_addr_t src, u32 size,
                                  u32 flags, gfp_t gfp_flags);
  
- int mv_cesa_dma_add_dummy_launch(struct mv_cesa_tdma_chain *chain,
-                                u32 flags);
- int mv_cesa_dma_add_dummy_end(struct mv_cesa_tdma_chain *chain, u32 flags);
+ int mv_cesa_dma_add_dummy_launch(struct mv_cesa_tdma_chain *chain, gfp_t flags);
+ int mv_cesa_dma_add_dummy_end(struct mv_cesa_tdma_chain *chain, gfp_t flags);
  
  int mv_cesa_dma_add_op_transfers(struct mv_cesa_tdma_chain *chain,
                                 struct mv_cesa_dma_iter *dma_iter,
index 3df2f4e7adb29a681f18a4f77acdf9df2f5e411b,2864d1e6ce2811c33175d89316729ebe34ed3dcd..6edae64bb3873e9a5dac2a0ca9e5f96555bc2695
@@@ -98,14 -98,14 +98,14 @@@ static void mv_cesa_ablkcipher_std_step
  
        /* FIXME: only update enc_len field */
        if (!sreq->skip_ctx) {
-               memcpy(engine->sram, &sreq->op, sizeof(sreq->op));
+               memcpy_toio(engine->sram, &sreq->op, sizeof(sreq->op));
                sreq->skip_ctx = true;
        } else {
-               memcpy(engine->sram, &sreq->op, sizeof(sreq->op.desc));
+               memcpy_toio(engine->sram, &sreq->op, sizeof(sreq->op.desc));
        }
  
        mv_cesa_set_int_mask(engine, CESA_SA_INT_ACCEL0_DONE);
-       writel(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG);
+       writel_relaxed(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG);
        writel(CESA_SA_CMD_EN_CESA_SA_ACCL0, engine->regs + CESA_SA_CMD);
  }
  
@@@ -145,8 -145,9 +145,9 @@@ static int mv_cesa_ablkcipher_process(s
        if (ret)
                return ret;
  
-       memcpy(ablkreq->info, engine->sram + CESA_SA_CRYPT_IV_SRAM_OFFSET,
-              crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(ablkreq)));
+       memcpy_fromio(ablkreq->info,
+                     engine->sram + CESA_SA_CRYPT_IV_SRAM_OFFSET,
+                     crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(ablkreq)));
  
        return 0;
  }
@@@ -181,7 -182,7 +182,7 @@@ mv_cesa_ablkcipher_std_prepare(struct a
        sreq->size = 0;
        sreq->offset = 0;
        mv_cesa_adjust_op(engine, &sreq->op);
-       memcpy(engine->sram, &sreq->op, sizeof(sreq->op));
+       memcpy_toio(engine->sram, &sreq->op, sizeof(sreq->op));
  }
  
  static inline void mv_cesa_ablkcipher_prepare(struct crypto_async_request *req,
  {
        struct ablkcipher_request *ablkreq = ablkcipher_request_cast(req);
        struct mv_cesa_ablkcipher_req *creq = ablkcipher_request_ctx(ablkreq);
 -
        creq->req.base.engine = engine;
  
        if (creq->req.base.type == CESA_DMA_REQ)
@@@ -430,7 -432,7 +431,7 @@@ static int mv_cesa_des_op(struct ablkci
                return ret;
  
        ret = mv_cesa_queue_req(&req->base);
 -      if (ret && ret != -EINPROGRESS)
 +      if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ablkcipher_cleanup(req);
  
        return ret;
@@@ -550,7 -552,7 +551,7 @@@ static int mv_cesa_des3_op(struct ablkc
                return ret;
  
        ret = mv_cesa_queue_req(&req->base);
 -      if (ret && ret != -EINPROGRESS)
 +      if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ablkcipher_cleanup(req);
  
        return ret;
@@@ -692,7 -694,7 +693,7 @@@ static int mv_cesa_aes_op(struct ablkci
                return ret;
  
        ret = mv_cesa_queue_req(&req->base);
 -      if (ret && ret != -EINPROGRESS)
 +      if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ablkcipher_cleanup(req);
  
        return ret;
index e8d0d712813746bd9360f4726e8cffb18110ae02,a70193ede02d2ccabbefb7236ed725181924e35b..6ec55b4a087bf740d80d3fa441d1b25c7a78ec77
@@@ -27,10 -27,10 +27,10 @@@ mv_cesa_ahash_req_iter_init(struct mv_c
                            struct ahash_request *req)
  {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
-       unsigned int len = req->nbytes;
+       unsigned int len = req->nbytes + creq->cache_ptr;
  
        if (!creq->last_req)
-               len = (len + creq->cache_ptr) & ~CESA_HASH_BLOCK_SIZE_MSK;
+               len &= ~CESA_HASH_BLOCK_SIZE_MSK;
  
        mv_cesa_req_dma_iter_init(&iter->base, len);
        mv_cesa_sg_dma_iter_init(&iter->src, req->src, DMA_TO_DEVICE);
@@@ -179,7 -179,6 +179,6 @@@ static int mv_cesa_ahash_pad_len(struc
  
  static int mv_cesa_ahash_pad_req(struct mv_cesa_ahash_req *creq, u8 *buf)
  {
-       __be64 bits = cpu_to_be64(creq->len << 3);
        unsigned int index, padlen;
  
        buf[0] = 0x80;
        index = creq->len & CESA_HASH_BLOCK_SIZE_MSK;
        padlen = mv_cesa_ahash_pad_len(creq);
        memset(buf + 1, 0, padlen - 1);
-       memcpy(buf + padlen, &bits, sizeof(bits));
+       if (creq->algo_le) {
+               __le64 bits = cpu_to_le64(creq->len << 3);
+               memcpy(buf + padlen, &bits, sizeof(bits));
+       } else {
+               __be64 bits = cpu_to_be64(creq->len << 3);
+               memcpy(buf + padlen, &bits, sizeof(bits));
+       }
  
        return padlen + 8;
  }
@@@ -203,8 -209,8 +209,8 @@@ static void mv_cesa_ahash_std_step(stru
        size_t  len;
  
        if (creq->cache_ptr)
-               memcpy(engine->sram + CESA_SA_DATA_SRAM_OFFSET, creq->cache,
-                      creq->cache_ptr);
+               memcpy_toio(engine->sram + CESA_SA_DATA_SRAM_OFFSET,
+                           creq->cache, creq->cache_ptr);
  
        len = min_t(size_t, req->nbytes + creq->cache_ptr - sreq->offset,
                    CESA_SA_SRAM_PAYLOAD_SIZE);
                        if (len + trailerlen > CESA_SA_SRAM_PAYLOAD_SIZE) {
                                len &= CESA_HASH_BLOCK_SIZE_MSK;
                                new_cache_ptr = 64 - trailerlen;
-                               memcpy(creq->cache,
-                                      engine->sram +
-                                      CESA_SA_DATA_SRAM_OFFSET + len,
-                                      new_cache_ptr);
+                               memcpy_fromio(creq->cache,
+                                             engine->sram +
+                                             CESA_SA_DATA_SRAM_OFFSET + len,
+                                             new_cache_ptr);
                        } else {
                                len += mv_cesa_ahash_pad_req(creq,
                                                engine->sram + len +
        mv_cesa_update_op_cfg(op, frag_mode, CESA_SA_DESC_CFG_FRAG_MSK);
  
        /* FIXME: only update enc_len field */
-       memcpy(engine->sram, op, sizeof(*op));
+       memcpy_toio(engine->sram, op, sizeof(*op));
  
        if (frag_mode == CESA_SA_DESC_CFG_FIRST_FRAG)
                mv_cesa_update_op_cfg(op, CESA_SA_DESC_CFG_MID_FRAG,
        creq->cache_ptr = new_cache_ptr;
  
        mv_cesa_set_int_mask(engine, CESA_SA_INT_ACCEL0_DONE);
-       writel(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG);
+       writel_relaxed(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG);
        writel(CESA_SA_CMD_EN_CESA_SA_ACCL0, engine->regs + CESA_SA_CMD);
  }
  
@@@ -306,7 -312,7 +312,7 @@@ static void mv_cesa_ahash_std_prepare(s
  
        sreq->offset = 0;
        mv_cesa_adjust_op(engine, &creq->op_tmpl);
-       memcpy(engine->sram, &creq->op_tmpl, sizeof(creq->op_tmpl));
+       memcpy_toio(engine->sram, &creq->op_tmpl, sizeof(creq->op_tmpl));
  }
  
  static void mv_cesa_ahash_step(struct crypto_async_request *req)
@@@ -338,7 -344,7 +344,7 @@@ static int mv_cesa_ahash_process(struc
  
        digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq));
        for (i = 0; i < digsize / 4; i++)
-               creq->state[i] = readl(engine->regs + CESA_IVDIG(i));
+               creq->state[i] = readl_relaxed(engine->regs + CESA_IVDIG(i));
  
        if (creq->cache_ptr)
                sg_pcopy_to_buffer(ahashreq->src, creq->src_nents,
                                   ahashreq->nbytes - creq->cache_ptr);
  
        if (creq->last_req) {
-               for (i = 0; i < digsize / 4; i++) {
-                       /*
-                        * Hardware provides MD5 digest in a different
-                        * endianness than SHA-1 and SHA-256 ones.
-                        */
-                       if (digsize == MD5_DIGEST_SIZE)
-                               creq->state[i] = cpu_to_le32(creq->state[i]);
-                       else
-                               creq->state[i] = cpu_to_be32(creq->state[i]);
-               }
+               /*
+                * Hardware's MD5 digest is in little endian format, but
+                * SHA in big endian format
+                */
+               if (creq->algo_le) {
+                       __le32 *result = (void *)ahashreq->result;
+                       for (i = 0; i < digsize / 4; i++)
+                               result[i] = cpu_to_le32(creq->state[i]);
+               } else {
+                       __be32 *result = (void *)ahashreq->result;
  
-               memcpy(ahashreq->result, creq->state, digsize);
+                       for (i = 0; i < digsize / 4; i++)
+                               result[i] = cpu_to_be32(creq->state[i]);
+               }
        }
  
        return ret;
@@@ -381,8 -390,7 +390,7 @@@ static void mv_cesa_ahash_prepare(struc
  
        digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq));
        for (i = 0; i < digsize / 4; i++)
-               writel(creq->state[i],
-                      engine->regs + CESA_IVDIG(i));
+               writel_relaxed(creq->state[i], engine->regs + CESA_IVDIG(i));
  }
  
  static void mv_cesa_ahash_req_cleanup(struct crypto_async_request *req)
@@@ -404,7 -412,7 +412,7 @@@ static const struct mv_cesa_req_ops mv_
  };
  
  static int mv_cesa_ahash_init(struct ahash_request *req,
-                             struct mv_cesa_op_ctx *tmpl)
+                             struct mv_cesa_op_ctx *tmpl, bool algo_le)
  {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
  
        mv_cesa_set_mac_op_frag_len(tmpl, 0);
        creq->op_tmpl = *tmpl;
        creq->len = 0;
+       creq->algo_le = algo_le;
  
        return 0;
  }
@@@ -462,145 -471,114 +471,114 @@@ static int mv_cesa_ahash_cache_req(stru
  }
  
  static struct mv_cesa_op_ctx *
- mv_cesa_ahash_dma_add_cache(struct mv_cesa_tdma_chain *chain,
-                           struct mv_cesa_ahash_dma_iter *dma_iter,
-                           struct mv_cesa_ahash_req *creq,
-                           gfp_t flags)
+ mv_cesa_dma_add_frag(struct mv_cesa_tdma_chain *chain,
+                    struct mv_cesa_op_ctx *tmpl, unsigned int frag_len,
+                    gfp_t flags)
  {
-       struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
-       struct mv_cesa_op_ctx *op = NULL;
+       struct mv_cesa_op_ctx *op;
        int ret;
  
-       if (!creq->cache_ptr)
-               return NULL;
+       op = mv_cesa_dma_add_op(chain, tmpl, false, flags);
+       if (IS_ERR(op))
+               return op;
  
-       ret = mv_cesa_dma_add_data_transfer(chain,
-                                           CESA_SA_DATA_SRAM_OFFSET,
-                                           ahashdreq->cache_dma,
-                                           creq->cache_ptr,
-                                           CESA_TDMA_DST_IN_SRAM,
-                                           flags);
+       /* Set the operation block fragment length. */
+       mv_cesa_set_mac_op_frag_len(op, frag_len);
+       /* Append dummy desc to launch operation */
+       ret = mv_cesa_dma_add_dummy_launch(chain, flags);
        if (ret)
                return ERR_PTR(ret);
  
-       if (!dma_iter->base.op_len) {
-               op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
-               if (IS_ERR(op))
-                       return op;
-               mv_cesa_set_mac_op_frag_len(op, creq->cache_ptr);
-               /* Add dummy desc to launch crypto operation */
-               ret = mv_cesa_dma_add_dummy_launch(chain, flags);
-               if (ret)
-                       return ERR_PTR(ret);
-       }
+       if (mv_cesa_mac_op_is_first_frag(tmpl))
+               mv_cesa_update_op_cfg(tmpl,
+                                     CESA_SA_DESC_CFG_MID_FRAG,
+                                     CESA_SA_DESC_CFG_FRAG_MSK);
  
        return op;
  }
  
- static struct mv_cesa_op_ctx *
- mv_cesa_ahash_dma_add_data(struct mv_cesa_tdma_chain *chain,
-                          struct mv_cesa_ahash_dma_iter *dma_iter,
-                          struct mv_cesa_ahash_req *creq,
-                          gfp_t flags)
+ static int
+ mv_cesa_ahash_dma_add_cache(struct mv_cesa_tdma_chain *chain,
+                           struct mv_cesa_ahash_dma_iter *dma_iter,
+                           struct mv_cesa_ahash_req *creq,
+                           gfp_t flags)
  {
-       struct mv_cesa_op_ctx *op;
-       int ret;
-       op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
-       if (IS_ERR(op))
-               return op;
-       mv_cesa_set_mac_op_frag_len(op, dma_iter->base.op_len);
-       if ((mv_cesa_get_op_cfg(&creq->op_tmpl) & CESA_SA_DESC_CFG_FRAG_MSK) ==
-           CESA_SA_DESC_CFG_FIRST_FRAG)
-               mv_cesa_update_op_cfg(&creq->op_tmpl,
-                                     CESA_SA_DESC_CFG_MID_FRAG,
-                                     CESA_SA_DESC_CFG_FRAG_MSK);
-       /* Add input transfers */
-       ret = mv_cesa_dma_add_op_transfers(chain, &dma_iter->base,
-                                          &dma_iter->src, flags);
-       if (ret)
-               return ERR_PTR(ret);
+       struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
  
-       /* Add dummy desc to launch crypto operation */
-       ret = mv_cesa_dma_add_dummy_launch(chain, flags);
-       if (ret)
-               return ERR_PTR(ret);
+       if (!creq->cache_ptr)
+               return 0;
  
-       return op;
+       return mv_cesa_dma_add_data_transfer(chain,
+                                            CESA_SA_DATA_SRAM_OFFSET,
+                                            ahashdreq->cache_dma,
+                                            creq->cache_ptr,
+                                            CESA_TDMA_DST_IN_SRAM,
+                                            flags);
  }
  
  static struct mv_cesa_op_ctx *
  mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain,
                           struct mv_cesa_ahash_dma_iter *dma_iter,
                           struct mv_cesa_ahash_req *creq,
-                          struct mv_cesa_op_ctx *op,
-                          gfp_t flags)
+                          unsigned int frag_len, gfp_t flags)
  {
        struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
        unsigned int len, trailerlen, padoff = 0;
+       struct mv_cesa_op_ctx *op;
        int ret;
  
-       if (!creq->last_req)
-               return op;
-       if (op && creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX) {
-               u32 frag = CESA_SA_DESC_CFG_NOT_FRAG;
-               if ((mv_cesa_get_op_cfg(op) & CESA_SA_DESC_CFG_FRAG_MSK) !=
-                   CESA_SA_DESC_CFG_FIRST_FRAG)
-                       frag = CESA_SA_DESC_CFG_LAST_FRAG;
+       /*
+        * If the transfer is smaller than our maximum length, and we have
+        * some data outstanding, we can ask the engine to finish the hash.
+        */
+       if (creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX && frag_len) {
+               op = mv_cesa_dma_add_frag(chain, &creq->op_tmpl, frag_len,
+                                         flags);
+               if (IS_ERR(op))
+                       return op;
  
-               mv_cesa_update_op_cfg(op, frag, CESA_SA_DESC_CFG_FRAG_MSK);
+               mv_cesa_set_mac_op_total_len(op, creq->len);
+               mv_cesa_update_op_cfg(op, mv_cesa_mac_op_is_first_frag(op) ?
+                                               CESA_SA_DESC_CFG_NOT_FRAG :
+                                               CESA_SA_DESC_CFG_LAST_FRAG,
+                                     CESA_SA_DESC_CFG_FRAG_MSK);
  
                return op;
        }
  
+       /*
+        * The request is longer than the engine can handle, or we have
+        * no data outstanding. Manually generate the padding, adding it
+        * as a "mid" fragment.
+        */
        ret = mv_cesa_ahash_dma_alloc_padding(ahashdreq, flags);
        if (ret)
                return ERR_PTR(ret);
  
        trailerlen = mv_cesa_ahash_pad_req(creq, ahashdreq->padding);
  
-       if (op) {
-               len = min(CESA_SA_SRAM_PAYLOAD_SIZE - dma_iter->base.op_len,
-                         trailerlen);
-               if (len) {
-                       ret = mv_cesa_dma_add_data_transfer(chain,
+       len = min(CESA_SA_SRAM_PAYLOAD_SIZE - frag_len, trailerlen);
+       if (len) {
+               ret = mv_cesa_dma_add_data_transfer(chain,
                                                CESA_SA_DATA_SRAM_OFFSET +
-                                               dma_iter->base.op_len,
+                                               frag_len,
                                                ahashdreq->padding_dma,
                                                len, CESA_TDMA_DST_IN_SRAM,
                                                flags);
-                       if (ret)
-                               return ERR_PTR(ret);
-                       mv_cesa_update_op_cfg(op, CESA_SA_DESC_CFG_MID_FRAG,
-                                             CESA_SA_DESC_CFG_FRAG_MSK);
-                       mv_cesa_set_mac_op_frag_len(op,
-                                       dma_iter->base.op_len + len);
-                       padoff += len;
-               }
-       }
-       if (padoff >= trailerlen)
-               return op;
+               if (ret)
+                       return ERR_PTR(ret);
  
-       if ((mv_cesa_get_op_cfg(&creq->op_tmpl) & CESA_SA_DESC_CFG_FRAG_MSK) !=
-           CESA_SA_DESC_CFG_FIRST_FRAG)
-               mv_cesa_update_op_cfg(&creq->op_tmpl,
-                                     CESA_SA_DESC_CFG_MID_FRAG,
-                                     CESA_SA_DESC_CFG_FRAG_MSK);
+               op = mv_cesa_dma_add_frag(chain, &creq->op_tmpl, frag_len + len,
+                                         flags);
+               if (IS_ERR(op))
+                       return op;
  
-       op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
-       if (IS_ERR(op))
-               return op;
+               if (len == trailerlen)
+                       return op;
  
-       mv_cesa_set_mac_op_frag_len(op, trailerlen - padoff);
+               padoff += len;
+       }
  
        ret = mv_cesa_dma_add_data_transfer(chain,
                                            CESA_SA_DATA_SRAM_OFFSET,
        if (ret)
                return ERR_PTR(ret);
  
-       /* Add dummy desc to launch crypto operation */
-       ret = mv_cesa_dma_add_dummy_launch(chain, flags);
-       if (ret)
-               return ERR_PTR(ret);
-       return op;
+       return mv_cesa_dma_add_frag(chain, &creq->op_tmpl, trailerlen - padoff,
+                                   flags);
  }
  
  static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
                      GFP_KERNEL : GFP_ATOMIC;
        struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
        struct mv_cesa_tdma_req *dreq = &ahashdreq->base;
-       struct mv_cesa_tdma_chain chain;
        struct mv_cesa_ahash_dma_iter iter;
        struct mv_cesa_op_ctx *op = NULL;
+       unsigned int frag_len;
        int ret;
  
        dreq->chain.first = NULL;
                }
        }
  
-       mv_cesa_tdma_desc_iter_init(&chain);
+       mv_cesa_tdma_desc_iter_init(&dreq->chain);
        mv_cesa_ahash_req_iter_init(&iter, req);
  
-       op = mv_cesa_ahash_dma_add_cache(&chain, &iter,
-                                        creq, flags);
-       if (IS_ERR(op)) {
-               ret = PTR_ERR(op);
+       /*
+        * Add the cache (left-over data from a previous block) first.
+        * This will never overflow the SRAM size.
+        */
+       ret = mv_cesa_ahash_dma_add_cache(&dreq->chain, &iter, creq, flags);
+       if (ret)
                goto err_free_tdma;
-       }
  
-       do {
-               if (!iter.base.op_len)
-                       break;
+       if (iter.src.sg) {
+               /*
+                * Add all the new data, inserting an operation block and
+                * launch command between each full SRAM block-worth of
+                * data. We intentionally do not add the final op block.
+                */
+               while (true) {
+                       ret = mv_cesa_dma_add_op_transfers(&dreq->chain,
+                                                          &iter.base,
+                                                          &iter.src, flags);
+                       if (ret)
+                               goto err_free_tdma;
+                       frag_len = iter.base.op_len;
  
-               op = mv_cesa_ahash_dma_add_data(&chain, &iter,
-                                               creq, flags);
-               if (IS_ERR(op)) {
-                       ret = PTR_ERR(op);
-                       goto err_free_tdma;
+                       if (!mv_cesa_ahash_req_iter_next_op(&iter))
+                               break;
+                       op = mv_cesa_dma_add_frag(&dreq->chain, &creq->op_tmpl,
+                                                 frag_len, flags);
+                       if (IS_ERR(op)) {
+                               ret = PTR_ERR(op);
+                               goto err_free_tdma;
+                       }
                }
-       } while (mv_cesa_ahash_req_iter_next_op(&iter));
+       } else {
+               /* Account for the data that was in the cache. */
+               frag_len = iter.base.op_len;
+       }
+       /*
+        * At this point, frag_len indicates whether we have any data
+        * outstanding which needs an operation.  Queue up the final
+        * operation, which depends whether this is the final request.
+        */
+       if (creq->last_req)
+               op = mv_cesa_ahash_dma_last_req(&dreq->chain, &iter, creq,
+                                               frag_len, flags);
+       else if (frag_len)
+               op = mv_cesa_dma_add_frag(&dreq->chain, &creq->op_tmpl,
+                                         frag_len, flags);
  
-       op = mv_cesa_ahash_dma_last_req(&chain, &iter, creq, op, flags);
        if (IS_ERR(op)) {
                ret = PTR_ERR(op);
                goto err_free_tdma;
  
        if (op) {
                /* Add dummy desc to wait for crypto operation end */
-               ret = mv_cesa_dma_add_dummy_end(&chain, flags);
+               ret = mv_cesa_dma_add_dummy_end(&dreq->chain, flags);
                if (ret)
                        goto err_free_tdma;
        }
        else
                creq->cache_ptr = 0;
  
-       dreq->chain = chain;
        return 0;
  
  err_free_tdma:
@@@ -739,8 -741,10 +741,8 @@@ static int mv_cesa_ahash_update(struct 
                return 0;
  
        ret = mv_cesa_queue_req(&req->base);
 -      if (ret && ret != -EINPROGRESS) {
 +      if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ahash_cleanup(req);
 -              return ret;
 -      }
  
        return ret;
  }
@@@ -764,7 -768,7 +766,7 @@@ static int mv_cesa_ahash_final(struct a
                return 0;
  
        ret = mv_cesa_queue_req(&req->base);
 -      if (ret && ret != -EINPROGRESS)
 +      if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ahash_cleanup(req);
  
        return ret;
@@@ -789,53 -793,56 +791,56 @@@ static int mv_cesa_ahash_finup(struct a
                return 0;
  
        ret = mv_cesa_queue_req(&req->base);
 -      if (ret && ret != -EINPROGRESS)
 +      if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ahash_cleanup(req);
  
        return ret;
  }
  
- static int mv_cesa_md5_init(struct ahash_request *req)
+ static int mv_cesa_ahash_export(struct ahash_request *req, void *hash,
+                               u64 *len, void *cache)
  {
-       struct mv_cesa_op_ctx tmpl;
-       mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5);
-       mv_cesa_ahash_init(req, &tmpl);
-       return 0;
- }
- static int mv_cesa_md5_export(struct ahash_request *req, void *out)
- {
-       struct md5_state *out_state = out;
        struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
        unsigned int digsize = crypto_ahash_digestsize(ahash);
+       unsigned int blocksize;
+       blocksize = crypto_ahash_blocksize(ahash);
  
-       out_state->byte_count = creq->len;
-       memcpy(out_state->hash, creq->state, digsize);
-       memset(out_state->block, 0, sizeof(out_state->block));
+       *len = creq->len;
+       memcpy(hash, creq->state, digsize);
+       memset(cache, 0, blocksize);
        if (creq->cache)
-               memcpy(out_state->block, creq->cache, creq->cache_ptr);
+               memcpy(cache, creq->cache, creq->cache_ptr);
  
        return 0;
  }
  
- static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
+ static int mv_cesa_ahash_import(struct ahash_request *req, const void *hash,
+                               u64 len, const void *cache)
  {
-       const struct md5_state *in_state = in;
        struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
        unsigned int digsize = crypto_ahash_digestsize(ahash);
+       unsigned int blocksize;
        unsigned int cache_ptr;
        int ret;
  
-       creq->len = in_state->byte_count;
-       memcpy(creq->state, in_state->hash, digsize);
+       ret = crypto_ahash_init(req);
+       if (ret)
+               return ret;
+       blocksize = crypto_ahash_blocksize(ahash);
+       if (len >= blocksize)
+               mv_cesa_update_op_cfg(&creq->op_tmpl,
+                                     CESA_SA_DESC_CFG_MID_FRAG,
+                                     CESA_SA_DESC_CFG_FRAG_MSK);
+       creq->len = len;
+       memcpy(creq->state, hash, digsize);
        creq->cache_ptr = 0;
  
-       cache_ptr = creq->len % sizeof(in_state->block);
+       cache_ptr = do_div(len, blocksize);
        if (!cache_ptr)
                return 0;
  
        if (ret)
                return ret;
  
-       memcpy(creq->cache, in_state->block, cache_ptr);
+       memcpy(creq->cache, cache, cache_ptr);
        creq->cache_ptr = cache_ptr;
  
        return 0;
  }
  
+ static int mv_cesa_md5_init(struct ahash_request *req)
+ {
+       struct mv_cesa_op_ctx tmpl = { };
+       mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5);
+       mv_cesa_ahash_init(req, &tmpl, true);
+       return 0;
+ }
+ static int mv_cesa_md5_export(struct ahash_request *req, void *out)
+ {
+       struct md5_state *out_state = out;
+       return mv_cesa_ahash_export(req, out_state->hash,
+                                   &out_state->byte_count, out_state->block);
+ }
+ static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
+ {
+       const struct md5_state *in_state = in;
+       return mv_cesa_ahash_import(req, in_state->hash, in_state->byte_count,
+                                   in_state->block);
+ }
  static int mv_cesa_md5_digest(struct ahash_request *req)
  {
        int ret;
@@@ -870,6 -904,7 +902,7 @@@ struct ahash_alg mv_md5_alg = 
        .import = mv_cesa_md5_import,
        .halg = {
                .digestsize = MD5_DIGEST_SIZE,
+               .statesize = sizeof(struct md5_state),
                .base = {
                        .cra_name = "md5",
                        .cra_driver_name = "mv-md5",
  
  static int mv_cesa_sha1_init(struct ahash_request *req)
  {
-       struct mv_cesa_op_ctx tmpl;
+       struct mv_cesa_op_ctx tmpl = { };
  
        mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA1);
  
-       mv_cesa_ahash_init(req, &tmpl);
+       mv_cesa_ahash_init(req, &tmpl, false);
  
        return 0;
  }
  static int mv_cesa_sha1_export(struct ahash_request *req, void *out)
  {
        struct sha1_state *out_state = out;
-       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
-       struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
-       unsigned int digsize = crypto_ahash_digestsize(ahash);
-       out_state->count = creq->len;
-       memcpy(out_state->state, creq->state, digsize);
-       memset(out_state->buffer, 0, sizeof(out_state->buffer));
-       if (creq->cache)
-               memcpy(out_state->buffer, creq->cache, creq->cache_ptr);
  
-       return 0;
+       return mv_cesa_ahash_export(req, out_state->state, &out_state->count,
+                                   out_state->buffer);
  }
  
  static int mv_cesa_sha1_import(struct ahash_request *req, const void *in)
  {
        const struct sha1_state *in_state = in;
-       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
-       struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
-       unsigned int digsize = crypto_ahash_digestsize(ahash);
-       unsigned int cache_ptr;
-       int ret;
  
-       creq->len = in_state->count;
-       memcpy(creq->state, in_state->state, digsize);
-       creq->cache_ptr = 0;
-       cache_ptr = creq->len % SHA1_BLOCK_SIZE;
-       if (!cache_ptr)
-               return 0;
-       ret = mv_cesa_ahash_alloc_cache(req);
-       if (ret)
-               return ret;
-       memcpy(creq->cache, in_state->buffer, cache_ptr);
-       creq->cache_ptr = cache_ptr;
-       return 0;
+       return mv_cesa_ahash_import(req, in_state->state, in_state->count,
+                                   in_state->buffer);
  }
  
  static int mv_cesa_sha1_digest(struct ahash_request *req)
@@@ -959,6 -967,7 +965,7 @@@ struct ahash_alg mv_sha1_alg = 
        .import = mv_cesa_sha1_import,
        .halg = {
                .digestsize = SHA1_DIGEST_SIZE,
+               .statesize = sizeof(struct sha1_state),
                .base = {
                        .cra_name = "sha1",
                        .cra_driver_name = "mv-sha1",
  
  static int mv_cesa_sha256_init(struct ahash_request *req)
  {
-       struct mv_cesa_op_ctx tmpl;
+       struct mv_cesa_op_ctx tmpl = { };
  
        mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA256);
  
-       mv_cesa_ahash_init(req, &tmpl);
+       mv_cesa_ahash_init(req, &tmpl, false);
  
        return 0;
  }
@@@ -998,44 -1007,17 +1005,17 @@@ static int mv_cesa_sha256_digest(struc
  static int mv_cesa_sha256_export(struct ahash_request *req, void *out)
  {
        struct sha256_state *out_state = out;
-       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
-       struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
-       unsigned int ds = crypto_ahash_digestsize(ahash);
  
-       out_state->count = creq->len;
-       memcpy(out_state->state, creq->state, ds);
-       memset(out_state->buf, 0, sizeof(out_state->buf));
-       if (creq->cache)
-               memcpy(out_state->buf, creq->cache, creq->cache_ptr);
-       return 0;
+       return mv_cesa_ahash_export(req, out_state->state, &out_state->count,
+                                   out_state->buf);
  }
  
  static int mv_cesa_sha256_import(struct ahash_request *req, const void *in)
  {
        const struct sha256_state *in_state = in;
-       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
-       struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
-       unsigned int digsize = crypto_ahash_digestsize(ahash);
-       unsigned int cache_ptr;
-       int ret;
-       creq->len = in_state->count;
-       memcpy(creq->state, in_state->state, digsize);
-       creq->cache_ptr = 0;
-       cache_ptr = creq->len % SHA256_BLOCK_SIZE;
-       if (!cache_ptr)
-               return 0;
-       ret = mv_cesa_ahash_alloc_cache(req);
-       if (ret)
-               return ret;
-       memcpy(creq->cache, in_state->buf, cache_ptr);
-       creq->cache_ptr = cache_ptr;
  
-       return 0;
+       return mv_cesa_ahash_import(req, in_state->state, in_state->count,
+                                   in_state->buf);
  }
  
  struct ahash_alg mv_sha256_alg = {
        .import = mv_cesa_sha256_import,
        .halg = {
                .digestsize = SHA256_DIGEST_SIZE,
+               .statesize = sizeof(struct sha256_state),
                .base = {
                        .cra_name = "sha256",
                        .cra_driver_name = "mv-sha256",
@@@ -1231,12 -1214,12 +1212,12 @@@ static int mv_cesa_ahmac_cra_init(struc
  static int mv_cesa_ahmac_md5_init(struct ahash_request *req)
  {
        struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
-       struct mv_cesa_op_ctx tmpl;
+       struct mv_cesa_op_ctx tmpl = { };
  
        mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_MD5);
        memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
  
-       mv_cesa_ahash_init(req, &tmpl);
+       mv_cesa_ahash_init(req, &tmpl, true);
  
        return 0;
  }
@@@ -1301,12 -1284,12 +1282,12 @@@ struct ahash_alg mv_ahmac_md5_alg = 
  static int mv_cesa_ahmac_sha1_init(struct ahash_request *req)
  {
        struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
-       struct mv_cesa_op_ctx tmpl;
+       struct mv_cesa_op_ctx tmpl = { };
  
        mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA1);
        memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
  
-       mv_cesa_ahash_init(req, &tmpl);
+       mv_cesa_ahash_init(req, &tmpl, false);
  
        return 0;
  }
@@@ -1391,12 -1374,12 +1372,12 @@@ static int mv_cesa_ahmac_sha256_setkey(
  static int mv_cesa_ahmac_sha256_init(struct ahash_request *req)
  {
        struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
-       struct mv_cesa_op_ctx tmpl;
+       struct mv_cesa_op_ctx tmpl = { };
  
        mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA256);
        memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
  
-       mv_cesa_ahash_init(req, &tmpl);
+       mv_cesa_ahash_init(req, &tmpl, false);
  
        return 0;
  }