at v4.15 2.8 kB view raw
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 */