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 */ 37 static 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 70 void dev_coredumpv(struct device *dev, void *data, size_t datalen, 71 gfp_t gfp); 72 73 void 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 79 void dev_coredumpsg(struct device *dev, struct scatterlist *table, 80 size_t datalen, gfp_t gfp); 81 #else 82 static inline void dev_coredumpv(struct device *dev, void *data, 83 size_t datalen, gfp_t gfp) 84 { 85 vfree(data); 86 } 87 88 static inline void 89 dev_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 98 static 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