linux/crypto/scatterwalk.c
<<
>>
Prefs
   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#include <linux/kernel.h>
  17#include <linux/mm.h>
  18#include <linux/module.h>
  19#include <linux/pagemap.h>
  20#include <linux/highmem.h>
  21#include <linux/scatterlist.h>
  22
  23#include "internal.h"
  24#include "scatterwalk.h"
  25
  26enum km_type crypto_km_types[] = {
  27        KM_USER0,
  28        KM_USER1,
  29        KM_SOFTIRQ0,
  30        KM_SOFTIRQ1,
  31};
  32EXPORT_SYMBOL_GPL(crypto_km_types);
  33
  34static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
  35{
  36        void *src = out ? buf : sgdata;
  37        void *dst = out ? sgdata : buf;
  38
  39        memcpy(dst, src, nbytes);
  40}
  41
  42void scatterwalk_start(struct scatter_walk *walk, struct scatterlist *sg)
  43{
  44        walk->sg = sg;
  45
  46        BUG_ON(!sg->length);
  47
  48        walk->offset = sg->offset;
  49}
  50EXPORT_SYMBOL_GPL(scatterwalk_start);
  51
  52void *scatterwalk_map(struct scatter_walk *walk, int out)
  53{
  54        return crypto_kmap(scatterwalk_page(walk), out) +
  55               offset_in_page(walk->offset);
  56}
  57EXPORT_SYMBOL_GPL(scatterwalk_map);
  58
  59static void scatterwalk_pagedone(struct scatter_walk *walk, int out,
  60                                 unsigned int more)
  61{
  62        if (out)
  63                flush_dcache_page(scatterwalk_page(walk));
  64
  65        if (more) {
  66                walk->offset += PAGE_SIZE - 1;
  67                walk->offset &= PAGE_MASK;
  68                if (walk->offset >= walk->sg->offset + walk->sg->length)
  69                        scatterwalk_start(walk, sg_next(walk->sg));
  70        }
  71}
  72
  73void scatterwalk_done(struct scatter_walk *walk, int out, int more)
  74{
  75        if (!offset_in_page(walk->offset) || !more)
  76                scatterwalk_pagedone(walk, out, more);
  77}
  78EXPORT_SYMBOL_GPL(scatterwalk_done);
  79
  80void scatterwalk_copychunks(void *buf, struct scatter_walk *walk,
  81                            size_t nbytes, int out)
  82{
  83        for (;;) {
  84                unsigned int len_this_page = scatterwalk_pagelen(walk);
  85                u8 *vaddr;
  86
  87                if (len_this_page > nbytes)
  88                        len_this_page = nbytes;
  89
  90                vaddr = scatterwalk_map(walk, out);
  91                memcpy_dir(buf, vaddr, len_this_page, out);
  92                scatterwalk_unmap(vaddr, out);
  93
  94                if (nbytes == len_this_page)
  95                        break;
  96
  97                buf += len_this_page;
  98                nbytes -= len_this_page;
  99
 100                scatterwalk_pagedone(walk, out, 1);
 101        }
 102
 103        scatterwalk_advance(walk, nbytes);
 104}
 105EXPORT_SYMBOL_GPL(scatterwalk_copychunks);
 106
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.