Hi Patrick.

On Thu, Feb 21, 2008 at 04:29:54PM +0100, Patrick McHardy ([EMAIL PROTECTED]) 
wrote:
> Unfortunately still no luck. I got an error from ablkcipher_add()
> because of this condition:

...

> - further down it uses dst->length in the last while-loop,
>   which seems to need a similar change.

Does this patch  (on top of unpatched tree) helps?
I can not test it with real hardware, since I'm sicking at home with
laptop only, but I already know how to make a test case for this problem
without complex setup, so if it does not work, I will investigate it
further as soon as be able to move to office with testing machine :)

diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c
index dfbf24c..7807ca9 100644
--- a/drivers/crypto/hifn_795x.c
+++ b/drivers/crypto/hifn_795x.c
@@ -1464,7 +1464,7 @@ static int ablkcipher_walk(struct ablkcipher_request *req,
                crypto_ablkcipher_alignmask(crypto_ablkcipher_reqtfm(req));
        struct scatterlist *src, *dst, *t;
        void *daddr;
-       unsigned int nbytes = req->nbytes, offset, copy, diff;
+       unsigned int nbytes = req->nbytes, offset, copy, diff, nb;
        int idx, tidx, err;
 
        tidx = idx = 0;
@@ -1475,11 +1475,13 @@ static int ablkcipher_walk(struct ablkcipher_request 
*req,
 
                src = &req->src[idx];
                dst = &req->dst[idx];
+               
+               nb = min(nbytes, src->length);
 
                dprintk("\n%s: slen: %u, dlen: %u, soff: %u, doff: %u, offset: 
%u, "
-                               "blocksize: %u, nbytes: %u.\n",
+                               "blocksize: %u, nbytes: %u, nb: %u.\n",
                                __func__, src->length, dst->length, src->offset,
-                               dst->offset, offset, blocksize, nbytes);
+                               dst->offset, offset, blocksize, nbytes, nb);
 
                if (src->length & (blocksize - 1) ||
                                src->offset & (alignmask - 1) ||
@@ -1492,7 +1494,7 @@ static int ablkcipher_walk(struct ablkcipher_request *req,
                        t = &w->cache[idx];
 
                        daddr = kmap_atomic(sg_page(t), KM_SOFTIRQ0);
-                       err = ablkcipher_add(daddr, &dlen, src, slen, &nbytes);
+                       err = ablkcipher_add(daddr, &dlen, src, nb, &nbytes);
                        if (err < 0)
                                goto err_out_unmap;
 
@@ -1501,7 +1503,7 @@ static int ablkcipher_walk(struct ablkcipher_request *req,
                        copy = slen & ~(blocksize - 1);
                        diff = slen & (blocksize - 1);
 
-                       if (dlen < nbytes) {
+                       if (dlen < nb) {
                                /*
                                 * Destination page does not have enough space
                                 * to put there additional blocksized chunk,
@@ -1510,17 +1512,17 @@ static int ablkcipher_walk(struct ablkcipher_request 
*req,
                                 *      t->length = (slen & ~(blocksize - 1));
                                 * and increase number of bytes to be processed
                                 * in next chunk:
-                                *      nbytes += diff;
+                                *      nb += diff;
                                 */
-                               nbytes += diff;
+                               nb += diff;
 
                                /*
                                 * Temporary of course...
                                 * Kick author if you will catch this one.
                                 */
                                printk(KERN_ERR "%s: dlen: %u, nbytes: %u,"
-                                       "slen: %u, offset: %u.\n",
-                                       __func__, dlen, nbytes, slen, offset);
+                                       "slen: %u, offset: %u, nb: %u.\n",
+                                       __func__, dlen, nbytes, slen, offset, 
nb);
                                printk(KERN_ERR "%s: please contact author to 
fix this "
                                        "issue, generally you should not catch "
                                        "this path under any condition but who "
@@ -1528,11 +1530,11 @@ static int ablkcipher_walk(struct ablkcipher_request 
*req,
                                        "Thank you.\n", __func__);
                                BUG();
                        } else {
-                               copy += diff + nbytes;
+                               copy += diff + nb;
 
                                src = &req->src[idx];
 
-                               err = ablkcipher_add(daddr + slen, &dlen, src, 
nbytes, &nbytes);
+                               err = ablkcipher_add(daddr + slen, &dlen, src, 
nb, &nbytes);
                                if (err < 0)
                                        goto err_out_unmap;
 
@@ -1544,7 +1546,7 @@ static int ablkcipher_walk(struct ablkcipher_request *req,
 
                        kunmap_atomic(daddr, KM_SOFTIRQ0);
                } else {
-                       nbytes -= src->length;
+                       nbytes -= nb;
                        idx++;
                }
 
@@ -1564,7 +1566,7 @@ static int hifn_setup_session(struct ablkcipher_request 
*req)
        struct hifn_device *dev = ctx->dev;
        struct page *spage, *dpage;
        unsigned long soff, doff, flags;
-       unsigned int nbytes = req->nbytes, idx = 0, len;
+       unsigned int nbytes = req->nbytes, idx = 0, len, nb;
        int err = -EINVAL, sg_num;
        struct scatterlist *src, *dst, *t;
        unsigned blocksize =
@@ -1581,6 +1583,8 @@ static int hifn_setup_session(struct ablkcipher_request 
*req)
                src = &req->src[idx];
                dst = &req->dst[idx];
 
+               nb = min(src->length, nbytes);
+
                if (src->length & (blocksize - 1) ||
                                src->offset & (alignmask - 1) ||
                                dst->length & (blocksize - 1) ||
@@ -1588,7 +1592,7 @@ static int hifn_setup_session(struct ablkcipher_request 
*req)
                        ctx->walk.flags |= ASYNC_FLAGS_MISALIGNED;
                }
 
-               nbytes -= src->length;
+               nbytes -= nb;
                idx++;
        }
 
@@ -1602,6 +1606,10 @@ static int hifn_setup_session(struct ablkcipher_request 
*req)
        idx = 0;
 
        sg_num = ablkcipher_walk(req, &ctx->walk);
+       if (sg_num < 0) {
+               err = sg_num;
+               goto err_out_exit;
+       }
 
        atomic_set(&ctx->sg_num, sg_num);
 
@@ -1632,10 +1640,12 @@ static int hifn_setup_session(struct ablkcipher_request 
*req)
 
                        len = dst->length;
                }
+               
+               nb = min(len, nbytes);
 
                idx++;
 
-               err = hifn_setup_dma(dev, spage, soff, dpage, doff, nbytes,
+               err = hifn_setup_dma(dev, spage, soff, dpage, doff, nb,
                                req, ctx);
                if (err)
                        goto err_out;
@@ -1652,7 +1662,7 @@ err_out:
        spin_unlock_irqrestore(&dev->lock, flags);
 err_out_exit:
        if (err && printk_ratelimit())
-               dprintk("%s: iv: %p [%d], key: %p [%d], mode: %u, op: %u, "
+               printk("%s: iv: %p [%d], key: %p [%d], mode: %u, op: %u, "
                                "type: %u, err: %d.\n",
                        dev->name, ctx->iv, ctx->ivsize,
                        ctx->key, ctx->keysize,
@@ -1786,7 +1796,7 @@ static void hifn_process_ready(struct ablkcipher_request 
*req, int error)
                BUG();
 
        if (atomic_dec_and_test(&ctx->sg_num)) {
-               unsigned int nbytes = req->nbytes;
+               unsigned int nbytes = req->nbytes, nb;
                int idx = 0, err;
                struct scatterlist *dst, *t;
                void *saddr;
@@ -1796,6 +1806,8 @@ static void hifn_process_ready(struct ablkcipher_request 
*req, int error)
                                t = &ctx->walk.cache[idx];
                                dst = &req->dst[idx];
 
+                               nb = min(nbytes, dst->length);
+
                                dprintk("\n%s: sg_page(t): %p, t->length: %u, "
                                        "sg_page(dst): %p, dst->length: %u, "
                                        "nbytes: %u.\n",
@@ -1803,7 +1815,7 @@ static void hifn_process_ready(struct ablkcipher_request 
*req, int error)
                                        sg_page(dst), dst->length, nbytes);
 
                                if (!t->length) {
-                                       nbytes -= dst->length;
+                                       nbytes -= nb;
                                        idx++;
                                        continue;
                                }
@@ -1811,7 +1823,7 @@ static void hifn_process_ready(struct ablkcipher_request 
*req, int error)
                                saddr = kmap_atomic(sg_page(t), KM_IRQ1);
 
                                err = ablkcipher_get(saddr, &t->length, 
t->offset,
-                                               dst, nbytes, &nbytes);
+                                               dst, nb, &nbytes);
                                if (err < 0) {
                                        kunmap_atomic(saddr, KM_IRQ1);
                                        break;


-- 
        Evgeniy Polyakov
-
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to