Commit 5d5f3eed authored by Tero Kristo's avatar Tero Kristo Committed by Herbert Xu

crypto: omap-aes-gcm - fix failure with assocdata only

If we only have assocdata with an omap-aes-gcm, it currently just
completes it directly without passing it over to the crypto HW. This
produces wrong results.

Fix by passing the request down to the crypto HW, and fix the DMA
support code to accept a case where we don't expect any output data.
In the case where only assocdata is provided, it just passes through
the accelerator and provides authentication results, without any
encrypted/decrypted buffer via DMA.
Signed-off-by: default avatarTero Kristo <t-kristo@ti.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent f0956d42
...@@ -244,7 +244,7 @@ static int omap_aes_gcm_handle_queue(struct omap_aes_dev *dd, ...@@ -244,7 +244,7 @@ static int omap_aes_gcm_handle_queue(struct omap_aes_dev *dd,
err = omap_aes_write_ctrl(dd); err = omap_aes_write_ctrl(dd);
if (!err) { if (!err) {
if (dd->in_sg_len && dd->out_sg_len) if (dd->in_sg_len)
err = omap_aes_crypt_dma_start(dd); err = omap_aes_crypt_dma_start(dd);
else else
omap_aes_gcm_dma_out_callback(dd); omap_aes_gcm_dma_out_callback(dd);
......
...@@ -269,13 +269,14 @@ static int omap_aes_crypt_dma(struct omap_aes_dev *dd, ...@@ -269,13 +269,14 @@ static int omap_aes_crypt_dma(struct omap_aes_dev *dd,
struct scatterlist *out_sg, struct scatterlist *out_sg,
int in_sg_len, int out_sg_len) int in_sg_len, int out_sg_len)
{ {
struct dma_async_tx_descriptor *tx_in, *tx_out; struct dma_async_tx_descriptor *tx_in, *tx_out = NULL, *cb_desc;
struct dma_slave_config cfg; struct dma_slave_config cfg;
int ret; int ret;
if (dd->pio_only) { if (dd->pio_only) {
scatterwalk_start(&dd->in_walk, dd->in_sg); scatterwalk_start(&dd->in_walk, dd->in_sg);
scatterwalk_start(&dd->out_walk, dd->out_sg); if (out_sg_len)
scatterwalk_start(&dd->out_walk, dd->out_sg);
/* Enable DATAIN interrupt and let it take /* Enable DATAIN interrupt and let it take
care of the rest */ care of the rest */
...@@ -312,34 +313,45 @@ static int omap_aes_crypt_dma(struct omap_aes_dev *dd, ...@@ -312,34 +313,45 @@ static int omap_aes_crypt_dma(struct omap_aes_dev *dd,
/* No callback necessary */ /* No callback necessary */
tx_in->callback_param = dd; tx_in->callback_param = dd;
tx_in->callback = NULL;
/* OUT */ /* OUT */
ret = dmaengine_slave_config(dd->dma_lch_out, &cfg); if (out_sg_len) {
if (ret) { ret = dmaengine_slave_config(dd->dma_lch_out, &cfg);
dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n", if (ret) {
ret); dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n",
return ret; ret);
} return ret;
}
tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, out_sg_len, tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg,
DMA_DEV_TO_MEM, out_sg_len,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK); DMA_DEV_TO_MEM,
if (!tx_out) { DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
dev_err(dd->dev, "OUT prep_slave_sg() failed\n"); if (!tx_out) {
return -EINVAL; dev_err(dd->dev, "OUT prep_slave_sg() failed\n");
return -EINVAL;
}
cb_desc = tx_out;
} else {
cb_desc = tx_in;
} }
if (dd->flags & FLAGS_GCM) if (dd->flags & FLAGS_GCM)
tx_out->callback = omap_aes_gcm_dma_out_callback; cb_desc->callback = omap_aes_gcm_dma_out_callback;
else else
tx_out->callback = omap_aes_dma_out_callback; cb_desc->callback = omap_aes_dma_out_callback;
tx_out->callback_param = dd; cb_desc->callback_param = dd;
dmaengine_submit(tx_in); dmaengine_submit(tx_in);
dmaengine_submit(tx_out); if (tx_out)
dmaengine_submit(tx_out);
dma_async_issue_pending(dd->dma_lch_in); dma_async_issue_pending(dd->dma_lch_in);
dma_async_issue_pending(dd->dma_lch_out); if (out_sg_len)
dma_async_issue_pending(dd->dma_lch_out);
/* start DMA */ /* start DMA */
dd->pdata->trigger(dd, dd->total); dd->pdata->trigger(dd, dd->total);
...@@ -361,11 +373,13 @@ int omap_aes_crypt_dma_start(struct omap_aes_dev *dd) ...@@ -361,11 +373,13 @@ int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
return -EINVAL; return -EINVAL;
} }
err = dma_map_sg(dd->dev, dd->out_sg, dd->out_sg_len, if (dd->out_sg_len) {
DMA_FROM_DEVICE); err = dma_map_sg(dd->dev, dd->out_sg, dd->out_sg_len,
if (!err) { DMA_FROM_DEVICE);
dev_err(dd->dev, "dma_map_sg() error\n"); if (!err) {
return -EINVAL; dev_err(dd->dev, "dma_map_sg() error\n");
return -EINVAL;
}
} }
} }
...@@ -373,8 +387,9 @@ int omap_aes_crypt_dma_start(struct omap_aes_dev *dd) ...@@ -373,8 +387,9 @@ int omap_aes_crypt_dma_start(struct omap_aes_dev *dd)
dd->out_sg_len); dd->out_sg_len);
if (err && !dd->pio_only) { if (err && !dd->pio_only) {
dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, 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, if (dd->out_sg_len)
DMA_FROM_DEVICE); dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len,
DMA_FROM_DEVICE);
} }
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment