From b6dc7a859bd7e0fa99fabefdd36dffa3884b2247 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 21 Mar 2013 21:16:42 +0000 Subject: [PATCH] compat: backport sg page iterator a321e91b This backports commit a321e91b which adds the scatterlist simple page iterator. mcgrof@frijol ~/linux-next (git::master)$ git describe --contains a321e91b v3.9-rc1~46^2~149 commit a321e91b6d73ed011ffceed384c40d2785cf723b Author: Imre Deak Date: Wed Feb 27 17:02:56 2013 -0800 lib/scatterlist: add simple page iterator Add an iterator to walk through a scatter list a page at a time starting at a specific page offset. As opposed to the mapping iterator this is meant to be small, performing well even in simple loops like collecting all pages on the scatterlist into an array or setting up an iommu table based on the pages' DMA address. Signed-off-by: Imre Deak Cc: Maxim Levitsky Cc: Tejun Heo Cc: Daniel Vetter Tested-by: Stephen Warren Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Luis R. Rodriguez --- compat/Makefile | 1 + compat/compat-3.9.c | 54 ++++++++++++++++++++++++++++++++++++ include/linux/compat-3.9.h | 44 +++++++++++++++++++++++++++++ scripts/gen-compat-config.sh | 2 +- 4 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 compat/compat-3.9.c diff --git a/compat/Makefile b/compat/Makefile index 3b9bfdebfea1..5abdc35a4f43 100644 --- a/compat/Makefile +++ b/compat/Makefile @@ -51,6 +51,7 @@ compat-$(CONFIG_COMPAT_KERNEL_3_5) += \ user_namespace.o compat-$(CONFIG_COMPAT_KERNEL_3_7) += compat-3.7.o compat-$(CONFIG_COMPAT_KERNEL_3_8) += compat-3.8.o +compat-$(CONFIG_COMPAT_KERNEL_3_9) += compat-3.9.o compat-$(CONFIG_COMPAT_CORDIC) += cordic.o compat-$(CONFIG_COMPAT_CRC8) += crc8.o diff --git a/compat/compat-3.9.c b/compat/compat-3.9.c new file mode 100644 index 000000000000..7134caa9615b --- /dev/null +++ b/compat/compat-3.9.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013 Luis R. Rodriguez + * + * Compatibility file for Linux wireless for kernels 3.9. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +#ifndef __sg_page_iter_next + +void __sg_page_iter_start(struct sg_page_iter *piter, + struct scatterlist *sglist, unsigned int nents, + unsigned long pgoffset) +{ + piter->__pg_advance = 0; + piter->__nents = nents; + + piter->page = NULL; + piter->sg = sglist; + piter->sg_pgoffset = pgoffset; +} +EXPORT_SYMBOL_GPL(__sg_page_iter_start); + +static int sg_page_count(struct scatterlist *sg) +{ + return PAGE_ALIGN(sg->offset + sg->length) >> PAGE_SHIFT; +} + +bool __sg_page_iter_next(struct sg_page_iter *piter) +{ + if (!piter->__nents || !piter->sg) + return false; + + piter->sg_pgoffset += piter->__pg_advance; + piter->__pg_advance = 1; + + while (piter->sg_pgoffset >= sg_page_count(piter->sg)) { + piter->sg_pgoffset -= sg_page_count(piter->sg); + piter->sg = sg_next(piter->sg); + if (!--piter->__nents || !piter->sg) + return false; + } + piter->page = nth_page(sg_page(piter->sg), piter->sg_pgoffset); + + return true; +} +EXPORT_SYMBOL_GPL(__sg_page_iter_next); + +#endif /* __sg_page_iter_next */ diff --git a/include/linux/compat-3.9.h b/include/linux/compat-3.9.h index 89b94a4532e1..240a328d7b6c 100644 --- a/include/linux/compat-3.9.h +++ b/include/linux/compat-3.9.h @@ -14,10 +14,54 @@ #include #include #include +#include /* include this before changing hlist_for_each_* to use the old versions. */ #include +/* Lets expect distributions might backport this */ + +#ifndef for_each_sg_page +/* + * sg page iterator + * + * Iterates over sg entries page-by-page. On each successful iteration, + * @piter->page points to the current page, @piter->sg to the sg holding this + * page and @piter->sg_pgoffset to the page's page offset within the sg. The + * iteration will stop either when a maximum number of sg entries was reached + * or a terminating sg (sg_last(sg) == true) was reached. + */ +struct sg_page_iter { + struct page *page; /* current page */ + struct scatterlist *sg; /* sg holding the page */ + unsigned int sg_pgoffset; /* page offset within the sg */ + + /* these are internal states, keep away */ + unsigned int __nents; /* remaining sg entries */ + int __pg_advance; /* nr pages to advance at the + * next step */ +}; + +#define __sg_page_iter_next LINUX_BACKPORT(__sg_page_iter_next) +bool __sg_page_iter_next(struct sg_page_iter *piter); +#define __sg_page_iter_start LINUX_BACKPORT(__sg_page_iter_start) +void __sg_page_iter_start(struct sg_page_iter *piter, + struct scatterlist *sglist, unsigned int nents, + unsigned long pgoffset); + +/** + * for_each_sg_page - iterate over the pages of the given sg list + * @sglist: sglist to iterate over + * @piter: page iterator to hold current page, sg, sg_pgoffset + * @nents: maximum number of sg entries to iterate over + * @pgoffset: starting page offset + */ +#define for_each_sg_page(sglist, piter, nents, pgoffset) \ + for (__sg_page_iter_start((piter), (sglist), (nents), (pgoffset)); \ + __sg_page_iter_next(piter);) + +#endif /* for_each_sg_page assumption */ + /* backports 7a555613 */ #if defined(CONFIG_DYNAMIC_DEBUG) #define dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ diff --git a/scripts/gen-compat-config.sh b/scripts/gen-compat-config.sh index 00511c517370..8dd6f4c4f6ea 100755 --- a/scripts/gen-compat-config.sh +++ b/scripts/gen-compat-config.sh @@ -17,7 +17,7 @@ fi KERNEL_VERSION=$(${MAKE} -C ${KLIB_BUILD} kernelversion | sed -n 's/^\([0-9]\)\..*/\1/p') # 3.0 kernel stuff -COMPAT_LATEST_VERSION="8" +COMPAT_LATEST_VERSION="9" KERNEL_SUBLEVEL="-1" # Note that this script will export all variables explicitly, -- 2.30.2