summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorTom Lendacky <thomas.lendacky@amd.com>2015-06-01 18:15:25 +0200
committerHerbert Xu <herbert@gondor.apana.org.au>2015-06-03 04:51:27 +0200
commitcfaed10d1f27d036b72bbdc6b1e59ea28c38ec7f (patch)
tree41afa11a44a4486966af9f1b89025bc9f8e2c8e7 /lib
parentcrypto: scatterwalk - Hide PageSlab call to optimise away flush_dcache_page (diff)
downloadlinux-cfaed10d1f27d036b72bbdc6b1e59ea28c38ec7f.tar.xz
linux-cfaed10d1f27d036b72bbdc6b1e59ea28c38ec7f.zip
scatterlist: introduce sg_nents_for_len
When performing a dma_map_sg() call, the number of sg entries to map is required. Using sg_nents to retrieve the number of sg entries will return the total number of entries in the sg list up to the entry marked as the end. If there happen to be unused entries in the list, these will still be counted. Some dma_map_sg() implementations will not handle the unused entries correctly (lib/swiotlb.c) and execute a BUG_ON. The sg_nents_for_len() function will traverse the sg list and return the number of entries required to satisfy the supplied length argument. This can then be supplied to the dma_map_sg() call to successfully map the sg. Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'lib')
-rw-r--r--lib/scatterlist.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index c9f2e8c6ccc9..99fbc2f238c4 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -56,6 +56,38 @@ int sg_nents(struct scatterlist *sg)
}
EXPORT_SYMBOL(sg_nents);
+/**
+ * sg_nents_for_len - return total count of entries in scatterlist
+ * needed to satisfy the supplied length
+ * @sg: The scatterlist
+ * @len: The total required length
+ *
+ * Description:
+ * Determines the number of entries in sg that are required to meet
+ * the supplied length, taking into acount chaining as well
+ *
+ * Returns:
+ * the number of sg entries needed, negative error on failure
+ *
+ **/
+int sg_nents_for_len(struct scatterlist *sg, u64 len)
+{
+ int nents;
+ u64 total;
+
+ if (!len)
+ return 0;
+
+ for (nents = 0, total = 0; sg; sg = sg_next(sg)) {
+ nents++;
+ total += sg->length;
+ if (total >= len)
+ return nents;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(sg_nents_for_len);
/**
* sg_last - return the last scatterlist entry in a list