linux/include/linux/devcoredump.h
<<
>>
Prefs
   1/*
   2 * This file is provided under the GPLv2 license.
   3 *
   4 * GPL LICENSE SUMMARY
   5 *
   6 * Copyright(c) 2015 Intel Deutschland GmbH
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of version 2 of the GNU General Public License as
  10 * published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 *
  17 * The full GNU General Public License is included in this distribution
  18 * in the file called COPYING.
  19 */
  20#ifndef __DEVCOREDUMP_H
  21#define __DEVCOREDUMP_H
  22
  23#include <linux/device.h>
  24#include <linux/module.h>
  25#include <linux/vmalloc.h>
  26
  27#include <linux/scatterlist.h>
  28#include <linux/slab.h>
  29
  30/*
  31 * _devcd_free_sgtable - free all the memory of the given scatterlist table
  32 * (i.e. both pages and scatterlist instances)
  33 * NOTE: if two tables allocated and chained using the sg_chain function then
  34 * this function should be called only once on the first table
  35 * @table: pointer to sg_table to free
  36 */
  37static inline void _devcd_free_sgtable(struct scatterlist *table)
  38{
  39        int i;
  40        struct page *page;
  41        struct scatterlist *iter;
  42        struct scatterlist *delete_iter;
  43
  44        /* free pages */
  45        iter = table;
  46        for_each_sg(table, iter, sg_nents(table), i) {
  47                page = sg_page(iter);
  48                if (page)
  49                        __free_page(page);
  50        }
  51
  52        /* then free all chained tables */
  53        iter = table;
  54        delete_iter = table;    /* always points on a head of a table */
  55        while (!sg_is_last(iter)) {
  56                iter++;
  57                if (sg_is_chain(iter)) {
  58                        iter = sg_chain_ptr(iter);
  59                        kfree(delete_iter);
  60                        delete_iter = iter;
  61                }
  62        }
  63
  64        /* free the last table */
  65        kfree(delete_iter);
  66}
  67
  68
  69#ifdef CONFIG_DEV_COREDUMP
  70void dev_coredumpv(struct device *dev, void *data, size_t datalen,
  71                   gfp_t gfp);
  72
  73void dev_coredumpm(struct device *dev, struct module *owner,
  74                   void *data, size_t datalen, gfp_t gfp,
  75                   ssize_t (*read)(char *buffer, loff_t offset, size_t count,
  76                                   void *data, size_t datalen),
  77                   void (*free)(void *data));
  78
  79void dev_coredumpsg(struct device *dev, struct scatterlist *table,
  80                    size_t datalen, gfp_t gfp);
  81#else
  82static inline void dev_coredumpv(struct device *dev, void *data,
  83                                 size_t datalen, gfp_t gfp)
  84{
  85        vfree(data);
  86}
  87
  88static inline void
  89dev_coredumpm(struct device *dev, struct module *owner,
  90              void *data, size_t datalen, gfp_t gfp,
  91              ssize_t (*read)(char *buffer, loff_t offset, size_t count,
  92                              void *data, size_t datalen),
  93              void (*free)(void *data))
  94{
  95        free(data);
  96}
  97
  98static inline void dev_coredumpsg(struct device *dev, struct scatterlist *table,
  99                                  size_t datalen, gfp_t gfp)
 100{
 101        _devcd_free_sgtable(table);
 102}
 103#endif /* CONFIG_DEV_COREDUMP */
 104
 105#endif /* __DEVCOREDUMP_H */
 106