--- /dev/null
+From e80a0af4759a164214f02da157a3800753ce135f Mon Sep 17 00:00:00 2001
+From: Bart Van Assche <bart.vanassche@wdc.com>
+Date: Fri, 5 Jan 2018 08:26:46 -0800
+Subject: lib/scatterlist: Introduce sgl_alloc() and sgl_free()
+
+From: Bart Van Assche <bart.vanassche@wdc.com>
+
+commit e80a0af4759a164214f02da157a3800753ce135f upstream.
+
+Many kernel drivers contain code that allocates and frees both a
+scatterlist and the pages that populate that scatterlist.
+Introduce functions in lib/scatterlist.c that perform these tasks
+instead of duplicating this functionality in multiple drivers.
+Only include these functions in the build if CONFIG_SGL_ALLOC=y
+to avoid that the kernel size increases if this functionality is
+not used.
+
+Signed-off-by: Bart Van Assche <bart.vanassche@wdc.com>
+Reviewed-by: Hannes Reinecke <hare@suse.com>
+Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/scatterlist.h | 10 ++++
+ lib/Kconfig | 4 +
+ lib/scatterlist.c | 105 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 119 insertions(+)
+
+--- a/include/linux/scatterlist.h
++++ b/include/linux/scatterlist.h
+@@ -267,6 +267,16 @@ int sg_alloc_table_from_pages(struct sg_
+ unsigned long offset, unsigned long size,
+ gfp_t gfp_mask);
+
++#ifdef CONFIG_SGL_ALLOC
++struct scatterlist *sgl_alloc_order(unsigned long long length,
++ unsigned int order, bool chainable,
++ gfp_t gfp, unsigned int *nent_p);
++struct scatterlist *sgl_alloc(unsigned long long length, gfp_t gfp,
++ unsigned int *nent_p);
++void sgl_free_order(struct scatterlist *sgl, int order);
++void sgl_free(struct scatterlist *sgl);
++#endif /* CONFIG_SGL_ALLOC */
++
+ size_t sg_copy_buffer(struct scatterlist *sgl, unsigned int nents, void *buf,
+ size_t buflen, off_t skip, bool to_buffer);
+
+--- a/lib/Kconfig
++++ b/lib/Kconfig
+@@ -413,6 +413,10 @@ config HAS_DMA
+ depends on !NO_DMA
+ default y
+
++config SGL_ALLOC
++ bool
++ default n
++
+ config DMA_NOOP_OPS
+ bool
+ depends on HAS_DMA && (!64BIT || ARCH_DMA_ADDR_T_64BIT)
+--- a/lib/scatterlist.c
++++ b/lib/scatterlist.c
+@@ -433,6 +433,111 @@ int sg_alloc_table_from_pages(struct sg_
+ }
+ EXPORT_SYMBOL(sg_alloc_table_from_pages);
+
++#ifdef CONFIG_SGL_ALLOC
++
++/**
++ * sgl_alloc_order - allocate a scatterlist and its pages
++ * @length: Length in bytes of the scatterlist. Must be at least one
++ * @order: Second argument for alloc_pages()
++ * @chainable: Whether or not to allocate an extra element in the scatterlist
++ * for scatterlist chaining purposes
++ * @gfp: Memory allocation flags
++ * @nent_p: [out] Number of entries in the scatterlist that have pages
++ *
++ * Returns: A pointer to an initialized scatterlist or %NULL upon failure.
++ */
++struct scatterlist *sgl_alloc_order(unsigned long long length,
++ unsigned int order, bool chainable,
++ gfp_t gfp, unsigned int *nent_p)
++{
++ struct scatterlist *sgl, *sg;
++ struct page *page;
++ unsigned int nent, nalloc;
++ u32 elem_len;
++
++ nent = round_up(length, PAGE_SIZE << order) >> (PAGE_SHIFT + order);
++ /* Check for integer overflow */
++ if (length > (nent << (PAGE_SHIFT + order)))
++ return NULL;
++ nalloc = nent;
++ if (chainable) {
++ /* Check for integer overflow */
++ if (nalloc + 1 < nalloc)
++ return NULL;
++ nalloc++;
++ }
++ sgl = kmalloc_array(nalloc, sizeof(struct scatterlist),
++ (gfp & ~GFP_DMA) | __GFP_ZERO);
++ if (!sgl)
++ return NULL;
++
++ sg_init_table(sgl, nent);
++ sg = sgl;
++ while (length) {
++ elem_len = min_t(u64, length, PAGE_SIZE << order);
++ page = alloc_pages(gfp, order);
++ if (!page) {
++ sgl_free(sgl);
++ return NULL;
++ }
++
++ sg_set_page(sg, page, elem_len, 0);
++ length -= elem_len;
++ sg = sg_next(sg);
++ }
++ WARN_ON_ONCE(sg);
++ if (nent_p)
++ *nent_p = nent;
++ return sgl;
++}
++EXPORT_SYMBOL(sgl_alloc_order);
++
++/**
++ * sgl_alloc - allocate a scatterlist and its pages
++ * @length: Length in bytes of the scatterlist
++ * @gfp: Memory allocation flags
++ * @nent_p: [out] Number of entries in the scatterlist
++ *
++ * Returns: A pointer to an initialized scatterlist or %NULL upon failure.
++ */
++struct scatterlist *sgl_alloc(unsigned long long length, gfp_t gfp,
++ unsigned int *nent_p)
++{
++ return sgl_alloc_order(length, 0, false, gfp, nent_p);
++}
++EXPORT_SYMBOL(sgl_alloc);
++
++/**
++ * sgl_free_order - free a scatterlist and its pages
++ * @sgl: Scatterlist with one or more elements
++ * @order: Second argument for __free_pages()
++ */
++void sgl_free_order(struct scatterlist *sgl, int order)
++{
++ struct scatterlist *sg;
++ struct page *page;
++
++ for (sg = sgl; sg; sg = sg_next(sg)) {
++ page = sg_page(sg);
++ if (page)
++ __free_pages(page, order);
++ }
++ kfree(sgl);
++}
++EXPORT_SYMBOL(sgl_free_order);
++
++/**
++ * sgl_free - free a scatterlist and its pages
++ * @sgl: Scatterlist with one or more elements
++ */
++void sgl_free(struct scatterlist *sgl)
++{
++ sgl_free_order(sgl, 0);
++}
++EXPORT_SYMBOL(sgl_free);
++
++#endif /* CONFIG_SGL_ALLOC */
++
+ void __sg_page_iter_start(struct sg_page_iter *piter,
+ struct scatterlist *sglist, unsigned int nents,
+ unsigned long pgoffset)