Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-only */ 2 : : /* 3 : : * Copyright(c) 2015 Intel Deutschland GmbH 4 : : */ 5 : : #ifndef __DEVCOREDUMP_H 6 : : #define __DEVCOREDUMP_H 7 : : 8 : : #include <linux/device.h> 9 : : #include <linux/module.h> 10 : : #include <linux/vmalloc.h> 11 : : 12 : : #include <linux/scatterlist.h> 13 : : #include <linux/slab.h> 14 : : 15 : : /* 16 : : * _devcd_free_sgtable - free all the memory of the given scatterlist table 17 : : * (i.e. both pages and scatterlist instances) 18 : : * NOTE: if two tables allocated and chained using the sg_chain function then 19 : : * this function should be called only once on the first table 20 : : * @table: pointer to sg_table to free 21 : : */ 22 : 0 : static inline void _devcd_free_sgtable(struct scatterlist *table) 23 : : { 24 : : int i; 25 : : struct page *page; 26 : : struct scatterlist *iter; 27 : : struct scatterlist *delete_iter; 28 : : 29 : : /* free pages */ 30 : : iter = table; 31 : 0 : for_each_sg(table, iter, sg_nents(table), i) { 32 : : page = sg_page(iter); 33 : 0 : if (page) 34 : 0 : __free_page(page); 35 : : } 36 : : 37 : : /* then free all chained tables */ 38 : : iter = table; 39 : : delete_iter = table; /* always points on a head of a table */ 40 : 0 : while (!sg_is_last(iter)) { 41 : 0 : iter++; 42 : 0 : if (sg_is_chain(iter)) { 43 : 0 : iter = sg_chain_ptr(iter); 44 : 0 : kfree(delete_iter); 45 : : delete_iter = iter; 46 : : } 47 : : } 48 : : 49 : : /* free the last table */ 50 : 0 : kfree(delete_iter); 51 : 0 : } 52 : : 53 : : 54 : : #ifdef CONFIG_DEV_COREDUMP 55 : : void dev_coredumpv(struct device *dev, void *data, size_t datalen, 56 : : gfp_t gfp); 57 : : 58 : : void dev_coredumpm(struct device *dev, struct module *owner, 59 : : void *data, size_t datalen, gfp_t gfp, 60 : : ssize_t (*read)(char *buffer, loff_t offset, size_t count, 61 : : void *data, size_t datalen), 62 : : void (*free)(void *data)); 63 : : 64 : : void dev_coredumpsg(struct device *dev, struct scatterlist *table, 65 : : size_t datalen, gfp_t gfp); 66 : : #else 67 : : static inline void dev_coredumpv(struct device *dev, void *data, 68 : : size_t datalen, gfp_t gfp) 69 : : { 70 : : vfree(data); 71 : : } 72 : : 73 : : static inline void 74 : : dev_coredumpm(struct device *dev, struct module *owner, 75 : : void *data, size_t datalen, gfp_t gfp, 76 : : ssize_t (*read)(char *buffer, loff_t offset, size_t count, 77 : : void *data, size_t datalen), 78 : : void (*free)(void *data)) 79 : : { 80 : : free(data); 81 : : } 82 : : 83 : : static inline void dev_coredumpsg(struct device *dev, struct scatterlist *table, 84 : : size_t datalen, gfp_t gfp) 85 : : { 86 : : _devcd_free_sgtable(table); 87 : : } 88 : : #endif /* CONFIG_DEV_COREDUMP */ 89 : : 90 : : #endif /* __DEVCOREDUMP_H */