|
@@ -231,6 +231,41 @@ size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
|
|
|
*/
|
|
|
#define SG_MAX_SINGLE_ALLOC (PAGE_SIZE / sizeof(struct scatterlist))
|
|
|
|
|
|
+/*
|
|
|
+ * 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 */
|
|
|
+};
|
|
|
+
|
|
|
+bool __sg_page_iter_next(struct sg_page_iter *piter);
|
|
|
+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);)
|
|
|
|
|
|
/*
|
|
|
* Mapping sg iterator
|