[PATCH v2 04/14] crypto: omap-aes: Simplify DMA usage by using direct SGs
Lokesh Vutla
lokeshvutla at ti.com
Tue Aug 20 08:57:24 EDT 2013
Hi Joel,
On Sunday 18 August 2013 08:12 AM, Joel Fernandes wrote:
> In early version of this driver, assumptions were made such as DMA layer
> requires contiguous buffers etc. Due to this, new buffers were allocated,
> mapped and used for DMA. These assumptions are no longer true and DMAEngine
> scatter-gather DMA doesn't have such requirements. We simply the DMA operations
> by directly using the scatter-gather buffers provided by the crypto layer
> instead of creating our own.
>
> Lot of logic that handled DMA'ing only X number of bytes of the total, or as
> much as fitted into a 3rd party buffer is removed and is no longer required.
>
> Also, good performance improvement of atleast ~20% seen with encrypting a
> buffer size of 8K (1800 ops/sec vs 1400 ops/sec). Improvement will be higher
> for much larger blocks though such benchmarking is left as an exercise for the
> reader. Also DMA usage is much more simplified and coherent with rest of the
> code.
>
> Signed-off-by: Joel Fernandes <joelf at ti.com>
> ---
> drivers/crypto/omap-aes.c | 147 ++++++++-------------------------------------
> 1 file changed, 25 insertions(+), 122 deletions(-)
>
> diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
> index e369e6e..64dd5c1 100644
> --- a/drivers/crypto/omap-aes.c
> +++ b/drivers/crypto/omap-aes.c
> @@ -480,22 +480,14 @@ static int sg_copy(struct scatterlist **sg, size_t *offset, void *buf,
> }
>
> static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
> - struct scatterlist *in_sg, struct scatterlist *out_sg)
> + struct scatterlist *in_sg, struct scatterlist *out_sg,
> + int in_sg_len, int out_sg_len)
> {
> struct omap_aes_ctx *ctx = crypto_tfm_ctx(tfm);
> struct omap_aes_dev *dd = ctx->dd;
> struct dma_async_tx_descriptor *tx_in, *tx_out;
> struct dma_slave_config cfg;
> - dma_addr_t dma_addr_in = sg_dma_address(in_sg);
> - int ret, length = sg_dma_len(in_sg);
> -
> - pr_debug("len: %d\n", length);
> -
> - dd->dma_size = length;
> -
> - if (!(dd->flags & FLAGS_FAST))
> - dma_sync_single_for_device(dd->dev, dma_addr_in, length,
> - DMA_TO_DEVICE);
> + int ret;
By this change FLAGS_FAST is unsed, it can be cleaned right?
or Am I missing something?
Thanks and regards,
Lokesh
>
> memset(&cfg, 0, sizeof(cfg));
>
> @@ -514,7 +506,7 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
> return ret;
> }
>
> - tx_in = dmaengine_prep_slave_sg(dd->dma_lch_in, in_sg, 1,
> + tx_in = dmaengine_prep_slave_sg(dd->dma_lch_in, in_sg, in_sg_len,
> DMA_MEM_TO_DEV,
> DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> if (!tx_in) {
> @@ -533,7 +525,7 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
> return ret;
> }
>
> - tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, 1,
> + tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, out_sg_len,
> DMA_DEV_TO_MEM,
> DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> if (!tx_out) {
> @@ -551,7 +543,7 @@ static int omap_aes_crypt_dma(struct crypto_tfm *tfm,
> dma_async_issue_pending(dd->dma_lch_out);
>
> /* start DMA */
> - dd->pdata->trigger(dd, length);
> + dd->pdata->trigger(dd, dd->total);
>
> return 0;
> }
> @@ -560,93 +552,28 @@ static int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
> {
> struct crypto_tfm *tfm = crypto_ablkcipher_tfm(
> crypto_ablkcipher_reqtfm(dd->req));
> - int err, fast = 0, in, out;
> - size_t count;
> - dma_addr_t addr_in, addr_out;
> - struct scatterlist *in_sg, *out_sg;
> - int len32;
> + int err;
>
> pr_debug("total: %d\n", dd->total);
>
> - if (sg_is_last(dd->in_sg) && sg_is_last(dd->out_sg)) {
> - /* check for alignment */
> - in = IS_ALIGNED((u32)dd->in_sg->offset, sizeof(u32));
> - out = IS_ALIGNED((u32)dd->out_sg->offset, sizeof(u32));
> -
> - fast = in && out;
> + err = dma_map_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
> + if (!err) {
> + dev_err(dd->dev, "dma_map_sg() error\n");
> + return -EINVAL;
> }
>
> - if (fast) {
> - count = min(dd->total, sg_dma_len(dd->in_sg));
> - count = min(count, sg_dma_len(dd->out_sg));
> -
> - if (count != dd->total) {
> - pr_err("request length != buffer length\n");
> - return -EINVAL;
> - }
> -
> - pr_debug("fast\n");
> -
> - err = dma_map_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
> - if (!err) {
> - dev_err(dd->dev, "dma_map_sg() error\n");
> - return -EINVAL;
> - }
> -
> - err = dma_map_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
> - if (!err) {
> - dev_err(dd->dev, "dma_map_sg() error\n");
> - dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
> - return -EINVAL;
> - }
> -
> - addr_in = sg_dma_address(dd->in_sg);
> - addr_out = sg_dma_address(dd->out_sg);
> -
> - in_sg = dd->in_sg;
> - out_sg = dd->out_sg;
> -
> - dd->flags |= FLAGS_FAST;
> -
> - } else {
> - /* use cache buffers */
> - count = sg_copy(&dd->in_sg, &dd->in_offset, dd->buf_in,
> - dd->buflen, dd->total, 0);
> -
> - len32 = DIV_ROUND_UP(count, DMA_MIN) * DMA_MIN;
> -
> - /*
> - * The data going into the AES module has been copied
> - * to a local buffer and the data coming out will go
> - * into a local buffer so set up local SG entries for
> - * both.
> - */
> - sg_init_table(&dd->in_sgl, 1);
> - dd->in_sgl.offset = dd->in_offset;
> - sg_dma_len(&dd->in_sgl) = len32;
> - sg_dma_address(&dd->in_sgl) = dd->dma_addr_in;
> -
> - sg_init_table(&dd->out_sgl, 1);
> - dd->out_sgl.offset = dd->out_offset;
> - sg_dma_len(&dd->out_sgl) = len32;
> - sg_dma_address(&dd->out_sgl) = dd->dma_addr_out;
> -
> - in_sg = &dd->in_sgl;
> - out_sg = &dd->out_sgl;
> -
> - addr_in = dd->dma_addr_in;
> - addr_out = dd->dma_addr_out;
> -
> - dd->flags &= ~FLAGS_FAST;
> -
> + err = dma_map_sg(dd->dev, dd->out_sg, dd->out_sg_len, DMA_FROM_DEVICE);
> + if (!err) {
> + dev_err(dd->dev, "dma_map_sg() error\n");
> + return -EINVAL;
> }
>
> - dd->total -= count;
> -
> - err = omap_aes_crypt_dma(tfm, in_sg, out_sg);
> + err = omap_aes_crypt_dma(tfm, dd->in_sg, dd->out_sg, dd->in_sg_len,
> + dd->out_sg_len);
> if (err) {
> - dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
> - dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_TO_DEVICE);
> + dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
> + dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len,
> + DMA_FROM_DEVICE);
> }
>
> return err;
> @@ -667,7 +594,6 @@ static void omap_aes_finish_req(struct omap_aes_dev *dd, int err)
> static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
> {
> int err = 0;
> - size_t count;
>
> pr_debug("total: %d\n", dd->total);
>
> @@ -676,21 +602,8 @@ static int omap_aes_crypt_dma_stop(struct omap_aes_dev *dd)
> dmaengine_terminate_all(dd->dma_lch_in);
> dmaengine_terminate_all(dd->dma_lch_out);
>
> - if (dd->flags & FLAGS_FAST) {
> - dma_unmap_sg(dd->dev, dd->out_sg, 1, DMA_FROM_DEVICE);
> - dma_unmap_sg(dd->dev, dd->in_sg, 1, DMA_TO_DEVICE);
> - } else {
> - dma_sync_single_for_device(dd->dev, dd->dma_addr_out,
> - dd->dma_size, DMA_FROM_DEVICE);
> -
> - /* copy data */
> - count = sg_copy(&dd->out_sg, &dd->out_offset, dd->buf_out,
> - dd->buflen, dd->dma_size, 1);
> - if (count != dd->dma_size) {
> - err = -EINVAL;
> - pr_err("not all data converted: %u\n", count);
> - }
> - }
> + dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE);
> + dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, DMA_FROM_DEVICE);
>
> return err;
> }
> @@ -760,21 +673,11 @@ static int omap_aes_handle_queue(struct omap_aes_dev *dd,
> static void omap_aes_done_task(unsigned long data)
> {
> struct omap_aes_dev *dd = (struct omap_aes_dev *)data;
> - int err;
> -
> - pr_debug("enter\n");
>
> - err = omap_aes_crypt_dma_stop(dd);
> -
> - err = dd->err ? : err;
> -
> - if (dd->total && !err) {
> - err = omap_aes_crypt_dma_start(dd);
> - if (!err)
> - return; /* DMA started. Not fininishing. */
> - }
> + pr_debug("enter done_task\n");
>
> - omap_aes_finish_req(dd, err);
> + omap_aes_crypt_dma_stop(dd);
> + omap_aes_finish_req(dd, 0);
> omap_aes_handle_queue(dd, NULL);
>
> pr_debug("exit\n");
>
More information about the linux-arm-kernel
mailing list