diff options
author | Patrick McHardy <kaber@trash.net> | 2008-11-24 08:59:25 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2008-12-24 19:01:51 -0500 |
commit | 75741a034024f146ba5431602f3ad33a5df8363c (patch) | |
tree | dff26a78946ac5c51f445f17cef3d69235ba04a9 | |
parent | 09fbf7c0f24176ef3b450c590f220ed8033dd2c3 (diff) |
crypto: hifn_795x - Fix DMA setup
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: Evgeniy Polyakov <zbr@ioremap.net>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | drivers/crypto/hifn_795x.c | 165 |
1 files changed, 81 insertions, 84 deletions
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index 2969ea99f7c7..27b8af983aae 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c | |||
@@ -662,7 +662,6 @@ struct hifn_context | |||
662 | unsigned int keysize, ivsize; | 662 | unsigned int keysize, ivsize; |
663 | u8 op, type, mode, unused; | 663 | u8 op, type, mode, unused; |
664 | struct ablkcipher_walk walk; | 664 | struct ablkcipher_walk walk; |
665 | atomic_t sg_num; | ||
666 | }; | 665 | }; |
667 | 666 | ||
668 | #define crypto_alg_to_hifn(a) container_of(a, struct hifn_crypto_alg, alg) | 667 | #define crypto_alg_to_hifn(a) container_of(a, struct hifn_crypto_alg, alg) |
@@ -1284,7 +1283,7 @@ err_out: | |||
1284 | } | 1283 | } |
1285 | 1284 | ||
1286 | static int hifn_setup_src_desc(struct hifn_device *dev, struct page *page, | 1285 | static int hifn_setup_src_desc(struct hifn_device *dev, struct page *page, |
1287 | unsigned int offset, unsigned int size) | 1286 | unsigned int offset, unsigned int size, int last) |
1288 | { | 1287 | { |
1289 | struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt; | 1288 | struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt; |
1290 | int idx; | 1289 | int idx; |
@@ -1296,12 +1295,12 @@ static int hifn_setup_src_desc(struct hifn_device *dev, struct page *page, | |||
1296 | 1295 | ||
1297 | dma->srcr[idx].p = __cpu_to_le32(addr); | 1296 | dma->srcr[idx].p = __cpu_to_le32(addr); |
1298 | dma->srcr[idx].l = __cpu_to_le32(size | HIFN_D_VALID | | 1297 | dma->srcr[idx].l = __cpu_to_le32(size | HIFN_D_VALID | |
1299 | HIFN_D_MASKDONEIRQ | HIFN_D_LAST); | 1298 | HIFN_D_MASKDONEIRQ | (last ? HIFN_D_LAST : 0)); |
1300 | 1299 | ||
1301 | if (++idx == HIFN_D_SRC_RSIZE) { | 1300 | if (++idx == HIFN_D_SRC_RSIZE) { |
1302 | dma->srcr[idx].l = __cpu_to_le32(HIFN_D_VALID | | 1301 | dma->srcr[idx].l = __cpu_to_le32(HIFN_D_VALID | |
1303 | HIFN_D_JUMP | | 1302 | HIFN_D_JUMP | HIFN_D_MASKDONEIRQ | |
1304 | HIFN_D_MASKDONEIRQ | HIFN_D_LAST); | 1303 | (last ? HIFN_D_LAST : 0)); |
1305 | idx = 0; | 1304 | idx = 0; |
1306 | } | 1305 | } |
1307 | 1306 | ||
@@ -1342,7 +1341,7 @@ static void hifn_setup_res_desc(struct hifn_device *dev) | |||
1342 | } | 1341 | } |
1343 | 1342 | ||
1344 | static void hifn_setup_dst_desc(struct hifn_device *dev, struct page *page, | 1343 | static void hifn_setup_dst_desc(struct hifn_device *dev, struct page *page, |
1345 | unsigned offset, unsigned size) | 1344 | unsigned offset, unsigned size, int last) |
1346 | { | 1345 | { |
1347 | struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt; | 1346 | struct hifn_dma *dma = (struct hifn_dma *)dev->desc_virt; |
1348 | int idx; | 1347 | int idx; |
@@ -1353,12 +1352,12 @@ static void hifn_setup_dst_desc(struct hifn_device *dev, struct page *page, | |||
1353 | idx = dma->dsti; | 1352 | idx = dma->dsti; |
1354 | dma->dstr[idx].p = __cpu_to_le32(addr); | 1353 | dma->dstr[idx].p = __cpu_to_le32(addr); |
1355 | dma->dstr[idx].l = __cpu_to_le32(size | HIFN_D_VALID | | 1354 | dma->dstr[idx].l = __cpu_to_le32(size | HIFN_D_VALID | |
1356 | HIFN_D_MASKDONEIRQ | HIFN_D_LAST); | 1355 | HIFN_D_MASKDONEIRQ | (last ? HIFN_D_LAST : 0)); |
1357 | 1356 | ||
1358 | if (++idx == HIFN_D_DST_RSIZE) { | 1357 | if (++idx == HIFN_D_DST_RSIZE) { |
1359 | dma->dstr[idx].l = __cpu_to_le32(HIFN_D_VALID | | 1358 | dma->dstr[idx].l = __cpu_to_le32(HIFN_D_VALID | |
1360 | HIFN_D_JUMP | HIFN_D_MASKDONEIRQ | | 1359 | HIFN_D_JUMP | HIFN_D_MASKDONEIRQ | |
1361 | HIFN_D_LAST); | 1360 | (last ? HIFN_D_LAST : 0)); |
1362 | idx = 0; | 1361 | idx = 0; |
1363 | } | 1362 | } |
1364 | dma->dsti = idx; | 1363 | dma->dsti = idx; |
@@ -1370,16 +1369,47 @@ static void hifn_setup_dst_desc(struct hifn_device *dev, struct page *page, | |||
1370 | } | 1369 | } |
1371 | } | 1370 | } |
1372 | 1371 | ||
1373 | static int hifn_setup_dma(struct hifn_device *dev, struct page *spage, unsigned int soff, | 1372 | static int hifn_setup_dma(struct hifn_device *dev, struct hifn_context *ctx, |
1374 | struct page *dpage, unsigned int doff, unsigned int nbytes, void *priv, | 1373 | struct scatterlist *src, struct scatterlist *dst, |
1375 | struct hifn_context *ctx) | 1374 | unsigned int nbytes, void *priv) |
1376 | { | 1375 | { |
1377 | dprintk("%s: spage: %p, soffset: %u, dpage: %p, doffset: %u, nbytes: %u, priv: %p, ctx: %p.\n", | 1376 | struct scatterlist *t; |
1377 | struct page *spage, *dpage; | ||
1378 | unsigned int soff, doff; | ||
1379 | unsigned int n, len; | ||
1380 | |||
1381 | t = &ctx->walk.cache[0]; | ||
1382 | n = nbytes; | ||
1383 | while (n) { | ||
1384 | if (t->length) { | ||
1385 | spage = dpage = sg_page(t); | ||
1386 | soff = doff = 0; | ||
1387 | len = t->length; | ||
1388 | } else { | ||
1389 | spage = sg_page(src); | ||
1390 | soff = src->offset; | ||
1391 | |||
1392 | dpage = sg_page(dst); | ||
1393 | doff = dst->offset; | ||
1394 | |||
1395 | len = dst->length; | ||
1396 | } | ||
1397 | len = min(len, n); | ||
1398 | |||
1399 | dprintk("%s: spage: %p, soffset: %u, dpage: %p, doffset: %u, " | ||
1400 | "nbytes: %u, priv: %p, ctx: %p.\n", | ||
1378 | dev->name, spage, soff, dpage, doff, nbytes, priv, ctx); | 1401 | dev->name, spage, soff, dpage, doff, nbytes, priv, ctx); |
1379 | 1402 | ||
1380 | hifn_setup_src_desc(dev, spage, soff, nbytes); | 1403 | hifn_setup_src_desc(dev, spage, soff, len, n - len == 0); |
1404 | hifn_setup_dst_desc(dev, dpage, doff, len, n - len == 0); | ||
1405 | |||
1406 | src++; | ||
1407 | dst++; | ||
1408 | t++; | ||
1409 | n -= len; | ||
1410 | } | ||
1411 | |||
1381 | hifn_setup_cmd_desc(dev, ctx, priv, nbytes); | 1412 | hifn_setup_cmd_desc(dev, ctx, priv, nbytes); |
1382 | hifn_setup_dst_desc(dev, dpage, doff, nbytes); | ||
1383 | hifn_setup_res_desc(dev); | 1413 | hifn_setup_res_desc(dev); |
1384 | return 0; | 1414 | return 0; |
1385 | } | 1415 | } |
@@ -1560,11 +1590,10 @@ static int hifn_setup_session(struct ablkcipher_request *req) | |||
1560 | { | 1590 | { |
1561 | struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm); | 1591 | struct hifn_context *ctx = crypto_tfm_ctx(req->base.tfm); |
1562 | struct hifn_device *dev = ctx->dev; | 1592 | struct hifn_device *dev = ctx->dev; |
1563 | struct page *spage, *dpage; | 1593 | unsigned long dlen, flags; |
1564 | unsigned long soff, doff, dlen, flags; | 1594 | unsigned int nbytes = req->nbytes, idx = 0; |
1565 | unsigned int nbytes = req->nbytes, idx = 0, len; | ||
1566 | int err = -EINVAL, sg_num; | 1595 | int err = -EINVAL, sg_num; |
1567 | struct scatterlist *src, *dst, *t; | 1596 | struct scatterlist *dst; |
1568 | 1597 | ||
1569 | if (ctx->iv && !ctx->ivsize && ctx->mode != ACRYPTO_MODE_ECB) | 1598 | if (ctx->iv && !ctx->ivsize && ctx->mode != ACRYPTO_MODE_ECB) |
1570 | goto err_out_exit; | 1599 | goto err_out_exit; |
@@ -1589,15 +1618,11 @@ static int hifn_setup_session(struct ablkcipher_request *req) | |||
1589 | return err; | 1618 | return err; |
1590 | } | 1619 | } |
1591 | 1620 | ||
1592 | nbytes = req->nbytes; | ||
1593 | idx = 0; | ||
1594 | |||
1595 | sg_num = ablkcipher_walk(req, &ctx->walk); | 1621 | sg_num = ablkcipher_walk(req, &ctx->walk); |
1596 | if (sg_num < 0) { | 1622 | if (sg_num < 0) { |
1597 | err = sg_num; | 1623 | err = sg_num; |
1598 | goto err_out_exit; | 1624 | goto err_out_exit; |
1599 | } | 1625 | } |
1600 | atomic_set(&ctx->sg_num, sg_num); | ||
1601 | 1626 | ||
1602 | spin_lock_irqsave(&dev->lock, flags); | 1627 | spin_lock_irqsave(&dev->lock, flags); |
1603 | if (dev->started + sg_num > HIFN_QUEUE_LENGTH) { | 1628 | if (dev->started + sg_num > HIFN_QUEUE_LENGTH) { |
@@ -1606,36 +1631,11 @@ static int hifn_setup_session(struct ablkcipher_request *req) | |||
1606 | } | 1631 | } |
1607 | 1632 | ||
1608 | dev->snum++; | 1633 | dev->snum++; |
1609 | dev->started += sg_num; | 1634 | dev->started++; |
1610 | |||
1611 | while (nbytes) { | ||
1612 | src = &req->src[idx]; | ||
1613 | dst = &req->dst[idx]; | ||
1614 | t = &ctx->walk.cache[idx]; | ||
1615 | |||
1616 | if (t->length) { | ||
1617 | spage = dpage = sg_page(t); | ||
1618 | soff = doff = 0; | ||
1619 | len = t->length; | ||
1620 | } else { | ||
1621 | spage = sg_page(src); | ||
1622 | soff = src->offset; | ||
1623 | |||
1624 | dpage = sg_page(dst); | ||
1625 | doff = dst->offset; | ||
1626 | |||
1627 | len = dst->length; | ||
1628 | } | ||
1629 | |||
1630 | idx++; | ||
1631 | 1635 | ||
1632 | err = hifn_setup_dma(dev, spage, soff, dpage, doff, nbytes, | 1636 | err = hifn_setup_dma(dev, ctx, req->src, req->dst, req->nbytes, req); |
1633 | req, ctx); | 1637 | if (err) |
1634 | if (err) | 1638 | goto err_out; |
1635 | goto err_out; | ||
1636 | |||
1637 | nbytes -= min(len, nbytes); | ||
1638 | } | ||
1639 | 1639 | ||
1640 | dev->active = HIFN_DEFAULT_ACTIVE_NUM; | 1640 | dev->active = HIFN_DEFAULT_ACTIVE_NUM; |
1641 | spin_unlock_irqrestore(&dev->lock, flags); | 1641 | spin_unlock_irqrestore(&dev->lock, flags); |
@@ -1665,6 +1665,7 @@ static int hifn_test(struct hifn_device *dev, int encdec, u8 snum) | |||
1665 | 0xEF, 0x8A, 0x2C, 0x3B, | 1665 | 0xEF, 0x8A, 0x2C, 0x3B, |
1666 | 0x88, 0x4C, 0xFA, 0x59, | 1666 | 0x88, 0x4C, 0xFA, 0x59, |
1667 | 0xCA, 0x34, 0x2B, 0x2E}; | 1667 | 0xCA, 0x34, 0x2B, 0x2E}; |
1668 | struct scatterlist sg; | ||
1668 | 1669 | ||
1669 | memset(src, 0, sizeof(src)); | 1670 | memset(src, 0, sizeof(src)); |
1670 | memset(ctx.key, 0, sizeof(ctx.key)); | 1671 | memset(ctx.key, 0, sizeof(ctx.key)); |
@@ -1676,12 +1677,11 @@ static int hifn_test(struct hifn_device *dev, int encdec, u8 snum) | |||
1676 | ctx.op = (encdec)?ACRYPTO_OP_ENCRYPT:ACRYPTO_OP_DECRYPT; | 1677 | ctx.op = (encdec)?ACRYPTO_OP_ENCRYPT:ACRYPTO_OP_DECRYPT; |
1677 | ctx.mode = ACRYPTO_MODE_ECB; | 1678 | ctx.mode = ACRYPTO_MODE_ECB; |
1678 | ctx.type = ACRYPTO_TYPE_AES_128; | 1679 | ctx.type = ACRYPTO_TYPE_AES_128; |
1679 | atomic_set(&ctx.sg_num, 1); | 1680 | ctx.walk.cache[0].length = 0; |
1680 | 1681 | ||
1681 | err = hifn_setup_dma(dev, | 1682 | sg_init_one(&sg, &src, sizeof(src)); |
1682 | virt_to_page(src), offset_in_page(src), | 1683 | |
1683 | virt_to_page(src), offset_in_page(src), | 1684 | err = hifn_setup_dma(dev, &ctx, &sg, &sg, sizeof(src), NULL); |
1684 | sizeof(src), NULL, &ctx); | ||
1685 | if (err) | 1685 | if (err) |
1686 | goto err_out; | 1686 | goto err_out; |
1687 | 1687 | ||
@@ -1772,53 +1772,50 @@ static void hifn_process_ready(struct ablkcipher_request *req, int error) | |||
1772 | dprintk("%s: req: %p, ctx: %p.\n", __func__, req, ctx); | 1772 | dprintk("%s: req: %p, ctx: %p.\n", __func__, req, ctx); |
1773 | 1773 | ||
1774 | dev = ctx->dev; | 1774 | dev = ctx->dev; |
1775 | dprintk("%s: req: %p, started: %d, sg_num: %d.\n", | 1775 | dprintk("%s: req: %p, started: %d.\n", __func__, req, dev->started); |
1776 | __func__, req, dev->started, atomic_read(&ctx->sg_num)); | ||
1777 | 1776 | ||
1778 | if (--dev->started < 0) | 1777 | if (--dev->started < 0) |
1779 | BUG(); | 1778 | BUG(); |
1780 | 1779 | ||
1781 | if (atomic_dec_and_test(&ctx->sg_num)) { | 1780 | if (ctx->walk.flags & ASYNC_FLAGS_MISALIGNED) { |
1782 | unsigned int nbytes = req->nbytes; | 1781 | unsigned int nbytes = req->nbytes; |
1783 | int idx = 0, err; | 1782 | int idx = 0, err; |
1784 | struct scatterlist *dst, *t; | 1783 | struct scatterlist *dst, *t; |
1785 | void *saddr; | 1784 | void *saddr; |
1786 | 1785 | ||
1787 | if (ctx->walk.flags & ASYNC_FLAGS_MISALIGNED) { | 1786 | while (nbytes) { |
1788 | while (nbytes) { | 1787 | t = &ctx->walk.cache[idx]; |
1789 | t = &ctx->walk.cache[idx]; | 1788 | dst = &req->dst[idx]; |
1790 | dst = &req->dst[idx]; | ||
1791 | 1789 | ||
1792 | dprintk("\n%s: sg_page(t): %p, t->length: %u, " | 1790 | dprintk("\n%s: sg_page(t): %p, t->length: %u, " |
1793 | "sg_page(dst): %p, dst->length: %u, " | 1791 | "sg_page(dst): %p, dst->length: %u, " |
1794 | "nbytes: %u.\n", | 1792 | "nbytes: %u.\n", |
1795 | __func__, sg_page(t), t->length, | 1793 | __func__, sg_page(t), t->length, |
1796 | sg_page(dst), dst->length, nbytes); | 1794 | sg_page(dst), dst->length, nbytes); |
1797 | |||
1798 | if (!t->length) { | ||
1799 | nbytes -= min(dst->length, nbytes); | ||
1800 | idx++; | ||
1801 | continue; | ||
1802 | } | ||
1803 | 1795 | ||
1804 | saddr = kmap_atomic(sg_page(t), KM_IRQ1); | 1796 | if (!t->length) { |
1797 | nbytes -= min(dst->length, nbytes); | ||
1798 | idx++; | ||
1799 | continue; | ||
1800 | } | ||
1805 | 1801 | ||
1806 | err = ablkcipher_get(saddr, &t->length, t->offset, | 1802 | saddr = kmap_atomic(sg_page(t), KM_IRQ1); |
1807 | dst, nbytes, &nbytes); | ||
1808 | if (err < 0) { | ||
1809 | kunmap_atomic(saddr, KM_IRQ1); | ||
1810 | break; | ||
1811 | } | ||
1812 | 1803 | ||
1813 | idx += err; | 1804 | err = ablkcipher_get(saddr, &t->length, t->offset, |
1805 | dst, nbytes, &nbytes); | ||
1806 | if (err < 0) { | ||
1814 | kunmap_atomic(saddr, KM_IRQ1); | 1807 | kunmap_atomic(saddr, KM_IRQ1); |
1808 | break; | ||
1815 | } | 1809 | } |
1816 | 1810 | ||
1817 | ablkcipher_walk_exit(&ctx->walk); | 1811 | idx += err; |
1812 | kunmap_atomic(saddr, KM_IRQ1); | ||
1818 | } | 1813 | } |
1819 | 1814 | ||
1820 | req->base.complete(&req->base, error); | 1815 | ablkcipher_walk_exit(&ctx->walk); |
1821 | } | 1816 | } |
1817 | |||
1818 | req->base.complete(&req->base, error); | ||
1822 | } | 1819 | } |
1823 | 1820 | ||
1824 | static void hifn_check_for_completion(struct hifn_device *dev, int error) | 1821 | static void hifn_check_for_completion(struct hifn_device *dev, int error) |