update OCF framework to version 20100325
authorJo-Philipp Wich <jow@openwrt.org>
Tue, 4 May 2010 20:59:19 +0000 (20:59 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Tue, 4 May 2010 20:59:19 +0000 (20:59 +0000)
SVN-Revision: 21356

198 files changed:
target/linux/generic-2.6/config-2.6.25
target/linux/generic-2.6/config-2.6.30
target/linux/generic-2.6/config-2.6.31
target/linux/generic-2.6/config-2.6.32
target/linux/generic-2.6/config-2.6.33
target/linux/generic-2.6/config-2.6.34
target/linux/generic-2.6/files/crypto/ocf/ChangeLog [deleted file]
target/linux/generic-2.6/files/crypto/ocf/Config.in
target/linux/generic-2.6/files/crypto/ocf/Kconfig
target/linux/generic-2.6/files/crypto/ocf/Makefile
target/linux/generic-2.6/files/crypto/ocf/README [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/c7108/Makefile [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/c7108/aes-7108.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/c7108/aes-7108.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/criov.c
target/linux/generic-2.6/files/crypto/ocf/crypto.c
target/linux/generic-2.6/files/crypto/ocf/cryptocteon/Makefile [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/cryptocteon/cavium_crypto.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/cryptocteon/cryptocteon.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/cryptodev.c
target/linux/generic-2.6/files/crypto/ocf/cryptodev.h
target/linux/generic-2.6/files/crypto/ocf/cryptosoft.c
target/linux/generic-2.6/files/crypto/ocf/ep80579/Makefile
target/linux/generic-2.6/files/crypto/ocf/ep80579/environment.mk [deleted file]
target/linux/generic-2.6/files/crypto/ocf/ep80579/icp_asym.c
target/linux/generic-2.6/files/crypto/ocf/ep80579/icp_common.c
target/linux/generic-2.6/files/crypto/ocf/ep80579/icp_ocf.h
target/linux/generic-2.6/files/crypto/ocf/ep80579/icp_sym.c
target/linux/generic-2.6/files/crypto/ocf/ep80579/linux_2.6_kernel_space.mk [deleted file]
target/linux/generic-2.6/files/crypto/ocf/hifn/hifn7751.c
target/linux/generic-2.6/files/crypto/ocf/ixp4xx/ixp4xx.c
target/linux/generic-2.6/files/crypto/ocf/kirkwood/Makefile [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/AES/mvAes.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/AES/mvAesAlg.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/AES/mvAesAlg.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/AES/mvAesApi.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/mvCesa.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/mvCesa.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/mvCesaDebug.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/mvCesaRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/mvCesaTest.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/mvLru.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/mvLru.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/mvMD5.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/mvMD5.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/mvSHA1.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa/mvSHA1.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/cesa_ocf_drv.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/common/mv802_3.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/common/mvCommon.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/common/mvCommon.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/common/mvDebug.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/common/mvDebug.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/common/mvDeviceId.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/common/mvHalVer.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/common/mvStack.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/common/mvStack.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/common/mvTypes.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/dbg-trace.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/dbg-trace.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvLib.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvLib.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvSpec.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/boardEnv/mvBoardEnvSpec.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/cpu/mvCpu.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/cpu/mvCpu.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAddrDec.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvAsm.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvLib.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/mvCtrlEnvSpec.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbus.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvAhbToMbusRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIf.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvCpuIfRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysAudio.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysAudio.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysCesa.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysCesa.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysDram.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysDram.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysGbe.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysGbe.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysPex.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysPex.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSata.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSata.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysSdmmc.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTdm.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTdm.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysTs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysUsb.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysUsb.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysXor.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/ctrlEnv/sys/mvSysXor.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDevice.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDevice.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/kw_family/device/mvDeviceRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/linux_oss/mvOs.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/linux_oss/mvOs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/linux_oss/mvOsSata.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mvSysHwConfig.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmr.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/cntmr/mvCntmrRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuCntrs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/cpu/mvCpuL2Cntrs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDram.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIf.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfConfig.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr1_2/mvDramIfRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIf.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfConfig.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/mvDramIfStaticInit.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/spd/mvSpd.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/ddr2/spd/mvSpd.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEth.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthDebug.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthGbe.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/eth/gbe/mvEthRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/eth/mvEth.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGpp.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/gpp/mvGppRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIf.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIf.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/mvPciIfRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/pci_util/mvPciUtils.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/pci_util/mvPciUtils.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPci.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pci/mvPciRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPex.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvPexRegs.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/pex/mvVrtBrgPex.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlash.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/sflash/mvSFlashSpec.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpi.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiCmnd.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/spi/mvSpiSpec.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.c [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsi.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/kirkwood/mvHal/mv_hal/twsi/mvTwsiSpec.h [new file with mode: 0644]
target/linux/generic-2.6/files/crypto/ocf/ocf-bench.c
target/linux/generic-2.6/files/crypto/ocf/ocf-compat.h
target/linux/generic-2.6/files/crypto/ocf/ocfnull/ocfnull.c
target/linux/generic-2.6/files/crypto/ocf/random.c
target/linux/generic-2.6/files/crypto/ocf/rndtest.c
target/linux/generic-2.6/files/crypto/ocf/safe/safe.c
target/linux/generic-2.6/files/crypto/ocf/safe/safevar.h
target/linux/generic-2.6/files/crypto/ocf/talitos/talitos.c
target/linux/generic-2.6/files/crypto/ocf/uio.h
target/linux/generic-2.6/patches-2.6.25/971-ocf_20080917.patch [deleted file]
target/linux/generic-2.6/patches-2.6.25/971-ocf_20100325.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.25/972-ocf_compile_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.30/970-ocf_kbuild_integration.patch
target/linux/generic-2.6/patches-2.6.30/971-ocf_20080917.patch [deleted file]
target/linux/generic-2.6/patches-2.6.30/971-ocf_20100325.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.30/972-ocf_compile_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.30/973-ocf_2.6.27_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.31/970-ocf_kbuild_integration.patch
target/linux/generic-2.6/patches-2.6.31/971-ocf_20080917.patch [deleted file]
target/linux/generic-2.6/patches-2.6.31/971-ocf_20100325.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.31/972-ocf_compile_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.31/973-ocf_2.6.27_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.32/970-ocf_kbuild_integration.patch
target/linux/generic-2.6/patches-2.6.32/971-ocf_20080917.patch [deleted file]
target/linux/generic-2.6/patches-2.6.32/971-ocf_20100325.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.32/972-ocf_compile_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.32/973-ocf_2.6.27_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.33/970-ocf_kbuild_integration.patch
target/linux/generic-2.6/patches-2.6.33/971-ocf_20080917.patch [deleted file]
target/linux/generic-2.6/patches-2.6.33/971-ocf_20100325.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.33/972-ocf_compile_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.33/973-ocf_2.6.27_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.34/970-ocf_kbuild_integration.patch
target/linux/generic-2.6/patches-2.6.34/971-ocf_20080917.patch [deleted file]
target/linux/generic-2.6/patches-2.6.34/971-ocf_20100325.patch [new file with mode: 0644]
target/linux/generic-2.6/patches-2.6.34/972-ocf_compile_fix.patch [deleted file]
target/linux/generic-2.6/patches-2.6.34/973-ocf_2.6.27_fix.patch [deleted file]

index 2312891..a97db40 100644 (file)
@@ -1128,10 +1128,13 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NTFS_RW is not set
 # CONFIG_NVRAM is not set
 # CONFIG_OCF_BENCH is not set
+# CONFIG_OCF_C7108 is not set
+# CONFIG_OCF_CRYPTOCTEON is not set
 # CONFIG_OCF_EP80579 is not set
 # CONFIG_OCF_HIFNHIPP is not set
 # CONFIG_OCF_HIFN is not set
 # CONFIG_OCF_IXP4XX is not set
+# CONFIG_OCF_KIRKWOOD is not set
 # CONFIG_OCF_OCF is not set
 # CONFIG_OCF_OCFNULL is not set
 # CONFIG_OCFS2_FS is not set
index 0ae8293..79cdf76 100644 (file)
@@ -1525,10 +1525,13 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NTFS_RW is not set
 # CONFIG_NVRAM is not set
 # CONFIG_OCF_BENCH is not set
+# CONFIG_OCF_C7108 is not set
+# CONFIG_OCF_CRYPTOCTEON is not set
 # CONFIG_OCF_EP80579 is not set
 # CONFIG_OCF_HIFNHIPP is not set
 # CONFIG_OCF_HIFN is not set
 # CONFIG_OCF_IXP4XX is not set
+# CONFIG_OCF_KIRKWOOD is not set
 # CONFIG_OCF_OCF is not set
 # CONFIG_OCF_OCFNULL is not set
 # CONFIG_OCFS2_FS is not set
index 585f2a5..6017db9 100644 (file)
@@ -1522,10 +1522,13 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NTFS_RW is not set
 # CONFIG_NVRAM is not set
 # CONFIG_OCF_BENCH is not set
+# CONFIG_OCF_C7108 is not set
+# CONFIG_OCF_CRYPTOCTEON is not set
 # CONFIG_OCF_EP80579 is not set
 # CONFIG_OCF_HIFNHIPP is not set
 # CONFIG_OCF_HIFN is not set
 # CONFIG_OCF_IXP4XX is not set
+# CONFIG_OCF_KIRKWOOD is not set
 # CONFIG_OCF_OCF is not set
 # CONFIG_OCF_OCFNULL is not set
 # CONFIG_OCFS2_FS is not set
index 7a2c896..41a4ef3 100644 (file)
@@ -1603,10 +1603,13 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NTFS_RW is not set
 # CONFIG_NVRAM is not set
 # CONFIG_OCF_BENCH is not set
+# CONFIG_OCF_C7108 is not set
+# CONFIG_OCF_CRYPTOCTEON is not set
 # CONFIG_OCF_EP80579 is not set
 # CONFIG_OCF_HIFNHIPP is not set
 # CONFIG_OCF_HIFN is not set
 # CONFIG_OCF_IXP4XX is not set
+# CONFIG_OCF_KIRKWOOD is not set
 # CONFIG_OCF_OCF is not set
 # CONFIG_OCF_OCFNULL is not set
 # CONFIG_OCFS2_FS is not set
index 70af22b..77e0060 100644 (file)
@@ -1616,10 +1616,13 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NVRAM is not set
 # CONFIG_OC_ETM is not set
 # CONFIG_OCF_BENCH is not set
+# CONFIG_OCF_C7108 is not set
+# CONFIG_OCF_CRYPTOCTEON is not set
 # CONFIG_OCF_EP80579 is not set
 # CONFIG_OCF_HIFNHIPP is not set
 # CONFIG_OCF_HIFN is not set
 # CONFIG_OCF_IXP4XX is not set
+# CONFIG_OCF_KIRKWOOD is not set
 # CONFIG_OCF_OCF is not set
 # CONFIG_OCF_OCFNULL is not set
 # CONFIG_OCFS2_FS is not set
index ab12b28..ba7cc73 100644 (file)
@@ -1629,10 +1629,13 @@ CONFIG_NLS_DEFAULT="iso8859-1"
 # CONFIG_NVRAM is not set
 # CONFIG_OC_ETM is not set
 # CONFIG_OCF_BENCH is not set
+# CONFIG_OCF_C7108 is not set
+# CONFIG_OCF_CRYPTOCTEON is not set
 # CONFIG_OCF_EP80579 is not set
 # CONFIG_OCF_HIFNHIPP is not set
 # CONFIG_OCF_HIFN is not set
 # CONFIG_OCF_IXP4XX is not set
+# CONFIG_OCF_KIRKWOOD is not set
 # CONFIG_OCF_OCF is not set
 # CONFIG_OCF_OCFNULL is not set
 # CONFIG_OCFS2_FS is not set
diff --git a/target/linux/generic-2.6/files/crypto/ocf/ChangeLog b/target/linux/generic-2.6/files/crypto/ocf/ChangeLog
deleted file mode 100644 (file)
index e913ef2..0000000
+++ /dev/null
@@ -1,1960 +0,0 @@
-2008-09-18 01:27  davidm
-
-       * Makefile, README, README.sglinux,
-       patches/linux-2.6.26-natt.patch, patches/linux-2.6.26-ocf.patch,
-       patches/openssl-0.9.8g.patch, patches/openssl-0.9.8i.patch: 
-       
-       Updates for a new OCF release with openssl-0.9.8i and linux-2.6.26
-       support.
-
-2008-09-18 00:19  davidm
-
-       * Config.in, Kconfig, Makefile, ep80579/Makefile,
-       ep80579/environment.mk, ep80579/icp_asym.c, ep80579/icp_common.c,
-       ep80579/icp_ocf.h, ep80579/icp_sym.c,
-       ep80579/linux_2.6_kernel_space.mk: 
-       
-       A new driver from Intel for their Intel QuickAssist enabled EP80579
-       Integrated Processor Product Line.
-       
-       Adrian Hoban  Brad Vrabete
-       
-
-2008-07-25 01:01  gerg
-
-       * ocf-compat.h: 
-       
-       From linux-2.6.26 onwards there is now a linux/fdtable.h include
-       that contains the file_fdtable() definition.
-
-2008-07-05 01:20  davidm
-
-       * Makefile, patches/linux-2.6.25-natt.patch,
-       patches/linux-2.6.25-ocf.patch: 
-       
-       A new ocf-linux release and some patches to send to the OS guys.
-
-2008-07-03 21:21  davidm
-
-       * crypto.c: 
-       
-       Clean up a some possible deadlock/busy wait issues with
-       locking/sleeping.  This has greatly improved openswan 2.6.14
-       reliability ;-)
-       
-       Make more of our state available in /sys for debugging.
-
-2008-06-23 20:38  davidm
-
-       * Config.in, Kconfig: 
-       
-       Some settings should be bool's John Gumb 
-
-2008-05-28 03:43  philipc
-
-       * ixp4xx/ixp4xx.c:  Revert previous checkin since the
-       callbacks are meant to complete the crypto request.  Before
-       reverting this, CONFIG_DEBUG_SLAB gives: slab error in
-       verify_redzone_free(): cache `ixp4xx_q': double free detected when
-       trying to ssh to the device.
-
-2008-04-27 19:31  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       We were not completing a crypto request under some error
-       conditions.
-
-2008-04-02 01:51  davidm
-
-       * talitos/talitos.c: 
-       
-       This patch is for crypto/ocf/talitos for use on linux 2.6.23.  It
-       is applied to the ocf-linux-20071215 release.
-       
-       Signed-off-by: Lee Nipper 
-
-2008-02-29 00:43  davidm
-
-       * crypto.c, ocf-compat.h, ixp4xx/ixp4xx.c: 
-       
-       freshen  up the 2.4 support,  some recent OCF changes and openswan
-       changes are not that old-os friendly.
-       
-       Force OCF to select HW/SW,  otherwise it may get stuck on the first
-       device.  This change means we will favour HW over SW,  but we will
-       use both as required.  Passing in a crid of 0 to crypto_newsession
-       effectively meant we were stuck on the first device registered with
-       OCF,  not good.  This only applied to ipsec,  cryptodev already did
-       the right thing.
-
-2008-01-31 07:37  gerg
-
-       * hifn/hifn7751.c: 
-       
-       The linux-2.6.24 modules build fails if the pci ID table doesn't
-       have a NULL entry at the end. So add one.
-
-2008-01-29 09:16  gerg
-
-       * cryptosoft.c, ocf-compat.h: 
-       
-       Added some compatability macros for scatterlist changes from 2.6.24
-       onwards.
-
-2007-12-16 07:31  davidm
-
-       * Makefile: 
-       
-       missed an openssl patch name change
-
-2007-12-16 07:27  davidm
-
-       * Makefile, README, README.sglinux, patches/linux-2.6.23-ocf.patch,
-       patches/openssl-0.9.8e.patch, patches/openssl-0.9.8g.patch,
-       patches/ssl.patch: 
-       
-       updates for a new ocf release and associated bits
-
-2007-12-16 06:36  davidm
-
-       * crypto.c: 
-       
-       Be very careful what you do while potentially in an driver unload
-       state or we will call through NULL pointers.
-       
-       Reported by Nawang Chhetan .
-
-2007-12-14 22:32  davidm
-
-       * cryptodev.c: 
-       
-       Add in an unlock_ioctl when available to help SMP systems a lot. 
-       Otherwise all ioctls get a BKL :-(
-       
-       Problem found by Egor N. Martovetsky 
-
-2007-12-14 18:29  davidm
-
-       * cryptosoft.c: 
-       
-       reformat the alg table to make it easier to read.
-
-2007-12-14 18:29  davidm
-
-       * crypto.c: 
-       
-       Fix more driver locking/sleeping bugs report by Nawang Chhetan
-       
-
-2007-12-12 21:36  davidm
-
-       * Config.in, Kconfig, Makefile, pasemi/Makefile, pasemi/pasemi.c,
-       pasemi/pasemi_fnu.h: 
-       
-       Here I'm including my PA Semi driver patch to OCF.  Please consider
-       it for inclusion into next OCF release.
-       
-       Egor N. Martovetsky 
-
-2007-12-05 00:37  davidm
-
-       * patches/: linux-2.4.35-ocf.patch, linux-2.6.22-ocf.patch: 
-       
-       More correct count setting if we get a signal
-       
-       Adrian Hoban 
-
-2007-12-05 00:02  davidm
-
-       * random.c: 
-       
-       OCF has a static array for holding random data. The random number
-       generator I have can write directly into physically contiguous
-       memory. Static memory comes from the heap and isn't physically
-       contiguous. I could use kmalloc'd memory and then copy into the OCF
-       static buf but I'd like to avoid a memory copy. The following patch
-       (Physically_Contig_Rand.patch) allows me to avoid a memory copy and
-       should not impact the other OCF drivers:
-       
-       Adrian Hoban 
-
-2007-12-05 00:01  davidm
-
-       * Kconfig: 
-       
-       Fix a typo in the Kconfig
-
-2007-11-23 19:15  davidm
-
-       * talitos/talitos_dev.h: 
-       
-       fix the DPRINTF macro so that it actually compiles.
-
-2007-11-22 19:41  davidm
-
-       * ocf-compat.h, talitos/talitos.c, talitos/talitos_dev.h: 
-       
-       Various updates to get talitos compiling and work on real-world (ie
-       ubuntu) kernels.
-
-2007-11-08 02:21  davidm
-
-       * crypto.c: 
-       
-       keep and eye on us being completely blocked.  If we have Q's to
-       process, but all the requests are blocked,  sleep.  We do not want
-       to busy loop until a driver unblocks as it uses valuable CPU
-       resources that could be doing something much more important ;-)
-
-2007-11-07 19:04  davidm
-
-       * hifn/hifn7751.c: 
-       
-       hifn driver was failing to unblock itself under some "out of
-       resources" conditions.  It would return ERESTART to signal it was
-       full but never call crypto_unblock to start things moving again.
-
-2007-11-06 02:09  davidm
-
-       * hifn/hifn7751.c: 
-       
-       Remove some bogus trace left in the driver for the overflow (too
-       busy) case.
-
-2007-10-12 21:10  gerg
-
-       * crypto.c, ixp4xx/ixp4xx.c: 
-       
-       Fix up use of kmem_cache_create() - it takes one less argument in
-       2.6.23 onwards.
-
-2007-10-03 02:41  gerg
-
-       * ixp4xx/Makefile: 
-       
-       The directory locations for includes in CSR-2.4 is different.  Need
-       to modify the CFLAGS accordingly if using CSR-2.4.
-
-2007-09-22 00:39  philipc
-
-       * ixp4xx/Makefile:  linux 2.4 make dep was failing.  This is
-       a quick fix to get it building, need to double check this.
-
-2007-09-19 00:13  mmccreat
-
-       * Config.in:  Add config option CONFIG_OCF_IXP4XX_SHA1_MD5,
-       that enables SHA1 and MD5 hashing to be done by the IXP4xx crypto
-       accelerator (although it is much slower than using cryptosoft).
-
-2007-09-18 21:45  mmccreat
-
-       * Makefile, random.c:  - Force the inclusion of autoconf.h,
-       which contains #defines for CONFIG_xxx   options for OCF.  -
-       Removing additional -D option, now that we are including the
-       CONFIG_xxx   #defines.
-
-2007-09-18 21:44  mmccreat
-
-       * Kconfig:  Add config option CONFIG_OCF_IXP4XX_SHA1_MD5,
-       that enables SHA1 and MD5 hashing to be done by the IXP4xx crypto
-       accelerator (although it is much slower than using cryptosoft).
-
-2007-09-18 21:37  mmccreat
-
-       * cryptodev.h:  The CRYPTO_MAX_DATA_LEN limit should be
-       0xFFFF ie 64K - 1.
-
-2007-09-18 21:19  mmccreat
-
-       * ixp4xx/ixp4xx.c:  - Rework the code so that the correct IXP
-       function, ixCryptoAccHashPerform(), is   used to calculate SHA1 and
-       MD5 hashes.    NB: The performance of using the IXP4xx hardware is
-       really, really poor    compared to using cryptosoft (and the kernel
-       crypto).  - Only support SHA1 and MD5 hashing if the
-       CONFIG_OCF_IXP4XX_SHA1_MD5 is   enabled.
-
-2007-08-30 21:42  davidm
-
-       * Makefile: 
-       
-       do not archive build files in the crypto-tools archive
-
-2007-08-22 19:19  mmccreat
-
-       * cryptodev.c:  Fix up the checking for key lengths, when the
-       key can be of unlimited size.
-
-2007-08-16 01:50  davidm
-
-       * Makefile: 
-       
-       Better 2.4 compat for "make dep" now working with fastdep.
-
-2007-07-28 08:25  davidm
-
-       * Makefile, README, README.sglinux, patches/crypto-tools.patch,
-       patches/linux-2.4.29-ocf.patch, patches/linux-2.4.35-ocf.patch,
-       patches/linux-2.6.11-ocf.patch, patches/linux-2.6.22-ocf.patch,
-       patches/ssl.patch: 
-       
-       Update all the patches and put the patch making target back into
-       the Makefile.
-
-2007-07-28 08:25  davidm
-
-       * hifn/hifn7751.c: 
-       
-       fix an unused variable warning when HARVESTING is disabled
-
-2007-07-27 21:33  davidm
-
-       * hifn/hifn7751.c, ixp4xx/ixp4xx.c, safe/safe.c, talitos/talitos.c:
-       
-       
-       Remove all the random code if OCF does not have radom harvesting
-       enabled.
-
-2007-07-26 00:36  davidm
-
-       * Kconfig, hifn/hifnHIPP.c, hifn/hifnHIPPvar.h: 
-       
-       Changes to get the hifn HIPP stub driver to build.
-
-2007-07-25 21:25  davidm
-
-       * Makefile, hifn/Makefile, hifn/hifnHIPP.c, hifn/hifnHIPPreg.h,
-       hifn/hifnHIPPvar.h, ixp4xx/Makefile, ocfnull/Makefile,
-       safe/Makefile, talitos/Makefile: 
-       
-       Bring in the hifnHIPP driver written by Xelerance.  This is the
-       super hifn chip with full protocol offload.
-       
-       Switch to much more traditional Makefile/subdir building.  The
-       Makefiles are nicer now,  but still not beautiful,  2.6 and 2.4
-       capable builds result in a certain amount of uglyiness.
-
-2007-07-24 21:46  davidm
-
-       * cryptodev.c: 
-       
-       Clean up all the driver id checking and session management so
-       adding/removing drivers all continues to run cleanly.
-
-2007-07-24 20:14  davidm
-
-       * talitos/talitos.c: 
-       
-       From: Ahsan Kabir 
-       
-       less than .1% packet corruption was detected using the talitos
-       driver. It turns out we don't need the cipher iv out len/ptr field
-       to do ESP IPsec. Therefore we set the len field as 0, which tells
-       the SEC not to do anything with this len/ptr field.
-       
-       Signed-off-by: Ahsan Kabir 
-       Signed-off-by: Kim Phillips 
-
-2007-07-24 08:25  davidm
-
-       * cryptosoft.c, ocf-bench.c, hifn/hifn7751.c, ixp4xx/ixp4xx.c,
-       safe/safe.c, talitos/talitos.c: 
-       
-       Switch the remaining GFP_ATOMIC to the newer and not deprecated
-       SLAB_ATOMIC
-
-2007-07-23 22:16  mmccreat
-
-       * ixp4xx/ixp4xx.c:  Add missing ";" from end of dprintk()
-       call!
-
-2007-07-21 01:16  davidm
-
-       * ocf-compat.h, rndtest.c, hifn/hifn7751.c, safe/safe.c: 
-       
-       pci_register_driver is nothing like it is depending on the kernel,
-       so we need a compat function to fix it up for all kernels before
-       2.6.10, and in different ways for older and not so older versions.
-
-2007-07-20 21:54  davidm
-
-       * safe/safe.c: 
-       
-       Make the debug macro ';' safe so you do not get compiler warnings
-
-2007-07-20 21:53  davidm
-
-       * talitos/: talitos.c, talitos_dev.h, talitos_soft.h: 
-       
-       update to the latest FreeBSD driver structure and fix up the code
-       as required.
-
-2007-07-20 03:07  davidm
-
-       * rndtest.c: 
-       
-       more headers needed to compile on 2.4
-
-2007-07-20 03:00  davidm
-
-       * cryptosoft.c: 
-       
-       Put in the 2.4 stubs to support compression
-
-2007-07-20 02:53  davidm
-
-       * crypto.c, ocf-compat.h: 
-       
-       move some more compat stuff into the compat header.
-
-2007-07-20 02:47  davidm
-
-       * talitos/talitos.c: 
-       
-       support of_platform_driver for newer, ARCH=powerpc based kernels. 
-       Signed-off-by: Kim Phillips 
-
-2007-07-20 02:46  davidm
-
-       * talitos/talitos.c: 
-       
-       From: Ahsan Kabir 
-       
-       When Talitos completes job both the channel and execution unit are
-       capable of generating interrupts.  Talitos used to take two
-       interrupts per request - one for channel completion and the other
-       for execution unit completion. This patch ensures that Talitos
-       takes interrupt only for channel completion. Execution unit will
-       generate interrupt only when there is error and the error
-       interrupts for execution units are not masked.
-       
-       Signed-off-by: Ahsan Kabir 
-       Signed-off-by: Kim Phillips 
-
-2007-07-20 02:37  davidm
-
-       * cryptodev.c: 
-       
-       Unless the user specifies,  select from both HW and SW.
-       
-       Clean up some debug to report the actual ioctl name.
-       
-       Compiler warning on newer compilers.
-
-2007-07-20 02:35  davidm
-
-       * cryptodev.h: 
-       
-       moved dprintk to the compat code,  seemed nicer in there.
-
-2007-07-20 02:35  davidm
-
-       * rndtest.c: 
-       
-       Need to clean up some warnings etc,  more includes
-
-2007-07-20 02:34  davidm
-
-       * ocf-compat.h, hifn/hifn7751.c, safe/safe.c: 
-       
-       new shared IRQ flags for 2.6.22 and a safer version of the debug
-       macro
-
-2007-07-20 00:52  davidm
-
-       * cryptosoft.c: 
-       
-       Implement compression based on the code from the openswan guys.
-
-2007-07-20 00:52  davidm
-
-       * criov.c: 
-       
-       Fix compiler warning on non-value returning void func.
-
-2007-07-18 22:55  davidm
-
-       * hifn/hifn7751.c, safe/safe.c: 
-       
-       Use pci_register_driver rather than pci_module_init. 
-       pci_module_init has been dropped in 2.6.22 yet pci_register_driver
-       has always existed and used to do some crazy hotplug junk.
-
-2007-07-18 21:55  gerg
-
-       * ixp4xx/ixp4xx.c: 
-       
-       Added a missing ";" at the end of the ixp_kproces() prototype.  It
-       is IXP465 specific, only showed up when generateing for SG720.
-
-2007-07-17 00:37  davidm
-
-       * Makefile, cryptodev.c, random.c, rndtest.c, hifn/hifn7751.c,
-       ocfnull/ocfnull.c, safe/safe.c: 
-       
-       Fixup all the debug support for 2.4 kernels,  clean up the entropy
-       harvester to be far more robust.
-
-2007-07-14 02:19  davidm
-
-       * talitos/talitos.c: 
-       
-       Old patch that had not been applied Kim Phillips
-       
-
-2007-07-14 01:12  davidm
-
-       * Config.in, Kconfig, Makefile, cryptodev.c, cryptodev.h, random.c,
-       syscall.h: 
-       
-       Finally ditched all the syscall stuff.  You can now enable/disable
-       the random harvestor.  Pulled in most of random.c from openswan
-       project and fixed some obvious bugs (that were always there).
-
-2007-07-13 21:59  davidm
-
-       * ocf-compat.h: 
-       
-       Better error printing and checking for drivers
-
-2007-07-13 21:56  davidm
-
-       * cryptosoft.c: 
-       
-       Fix some incorrect debug (reporting wrong error type)
-
-2007-07-13 21:55  davidm
-
-       * hifn/hifn7751.c, safe/safe.c: 
-       
-       Make the code more similar to Free-BSD by reverting to the same
-       debug macros
-
-2007-07-13 21:53  davidm
-
-       * ocfnull/ocfnull.c: 
-       
-       Fix up the null driver to work again in the new framework.
-
-2007-07-06 23:54  mmccreat
-
-       * cryptodev.c, cryptodev.h, cryptosoft.c:  - Update OCF to
-       work with new Crypto API introduced in 2.6.19 kerneli, and add
-       macros so it work with older kernels.  - Add support for SHA256,
-       SHA384 and SHA512 HASH and HMAC algorithms.  - Cryptosoft: Only
-       register algorithms that the kernel has implementations for.
-
-2007-07-03 19:52  davidm
-
-       * Kconfig, README, README.sglinux, criov.c, crypto.c, cryptodev.c,
-       cryptodev.h, cryptosoft.c, ocf-bench.c, ocf-compat.h, random.c,
-       rndtest.c, uio.h, hifn/hifn7751.c, hifn/hifn7751reg.h,
-       hifn/hifn7751var.h, ixp4xx/ixp4xx.c, ocfnull/ocfnull.c,
-       safe/safe.c, safe/safevar.h, talitos/talitos.c: 
-       
-       Updated OCF to the lastest FreeBSD version.
-       
-       There was a lot of change in here,  some of which will help FIP's,
-       some which won't.
-       
-       Did lots of cleaning and diff reduction against the freebsd code. 
-       Still more cleaning to do.
-
-2007-06-01 21:58  gerg
-
-       * Config.in: 
-       
-       Put the regular old Config.in back, needed for puclic releases.
-
-2007-06-01 21:58  gerg
-
-       * Kconfig: 
-       
-       Change the CONFIG_OCF_IXP400 dependencies to be the same as they
-       where in the Config.in file.
-
-2007-05-28 21:40  gerg
-
-       * Config.in, Kconfig: 
-       
-       Switch all module configuration over to new style Kconfigs.
-
-2007-05-24 18:49  davidm
-
-       * cryptodev.c, random.c: 
-       
-       Work around some problems on redhat systems with errno redefinition
-
-2007-04-30 21:09  gerg
-
-       * cryptosoft.c: 
-       
-       The CRYPTO_TFM_MODE_ family of defines no longer exists from 2.6.21
-       onwards. As far as I can tell you don't need to pass it to the
-       crypto_alloc_tfm() function anymore.
-       
-       So define it to be 0 if it doesn't exist.
-
-2007-04-03 02:13  gerg
-
-       * syscall.h: 
-       
-       Added syscall macros for SH architecture. Just temporary, 'till
-       Dave fixes the OCF code to not use syscalls from the modules :-)
-
-2007-02-16 23:10  davidm
-
-       * syscall.h: 
-       
-       ensure the temprary 2.6 fix doesn't break 2.4
-
-2007-02-07 22:23  gerg
-
-       * cryptodev.c, random.c, syscall.h: 
-       
-       Temporary fix for new 2.6 kernels no longer defining in-kernel
-       system call functions. Define them locally for now until we fix
-       properly.
-
-2007-02-07 03:10  gerg
-
-       * ixp4xx/ixp4xx.c: 
-       
-       Changes to support the different INIT_WORK() mechanism from kernels
-       2.6.20 onwards.
-
-2007-02-06 02:38  gerg
-
-       * crypto.c: 
-       
-       Cleaned up use of kmem_cache_t and use of SLAB_ATOMIC.
-
-2006-12-05 20:50  cpascoe
-
-       * hifn/hifn7751.c, safe/safe.c, talitos/talitos.c: 
-       
-       Remove pt_regs from OCF interrupt handlers for 2.6.19+
-
-2006-12-02 03:36  gerg
-
-       * criov.c, crypto.c, cryptodev.c, cryptosoft.c, ocf-bench.c,
-       random.c, rndtest.c, hifn/hifn7751.c, ixp4xx/ixp4xx.c,
-       ocfnull/ocfnull.c, safe/safe.c, talitos/talitos.c: 
-       
-       Can no longer include linux/config.h as of 2.6.19 kernels.  Need to
-       conditionally include it based on AUTOCONF_INCLUDED not being
-       defined.
-
-2006-10-13 21:52  cpascoe
-
-       * random.c: 
-       
-       Remove another race condition that may result in us running more
-       than one random thread if modules are reloaded during heavy system
-       load.
-
-2006-10-13 21:18  cpascoe
-
-       * random.c: 
-       
-       - Permit delivery of SIGKILL to the random thread.  - Do not exit
-       prematurely if poll() is interrupted.  - Improve exit conditions so
-       that we quit immediately, rather than loop   infinitely, if the
-       last RNG source is removed while we are trying to   fill our
-       buffer.
-
-2006-10-03 20:28  cpascoe
-
-       * crypto.c, crypto.c:  AutoMerged
-       >
-       > Zero the empty half of "new driver" buffer, and not past the end
-       of the old
-       > buffer that we are about to free.
-
-2006-10-03 20:28  cpascoe
-
-       * crypto.c: 
-       
-       Zero the empty half of "new driver" buffer, and not past the end of
-       the old buffer that we are about to free.
-
-2006-08-25 23:57  davidm
-
-       * cryptosoft.c: 
-       
-       Do not print errors for failed ALG requests unless debugging
-
-2006-07-14 21:44  davidm
-
-       * cryptodev.h: 
-       
-       2.6.11 and earlier did not have the files_fdtable macro.
-
-2006-06-21 21:26  gerg
-
-       * cryptodev.h, hifn/hifn7751.c, ocfnull/ocfnull.c, safe/safe.c,
-       talitos/talitos.c: 
-       
-       Fixed up more occurrances of MODULE_PARM() needing to be converted
-       to module_param() (as of 2.6.17 and onwards).
-
-2006-06-21 00:28  gerg
-
-       * cryptosoft.c: 
-       
-       Change use of MODULE_PARM to module_param() for 2.6.17+ kernels.
-
-2006-06-20 22:13  gerg
-
-       * crypto.c, cryptodev.c, cryptodev.h, ocf-bench.c, ixp4xx/ixp4xx.c:
-       
-       
-       As of 2.6.17 and onwards module_param is used in place of
-       MODULE_PARM.
-
-2006-06-06 00:31  gerg
-
-       * Makefile: 
-       
-       Fix Makefile to find includes is using CSR-2.1.
-
-2006-05-31 01:44  gerg
-
-       * cryptodev.h: 
-       
-       The vars "crypto_usercrypto", "crypto_userasymcrypto" are declared
-       as extern in the header file, but static in the c file. I guessed
-       that they should probably be truely static, so removed the extern
-       declarations from the header.
-
-2006-05-25 21:06  davidm
-
-       * talitos/talitos.c: 
-       
-       This fixes a situation that I never provably experienced, where a
-       descriptor in memory may be reserved within the proper lock, and
-       freed immediately after, only for a few cycles, right outside the
-       lock.  Kim Phillips 
-
-2006-05-15 19:49  davidm
-
-       * criov.c, crypto.c, cryptodev.c, cryptodev.h, cryptosoft.c,
-       ocf-bench.c, random.c, rndtest.c, uio.h, ixp4xx/ixp4xx.c: 
-       
-       Remove the "all rights reserved" from the Intel copyrights.
-
-2006-05-12 21:19  davidm
-
-       * Config.in, Kconfig, Makefile, cryptodev.c, ocf-bench.c,
-       ocfnull/ocfnull.c: 
-       
-       Add in a null OCF driver that does nothing at all,  useful for
-       measuring the cost of various parts of the ipsec stack.
-
-2006-05-12 21:17  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       make sure we do not overwrite a correctly set error type.
-
-2006-05-12 06:52  davidm
-
-       * crypto.c: 
-       
-       Fix a problem where a driver would return ERESTART (full) but then
-       unblock itself before the upper layer had marked it as blocked. 
-       This caused the code to get stuck in crypto_proc and process no
-       more requests.
-
-2006-05-12 06:47  davidm
-
-       * cryptosoft.c: 
-       
-       Implement CRD_F_KEY_EXPLICIT for cryptosoft so keys can be changed
-       on an active session.
-
-2006-05-10 20:09  davidm
-
-       * README, criov.c, crypto.c, cryptodev.h, cryptosoft.c,
-       ocf-bench.c, random.c, rndtest.c, uio.h, hifn/hifn7751.c,
-       ixp4xx/ixp4xx.c, safe/safe.c, safe/safevar.h: 
-       
-       update email addresses and other house cleaning
-
-2006-05-10 20:08  davidm
-
-       * cryptodev.c: 
-       
-       pull in better error checking from openswan modifications
-
-2006-05-10 19:11  davidm
-
-       * cryptosoft.c: 
-       
-       Fix an unused variable warning when various options are disabled.
-
-2006-05-10 19:10  davidm
-
-       * cryptodev.h: 
-       
-       Add support for 2.4 kernels for the new FD cloning operation
-
-2006-05-09 19:48  davidm
-
-       * hifn/hifn7751.c: 
-       
-       remove the hifn 7855 support,  this driver will never work with
-       that chip.
-
-2006-05-08 23:34  davidm
-
-       * hifn/hifn7751var.h: 
-       
-       Contiguous buffer support so that ocf-bench can run properly.
-
-2006-05-05 23:21  davidm
-
-       * hifn/hifn7751.c: 
-       
-       Add in contiguous buffer support so that ocf-bench and run on the
-       driver.
-
-2006-05-05 23:14  davidm
-
-       * ocf-bench.c: 
-       
-       Our requests were out of order,  need to do crypto then auth on
-       encrypt requests.  Some drivers enforce this.
-
-2006-05-04 23:21  davidm
-
-       * crypto.c: 
-       
-       Do not run "newsession" with lock,  since newsession may sleep on
-       some targets.  Handle the accounting so that things are not pulled
-       from underneath us.
-
-2006-05-04 23:20  davidm
-
-       * cryptodev.c: 
-       
-       Switch to a less optimal (marginally) solution for creating a new
-       fd that appears to work in far more versions of the kernel
-       including 64bit versions.
-
-2006-05-04 18:54  davidm
-
-       * ocf-bench.c: 
-       
-       Turn off the IXP access lib benchmarking by default as most people
-       don't have it.
-       
-       Paul Wouters 
-
-2006-04-01 08:23  davidm
-
-       * Makefile: 
-       
-       Remove more temp files when cleaning
-
-2006-04-01 08:12  davidm
-
-       * hifn/hifn7751reg.h: 
-       
-       7855 PCI id's as yet untested
-
-2006-04-01 08:08  davidm
-
-       * hifn/hifn7751.c: 
-       
-       add PCI id's for the 7855 and AES support,  card is untested still
-       as it requires 128MB of PCI memory !
-
-2006-03-31 08:38  davidm
-
-       * README.sglinux: 
-       
-       small update to instructions with corrected patch name
-
-2006-03-31 00:23  davidm
-
-       * Config.in: 
-       
-       Add the Talitos driver to the 2.4 config,  even though it probably
-       won't compile.
-
-2006-03-30 07:48  davidm
-
-       * Kconfig, Makefile, talitos/talitos.c, talitos/talitos_dev.h,
-       talitos/talitos_soft.h: 
-       
-       Please find attached the freescale SEC driver for OCF.  It's been
-       (most recently) tested on an SEC2.0 based MPC8541E
-       (cryptographically identical to the MPC8555E) under 2.6.15.2, with
-       openssl-0.9.8a and openswan-2.4.3 (2.4.5rc5 won't keep the security
-       association up for me for some reason).
-       
-       Please feel free to add it to your next release of OCF-Linux :-)
-       
-       Kim Phillips 
-
-2006-03-20 19:34  davidm
-
-       * safe/: safe.c, safevar.h: 
-       
-       Safenet 1141 v1.0 chips have a DMA lockup error if you access the
-       chip while DMA'ing.  As a work around you need to limit your DMA to
-       256 byte chunks using scatter/gather descriptors.  All the SG/SME
-       products have v1.0 chips and would lockup with more than two
-       outstanding packets at one time.
-       
-       Fix the KASSERT macro
-       
-       Add some more exhaustive initialisation.
-
-2006-03-15 21:58  davidm
-
-       * cryptodev.h, random.c: 
-       
-       Switch random support to "ints" since that is what the kernel uses
-       and not using the same thing is 64bit wise a bad idea.
-       
-       Fix FIP's code to ensure correct amount of data is passed in.
-       
-       Add work around for broken 64bit OS RNG support (disable it)
-       
-       General code cleanups.
-
-2006-03-15 21:55  davidm
-
-       * hifn/hifn7751.c: 
-       
-       Fixes for 64bit OS's,  make sure PCI address are within bus space,
-       make sure we order writes to the bus so that chip functions
-       correctly.  Some small cleanups.
-
-2006-03-15 21:48  davidm
-
-       * hifn/hifn7751var.h: 
-       
-       Remove unused field from structure
-
-2006-03-15 21:47  davidm
-
-       * safe/safe.c: 
-       
-       Make the code more 64bit OS compatible,  force PCI address space
-       and so on.
-
-2006-03-09 20:42  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       If we call ixpCryptoAccInit() and it fails,  just assume that it
-       has already been called.  This allows our "rc" scripts to be
-       openswan and freeswan compatible ore easily.
-
-2006-02-28 23:21  davidm
-
-       * README: 
-       
-       generalise it a bit so rel-dates don't get in the way
-
-2006-02-28 01:52  davidm
-
-       * README, patches/ssh.patch, patches/ssl.patch: 
-       
-       Updated the README and patches for a release
-
-2006-02-25 09:21  davidm
-
-       * README, README.sglinux: 
-       
-       updates for a new release of OCF,  ssl patches and so on.
-
-2006-02-25 08:44  davidm
-
-       * crypto.c: 
-       
-       We were calling the "process"routines with interrupts disabled.  I
-       can see no good reason for this and it provokes badness warnings in
-       2.6 under some conditions.
-       
-       I am going to run with the Q's unlocked for processing,  and
-       hopefully it will allow the system to be more responsive.  It
-       hasn't affected ipsec throughput in any way.  Userland throughput
-       (multi threaded) may have improved significantly though,  but it
-       needs more testing.
-
-2006-02-24 23:32  davidm
-
-       * cryptodev.c: 
-       
-       Whoa,  set the segments with uninitted values can't be good.  Clean
-       out the rest of the old code that was accidently left in.
-
-2006-02-22 01:02  davidm
-
-       * cryptodev.c: 
-       
-       Still not sure about this one,  but this is working for all the
-       cases I can see so far.  If it gets weird,  I am going to switch to
-       a simple clone and chain the sessions rather than a new fcr per fd.
-
-2006-02-20 22:12  davidm
-
-       * cryptodev.c: 
-       
-       Error handling case could free data that was not allocated
-       
-       Ronen Shitrit  Marvell Semiconductor Israel
-       Ltd
-
-2006-02-20 21:57  davidm
-
-       * cryptosoft.c: 
-       
-       Proper SHA/MD5 (non hmac) implementation,  remove some retrictions
-       for hashes (which only applied to crypto) and fix over zealous
-       error checking.
-       
-       Ronen Shitrit  Marvell Semiconductor Israel
-       Ltd
-
-2006-02-09 21:15  davidm
-
-       * cryptodev.c: 
-       
-       The code wasn't quite right and needed some fixing for proper file
-       accounting.
-
-2006-01-24 20:08  davidm
-
-       * crypto.c, cryptodev.c, hifn/hifn7751.c: 
-       
-       We implement our own open in the CRIOGET ioctl now which does
-       pretty much the same thing as the BSD version,  rather than use an
-       open system call which gets caught out by chroot.
-
-2006-01-06 00:42  gerg
-
-       * cryptosoft.c: 
-       
-       Moved "{" block marker inside the set of
-       "defined(CONFIG_CRYPTO_HMAC) || defined(CONFIG_CRYPTO_HMAC_MODULE)"
-       code (in function swcr_process) so that it compiled if these where
-       not defined.
-
-2005-11-11 01:44  davidm
-
-       * Makefile, README: 
-       
-       cleanups for a general release of OCF
-
-2005-11-11 01:18  davidm
-
-       * patches/ssl.patch: 
-       
-       Updated the ssl patch to the latest and greatest changed we have
-       made.
-
-2005-11-10 21:41  davidm
-
-       * Makefile, ixp4xx/ixp4xx.c: 
-       
-       Better debug for bad input.
-       
-       Have make clean do more cleaning and less talking.
-
-2005-11-03 20:53  davidm
-
-       * cryptosoft.c: 
-       
-       clean up some compilation errors with various options on/off
-
-2005-10-25 00:25  davidm
-
-       * Makefile: 
-       
-       Add a patch target that generates full kernel patches to add OCF
-       into either a 2.4 or 2.6 kernel as a single patch.
-
-2005-10-25 00:24  davidm
-
-       * Kconfig: 
-       
-       Make sure all OCF settings depend on OCF_OCF
-
-2005-09-23 02:45  davidm
-
-       * README, README.sglinux: 
-       
-       new crypto-tools archive to keep the tools up to date
-
-2005-09-23 02:08  davidm
-
-       * Makefile, README, README.sglinux: 
-       
-       updates for doing OCF releases
-
-2005-09-23 01:59  davidm
-
-       * patches/: ssh.patch, ssl.patch: 
-       
-       updated the patches for the latest in fixes etc to ssh/ssl for a
-       new OCF release before the openswan 2.4.1 merge.
-
-2005-09-21 00:57  davidm
-
-       * Makefile, cryptosoft.c, hifn/hifn7751.c, ixp4xx/ixp4xx.c: 
-       
-       Fixes for building cleanly under 2.6
-
-2005-09-13 23:11  davidm
-
-       * ocf-bench.c: 
-       
-       Add an exit function for cleaner 2.6 support.  Patch from Ronen
-       Shitrit 
-
-2005-07-30 00:23  davidm
-
-       * cryptosoft.c: 
-       
-       Add proper hooks for MD5/SHA and their HMAC countrparts processing
-       from cryptodev.
-
-2005-07-29 01:50  davidm
-
-       * cryptodev.c: 
-       
-       cryptodev did not support MD5 and SHA1,  only the HMAC versions
-
-2005-07-29 01:05  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       register for MD5,  return 16 bytes for MD5 and 12 for MD5_HMAC, 
-       likewise for SHA1 (only 20 is not HMAC).
-
-2005-07-28 21:52  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       First pass fix of userland MD5 processing.  We now do as well as
-       the safenet does,  I think.
-
-2005-07-27 06:23  davidm
-
-       * cryptodev.c: 
-       
-       udelay doesn't give up the current thread, thus the kernel will get
-       locked if a process is killed but the hardware never completes the
-       crypto request.
-
-2005-07-22 02:07  davidm
-
-       * crypto.c, cryptodev.h: 
-       
-       Implement queuing limits for input/output and OCF requests.
-       
-       Implement 2.6 style work queues instead of the 2.4 task_queues.
-
-2005-07-21 20:42  davidm
-
-       * cryptodev.h, ocf-bench.c, ixp4xx/ixp4xx.c: 
-       
-       Fix OCF to use work queues,  add 2.4 version of work queues to
-       cryptodev.h for use in ipsec and elsewhere.
-       
-       Problem and initial patch provided by David Vrabel
-       .  Cleaned up and 2.4 support added by me.
-
-2005-07-21 19:08  davidm
-
-       * random.c: 
-       
-       Fix spinlock initialisation, problem reported by Andy @
-       windsorcarclub.co.uk.
-
-2005-07-20 20:24  davidm
-
-       * cryptodev.c: 
-       
-       fix a silly spelling mistake
-
-2005-07-08 00:56  gerg
-
-       * Makefile: 
-       
-       Only build ocf-bench when CONFIG_OCF_BENCH is acrually enabled.
-
-2005-06-27 20:29  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       Ok,  we need a simple implentation here or we go too slow for UDP
-       tests.  For now,  if the Q is full just ditch the packet,  someone
-       has to do it.
-
-2005-06-25 01:13  davidm
-
-       * safe/safe.c: 
-       
-       bytes swapping etc all seems wrong for safenet on BE,  these fixes
-       see both MD5 and SHA1 working with OpenSwan.
-
-2005-06-22 23:10  davidm
-
-       * random.c: 
-       
-       clean up some ifdef code a little
-
-2005-06-22 21:28  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       Make sure we do not call blocking functions from ISR callable
-       routines.  In this case we were calling ixCryptoAccCtxUnregister.
-       
-       Run all the random numbers through SHA1 process to ensure more
-       uniform distribution of bits (NOTE:  it is not more random in any
-       way)
-
-2005-06-21 00:11  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       do not process requests from the register callback, gets the AES
-       code all messed up.
-       
-       Align caches on HW cache boundaries ot improve speed.
-       
-       More tracking or potential errors.
-
-2005-06-15 01:55  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       technically ixCryptoAccCtxRegister cannot be called from IRQ
-       context, so run it from the immediate BH.
-
-2005-06-14 23:13  davidm
-
-       * ocf-bench.c: 
-       
-       Fix some compile warnings/errors
-
-2005-06-14 20:52  davidm
-
-       * Config.in, Kconfig, Makefile, ocf-bench.c: 
-       
-       Add in kernel benchmark driver
-       
-       Support for building under CSR 1.4 and 2.0 is now complete
-
-2005-06-14 20:51  davidm
-
-       * crypto.c: 
-       
-       Do not use immediate processing for SW drivers otherwise we hold a
-       lock for too long.  Instead force BATCH processing.
-       
-       Problem found by David Vrabel 
-
-2005-06-14 20:46  davidm
-
-       * cryptodev.c: 
-       
-       Fix up AES minimum key size
-       
-       Make some more variables static
-
-2005-06-14 20:36  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       Use kernel caches as they are more efficient and faster to obtain.
-       
-       Fix some spelling
-       
-       Tune PKE to only use the space required.  Turn off go fast options
-       to reduce any speed-related cracking.
-       
-       Only zero data that needs to be zeroed (save some cycles)
-
-2005-06-02 21:42  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       Added optimisations ideas from Intel the improve the PKE
-       performance for 512 and 1024 bits operations.
-
-2005-06-01 02:13  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       Looks like I found the ixp bug.  Using OSAL buffer routines on
-       non-OSAL buffers is a very very bad thing to do.  Must double check
-       all the API's I am using (ie., PKE) just to be sure.
-
-2005-05-31 21:38  davidm
-
-       * Config.in, Kconfig: 
-       
-       Updated/Added the menu wrapper for the config options
-
-2005-05-31 21:18  gerg
-
-       * Config.in: 
-       
-       Reworked the config.in so that each sub-module has its own
-       Config.in.  That way it is easier to make release trees with some
-       modules left in.
-
-2005-05-30 19:46  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       Not all the Pke code was appropriately ifdef'd
-
-2005-05-28 01:49  davidm
-
-       * cryptosoft.c: 
-       
-       We were not injecting data in the right places nor calling the
-       cipher code the best was under all situations.  We are now good
-       enought to do ESP/AH processing with 3DES and SHA1-HMAC.
-
-2005-05-28 01:42  davidm
-
-       * hifn/hifn7751.c: 
-       
-       Non atomic kmallocs at IRQ time are bad and cause lockups
-
-2005-05-21 08:31  davidm
-
-       * README, README.sglinux: 
-       
-       Some small updates to email and patches that no longer exist
-
-2005-05-21 08:25  davidm
-
-       * cryptosoft.c: 
-       
-       better error message on failure,  a lot of the error check we do
-       sems to break apps like cryptotest, not sure who is right yet.
-
-2005-05-21 00:55  davidm
-
-       * criov.c, crypto.c, cryptodev.c, cryptodev.h, cryptosoft.c,
-       random.c, rndtest.c, uio.h, hifn/hifn7751.c, ixp4xx/ixp4xx.c,
-       safe/safe.c, safe/safevar.h: 
-       
-       Convert to CyberGuard email addresses for OCF files.
-
-2005-05-21 00:28  davidm
-
-       * crypto.c, cryptodev.c, cryptosoft.c, hifn/hifn7751.c,
-       ixp4xx/ixp4xx.c, safe/safe.c: 
-       
-       final round of naming changes,  hifn driver also confirmed working
-       in SG710
-
-2005-05-20 23:50  davidm
-
-       * cryptosoft.c, random.c, uio.h, ixp4xx/ixp4xx.c: 
-       
-       more copyright/author updates etc for Intel
-
-2005-05-20 23:48  davidm
-
-       * criov.c, crypto.c, cryptodev.c, cryptodev.h, cryptosoft.c,
-       random.c, rndtest.c, uio.h, ixp4xx/ixp4xx.c, safe/safe.c,
-       safe/safevar.h: 
-       
-       updated copyrights to reflect Intels interest/investment in the
-       project
-
-2005-05-20 20:31  davidm
-
-       * hifn/: hifn7751.c, hifn7751var.h: 
-       
-       Most of a working SKB implementation now
-
-2005-05-20 20:30  davidm
-
-       * safe/: md5.c, md5.h, safe.c, sha1.c, sha1.h: 
-       
-       Full AH/ESP processing now working,  just added BSD sha/md5
-       routines as needed for now.
-
-2005-05-20 20:30  davidm
-
-       * random.c: 
-       
-       use the new BSD rndtest code rather than the old GPL fips code
-
-2005-05-20 20:28  davidm
-
-       * Makefile, fips.c, fips.h, rndtest.c, rndtest.h: 
-       
-       Get rid of the GPL version of the fips test and use a BSD licensed
-       version so no one can get upset and cry derivative :-)
-
-2005-05-20 08:19  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       High throughput improvements. Can now handle multiple simultaneous
-       requests.
-
-2005-05-20 00:55  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       
-       works with openswan/OCF for ipsec receive.
-       
-       fixes ESP/AUTH processing (esp. HMAC)
-       
-       This driver needs a rework for kernel IPSEC as it's current packet
-       at a time processing is not up to the task.
-
-2005-05-20 00:53  davidm
-
-       * cryptosoft.c: 
-       
-       working ESP/AUTH code now impleneted.  Can do RX processing for
-       openswan KLIPS.
-       
-       Fixes numerous problems in skb processing
-       
-       Fixes broken HMAC code and IV processing
-
-2005-05-14 01:44  davidm
-
-       * cryptodev.c, ixp4xx/ixp4xx.c: 
-       
-       Cleanup IXP key processing to guarantee only a single outstanding
-       request rather than relying on the intel driver to get it right. 
-       Stops us losing requests.
-       
-       Tighten up the cryptodev response to "no answer" so that we don't
-       take all the CPU.  Only happens if there is a driver bug.
-
-2005-05-14 00:07  davidm
-
-       * Config.in, Kconfig, Makefile, crypto.c, fips.c, fips.h, random.c,
-       ixp4xx/ixp4xx.c, tools/bench-ocf: 
-       
-       PKE and RNG support running on the ixp driver,  added PKE bench
-       marking to script.  Still some multi-thread problems in the PKE
-       code.
-       
-       Added FIP RNG checking option to config and code.
-
-2005-05-10 19:18  davidm
-
-       * Makefile, ixp4xx/ixp4xx.c: 
-       
-       Get the OCF stuff building for the 465 and CSR-2.0
-
-2005-04-27 19:18  davidm
-
-       * cryptodev.h, random.c, hifn/hifn7751.c, safe/safe.c: 
-       cleanup the random number interface some more
-
-2005-04-27 00:57  davidm
-
-       * cryptodev.h, cryptosoft.c, random.c, hifn/hifn7751.c,
-       ixp4xx/ixp4xx.c, patches/linux-2.4.29-add_true_randomness.patch,
-       patches/linux-2.6.11-add_true_randomness.patch, safe/safe.c,
-       safe/safevar.h: 
-       
-       Switch to a more "user" like random number handling.  Drivers no
-       longer poll for RNG data,  we pull it as needed to fill
-       /dev/random's entropy.
-       
-       Implement sk_buff handling within the OCF framework.
-       
-       fixup IV handling in cryptosoft.
-
-2005-04-27 00:41  davidm
-
-       * crypto.c: 
-       
-       Fix a race condition with the starting of kernel threads.  The
-       threads were running before the pid assignment in the parent.
-
-2005-03-24 23:57  davidm
-
-       * Makefile: 
-       include crypto-tools.patch in the release file
-       
-       
-
-2005-03-24 20:14  davidm
-
-       * safe/safe.c: 
-       Fixup compile time warnings due to some left over BSDisms
-       
-
-2005-03-24 00:53  davidm
-
-       * Makefile, README, README.sglinux, patches/linux-2.4.29-ocf.patch,
-       patches/linux-2.6.11-ocf.patch, patches/ocf-linux-2.4.29.patch,
-       patches/ocf-linux-2.6.11.patch: 
-       added cleaner patch names and a tarball target to aid releases
-       
-
-2005-03-24 00:28  davidm
-
-       * patches/crypto-tools.patch,
-       patches/linux-2.4.29-add_true_randomness.patch,
-       patches/linux-2.6.11-add_true_randomness.patch,
-       patches/ocf-linux-2.4.29.patch, patches/ocf-linux-2.6.11.patch,
-       patches/ssh.patch, patches/ssl.patch, tools/bench-ocf: 
-       move all the release file patches into CVS for simplicity
-       
-
-2005-03-23 20:37  davidm
-
-       * safe/safe.c: 
-       remove excessive debug from RNG routines so that you can turn on
-       debug and live through it
-       
-       
-
-2005-03-23 02:23  davidm
-
-       * safe/safe.c: 
-       fix memory corruption for mod_exp and the safenet,  we were copying
-       back more than the space available.
-       
-       
-
-2005-03-22 21:45  davidm
-
-       * crypto.c, cryptodev.c, cryptodev.h, safe/safe.c: 
-       fixup a major sync issues with key processing (callback called
-       before sleeping).  Improve its performance while we are there with
-       a CBIMM (callback immediate) option.
-       
-       
-
-2005-03-19 00:33  davidm
-
-       * random.c: 
-       A new randomness function for both 2.4 and 2.6 that replaces out
-       previous old solution for the hifn driver with more generic code
-       that works on both kernels.
-       
-               add_true_randomness(u_int32_t *buf, int nwords);
-       
-       
-
-2005-03-18 21:01  davidm
-
-       * Makefile, cryptodev.h, random.c, hifn/hifn7751.c, safe/safe.c: 
-       RNG support in both the safenet and the hifn plus the required
-       kernel support.
-       
-       "hd /dev/random" runs much much faster now :-)
-       
-       
-
-2005-03-17 23:29  toby
-
-       * cryptodev.c:  Make sure the CIOCASYMFEAT ioctl on
-       /dev/crypto copies out the capable features.
-
-2005-03-17 01:19  davidm
-
-       * safe/: safe.c, safereg.h, safevar.h: 
-       hardware PK acceleration on the safenet (CRK_MOD_EXP only)
-       
-
-2005-03-16 04:28  davidm
-
-       * criov.c, crypto.c, cryptodev.c, safe/safe.c: 
-       fixup the FBSD id stuff to compile :-) 
-
-2005-03-16 04:02  davidm
-
-       * README, README.sglinux, TODO: 
-       Updated with versions,  removed tabs,  new kernel versions, web
-       site etc 
-
-2005-03-16 03:45  davidm
-
-       * criov.c, crypto.c, cryptodev.c, cryptodev.h: 
-       more license formatting and version id's to help keep in touch with
-       FreeBSD 
-
-2005-03-16 03:16  davidm
-
-       * safe/safe.c: 
-       up to date with FreeBSD versioning, no changes to merge 
-
-2005-03-16 03:15  davidm
-
-       * safe/safe.c: 
-       include FreeBSD version info so I can track changes better
-       
-
-2005-03-16 03:11  davidm
-
-       * hifn/: hifn7751.c, hifn7751reg.h, hifn7751var.h: 
-       incorporate latest updates from FreeBSD:
-       
-       | Update support for 795x parts: | o rework pll setup code to
-       follow h/w specification | o add hint.hifn.X.pllconfig to specify
-       reference clock setup |   requirements; default is pci66 which
-       means the clock is |   derived from the PCI bus clock and the card
-       resides in a |   66MHz slot | | Tested on 7955 and 7956 cards;
-       support for 7954 cards not enabled | since we have no cards to test
-       against.
-       
-       
-
-2005-03-16 02:50  davidm
-
-       * Config.in, Kconfig, README, crypto.c, cryptodev.c, cryptodev.h,
-       hifn/hifn7751.c, hifn/hifn7751var.h, safe/safe.c, safe/safevar.h: 
-       cleanups to build and run on 2.6.11 and 2.4.29 for a public release
-       
-       included configs locally to reduce patch to kernel and required
-       user effort.
-       
-       pci_dma_sync_single fix from Michele Baldessari
-       ,       with modifications by me to work on all
-       kernels.
-       
-       
-
-2005-03-11 23:30  davidm
-
-       * Makefile: 
-       fix up the compiling again, I had outstanding commits for this one
-       :-) 
-
-2005-03-11 21:56  danield
-
-       * Makefile: Get ocf modules building again.  
-
-2004-12-25 07:12  davidm
-
-       * TODO: 
-       safenet is all good now AKAIK 
-
-2004-12-25 07:02  davidm
-
-       * Makefile, crypto.c, cryptodev.c, cryptosoft.c, uio.h: 
-       2.6 port of the OCF framework,  tested on Xscale and compiled for
-       x86
-       
-       
-
-2004-12-10 02:41  davidm
-
-       * hifn/hifn7751.c: 
-       Fix compilation as l_flags was not defined for LOCK in pci_remove
-       
-
-2004-12-06 19:15  davidm
-
-       * hifn/hifn7751.c, safe/safe.c: 
-       * Put locking into hifn_remove to ensure interrupts are not running
-       while we   remove the driver
-       
-         Use del_timer_sync (need to ensure timer is not running on
-       another CPU
-       * when we delete it).
-       
-       Improvements suggested by Evgeniy Polyakov <johnpol@2ka.mipt.ru>
-       
-
-2004-12-02 09:16  davidm
-
-       * README, README.sglinux: 
-       * Fix up all tabs to be spaces * explain how to update the ocf
-       support in the patch to the current version.
-       
-       
-
-2004-12-02 09:11  davidm
-
-       * README: 
-       * fix some spelling/grammar * add more info on the ssl.patch file
-       and what it contains 
-
-2004-12-02 09:08  davidm
-
-       * README.sglinux: 
-       give some more instructions on the shar archive and extracting the
-       release.  
-
-2004-12-02 09:03  davidm
-
-       * README.sglinux: 
-       how to include crypto-tools into 3.1.6
-       
-       
-
-2004-12-02 08:48  davidm
-
-       * README.sglinux: 
-       updated for a new crypto patch for openssl-0.9.7e 
-
-2004-12-02 08:04  davidm
-
-       * README, README.sglinux: 
-       Clean up the README's to use the new SG Linux alpha and a specific
-       2.4.28 patch.
-       
-       
-
-2004-12-01 23:11  davidm
-
-       * Makefile, criov.c, crypto.c, cryptodev.c, cryptosoft.c,
-       hifn/Makefile, hifn/hifn7751.c, ixp4xx/Makefile, ixp4xx/ixp4xx.c,
-       safe/Makefile, safe/safe.c: 
-       Re-worked the Makefiles so that including the code into a standard
-       non-SG kernel is really easy.
-       
-       Fixed a non-initialised bug that was introduce into cryptosoft.c
-       with the additional error checking.
-       
-       
-
-2004-12-01 01:54  davidm
-
-       * TODO: 
-       updates based on things that have been fixed.  
-
-2004-12-01 01:53  davidm
-
-       * safe/: safe.c, safevar.h: 
-       Cleanup some old hacks based on the much cleaner port of the hifn
-       driver.  
-
-2004-12-01 01:53  davidm
-
-       * cryptosoft.c: 
-       fix some crashes due to bad buffer sizes etc.  
-
-2004-11-27 09:16  davidm
-
-       * crypto.c, cryptodev.c, ixp4xx/ixp4xx.c: 
-       Fixed some nasty problems that were stopping reliable behaviour:
-       
-       1) we were not initialising some of our lists/wait queues,  which  
-        meant they appears to have things in them when in fact they did
-       not.     This actually didn't seems to cause any problems but is
-       extremely bogus.
-       
-       2) While a process was waiting for the crypto engine,  if
-       itreceived a    signal we would lose sync with the engine and end
-       up allowing out-of-band    actions that were invalid (ie.,
-       unregistering a context that was still    active in a crypto
-       operation).
-       
-          Of source the CryptACC should probably deal with this as well
-       ;-)
-       
-       
-
-2004-11-26 01:33  davidm
-
-       * TODO: 
-       We should also hook in the random number generators to linux
-       
-
-2004-11-26 01:33  davidm
-
-       * hifn/hifn7751.c: 
-       Changed all the accesses to DMS descriptors to not set the valid
-       bit until after everything else was set.  This got the driver
-       running smoothly, along with a fixup to the pci_map_uio which
-       wasn't settings lengths correctly.
-       
-       
-
-2004-11-25 21:15  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       document why using a new context for each packet is actually a
-       better idea than allocating one (actually two) per session.
-       
-       
-
-2004-11-25 08:48  davidm
-
-       * README, README.sglinux: 
-       updates from email with Intel to fix a few little things
-       
-
-2004-11-25 00:02  davidm
-
-       * README, README.sglinux, safe/safe.c: 
-       Some cleanups of doc and so on for Intel/General use 
-
-2004-11-23 07:58  davidm
-
-       * TODO: 
-       safenet is working on big endian machines now
-       
-       
-
-2004-11-23 07:56  davidm
-
-       * ixp4xx/: Makefile, ixp4xx.c: 
-       Reference the Intel library,  cleanup the IV sizes and turn on AES.
-        Fix Makefile for new config options.
-       
-       
-
-2004-11-23 07:52  davidm
-
-       * Makefile: 
-       Complete the changes of ixp to ixp4xx (IXP4xx) as appropriate
-       
-
-2004-11-23 00:33  davidm
-
-       * Makefile, README, ixp4xx/Makefile: 
-       Changes all references to ixp to be ixp4xx at Intels request
-       
-
-2004-11-20 01:07  davidm
-
-       * safe/: safe.c, safereg.h: 
-       fully working safenet on BE machines 
-
-2004-11-19 01:03  davidm
-
-       * Makefile, hifn/Makefile, hifn/hifn7751.c, hifn/hifn7751reg.h,
-       hifn/hifn7751var.h: 
-       hifn driver code complete and compiling,  needs a test now ;-)
-       
-
-2004-11-18 21:45  davidm
-
-       * hifn/: Makefile, hifn7751.c, hifn7751var.h: 
-       Makefile for building the hifn driver 
-
-2004-11-18 21:44  davidm
-
-       * hifn/: hifn7751.c, hifn7751reg.h, hifn7751var.h: 
-       Checkin the orginal freebsd source for the hifn driver as a
-       reference in the future.
-       
-       
-
-2004-11-18 10:05  davidm
-
-       * Makefile, README, TODO, criov.c, crypto.c, cryptodev.c,
-       cryptodev.h, cryptosoft.c, uio.h, ixp4xx/Makefile, ixp4xx/ixp4xx.c,
-       safe/Makefile, safe/safe.c, safe/safevar.h: 
-       Clean up license and copyright info to be more acceptable (and
-       present) Clean up debug and trace Fixup memory freeing etc on
-       safenet Fix compiler warnings (some were bugs)
-       
-       
-
-2004-11-17 02:23  davidm
-
-       * safe/safe.c: 
-       working on Xscale (big endian) now but packet data is getting
-       stuffed up due to endian problems (at least now we are talking to
-       the chip correctly for BE).  Good enough to test packet throughput,
-        no good for testing scp.
-       
-       
-
-2004-11-17 02:21  davidm
-
-       * criov.c: 
-       Make sure public symbols are exported by including the correct
-       header files 
-
-2004-11-17 02:15  davidm
-
-       * crypto.c: 
-       even better cleanup of kernel threads on exit 
-
-2004-11-17 02:15  davidm
-
-       * cryptosoft.c: 
-       return some trace to debug so it doesn't appear 
-
-2004-11-17 02:14  davidm
-
-       * Makefile: 
-       Make sure all drivers get built, not just IXP 
-
-2004-11-16 21:31  davidm
-
-       * crypto.c: 
-       Fix problem with reboots and driver not unloading cleanly,  we were
-       not handling signals correctly in the kernel threads, 
-
-2004-11-10 10:46  davidm
-
-       * ixp4xx/ixp4xx.c: 
-       fix serious context leak,  itturns out the context is still
-       considered busy while it is calling the perform callback,  so we
-       cleanup on closing the session and on allocating the next context
-       to work around this.
-       
-       
-
-2004-11-10 05:26  davidm
-
-       * crypto.c, cryptodev.c, ixp4xx/ixp4xx.c, safe/safe.c: 
-       cleaned out some debug,  found MAX tunnels bug,  traced it various
-       other cleanups.
-       
-       
-
-2004-11-10 04:02  davidm
-
-       * cryptodev.c, cryptosoft.c, ixp4xx/ixp4xx.c, safe/Makefile,
-       safe/safe.c: 
-       Fix up kmalloc usage to always zero resulting buffer everywhere   
-       (stops crashes in ixp)
-       
-       Add some function debug to ixp so you can see it working
-       
-       Fix safe driver to build and install in a real tree.
-       
-       
-
-2004-11-10 02:27  davidm
-
-       * Makefile, criov.c, crypto.c, cryptosoft.c, ixp4xx/Makefile,
-       ixp4xx/ixp4xx.c: 
-       Compiling OCF modules for the IXP crypto, needs testing now
-       
-
-2004-11-09 19:16  davidm
-
-       * criov.c, crypto.c, cryptodev.c, cryptodev.h, cryptosoft.c,
-       cryptosoft.h, uio.h, safe/safe.c, safe/safevar.h: 
-       The linux port of OCF with working safenet and software modules. 
-       Still some bugs with mutiple crypto threads using the safenet
-       driver.
-       
-       
-
-2004-11-09 18:49  davidm
-
-       * Makefile, criov.c, crypto.c, cryptodev.c, cryptodev.h,
-       cryptosoft.c, cryptosoft.h, uio.h, safe/Makefile, safe/safe.c,
-       safe/safereg.h, safe/safevar.h: 
-       Check in the orginal free-bsd sources for the OCF support.  This
-       allows us to diff against it later to see if we botched anything
-       major league.
-       
-       
-
index cb01ea9..d722cba 100644 (file)
@@ -25,6 +25,8 @@ dep_tristate '  pasemi (HW crypto engine)' \
                                CONFIG_OCF_PASEMI $CONFIG_OCF_OCF
 dep_tristate '  ep80579 (HW crypto engine)' \
                                CONFIG_OCF_EP80579 $CONFIG_OCF_OCF
+dep_tristate '  Micronas c7108 (HW crypto engine)' \
+                               CONFIG_OCF_C7108 $CONFIG_OCF_OCF
 dep_tristate '  ocfnull (does no crypto)' \
                                CONFIG_OCF_OCFNULL $CONFIG_OCF_OCF
 dep_tristate '  ocf-bench (HW crypto in-kernel benchmark)' \
index 74b98b2..b9c24ff 100644 (file)
@@ -84,6 +84,24 @@ config OCF_EP80579
        help
          OCF driver for the Intel EP80579 Integrated Processor Product Line.
 
+config OCF_CRYPTOCTEON
+       tristate "cryptocteon (HW crypto engine)"
+       depends on OCF_OCF
+       help
+         OCF driver for the Cavium OCTEON Processors.
+
+config OCF_KIRKWOOD
+       tristate "kirkwood (HW crypto engine)"
+       depends on OCF_OCF
+       help
+         OCF driver for the Marvell Kirkwood (88F6xxx) Processors.
+
+config OCF_C7108
+       tristate "Micronas 7108 (HW crypto engine)"
+       depends on OCF_OCF
+       help
+         OCF driver for the Microna 7108 Cipher processors.
+
 config OCF_OCFNULL
        tristate "ocfnull (fake crypto engine)"
        depends on OCF_OCF
index 919e551..fa951f4 100644 (file)
@@ -43,7 +43,10 @@ $(_obj)-$(CONFIG_OCF_IXP4XX)  += ixp4xx$(_slash)
 $(_obj)-$(CONFIG_OCF_TALITOS) += talitos$(_slash)
 $(_obj)-$(CONFIG_OCF_PASEMI)  += pasemi$(_slash)
 $(_obj)-$(CONFIG_OCF_EP80579) += ep80579$(_slash)
+$(_obj)-$(CONFIG_OCF_CRYPTOCTEON) += cryptocteon$(_slash)
+$(_obj)-$(CONFIG_OCF_KIRKWOOD) += kirkwood$(_slash)
 $(_obj)-$(CONFIG_OCF_OCFNULL) += ocfnull$(_slash)
+$(_obj)-$(CONFIG_OCF_C7108) += c7108$(_slash)
 
 ocf-objs := $(OCF_OBJS)
 
@@ -79,7 +82,7 @@ patch:
                        diff -Nau /dev/null $$t | sed 's?^+++ \./?+++ linux/crypto/ocf/?'; \
                done > $$patch; \
                cat patches/linux-2.4.35-ocf.patch $$patch > $$patch24; \
-               cat patches/linux-2.6.26-ocf.patch $$patch > $$patch26
+               cat patches/linux-2.6.33-ocf.patch $$patch > $$patch26
 
 .PHONY: tarball
 tarball:
diff --git a/target/linux/generic-2.6/files/crypto/ocf/README b/target/linux/generic-2.6/files/crypto/ocf/README
new file mode 100644 (file)
index 0000000..5ac39f7
--- /dev/null
@@ -0,0 +1,167 @@
+README - ocf-linux-20100325
+---------------------------
+
+This README provides instructions for getting ocf-linux compiled and
+operating in a generic linux environment.  For other information you
+might like to visit the home page for this project:
+
+    http://ocf-linux.sourceforge.net/
+
+Adding OCF to linux
+-------------------
+
+    Not much in this file for now,  just some notes.  I usually build
+    the ocf support as modules but it can be built into the kernel as
+    well.  To use it:
+
+    * mknod /dev/crypto c 10 70
+
+    * to add OCF to your kernel source,  you have two options.  Apply
+      the kernel specific patch:
+
+          cd linux-2.4*; gunzip < ocf-linux-24-XXXXXXXX.patch.gz | patch -p1
+          cd linux-2.6*; gunzip < ocf-linux-26-XXXXXXXX.patch.gz | patch -p1
+    
+      if you do one of the above,  then you can proceed to the next step,
+      or you can do the above process by hand with using the patches against
+      linux-2.4.35 and 2.6.33 to include the ocf code under crypto/ocf.
+      Here's how to add it:
+
+      for 2.4.35 (and later)
+
+          cd linux-2.4.35/crypto
+          tar xvzf ocf-linux.tar.gz
+          cd ..
+          patch -p1 < crypto/ocf/patches/linux-2.4.35-ocf.patch
+
+      for 2.6.23 (and later),  find the kernel patch specific (or nearest)
+      to your kernel versions and then:
+
+          cd linux-2.6.NN/crypto
+          tar xvzf ocf-linux.tar.gz
+          cd ..
+          patch -p1 < crypto/ocf/patches/linux-2.6.NN-ocf.patch
+
+      It should be easy to take this patch and apply it to other more
+      recent versions of the kernels.  The same patches should also work
+      relatively easily on kernels as old as 2.6.11 and 2.4.18.
+      
+    * under 2.4 if you are on a non-x86 platform,  you may need to:
+
+        cp linux-2.X.x/include/asm-i386/kmap_types.h linux-2.X.x/include/asm-YYY
+
+      so that you can build the kernel crypto support needed for the cryptosoft
+      driver.
+
+    * For simplicity you should enable all the crypto support in your kernel
+      except for the test driver.  Likewise for the OCF options.  Do not
+      enable OCF crypto drivers for HW that you do not have (for example
+      ixp4xx will not compile on non-Xscale systems).
+
+    * make sure that cryptodev.h (from ocf-linux.tar.gz) is installed as
+      crypto/cryptodev.h in an include directory that is used for building
+      applications for your platform.  For example on a host system that
+      might be:
+
+              /usr/include/crypto/cryptodev.h
+
+    * patch your openssl-0.9.8n code with the openssl-0.9.8n.patch.
+      (NOTE: there is no longer a need to patch ssh). The patch is against:
+      openssl-0_9_8e
+
+      If you need a patch for an older version of openssl,  you should look
+      to older OCF releases.  This patch is unlikely to work on older
+      openssl versions.
+
+      openssl-0.9.8n.patch
+                - enables --with-cryptodev for non BSD systems
+                - adds -cpu option to openssl speed for calculating CPU load
+                  under linux
+                - fixes null pointer in openssl speed multi thread output.
+                - fixes test keys to work with linux crypto's more stringent
+                  key checking.
+                - adds MD5/SHA acceleration (Ronen Shitrit), only enabled
+                  with the --with-cryptodev-digests option
+                - fixes bug in engine code caching.
+
+    * build crypto-tools-XXXXXXXX.tar.gz if you want to try some of the BSD
+      tools for testing OCF (ie., cryptotest).
+
+How to load the OCF drivers
+---------------------------
+
+    First insert the base modules:
+
+        insmod ocf
+        insmod cryptodev
+
+    You can then install the software OCF driver with:
+
+        insmod cryptosoft
+
+    and one or more of the OCF HW drivers with:
+
+        insmod safe
+        insmod hifn7751
+        insmod ixp4xx
+        ...
+
+    all the drivers take a debug option to enable verbose debug so that
+    you can see what is going on.  For debug you load them as:
+
+        insmod ocf crypto_debug=1
+        insmod cryptodev cryptodev_debug=1
+        insmod cryptosoft swcr_debug=1
+
+    You may load more than one OCF crypto driver but then there is no guarantee
+    as to which will be used.
+
+    You can also enable debug at run time on 2.6 systems with the following:
+
+        echo 1 > /sys/module/ocf/parameters/crypto_debug
+        echo 1 > /sys/module/cryptodev/parameters/cryptodev_debug
+        echo 1 > /sys/module/cryptosoft/parameters/swcr_debug
+        echo 1 > /sys/module/hifn7751/parameters/hifn_debug
+        echo 1 > /sys/module/safe/parameters/safe_debug
+        echo 1 > /sys/module/ixp4xx/parameters/ixp_debug
+        ...
+
+Testing the OCF support
+-----------------------
+
+    run "cryptotest",  it should do a short test for a couple of
+    des packets.  If it does everything is working.
+
+    If this works,  then ssh will use the driver when invoked as:
+
+        ssh -c 3des username@host
+
+    to see for sure that it is operating, enable debug as defined above.
+
+    To get a better idea of performance run:
+
+        cryptotest 100 4096
+
+    There are more options to cryptotest,  see the help.
+
+    It is also possible to use openssl to test the speed of the crypto
+    drivers.
+
+        openssl speed -evp des -engine cryptodev -elapsed
+        openssl speed -evp des3 -engine cryptodev -elapsed
+        openssl speed -evp aes128 -engine cryptodev -elapsed
+
+    and multiple threads (10) with:
+
+        openssl speed -evp des -engine cryptodev -elapsed -multi 10
+        openssl speed -evp des3 -engine cryptodev -elapsed -multi 10
+        openssl speed -evp aes128 -engine cryptodev -elapsed -multi 10
+
+    for public key testing you can try:
+
+        cryptokeytest
+        openssl speed -engine cryptodev rsa -elapsed
+        openssl speed -engine cryptodev dsa -elapsed
+
+David McCullough
+david_mccullough@mcafee.com
diff --git a/target/linux/generic-2.6/files/crypto/ocf/c7108/Makefile b/target/linux/generic-2.6/files/crypto/ocf/c7108/Makefile
new file mode 100644 (file)
index 0000000..e7e634b
--- /dev/null
@@ -0,0 +1,12 @@
+# for SGlinux builds
+-include $(ROOTDIR)/modules/.config
+
+obj-$(CONFIG_OCF_C7108) += aes-7108.o
+
+obj ?= .
+EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
+
+ifdef TOPDIR
+-include $(TOPDIR)/Rules.make
+endif
+
diff --git a/target/linux/generic-2.6/files/crypto/ocf/c7108/aes-7108.c b/target/linux/generic-2.6/files/crypto/ocf/c7108/aes-7108.c
new file mode 100644 (file)
index 0000000..a5ac054
--- /dev/null
@@ -0,0 +1,839 @@
+/*
+ * Copyright (C) 2006 Micronas USA
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ */
+
+//#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/skbuff.h>
+#include <linux/random.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+//#include <asm/scatterlist.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
+#include <cryptodev.h>
+#include <uio.h>
+#include <aes-7108.h>
+
+/* Runtime mode */
+static int c7108_crypto_mode = C7108_AES_CTRL_MODE_CTR;
+//static int c7108_crypto_mode = C7108_AES_CTRL_MODE_CBC;
+
+static int32_t c7108_id = -1;
+static struct cipher_7108 **c7108_sessions = NULL;
+static u_int32_t c7108_sesnum = 0;
+static unsigned long iobar;
+
+/* Crypto entry points */
+static int c7108_process(void *, struct cryptop *, int);
+static int c7108_newsession(void *, u_int32_t *, struct cryptoini *);
+static int c7108_freesession(void *, u_int64_t);
+
+/* Globals */
+static int debug = 0;
+static spinlock_t csr_mutex;
+
+/* Generic controller-based lock */
+#define AES_LOCK()\
+          spin_lock(&csr_mutex)
+#define AES_UNLOCK()\
+          spin_unlock(&csr_mutex)
+
+/* 7108 AES register access */
+#define c7108_reg_wr8(a,d)   iowrite8(d, (void*)(iobar+(a)))
+#define c7108_reg_wr16(a,d)  iowrite16(d, (void*)(iobar+(a)))
+#define c7108_reg_wr32(a,d)  iowrite32(d, (void*)(iobar+(a)))
+#define c7108_reg_rd8(a)     ioread8((void*)(iobar+(a)))
+#define c7108_reg_rd16(a)    ioread16((void*)(iobar+(a)))
+#define c7108_reg_rd32(a)    ioread32((void*)(iobar+(a)))
+
+static int 
+c7108_xlate_key(int klen, u8* k8ptr, u32* k32ptr)
+{
+        int i, nw=0;
+       nw = ((klen >= 256) ? 8 : (klen >= 192) ? 6 : 4);
+       for ( i = 0; i < nw; i++) { 
+           k32ptr[i] =    (k8ptr[i+3] << 24) | (k8ptr[i+2] << 16) | 
+                          (k8ptr[i+1] << 8)  | k8ptr[i];
+           
+       }
+       return 0;
+}
+
+static int 
+c7108_cache_key(int klen, u32* k32ptr, u8* k8ptr)
+{
+        int i, nb=0;
+       u8* ptr = (u8*)k32ptr;
+       nb = ((klen >= 256) ? 32 : (klen >= 192) ? 24 : 16);
+       for ( i = 0; i < nb; i++)
+           k8ptr[i] = ptr[i];
+       return 0;
+}
+
+static int
+c7108_aes_setup_dma(u32 src, u32 dst, u32 len)
+{
+        if (len < 16) {
+           printk("len < 16\n");
+           return -10;
+       }
+       if (len % 16) {
+           printk("len not multiple of 16\n");
+           return -11;
+       }       
+       c7108_reg_wr16(C7108_AES_DMA_SRC0_LO, (u16) src);
+       c7108_reg_wr16(C7108_AES_DMA_SRC0_HI, (u16)((src & 0xffff0000) >> 16));
+       c7108_reg_wr16(C7108_AES_DMA_DST0_LO, (u16) dst);
+       c7108_reg_wr16(C7108_AES_DMA_DST0_HI, (u16)((dst & 0xffff0000) >> 16));
+       c7108_reg_wr16(C7108_AES_DMA_LEN, (u16) ((len / 16) - 1));
+
+       return 0;
+}
+
+static int
+c7108_aes_set_hw_iv(u8 iv[16])
+{
+        c7108_reg_wr16(C7108_AES_IV0_LO, (u16) ((iv[1] << 8) | iv[0]));
+       c7108_reg_wr16(C7108_AES_IV0_HI, (u16) ((iv[3] << 8) | iv[2]));
+       c7108_reg_wr16(C7108_AES_IV1_LO, (u16) ((iv[5] << 8) | iv[4]));
+       c7108_reg_wr16(C7108_AES_IV1_HI, (u16) ((iv[7] << 8) | iv[6]));
+       c7108_reg_wr16(C7108_AES_IV2_LO, (u16) ((iv[9] << 8) | iv[8]));
+       c7108_reg_wr16(C7108_AES_IV2_HI, (u16) ((iv[11] << 8) | iv[10]));
+       c7108_reg_wr16(C7108_AES_IV3_LO, (u16) ((iv[13] << 8) | iv[12]));
+       c7108_reg_wr16(C7108_AES_IV3_HI, (u16) ((iv[15] << 8) | iv[14]));
+
+    return 0;
+}
+
+static void
+c7108_aes_read_dkey(u32 * dkey)
+{
+        dkey[0] = (c7108_reg_rd16(C7108_AES_EKEY0_HI) << 16) | 
+                  c7108_reg_rd16(C7108_AES_EKEY0_LO);
+       dkey[1] = (c7108_reg_rd16(C7108_AES_EKEY1_HI) << 16) | 
+                  c7108_reg_rd16(C7108_AES_EKEY1_LO);
+       dkey[2] = (c7108_reg_rd16(C7108_AES_EKEY2_HI) << 16) | 
+                  c7108_reg_rd16(C7108_AES_EKEY2_LO);
+       dkey[3] = (c7108_reg_rd16(C7108_AES_EKEY3_HI) << 16) | 
+                  c7108_reg_rd16(C7108_AES_EKEY3_LO);
+       dkey[4] = (c7108_reg_rd16(C7108_AES_EKEY4_HI) << 16) | 
+                   c7108_reg_rd16(C7108_AES_EKEY4_LO);
+       dkey[5] = (c7108_reg_rd16(C7108_AES_EKEY5_HI) << 16) | 
+                   c7108_reg_rd16(C7108_AES_EKEY5_LO);
+       dkey[6] = (c7108_reg_rd16(C7108_AES_EKEY6_HI) << 16) | 
+                   c7108_reg_rd16(C7108_AES_EKEY6_LO);
+       dkey[7] = (c7108_reg_rd16(C7108_AES_EKEY7_HI) << 16) | 
+                   c7108_reg_rd16(C7108_AES_EKEY7_LO);
+}
+
+static int
+c7108_aes_cipher(int op,
+                u32 dst,
+                u32 src,
+                u32 len,
+                int klen,
+                u16 mode,
+                u32 key[8],
+                u8 iv[16])
+{
+        int rv = 0, cnt=0;
+       u16 ctrl = 0, stat = 0;
+
+       AES_LOCK();
+
+       /* Setup key length */
+       if (klen == 128) {
+           ctrl |= C7108_AES_KEY_LEN_128;
+       } else if (klen == 192) {
+           ctrl |= C7108_AES_KEY_LEN_192;
+       } else if (klen == 256) {
+           ctrl |= C7108_AES_KEY_LEN_256;
+       } else {
+           AES_UNLOCK();
+           return -3;
+       }
+       
+       /* Check opcode */
+       if (C7108_AES_ENCRYPT == op) {
+           ctrl |= C7108_AES_ENCRYPT;
+       } else if (C7108_AES_DECRYPT == op) {
+           ctrl |= C7108_AES_DECRYPT;
+       } else {
+           AES_UNLOCK();
+           return -4;
+       }
+       
+       /* check mode */
+       if ( (mode != C7108_AES_CTRL_MODE_CBC) &&
+            (mode != C7108_AES_CTRL_MODE_CFB) &&
+            (mode != C7108_AES_CTRL_MODE_OFB) &&
+            (mode != C7108_AES_CTRL_MODE_CTR) && 
+            (mode != C7108_AES_CTRL_MODE_ECB) ) { 
+           AES_UNLOCK();           
+           return -5;
+       }
+       
+       /* Now set mode */
+       ctrl |= mode;
+       
+       /* For CFB, OFB, and CTR, neither backward key
+        * expansion nor key inversion is required.
+        */
+       if ( (C7108_AES_DECRYPT == op) &&  
+            (C7108_AES_CTRL_MODE_CBC == mode ||
+             C7108_AES_CTRL_MODE_ECB == mode ) ){ 
+
+           /* Program Key */
+           c7108_reg_wr16(C7108_AES_KEY0_LO, (u16) key[4]);
+           c7108_reg_wr16(C7108_AES_KEY0_HI, (u16) (key[4] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY1_LO, (u16) key[5]);
+           c7108_reg_wr16(C7108_AES_KEY1_HI, (u16) (key[5] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY2_LO, (u16) key[6]);
+           c7108_reg_wr16(C7108_AES_KEY2_HI, (u16) (key[6] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY3_LO, (u16) key[7]);
+           c7108_reg_wr16(C7108_AES_KEY3_HI, (u16) (key[7] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY6_LO, (u16) key[2]);
+           c7108_reg_wr16(C7108_AES_KEY6_HI, (u16) (key[2] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY7_LO, (u16) key[3]);
+           c7108_reg_wr16(C7108_AES_KEY7_HI, (u16) (key[3] >> 16));
+           
+           
+           if (192 == klen) { 
+               c7108_reg_wr16(C7108_AES_KEY4_LO, (u16) key[7]);
+               c7108_reg_wr16(C7108_AES_KEY4_HI, (u16) (key[7] >> 16));
+               c7108_reg_wr16(C7108_AES_KEY5_LO, (u16) key[7]);
+               c7108_reg_wr16(C7108_AES_KEY5_HI, (u16) (key[7] >> 16));
+               
+           } else if (256 == klen) {
+               /* 256 */
+               c7108_reg_wr16(C7108_AES_KEY4_LO, (u16) key[0]);
+               c7108_reg_wr16(C7108_AES_KEY4_HI, (u16) (key[0] >> 16));
+               c7108_reg_wr16(C7108_AES_KEY5_LO, (u16) key[1]);
+               c7108_reg_wr16(C7108_AES_KEY5_HI, (u16) (key[1] >> 16));
+               
+           }
+           
+       } else { 
+           /* Program Key */
+           c7108_reg_wr16(C7108_AES_KEY0_LO, (u16) key[0]);
+           c7108_reg_wr16(C7108_AES_KEY0_HI, (u16) (key[0] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY1_LO, (u16) key[1]);
+           c7108_reg_wr16(C7108_AES_KEY1_HI, (u16) (key[1] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY2_LO, (u16) key[2]);
+           c7108_reg_wr16(C7108_AES_KEY2_HI, (u16) (key[2] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY3_LO, (u16) key[3]);
+           c7108_reg_wr16(C7108_AES_KEY3_HI, (u16) (key[3] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY4_LO, (u16) key[4]);
+           c7108_reg_wr16(C7108_AES_KEY4_HI, (u16) (key[4] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY5_LO, (u16) key[5]);
+           c7108_reg_wr16(C7108_AES_KEY5_HI, (u16) (key[5] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY6_LO, (u16) key[6]);
+           c7108_reg_wr16(C7108_AES_KEY6_HI, (u16) (key[6] >> 16));
+           c7108_reg_wr16(C7108_AES_KEY7_LO, (u16) key[7]);
+           c7108_reg_wr16(C7108_AES_KEY7_HI, (u16) (key[7] >> 16));
+           
+       }
+       
+       /* Set IV always */
+       c7108_aes_set_hw_iv(iv);
+       
+       /* Program DMA addresses */
+       if ((rv = c7108_aes_setup_dma(src, dst, len)) < 0) { 
+           AES_UNLOCK();
+           return rv;
+       }
+
+       
+       /* Start AES cipher */
+       c7108_reg_wr16(C7108_AES_CTRL, ctrl | C7108_AES_GO);
+       
+       //printk("Ctrl: 0x%x\n", ctrl | C7108_AES_GO);
+       do {
+           /* TODO: interrupt mode */
+           //        printk("aes_stat=0x%x\n", stat);
+           //udelay(100);
+       } while ((cnt++ < 1000000) && 
+                !((stat=c7108_reg_rd16(C7108_AES_CTRL))&C7108_AES_OP_DONE));
+
+
+       if ((mode == C7108_AES_CTRL_MODE_ECB)||
+           (mode == C7108_AES_CTRL_MODE_CBC)) { 
+           /* Save out key when the lock is held ... */
+           c7108_aes_read_dkey(key);
+       }
+       
+       AES_UNLOCK();
+       return 0;
+       
+}
+
+/*
+ * Generate a new crypto device session.
+ */
+static int
+c7108_newsession(void *arg, u_int32_t *sid, struct cryptoini *cri)
+{
+       struct cipher_7108 **swd;
+       u_int32_t i;
+       char *algo;
+       int mode, xfm_type;
+
+       dprintk("%s()\n", __FUNCTION__);
+       if (sid == NULL || cri == NULL) {
+               dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
+               return EINVAL;
+       }
+
+       if (c7108_sessions) {
+               for (i = 1; i < c7108_sesnum; i++)
+                       if (c7108_sessions[i] == NULL)
+                               break;
+       } else
+               i = 1;          /* NB: to silence compiler warning */
+
+       if (c7108_sessions == NULL || i == c7108_sesnum) {
+           if (c7108_sessions == NULL) {
+               i = 1; /* We leave c7108_sessions[0] empty */
+               c7108_sesnum = CRYPTO_SW_SESSIONS;
+           } else
+               c7108_sesnum *= 2;
+           
+           swd = kmalloc(c7108_sesnum * sizeof(struct cipher_7108 *), 
+                         GFP_ATOMIC);
+           if (swd == NULL) {
+               /* Reset session number */
+               if (c7108_sesnum == CRYPTO_SW_SESSIONS)
+                   c7108_sesnum = 0;
+               else
+                   c7108_sesnum /= 2;
+               dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
+               return ENOBUFS;
+           }
+           memset(swd, 0, c7108_sesnum * sizeof(struct cipher_7108 *));
+           
+           /* Copy existing sessions */
+           if (c7108_sessions) {
+               memcpy(swd, c7108_sessions,
+                      (c7108_sesnum / 2) * sizeof(struct cipher_7108 *));
+               kfree(c7108_sessions);
+           }
+           
+           c7108_sessions = swd;
+
+       }
+       
+       swd = &c7108_sessions[i];
+       *sid = i;
+
+       while (cri) {
+               *swd = (struct cipher_7108 *) 
+                   kmalloc(sizeof(struct cipher_7108), GFP_ATOMIC);
+               if (*swd == NULL) {
+                   c7108_freesession(NULL, i);
+                   dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+                   return ENOBUFS;
+               }
+               memset(*swd, 0, sizeof(struct cipher_7108));
+
+               algo = NULL;
+               mode = 0;
+               xfm_type = HW_TYPE_CIPHER;
+
+               switch (cri->cri_alg) {
+
+               case CRYPTO_AES_CBC:
+                       algo = "aes";
+                       mode = CRYPTO_TFM_MODE_CBC;
+                       c7108_crypto_mode = C7108_AES_CTRL_MODE_CBC;
+                       break;
+#if 0
+               case CRYPTO_AES_CTR:
+                       algo = "aes_ctr";
+                       mode = CRYPTO_TFM_MODE_CBC;
+                       c7108_crypto_mode = C7108_AES_CTRL_MODE_CTR;
+                       break;
+               case CRYPTO_AES_ECB:
+                       algo = "aes_ecb";
+                       mode = CRYPTO_TFM_MODE_CBC;
+                       c7108_crypto_mode = C7108_AES_CTRL_MODE_ECB;
+                       break;
+               case CRYPTO_AES_OFB:
+                       algo = "aes_ofb";
+                       mode = CRYPTO_TFM_MODE_CBC;
+                       c7108_crypto_mode = C7108_AES_CTRL_MODE_OFB;
+                       break;
+               case CRYPTO_AES_CFB:
+                       algo = "aes_cfb";
+                       mode = CRYPTO_TFM_MODE_CBC;
+                       c7108_crypto_mode = C7108_AES_CTRL_MODE_CFB;
+                       break;
+#endif
+               default:
+                       printk("unsupported crypto algorithm: %d\n", 
+                              cri->cri_alg);
+                       return -EINVAL;
+                       break;
+               }
+
+
+               if (!algo || !*algo) {
+                   printk("cypher_7108_crypto: Unknown algo 0x%x\n", 
+                          cri->cri_alg);
+                   c7108_freesession(NULL, i);
+                   return EINVAL;
+               }
+               
+               if (xfm_type == HW_TYPE_CIPHER) {
+                   if (debug) {
+                       dprintk("%s key:", __FUNCTION__);
+                       for (i = 0; i < (cri->cri_klen + 7) / 8; i++)
+                           dprintk("%s0x%02x", (i % 8) ? " " : "\n    ",
+                                   cri->cri_key[i]);
+                       dprintk("\n");
+                   }
+
+               } else if (xfm_type == SW_TYPE_HMAC || 
+                          xfm_type == SW_TYPE_HASH) {
+                   printk("cypher_7108_crypto: HMAC unsupported!\n");
+                   return -EINVAL;
+                   c7108_freesession(NULL, i);
+               } else {
+                   printk("cypher_7108_crypto: "
+                          "Unhandled xfm_type %d\n", xfm_type);
+                   c7108_freesession(NULL, i);
+                   return EINVAL;
+               }
+               
+               (*swd)->cri_alg = cri->cri_alg;
+               (*swd)->xfm_type = xfm_type;
+               
+               cri = cri->cri_next;
+               swd = &((*swd)->next);
+       }
+       return 0;
+}
+
+/*
+ * Free a session.
+ */
+static int
+c7108_freesession(void *arg, u_int64_t tid)
+{
+       struct cipher_7108 *swd;
+       u_int32_t sid = CRYPTO_SESID2LID(tid);
+
+       dprintk("%s()\n", __FUNCTION__);
+       if (sid > c7108_sesnum || c7108_sessions == NULL ||
+                       c7108_sessions[sid] == NULL) {
+               dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+               return(EINVAL);
+       }
+
+       /* Silently accept and return */
+       if (sid == 0)
+               return(0);
+
+       while ((swd = c7108_sessions[sid]) != NULL) {
+               c7108_sessions[sid] = swd->next;
+               kfree(swd);
+       }
+       return 0;
+}
+
+/*
+ * Process a hardware request.
+ */
+static int
+c7108_process(void *arg, struct cryptop *crp, int hint)
+{
+       struct cryptodesc *crd;
+       struct cipher_7108 *sw;
+       u_int32_t lid;
+       int type;
+       u32 hwkey[8];
+
+#define SCATTERLIST_MAX 16
+       struct scatterlist sg[SCATTERLIST_MAX];
+       int sg_num, sg_len, skip;
+       struct sk_buff *skb = NULL;
+       struct uio *uiop = NULL;
+
+       dprintk("%s()\n", __FUNCTION__);
+       /* Sanity check */
+       if (crp == NULL) {
+               dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+               return EINVAL;
+       }
+
+       crp->crp_etype = 0;
+
+       if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
+               dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+               crp->crp_etype = EINVAL;
+               goto done;
+       }
+
+       lid = crp->crp_sid & 0xffffffff;
+       if (lid >= c7108_sesnum || lid == 0 || c7108_sessions == NULL ||
+                       c7108_sessions[lid] == NULL) {
+               crp->crp_etype = ENOENT;
+               dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
+               goto done;
+       }
+
+       /*
+        * do some error checking outside of the loop for SKB and IOV
+        * processing this leaves us with valid skb or uiop pointers
+        * for later
+        */
+       if (crp->crp_flags & CRYPTO_F_SKBUF) {
+               skb = (struct sk_buff *) crp->crp_buf;
+               if (skb_shinfo(skb)->nr_frags >= SCATTERLIST_MAX) {
+                       printk("%s,%d: %d nr_frags > SCATTERLIST_MAX", 
+                              __FILE__, __LINE__,
+                              skb_shinfo(skb)->nr_frags);
+                       goto done;
+               }
+       } else if (crp->crp_flags & CRYPTO_F_IOV) {
+               uiop = (struct uio *) crp->crp_buf;
+               if (uiop->uio_iovcnt > SCATTERLIST_MAX) {
+                       printk("%s,%d: %d uio_iovcnt > SCATTERLIST_MAX", 
+                              __FILE__, __LINE__,
+                              uiop->uio_iovcnt);
+                       goto done;
+               }
+       }
+
+       /* Go through crypto descriptors, processing as we go */
+       for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
+           /*
+            * Find the crypto context.
+            *
+            * XXX Note that the logic here prevents us from having
+            * XXX the same algorithm multiple times in a session
+            * XXX (or rather, we can but it won't give us the right
+            * XXX results). To do that, we'd need some way of differentiating
+            * XXX between the various instances of an algorithm (so we can
+            * XXX locate the correct crypto context).
+            */
+           for (sw = c7108_sessions[lid]; 
+                sw && sw->cri_alg != crd->crd_alg;
+                sw = sw->next)
+               ;
+           
+           /* No such context ? */
+           if (sw == NULL) {
+               crp->crp_etype = EINVAL;
+               dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+               goto done;
+           }
+           
+           skip = crd->crd_skip;
+           
+           /*
+            * setup the SG list skip from the start of the buffer
+            */
+           memset(sg, 0, sizeof(sg));
+           if (crp->crp_flags & CRYPTO_F_SKBUF) {
+               int i, len;
+               type = CRYPTO_BUF_SKBUF;
+               
+               sg_num = 0;
+               sg_len = 0;
+
+               if (skip < skb_headlen(skb)) {
+                   //sg[sg_num].page   = virt_to_page(skb->data + skip);
+                       //sg[sg_num].offset = offset_in_page(skb->data + skip);
+                   len = skb_headlen(skb) - skip;
+                   if (len + sg_len > crd->crd_len)
+                       len = crd->crd_len - sg_len;
+                   //sg[sg_num].length = len;
+                   sg_set_page(&sg[sg_num], virt_to_page(skb->data + skip), len, offset_in_page(skb->data + skip));
+                       sg_len += sg[sg_num].length;
+                   sg_num++;
+                   skip = 0;
+               } else
+                   skip -= skb_headlen(skb);
+               
+               for (i = 0; sg_len < crd->crd_len &&
+                        i < skb_shinfo(skb)->nr_frags &&
+                        sg_num < SCATTERLIST_MAX; i++) {
+                   if (skip < skb_shinfo(skb)->frags[i].size) {
+                       //sg[sg_num].page   = skb_shinfo(skb)->frags[i].page;
+                       //sg[sg_num].offset = skb_shinfo(skb)->frags[i].page_offset + skip;
+                       len = skb_shinfo(skb)->frags[i].size - skip;
+                       if (len + sg_len > crd->crd_len)
+                           len = crd->crd_len - sg_len;
+                       //sg[sg_num].length = len;
+                       sg_set_page(&sg[sg_num], skb_shinfo(skb)->frags[i].page, len, skb_shinfo(skb)->frags[i].page_offset + skip);
+                       sg_len += sg[sg_num].length;
+                       sg_num++;
+                       skip = 0;
+                   } else
+                       skip -= skb_shinfo(skb)->frags[i].size;
+               }
+           } else if (crp->crp_flags & CRYPTO_F_IOV) {
+               int len;
+               type = CRYPTO_BUF_IOV;
+               sg_len = 0;
+               for (sg_num = 0; sg_len < crd->crd_len &&
+                        sg_num < uiop->uio_iovcnt &&
+                        sg_num < SCATTERLIST_MAX; sg_num++) {
+                   if (skip < uiop->uio_iov[sg_num].iov_len) {
+                       //sg[sg_num].page   =                       virt_to_page(uiop->uio_iov[sg_num].iov_base+skip);
+                       //sg[sg_num].offset =                      offset_in_page(uiop->uio_iov[sg_num].iov_base+skip);
+                       len = uiop->uio_iov[sg_num].iov_len - skip;
+                       if (len + sg_len > crd->crd_len)
+                           len = crd->crd_len - sg_len;
+                       //sg[sg_num].length = len;
+                       sg_set_page(&sg[sg_num], virt_to_page(uiop->uio_iov[sg_num].iov_base+skip), len, offset_in_page(uiop->uio_iov[sg_num].iov_base+skip));
+                       sg_len += sg[sg_num].length;
+                       skip = 0;
+                   } else 
+                       skip -= uiop->uio_iov[sg_num].iov_len;
+               }
+           } else {
+               type = CRYPTO_BUF_CONTIG;
+               //sg[0].page   = virt_to_page(crp->crp_buf + skip);
+               //sg[0].offset = offset_in_page(crp->crp_buf + skip);
+               sg_len = (crp->crp_ilen - skip);
+               if (sg_len > crd->crd_len)
+                   sg_len = crd->crd_len;
+               //sg[0].length = sg_len;
+               sg_set_page(&sg[0], virt_to_page(crp->crp_buf + skip), sg_len, offset_in_page(crp->crp_buf + skip));
+               sg_num = 1;
+           }
+           
+           
+           switch (sw->xfm_type) {
+
+           case HW_TYPE_CIPHER: {
+
+               unsigned char iv[64];
+               unsigned char *ivp = iv;
+               int i;
+               int ivsize = 16;    /* fixed for AES */
+               int blocksize = 16; /* fixed for AES */
+
+               if (sg_len < blocksize) {
+                   crp->crp_etype = EINVAL;
+                   dprintk("%s,%d: EINVAL len %d < %d\n", 
+                           __FILE__, __LINE__,
+                           sg_len, 
+                           blocksize);
+                   goto done;
+               }
+               
+               if (ivsize > sizeof(iv)) {
+                   crp->crp_etype = EINVAL;
+                   dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+                   goto done;
+               }
+               
+               if (crd->crd_flags & CRD_F_ENCRYPT) { /* encrypt */
+                   
+                   if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
+                       ivp = crd->crd_iv;
+                   } else {
+                       get_random_bytes(ivp, ivsize);
+                   }
+                   /*
+                    * do we have to copy the IV back to the buffer ?
+                    */
+                   if ((crd->crd_flags & CRD_F_IV_PRESENT) == 0) {
+                           crypto_copyback(crp->crp_buf,
+                                         crd->crd_inject,
+                                         ivsize,
+                                         (caddr_t)ivp);
+                   }
+
+                   c7108_xlate_key(crd->crd_klen,
+                                   (u8*)crd->crd_key, (u32*)hwkey);
+
+                   /* Encrypt SG list */
+                   for (i = 0; i < sg_num; i++) { 
+                       sg[i].dma_address = 
+                           dma_map_single(NULL, 
+                                          kmap(sg_page(&sg[i])) + sg[i].offset, sg_len, DMA_BIDIRECTIONAL);
+#if 0                                                     
+                       printk("sg[%d]:0x%08x, off 0x%08x "
+                              "kmap 0x%08x phys 0x%08x\n", 
+                              i, sg[i].page, sg[i].offset,
+                              kmap(sg[i].page) + sg[i].offset,
+                              sg[i].dma_address);
+#endif
+                       c7108_aes_cipher(C7108_AES_ENCRYPT,
+                                        sg[i].dma_address,
+                                        sg[i].dma_address,
+                                        sg_len,
+                                        crd->crd_klen,
+                                        c7108_crypto_mode,
+                                        hwkey,
+                                        ivp);
+
+                       if ((c7108_crypto_mode == C7108_AES_CTRL_MODE_CBC)||
+                           (c7108_crypto_mode == C7108_AES_CTRL_MODE_ECB)) { 
+                           /* Read back expanded key and cache it in key
+                            * context.
+                            * NOTE: for ECB/CBC modes only (not CTR, CFB, OFB)
+                            *       where you set the key once.
+                            */
+                           c7108_cache_key(crd->crd_klen, 
+                                           (u32*)hwkey, (u8*)crd->crd_key);
+#if 0
+                           printk("%s expanded key:", __FUNCTION__);
+                           for (i = 0; i < (crd->crd_klen + 7) / 8; i++)
+                               printk("%s0x%02x", (i % 8) ? " " : "\n    ",
+                                      crd->crd_key[i]);
+                           printk("\n");
+#endif
+                       }
+                   }
+               }
+               else { /*decrypt */
+
+                   if (crd->crd_flags & CRD_F_IV_EXPLICIT) {
+                       ivp = crd->crd_iv;
+                   } else {
+                       crypto_copydata(crp->crp_buf, crd->crd_inject,
+                                 ivsize, (caddr_t)ivp);
+                   }
+
+                   c7108_xlate_key(crd->crd_klen,
+                                   (u8*)crd->crd_key, (u32*)hwkey);
+
+                   /* Decrypt SG list */
+                   for (i = 0; i < sg_num; i++) { 
+                       sg[i].dma_address = 
+                           dma_map_single(NULL, 
+                                          kmap(sg_page(&sg[i])) + sg[i].offset,
+                                          sg_len, DMA_BIDIRECTIONAL);
+
+#if 0
+                       printk("sg[%d]:0x%08x, off 0x%08x "
+                              "kmap 0x%08x phys 0x%08x\n", 
+                              i, sg[i].page, sg[i].offset,
+                              kmap(sg[i].page) + sg[i].offset,
+                              sg[i].dma_address);
+#endif
+                       c7108_aes_cipher(C7108_AES_DECRYPT,
+                                        sg[i].dma_address,
+                                        sg[i].dma_address,
+                                        sg_len,
+                                        crd->crd_klen,
+                                        c7108_crypto_mode,
+                                        hwkey,
+                                        ivp);
+                   }
+               }
+           } break;
+           case SW_TYPE_HMAC:
+           case SW_TYPE_HASH:
+               crp->crp_etype = EINVAL;
+               goto done;
+               break;
+               
+           case SW_TYPE_COMP:
+               crp->crp_etype = EINVAL;
+               goto done;
+               break;
+               
+           default:
+               /* Unknown/unsupported algorithm */
+               dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+               crp->crp_etype = EINVAL;
+               goto done;
+           }
+       }
+       
+done:
+       crypto_done(crp);
+       return 0;
+}
+
+static struct {                                                                                                                 
+       softc_device_decl sc_dev;                                                                                               
+} a7108dev;
+
+static device_method_t a7108_methods = {                                                                                          
+/* crypto device methods */                                                                                             
+       DEVMETHOD(cryptodev_newsession, c7108_newsession),                                                                  
+       DEVMETHOD(cryptodev_freesession, c7108_freesession),                                                             
+       DEVMETHOD(cryptodev_process, c7108_process),                                                                     
+       DEVMETHOD(cryptodev_kprocess, NULL) 
+};   
+
+static int
+cypher_7108_crypto_init(void)
+{
+       dprintk("%s(%p)\n", __FUNCTION__, cypher_7108_crypto_init);
+       
+       iobar = (unsigned long)ioremap(CCU_AES_REG_BASE, 0x4000);
+       printk("7108: AES @ 0x%08x (0x%08x phys) %s mode\n", 
+              iobar, CCU_AES_REG_BASE, 
+              c7108_crypto_mode & C7108_AES_CTRL_MODE_CBC ? "CBC" :
+              c7108_crypto_mode & C7108_AES_CTRL_MODE_ECB ? "ECB" : 
+              c7108_crypto_mode & C7108_AES_CTRL_MODE_CTR ? "CTR" : 
+              c7108_crypto_mode & C7108_AES_CTRL_MODE_CFB ? "CFB" : 
+              c7108_crypto_mode & C7108_AES_CTRL_MODE_OFB ? "OFB" : "???");
+       csr_mutex  = SPIN_LOCK_UNLOCKED;
+
+       memset(&a7108dev, 0, sizeof(a7108dev));                                                                                     
+       softc_device_init(&a7108dev, "aes7108", 0, a7108_methods);
+
+               c7108_id = crypto_get_driverid(softc_get_device(&a7108dev), CRYPTOCAP_F_HARDWARE);
+       if (c7108_id < 0)
+               panic("7108: crypto device cannot initialize!");
+
+//     crypto_register(c7108_id, CRYPTO_AES_CBC, 0, 0, c7108_newsession, c7108_freesession, c7108_process, NULL);
+       crypto_register(c7108_id, CRYPTO_AES_CBC, 0, 0);
+
+       return(0);
+}
+
+static void
+cypher_7108_crypto_exit(void)
+{
+       dprintk("%s()\n", __FUNCTION__);
+       crypto_unregister_all(c7108_id);
+       c7108_id = -1;
+}
+
+module_init(cypher_7108_crypto_init);
+module_exit(cypher_7108_crypto_exit);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_DESCRIPTION("Cypher 7108 Crypto (OCF module for kernel crypto)");
diff --git a/target/linux/generic-2.6/files/crypto/ocf/c7108/aes-7108.h b/target/linux/generic-2.6/files/crypto/ocf/c7108/aes-7108.h
new file mode 100644 (file)
index 0000000..0c7bfcb
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2006 Micronas USA
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ */
+
+#ifndef __AES_7108_H__
+#define __AES_7108_H__
+
+/* Cypher 7108 AES Controller Hardware */
+#define CCU_REG_BASE       0x1b500000  
+#define CCU_AES_REG_BASE   (CCU_REG_BASE + 0x100)
+#define C7108_AES_KEY0_LO        (0x0000) 
+#define C7108_AES_KEY0_HI        (0x0004) 
+#define C7108_AES_KEY1_LO        (0x0008) 
+#define C7108_AES_KEY1_HI        (0x000c) 
+#define C7108_AES_KEY2_LO        (0x0010) 
+#define C7108_AES_KEY2_HI        (0x0014) 
+#define C7108_AES_KEY3_LO        (0x0018) 
+#define C7108_AES_KEY3_HI        (0x001c) 
+#define C7108_AES_KEY4_LO        (0x0020) 
+#define C7108_AES_KEY4_HI        (0x0024) 
+#define C7108_AES_KEY5_LO        (0x0028) 
+#define C7108_AES_KEY5_HI        (0x002c) 
+#define C7108_AES_KEY6_LO        (0x0030) 
+#define C7108_AES_KEY6_HI        (0x0034) 
+#define C7108_AES_KEY7_LO        (0x0038) 
+#define C7108_AES_KEY7_HI        (0x003c) 
+#define C7108_AES_IV0_LO         (0x0040) 
+#define C7108_AES_IV0_HI         (0x0044) 
+#define C7108_AES_IV1_LO         (0x0048) 
+#define C7108_AES_IV1_HI         (0x004c) 
+#define C7108_AES_IV2_LO         (0x0050) 
+#define C7108_AES_IV2_HI         (0x0054) 
+#define C7108_AES_IV3_LO         (0x0058) 
+#define C7108_AES_IV3_HI         (0x005c) 
+
+#define C7108_AES_DMA_SRC0_LO    (0x0068) /* Bits 0:15 */
+#define C7108_AES_DMA_SRC0_HI    (0x006c) /* Bits 27:16 */
+#define C7108_AES_DMA_DST0_LO    (0x0070) /* Bits 0:15 */
+#define C7108_AES_DMA_DST0_HI    (0x0074) /* Bits 27:16 */
+#define C7108_AES_DMA_LEN        (0x0078)  /*Bytes:(Count+1)x16 */
+
+/* AES/Copy engine control register */
+#define C7108_AES_CTRL           (0x007c) /* AES control */
+#define C7108_AES_CTRL_RS        (1<<0)     /* Which set of src/dst to use */
+
+/* AES Cipher mode, controlled by setting Bits 2:0 */
+#define C7108_AES_CTRL_MODE_CBC     0
+#define C7108_AES_CTRL_MODE_CFB     (1<<0)
+#define C7108_AES_CTRL_MODE_OFB     (1<<1)
+#define C7108_AES_CTRL_MODE_CTR     ((1<<0)|(1<<1))
+#define C7108_AES_CTRL_MODE_ECB     (1<<2)
+
+/* AES Key length , Bits 5:4 */
+#define C7108_AES_KEY_LEN_128         0       /* 00 */
+#define C7108_AES_KEY_LEN_192         (1<<4)  /* 01 */
+#define C7108_AES_KEY_LEN_256         (1<<5)  /* 10 */
+
+/* AES Operation (crypt/decrypt), Bit 3 */
+#define C7108_AES_DECRYPT             (1<<3)   /* Clear for encrypt */
+#define C7108_AES_ENCRYPT              0       
+#define C7108_AES_INTR                (1<<13) /* Set on done trans from 0->1*/
+#define C7108_AES_GO                  (1<<14) /* Run */
+#define C7108_AES_OP_DONE             (1<<15) /* Set when complete */
+
+
+/* Expanded key registers */
+#define C7108_AES_EKEY0_LO            (0x0080)
+#define C7108_AES_EKEY0_HI            (0x0084)
+#define C7108_AES_EKEY1_LO            (0x0088)
+#define C7108_AES_EKEY1_HI            (0x008c)
+#define C7108_AES_EKEY2_LO            (0x0090)
+#define C7108_AES_EKEY2_HI            (0x0094)
+#define C7108_AES_EKEY3_LO            (0x0098)
+#define C7108_AES_EKEY3_HI            (0x009c)
+#define C7108_AES_EKEY4_LO            (0x00a0)
+#define C7108_AES_EKEY4_HI            (0x00a4)
+#define C7108_AES_EKEY5_LO            (0x00a8)
+#define C7108_AES_EKEY5_HI            (0x00ac)
+#define C7108_AES_EKEY6_LO            (0x00b0)
+#define C7108_AES_EKEY6_HI            (0x00b4)
+#define C7108_AES_EKEY7_LO            (0x00b8)
+#define C7108_AES_EKEY7_HI            (0x00bc)
+#define C7108_AES_OK                  (0x00fc) /* Reset: "OK" */
+
+#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
+
+/* Software session entry */
+
+#define HW_TYPE_CIPHER 0
+#define SW_TYPE_HMAC   1
+#define SW_TYPE_AUTH2  2
+#define SW_TYPE_HASH   3
+#define SW_TYPE_COMP   4
+
+struct cipher_7108 {
+       int                     xfm_type;
+       int                     cri_alg;
+       union {
+               struct {
+                       char sw_key[HMAC_BLOCK_LEN];
+                       int  sw_klen;
+                       int  sw_authlen;
+               } hmac;
+       } u;
+       struct cipher_7108      *next;
+};
+
+
+
+#endif /* __C7108_AES_7108_H__ */
index 3bf7c32..6d7d3ad 100644 (file)
@@ -1,8 +1,8 @@
 /*      $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $        */
 
 /*
- * Linux port done by David McCullough <david_mccullough@securecomputing.com>
- * Copyright (C) 2006-2007 David McCullough
+ * Linux port done by David McCullough <david_mccullough@mcafee.com>
+ * Copyright (C) 2006-2010 David McCullough
  * Copyright (C) 2004-2005 Intel Corporation.
  * The license and original author are listed below.
  *
index 5121b3d..9735f0c 100644 (file)
@@ -1,6 +1,6 @@
 /*-
- * Linux port done by David McCullough <david_mccullough@securecomputing.com>
- * Copyright (C) 2006-2007 David McCullough
+ * Linux port done by David McCullough <david_mccullough@mcafee.com>
+ * Copyright (C) 2006-2010 David McCullough
  * Copyright (C) 2004-2005 Intel Corporation.
  * The license and original author are listed below.
  *
@@ -139,6 +139,9 @@ struct cryptocap {
 #define CRYPTOCAP_F_CLEANUP    0x80000000      /* needs resource cleanup */
        int             cc_qblocked;            /* (q) symmetric q blocked */
        int             cc_kqblocked;           /* (q) asymmetric q blocked */
+
+       int             cc_unqblocked;          /* (q) symmetric q blocked */
+       int             cc_unkqblocked;         /* (q) asymmetric q blocked */
 };
 static struct cryptocap *crypto_drivers = NULL;
 static int crypto_drivers_num = 0;
@@ -207,6 +210,11 @@ static struct kmem_cache *cryptop_zone;
 static struct kmem_cache *cryptodesc_zone;
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
+#include <linux/sched.h>
+#define        kill_proc(p,s,v)        send_sig(s,find_task_by_vpid(p),0)
+#endif
+
 #define debug crypto_debug
 int crypto_debug = 0;
 module_param(crypto_debug, int, 0644);
@@ -255,6 +263,18 @@ module_param(crypto_devallowsoft, int, 0644);
 MODULE_PARM_DESC(crypto_devallowsoft,
           "Enable/disable use of software crypto support");
 
+/*
+ * This parameter controls the maximum number of crypto operations to 
+ * do consecutively in the crypto kernel thread before scheduling to allow 
+ * other processes to run. Without it, it is possible to get into a 
+ * situation where the crypto thread never allows any other processes to run.
+ * Default to 1000 which should be less than one second.
+ */
+static int crypto_max_loopcount = 1000;
+module_param(crypto_max_loopcount, int, 0644);
+MODULE_PARM_DESC(crypto_max_loopcount,
+          "Maximum number of crypto ops to do before yielding to other processes");
+
 static pid_t   cryptoproc = (pid_t) -1;
 static struct  completion cryptoproc_exited;
 static DECLARE_WAIT_QUEUE_HEAD(cryptoproc_wait);
@@ -760,10 +780,12 @@ crypto_unblock(u_int32_t driverid, int what)
        if (cap != NULL) {
                if (what & CRYPTO_SYMQ) {
                        cap->cc_qblocked = 0;
+                       cap->cc_unqblocked = 0;
                        crypto_all_qblocked = 0;
                }
                if (what & CRYPTO_ASYMQ) {
                        cap->cc_kqblocked = 0;
+                       cap->cc_unkqblocked = 0;
                        crypto_all_kqblocked = 0;
                }
                if (crp_sleep)
@@ -798,6 +820,10 @@ crypto_dispatch(struct cryptop *crp)
        }
        crypto_q_cnt++;
 
+       /* make sure we are starting a fresh run on this crp. */
+       crp->crp_flags &= ~CRYPTO_F_DONE;
+       crp->crp_etype = 0;
+
        /*
         * Caller marked the request to be processed immediately; dispatch
         * it directly to the driver unless the driver is currently blocked.
@@ -809,12 +835,14 @@ crypto_dispatch(struct cryptop *crp)
                KASSERT(cap != NULL, ("%s: Driver disappeared.", __func__));
                if (!cap->cc_qblocked) {
                        crypto_all_qblocked = 0;
-                       crypto_drivers[hid].cc_qblocked = 1;
+                       crypto_drivers[hid].cc_unqblocked = 1;
                        CRYPTO_Q_UNLOCK();
                        result = crypto_invoke(cap, crp, 0);
                        CRYPTO_Q_LOCK();
-                       if (result != ERESTART)
-                               crypto_drivers[hid].cc_qblocked = 0;
+                       if (result == ERESTART)
+                               if (crypto_drivers[hid].cc_unqblocked)
+                                       crypto_drivers[hid].cc_qblocked = 1;
+                       crypto_drivers[hid].cc_unqblocked = 0;
                }
        }
        if (result == ERESTART) {
@@ -829,13 +857,15 @@ crypto_dispatch(struct cryptop *crp)
                 */
                list_add(&crp->crp_next, &crp_q);
                cryptostats.cs_blocks++;
+               result = 0;
        } else if (result == -1) {
                TAILQ_INSERT_TAIL(&crp_q, crp, crp_next);
+               result = 0;
        }
        if (crp_sleep)
                wake_up_interruptible(&cryptoproc_wait);
        CRYPTO_Q_UNLOCK();
-       return 0;
+       return result;
 }
 
 /*
@@ -1246,6 +1276,7 @@ crypto_proc(void *arg)
        u_int32_t hid;
        int result, hint;
        unsigned long q_flags;
+       int loopcount = 0;
 
        ocf_daemonize("crypto");
 
@@ -1306,7 +1337,7 @@ crypto_proc(void *arg)
                        hid = CRYPTO_SESID2HID(submit->crp_sid);
                        crypto_all_qblocked = 0;
                        list_del(&submit->crp_next);
-                       crypto_drivers[hid].cc_qblocked = 1;
+                       crypto_drivers[hid].cc_unqblocked = 1;
                        cap = crypto_checkdriver(hid);
                        CRYPTO_Q_UNLOCK();
                        KASSERT(cap != NULL, ("%s:%u Driver disappeared.",
@@ -1326,8 +1357,11 @@ crypto_proc(void *arg)
                                /* XXX validate sid again? */
                                list_add(&submit->crp_next, &crp_q);
                                cryptostats.cs_blocks++;
-                       } else
-                               crypto_drivers[hid].cc_qblocked=0;
+                               if (crypto_drivers[hid].cc_unqblocked)
+                                       crypto_drivers[hid].cc_qblocked=0;
+                               crypto_drivers[hid].cc_unqblocked=0;
+                       }
+                       crypto_drivers[hid].cc_unqblocked = 0;
                }
 
                crypto_all_kqblocked = !list_empty(&crp_kq);
@@ -1396,6 +1430,7 @@ crypto_proc(void *arg)
                                        __FUNCTION__,
                                        list_empty(&crp_q), crypto_all_qblocked,
                                        list_empty(&crp_kq), crypto_all_kqblocked);
+                       loopcount = 0;
                        CRYPTO_Q_UNLOCK();
                        crp_sleep = 1;
                        wait_event_interruptible(cryptoproc_wait,
@@ -1417,7 +1452,15 @@ crypto_proc(void *arg)
                        if (cryptoproc == (pid_t) -1)
                                break;
                        cryptostats.cs_intrs++;
+               } else if (loopcount > crypto_max_loopcount) {
+                       /*
+                        * Give other processes a chance to run if we've 
+                        * been using the CPU exclusively for a while.
+                        */
+                       loopcount = 0;
+                       schedule();
                }
+               loopcount++;
        }
        CRYPTO_Q_UNLOCK();
        complete_and_exit(&cryptoproc_exited, 0);
@@ -1599,7 +1642,7 @@ crypto_init(void)
 {
        int error;
 
-       dprintk("%s(0x%x)\n", __FUNCTION__, (int) crypto_init);
+       dprintk("%s(%p)\n", __FUNCTION__, (void *) crypto_init);
 
        if (crypto_initted)
                return 0;
@@ -1737,5 +1780,5 @@ module_init(crypto_init);
 module_exit(crypto_exit);
 
 MODULE_LICENSE("BSD");
-MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
+MODULE_AUTHOR("David McCullough <david_mccullough@mcafee.com>");
 MODULE_DESCRIPTION("OCF (OpenBSD Cryptographic Framework)");
diff --git a/target/linux/generic-2.6/files/crypto/ocf/cryptocteon/Makefile b/target/linux/generic-2.6/files/crypto/ocf/cryptocteon/Makefile
new file mode 100644 (file)
index 0000000..eeed0d6
--- /dev/null
@@ -0,0 +1,17 @@
+# for SGlinux builds
+-include $(ROOTDIR)/modules/.config
+
+obj-$(CONFIG_OCF_CRYPTOCTEON) += cryptocteon.o
+
+obj ?= .
+EXTRA_CFLAGS += -I$(obj)/.. -I$(obj)/
+
+ifdef CONFIG_OCF_CRYPTOCTEON
+# you need the cavium crypto component installed
+EXTRA_CFLAGS += -I$(ROOTDIR)/prop/include
+endif
+
+ifdef TOPDIR
+-include $(TOPDIR)/Rules.make
+endif
+
diff --git a/target/linux/generic-2.6/files/crypto/ocf/cryptocteon/cavium_crypto.c b/target/linux/generic-2.6/files/crypto/ocf/cryptocteon/cavium_crypto.c
new file mode 100644 (file)
index 0000000..ceaf77c
--- /dev/null
@@ -0,0 +1,2283 @@
+/*
+ * Copyright (c) 2009 David McCullough <david.mccullough@securecomputing.com>
+ *
+ * Copyright (c) 2003-2007 Cavium Networks (support@cavium.com). All rights
+ * reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Cavium Networks
+ * 4. Cavium Networks' name may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ * 
+ * This Software, including technical data, may be subject to U.S. export
+ * control laws, including the U.S. Export Administration Act and its
+ * associated regulations, and may be subject to export or import regulations
+ * in other countries. You warrant that You will comply strictly in all
+ * respects with all such regulations and acknowledge that you have the
+ * responsibility to obtain licenses to export, re-export or import the
+ * Software.
+ * 
+ * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" AND
+ * WITH ALL FAULTS AND CAVIUM MAKES NO PROMISES, REPRESENTATIONS OR WARRANTIES,
+ * EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO THE
+ * SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
+ * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
+ * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
+ * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
+ * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
+ * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
+ * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
+*/
+/****************************************************************************/
+
+#include <linux/scatterlist.h>
+#include <asm/octeon/octeon.h>
+#include "octeon-asm.h"
+
+/****************************************************************************/
+
+extern unsigned long octeon_crypto_enable(struct octeon_cop2_state *);
+extern void octeon_crypto_disable(struct octeon_cop2_state *, unsigned long);
+
+#define SG_INIT(s, p, i, l) \
+       { \
+           (i) = 0; \
+           (l) = (s)[0].length; \
+           (p) = (typeof(p)) sg_virt((s)); \
+               CVMX_PREFETCH0((p)); \
+       }
+
+#define SG_CONSUME(s, p, i, l) \
+       { \
+               (p)++; \
+               (l) -= sizeof(*(p)); \
+               if ((l) < 0) { \
+                       dprintk("%s, %d: l = %d\n", __FILE__, __LINE__, l); \
+               } else if ((l) == 0) { \
+                   (i)++; \
+                   (l) = (s)[0].length; \
+                   (p) = (typeof(p)) sg_virt(s); \
+                       CVMX_PREFETCH0((p)); \
+               } \
+       }
+
+#define ESP_HEADER_LENGTH     8
+#define DES_CBC_IV_LENGTH     8
+#define AES_CBC_IV_LENGTH     16
+#define ESP_HMAC_LEN          12
+
+#define ESP_HEADER_LENGTH 8
+#define DES_CBC_IV_LENGTH 8
+
+/****************************************************************************/
+
+#define CVM_LOAD_SHA_UNIT(dat, next)  { \
+   if (next == 0) {                     \
+      next = 1;                         \
+      CVMX_MT_HSH_DAT (dat, 0);         \
+   } else if (next == 1) {              \
+      next = 2;                         \
+      CVMX_MT_HSH_DAT (dat, 1);         \
+   } else if (next == 2) {              \
+      next = 3;                    \
+      CVMX_MT_HSH_DAT (dat, 2);         \
+   } else if (next == 3) {              \
+      next = 4;                         \
+      CVMX_MT_HSH_DAT (dat, 3);         \
+   } else if (next == 4) {              \
+      next = 5;                           \
+      CVMX_MT_HSH_DAT (dat, 4);         \
+   } else if (next == 5) {              \
+      next = 6;                         \
+      CVMX_MT_HSH_DAT (dat, 5);         \
+   } else if (next == 6) {              \
+      next = 7;                         \
+      CVMX_MT_HSH_DAT (dat, 6);         \
+   } else {                             \
+     CVMX_MT_HSH_STARTSHA (dat);        \
+     next = 0;                          \
+   }                                    \
+}
+
+#define CVM_LOAD2_SHA_UNIT(dat1, dat2, next)  { \
+   if (next == 0) {                      \
+      CVMX_MT_HSH_DAT (dat1, 0);         \
+      CVMX_MT_HSH_DAT (dat2, 1);         \
+      next = 2;                          \
+   } else if (next == 1) {               \
+      CVMX_MT_HSH_DAT (dat1, 1);         \
+      CVMX_MT_HSH_DAT (dat2, 2);         \
+      next = 3;                          \
+   } else if (next == 2) {               \
+      CVMX_MT_HSH_DAT (dat1, 2);         \
+      CVMX_MT_HSH_DAT (dat2, 3);         \
+      next = 4;                          \
+   } else if (next == 3) {               \
+      CVMX_MT_HSH_DAT (dat1, 3);         \
+      CVMX_MT_HSH_DAT (dat2, 4);         \
+      next = 5;                          \
+   } else if (next == 4) {               \
+      CVMX_MT_HSH_DAT (dat1, 4);         \
+      CVMX_MT_HSH_DAT (dat2, 5);         \
+      next = 6;                          \
+   } else if (next == 5) {               \
+      CVMX_MT_HSH_DAT (dat1, 5);         \
+      CVMX_MT_HSH_DAT (dat2, 6);         \
+      next = 7;                          \
+   } else if (next == 6) {               \
+      CVMX_MT_HSH_DAT (dat1, 6);         \
+      CVMX_MT_HSH_STARTSHA (dat2);       \
+      next = 0;                          \
+   } else {                              \
+     CVMX_MT_HSH_STARTSHA (dat1);        \
+     CVMX_MT_HSH_DAT (dat2, 0);          \
+     next = 1;                           \
+   }                                     \
+}
+
+/****************************************************************************/
+
+#define CVM_LOAD_MD5_UNIT(dat, next)  { \
+   if (next == 0) {                     \
+      next = 1;                         \
+      CVMX_MT_HSH_DAT (dat, 0);         \
+   } else if (next == 1) {              \
+      next = 2;                         \
+      CVMX_MT_HSH_DAT (dat, 1);         \
+   } else if (next == 2) {              \
+      next = 3;                    \
+      CVMX_MT_HSH_DAT (dat, 2);         \
+   } else if (next == 3) {              \
+      next = 4;                         \
+      CVMX_MT_HSH_DAT (dat, 3);         \
+   } else if (next == 4) {              \
+      next = 5;                           \
+      CVMX_MT_HSH_DAT (dat, 4);         \
+   } else if (next == 5) {              \
+      next = 6;                         \
+      CVMX_MT_HSH_DAT (dat, 5);         \
+   } else if (next == 6) {              \
+      next = 7;                         \
+      CVMX_MT_HSH_DAT (dat, 6);         \
+   } else {                             \
+     CVMX_MT_HSH_STARTMD5 (dat);        \
+     next = 0;                          \
+   }                                    \
+}
+
+#define CVM_LOAD2_MD5_UNIT(dat1, dat2, next)  { \
+   if (next == 0) {                      \
+      CVMX_MT_HSH_DAT (dat1, 0);         \
+      CVMX_MT_HSH_DAT (dat2, 1);         \
+      next = 2;                          \
+   } else if (next == 1) {               \
+      CVMX_MT_HSH_DAT (dat1, 1);         \
+      CVMX_MT_HSH_DAT (dat2, 2);         \
+      next = 3;                          \
+   } else if (next == 2) {               \
+      CVMX_MT_HSH_DAT (dat1, 2);         \
+      CVMX_MT_HSH_DAT (dat2, 3);         \
+      next = 4;                          \
+   } else if (next == 3) {               \
+      CVMX_MT_HSH_DAT (dat1, 3);         \
+      CVMX_MT_HSH_DAT (dat2, 4);         \
+      next = 5;                          \
+   } else if (next == 4) {               \
+      CVMX_MT_HSH_DAT (dat1, 4);         \
+      CVMX_MT_HSH_DAT (dat2, 5);         \
+      next = 6;                          \
+   } else if (next == 5) {               \
+      CVMX_MT_HSH_DAT (dat1, 5);         \
+      CVMX_MT_HSH_DAT (dat2, 6);         \
+      next = 7;                          \
+   } else if (next == 6) {               \
+      CVMX_MT_HSH_DAT (dat1, 6);         \
+      CVMX_MT_HSH_STARTMD5 (dat2);       \
+      next = 0;                          \
+   } else {                              \
+     CVMX_MT_HSH_STARTMD5 (dat1);        \
+     CVMX_MT_HSH_DAT (dat2, 0);          \
+     next = 1;                           \
+   }                                     \
+}
+
+/****************************************************************************/
+
+static inline uint64_t
+swap64(uint64_t a)
+{
+    return ((a >> 56) |
+       (((a >> 48) & 0xfful) << 8) |
+       (((a >> 40) & 0xfful) << 16) |
+       (((a >> 32) & 0xfful) << 24) |
+       (((a >> 24) & 0xfful) << 32) |
+       (((a >> 16) & 0xfful) << 40) |
+       (((a >> 8) & 0xfful) << 48) | (((a >> 0) & 0xfful) << 56));
+}
+
+/****************************************************************************/
+
+void
+octo_calc_hash(__u8 auth, unsigned char *key, uint64_t *inner, uint64_t *outer)
+{
+    uint8_t hash_key[64];
+    uint64_t *key1;
+    register uint64_t xor1 = 0x3636363636363636ULL;
+    register uint64_t xor2 = 0x5c5c5c5c5c5c5c5cULL;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    memset(hash_key, 0, sizeof(hash_key));
+    memcpy(hash_key, (uint8_t *) key, (auth ? 20 : 16));
+    key1 = (uint64_t *) hash_key;
+    flags = octeon_crypto_enable(&state);
+    if (auth) {
+       CVMX_MT_HSH_IV(0x67452301EFCDAB89ULL, 0);
+       CVMX_MT_HSH_IV(0x98BADCFE10325476ULL, 1);
+       CVMX_MT_HSH_IV(0xC3D2E1F000000000ULL, 2);
+    } else {
+       CVMX_MT_HSH_IV(0x0123456789ABCDEFULL, 0);
+       CVMX_MT_HSH_IV(0xFEDCBA9876543210ULL, 1);
+    }
+
+    CVMX_MT_HSH_DAT((*key1 ^ xor1), 0);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor1), 1);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor1), 2);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor1), 3);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor1), 4);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor1), 5);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor1), 6);
+    key1++;
+    if (auth)
+       CVMX_MT_HSH_STARTSHA((*key1 ^ xor1));
+    else
+       CVMX_MT_HSH_STARTMD5((*key1 ^ xor1));
+
+    CVMX_MF_HSH_IV(inner[0], 0);
+    CVMX_MF_HSH_IV(inner[1], 1);
+    if (auth) {
+       inner[2] = 0;
+       CVMX_MF_HSH_IV(((uint64_t *) inner)[2], 2);
+    }
+
+    memset(hash_key, 0, sizeof(hash_key));
+    memcpy(hash_key, (uint8_t *) key, (auth ? 20 : 16));
+    key1 = (uint64_t *) hash_key;
+    if (auth) {
+      CVMX_MT_HSH_IV(0x67452301EFCDAB89ULL, 0);
+      CVMX_MT_HSH_IV(0x98BADCFE10325476ULL, 1);
+      CVMX_MT_HSH_IV(0xC3D2E1F000000000ULL, 2);
+    } else {
+      CVMX_MT_HSH_IV(0x0123456789ABCDEFULL, 0);
+      CVMX_MT_HSH_IV(0xFEDCBA9876543210ULL, 1);
+    }
+
+    CVMX_MT_HSH_DAT((*key1 ^ xor2), 0);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor2), 1);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor2), 2);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor2), 3);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor2), 4);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor2), 5);
+    key1++;
+    CVMX_MT_HSH_DAT((*key1 ^ xor2), 6);
+    key1++;
+    if (auth)
+       CVMX_MT_HSH_STARTSHA((*key1 ^ xor2));
+    else 
+       CVMX_MT_HSH_STARTMD5((*key1 ^ xor2));
+
+    CVMX_MF_HSH_IV(outer[0], 0);
+    CVMX_MF_HSH_IV(outer[1], 1);
+    if (auth) {
+      outer[2] = 0;
+      CVMX_MF_HSH_IV(outer[2], 2);
+    }
+    octeon_crypto_disable(&state, flags);
+    return;
+}
+
+/****************************************************************************/
+/* DES functions */
+
+int
+octo_des_cbc_encrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    uint64_t *data;
+    int data_i, data_l;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x7) || (crypt_off + crypt_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load 3DES Key */
+    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    if (od->octo_encklen == 24) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+    } else if (od->octo_encklen == 8) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+
+    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
+
+    while (crypt_off > 0) {
+       SG_CONSUME(sg, data, data_i, data_l);
+       crypt_off -= 8;
+    }
+
+    while (crypt_len > 0) {
+       CVMX_MT_3DES_ENC_CBC(*data);
+       CVMX_MF_3DES_RESULT(*data);
+       SG_CONSUME(sg, data, data_i, data_l);
+       crypt_len -= 8;
+    }
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+
+int
+octo_des_cbc_decrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    uint64_t *data;
+    int data_i, data_l;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x7) || (crypt_off + crypt_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load 3DES Key */
+    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    if (od->octo_encklen == 24) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+    } else if (od->octo_encklen == 8) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+
+    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
+
+    while (crypt_off > 0) {
+       SG_CONSUME(sg, data, data_i, data_l);
+       crypt_off -= 8;
+    }
+
+    while (crypt_len > 0) {
+       CVMX_MT_3DES_DEC_CBC(*data);
+       CVMX_MF_3DES_RESULT(*data);
+       SG_CONSUME(sg, data, data_i, data_l);
+       crypt_len -= 8;
+    }
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+/****************************************************************************/
+/* AES functions */
+
+int
+octo_aes_cbc_encrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    uint64_t *data, *pdata;
+    int data_i, data_l;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x7) || (crypt_off + crypt_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load AES Key */
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+
+    if (od->octo_encklen == 16) {
+       CVMX_MT_AES_KEY(0x0, 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 24) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 32) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
+
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
+
+    while (crypt_off > 0) {
+       SG_CONSUME(sg, data, data_i, data_l);
+       crypt_off -= 8;
+    }
+
+    while (crypt_len > 0) {
+       pdata = data;
+       CVMX_MT_AES_ENC_CBC0(*data);
+       SG_CONSUME(sg, data, data_i, data_l);
+       CVMX_MT_AES_ENC_CBC1(*data);
+       CVMX_MF_AES_RESULT(*pdata, 0);
+       CVMX_MF_AES_RESULT(*data, 1);
+       SG_CONSUME(sg, data, data_i, data_l);
+       crypt_len -= 16;
+    }
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+
+int
+octo_aes_cbc_decrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    uint64_t *data, *pdata;
+    int data_i, data_l;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x7) || (crypt_off + crypt_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load AES Key */
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+
+    if (od->octo_encklen == 16) {
+       CVMX_MT_AES_KEY(0x0, 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 24) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 32) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
+
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
+
+    while (crypt_off > 0) {
+       SG_CONSUME(sg, data, data_i, data_l);
+       crypt_off -= 8;
+    }
+
+    while (crypt_len > 0) {
+       pdata = data;
+       CVMX_MT_AES_DEC_CBC0(*data);
+       SG_CONSUME(sg, data, data_i, data_l);
+       CVMX_MT_AES_DEC_CBC1(*data);
+       CVMX_MF_AES_RESULT(*pdata, 0);
+       CVMX_MF_AES_RESULT(*data, 1);
+       SG_CONSUME(sg, data, data_i, data_l);
+       crypt_len -= 16;
+    }
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+/****************************************************************************/
+/* MD5 */
+
+int
+octo_null_md5_encrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    register int next = 0;
+    uint64_t *data;
+    uint64_t tmp1, tmp2;
+    int data_i, data_l, alen = auth_len;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 ||
+           (auth_off & 0x7) || (auth_off + auth_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data, data_i, data_l);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* Load MD5 IV */
+    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
+
+    while (auth_off > 0) {
+       SG_CONSUME(sg, data, data_i, data_l);
+       auth_off -= 8;
+    }
+
+    while (auth_len > 0) {
+       CVM_LOAD_MD5_UNIT(*data, next);
+       auth_len -= 8;
+       SG_CONSUME(sg, data, data_i, data_l);
+    }
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_MD5_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* Finish Inner hash */
+    while (next != 7) {
+       CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
+    }
+    CVMX_ES64(tmp1, ((alen + 64) << 3));
+    CVM_LOAD_MD5_UNIT(tmp1, next);
+
+    /* Get the inner hash of HMAC */
+    CVMX_MF_HSH_IV(tmp1, 0);
+    CVMX_MF_HSH_IV(tmp2, 1);
+
+    /* Initialize hash unit */
+    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
+
+    CVMX_MT_HSH_DAT(tmp1, 0);
+    CVMX_MT_HSH_DAT(tmp2, 1);
+    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
+    CVMX_MT_HSH_DATZ(3);
+    CVMX_MT_HSH_DATZ(4);
+    CVMX_MT_HSH_DATZ(5);
+    CVMX_MT_HSH_DATZ(6);
+    CVMX_ES64(tmp1, ((64 + 16) << 3));
+    CVMX_MT_HSH_STARTMD5(tmp1);
+
+    /* save the HMAC */
+    SG_INIT(sg, data, data_i, data_l);
+    while (icv_off > 0) {
+       SG_CONSUME(sg, data, data_i, data_l);
+       icv_off -= 8;
+    }
+    CVMX_MF_HSH_IV(*data, 0);
+    SG_CONSUME(sg, data, data_i, data_l);
+    CVMX_MF_HSH_IV(tmp1, 1);
+    *(uint32_t *)data = (uint32_t) (tmp1 >> 32);
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+/****************************************************************************/
+/* SHA1 */
+
+int
+octo_null_sha1_encrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    register int next = 0;
+    uint64_t *data;
+    uint64_t tmp1, tmp2, tmp3;
+    int data_i, data_l, alen = auth_len;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 ||
+           (auth_off & 0x7) || (auth_off + auth_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data, data_i, data_l);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* Load SHA1 IV */
+    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
+    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
+
+    while (auth_off > 0) {
+       SG_CONSUME(sg, data, data_i, data_l);
+       auth_off -= 8;
+    }
+
+    while (auth_len > 0) {
+       CVM_LOAD_SHA_UNIT(*data, next);
+       auth_len -= 8;
+       SG_CONSUME(sg, data, data_i, data_l);
+    }
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_MD5_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* Finish Inner hash */
+    while (next != 7) {
+       CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
+    }
+    CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
+
+    /* Get the inner hash of HMAC */
+    CVMX_MF_HSH_IV(tmp1, 0);
+    CVMX_MF_HSH_IV(tmp2, 1);
+    tmp3 = 0;
+    CVMX_MF_HSH_IV(tmp3, 2);
+
+    /* Initialize hash unit */
+    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
+    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
+
+    CVMX_MT_HSH_DAT(tmp1, 0);
+    CVMX_MT_HSH_DAT(tmp2, 1);
+    tmp3 |= 0x0000000080000000;
+    CVMX_MT_HSH_DAT(tmp3, 2);
+    CVMX_MT_HSH_DATZ(3);
+    CVMX_MT_HSH_DATZ(4);
+    CVMX_MT_HSH_DATZ(5);
+    CVMX_MT_HSH_DATZ(6);
+    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
+
+    /* save the HMAC */
+    SG_INIT(sg, data, data_i, data_l);
+    while (icv_off > 0) {
+       SG_CONSUME(sg, data, data_i, data_l);
+       icv_off -= 8;
+    }
+    CVMX_MF_HSH_IV(*data, 0);
+    SG_CONSUME(sg, data, data_i, data_l);
+    CVMX_MF_HSH_IV(tmp1, 1);
+    *(uint32_t *)data = (uint32_t) (tmp1 >> 32);
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+/****************************************************************************/
+/* DES MD5 */
+
+int
+octo_des_cbc_md5_encrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    register int next = 0;
+    union {
+       uint32_t data32[2];
+       uint64_t data64[1];
+    } mydata;
+    uint64_t *data = &mydata.data64[0];
+    uint32_t *data32;
+    uint64_t tmp1, tmp2;
+    int data_i, data_l, alen = auth_len;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
+           (crypt_len  & 0x7) ||
+           (auth_len  & 0x7) ||
+           (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data32, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load 3DES Key */
+    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    if (od->octo_encklen == 24) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+    } else if (od->octo_encklen == 8) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+
+    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
+
+    /* Load MD5 IV */
+    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
+
+    while (crypt_off > 0 && auth_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       crypt_off -= 4;
+       auth_off -= 4;
+    }
+
+    while (crypt_len > 0 || auth_len > 0) {
+       uint32_t *first = data32;
+       mydata.data32[0] = *first;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata.data32[1] = *data32;
+       if (crypt_off <= 0) {
+           if (crypt_len > 0) {
+               CVMX_MT_3DES_ENC_CBC(*data);
+               CVMX_MF_3DES_RESULT(*data);
+               crypt_len -= 8;
+           }
+       } else
+           crypt_off -= 8;
+       if (auth_off <= 0) {
+           if (auth_len > 0) {
+               CVM_LOAD_MD5_UNIT(*data, next);
+               auth_len -= 8;
+           }
+       } else
+           auth_off -= 8;
+       *first = mydata.data32[0];
+       *data32 = mydata.data32[1];
+       SG_CONSUME(sg, data32, data_i, data_l);
+    }
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_MD5_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* Finish Inner hash */
+    while (next != 7) {
+       CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
+    }
+    CVMX_ES64(tmp1, ((alen + 64) << 3));
+    CVM_LOAD_MD5_UNIT(tmp1, next);
+
+    /* Get the inner hash of HMAC */
+    CVMX_MF_HSH_IV(tmp1, 0);
+    CVMX_MF_HSH_IV(tmp2, 1);
+
+    /* Initialize hash unit */
+    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
+
+    CVMX_MT_HSH_DAT(tmp1, 0);
+    CVMX_MT_HSH_DAT(tmp2, 1);
+    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
+    CVMX_MT_HSH_DATZ(3);
+    CVMX_MT_HSH_DATZ(4);
+    CVMX_MT_HSH_DATZ(5);
+    CVMX_MT_HSH_DATZ(6);
+    CVMX_ES64(tmp1, ((64 + 16) << 3));
+    CVMX_MT_HSH_STARTMD5(tmp1);
+
+    /* save the HMAC */
+    SG_INIT(sg, data32, data_i, data_l);
+    while (icv_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       icv_off -= 4;
+    }
+    CVMX_MF_HSH_IV(tmp1, 0);
+    *data32 = (uint32_t) (tmp1 >> 32);
+    SG_CONSUME(sg, data32, data_i, data_l);
+    *data32 = (uint32_t) tmp1;
+    SG_CONSUME(sg, data32, data_i, data_l);
+    CVMX_MF_HSH_IV(tmp1, 1);
+    *data32 = (uint32_t) (tmp1 >> 32);
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+int
+octo_des_cbc_md5_decrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    register int next = 0;
+    union {
+       uint32_t data32[2];
+       uint64_t data64[1];
+    } mydata;
+    uint64_t *data = &mydata.data64[0];
+    uint32_t *data32;
+    uint64_t tmp1, tmp2;
+    int data_i, data_l, alen = auth_len;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
+           (crypt_len  & 0x7) ||
+           (auth_len  & 0x7) ||
+           (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data32, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load 3DES Key */
+    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    if (od->octo_encklen == 24) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+    } else if (od->octo_encklen == 8) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+
+    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
+
+    /* Load MD5 IV */
+    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
+
+    while (crypt_off > 0 && auth_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       crypt_off -= 4;
+       auth_off -= 4;
+    }
+
+    while (crypt_len > 0 || auth_len > 0) {
+       uint32_t *first = data32;
+       mydata.data32[0] = *first;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata.data32[1] = *data32;
+       if (auth_off <= 0) {
+           if (auth_len > 0) {
+               CVM_LOAD_MD5_UNIT(*data, next);
+               auth_len -= 8;
+           }
+       } else
+           auth_off -= 8;
+       if (crypt_off <= 0) {
+           if (crypt_len > 0) {
+               CVMX_MT_3DES_DEC_CBC(*data);
+               CVMX_MF_3DES_RESULT(*data);
+               crypt_len -= 8;
+           }
+       } else
+           crypt_off -= 8;
+       *first = mydata.data32[0];
+       *data32 = mydata.data32[1];
+       SG_CONSUME(sg, data32, data_i, data_l);
+    }
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_MD5_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* Finish Inner hash */
+    while (next != 7) {
+       CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
+    }
+    CVMX_ES64(tmp1, ((alen + 64) << 3));
+    CVM_LOAD_MD5_UNIT(tmp1, next);
+
+    /* Get the inner hash of HMAC */
+    CVMX_MF_HSH_IV(tmp1, 0);
+    CVMX_MF_HSH_IV(tmp2, 1);
+
+    /* Initialize hash unit */
+    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
+
+    CVMX_MT_HSH_DAT(tmp1, 0);
+    CVMX_MT_HSH_DAT(tmp2, 1);
+    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
+    CVMX_MT_HSH_DATZ(3);
+    CVMX_MT_HSH_DATZ(4);
+    CVMX_MT_HSH_DATZ(5);
+    CVMX_MT_HSH_DATZ(6);
+    CVMX_ES64(tmp1, ((64 + 16) << 3));
+    CVMX_MT_HSH_STARTMD5(tmp1);
+
+    /* save the HMAC */
+    SG_INIT(sg, data32, data_i, data_l);
+    while (icv_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       icv_off -= 4;
+    }
+    CVMX_MF_HSH_IV(tmp1, 0);
+    *data32 = (uint32_t) (tmp1 >> 32);
+    SG_CONSUME(sg, data32, data_i, data_l);
+    *data32 = (uint32_t) tmp1;
+    SG_CONSUME(sg, data32, data_i, data_l);
+    CVMX_MF_HSH_IV(tmp1, 1);
+    *data32 = (uint32_t) (tmp1 >> 32);
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+/****************************************************************************/
+/* DES SHA */
+
+int
+octo_des_cbc_sha1_encrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    register int next = 0;
+    union {
+       uint32_t data32[2];
+       uint64_t data64[1];
+    } mydata;
+    uint64_t *data = &mydata.data64[0];
+    uint32_t *data32;
+    uint64_t tmp1, tmp2, tmp3;
+    int data_i, data_l, alen = auth_len;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
+           (crypt_len  & 0x7) ||
+           (auth_len  & 0x7) ||
+           (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data32, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load 3DES Key */
+    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    if (od->octo_encklen == 24) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+    } else if (od->octo_encklen == 8) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+
+    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
+
+    /* Load SHA1 IV */
+    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
+    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
+
+    while (crypt_off > 0 && auth_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       crypt_off -= 4;
+       auth_off -= 4;
+    }
+
+    while (crypt_len > 0 || auth_len > 0) {
+       uint32_t *first = data32;
+       mydata.data32[0] = *first;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata.data32[1] = *data32;
+       if (crypt_off <= 0) {
+           if (crypt_len > 0) {
+               CVMX_MT_3DES_ENC_CBC(*data);
+               CVMX_MF_3DES_RESULT(*data);
+               crypt_len -= 8;
+           }
+       } else
+           crypt_off -= 8;
+       if (auth_off <= 0) {
+           if (auth_len > 0) {
+               CVM_LOAD_SHA_UNIT(*data, next);
+               auth_len -= 8;
+           }
+       } else
+           auth_off -= 8;
+       *first = mydata.data32[0];
+       *data32 = mydata.data32[1];
+       SG_CONSUME(sg, data32, data_i, data_l);
+    }
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_SHA_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* Finish Inner hash */
+    while (next != 7) {
+       CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
+    }
+       CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
+
+    /* Get the inner hash of HMAC */
+    CVMX_MF_HSH_IV(tmp1, 0);
+    CVMX_MF_HSH_IV(tmp2, 1);
+    tmp3 = 0;
+    CVMX_MF_HSH_IV(tmp3, 2);
+
+    /* Initialize hash unit */
+    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
+    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
+
+    CVMX_MT_HSH_DAT(tmp1, 0);
+    CVMX_MT_HSH_DAT(tmp2, 1);
+    tmp3 |= 0x0000000080000000;
+    CVMX_MT_HSH_DAT(tmp3, 2);
+    CVMX_MT_HSH_DATZ(3);
+    CVMX_MT_HSH_DATZ(4);
+    CVMX_MT_HSH_DATZ(5);
+    CVMX_MT_HSH_DATZ(6);
+    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
+
+    /* save the HMAC */
+    SG_INIT(sg, data32, data_i, data_l);
+    while (icv_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       icv_off -= 4;
+    }
+    CVMX_MF_HSH_IV(tmp1, 0);
+    *data32 = (uint32_t) (tmp1 >> 32);
+    SG_CONSUME(sg, data32, data_i, data_l);
+    *data32 = (uint32_t) tmp1;
+    SG_CONSUME(sg, data32, data_i, data_l);
+    CVMX_MF_HSH_IV(tmp1, 1);
+    *data32 = (uint32_t) (tmp1 >> 32);
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+int
+octo_des_cbc_sha1_decrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    register int next = 0;
+    union {
+       uint32_t data32[2];
+       uint64_t data64[1];
+    } mydata;
+    uint64_t *data = &mydata.data64[0];
+    uint32_t *data32;
+    uint64_t tmp1, tmp2, tmp3;
+    int data_i, data_l, alen = auth_len;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
+           (crypt_len  & 0x7) ||
+           (auth_len  & 0x7) ||
+           (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data32, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load 3DES Key */
+    CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    if (od->octo_encklen == 24) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+    } else if (od->octo_encklen == 8) {
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 1);
+       CVMX_MT_3DES_KEY(((uint64_t *) od->octo_enckey)[0], 2);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+
+    CVMX_MT_3DES_IV(* (uint64_t *) ivp);
+
+    /* Load SHA1 IV */
+    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
+    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
+
+    while (crypt_off > 0 && auth_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       crypt_off -= 4;
+       auth_off -= 4;
+    }
+
+    while (crypt_len > 0 || auth_len > 0) {
+       uint32_t *first = data32;
+       mydata.data32[0] = *first;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata.data32[1] = *data32;
+       if (auth_off <= 0) {
+           if (auth_len > 0) {
+               CVM_LOAD_SHA_UNIT(*data, next);
+               auth_len -= 8;
+           }
+       } else
+           auth_off -= 8;
+       if (crypt_off <= 0) {
+           if (crypt_len > 0) {
+               CVMX_MT_3DES_DEC_CBC(*data);
+               CVMX_MF_3DES_RESULT(*data);
+               crypt_len -= 8;
+           }
+       } else
+           crypt_off -= 8;
+       *first = mydata.data32[0];
+       *data32 = mydata.data32[1];
+       SG_CONSUME(sg, data32, data_i, data_l);
+    }
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_SHA_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* Finish Inner hash */
+    while (next != 7) {
+       CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
+    }
+    CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
+
+    /* Get the inner hash of HMAC */
+    CVMX_MF_HSH_IV(tmp1, 0);
+    CVMX_MF_HSH_IV(tmp2, 1);
+    tmp3 = 0;
+    CVMX_MF_HSH_IV(tmp3, 2);
+
+    /* Initialize hash unit */
+    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
+    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
+
+    CVMX_MT_HSH_DAT(tmp1, 0);
+    CVMX_MT_HSH_DAT(tmp2, 1);
+    tmp3 |= 0x0000000080000000;
+    CVMX_MT_HSH_DAT(tmp3, 2);
+    CVMX_MT_HSH_DATZ(3);
+    CVMX_MT_HSH_DATZ(4);
+    CVMX_MT_HSH_DATZ(5);
+    CVMX_MT_HSH_DATZ(6);
+    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
+    /* save the HMAC */
+    SG_INIT(sg, data32, data_i, data_l);
+    while (icv_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       icv_off -= 4;
+    }
+    CVMX_MF_HSH_IV(tmp1, 0);
+    *data32 = (uint32_t) (tmp1 >> 32);
+    SG_CONSUME(sg, data32, data_i, data_l);
+    *data32 = (uint32_t) tmp1;
+    SG_CONSUME(sg, data32, data_i, data_l);
+    CVMX_MF_HSH_IV(tmp1, 1);
+    *data32 = (uint32_t) (tmp1 >> 32);
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+/****************************************************************************/
+/* AES MD5 */
+
+int
+octo_aes_cbc_md5_encrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    register int next = 0;
+    union {
+       uint32_t data32[2];
+       uint64_t data64[1];
+    } mydata[2];
+    uint64_t *pdata = &mydata[0].data64[0];
+    uint64_t *data =  &mydata[1].data64[0];
+    uint32_t *data32;
+    uint64_t tmp1, tmp2;
+    int data_i, data_l, alen = auth_len;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
+           (crypt_len  & 0x7) ||
+           (auth_len  & 0x7) ||
+           (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data32, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load AES Key */
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+
+    if (od->octo_encklen == 16) {
+       CVMX_MT_AES_KEY(0x0, 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 24) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 32) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
+
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
+
+    /* Load MD5 IV */
+    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
+
+    while (crypt_off > 0 && auth_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       crypt_off -= 4;
+       auth_off -= 4;
+    }
+
+    /* align auth and crypt */
+    while (crypt_off > 0 && auth_len > 0) {
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       CVM_LOAD_MD5_UNIT(*pdata, next);
+       crypt_off -= 8;
+       auth_len -= 8;
+    }
+
+    while (crypt_len > 0) {
+       uint32_t *pdata32[3];
+
+       pdata32[0] = data32;
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+
+       pdata32[1] = data32;
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+
+       pdata32[2] = data32;
+       mydata[1].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+
+       mydata[1].data32[1] = *data32;
+
+       CVMX_MT_AES_ENC_CBC0(*pdata);
+       CVMX_MT_AES_ENC_CBC1(*data);
+       CVMX_MF_AES_RESULT(*pdata, 0);
+       CVMX_MF_AES_RESULT(*data, 1);
+       crypt_len -= 16;
+
+       if (auth_len > 0) {
+           CVM_LOAD_MD5_UNIT(*pdata, next);
+           auth_len -= 8;
+       }
+       if (auth_len > 0) {
+           CVM_LOAD_MD5_UNIT(*data, next);
+           auth_len -= 8;
+       }
+
+       *pdata32[0] = mydata[0].data32[0];
+       *pdata32[1] = mydata[0].data32[1];
+       *pdata32[2] = mydata[1].data32[0];
+       *data32     = mydata[1].data32[1];
+
+       SG_CONSUME(sg, data32, data_i, data_l);
+    }
+
+    /* finish any left over hashing */
+    while (auth_len > 0) {
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       CVM_LOAD_MD5_UNIT(*pdata, next);
+       auth_len -= 8;
+    }
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_MD5_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* Finish Inner hash */
+    while (next != 7) {
+       CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
+    }
+    CVMX_ES64(tmp1, ((alen + 64) << 3));
+    CVM_LOAD_MD5_UNIT(tmp1, next);
+
+    /* Get the inner hash of HMAC */
+    CVMX_MF_HSH_IV(tmp1, 0);
+    CVMX_MF_HSH_IV(tmp2, 1);
+
+    /* Initialize hash unit */
+    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
+
+    CVMX_MT_HSH_DAT(tmp1, 0);
+    CVMX_MT_HSH_DAT(tmp2, 1);
+    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
+    CVMX_MT_HSH_DATZ(3);
+    CVMX_MT_HSH_DATZ(4);
+    CVMX_MT_HSH_DATZ(5);
+    CVMX_MT_HSH_DATZ(6);
+    CVMX_ES64(tmp1, ((64 + 16) << 3));
+    CVMX_MT_HSH_STARTMD5(tmp1);
+
+    /* save the HMAC */
+    SG_INIT(sg, data32, data_i, data_l);
+    while (icv_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       icv_off -= 4;
+    }
+    CVMX_MF_HSH_IV(tmp1, 0);
+    *data32 = (uint32_t) (tmp1 >> 32);
+    SG_CONSUME(sg, data32, data_i, data_l);
+    *data32 = (uint32_t) tmp1;
+    SG_CONSUME(sg, data32, data_i, data_l);
+    CVMX_MF_HSH_IV(tmp1, 1);
+    *data32 = (uint32_t) (tmp1 >> 32);
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+int
+octo_aes_cbc_md5_decrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    register int next = 0;
+    union {
+       uint32_t data32[2];
+       uint64_t data64[1];
+    } mydata[2];
+    uint64_t *pdata = &mydata[0].data64[0];
+    uint64_t *data =  &mydata[1].data64[0];
+    uint32_t *data32;
+    uint64_t tmp1, tmp2;
+    int data_i, data_l, alen = auth_len;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s()\n", __FUNCTION__);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
+           (crypt_len  & 0x7) ||
+           (auth_len  & 0x7) ||
+           (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data32, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load AES Key */
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+
+    if (od->octo_encklen == 16) {
+       CVMX_MT_AES_KEY(0x0, 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 24) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 32) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
+
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
+
+    /* Load MD5 IV */
+    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
+
+    while (crypt_off > 0 && auth_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       crypt_off -= 4;
+       auth_off -= 4;
+    }
+
+    /* align auth and crypt */
+    while (crypt_off > 0 && auth_len > 0) {
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       CVM_LOAD_MD5_UNIT(*pdata, next);
+       crypt_off -= 8;
+       auth_len -= 8;
+    }
+
+    while (crypt_len > 0) {
+       uint32_t *pdata32[3];
+
+       pdata32[0] = data32;
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       pdata32[1] = data32;
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       pdata32[2] = data32;
+       mydata[1].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata[1].data32[1] = *data32;
+
+       if (auth_len > 0) {
+           CVM_LOAD_MD5_UNIT(*pdata, next);
+           auth_len -= 8;
+       }
+
+       if (auth_len > 0) {
+           CVM_LOAD_MD5_UNIT(*data, next);
+           auth_len -= 8;
+       }
+
+       CVMX_MT_AES_DEC_CBC0(*pdata);
+       CVMX_MT_AES_DEC_CBC1(*data);
+       CVMX_MF_AES_RESULT(*pdata, 0);
+       CVMX_MF_AES_RESULT(*data, 1);
+       crypt_len -= 16;
+
+       *pdata32[0] = mydata[0].data32[0];
+       *pdata32[1] = mydata[0].data32[1];
+       *pdata32[2] = mydata[1].data32[0];
+       *data32     = mydata[1].data32[1];
+
+       SG_CONSUME(sg, data32, data_i, data_l);
+    }
+
+    /* finish left over hash if any */
+    while (auth_len > 0) {
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       CVM_LOAD_MD5_UNIT(*pdata, next);
+       auth_len -= 8;
+    }
+
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_MD5_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* Finish Inner hash */
+    while (next != 7) {
+       CVM_LOAD_MD5_UNIT(((uint64_t) 0x0ULL), next);
+    }
+    CVMX_ES64(tmp1, ((alen + 64) << 3));
+    CVM_LOAD_MD5_UNIT(tmp1, next);
+
+    /* Get the inner hash of HMAC */
+    CVMX_MF_HSH_IV(tmp1, 0);
+    CVMX_MF_HSH_IV(tmp2, 1);
+
+    /* Initialize hash unit */
+    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
+
+    CVMX_MT_HSH_DAT(tmp1, 0);
+    CVMX_MT_HSH_DAT(tmp2, 1);
+    CVMX_MT_HSH_DAT(0x8000000000000000ULL, 2);
+    CVMX_MT_HSH_DATZ(3);
+    CVMX_MT_HSH_DATZ(4);
+    CVMX_MT_HSH_DATZ(5);
+    CVMX_MT_HSH_DATZ(6);
+    CVMX_ES64(tmp1, ((64 + 16) << 3));
+    CVMX_MT_HSH_STARTMD5(tmp1);
+
+    /* save the HMAC */
+    SG_INIT(sg, data32, data_i, data_l);
+    while (icv_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       icv_off -= 4;
+    }
+    CVMX_MF_HSH_IV(tmp1, 0);
+    *data32 = (uint32_t) (tmp1 >> 32);
+    SG_CONSUME(sg, data32, data_i, data_l);
+    *data32 = (uint32_t) tmp1;
+    SG_CONSUME(sg, data32, data_i, data_l);
+    CVMX_MF_HSH_IV(tmp1, 1);
+    *data32 = (uint32_t) (tmp1 >> 32);
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+/****************************************************************************/
+/* AES SHA1 */
+
+int
+octo_aes_cbc_sha1_encrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    register int next = 0;
+    union {
+       uint32_t data32[2];
+       uint64_t data64[1];
+    } mydata[2];
+    uint64_t *pdata = &mydata[0].data64[0];
+    uint64_t *data =  &mydata[1].data64[0];
+    uint32_t *data32;
+    uint64_t tmp1, tmp2, tmp3;
+    int data_i, data_l, alen = auth_len;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s(a_off=%d a_len=%d c_off=%d c_len=%d icv_off=%d)\n",
+                       __FUNCTION__, auth_off, auth_len, crypt_off, crypt_len, icv_off);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
+           (crypt_len  & 0x7) ||
+           (auth_len  & 0x7) ||
+           (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data32, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load AES Key */
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+
+    if (od->octo_encklen == 16) {
+       CVMX_MT_AES_KEY(0x0, 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 24) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 32) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
+
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
+
+    /* Load SHA IV */
+    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
+    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
+
+    while (crypt_off > 0 && auth_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       crypt_off -= 4;
+       auth_off -= 4;
+    }
+
+    /* align auth and crypt */
+    while (crypt_off > 0 && auth_len > 0) {
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       CVM_LOAD_SHA_UNIT(*pdata, next);
+       crypt_off -= 8;
+       auth_len -= 8;
+    }
+
+    while (crypt_len > 0) {
+       uint32_t *pdata32[3];
+
+       pdata32[0] = data32;
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       pdata32[1] = data32;
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       pdata32[2] = data32;
+       mydata[1].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata[1].data32[1] = *data32;
+
+       CVMX_MT_AES_ENC_CBC0(*pdata);
+       CVMX_MT_AES_ENC_CBC1(*data);
+       CVMX_MF_AES_RESULT(*pdata, 0);
+       CVMX_MF_AES_RESULT(*data, 1);
+       crypt_len -= 16;
+
+       if (auth_len > 0) {
+           CVM_LOAD_SHA_UNIT(*pdata, next);
+           auth_len -= 8;
+       }
+       if (auth_len > 0) {
+           CVM_LOAD_SHA_UNIT(*data, next);
+           auth_len -= 8;
+       }
+
+       *pdata32[0] = mydata[0].data32[0];
+       *pdata32[1] = mydata[0].data32[1];
+       *pdata32[2] = mydata[1].data32[0];
+       *data32     = mydata[1].data32[1];
+
+       SG_CONSUME(sg, data32, data_i, data_l);
+    }
+
+    /* finish and hashing */
+    while (auth_len > 0) {
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       CVM_LOAD_SHA_UNIT(*pdata, next);
+       auth_len -= 8;
+    }
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_SHA_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* Finish Inner hash */
+    while (next != 7) {
+       CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
+    }
+    CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
+
+    /* Get the inner hash of HMAC */
+    CVMX_MF_HSH_IV(tmp1, 0);
+    CVMX_MF_HSH_IV(tmp2, 1);
+    tmp3 = 0;
+    CVMX_MF_HSH_IV(tmp3, 2);
+
+    /* Initialize hash unit */
+    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
+    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
+
+    CVMX_MT_HSH_DAT(tmp1, 0);
+    CVMX_MT_HSH_DAT(tmp2, 1);
+    tmp3 |= 0x0000000080000000;
+    CVMX_MT_HSH_DAT(tmp3, 2);
+    CVMX_MT_HSH_DATZ(3);
+    CVMX_MT_HSH_DATZ(4);
+    CVMX_MT_HSH_DATZ(5);
+    CVMX_MT_HSH_DATZ(6);
+    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_MD5_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* save the HMAC */
+    SG_INIT(sg, data32, data_i, data_l);
+    while (icv_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       icv_off -= 4;
+    }
+    CVMX_MF_HSH_IV(tmp1, 0);
+    *data32 = (uint32_t) (tmp1 >> 32);
+    SG_CONSUME(sg, data32, data_i, data_l);
+    *data32 = (uint32_t) tmp1;
+    SG_CONSUME(sg, data32, data_i, data_l);
+    CVMX_MF_HSH_IV(tmp1, 1);
+    *data32 = (uint32_t) (tmp1 >> 32);
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+int
+octo_aes_cbc_sha1_decrypt(
+    struct octo_sess *od,
+    struct scatterlist *sg, int sg_len,
+    int auth_off, int auth_len,
+    int crypt_off, int crypt_len,
+    int icv_off, uint8_t *ivp)
+{
+    register int next = 0;
+    union {
+       uint32_t data32[2];
+       uint64_t data64[1];
+    } mydata[2];
+    uint64_t *pdata = &mydata[0].data64[0];
+    uint64_t *data =  &mydata[1].data64[0];
+    uint32_t *data32;
+    uint64_t tmp1, tmp2, tmp3;
+    int data_i, data_l, alen = auth_len;
+    struct octeon_cop2_state state;
+    unsigned long flags;
+
+    dprintk("%s(a_off=%d a_len=%d c_off=%d c_len=%d icv_off=%d)\n",
+                       __FUNCTION__, auth_off, auth_len, crypt_off, crypt_len, icv_off);
+
+    if (unlikely(od == NULL || sg==NULL || sg_len==0 || ivp==NULL ||
+           (crypt_off & 0x3) || (crypt_off + crypt_len > sg_len) ||
+           (crypt_len  & 0x7) ||
+           (auth_len  & 0x7) ||
+           (auth_off & 0x3) || (auth_off + auth_len > sg_len))) {
+       dprintk("%s: Bad parameters od=%p sg=%p sg_len=%d "
+               "auth_off=%d auth_len=%d crypt_off=%d crypt_len=%d "
+               "icv_off=%d ivp=%p\n", __FUNCTION__, od, sg, sg_len,
+               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       return -EINVAL;
+    }
+
+    SG_INIT(sg, data32, data_i, data_l);
+
+    CVMX_PREFETCH0(ivp);
+    CVMX_PREFETCH0(od->octo_enckey);
+
+    flags = octeon_crypto_enable(&state);
+
+    /* load AES Key */
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[0], 0);
+    CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[1], 1);
+
+    if (od->octo_encklen == 16) {
+       CVMX_MT_AES_KEY(0x0, 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 24) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(0x0, 3);
+    } else if (od->octo_encklen == 32) {
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[2], 2);
+       CVMX_MT_AES_KEY(((uint64_t *) od->octo_enckey)[3], 3);
+    } else {
+       octeon_crypto_disable(&state, flags);
+       dprintk("%s: Bad key length %d\n", __FUNCTION__, od->octo_encklen);
+       return -EINVAL;
+    }
+    CVMX_MT_AES_KEYLENGTH(od->octo_encklen / 8 - 1);
+
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[0], 0);
+    CVMX_MT_AES_IV(((uint64_t *) ivp)[1], 1);
+
+    /* Load SHA1 IV */
+    CVMX_MT_HSH_IV(od->octo_hminner[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hminner[1], 1);
+    CVMX_MT_HSH_IV(od->octo_hminner[2], 2);
+
+    while (crypt_off > 0 && auth_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       crypt_off -= 4;
+       auth_off -= 4;
+    }
+
+    /* align auth and crypt */
+    while (crypt_off > 0 && auth_len > 0) {
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       CVM_LOAD_SHA_UNIT(*pdata, next);
+       crypt_off -= 8;
+       auth_len -= 8;
+    }
+
+    while (crypt_len > 0) {
+       uint32_t *pdata32[3];
+
+       pdata32[0] = data32;
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       pdata32[1] = data32;
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       pdata32[2] = data32;
+       mydata[1].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata[1].data32[1] = *data32;
+
+       if (auth_len > 0) {
+           CVM_LOAD_SHA_UNIT(*pdata, next);
+           auth_len -= 8;
+       }
+       if (auth_len > 0) {
+           CVM_LOAD_SHA_UNIT(*data, next);
+           auth_len -= 8;
+       }
+
+       CVMX_MT_AES_DEC_CBC0(*pdata);
+       CVMX_MT_AES_DEC_CBC1(*data);
+       CVMX_MF_AES_RESULT(*pdata, 0);
+       CVMX_MF_AES_RESULT(*data, 1);
+       crypt_len -= 16;
+
+       *pdata32[0] = mydata[0].data32[0];
+       *pdata32[1] = mydata[0].data32[1];
+       *pdata32[2] = mydata[1].data32[0];
+       *data32     = mydata[1].data32[1];
+
+       SG_CONSUME(sg, data32, data_i, data_l);
+    }
+
+    /* finish and leftover hashing */
+    while (auth_len > 0) {
+       mydata[0].data32[0] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       mydata[0].data32[1] = *data32;
+       SG_CONSUME(sg, data32, data_i, data_l);
+       CVM_LOAD_SHA_UNIT(*pdata, next);
+       auth_len -= 8;
+    }
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_SHA_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_SHA_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* Finish Inner hash */
+    while (next != 7) {
+       CVM_LOAD_SHA_UNIT(((uint64_t) 0x0ULL), next);
+    }
+       CVM_LOAD_SHA_UNIT((uint64_t) ((alen + 64) << 3), next);
+
+    /* Get the inner hash of HMAC */
+    CVMX_MF_HSH_IV(tmp1, 0);
+    CVMX_MF_HSH_IV(tmp2, 1);
+    tmp3 = 0;
+    CVMX_MF_HSH_IV(tmp3, 2);
+
+    /* Initialize hash unit */
+    CVMX_MT_HSH_IV(od->octo_hmouter[0], 0);
+    CVMX_MT_HSH_IV(od->octo_hmouter[1], 1);
+    CVMX_MT_HSH_IV(od->octo_hmouter[2], 2);
+
+    CVMX_MT_HSH_DAT(tmp1, 0);
+    CVMX_MT_HSH_DAT(tmp2, 1);
+    tmp3 |= 0x0000000080000000;
+    CVMX_MT_HSH_DAT(tmp3, 2);
+    CVMX_MT_HSH_DATZ(3);
+    CVMX_MT_HSH_DATZ(4);
+    CVMX_MT_HSH_DATZ(5);
+    CVMX_MT_HSH_DATZ(6);
+    CVMX_MT_HSH_STARTSHA((uint64_t) ((64 + 20) << 3));
+
+    /* finish the hash */
+    CVMX_PREFETCH0(od->octo_hmouter);
+#if 0
+    if (unlikely(inplen)) {
+       uint64_t tmp = 0;
+       uint8_t *p = (uint8_t *) & tmp;
+       p[inplen] = 0x80;
+       do {
+           inplen--;
+           p[inplen] = ((uint8_t *) data)[inplen];
+       } while (inplen);
+       CVM_LOAD_MD5_UNIT(tmp, next);
+    } else {
+       CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+    }
+#else
+    CVM_LOAD_MD5_UNIT(0x8000000000000000ULL, next);
+#endif
+
+    /* save the HMAC */
+    SG_INIT(sg, data32, data_i, data_l);
+    while (icv_off > 0) {
+       SG_CONSUME(sg, data32, data_i, data_l);
+       icv_off -= 4;
+    }
+    CVMX_MF_HSH_IV(tmp1, 0);
+    *data32 = (uint32_t) (tmp1 >> 32);
+    SG_CONSUME(sg, data32, data_i, data_l);
+    *data32 = (uint32_t) tmp1;
+    SG_CONSUME(sg, data32, data_i, data_l);
+    CVMX_MF_HSH_IV(tmp1, 1);
+    *data32 = (uint32_t) (tmp1 >> 32);
+
+    octeon_crypto_disable(&state, flags);
+    return 0;
+}
+
+/****************************************************************************/
diff --git a/target/linux/generic-2.6/files/crypto/ocf/cryptocteon/cryptocteon.c b/target/linux/generic-2.6/files/crypto/ocf/cryptocteon/cryptocteon.c
new file mode 100644 (file)
index 0000000..9940f59
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+ * Octeon Crypto for OCF
+ *
+ * Written by David McCullough <david_mccullough@mcafee.com>
+ * Copyright (C) 2009-2010 David McCullough
+ *
+ * LICENSE TERMS
+ *
+ * The free distribution and use of this software in both source and binary
+ * form is allowed (with or without changes) provided that:
+ *
+ *   1. distributions of this source code include the above copyright
+ *      notice, this list of conditions and the following disclaimer;
+ *
+ *   2. distributions in binary form include the above copyright
+ *      notice, this list of conditions and the following disclaimer
+ *      in the documentation and/or other associated materials;
+ *
+ *   3. the copyright holder's name is not used to endorse products
+ *      built using this software without specific written permission.
+ *
+ * DISCLAIMER
+ *
+ * This software is provided 'as is' with no explicit or implied warranties
+ * in respect of its properties, including, but not limited to, correctness
+ * and/or fitness for purpose.
+ * ---------------------------------------------------------------------------
+ */
+
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/crypto.h>
+#include <linux/mm.h>
+#include <linux/skbuff.h>
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+
+#include <cryptodev.h>
+#include <uio.h>
+
+struct {
+       softc_device_decl       sc_dev;
+} octo_softc;
+
+#define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
+
+struct octo_sess {
+       int                                      octo_encalg;
+       #define MAX_CIPHER_KEYLEN       64
+       char                             octo_enckey[MAX_CIPHER_KEYLEN];
+       int                                      octo_encklen;
+
+       int                                      octo_macalg;
+       #define MAX_HASH_KEYLEN 64
+       char                             octo_mackey[MAX_HASH_KEYLEN];
+       int                                      octo_macklen;
+       int                                      octo_mackey_set;
+
+       int                                      octo_mlen;
+       int                                      octo_ivsize;
+
+#if 0
+       int                                     (*octo_decrypt)(struct scatterlist *sg, int sg_len,
+                                                       uint8_t *key, int key_len, uint8_t * iv,
+                                                       uint64_t *hminner, uint64_t *hmouter);
+
+       int                                     (*octo_encrypt)(struct scatterlist *sg, int sg_len,
+                                                       uint8_t *key, int key_len, uint8_t * iv,
+                                                       uint64_t *hminner, uint64_t *hmouter);
+#else
+       int                                     (*octo_encrypt)(struct octo_sess *od,
+                             struct scatterlist *sg, int sg_len,
+                                                 int auth_off, int auth_len,
+                                                 int crypt_off, int crypt_len,
+                                                 int icv_off, uint8_t *ivp);
+       int                                     (*octo_decrypt)(struct octo_sess *od,
+                             struct scatterlist *sg, int sg_len,
+                                                 int auth_off, int auth_len,
+                                                 int crypt_off, int crypt_len,
+                                                 int icv_off, uint8_t *ivp);
+#endif
+
+       uint64_t                         octo_hminner[3];
+       uint64_t                         octo_hmouter[3];
+};
+
+int32_t octo_id = -1;
+module_param(octo_id, int, 0444);
+MODULE_PARM_DESC(octo_id, "Read-Only OCF ID for cryptocteon driver");
+
+static struct octo_sess **octo_sessions = NULL;
+static u_int32_t octo_sesnum = 0;
+
+static int octo_process(device_t, struct cryptop *, int);
+static int octo_newsession(device_t, u_int32_t *, struct cryptoini *);
+static int octo_freesession(device_t, u_int64_t);
+
+static device_method_t octo_methods = {
+       /* crypto device methods */
+       DEVMETHOD(cryptodev_newsession, octo_newsession),
+       DEVMETHOD(cryptodev_freesession,octo_freesession),
+       DEVMETHOD(cryptodev_process,    octo_process),
+};
+
+#define debug octo_debug
+int octo_debug = 0;
+module_param(octo_debug, int, 0644);
+MODULE_PARM_DESC(octo_debug, "Enable debug");
+
+
+#include "cavium_crypto.c"
+
+
+/*
+ * Generate a new octo session.  We artifically limit it to a single
+ * hash/cipher or hash-cipher combo just to make it easier, most callers
+ * do not expect more than this anyway.
+ */
+static int
+octo_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
+{
+       struct cryptoini *c, *encini = NULL, *macini = NULL;
+       struct octo_sess **ocd;
+       int i;
+
+       dprintk("%s()\n", __FUNCTION__);
+       if (sid == NULL || cri == NULL) {
+               dprintk("%s,%d - EINVAL\n", __FILE__, __LINE__);
+               return EINVAL;
+       }
+
+       /*
+        * To keep it simple, we only handle hash, cipher or hash/cipher in a
+        * session,  you cannot currently do multiple ciphers/hashes in one
+        * session even though it would be possibel to code this driver to
+        * handle it.
+        */
+       for (i = 0, c = cri; c && i < 2; i++) {
+               if (c->cri_alg == CRYPTO_MD5_HMAC ||
+                               c->cri_alg == CRYPTO_SHA1_HMAC ||
+                               c->cri_alg == CRYPTO_NULL_HMAC) {
+                       if (macini) {
+                               break;
+                       }
+                       macini = c;
+               }
+               if (c->cri_alg == CRYPTO_DES_CBC ||
+                               c->cri_alg == CRYPTO_3DES_CBC ||
+                               c->cri_alg == CRYPTO_AES_CBC ||
+                               c->cri_alg == CRYPTO_NULL_CBC) {
+                       if (encini) {
+                               break;
+                       }
+                       encini = c;
+               }
+               c = c->cri_next;
+       }
+       if (!macini && !encini) {
+               dprintk("%s,%d - EINVAL bad cipher/hash or combination\n",
+                               __FILE__, __LINE__);
+               return EINVAL;
+       }
+       if (c) {
+               dprintk("%s,%d - EINVAL cannot handle chained cipher/hash combos\n",
+                               __FILE__, __LINE__);
+               return EINVAL;
+       }
+
+       /*
+        * So we have something we can do, lets setup the session
+        */
+
+       if (octo_sessions) {
+               for (i = 1; i < octo_sesnum; i++)
+                       if (octo_sessions[i] == NULL)
+                               break;
+       } else
+               i = 1;          /* NB: to silence compiler warning */
+
+       if (octo_sessions == NULL || i == octo_sesnum) {
+               if (octo_sessions == NULL) {
+                       i = 1; /* We leave octo_sessions[0] empty */
+                       octo_sesnum = CRYPTO_SW_SESSIONS;
+               } else
+                       octo_sesnum *= 2;
+
+               ocd = kmalloc(octo_sesnum * sizeof(struct octo_sess *), SLAB_ATOMIC);
+               if (ocd == NULL) {
+                       /* Reset session number */
+                       if (octo_sesnum == CRYPTO_SW_SESSIONS)
+                               octo_sesnum = 0;
+                       else
+                               octo_sesnum /= 2;
+                       dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
+                       return ENOBUFS;
+               }
+               memset(ocd, 0, octo_sesnum * sizeof(struct octo_sess *));
+
+               /* Copy existing sessions */
+               if (octo_sessions) {
+                       memcpy(ocd, octo_sessions,
+                           (octo_sesnum / 2) * sizeof(struct octo_sess *));
+                       kfree(octo_sessions);
+               }
+
+               octo_sessions = ocd;
+       }
+
+       ocd = &octo_sessions[i];
+       *sid = i;
+
+
+       *ocd = (struct octo_sess *) kmalloc(sizeof(struct octo_sess), SLAB_ATOMIC);
+       if (*ocd == NULL) {
+               octo_freesession(NULL, i);
+               dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
+               return ENOBUFS;
+       }
+       memset(*ocd, 0, sizeof(struct octo_sess));
+
+       if (encini && encini->cri_key) {
+               (*ocd)->octo_encklen = (encini->cri_klen + 7) / 8;
+               memcpy((*ocd)->octo_enckey, encini->cri_key, (*ocd)->octo_encklen);
+       }
+
+       if (macini && macini->cri_key) {
+               (*ocd)->octo_macklen = (macini->cri_klen + 7) / 8;
+               memcpy((*ocd)->octo_mackey, macini->cri_key, (*ocd)->octo_macklen);
+       }
+
+       (*ocd)->octo_mlen = 0;
+       if (encini && encini->cri_mlen)
+               (*ocd)->octo_mlen = encini->cri_mlen;
+       else if (macini && macini->cri_mlen)
+               (*ocd)->octo_mlen = macini->cri_mlen;
+       else
+               (*ocd)->octo_mlen = 12;
+
+       /*
+        * point c at the enc if it exists, otherwise the mac
+        */
+       c = encini ? encini : macini;
+
+       switch (c->cri_alg) {
+       case CRYPTO_DES_CBC:
+       case CRYPTO_3DES_CBC:
+               (*ocd)->octo_ivsize  = 8;
+               switch (macini ? macini->cri_alg : -1) {
+               case CRYPTO_MD5_HMAC:
+                       (*ocd)->octo_encrypt = octo_des_cbc_md5_encrypt;
+                       (*ocd)->octo_decrypt = octo_des_cbc_md5_decrypt;
+                       octo_calc_hash(0, macini->cri_key, (*ocd)->octo_hminner,
+                                       (*ocd)->octo_hmouter);
+                       break;
+               case CRYPTO_SHA1_HMAC:
+                       (*ocd)->octo_encrypt = octo_des_cbc_sha1_encrypt;
+                       (*ocd)->octo_decrypt = octo_des_cbc_sha1_encrypt;
+                       octo_calc_hash(1, macini->cri_key, (*ocd)->octo_hminner,
+                                       (*ocd)->octo_hmouter);
+                       break;
+               case -1:
+                       (*ocd)->octo_encrypt = octo_des_cbc_encrypt;
+                       (*ocd)->octo_decrypt = octo_des_cbc_decrypt;
+                       break;
+               default:
+                       octo_freesession(NULL, i);
+                       dprintk("%s,%d: EINVALn", __FILE__, __LINE__);
+                       return EINVAL;
+               }
+               break;
+       case CRYPTO_AES_CBC:
+               (*ocd)->octo_ivsize  = 16;
+               switch (macini ? macini->cri_alg : -1) {
+               case CRYPTO_MD5_HMAC:
+                       (*ocd)->octo_encrypt = octo_aes_cbc_md5_encrypt;
+                       (*ocd)->octo_decrypt = octo_aes_cbc_md5_decrypt;
+                       octo_calc_hash(0, macini->cri_key, (*ocd)->octo_hminner,
+                                       (*ocd)->octo_hmouter);
+                       break;
+               case CRYPTO_SHA1_HMAC:
+                       (*ocd)->octo_encrypt = octo_aes_cbc_sha1_encrypt;
+                       (*ocd)->octo_decrypt = octo_aes_cbc_sha1_decrypt;
+                       octo_calc_hash(1, macini->cri_key, (*ocd)->octo_hminner,
+                                       (*ocd)->octo_hmouter);
+                       break;
+               case -1:
+                       (*ocd)->octo_encrypt = octo_aes_cbc_encrypt;
+                       (*ocd)->octo_decrypt = octo_aes_cbc_decrypt;
+                       break;
+               default:
+                       octo_freesession(NULL, i);
+                       dprintk("%s,%d: EINVALn", __FILE__, __LINE__);
+                       return EINVAL;
+               }
+               break;
+       case CRYPTO_MD5_HMAC:
+               (*ocd)->octo_encrypt = octo_null_md5_encrypt;
+               (*ocd)->octo_decrypt = octo_null_md5_encrypt;
+               octo_calc_hash(0, macini->cri_key, (*ocd)->octo_hminner,
+                               (*ocd)->octo_hmouter);
+               break;
+       case CRYPTO_SHA1_HMAC:
+               (*ocd)->octo_encrypt = octo_null_sha1_encrypt;
+               (*ocd)->octo_decrypt = octo_null_sha1_encrypt;
+               octo_calc_hash(1, macini->cri_key, (*ocd)->octo_hminner,
+                               (*ocd)->octo_hmouter);
+               break;
+       default:
+               octo_freesession(NULL, i);
+               dprintk("%s,%d: EINVALn", __FILE__, __LINE__);
+               return EINVAL;
+       }
+
+       (*ocd)->octo_encalg = encini ? encini->cri_alg : -1;
+       (*ocd)->octo_macalg = macini ? macini->cri_alg : -1;
+
+       return 0;
+}
+
+/*
+ * Free a session.
+ */
+static int
+octo_freesession(device_t dev, u_int64_t tid)
+{
+       u_int32_t sid = CRYPTO_SESID2LID(tid);
+
+       dprintk("%s()\n", __FUNCTION__);
+       if (sid > octo_sesnum || octo_sessions == NULL ||
+                       octo_sessions[sid] == NULL) {
+               dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+               return(EINVAL);
+       }
+
+       /* Silently accept and return */
+       if (sid == 0)
+               return(0);
+
+       if (octo_sessions[sid])
+               kfree(octo_sessions[sid]);
+       octo_sessions[sid] = NULL;
+       return 0;
+}
+
+/*
+ * Process a request.
+ */
+static int
+octo_process(device_t dev, struct cryptop *crp, int hint)
+{
+       struct cryptodesc *crd;
+       struct octo_sess *od;
+       u_int32_t lid;
+#define SCATTERLIST_MAX 16
+       struct scatterlist sg[SCATTERLIST_MAX];
+       int sg_num, sg_len;
+       struct sk_buff *skb = NULL;
+       struct uio *uiop = NULL;
+       struct cryptodesc *enccrd = NULL, *maccrd = NULL;
+       unsigned char *ivp = NULL;
+       unsigned char iv_data[HASH_MAX_LEN];
+       int auth_off = 0, auth_len = 0, crypt_off = 0, crypt_len = 0, icv_off = 0;
+
+       dprintk("%s()\n", __FUNCTION__);
+       /* Sanity check */
+       if (crp == NULL) {
+               dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+               return EINVAL;
+       }
+
+       crp->crp_etype = 0;
+
+       if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
+               dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+               crp->crp_etype = EINVAL;
+               goto done;
+       }
+
+       lid = crp->crp_sid & 0xffffffff;
+       if (lid >= octo_sesnum || lid == 0 || octo_sessions == NULL ||
+                       octo_sessions[lid] == NULL) {
+               crp->crp_etype = ENOENT;
+               dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
+               goto done;
+       }
+       od = octo_sessions[lid];
+
+       /*
+        * do some error checking outside of the loop for SKB and IOV processing
+        * this leaves us with valid skb or uiop pointers for later
+        */
+       if (crp->crp_flags & CRYPTO_F_SKBUF) {
+               skb = (struct sk_buff *) crp->crp_buf;
+               if (skb_shinfo(skb)->nr_frags >= SCATTERLIST_MAX) {
+                       printk("%s,%d: %d nr_frags > SCATTERLIST_MAX", __FILE__, __LINE__,
+                                       skb_shinfo(skb)->nr_frags);
+                       goto done;
+               }
+       } else if (crp->crp_flags & CRYPTO_F_IOV) {
+               uiop = (struct uio *) crp->crp_buf;
+               if (uiop->uio_iovcnt > SCATTERLIST_MAX) {
+                       printk("%s,%d: %d uio_iovcnt > SCATTERLIST_MAX", __FILE__, __LINE__,
+                                       uiop->uio_iovcnt);
+                       goto done;
+               }
+       }
+
+       /* point our enccrd and maccrd appropriately */
+       crd = crp->crp_desc;
+       if (crd->crd_alg == od->octo_encalg) enccrd = crd;
+       if (crd->crd_alg == od->octo_macalg) maccrd = crd;
+       crd = crd->crd_next;
+       if (crd) {
+               if (crd->crd_alg == od->octo_encalg) enccrd = crd;
+               if (crd->crd_alg == od->octo_macalg) maccrd = crd;
+               crd = crd->crd_next;
+       }
+       if (crd) {
+               crp->crp_etype = EINVAL;
+               dprintk("%s,%d: ENOENT - descriptors do not match session\n",
+                               __FILE__, __LINE__);
+               goto done;
+       }
+
+       if (enccrd) {
+               if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) {
+                       ivp = enccrd->crd_iv;
+               } else {
+                       ivp = iv_data;
+                       crypto_copydata(crp->crp_flags, crp->crp_buf,
+                                       enccrd->crd_inject, od->octo_ivsize, (caddr_t) ivp);
+               }
+
+               if (maccrd) {
+                       auth_off = maccrd->crd_skip;
+                       auth_len = maccrd->crd_len;
+                       icv_off  = maccrd->crd_inject;
+               }
+
+               crypt_off = enccrd->crd_skip;
+               crypt_len = enccrd->crd_len;
+       } else { /* if (maccrd) */
+               auth_off = maccrd->crd_skip;
+               auth_len = maccrd->crd_len;
+               icv_off  = maccrd->crd_inject;
+       }
+
+
+       /*
+        * setup the SG list to cover the buffer
+        */
+       memset(sg, 0, sizeof(sg));
+       if (crp->crp_flags & CRYPTO_F_SKBUF) {
+               int i, len;
+
+               sg_num = 0;
+               sg_len = 0;
+
+               len = skb_headlen(skb);
+               sg_set_page(&sg[sg_num], virt_to_page(skb->data), len,
+                               offset_in_page(skb->data));
+               sg_len += len;
+               sg_num++;
+
+               for (i = 0; i < skb_shinfo(skb)->nr_frags && sg_num < SCATTERLIST_MAX;
+                               i++) {
+                       len = skb_shinfo(skb)->frags[i].size;
+                       sg_set_page(&sg[sg_num], skb_shinfo(skb)->frags[i].page,
+                                       len, skb_shinfo(skb)->frags[i].page_offset);
+                       sg_len += len;
+                       sg_num++;
+               }
+       } else if (crp->crp_flags & CRYPTO_F_IOV) {
+               int len;
+
+               sg_len = 0;
+               for (sg_num = 0; sg_len < crp->crp_ilen &&
+                               sg_num < uiop->uio_iovcnt &&
+                               sg_num < SCATTERLIST_MAX; sg_num++) {
+                       len = uiop->uio_iov[sg_num].iov_len;
+                       sg_set_page(&sg[sg_num],
+                                       virt_to_page(uiop->uio_iov[sg_num].iov_base), len,
+                                       offset_in_page(uiop->uio_iov[sg_num].iov_base));
+                       sg_len += len;
+               }
+       } else {
+               sg_len = crp->crp_ilen;
+               sg_set_page(&sg[0], virt_to_page(crp->crp_buf), sg_len,
+                               offset_in_page(crp->crp_buf));
+               sg_num = 1;
+       }
+
+
+       /*
+        * setup a new explicit key
+        */
+       if (enccrd) {
+               if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
+                       od->octo_encklen = (enccrd->crd_klen + 7) / 8;
+                       memcpy(od->octo_enckey, enccrd->crd_key, od->octo_encklen);
+               }
+       }
+       if (maccrd) {
+               if (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
+                       od->octo_macklen = (maccrd->crd_klen + 7) / 8;
+                       memcpy(od->octo_mackey, maccrd->crd_key, od->octo_macklen);
+                       od->octo_mackey_set = 0;
+               }
+               if (!od->octo_mackey_set) {
+                       octo_calc_hash(maccrd->crd_alg == CRYPTO_MD5_HMAC ? 0 : 1,
+                               maccrd->crd_key, od->octo_hminner, od->octo_hmouter);
+                       od->octo_mackey_set = 1;
+               }
+       }
+
+
+       if (!enccrd || (enccrd->crd_flags & CRD_F_ENCRYPT))
+               (*od->octo_encrypt)(od, sg, sg_len,
+                               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+       else
+               (*od->octo_decrypt)(od, sg, sg_len,
+                               auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp);
+
+done:
+       crypto_done(crp);
+       return 0;
+}
+
+static int
+cryptocteon_init(void)
+{
+       dprintk("%s(%p)\n", __FUNCTION__, cryptocteon_init);
+
+       softc_device_init(&octo_softc, "cryptocteon", 0, octo_methods);
+
+       octo_id = crypto_get_driverid(softc_get_device(&octo_softc),
+                       CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SYNC);
+       if (octo_id < 0) {
+               printk("Cryptocteon device cannot initialize!");
+               return -ENODEV;
+       }
+
+       crypto_register(octo_id, CRYPTO_MD5_HMAC, 0,0);
+       crypto_register(octo_id, CRYPTO_SHA1_HMAC, 0,0);
+       //crypto_register(octo_id, CRYPTO_MD5, 0,0);
+       //crypto_register(octo_id, CRYPTO_SHA1, 0,0);
+       crypto_register(octo_id, CRYPTO_DES_CBC, 0,0);
+       crypto_register(octo_id, CRYPTO_3DES_CBC, 0,0);
+       crypto_register(octo_id, CRYPTO_AES_CBC, 0,0);
+
+       return(0);
+}
+
+static void
+cryptocteon_exit(void)
+{
+       dprintk("%s()\n", __FUNCTION__);
+       crypto_unregister_all(octo_id);
+       octo_id = -1;
+}
+
+module_init(cryptocteon_init);
+module_exit(cryptocteon_exit);
+
+MODULE_LICENSE("BSD");
+MODULE_AUTHOR("David McCullough <david_mccullough@mcafee.com>");
+MODULE_DESCRIPTION("Cryptocteon (OCF module for Cavium OCTEON crypto)");
index 13d57a1..87a4c37 100644 (file)
@@ -1,8 +1,8 @@
 /*     $OpenBSD: cryptodev.c,v 1.52 2002/06/19 07:22:46 deraadt Exp $  */
 
 /*-
- * Linux port done by David McCullough <david_mccullough@securecomputing.com>
- * Copyright (C) 2006-2007 David McCullough
+ * Linux port done by David McCullough <david_mccullough@mcafee.com>
+ * Copyright (C) 2006-2010 David McCullough
  * Copyright (C) 2004-2005 Intel Corporation.
  * The license and original author are listed below.
  *
@@ -77,6 +77,7 @@ struct csession_info {
        u_int16_t       keysize;
        /* u_int16_t    hashsize;  */
        u_int16_t       authsize;
+       u_int16_t       authkey;
        /* u_int16_t    ctxsize; */
 };
 
@@ -197,7 +198,7 @@ cryptodev_op(struct csession *cse, struct crypt_op *cop)
 
        if (cse->uio.uio_iov[0].iov_base == NULL) {
                dprintk("%s: iov_base kmalloc(%d) failed\n", __FUNCTION__,
-                               cse->uio.uio_iov[0].iov_len);
+                               (int)cse->uio.uio_iov[0].iov_len);
                return (ENOMEM);
        }
 
@@ -208,18 +209,22 @@ cryptodev_op(struct csession *cse, struct crypt_op *cop)
                goto bail;
        }
 
-       if (cse->info.authsize) {
-               crda = crp->crp_desc;
-               if (cse->info.blocksize)
-                       crde = crda->crd_next;
-       } else {
-               if (cse->info.blocksize)
+       if (cse->info.authsize && cse->info.blocksize) {
+               if (cop->op == COP_ENCRYPT) {
                        crde = crp->crp_desc;
-               else {
-                       dprintk("%s: bad request\n", __FUNCTION__);
-                       error = EINVAL;
-                       goto bail;
+                       crda = crde->crd_next;
+               } else {
+                       crda = crp->crp_desc;
+                       crde = crda->crd_next;
                }
+       } else if (cse->info.authsize) {
+               crda = crp->crp_desc;
+       } else if (cse->info.blocksize) {
+               crde = crp->crp_desc;
+       } else {
+               dprintk("%s: bad request\n", __FUNCTION__);
+               error = EINVAL;
+               goto bail;
        }
 
        if ((error = copy_from_user(cse->uio.uio_iov[0].iov_base, cop->src,
@@ -300,28 +305,31 @@ cryptodev_op(struct csession *cse, struct crypt_op *cop)
         * entry and the crypto_done callback into us.
         */
        error = crypto_dispatch(crp);
-       if (error == 0) {
-               dprintk("%s about to WAIT\n", __FUNCTION__);
+       if (error) {
+               dprintk("%s error in crypto_dispatch\n", __FUNCTION__);
+               goto bail;
+       }
+
+       dprintk("%s about to WAIT\n", __FUNCTION__);
+       /*
+        * we really need to wait for driver to complete to maintain
+        * state,  luckily interrupts will be remembered
+        */
+       do {
+               error = wait_event_interruptible(crp->crp_waitq,
+                               ((crp->crp_flags & CRYPTO_F_DONE) != 0));
                /*
-                * we really need to wait for driver to complete to maintain
-                * state,  luckily interrupts will be remembered
+                * we can't break out of this loop or we will leave behind
+                * a huge mess,  however,  staying here means if your driver
+                * is broken user applications can hang and not be killed.
+                * The solution,  fix your driver :-)
                 */
-               do {
-                       error = wait_event_interruptible(crp->crp_waitq,
-                                       ((crp->crp_flags & CRYPTO_F_DONE) != 0));
-                       /*
-                        * we can't break out of this loop or we will leave behind
-                        * a huge mess,  however,  staying here means if your driver
-                        * is broken user applications can hang and not be killed.
-                        * The solution,  fix your driver :-)
-                        */
-                       if (error) {
-                               schedule();
-                               error = 0;
-                       }
-               } while ((crp->crp_flags & CRYPTO_F_DONE) == 0);
-               dprintk("%s finished WAITING error=%d\n", __FUNCTION__, error);
-       }
+               if (error) {
+                       schedule();
+                       error = 0;
+               }
+       } while ((crp->crp_flags & CRYPTO_F_DONE) == 0);
+       dprintk("%s finished WAITING error=%d\n", __FUNCTION__, error);
 
        if (crp->crp_etype != 0) {
                error = crp->crp_etype;
@@ -625,7 +633,7 @@ cryptodev_ioctl(
        struct crypt_kop kop;
        struct crypt_find_op fop;
        u_int64_t sid;
-       u_int32_t ses;
+       u_int32_t ses = 0;
        int feat, fd, error = 0, crid;
        mm_segment_t fs;
 
@@ -744,21 +752,27 @@ cryptodev_ioctl(
                        break;
                case CRYPTO_MD5_HMAC:
                        info.authsize = MD5_HASH_LEN;
+                       info.authkey = 16;
                        break;
                case CRYPTO_SHA1_HMAC:
                        info.authsize = SHA1_HASH_LEN;
+                       info.authkey = 20;
                        break;
                case CRYPTO_SHA2_256_HMAC:
                        info.authsize = SHA2_256_HASH_LEN;
+                       info.authkey = 32;
                        break;
                case CRYPTO_SHA2_384_HMAC:
                        info.authsize = SHA2_384_HASH_LEN;
+                       info.authkey = 48;
                        break;
                case CRYPTO_SHA2_512_HMAC:
                        info.authsize = SHA2_512_HASH_LEN;
+                       info.authkey = 64;
                        break;
                case CRYPTO_RIPEMD160_HMAC:
                        info.authsize = RIPEMD160_HASH_LEN;
+                       info.authkey = 20;
                        break;
                default:
                        dprintk("%s(%s) - bad mac\n", __FUNCTION__, CIOCGSESSSTR);
@@ -790,10 +804,9 @@ cryptodev_ioctl(
                if (info.authsize) {
                        cria.cri_alg = sop.mac;
                        cria.cri_klen = sop.mackeylen * 8;
-                       if ((info.maxkey && sop.mackeylen > info.maxkey) ||
-                                       sop.keylen < info.minkey) {
-                               dprintk("%s(%s) - mackeylen %d\n", __FUNCTION__, CIOCGSESSSTR,
-                                               sop.mackeylen);
+                       if (info.authkey && sop.mackeylen != info.authkey) {
+                               dprintk("%s(%s) - mackeylen %d != %d\n", __FUNCTION__,
+                                               CIOCGSESSSTR, sop.mackeylen, info.authkey);
                                error = EINVAL;
                                goto bail;
                        }
@@ -1044,5 +1057,5 @@ module_init(cryptodev_init);
 module_exit(cryptodev_exit);
 
 MODULE_LICENSE("BSD");
-MODULE_AUTHOR("David McCullough <david_mccullough@securecomputing.com>");
+MODULE_AUTHOR("David McCullough <david_mccullough@mcafee.com>");
 MODULE_DESCRIPTION("Cryptodev (user interface to OCF)");
index fa1a57b..6032317 100644 (file)
@@ -2,8 +2,8 @@
 /*     $OpenBSD: cryptodev.h,v 1.31 2002/06/11 11:14:29 beck Exp $     */
 
 /*-
- * Linux port done by David McCullough <david_mccullough@securecomputing.com>
- * Copyright (C) 2006-2007 David McCullough
+ * Linux port done by David McCullough <david_mccullough@mcafee.com>
+ * Copyright (C) 2006-2010 David McCullough
  * Copyright (C) 2004-2005 Intel Corporation.
  * The license and original author are listed below.
  *
@@ -336,6 +336,7 @@ struct cryptodesc {
 #define crd_key                CRD_INI.cri_key
 #define crd_alg                CRD_INI.cri_alg
 #define crd_klen       CRD_INI.cri_klen
+#define crd_mlen       CRD_INI.cri_mlen
 
        struct cryptodesc *crd_next;
 };
index 1486889..52e1570 100644 (file)
@@ -3,8 +3,8 @@
  * original cryptosoft for BSD by Angelos D. Keromytis (angelos@cis.upenn.edu)
  * but is mostly unrecognisable,
  *
- * Written by David McCullough <david_mccullough@securecomputing.com>
- * Copyright (C) 2004-2007 David McCullough
+ * Written by David McCullough <david_mccullough@mcafee.com>
+ * Copyright (C) 2004-2010 David McCullough
  * Copyright (C) 2004-2005 Intel Corporation.
  *
  * LICENSE TERMS
 #include <linux/mm.h>
 #include <linux/skbuff.h>
 #include <linux/random.h>
-#include <asm/scatterlist.h>
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
+#include <linux/scatterlist.h>
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29)
+#include <crypto/hash.h>
+#endif
 
 #include <cryptodev.h>
 #include <uio.h>
@@ -58,14 +64,24 @@ struct {
 
 #define offset_in_page(p) ((unsigned long)(p) & ~PAGE_MASK)
 
-/* Software session entry */
+#define SW_TYPE_CIPHER         0x01
+#define SW_TYPE_HMAC           0x02
+#define SW_TYPE_HASH           0x04
+#define SW_TYPE_COMP           0x08
+#define SW_TYPE_BLKCIPHER      0x10
+#define SW_TYPE_ALG_MASK       0x1f
+
+#define SW_TYPE_ASYNC          0x8000
+
+/* We change some of the above if we have an async interface */
+
+#define SW_TYPE_ALG_AMASK      (SW_TYPE_ALG_MASK | SW_TYPE_ASYNC)
 
-#define SW_TYPE_CIPHER         0
-#define SW_TYPE_HMAC           1
-#define SW_TYPE_AUTH2          2
-#define SW_TYPE_HASH           3
-#define SW_TYPE_COMP           4
-#define SW_TYPE_BLKCIPHER      5
+#define SW_TYPE_ABLKCIPHER     (SW_TYPE_BLKCIPHER | SW_TYPE_ASYNC)
+#define SW_TYPE_AHASH          (SW_TYPE_HASH | SW_TYPE_ASYNC)
+#define SW_TYPE_AHMAC          (SW_TYPE_HMAC | SW_TYPE_ASYNC)
+
+#define SCATTERLIST_MAX 16
 
 struct swcr_data {
        int                                     sw_type;
@@ -82,6 +98,23 @@ struct swcr_data {
        struct swcr_data        *sw_next;
 };
 
+struct swcr_req {
+       struct swcr_data        *sw_head;
+       struct swcr_data        *sw;
+       struct cryptop          *crp;
+       struct cryptodesc       *crd;
+       struct scatterlist       sg[SCATTERLIST_MAX];
+       unsigned char            iv[EALG_MAX_BLOCK_LEN];
+       char                             result[HASH_MAX_LEN];
+       void                            *crypto_req;
+};
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
+static kmem_cache_t *swcr_req_cache;
+#else
+static struct kmem_cache *swcr_req_cache;
+#endif
+
 #ifndef CRYPTO_TFM_MODE_CBC
 /*
  * As of linux-2.6.21 this is no longer defined, and presumably no longer
@@ -103,8 +136,8 @@ struct swcr_data {
                struct crypto_tfm *tfm;
                void *info;
        };
-       #define ecb(X)                                                          #X
-       #define cbc(X)                                                          #X
+       #define ecb(X)                                                          #X , CRYPTO_TFM_MODE_ECB
+       #define cbc(X)                                                          #X , CRYPTO_TFM_MODE_CBC
        #define crypto_has_blkcipher(X, Y, Z)           crypto_alg_available(X, 0)
        #define crypto_blkcipher_cast(X)                        X
        #define crypto_blkcipher_tfm(X)                         X
@@ -116,13 +149,14 @@ struct swcr_data {
                                crypto_cipher_encrypt_iv((W)->tfm, X, Y, Z, (u8 *)((W)->info))
        #define crypto_blkcipher_decrypt_iv(W, X, Y, Z) \
                                crypto_cipher_decrypt_iv((W)->tfm, X, Y, Z, (u8 *)((W)->info))
+       #define crypto_blkcipher_set_flags(x, y)        /* nop */
 
        /* Hash/HMAC/Digest */
        struct hash_desc
        {
                struct crypto_tfm *tfm;
        };
-       #define hmac(X)                                                 #X
+       #define hmac(X)                                                 #X , 0
        #define crypto_has_hash(X, Y, Z)                crypto_alg_available(X, 0)
        #define crypto_hash_cast(X)                             X
        #define crypto_hash_tfm(X)                              X
@@ -139,53 +173,66 @@ struct swcr_data {
        #define crypto_comp_tfm(X)                              X
        #define crypto_comp_cast(X)                             X
        #define crypto_alloc_comp(X, Y, Z)              crypto_alloc_tfm(X, mode)
+       #define plain(X)        #X , 0
 #else
-       #define ecb(X)  "ecb(" #X ")"
-       #define cbc(X)  "cbc(" #X ")"
-       #define hmac(X) "hmac(" #X ")"
+       #define ecb(X)  "ecb(" #X ")" , 0
+       #define cbc(X)  "cbc(" #X ")" , 0
+       #define hmac(X) "hmac(" #X ")" , 0
+       #define plain(X)        #X , 0
 #endif /* if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) */
 
-struct crypto_details
-{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+/* no ablkcipher in older kernels */
+#define crypto_alloc_ablkcipher(a,b,c)         (NULL)
+#define crypto_ablkcipher_tfm(x)                       ((struct crypto_tfm *)(x))
+#define crypto_ablkcipher_set_flags(a, b)      /* nop */
+#define crypto_ablkcipher_setkey(x, y, z)      (-EINVAL)
+#define        crypto_has_ablkcipher(a,b,c)            (0)
+#else
+#define        HAVE_ABLKCIPHER
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32)
+/* no ahash in older kernels */
+#define crypto_ahash_tfm(x)                                    ((struct crypto_tfm *)(x))
+#define        crypto_alloc_ahash(a,b,c)                       (NULL)
+#define        crypto_ahash_digestsize(x)                      0
+#else
+#define        HAVE_AHASH
+#endif
+
+struct crypto_details {
        char *alg_name;
        int mode;
        int sw_type;
 };
 
-/*
- * This needs to be kept updated with CRYPTO_xxx list (cryptodev.h).
- * If the Algorithm is not supported, then insert a {NULL, 0, 0} entry.
- *
- * IMPORTANT: The index to the array IS CRYPTO_xxx.
- */
-static struct crypto_details crypto_details[CRYPTO_ALGORITHM_MAX + 1] = {
-       { NULL,              0,                   0 },
-       /* CRYPTO_xxx index starts at 1 */
-       { cbc(des),          CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
-       { cbc(des3_ede),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
-       { cbc(blowfish),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
-       { cbc(cast5),        CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
-       { cbc(skipjack),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
-       { hmac(md5),         0,                   SW_TYPE_HMAC },
-       { hmac(sha1),        0,                   SW_TYPE_HMAC },
-       { hmac(ripemd160),   0,                   SW_TYPE_HMAC },
-       { "md5-kpdk??",      0,                   SW_TYPE_HASH },
-       { "sha1-kpdk??",     0,                   SW_TYPE_HASH },
-       { cbc(aes),          CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
-       { ecb(arc4),         CRYPTO_TFM_MODE_ECB, SW_TYPE_BLKCIPHER },
-       { "md5",             0,                   SW_TYPE_HASH },
-       { "sha1",            0,                   SW_TYPE_HASH },
-       { hmac(digest_null), 0,                   SW_TYPE_HMAC },
-       { cbc(cipher_null),  CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
-       { "deflate",         0,                   SW_TYPE_COMP },
-       { hmac(sha256),      0,                   SW_TYPE_HMAC },
-       { hmac(sha384),      0,                   SW_TYPE_HMAC },
-       { hmac(sha512),      0,                   SW_TYPE_HMAC },
-       { cbc(camellia),     CRYPTO_TFM_MODE_CBC, SW_TYPE_BLKCIPHER },
-       { "sha256",          0,                   SW_TYPE_HASH },
-       { "sha384",          0,                   SW_TYPE_HASH },
-       { "sha512",          0,                   SW_TYPE_HASH },
-       { "ripemd160",       0,                   SW_TYPE_HASH },
+static struct crypto_details crypto_details[] = {
+       [CRYPTO_DES_CBC]         = { cbc(des),          SW_TYPE_BLKCIPHER, },
+       [CRYPTO_3DES_CBC]        = { cbc(des3_ede),     SW_TYPE_BLKCIPHER, },
+       [CRYPTO_BLF_CBC]         = { cbc(blowfish),     SW_TYPE_BLKCIPHER, },
+       [CRYPTO_CAST_CBC]        = { cbc(cast5),        SW_TYPE_BLKCIPHER, },
+       [CRYPTO_SKIPJACK_CBC]    = { cbc(skipjack),     SW_TYPE_BLKCIPHER, },
+       [CRYPTO_MD5_HMAC]        = { hmac(md5),         SW_TYPE_HMAC, },
+       [CRYPTO_SHA1_HMAC]       = { hmac(sha1),        SW_TYPE_HMAC, },
+       [CRYPTO_RIPEMD160_HMAC]  = { hmac(ripemd160),   SW_TYPE_HMAC, },
+       [CRYPTO_MD5_KPDK]        = { plain(md5-kpdk),   SW_TYPE_HASH, },
+       [CRYPTO_SHA1_KPDK]       = { plain(sha1-kpdk),  SW_TYPE_HASH, },
+       [CRYPTO_AES_CBC]         = { cbc(aes),          SW_TYPE_BLKCIPHER, },
+       [CRYPTO_ARC4]            = { ecb(arc4),         SW_TYPE_BLKCIPHER, },
+       [CRYPTO_MD5]             = { plain(md5),        SW_TYPE_HASH, },
+       [CRYPTO_SHA1]            = { plain(sha1),       SW_TYPE_HASH, },
+       [CRYPTO_NULL_HMAC]       = { hmac(digest_null), SW_TYPE_HMAC, },
+       [CRYPTO_NULL_CBC]        = { cbc(cipher_null),  SW_TYPE_BLKCIPHER, },
+       [CRYPTO_DEFLATE_COMP]    = { plain(deflate),    SW_TYPE_COMP, },
+       [CRYPTO_SHA2_256_HMAC]   = { hmac(sha256),      SW_TYPE_HMAC, },
+       [CRYPTO_SHA2_384_HMAC]   = { hmac(sha384),      SW_TYPE_HMAC, },
+       [CRYPTO_SHA2_512_HMAC]   = { hmac(sha512),      SW_TYPE_HMAC, },
+       [CRYPTO_CAMELLIA_CBC]    = { cbc(camellia),     SW_TYPE_BLKCIPHER, },
+       [CRYPTO_SHA2_256]        = { plain(sha256),     SW_TYPE_HASH, },
+       [CRYPTO_SHA2_384]        = { plain(sha384),     SW_TYPE_HASH, },
+       [CRYPTO_SHA2_512]        = { plain(sha512),     SW_TYPE_HASH, },
+       [CRYPTO_RIPEMD160]       = { plain(ripemd160),  SW_TYPE_HASH, },
 };
 
 int32_t swcr_id = -1;
@@ -197,6 +244,16 @@ module_param(swcr_fail_if_compression_grows, int, 0644);
 MODULE_PARM_DESC(swcr_fail_if_compression_grows,
                 "Treat compression that results in more data as a failure");
 
+int swcr_no_ahash = 0;
+module_param(swcr_no_ahash, int, 0644);
+MODULE_PARM_DESC(swcr_no_ahash,
+                "Do not use async hash/hmac even if available");
+
+int swcr_no_ablk = 0;
+module_param(swcr_no_ablk, int, 0644);
+MODULE_PARM_DESC(swcr_no_ablk,
+                "Do not use async blk ciphers even if available");
+
 static struct swcr_data **swcr_sessions = NULL;
 static u_int32_t swcr_sesnum = 0;
 
@@ -216,6 +273,8 @@ int swcr_debug = 0;
 module_param(swcr_debug, int, 0644);
 MODULE_PARM_DESC(swcr_debug, "Enable debug");
 
+static void swcr_process_req(struct swcr_req *req);
+
 /*
  * Generate a new software session.
  */
@@ -226,7 +285,7 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
        u_int32_t i;
        int error;
        char *algo;
-       int mode, sw_type;
+       int mode;
 
        dprintk("%s()\n", __FUNCTION__);
        if (sid == NULL || cri == NULL) {
@@ -283,7 +342,8 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
                }
                memset(*swd, 0, sizeof(struct swcr_data));
 
-               if (cri->cri_alg > CRYPTO_ALGORITHM_MAX) {
+               if (cri->cri_alg < 0 ||
+                               cri->cri_alg>=sizeof(crypto_details)/sizeof(crypto_details[0])){
                        printk("cryptosoft: Unknown algorithm 0x%x\n", cri->cri_alg);
                        swcr_freesession(NULL, i);
                        return EINVAL;
@@ -297,7 +357,8 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
                }
 
                mode = crypto_details[cri->cri_alg].mode;
-               sw_type = crypto_details[cri->cri_alg].sw_type;
+               (*swd)->sw_type = crypto_details[cri->cri_alg].sw_type;
+               (*swd)->sw_alg = cri->cri_alg;
 
                /* Algorithm specific configuration */
                switch (cri->cri_alg) {
@@ -308,15 +369,23 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
                        break;
                }
 
-               if (sw_type == SW_TYPE_BLKCIPHER) {
-                       dprintk("%s crypto_alloc_blkcipher(%s, 0x%x)\n", __FUNCTION__,
+               if ((*swd)->sw_type & SW_TYPE_BLKCIPHER) {
+                       dprintk("%s crypto_alloc_*blkcipher(%s, 0x%x)\n", __FUNCTION__,
                                        algo, mode);
 
-                       (*swd)->sw_tfm = crypto_blkcipher_tfm(
-                                                               crypto_alloc_blkcipher(algo, 0,
-                                                                       CRYPTO_ALG_ASYNC));
+                       /* try async first */
+                       (*swd)->sw_tfm = swcr_no_ablk ? NULL :
+                                       crypto_ablkcipher_tfm(crypto_alloc_ablkcipher(algo, 0, 0));
+                       if ((*swd)->sw_tfm) {
+                               dprintk("%s %s cipher is async\n", __FUNCTION__, algo);
+                               (*swd)->sw_type |= SW_TYPE_ASYNC;
+                       } else {
+                               dprintk("%s %s cipher is sync\n", __FUNCTION__, algo);
+                               (*swd)->sw_tfm = crypto_blkcipher_tfm(
+                                               crypto_alloc_blkcipher(algo, 0, CRYPTO_ALG_ASYNC));
+                       }
                        if (!(*swd)->sw_tfm) {
-                               dprintk("cryptosoft: crypto_alloc_blkcipher failed(%s,0x%x)\n",
+                               dprintk("cryptosoft: crypto_alloc_blkcipher failed(%s, 0x%x)\n",
                                                algo,mode);
                                swcr_freesession(NULL, i);
                                return EINVAL;
@@ -324,28 +393,50 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
 
                        if (debug) {
                                dprintk("%s key:cri->cri_klen=%d,(cri->cri_klen + 7)/8=%d",
-                                               __FUNCTION__,cri->cri_klen,(cri->cri_klen + 7)/8);
+                                               __FUNCTION__, cri->cri_klen, (cri->cri_klen + 7) / 8);
                                for (i = 0; i < (cri->cri_klen + 7) / 8; i++)
-                               {
-                                       dprintk("%s0x%x", (i % 8) ? " " : "\n    ",cri->cri_key[i]);
-                               }
+                                       dprintk("%s0x%x", (i % 8) ? " " : "\n    ",
+                                                       cri->cri_key[i] & 0xff);
                                dprintk("\n");
                        }
-                       error = crypto_blkcipher_setkey(
-                                               crypto_blkcipher_cast((*swd)->sw_tfm), cri->cri_key,
-                                                       (cri->cri_klen + 7) / 8);
+                       if ((*swd)->sw_type & SW_TYPE_ASYNC) {
+                               /* OCF doesn't enforce keys */
+                               crypto_ablkcipher_set_flags(
+                                               __crypto_ablkcipher_cast((*swd)->sw_tfm),
+                                                       CRYPTO_TFM_REQ_WEAK_KEY);
+                               error = crypto_ablkcipher_setkey(
+                                                       __crypto_ablkcipher_cast((*swd)->sw_tfm),
+                                                               cri->cri_key, (cri->cri_klen + 7) / 8);
+                       } else {
+                               /* OCF doesn't enforce keys */
+                               crypto_blkcipher_set_flags(
+                                               crypto_blkcipher_cast((*swd)->sw_tfm),
+                                                       CRYPTO_TFM_REQ_WEAK_KEY);
+                               error = crypto_blkcipher_setkey(
+                                                       crypto_blkcipher_cast((*swd)->sw_tfm),
+                                                               cri->cri_key, (cri->cri_klen + 7) / 8);
+                       }
                        if (error) {
                                printk("cryptosoft: setkey failed %d (crt_flags=0x%x)\n", error,
                                                (*swd)->sw_tfm->crt_flags);
                                swcr_freesession(NULL, i);
                                return error;
                        }
-               } else if (sw_type == SW_TYPE_HMAC || sw_type == SW_TYPE_HASH) {
-                       dprintk("%s crypto_alloc_hash(%s, 0x%x)\n", __FUNCTION__,
+               } else if ((*swd)->sw_type & (SW_TYPE_HMAC | SW_TYPE_HASH)) {
+                       dprintk("%s crypto_alloc_*hash(%s, 0x%x)\n", __FUNCTION__,
                                        algo, mode);
 
-                       (*swd)->sw_tfm = crypto_hash_tfm(
-                                                               crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC));
+                       /* try async first */
+                       (*swd)->sw_tfm = swcr_no_ahash ? NULL :
+                                       crypto_ahash_tfm(crypto_alloc_ahash(algo, 0, 0));
+                       if ((*swd)->sw_tfm) {
+                               dprintk("%s %s hash is async\n", __FUNCTION__, algo);
+                               (*swd)->sw_type |= SW_TYPE_ASYNC;
+                       } else {
+                               dprintk("%s %s hash is sync\n", __FUNCTION__, algo);
+                               (*swd)->sw_tfm = crypto_hash_tfm(
+                                               crypto_alloc_hash(algo, 0, CRYPTO_ALG_ASYNC));
+                       }
 
                        if (!(*swd)->sw_tfm) {
                                dprintk("cryptosoft: crypto_alloc_hash failed(%s,0x%x)\n",
@@ -356,7 +447,7 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
 
                        (*swd)->u.hmac.sw_klen = (cri->cri_klen + 7) / 8;
                        (*swd)->u.hmac.sw_key = (char *)kmalloc((*swd)->u.hmac.sw_klen,
-                               SLAB_ATOMIC);
+                                       SLAB_ATOMIC);
                        if ((*swd)->u.hmac.sw_key == NULL) {
                                swcr_freesession(NULL, i);
                                dprintk("%s,%d: ENOBUFS\n", __FILE__, __LINE__);
@@ -365,12 +456,14 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
                        memcpy((*swd)->u.hmac.sw_key, cri->cri_key, (*swd)->u.hmac.sw_klen);
                        if (cri->cri_mlen) {
                                (*swd)->u.hmac.sw_mlen = cri->cri_mlen;
-                       } else {
-                               (*swd)->u.hmac.sw_mlen =
-                                               crypto_hash_digestsize(
-                                                               crypto_hash_cast((*swd)->sw_tfm));
+                       } else if ((*swd)->sw_type & SW_TYPE_ASYNC) {
+                               (*swd)->u.hmac.sw_mlen = crypto_ahash_digestsize(
+                                               __crypto_ahash_cast((*swd)->sw_tfm));
+                       } else  {
+                               (*swd)->u.hmac.sw_mlen = crypto_hash_digestsize(
+                                               crypto_hash_cast((*swd)->sw_tfm));
                        }
-               } else if (sw_type == SW_TYPE_COMP) {
+               } else if ((*swd)->sw_type & SW_TYPE_COMP) {
                        (*swd)->sw_tfm = crypto_comp_tfm(
                                        crypto_alloc_comp(algo, 0, CRYPTO_ALG_ASYNC));
                        if (!(*swd)->sw_tfm) {
@@ -386,14 +479,11 @@ swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri)
                                return ENOBUFS;
                        }
                } else {
-                       printk("cryptosoft: Unhandled sw_type %d\n", sw_type);
+                       printk("cryptosoft: Unhandled sw_type %d\n", (*swd)->sw_type);
                        swcr_freesession(NULL, i);
                        return EINVAL;
                }
 
-               (*swd)->sw_alg = cri->cri_alg;
-               (*swd)->sw_type = sw_type;
-
                cri = cri->cri_next;
                swd = &((*swd)->sw_next);
        }
@@ -422,9 +512,35 @@ swcr_freesession(device_t dev, u_int64_t tid)
 
        while ((swd = swcr_sessions[sid]) != NULL) {
                swcr_sessions[sid] = swd->sw_next;
-               if (swd->sw_tfm)
-                       crypto_free_tfm(swd->sw_tfm);
-               if (swd->sw_type == SW_TYPE_COMP) {
+               if (swd->sw_tfm) {
+                       switch (swd->sw_type & SW_TYPE_ALG_AMASK) {
+#ifdef HAVE_AHASH
+                       case SW_TYPE_AHMAC:
+                       case SW_TYPE_AHASH:
+                               crypto_free_ahash(__crypto_ahash_cast(swd->sw_tfm));
+                               break;
+#endif
+#ifdef HAVE_ABLKCIPHER
+                       case SW_TYPE_ABLKCIPHER:
+                               crypto_free_ablkcipher(__crypto_ablkcipher_cast(swd->sw_tfm));
+                               break;
+#endif
+                       case SW_TYPE_BLKCIPHER:
+                               crypto_free_blkcipher(crypto_blkcipher_cast(swd->sw_tfm));
+                               break;
+                       case SW_TYPE_HMAC:
+                       case SW_TYPE_HASH:
+                               crypto_free_hash(crypto_hash_cast(swd->sw_tfm));
+                               break;
+                       case SW_TYPE_COMP:
+                               crypto_free_comp(crypto_comp_cast(swd->sw_tfm));
+                       default:
+                               crypto_free_tfm(swd->sw_tfm);
+                               break;
+                       }
+                       swd->sw_tfm = NULL;
+               }
+               if (swd->sw_type & SW_TYPE_COMP) {
                        if (swd->u.sw_comp_buf)
                                kfree(swd->u.sw_comp_buf);
                } else {
@@ -436,351 +552,574 @@ swcr_freesession(device_t dev, u_int64_t tid)
        return 0;
 }
 
-/*
- * Process a software request.
- */
-static int
-swcr_process(device_t dev, struct cryptop *crp, int hint)
+#if defined(HAVE_ABLKCIPHER) || defined(HAVE_AHASH)
+/* older kernels had no async interface */
+
+static void swcr_process_callback(struct crypto_async_request *creq, int err)
+{
+       struct swcr_req *req = creq->data;
+
+       dprintk("%s()\n", __FUNCTION__);
+       if (err) {
+               if (err == -EINPROGRESS)
+                       return;
+               dprintk("%s() fail %d\n", __FUNCTION__, -err);
+               req->crp->crp_etype = -err;
+               goto done;
+       }
+
+       switch (req->sw->sw_type & SW_TYPE_ALG_AMASK) {
+       case SW_TYPE_AHMAC:
+       case SW_TYPE_AHASH:
+               crypto_copyback(req->crp->crp_flags, req->crp->crp_buf,
+                               req->crd->crd_inject, req->sw->u.hmac.sw_mlen, req->result);
+               ahash_request_free(req->crypto_req);
+               break;
+       case SW_TYPE_ABLKCIPHER:
+               ablkcipher_request_free(req->crypto_req);
+               break;
+       default:
+               req->crp->crp_etype = EINVAL;
+               goto done;
+       }
+
+       req->crd = req->crd->crd_next;
+       if (req->crd) {
+               swcr_process_req(req);
+               return;
+       }
+
+done:
+       dprintk("%s crypto_done %p\n", __FUNCTION__, req);
+       crypto_done(req->crp);
+       kmem_cache_free(swcr_req_cache, req);
+}
+#endif /* defined(HAVE_ABLKCIPHER) || defined(HAVE_AHASH) */
+
+
+static void swcr_process_req(struct swcr_req *req)
 {
-       struct cryptodesc *crd;
        struct swcr_data *sw;
-       u_int32_t lid;
-#define SCATTERLIST_MAX 16
-       struct scatterlist sg[SCATTERLIST_MAX];
+       struct cryptop *crp = req->crp;
+       struct cryptodesc *crd = req->crd;
+       struct sk_buff *skb = (struct sk_buff *) crp->crp_buf;
+       struct uio *uiop = (struct uio *) crp->crp_buf;
        int sg_num, sg_len, skip;
-       struct sk_buff *skb = NULL;
-       struct uio *uiop = NULL;
 
        dprintk("%s()\n", __FUNCTION__);
-       /* Sanity check */
-       if (crp == NULL) {
-               dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
-               return EINVAL;
-       }
 
-       crp->crp_etype = 0;
+       /*
+        * Find the crypto context.
+        *
+        * XXX Note that the logic here prevents us from having
+        * XXX the same algorithm multiple times in a session
+        * XXX (or rather, we can but it won't give us the right
+        * XXX results). To do that, we'd need some way of differentiating
+        * XXX between the various instances of an algorithm (so we can
+        * XXX locate the correct crypto context).
+        */
+       for (sw = req->sw_head; sw && sw->sw_alg != crd->crd_alg; sw = sw->sw_next)
+               ;
 
-       if (crp->crp_desc == NULL || crp->crp_buf == NULL) {
-               dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
+       /* No such context ? */
+       if (sw == NULL) {
                crp->crp_etype = EINVAL;
+               dprintk("%s,%d: EINVAL\n", __FILE__, __LINE__);
                goto done;
        }
 
-       lid = crp->crp_sid & 0xffffffff;
-       if (lid >= swcr_sesnum || lid == 0 || swcr_sessions == NULL ||
-                       swcr_sessions[lid] == NULL) {
-               crp->crp_etype = ENOENT;
-               dprintk("%s,%d: ENOENT\n", __FILE__, __LINE__);
-               goto done;
-       }
+       req->sw = sw;
+       skip = crd->crd_skip;
 
        /*
-        * do some error checking outside of the loop for SKB and IOV processing
-        * this leaves us with valid skb or uiop pointers for later
+        * setup the SG list skip from the start of the buffer
         */
+       memset(req->sg, 0, sizeof(req->sg));
+       sg_init_table(req->sg, SCATTERLIST_MAX);
        if (crp->crp_flags & CRYPTO_F_SKBUF) {
-               skb = (struct sk_buff *) crp->crp_buf;
-               if (skb_shinfo(skb)->nr_frags >= SCATTERLIST_MAX) {
-                       printk("%s,%d: %d nr_frags > SCATTERLIST_MAX", __FILE__, __LINE__,
-                                       skb_shinfo(skb)->nr_frags);
-                       goto done;
+               int i, len;
+
+               sg_num = 0;
+               sg_len = 0;
+
+               if (skip < skb_headlen(skb)) {
+                       len = skb_headlen(skb) - skip;
+                       if (len + sg_len > crd->crd_len)
+                               len = crd->crd_len - sg_len;
+                       sg_set_page(&req->sg[sg_num],
+                               virt_to_page(skb->data + skip), len,
+                               offset_in_page(skb->data + skip));
+                       sg_len += len;
+                       sg_num++;
+                       skip = 0;
+               } else
+                       skip -= skb_headlen(skb);
+
+               for (i = 0; sg_len < crd->crd_len &&
+                                       i < skb_shinfo(skb)->nr_frags &&
+                                       sg_num < SCATTERLIST_MAX; i++) {
+                       if (skip < skb_shinfo(skb)->frags[i].size) {
+                               len = skb_shinfo(skb)->frags[i].size - skip;
+                               if (len + sg_len > crd->crd_len)
+                                       len = crd->crd_len - sg_len;
+                               sg_set_page(&req->sg[sg_num],
+                                       skb_shinfo(skb)->frags[i].page,
+                                       len,
+                                       skb_shinfo(skb)->frags[i].page_offset + skip);
+                               sg_len += len;
+                               sg_num++;
+                               skip = 0;
+                       } else
+                               skip -= skb_shinfo(skb)->frags[i].size;
                }
        } else if (crp->crp_flags & CRYPTO_F_IOV) {
-               uiop = (struct uio *) crp->crp_buf;
-               if (uiop->uio_iovcnt > SCATTERLIST_MAX) {
-                       printk("%s,%d: %d uio_iovcnt > SCATTERLIST_MAX", __FILE__, __LINE__,
-                                       uiop->uio_iovcnt);
-                       goto done;
+               int len;
+
+               sg_len = 0;
+               for (sg_num = 0; sg_len < crd->crd_len &&
+                               sg_num < uiop->uio_iovcnt &&
+                               sg_num < SCATTERLIST_MAX; sg_num++) {
+                       if (skip <= uiop->uio_iov[sg_num].iov_len) {
+                               len = uiop->uio_iov[sg_num].iov_len - skip;
+                               if (len + sg_len > crd->crd_len)
+                                       len = crd->crd_len - sg_len;
+                               sg_set_page(&req->sg[sg_num],
+                                       virt_to_page(uiop->uio_iov[sg_num].iov_base+skip),
+                                       len,
+                                       offset_in_page(uiop->uio_iov[sg_num].iov_base+skip));
+                               sg_len += len;
+                               skip = 0;
+                       } else 
+                               skip -= uiop->uio_iov[sg_num].iov_len;
                }
+       } else {
+               sg_len = (crp->crp_ilen - skip);
+               if (sg_len > crd->crd_len)
+                       sg_len = crd->crd_len;
+               sg_set_page(&req->sg[0], virt_to_page(crp->crp_buf + skip),
+                       sg_len, offset_in_page(crp->crp_buf + skip));
+               sg_num = 1;
        }
 
-       /* Go through crypto descriptors, processing as we go */
-       for (crd = crp->crp_desc; crd; crd = crd->crd_next) {
-               /*
-                * Find the crypto context.
-                *
-                * XXX Note that the logic here prevents us from having
-                * XXX the same algorithm multiple times in a session
-                * XXX (or rather, we can but it won't give us the right
-                * XXX results). To do that, we'd need some way of differentiating
-                * XXX between the various instances of an algorithm (so we can
-                * XXX locate the correct crypto context).
-                */
-               for (sw = swcr_sessions[lid]; sw && sw->sw_alg != crd->crd_alg;
-                               sw = sw->sw_next)
-                       ;
+       switch (sw->sw_type & SW_TYPE_ALG_AMASK) {
+
+#ifdef HAVE_AHASH
+       case SW_TYPE_AHMAC:
+       case SW_TYPE_AHASH:
+               {
+               int ret;
 
-               /* No such context ? */
-               if (sw == NULL) {
+               /* check we have room for the result */
+               if (crp->crp_ilen - crd->crd_inject < sw->u.hmac.sw_mlen) {
+                       dprintk("cryptosoft: EINVAL crp_ilen=%d, len=%d, inject=%d "
+                                       "digestsize=%d\n", crp->crp_ilen, crd->crd_skip + sg_len,
+                                       crd->crd_inject, sw->u.hmac.sw_mlen);
+                       crp->crp_etype = EINVAL;
+                       goto done;
+               }
+
+               req->crypto_req =
+                               ahash_request_alloc(__crypto_ahash_cast(sw->sw_tfm),GFP_KERNEL);
+               if (!req->crypto_req) {
+                       crp->crp_etype = ENOMEM;
+                       dprintk("%s,%d: ENOMEM ahash_request_alloc", __FILE__, __LINE__);
+                       goto done;
+               }
+
+               ahash_request_set_callback(req->crypto_req,
+                               CRYPTO_TFM_REQ_MAY_BACKLOG, swcr_process_callback, req);
+
+               memset(req->result, 0, sizeof(req->result));
+
+               if (sw->sw_type & SW_TYPE_AHMAC)
+                       crypto_ahash_setkey(__crypto_ahash_cast(sw->sw_tfm),
+                                       sw->u.hmac.sw_key, sw->u.hmac.sw_klen);
+               ahash_request_set_crypt(req->crypto_req, req->sg, req->result, sg_len);
+               ret = crypto_ahash_digest(req->crypto_req);
+               switch (ret) {
+               case -EINPROGRESS:
+               case -EBUSY:
+                       return;
+    &nb