crypto: caam - Handle errors in dma_map_sg_chained
authorHerbert Xu <herbert@gondor.apana.org.au>
Tue, 16 Jun 2015 05:54:22 +0000 (13:54 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Wed, 17 Jun 2015 07:35:08 +0000 (15:35 +0800)
Currently dma_map_sg_chained does not handle errors from the
underlying dma_map_sg calls.  This patch adds rollback in case
of an error by simply calling dma_unmap_sg_chained for the ones
that we've already mapped.

All current callers ignore the return value so this should have
no impact on them.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/crypto/caam/sg_sw_sec4.h

index efbc1db8da5307c532d0f3a48df94245afb70b2f..b68b74cc7b778dcd89eb75d8528fb88bc121b4f3 100644 (file)
@@ -100,34 +100,41 @@ static inline int sg_count(struct scatterlist *sg_list, int nbytes,
        return sg_nents;
 }
 
-static int dma_map_sg_chained(struct device *dev, struct scatterlist *sg,
-                             unsigned int nents, enum dma_data_direction dir,
-                             bool chained)
+static inline void dma_unmap_sg_chained(
+       struct device *dev, struct scatterlist *sg, unsigned int nents,
+       enum dma_data_direction dir, bool chained)
 {
        if (unlikely(chained)) {
                int i;
                for (i = 0; i < nents; i++) {
-                       dma_map_sg(dev, sg, 1, dir);
+                       dma_unmap_sg(dev, sg, 1, dir);
                        sg = sg_next(sg);
                }
-       } else {
-               dma_map_sg(dev, sg, nents, dir);
+       } else if (nents) {
+               dma_unmap_sg(dev, sg, nents, dir);
        }
-       return nents;
 }
 
-static int dma_unmap_sg_chained(struct device *dev, struct scatterlist *sg,
-                               unsigned int nents, enum dma_data_direction dir,
-                               bool chained)
+static inline int dma_map_sg_chained(
+       struct device *dev, struct scatterlist *sg, unsigned int nents,
+       enum dma_data_direction dir, bool chained)
 {
+       struct scatterlist *first = sg;
+
        if (unlikely(chained)) {
                int i;
                for (i = 0; i < nents; i++) {
-                       dma_unmap_sg(dev, sg, 1, dir);
+                       if (!dma_map_sg(dev, sg, 1, dir)) {
+                               dma_unmap_sg_chained(dev, first, i, dir,
+                                                    chained);
+                               nents = 0;
+                               break;
+                       }
+
                        sg = sg_next(sg);
                }
-       } else {
-               dma_unmap_sg(dev, sg, nents, dir);
-       }
+       } else
+               nents = dma_map_sg(dev, sg, nents, dir);
+
        return nents;
 }