summaryrefslogtreecommitdiffstats
path: root/kernel/lib/scatterlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/lib/scatterlist.c')
-rw-r--r--kernel/lib/scatterlist.c54
1 files changed, 41 insertions, 13 deletions
diff --git a/kernel/lib/scatterlist.c b/kernel/lib/scatterlist.c
index f6d1f8899..ebe3b7edd 100644
--- a/kernel/lib/scatterlist.c
+++ b/kernel/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
@@ -73,16 +105,12 @@ EXPORT_SYMBOL(sg_nents);
**/
struct scatterlist *sg_last(struct scatterlist *sgl, unsigned int nents)
{
-#ifndef CONFIG_ARCH_HAS_SG_CHAIN
- struct scatterlist *ret = &sgl[nents - 1];
-#else
struct scatterlist *sg, *ret = NULL;
unsigned int i;
for_each_sg(sgl, sg, nents, i)
ret = sg;
-#endif
#ifdef CONFIG_DEBUG_SG
BUG_ON(sgl[0].sg_magic != SG_MAGIC);
BUG_ON(!sg_is_last(ret));
@@ -618,9 +646,8 @@ EXPORT_SYMBOL(sg_miter_stop);
* Returns the number of copied bytes.
*
**/
-static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
- void *buf, size_t buflen, off_t skip,
- bool to_buffer)
+size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf,
+ size_t buflen, off_t skip, bool to_buffer)
{
unsigned int offset = 0;
struct sg_mapping_iter miter;
@@ -657,6 +684,7 @@ static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
local_irq_restore_nort(flags);
return offset;
}
+EXPORT_SYMBOL(sg_copy_buffer);
/**
* sg_copy_from_buffer - Copy from a linear buffer to an SG list
@@ -669,9 +697,9 @@ static size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents,
*
**/
size_t sg_copy_from_buffer(struct scatterlist *sgl, unsigned int nents,
- void *buf, size_t buflen)
+ const void *buf, size_t buflen)
{
- return sg_copy_buffer(sgl, nents, buf, buflen, 0, false);
+ return sg_copy_buffer(sgl, nents, (void *)buf, buflen, 0, false);
}
EXPORT_SYMBOL(sg_copy_from_buffer);
@@ -697,16 +725,16 @@ EXPORT_SYMBOL(sg_copy_to_buffer);
* @sgl: The SG list
* @nents: Number of SG entries
* @buf: Where to copy from
- * @skip: Number of bytes to skip before copying
* @buflen: The number of bytes to copy
+ * @skip: Number of bytes to skip before copying
*
* Returns the number of copied bytes.
*
**/
size_t sg_pcopy_from_buffer(struct scatterlist *sgl, unsigned int nents,
- void *buf, size_t buflen, off_t skip)
+ const void *buf, size_t buflen, off_t skip)
{
- return sg_copy_buffer(sgl, nents, buf, buflen, skip, false);
+ return sg_copy_buffer(sgl, nents, (void *)buf, buflen, skip, false);
}
EXPORT_SYMBOL(sg_pcopy_from_buffer);
@@ -715,8 +743,8 @@ EXPORT_SYMBOL(sg_pcopy_from_buffer);
* @sgl: The SG list
* @nents: Number of SG entries
* @buf: Where to copy to
- * @skip: Number of bytes to skip before copying
* @buflen: The number of bytes to copy
+ * @skip: Number of bytes to skip before copying
*
* Returns the number of copied bytes.
*