AMCC Crypto4xx Device Driver v4]
Subsystems (3)
PATCH 1/1 AMCC Crypto4xx Device Driver v4]
Hi,
This patch add canyonlands support.
Few performance optimizations:
Redesigned the crypto4xx_build_pd(), which now calculate number of scatter and gather descriptors need before taking them. Instead take these descriptors one by one, now we take them together. Doing this way the time needed to be locked is much reduced. This function now supports aad which needed by future release.
Introduced functions to setup the commands registers. This is to reduce code space and increase the likelihood for cache hit.
Eliminate the need for dynamically alloc memory for request context, by cache up per packet 'sa' in pd_uinfo.
Response to previous review:
Removed not needed includes.
Avoid using if else flow as Kim suggested in few places. lineup multiline parameters of functions. removed change log.
We still include crypto/internal/hash.h because we support 'ahash' which need that header file.
We still have the wrapper function for alg_init(), because we will have multiple algorithm files and external define for the struct ...alg[] does not work.
Thanks
James
--- arch/powerpc/boot/dts/canyonlands.dts | 7 + arch/powerpc/boot/dts/kilauea.dts | 7 + drivers/crypto/Kconfig | 9 + drivers/crypto/Makefile | 1 + drivers/crypto/amcc/Makefile | 2 + drivers/crypto/amcc/crypto4xx_alg.c | 353 +++++++++ drivers/crypto/amcc/crypto4xx_core.c | 1316 +++++++++++++++++++++++++++++++ drivers/crypto/amcc/crypto4xx_core.h | 190 +++++ drivers/crypto/amcc/crypto4xx_reg_def.h | 283 +++++++ drivers/crypto/amcc/crypto4xx_sa.c | 108 +++ drivers/crypto/amcc/crypto4xx_sa.h | 245 ++++++ 11 files changed, 2521 insertions(+), 0 deletions(-) create mode 100644 drivers/crypto/amcc/Makefile create mode 100644 drivers/crypto/amcc/crypto4xx_alg.c create mode 100644 drivers/crypto/amcc/crypto4xx_core.c create mode 100644 drivers/crypto/amcc/crypto4xx_core.h create mode 100644 drivers/crypto/amcc/crypto4xx_reg_def.h create mode 100644 drivers/crypto/amcc/crypto4xx_sa.c create mode 100644 drivers/crypto/amcc/crypto4xx_sa.h
arch/powerpc/boot/dts/canyonlands.dts +7 -0
@@ -116,6 +116,13 @@ dcr-reg = <0x010 0x002>; }; + CRYPTO: crypto@180000 { + compatible = "amcc,ppc460ex-crypto", "amcc,ppc4xx-crypto"; + reg = <4 0x00180000 0x80400>; + interrupt-parent = <&UIC0>; + interrupts = <0x1d 0x4>; + }; + MAL0: mcmal { compatible = "ibm,mcmal-460ex", "ibm,mcmal2"; dcr-reg = <0x180 0x062>;
arch/powerpc/boot/dts/kilauea.dts +7 -0
@@ -94,6 +94,13 @@ dcr-reg = <0x010 0x002>; }; + CRYPTO: crypto@ef700000 { + compatible = "amcc,ppc405ex-crypto", "amcc,ppc4xx-crypto"; + reg = <0xef700000 0x80400>; + interrupt-parent = <&UIC0>; + interrupts = <0x17 0x2>; + }; + MAL0: mcmal { compatible = "ibm,mcmal-405ex", "ibm,mcmal2"; dcr-reg = <0x180 0x062>;
drivers/crypto/Kconfig +9 -0
@@ -200,4 +200,13 @@ config CRYPTO_DEV_IXP4XX help Driver for the IXP4xx NPE crypto engine. +config CRYPTO_DEV_PPC4XX + tristate "Driver AMCC PPC4xx crypto accelerator" + depends on PPC && 4xx + select CRYPTO_HASH + select CRYPTO_ALGAPI + select CRYPTO_BLKCIPHER + help + This option allows you to have support for AMCC crypto acceleration. + endif # CRYPTO_HW
drivers/crypto/Makefile +1 -0
@@ -4,3 +4,4 @@ obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o +obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
drivers/crypto/amcc/Makefile new file +2 -0
@@ -0,0 +1,2 @@ +obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += crypto4xx.o +crypto4xx-objs := crypto4xx_core.o crypto4xx_alg.o crypto4xx_sa.o
drivers/crypto/amcc/crypto4xx_alg.c new file +353 -0
353 lines not on this page · raw message
drivers/crypto/amcc/crypto4xx_core.c new file +1316 -0
1,316 lines not on this page · raw message
drivers/crypto/amcc/crypto4xx_core.h new file +190 -0
190 lines not on this page · raw message
drivers/crypto/amcc/crypto4xx_reg_def.h new file +283 -0
283 lines not on this page · raw message
drivers/crypto/amcc/crypto4xx_sa.c new file +108 -0
108 lines not on this page · raw message
drivers/crypto/amcc/crypto4xx_sa.h new file +245 -0
245 lines not on this page · raw message
Quoted 30 lines · On Tue, 02 Dec 2008 14:17:12 -0800 James Hsiao <[email protected]> wrote:
Hi,
This patch add canyonlands support.
Few performance optimizations:
Redesigned thecrypto4xx_build_pd(), which now calculate number of scatter and gather descriptors need before taking them. Instead take these descriptors one by one, now we take them together. Doing this way the time needed to be locked is much reduced. This function now supports aad which needed by future release.Introduced functions to setup the commands registers. This is to reduce code space and increase the likelihood for cache hit.
Eliminate the need for dynamically alloc memory for request context, by cache up per packet 'sa' in
pd_uinfo.Response to previous review:
Removed not needed includes.
Avoid using if else flow as Kim suggested in few places. lineup multiline parameters of functions. removed change log.We still include
crypto/internal/hash.hbecause we support 'ahash' which need that header file.We still have the wrapper function for
alg_init(), because we will have multiple algorithm files and external define for the struct ...alg[] does not work.
Quoted 6 lines
Thanks
JamesSigned-off-by James Hsiao <[email protected]>---
just fyi, all text above the --- line above is part of the git commit message - might want to help the maintainers by cleaning up things like "Hi" etc. and moving them here, below the --- line.
arch/powerpc/boot/dts/canyonlands.dts line 123
Quoted 13 lines
arch/powerpc/boot/dts/canyonlands.dts +5
-0@@ -116,6 +116,13 @@ dcr-reg = <0x010 0x002>; }; + CRYPTO: crypto@180000 { + compatible = "amcc,ppc460ex-crypto", "amcc,ppc4xx-crypto"; + reg = <4 0x00180000 0x80400>; + interrupt-parent = <&UIC0>; + interrupts = <0x1d 0x4>;
that's odd, according to the current canyonlands.dts, irq 0x1d is already assigned to UART2 (and the request_irq this driver makes doesn't specify a shared flag).
Quoted 5 lines
drivers/crypto/amcc/crypto4xx_alg.c new file +0
-0
drivers/crypto/amcc/crypto4xx_alg.c line 97
Quoted 9 lines
drivers/crypto/amcc/crypto4xx_alg.c new file +9
-0+static int crypto4xx_decrypt (struct ablkcipher_request *req) +{ +struct crypto4xx_ctx *ctx =crypto_tfm_ctx (req->base.tfm); + + ctx->direction =DIR_INBOUND ; + ctx->hash_final =0 ; + ctx->is_hash =0 ; + ctx->pd_ctl =1 ; + ctx->direction =DIR_INBOUND ;
duplicate assignment
drivers/crypto/amcc/crypto4xx_core.c line 763
Quoted 4 lines
drivers/crypto/amcc/crypto4xx_core.c +3
-0+/* +* derive number of elements in scatterlist +* Shamlessly copy from talitos.c
this fn should one day be refactored and placed in lib/scatterlist.c - all the crypto drivers currently implement their own version.
drivers/crypto/amcc/crypto4xx_core.c line 773
Quoted 10 lines
+ */
drivers/crypto/amcc/crypto4xx_core.c +9
-0+static int get_sg_count (struct scatterlist *sg_list,int nbytes) +{ +struct scatterlist *sg = sg_list; +int sg_nents =0 ; + +while (nbytes) { + sg_nents++; +if (sg->length > nbytes) +break ;
this is slightly different - this condition shouldn't need checking here - see [1] below..
Quoted 26 lines
drivers/crypto/amcc/crypto4xx_core.c +25
-0+ nbytes -= sg->length; + sg =sg_next (sg); + } + +return sg_nents; +} +u32 crypto4xx_build_pd (struct crypto_async_request *req, +struct crypto4xx_ctx *ctx, +struct scatterlist *src, +struct scatterlist *dst, +unsigned int datalen, +struct scatterlist *assoc, +u32 aad_len,void *iv,u32 iv_len) +{ +struct crypto4xx_device *dev = ctx->dev; +dma_addr_t addr, pd_dma, sd_dma, gd_dma; +struct dynamic_sa_ctl *sa; +struct scatterlist *sg; +struct scatterlist *aad; +struct ce_gd *gd; +struct ce_pd *pd; +u32 num_gd, num_sd; +u32 fst_gd =0xffffffff ; +u32 fst_sd =0xffffffff ; +u32 pd_entry;
drivers/crypto/amcc/crypto4xx_core.c line 825
Quoted 10 lines
drivers/crypto/amcc/crypto4xx_core.c +10
-0+struct pd_uinfo *pd_uinfo =NULL ; +unsigned int nbytes = datalen, idx; +unsigned int aadlen =0 ; +unsigned int ivlen =0 ; +u32 gd_idx =0 ; + +/* figure how many gd is needed */ +if (aad_len) { + num_gd =get_sg_count (assoc, aad_len) + +get_sg_count (src, datalen);
this is dead code - aad_len is never non-zero - is there some code missing from crypto4xx_alg.c? Also, IIRC, assoc is a superset of src, so I believe something like num_gd = get_sg_count(assoc, aad_len + datalen) would work better - this should also permit removal of the nbytes reached check in [1] in get_sg_count.
drivers/crypto/amcc/crypto4xx_core.c line 854
Quoted 10 lines
drivers/crypto/amcc/crypto4xx_core.c +10
-0+/* +* The follow section of code needs to be protected +* The gather ring and scatter ring needs to be consecutive +* In case of run out of any kind of descriptor, the descriptor +* already got must be return the original place. So, here +* we disable interrupt. +* We found using irq disable here is 30% faster than +* using preempt disable. +*/ +local_irq_disable ();
the 30% increase in speed shouldn't be for the preemption-off case, and not using preempt_{en,dis}able adds latency outside of this driver for users that have preemption turned on (local_irq_enable doesn't check to reschedule). To satisfy memory barrier (completely absent here), preemption, and smp requirements, use of spin_lock methods is recommended. Performance shouldn't be negatively affected if CONFIG_SMP and CONFIG_PREEMPT are turned off.
Quoted 4 lines
drivers/crypto/amcc/crypto4xx_core.c +4
-0+while (nbytes) { + sd_idx =get_next_sd (sd_idx); + sd =crypto4xx_get_sdp (dev, &sd_dma, sd_idx); +/* setup scatter descriptor */
drivers/crypto/amcc/crypto4xx_core.c line 1029
Quoted 10 lines
drivers/crypto/amcc/crypto4xx_core.c +10
-0+ sd->ctl.done =0 ; + sd->ctl.rdy =1 ; +if (nbytes >=PPC4XX_SD_BUFFER_SIZE ) + nbytes -=PPC4XX_SD_BUFFER_SIZE ; +else +/* +* SD entry can hold PPC4XX_SD_BUFFER_SIZE, +* which is more than nbytes, so done. +*/ + nbytes =0 ;
alignment
Quoted 10 lines
drivers/crypto/amcc/crypto4xx_core.c +10
-0+/** +* Algorithm Registration Functions +*/ +static int crypto4xx_alg_init (struct crypto_tfm *tfm) +{ +struct crypto_alg *alg = tfm->__crt_alg; +struct crypto4xx_alg *amcc_alg =crypto_alg_to_crypto4xx_alg (alg); +struct crypto4xx_ctx *ctx =crypto_tfm_ctx (tfm); + + ctx->dev = amcc_alg->dev;
drivers/crypto/amcc/crypto4xx_core.c line 1063
Quoted 10 lines
drivers/crypto/amcc/crypto4xx_core.c +10
-0+ ctx->sa_in =NULL ; + ctx->sa_out =NULL ; + ctx->sa_in_dma_addr =0 ; + ctx->sa_out_dma_addr =0 ; + ctx->sa_len =0 ; + +if (alg->cra_type == &crypto_ablkcipher_type) + tfm->crt_ablkcipher.reqsize =sizeof (struct crypto4xx_ctx ); +else if (alg->cra_type == &crypto_ahash_type) + tfm->crt_ahash.reqsize =sizeof (struct crypto4xx_ctx );
insert blank line here please
drivers/crypto/amcc/crypto4xx_core.c line 1069
Quoted 6 lines
drivers/crypto/amcc/crypto4xx_core.c +6
-0+return 0 ; +} + +static void crypto4xx_alg_exit (struct crypto_tfm *tfm) +{ +struct crypto4xx_ctx *ctx =crypto_tfm_ctx (tfm);
insert blank line here please
Quoted 1 line
drivers/crypto/amcc/crypto4xx_core.c +1
-0+crypto4xx_free_sa (ctx);
<snip>
drivers/crypto/amcc/crypto4xx_core.c line 1251
Quoted 7 lines
drivers/crypto/amcc/crypto4xx_core.c +7
-0+printk (KERN_INFO "Loaded AMCC PPC4xx crypto " +"accelerator driver v%s\n" ,PPC4XX_SEC_VERSION_STR ); + +return rc; + +err_start_dev: +err_register_alg:
no redundant labels, please.
also, if some algorithms succeed registration, and then one fails, this code doesn't handle the de-registration of the ones that succeeded - not nice if the user wants this situation to revert to s/w crypto.
drivers/crypto/amcc/crypto4xx_core.c line 1255
Quoted 4 lines
drivers/crypto/amcc/crypto4xx_core.c +4
-0+iounmap (core_dev->dev->ce_base); +free_irq (core_dev->irq, dev); +irq_dispose_mapping (core_dev->irq); +err_request_irq:
irq_dispose_mapping goes here
drivers/crypto/amcc/crypto4xx_core.c line 1257
Quoted 2 lines
drivers/crypto/amcc/crypto4xx_core.c +2
-0+err_build_sdr: +crypto4xx_destroy_gdr (core_dev->dev);
destroy_sdr, no?
Quoted 1 line
+err_build_gdr:
destroy_gdr should probably go here
drivers/crypto/amcc/crypto4xx_core.c line 1266
Quoted 8 lines
drivers/crypto/amcc/crypto4xx_core.c +8
-0+err_build_pdr: +crypto4xx_destroy_pdr (core_dev->dev); +kfree (core_dev->dev); +err_alloc_dev: +kfree (core_dev); + +return rc; +}
missing at least a tasklet_kill and an iounmap
drivers/crypto/amcc/crypto4xx_core.h
Quoted 8 lines
drivers/crypto/amcc/crypto4xx_core.h new file +1
-0@@ -0,0 +1,190 @@ +extern struct crypto4xx_core_device lsec_core;
this appears to be leftovers from prior versions of this patch
Quoted 1 line
+extern struct
crypto_algcrypto4xx_basic_alg[];
afaict, this isn't necessary either
drivers/crypto/amcc/crypto4xx_reg_def.h line 5
Quoted 11 lines
drivers/crypto/amcc/crypto4xx_reg_def.h new file +5
-0@@ -0,0 +1,283 @@ +#ifndef __CRYPTO_ENGINE_REG_DEF_H__ +#define __CRYPTO_ENGINE_REG_DEF_H__ + +/* CRYPTO_ENGINE Register offset */ +#define CRYPTO_ENGINE_DESCRIPTOR 0x00000000
can we s/CRYPTO_ENGINE_/PPC4XX_/g (or CRYPTO4XX_?) so as to not pollute CRYPTO_ namespace?
Thanks,
Kim
Quoted 8 lines · Kim Phillips
Quoted 8 lines
(quoted diff) +0
-0
b/arch/powerpc/boot/dts/canyonlands.dtsindex 79fe412..b0f0096 100644arch/powerpc/boot/dts/canyonlands.dts +0
-0@@ -116,6 +116,13 @@ dcr-reg = <0x010 0x002>; };
Quoted 9 lines
arch/powerpc/boot/dts/canyonlands.dts line 123
Quoted 5 lines
arch/powerpc/boot/dts/canyonlands.dts +5
-0+ CRYPTO: crypto@180000 { + compatible = "amcc,ppc460ex-crypto", "amcc,ppc4xx-crypto"; + reg = <4 0x00180000 0x80400>; + interrupt-parent = <&UIC0>; + interrupts = <0x1d 0x4>;that's odd, according to the current
canyonlands.dts, irq0x1dis already assigned to UART2 (and therequest_irqthis driver makes doesn't specify a shared flag).
UART2 is using irq 0x1d from UIC1. Using 0x1d/UIC0 is correct for Security EIP-94 according to the latest users manual. No sharing needed.
Best regards,
Stefan
Quoted 19 lines · On Fri, 5 Dec 2008 06:41:13 +0100 Stefan Roese <[email protected]> wrote:
Quoted 8 lines · Kim Phillips
Quoted 8 lines
(quoted diff) +0
-0
b/arch/powerpc/boot/dts/canyonlands.dtsindex 79fe412..b0f0096 100644arch/powerpc/boot/dts/canyonlands.dts +0
-0@@ -116,6 +116,13 @@ dcr-reg = <0x010 0x002>; };Quoted 9 lines
arch/powerpc/boot/dts/canyonlands.dts line 123
Quoted 5 lines
arch/powerpc/boot/dts/canyonlands.dts +5
-0+ CRYPTO: crypto@180000 { + compatible = "amcc,ppc460ex-crypto", "amcc,ppc4xx-crypto"; + reg = <4 0x00180000 0x80400>; + interrupt-parent = <&UIC0>; + interrupts = <0x1d 0x4>;that's odd, according to the current
canyonlands.dts, irq0x1dis already assigned to UART2 (and therequest_irqthis driver makes doesn't specify a shared flag).
Quoted 2 lines
UART2 is using irq
0x1dfrom UIC1. Using 0x1d/UIC0 is correct for Security EIP-94 according to the latest users manual. No sharing needed.
ok, I didn't notice the machine had four interrupt controllers (!), thanks.
Kim
Hi Kim,
I try to address some of the comments. I am not mentioning things that I agree with you.
drivers/crypto/amcc/crypto4xx_core.c line 773
Quoted 10 lines
+ */
drivers/crypto/amcc/crypto4xx_core.c new file +9
-0+static int get_sg_count (struct scatterlist *sg_list,int nbytes) +{ +struct scatterlist *sg = sg_list; +int sg_nents =0 ; + +while (nbytes) { + sg_nents++; +if (sg->length > nbytes) +break ;
this is slightly different - this condition shouldn't need checking here - see [1] below..
drivers/crypto/amcc/crypto4xx_core.c line 779
Quoted 6 lines
drivers/crypto/amcc/crypto4xx_core.c new file +6
-0+ nbytes -= sg->length; + sg =sg_next (sg); + } + +return sg_nents; +}
Without the check, nbytes could become negative. The aead test case with .np will crash(ie. gcm tests), those test have sg->length > nbytes.
About aad_len, we didn't release code that use aad yet. We did test this function with aad_len none zero(the gcm tests).
About the irq_disable or spin_lock.
The driver could be used by a kernel thread and esp4 at same time. As I know process is preemptable. When the driver is used by a process it is possible to be preempted. The hardware require scatter/gather descriptor to be consecutive. So, if the process get a gather descriptor and then it is preempted by another process or esp4 which get a gather descriptor and return to the original process, the origianl process could get a non consecutive gather descriptor.
So, if spin_lock is recommended then I have to use spin_lock_irq_save, which use irq_disable too. Do you think that is acceptable?
Thanks and regards
James
Quoted 6 lines · On Fri, 05 Dec 2008 15:24:11 -0800 James Hsiao <[email protected]> wrote:
Without the check, nbytes could become negative. The aead test case with .np will crash(ie. gcm tests), those test have
sg->length> nbytes.About
aad_len, we didn't release code that use aad yet. We did test this function withaad_lennone zero(the gcm tests).
ok - btw, it would be nice if these submissions were more self-consistent, that way we could see how aad_len is being assigned.
Quoted 10 lines
About the
irq_disableorspin_lock.
The driver could be used by a kernel thread and esp4 at same time. As I know process is preemptable. When the driver is used by a process it is possible to be preempted. The hardware require scatter/gather descriptor to be consecutive. So, if the process get a gather descriptor and then it is preempted by another process or esp4 which get a gather descriptor and return to the original process, the origianl process could get a non consecutive gather descriptor.
So, ifspin_lockis recommended then I have to usespin_lock_irq_save, which useirq_disabletoo. Do you think that is acceptable?
yes.
Thanks,
Kim
Hi Kim,
Quoted 10 lines
drivers/crypto/amcc/crypto4xx_core.c line 825
Quoted 4 lines
drivers/crypto/amcc/crypto4xx_core.c new file +4
-0+/* figure how many gd is needed */ +if (aad_len) { + num_gd =get_sg_count (assoc, aad_len) + +get_sg_count (src, datalen);this is dead code -
aad_lenis never non-zero - is there some code missing fromcrypto4xx_alg.c? Also, IIRC, assoc is a superset of src, so I believe something likenum_gd=get_sg_count(assoc, aad_len + datalen)would work better - this should also permit removal of the nbytes reached check in [1] inget_sg_count.
For the get num_gd, assoc and src are two different scatter_lists. One for the packet and one for the aad, so, it makes more sense to me to count them seperately. Yes?
The way to driver pass aad and aad_len is from crypto4xx_build_pd. This aad support will be used in the future. Do you want me to remover from the current release? The reason I have it in, is to avoid too much code change for the future release.
Thanks
James
Quoted 11 lines · On Mon, 08 Dec 2008 13:55:07 -0800 James Hsiao <[email protected]> wrote:
Quoted 10 lines
drivers/crypto/amcc/crypto4xx_core.c line 825
Quoted 4 lines
drivers/crypto/amcc/crypto4xx_core.c new file +4
-0+/* figure how many gd is needed */ +if (aad_len) { + num_gd =get_sg_count (assoc, aad_len) + +get_sg_count (src, datalen);this is dead code -
aad_lenis never non-zero - is there some code missing fromcrypto4xx_alg.c? Also, IIRC, assoc is a superset of src, so I believe something likenum_gd=get_sg_count(assoc, aad_len + datalen)would work better - this should also permit removal of the nbytes reached check in [1] inget_sg_count.
Quoted 3 lines
For the get
num_gd, assoc and src are two differentscatter_lists. One for the packet and one for the aad, so, it makes more sense to me to count them seperately. Yes?
ok I looked it up - they are disjoint sg lists, so, yes, you're right.
Quoted 4 lines
The way to driver pass aad and
aad_lenis fromcrypto4xx_build_pd. This aad support will be used in the future. Do you want me to remover from the current release? The reason I have it in, is to avoid too much code change for the future release.
removing it would definitely make both this and any forthcoming aead patches more on topic and thus easier to review (plus I suspect adding unused code to the kernel is generally frowned upon...)
Kim
Ok, I will remove the unused code for now.
Thanks
James
On Mon, 2008-12-08 at 18:35 -0600, Kim Phillips wrote: