#include <crypto/algapi.h>
#include <crypto/aes.h>
+#include <crypto/des.h>
#include <crypto/sha.h>
#include <crypto/aead.h>
#include <crypto/authenc.h>
unsigned int exec_units;
unsigned int desc_types;
+ /* SEC Compatibility info */
+ unsigned long features;
+
/* next channel to be assigned next incoming descriptor */
atomic_t last_chan;
+ /* per-channel number of requests pending in channel h/w fifo */
+ atomic_t *submit_count;
+
/* per-channel request fifo */
struct talitos_request **fifo;
/* request callback tasklet */
struct tasklet_struct done_task;
- struct tasklet_struct error_task;
/* list of registered algorithms */
struct list_head alg_list;
struct hwrng rng;
};
+/* .features flag */
+#define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001
+#define TALITOS_FTR_HW_AUTH_CHECK 0x00000002
+
/*
* map virtual single (contiguous) pointer to h/w descriptor pointer
*/
setbits32(priv->reg + TALITOS_CCCR_LO(ch), TALITOS_CCCR_LO_CDWE |
TALITOS_CCCR_LO_CDIE);
+ /* and ICCR writeback, if available */
+ if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
+ setbits32(priv->reg + TALITOS_CCCR_LO(ch),
+ TALITOS_CCCR_LO_IWSE);
+
return 0;
}
setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT);
setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);
+ /* disable integrity check error interrupts (use writeback instead) */
+ if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
+ setbits32(priv->reg + TALITOS_MDEUICR_LO,
+ TALITOS_MDEUICR_LO_ICE);
+
return 0;
}
spin_lock_irqsave(&priv->head_lock[ch], flags);
- head = priv->head[ch];
- request = &priv->fifo[ch][head];
-
- if (request->desc) {
- /* request queue is full */
+ if (!atomic_inc_not_zero(&priv->submit_count[ch])) {
+ /* h/w fifo is full */
spin_unlock_irqrestore(&priv->head_lock[ch], flags);
return -EAGAIN;
}
+ head = priv->head[ch];
+ request = &priv->fifo[ch][head];
+
/* map descriptor and save caller data */
request->dma_desc = dma_map_single(dev, desc, sizeof(*desc),
DMA_BIDIRECTIONAL);
priv->tail[ch] = (tail + 1) & (priv->fifo_len - 1);
spin_unlock_irqrestore(&priv->tail_lock[ch], flags);
+
+ atomic_dec(&priv->submit_count[ch]);
+
saved_req.callback(dev, saved_req.desc, saved_req.context,
status);
/* channel may resume processing in single desc error case */
for (ch = 0; ch < priv->num_channels; ch++)
flush_channel(dev, ch, 0, 0);
+
+ /* At this point, all completed channels have been processed.
+ * Unmask done interrupts for channels completed later on.
+ */
+ setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT);
+ setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);
}
/*
/*
* recover from error interrupts
*/
-static void talitos_error(unsigned long data)
+static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
{
struct device *dev = (struct device *)data;
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
int ch, error, reset_dev = 0, reset_ch = 0;
- u32 isr, isr_lo, v, v_lo;
-
- isr = in_be32(priv->reg + TALITOS_ISR);
- isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);
+ u32 v, v_lo;
for (ch = 0; ch < priv->num_channels; ch++) {
/* skip channels without errors */
isr = in_be32(priv->reg + TALITOS_ISR);
isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);
-
- /* ack */
+ /* Acknowledge interrupt */
out_be32(priv->reg + TALITOS_ICR, isr);
out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);
if (unlikely((isr & ~TALITOS_ISR_CHDONE) || isr_lo))
- talitos_error((unsigned long)data);
+ talitos_error((unsigned long)data, isr, isr_lo);
else
- if (likely(isr & TALITOS_ISR_CHDONE))
+ if (likely(isr & TALITOS_ISR_CHDONE)) {
+ /* mask further done interrupts. */
+ clrbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_DONE);
+ /* done_task will unmask done interrupts at exit */
tasklet_schedule(&priv->done_task);
+ }
return (isr || isr_lo) ? IRQ_HANDLED : IRQ_NONE;
}
*/
#define TALITOS_CRA_PRIORITY 3000
#define TALITOS_MAX_KEY_SIZE 64
-#define TALITOS_MAX_AUTH_SIZE 20
-#define TALITOS_AES_MIN_BLOCK_SIZE 16
-#define TALITOS_AES_IV_LENGTH 16
+#define TALITOS_MAX_IV_LENGTH 16 /* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */
+
+#define MD5_DIGEST_SIZE 16
struct talitos_ctx {
struct device *dev;
__be32 desc_hdr_template;
u8 key[TALITOS_MAX_KEY_SIZE];
- u8 iv[TALITOS_AES_IV_LENGTH];
+ u8 iv[TALITOS_MAX_IV_LENGTH];
unsigned int keylen;
unsigned int enckeylen;
unsigned int authkeylen;
unsigned int authsize;
};
-static int aes_cbc_sha1_hmac_authenc_setauthsize(struct crypto_aead *authenc,
+static int aead_authenc_setauthsize(struct crypto_aead *authenc,
unsigned int authsize)
{
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
return 0;
}
-static int aes_cbc_sha1_hmac_authenc_setkey(struct crypto_aead *authenc,
+static int aead_authenc_setkey(struct crypto_aead *authenc,
const u8 *key, unsigned int keylen)
{
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
/* copy the generated ICV to dst */
if (edesc->dma_len) {
icvdata = &edesc->link_tbl[edesc->src_nents +
- edesc->dst_nents + 1];
+ edesc->dst_nents + 2];
sg = sg_last(areq->dst, edesc->dst_nents);
memcpy((char *)sg_virt(sg) + sg->length - ctx->authsize,
icvdata, ctx->authsize);
aead_request_complete(areq, err);
}
-static void ipsec_esp_decrypt_done(struct device *dev,
+static void ipsec_esp_decrypt_swauth_done(struct device *dev,
struct talitos_desc *desc, void *context,
int err)
{
/* auth check */
if (edesc->dma_len)
icvdata = &edesc->link_tbl[edesc->src_nents +
- edesc->dst_nents + 1];
+ edesc->dst_nents + 2];
else
icvdata = &edesc->link_tbl[0];
aead_request_complete(req, err);
}
+static void ipsec_esp_decrypt_hwauth_done(struct device *dev,
+ struct talitos_desc *desc, void *context,
+ int err)
+{
+ struct aead_request *req = context;
+ struct ipsec_esp_edesc *edesc =
+ container_of(desc, struct ipsec_esp_edesc, desc);
+
+ ipsec_esp_unmap(dev, edesc, req);
+
+ /* check ICV auth status */
+ if (!err)
+ if ((desc->hdr_lo & DESC_HDR_LO_ICCR1_MASK) !=
+ DESC_HDR_LO_ICCR1_PASS)
+ err = -EBADMSG;
+
+ kfree(edesc);
+
+ aead_request_complete(req, err);
+}
+
/*
* convert scatterlist to SEC h/w link table format
* stop at cryptlen bytes
*/
-static void sg_to_link_tbl(struct scatterlist *sg, int sg_count,
+static int sg_to_link_tbl(struct scatterlist *sg, int sg_count,
int cryptlen, struct talitos_ptr *link_tbl_ptr)
{
- while (cryptlen > 0) {
+ int n_sg = sg_count;
+
+ while (n_sg--) {
link_tbl_ptr->ptr = cpu_to_be32(sg_dma_address(sg));
link_tbl_ptr->len = cpu_to_be16(sg_dma_len(sg));
link_tbl_ptr->j_extent = 0;
sg = sg_next(sg);
}
- /* adjust (decrease) last entry's len to cryptlen */
+ /* adjust (decrease) last one (or two) entry's len to cryptlen */
link_tbl_ptr--;
+ while (be16_to_cpu(link_tbl_ptr->len) <= (-cryptlen)) {
+ /* Empty this entry, and move to previous one */
+ cryptlen += be16_to_cpu(link_tbl_ptr->len);
+ link_tbl_ptr->len = 0;
+ sg_count--;
+ link_tbl_ptr--;
+ }
link_tbl_ptr->len = cpu_to_be16(be16_to_cpu(link_tbl_ptr->len)
+ cryptlen);
/* tag end of link table */
link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
+
+ return sg_count;
}
/*
unsigned int cryptlen = areq->cryptlen;
unsigned int authsize = ctx->authsize;
unsigned int ivsize;
- int sg_count;
+ int sg_count, ret;
+ int sg_link_tbl_len;
/* hmac key */
map_single_talitos_ptr(dev, &desc->ptr[0], ctx->authkeylen, &ctx->key,
if (sg_count == 1) {
desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src));
} else {
- sg_to_link_tbl(areq->src, sg_count, cryptlen,
- &edesc->link_tbl[0]);
- desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
- desc->ptr[4].ptr = cpu_to_be32(edesc->dma_link_tbl);
- dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
- edesc->dma_len, DMA_BIDIRECTIONAL);
+ sg_link_tbl_len = cryptlen;
+
+ if ((edesc->desc.hdr & DESC_HDR_MODE1_MDEU_CICV) &&
+ (edesc->desc.hdr & DESC_HDR_MODE0_ENCRYPT) == 0) {
+ sg_link_tbl_len = cryptlen + authsize;
+ }
+ sg_count = sg_to_link_tbl(areq->src, sg_count, sg_link_tbl_len,
+ &edesc->link_tbl[0]);
+ if (sg_count > 1) {
+ desc->ptr[4].j_extent |= DESC_PTR_LNKTBL_JUMP;
+ desc->ptr[4].ptr = cpu_to_be32(edesc->dma_link_tbl);
+ dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
+ edesc->dma_len, DMA_BIDIRECTIONAL);
+ } else {
+ /* Only one segment now, so no link tbl needed */
+ desc->ptr[4].ptr = cpu_to_be32(sg_dma_address(areq->src));
+ }
}
/* cipher out */
desc->ptr[5].ptr = cpu_to_be32(sg_dma_address(areq->dst));
} else {
struct talitos_ptr *link_tbl_ptr =
- &edesc->link_tbl[edesc->src_nents];
- struct scatterlist *sg;
+ &edesc->link_tbl[edesc->src_nents + 1];
desc->ptr[5].ptr = cpu_to_be32((struct talitos_ptr *)
edesc->dma_link_tbl +
- edesc->src_nents);
- if (areq->src == areq->dst) {
- memcpy(link_tbl_ptr, &edesc->link_tbl[0],
- edesc->src_nents * sizeof(struct talitos_ptr));
- } else {
- sg_to_link_tbl(areq->dst, sg_count, cryptlen,
- link_tbl_ptr);
- }
- link_tbl_ptr += sg_count - 1;
-
- /* handle case where sg_last contains the ICV exclusively */
- sg = sg_last(areq->dst, edesc->dst_nents);
- if (sg->length == ctx->authsize)
- link_tbl_ptr--;
+ edesc->src_nents + 1);
+ sg_count = sg_to_link_tbl(areq->dst, sg_count, cryptlen,
+ link_tbl_ptr);
+ /* Add an entry to the link table for ICV data */
+ link_tbl_ptr += sg_count - 1;
link_tbl_ptr->j_extent = 0;
+ sg_count++;
link_tbl_ptr++;
link_tbl_ptr->j_extent = DESC_PTR_LNKTBL_RETURN;
link_tbl_ptr->len = cpu_to_be16(authsize);
link_tbl_ptr->ptr = cpu_to_be32((struct talitos_ptr *)
edesc->dma_link_tbl +
edesc->src_nents +
- edesc->dst_nents + 1);
+ edesc->dst_nents + 2);
desc->ptr[5].j_extent |= DESC_PTR_LNKTBL_JUMP;
dma_sync_single_for_device(ctx->dev, edesc->dma_link_tbl,
map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 0,
DMA_FROM_DEVICE);
- return talitos_submit(dev, desc, callback, areq);
+ ret = talitos_submit(dev, desc, callback, areq);
+ if (ret != -EINPROGRESS) {
+ ipsec_esp_unmap(dev, edesc, areq);
+ kfree(edesc);
+ }
+ return ret;
}
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
struct ipsec_esp_edesc *edesc;
int src_nents, dst_nents, alloc_len, dma_len;
+ gfp_t flags = areq->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL :
+ GFP_ATOMIC;
if (areq->cryptlen + ctx->authsize > TALITOS_MAX_DATA_LEN) {
dev_err(ctx->dev, "cryptlen exceeds h/w max limit\n");
dst_nents = src_nents;
} else {
dst_nents = sg_count(areq->dst, areq->cryptlen + ctx->authsize);
- dst_nents = (dst_nents == 1) ? 0 : src_nents;
+ dst_nents = (dst_nents == 1) ? 0 : dst_nents;
}
/*
* allocate space for base edesc plus the link tables,
- * allowing for a separate entry for the generated ICV (+ 1),
+ * allowing for two separate entries for ICV and generated ICV (+ 2),
* and the ICV data itself
*/
alloc_len = sizeof(struct ipsec_esp_edesc);
if (src_nents || dst_nents) {
- dma_len = (src_nents + dst_nents + 1) *
+ dma_len = (src_nents + dst_nents + 2) *
sizeof(struct talitos_ptr) + ctx->authsize;
alloc_len += dma_len;
} else {
alloc_len += icv_stashing ? ctx->authsize : 0;
}
- edesc = kmalloc(alloc_len, GFP_DMA);
+ edesc = kmalloc(alloc_len, GFP_DMA | flags);
if (!edesc) {
dev_err(ctx->dev, "could not allocate edescriptor\n");
return ERR_PTR(-ENOMEM);
return edesc;
}
-static int aes_cbc_sha1_hmac_authenc_encrypt(struct aead_request *req)
+static int aead_authenc_encrypt(struct aead_request *req)
{
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
return PTR_ERR(edesc);
/* set encrypt */
- edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_AESU_ENC;
+ edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_encrypt_done);
}
-static int aes_cbc_sha1_hmac_authenc_decrypt(struct aead_request *req)
+
+
+static int aead_authenc_decrypt(struct aead_request *req)
{
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
struct talitos_ctx *ctx = crypto_aead_ctx(authenc);
unsigned int authsize = ctx->authsize;
+ struct talitos_private *priv = dev_get_drvdata(ctx->dev);
struct ipsec_esp_edesc *edesc;
struct scatterlist *sg;
void *icvdata;
if (IS_ERR(edesc))
return PTR_ERR(edesc);
- /* stash incoming ICV for later cmp with ICV generated by the h/w */
- if (edesc->dma_len)
- icvdata = &edesc->link_tbl[edesc->src_nents +
- edesc->dst_nents + 1];
- else
- icvdata = &edesc->link_tbl[0];
+ if ((priv->features & TALITOS_FTR_HW_AUTH_CHECK) &&
+ (((!edesc->src_nents && !edesc->dst_nents) ||
+ priv->features & TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT))) {
+
+ /* decrypt and check the ICV */
+ edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND |
+ DESC_HDR_MODE1_MDEU_CICV;
+
+ /* reset integrity check result bits */
+ edesc->desc.hdr_lo = 0;
- sg = sg_last(req->src, edesc->src_nents ? : 1);
+ return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_hwauth_done);
- memcpy(icvdata, (char *)sg_virt(sg) + sg->length - ctx->authsize,
- ctx->authsize);
+ } else {
+
+ /* Have to check the ICV with software */
- /* decrypt */
- edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
+ edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
- return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_done);
+ /* stash incoming ICV for later cmp with ICV generated by the h/w */
+ if (edesc->dma_len)
+ icvdata = &edesc->link_tbl[edesc->src_nents +
+ edesc->dst_nents + 2];
+ else
+ icvdata = &edesc->link_tbl[0];
+
+ sg = sg_last(req->src, edesc->src_nents ? : 1);
+
+ memcpy(icvdata, (char *)sg_virt(sg) + sg->length - ctx->authsize,
+ ctx->authsize);
+
+ return ipsec_esp(edesc, req, NULL, 0, ipsec_esp_decrypt_swauth_done);
+ }
}
-static int aes_cbc_sha1_hmac_authenc_givencrypt(
+static int aead_authenc_givencrypt(
struct aead_givcrypt_request *req)
{
struct aead_request *areq = &req->areq;
return PTR_ERR(edesc);
/* set encrypt */
- edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_AESU_ENC;
+ edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
memcpy(req->giv, ctx->iv, crypto_aead_ivsize(authenc));
+ /* avoid consecutive packets going out with same IV */
+ *(__be64 *)req->giv ^= cpu_to_be64(req->seq);
return ipsec_esp(edesc, areq, req->giv, req->seq,
ipsec_esp_encrypt_done);
/* single-pass ipsec_esp descriptor */
{
.name = "authenc(hmac(sha1),cbc(aes))",
- .driver_name = "authenc(hmac(sha1-talitos),cbc(aes-talitos))",
- .blocksize = TALITOS_AES_MIN_BLOCK_SIZE,
+ .driver_name = "authenc-hmac-sha1-cbc-aes-talitos",
+ .blocksize = AES_BLOCK_SIZE,
.aead = {
- .setkey = aes_cbc_sha1_hmac_authenc_setkey,
- .setauthsize = aes_cbc_sha1_hmac_authenc_setauthsize,
- .encrypt = aes_cbc_sha1_hmac_authenc_encrypt,
- .decrypt = aes_cbc_sha1_hmac_authenc_decrypt,
- .givencrypt = aes_cbc_sha1_hmac_authenc_givencrypt,
+ .setkey = aead_authenc_setkey,
+ .setauthsize = aead_authenc_setauthsize,
+ .encrypt = aead_authenc_encrypt,
+ .decrypt = aead_authenc_decrypt,
+ .givencrypt = aead_authenc_givencrypt,
.geniv = "<built-in>",
- .ivsize = TALITOS_AES_IV_LENGTH,
- .maxauthsize = TALITOS_MAX_AUTH_SIZE,
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA1_DIGEST_SIZE,
},
.desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
DESC_HDR_SEL0_AESU |
DESC_HDR_MODE1_MDEU_INIT |
DESC_HDR_MODE1_MDEU_PAD |
DESC_HDR_MODE1_MDEU_SHA1_HMAC,
+ },
+ {
+ .name = "authenc(hmac(sha1),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-sha1-cbc-3des-talitos",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .aead = {
+ .setkey = aead_authenc_setkey,
+ .setauthsize = aead_authenc_setauthsize,
+ .encrypt = aead_authenc_encrypt,
+ .decrypt = aead_authenc_decrypt,
+ .givencrypt = aead_authenc_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = SHA1_DIGEST_SIZE,
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
+ DESC_HDR_SEL0_DEU |
+ DESC_HDR_MODE0_DEU_CBC |
+ DESC_HDR_MODE0_DEU_3DES |
+ DESC_HDR_SEL1_MDEUA |
+ DESC_HDR_MODE1_MDEU_INIT |
+ DESC_HDR_MODE1_MDEU_PAD |
+ DESC_HDR_MODE1_MDEU_SHA1_HMAC,
+ },
+ {
+ .name = "authenc(hmac(sha256),cbc(aes))",
+ .driver_name = "authenc-hmac-sha256-cbc-aes-talitos",
+ .blocksize = AES_BLOCK_SIZE,
+ .aead = {
+ .setkey = aead_authenc_setkey,
+ .setauthsize = aead_authenc_setauthsize,
+ .encrypt = aead_authenc_encrypt,
+ .decrypt = aead_authenc_decrypt,
+ .givencrypt = aead_authenc_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = SHA256_DIGEST_SIZE,
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
+ DESC_HDR_SEL0_AESU |
+ DESC_HDR_MODE0_AESU_CBC |
+ DESC_HDR_SEL1_MDEUA |
+ DESC_HDR_MODE1_MDEU_INIT |
+ DESC_HDR_MODE1_MDEU_PAD |
+ DESC_HDR_MODE1_MDEU_SHA256_HMAC,
+ },
+ {
+ .name = "authenc(hmac(sha256),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-sha256-cbc-3des-talitos",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .aead = {
+ .setkey = aead_authenc_setkey,
+ .setauthsize = aead_authenc_setauthsize,
+ .encrypt = aead_authenc_encrypt,
+ .decrypt = aead_authenc_decrypt,
+ .givencrypt = aead_authenc_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = SHA256_DIGEST_SIZE,
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
+ DESC_HDR_SEL0_DEU |
+ DESC_HDR_MODE0_DEU_CBC |
+ DESC_HDR_MODE0_DEU_3DES |
+ DESC_HDR_SEL1_MDEUA |
+ DESC_HDR_MODE1_MDEU_INIT |
+ DESC_HDR_MODE1_MDEU_PAD |
+ DESC_HDR_MODE1_MDEU_SHA256_HMAC,
+ },
+ {
+ .name = "authenc(hmac(md5),cbc(aes))",
+ .driver_name = "authenc-hmac-md5-cbc-aes-talitos",
+ .blocksize = AES_BLOCK_SIZE,
+ .aead = {
+ .setkey = aead_authenc_setkey,
+ .setauthsize = aead_authenc_setauthsize,
+ .encrypt = aead_authenc_encrypt,
+ .decrypt = aead_authenc_decrypt,
+ .givencrypt = aead_authenc_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
+ DESC_HDR_SEL0_AESU |
+ DESC_HDR_MODE0_AESU_CBC |
+ DESC_HDR_SEL1_MDEUA |
+ DESC_HDR_MODE1_MDEU_INIT |
+ DESC_HDR_MODE1_MDEU_PAD |
+ DESC_HDR_MODE1_MDEU_MD5_HMAC,
+ },
+ {
+ .name = "authenc(hmac(md5),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-md5-cbc-3des-talitos",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .aead = {
+ .setkey = aead_authenc_setkey,
+ .setauthsize = aead_authenc_setauthsize,
+ .encrypt = aead_authenc_encrypt,
+ .decrypt = aead_authenc_decrypt,
+ .givencrypt = aead_authenc_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_IPSEC_ESP |
+ DESC_HDR_SEL0_DEU |
+ DESC_HDR_MODE0_DEU_CBC |
+ DESC_HDR_MODE0_DEU_3DES |
+ DESC_HDR_SEL1_MDEUA |
+ DESC_HDR_MODE1_MDEU_INIT |
+ DESC_HDR_MODE1_MDEU_PAD |
+ DESC_HDR_MODE1_MDEU_MD5_HMAC,
}
};
ctx->desc_hdr_template = talitos_alg->desc_hdr_template;
/* random first IV */
- get_random_bytes(ctx->iv, TALITOS_AES_IV_LENGTH);
+ get_random_bytes(ctx->iv, TALITOS_MAX_IV_LENGTH);
return 0;
}
return ret;
}
-static int __devexit talitos_remove(struct of_device *ofdev)
+static int talitos_remove(struct of_device *ofdev)
{
struct device *dev = &ofdev->dev;
struct talitos_private *priv = dev_get_drvdata(dev);
if (hw_supports(dev, DESC_HDR_SEL0_RNG))
talitos_unregister_rng(dev);
+ kfree(priv->submit_count);
kfree(priv->tail);
kfree(priv->head);
}
tasklet_kill(&priv->done_task);
- tasklet_kill(&priv->error_task);
iounmap(priv->reg);
priv->ofdev = ofdev;
tasklet_init(&priv->done_task, talitos_done, (unsigned long)dev);
- tasklet_init(&priv->error_task, talitos_error, (unsigned long)dev);
+
+ INIT_LIST_HEAD(&priv->alg_list);
priv->irq = irq_of_parse_and_map(np, 0);
goto err_out;
}
- of_node_put(np);
- np = NULL;
+ if (of_device_is_compatible(np, "fsl,sec3.0"))
+ priv->features |= TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT;
+
+ if (of_device_is_compatible(np, "fsl,sec2.1"))
+ priv->features |= TALITOS_FTR_HW_AUTH_CHECK;
priv->head_lock = kmalloc(sizeof(spinlock_t) * priv->num_channels,
GFP_KERNEL);
}
}
+ priv->submit_count = kmalloc(sizeof(atomic_t) * priv->num_channels,
+ GFP_KERNEL);
+ if (!priv->submit_count) {
+ dev_err(dev, "failed to allocate fifo submit count space\n");
+ err = -ENOMEM;
+ goto err_out;
+ }
+ for (i = 0; i < priv->num_channels; i++)
+ atomic_set(&priv->submit_count[i], -(priv->chfifo_len - 1));
+
priv->head = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
priv->tail = kzalloc(sizeof(int) * priv->num_channels, GFP_KERNEL);
if (!priv->head || !priv->tail) {
}
/* register crypto algorithms the device supports */
- INIT_LIST_HEAD(&priv->alg_list);
-
for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
struct talitos_crypto_alg *t_alg;
err_out:
talitos_remove(ofdev);
- if (np)
- of_node_put(np);
return err;
}
.name = "talitos",
.match_table = talitos_match,
.probe = talitos_probe,
- .remove = __devexit_p(talitos_remove),
+ .remove = talitos_remove,
};
static int __init talitos_init(void)