aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto/talitos.c
diff options
context:
space:
mode:
authorHoria Geanta <horia.geanta@freescale.com>2013-11-13 05:20:37 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2013-12-05 08:28:41 -0500
commitb62ffd8c72c2f04ac737ef3ff0f7ba37d2013633 (patch)
treec84520c93e902b7bc95617e42b79b320d01bde68 /drivers/crypto/talitos.c
parentf13ab86a6123cc85c072253769fcaac72949ae93 (diff)
crypto: talitos - fix locating offending descriptor in error path
Commit 3e721aeb3df3816e283ab18e327cd4652972e213 ("crypto: talitos - handle descriptor not found in error path") tried to address the fact that CDPR (Current Descriptor Pointer Register) is unreliable. As it turns out, there are still issues in the function detecting the offending descriptor: -only 32 bits of the descriptor address are read, however the address is 36-bit - since reset_channel() initializes channels with EAE (extended address) bit set -reading CDPR can return zero in cur_desc; when searching the channel fifo for this address, cur_desc == dma_desc (= 0) case might happen, leading to an oops when trying to return desc->hdr (desc is zero) -read channel's .tail only once; the tail is a moving target; use a local variable for the end of search condition Signed-off-by: Lei Xu <Lei.Xu@freescale.com> Signed-off-by: Horia Geanta <horia.geanta@freescale.com> Tested-by: Kalyani Chowdhury <Kalyani.Chowdhury@freescale.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto/talitos.c')
-rw-r--r--drivers/crypto/talitos.c21
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index b44f4ddc565c..a3d2e9b88c41 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -338,20 +338,29 @@ DEF_TALITOS_DONE(ch1_3, TALITOS_ISR_CH_1_3_DONE)
338static u32 current_desc_hdr(struct device *dev, int ch) 338static u32 current_desc_hdr(struct device *dev, int ch)
339{ 339{
340 struct talitos_private *priv = dev_get_drvdata(dev); 340 struct talitos_private *priv = dev_get_drvdata(dev);
341 int tail = priv->chan[ch].tail; 341 int tail, iter;
342 dma_addr_t cur_desc; 342 dma_addr_t cur_desc;
343 343
344 cur_desc = in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO); 344 cur_desc = ((u64)in_be32(priv->chan[ch].reg + TALITOS_CDPR)) << 32;
345 cur_desc |= in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
345 346
346 while (priv->chan[ch].fifo[tail].dma_desc != cur_desc) { 347 if (!cur_desc) {
347 tail = (tail + 1) & (priv->fifo_len - 1); 348 dev_err(dev, "CDPR is NULL, giving up search for offending descriptor\n");
348 if (tail == priv->chan[ch].tail) { 349 return 0;
350 }
351
352 tail = priv->chan[ch].tail;
353
354 iter = tail;
355 while (priv->chan[ch].fifo[iter].dma_desc != cur_desc) {
356 iter = (iter + 1) & (priv->fifo_len - 1);
357 if (iter == tail) {
349 dev_err(dev, "couldn't locate current descriptor\n"); 358 dev_err(dev, "couldn't locate current descriptor\n");
350 return 0; 359 return 0;
351 } 360 }
352 } 361 }
353 362
354 return priv->chan[ch].fifo[tail].desc->hdr; 363 return priv->chan[ch].fifo[iter].desc->hdr;
355} 364}
356 365
357/* 366/*