The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/crypto/scatterwalk.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Cryptographic API.
    3  *
    4  * Cipher operations.
    5  *
    6  * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
    7  *               2002 Adam J. Richter <adam@yggdrasil.com>
    8  *               2004 Jean-Luc Cooke <jlcooke@certainkey.com>
    9  *
   10  * This program is free software; you can redistribute it and/or modify it
   11  * under the terms of the GNU General Public License as published by the Free
   12  * Software Foundation; either version 2 of the License, or (at your option)
   13  * any later version.
   14  *
   15  */
   16 
   17 #include <crypto/scatterwalk.h>
   18 #include <linux/kernel.h>
   19 #include <linux/mm.h>
   20 #include <linux/module.h>
   21 #include <linux/pagemap.h>
   22 #include <linux/highmem.h>
   23 #include <linux/scatterlist.h>
   24 
   25 static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
   26 {
   27         void *src = out ? buf : sgdata;
   28         void *dst = out ? sgdata : buf;
   29 
   30         memcpy(dst, src, nbytes);
   31 }
   32 
   33 void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
   34 {
   35         walk->sg = sg;
   36 
   37         BUG_ON(!sg->length);
   38 
   39         walk->offset = sg->offset;
   40 }
   41 EXPORT_SYMBOL_GPL(scatterwalk_start);
   42 
   43 void *scatterwalk_map(struct scatter_walk *walk)
   44 {
   45         return kmap_atomic(scatterwalk_page(walk)) +
   46                offset_in_page(walk->offset);
   47 }
   48 EXPORT_SYMBOL_GPL(scatterwalk_map);
   49 
   50 static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
   51                                  unsigned int more)
   52 {
   53         if (out) {
   54                 struct page *page;
   55 
   56                 page = sg_page(walk->sg) + ((walk->offset - 1) >> PAGE_SHIFT);
   57                 if (!PageSlab(page))
   58                         flush_dcache_page(page);
   59         }
   60 
   61         if (more) {
   62                 walk->offset += PAGE_SIZE - 1;
   63                 walk->offset &= PAGE_MASK;
   64                 if (walk->offset >= walk->sg->offset + walk->sg->length)
   65                         scatterwalk_start(walk, scatterwalk_sg_next(walk->sg));
   66         }
   67 }
   68 
   69 void scatterwalk_done(struct scatter_walk *walk, int out, int more)
   70 {
   71         if (!(scatterwalk_pagelen(walk) & (PAGE_SIZE - 1)) || !more)
   72                 scatterwalk_pagedone(walk, out, more);
   73 }
   74 EXPORT_SYMBOL_GPL(scatterwalk_done);
   75 
   76 void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
   77                             size_t nbytes, int out)
   78 {
   79         for (;;) {
   80                 unsigned int len_this_page = scatterwalk_pagelen(walk);
   81                 u8 *vaddr;
   82 
   83                 if (len_this_page > nbytes)
   84                         len_this_page = nbytes;
   85 
   86                 vaddr = scatterwalk_map(walk);
   87                 memcpy_dir(buf, vaddr, len_this_page, out);
   88                 scatterwalk_unmap(vaddr);
   89 
   90                 scatterwalk_advance(walk, len_this_page);
   91 
   92                 if (nbytes == len_this_page)
   93                         break;
   94 
   95                 buf += len_this_page;
   96                 nbytes -= len_this_page;
   97 
   98                 scatterwalk_pagedone(walk, out, 1);
   99         }
  100 }
  101 EXPORT_SYMBOL_GPL(scatterwalk_copychunks);
  102 
  103 void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg,
  104                               unsigned int start, unsigned int nbytes, int out)
  105 {
  106         struct scatter_walk walk;
  107         unsigned int offset = 0;
  108 
  109         if (!nbytes)
  110                 return;
  111 
  112         for (;;) {
  113                 scatterwalk_start(&walk, sg);
  114 
  115                 if (start < offset + sg->length)
  116                         break;
  117 
  118                 offset += sg->length;
  119                 sg = scatterwalk_sg_next(sg);
  120         }
  121 
  122         scatterwalk_advance(&walk, start - offset);
  123         scatterwalk_copychunks(buf, &walk, nbytes, out);
  124         scatterwalk_done(&walk, out, 0);
  125 }
  126 EXPORT_SYMBOL_GPL(scatterwalk_map_and_copy);

Cache object: cc139b8334c484df1ef5f849b0b32c50


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.