]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
crypto: scatterwalk - Use nth_page instead of doing it by hand
authorHerbert Xu <herbert@gondor.apana.org.au>
Fri, 14 Mar 2025 03:27:20 +0000 (11:27 +0800)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 21 Mar 2025 09:33:39 +0000 (17:33 +0800)
Curiously, the Crypto API scatterwalk incremented pages by hand
rather than using nth_page.  Possibly because scatterwalk predates
nth_page (the following commit is from the history tree):

commit 3957f2b34960d85b63e814262a8be7d5ad91444d
Author: James Morris <jmorris@intercode.com.au>
Date:   Sun Feb 2 07:35:32 2003 -0800

    [CRYPTO]: in/out scatterlist support for ciphers.

Fix this by using nth_page.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
include/crypto/scatterwalk.h

index b7e617ae44427ac3a90458d371761260297bfd32..94a8585f26b267f0eddbccd5980a4bc45dc587d7 100644 (file)
@@ -100,11 +100,15 @@ static inline void scatterwalk_get_sglist(struct scatter_walk *walk,
 static inline void scatterwalk_map(struct scatter_walk *walk)
 {
        struct page *base_page = sg_page(walk->sg);
+       unsigned int offset = walk->offset;
+       void *addr;
 
        if (IS_ENABLED(CONFIG_HIGHMEM)) {
-               walk->__addr = kmap_local_page(base_page +
-                                              (walk->offset >> PAGE_SHIFT)) +
-                              offset_in_page(walk->offset);
+               struct page *page;
+
+               page = nth_page(base_page, offset >> PAGE_SHIFT);
+               offset = offset_in_page(offset);
+               addr = kmap_local_page(page) + offset;
        } else {
                /*
                 * When !HIGHMEM we allow the walker to return segments that
@@ -117,8 +121,10 @@ static inline void scatterwalk_map(struct scatter_walk *walk)
                 * in the direct map, but this makes it clearer what is really
                 * going on.
                 */
-               walk->__addr = page_address(base_page) + walk->offset;
+               addr = page_address(base_page) + offset;
        }
+
+       walk->__addr = addr;
 }
 
 /**
@@ -189,14 +195,18 @@ static inline void scatterwalk_done_dst(struct scatter_walk *walk,
         * reliably optimized out or not.
         */
        if (ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE) {
-               struct page *base_page, *start_page, *end_page, *page;
+               struct page *base_page;
+               unsigned int offset;
+               int start, end, i;
 
                base_page = sg_page(walk->sg);
-               start_page = base_page + (walk->offset >> PAGE_SHIFT);
-               end_page = base_page + ((walk->offset + nbytes +
-                                        PAGE_SIZE - 1) >> PAGE_SHIFT);
-               for (page = start_page; page < end_page; page++)
-                       flush_dcache_page(page);
+               offset = walk->offset;
+               start = offset >> PAGE_SHIFT;
+               end = start + (nbytes >> PAGE_SHIFT);
+               end += (offset_in_page(offset) + offset_in_page(nbytes) +
+                       PAGE_SIZE - 1) >> PAGE_SHIFT;
+               for (i = start; i < end; i++)
+                       flush_dcache_page(nth_page(base_page, i));
        }
        scatterwalk_advance(walk, nbytes);
 }