Merge branch 'stable/bug.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git...
[pandora-kernel.git] / drivers / crypto / talitos.c
index 854e263..8a0bb41 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * talitos - Freescale Integrated Security Engine (SEC) device driver
  *
- * Copyright (c) 2008-2010 Freescale Semiconductor, Inc.
+ * Copyright (c) 2008-2011 Freescale Semiconductor, Inc.
  *
  * Scatterlist Crypto API glue code copied from files with the following:
  * Copyright (c) 2006-2007 Herbert Xu <herbert@gondor.apana.org.au>
@@ -282,6 +282,7 @@ static int init_device(struct device *dev)
 /**
  * talitos_submit - submits a descriptor to the device for processing
  * @dev:       the SEC device to be used
+ * @ch:                the SEC device channel to be used
  * @desc:      the descriptor to be processed by the device
  * @callback:  whom to call when processing is complete
  * @context:   a handle for use by caller (optional)
@@ -290,7 +291,7 @@ static int init_device(struct device *dev)
  * callback must check err and feedback in descriptor header
  * for device processing status.
  */
-static int talitos_submit(struct device *dev, struct talitos_desc *desc,
+static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
                          void (*callback)(struct device *dev,
                                           struct talitos_desc *desc,
                                           void *context, int error),
@@ -298,15 +299,9 @@ static int talitos_submit(struct device *dev, struct talitos_desc *desc,
 {
        struct talitos_private *priv = dev_get_drvdata(dev);
        struct talitos_request *request;
-       unsigned long flags, ch;
+       unsigned long flags;
        int head;
 
-       /* select done notification */
-       desc->hdr |= DESC_HDR_DONE_NOTIFY;
-
-       /* emulate SEC's round-robin channel fifo polling scheme */
-       ch = atomic_inc_return(&priv->last_chan) & (priv->num_channels - 1);
-
        spin_lock_irqsave(&priv->chan[ch].head_lock, flags);
 
        if (!atomic_inc_not_zero(&priv->chan[ch].submit_count)) {
@@ -706,6 +701,7 @@ static void talitos_unregister_rng(struct device *dev)
 
 struct talitos_ctx {
        struct device *dev;
+       int ch;
        __be32 desc_hdr_template;
        u8 key[TALITOS_MAX_KEY_SIZE];
        u8 iv[TALITOS_MAX_IV_LENGTH];
@@ -1117,7 +1113,7 @@ static int ipsec_esp(struct talitos_edesc *edesc, struct aead_request *areq,
        map_single_talitos_ptr(dev, &desc->ptr[6], ivsize, ctx->iv, 0,
                               DMA_FROM_DEVICE);
 
-       ret = talitos_submit(dev, desc, callback, areq);
+       ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
        if (ret != -EINPROGRESS) {
                ipsec_esp_unmap(dev, edesc, areq);
                kfree(edesc);
@@ -1382,22 +1378,11 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *cipher,
                             const u8 *key, unsigned int keylen)
 {
        struct talitos_ctx *ctx = crypto_ablkcipher_ctx(cipher);
-       struct ablkcipher_alg *alg = crypto_ablkcipher_alg(cipher);
-
-       if (keylen > TALITOS_MAX_KEY_SIZE)
-               goto badkey;
-
-       if (keylen < alg->min_keysize || keylen > alg->max_keysize)
-               goto badkey;
 
        memcpy(&ctx->key, key, keylen);
        ctx->keylen = keylen;
 
        return 0;
-
-badkey:
-       crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
-       return -EINVAL;
 }
 
 static void common_nonsnoop_unmap(struct device *dev,
@@ -1433,7 +1418,6 @@ static void ablkcipher_done(struct device *dev,
 
 static int common_nonsnoop(struct talitos_edesc *edesc,
                           struct ablkcipher_request *areq,
-                          u8 *giv,
                           void (*callback) (struct device *dev,
                                             struct talitos_desc *desc,
                                             void *context, int error))
@@ -1453,7 +1437,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
 
        /* cipher iv */
        ivsize = crypto_ablkcipher_ivsize(cipher);
-       map_single_talitos_ptr(dev, &desc->ptr[1], ivsize, giv ?: areq->info, 0,
+       map_single_talitos_ptr(dev, &desc->ptr[1], ivsize, areq->info, 0,
                               DMA_TO_DEVICE);
 
        /* cipher key */
@@ -1524,7 +1508,7 @@ static int common_nonsnoop(struct talitos_edesc *edesc,
        to_talitos_ptr(&desc->ptr[6], 0);
        desc->ptr[6].j_extent = 0;
 
-       ret = talitos_submit(dev, desc, callback, areq);
+       ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
        if (ret != -EINPROGRESS) {
                common_nonsnoop_unmap(dev, edesc, areq);
                kfree(edesc);
@@ -1556,7 +1540,7 @@ static int ablkcipher_encrypt(struct ablkcipher_request *areq)
        /* set encrypt */
        edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_MODE0_ENCRYPT;
 
-       return common_nonsnoop(edesc, areq, NULL, ablkcipher_done);
+       return common_nonsnoop(edesc, areq, ablkcipher_done);
 }
 
 static int ablkcipher_decrypt(struct ablkcipher_request *areq)
@@ -1572,7 +1556,7 @@ static int ablkcipher_decrypt(struct ablkcipher_request *areq)
 
        edesc->desc.hdr = ctx->desc_hdr_template | DESC_HDR_DIR_INBOUND;
 
-       return common_nonsnoop(edesc, areq, NULL, ablkcipher_done);
+       return common_nonsnoop(edesc, areq, ablkcipher_done);
 }
 
 static void common_nonsnoop_hash_unmap(struct device *dev,
@@ -1703,7 +1687,7 @@ static int common_nonsnoop_hash(struct talitos_edesc *edesc,
        /* last DWORD empty */
        desc->ptr[6] = zero_entry;
 
-       ret = talitos_submit(dev, desc, callback, areq);
+       ret = talitos_submit(dev, ctx->ch, desc, callback, areq);
        if (ret != -EINPROGRESS) {
                common_nonsnoop_hash_unmap(dev, edesc, areq);
                kfree(edesc);
@@ -2244,6 +2228,7 @@ static int talitos_cra_init(struct crypto_tfm *tfm)
        struct crypto_alg *alg = tfm->__crt_alg;
        struct talitos_crypto_alg *talitos_alg;
        struct talitos_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct talitos_private *priv;
 
        if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_AHASH)
                talitos_alg = container_of(__crypto_ahash_alg(alg),
@@ -2256,9 +2241,17 @@ static int talitos_cra_init(struct crypto_tfm *tfm)
        /* update context with ptr to dev */
        ctx->dev = talitos_alg->dev;
 
+       /* assign SEC channel to tfm in round-robin fashion */
+       priv = dev_get_drvdata(ctx->dev);
+       ctx->ch = atomic_inc_return(&priv->last_chan) &
+                 (priv->num_channels - 1);
+
        /* copy descriptor header template value */
        ctx->desc_hdr_template = talitos_alg->algt.desc_hdr_template;
 
+       /* select done notification */
+       ctx->desc_hdr_template |= DESC_HDR_DONE_NOTIFY;
+
        return 0;
 }