Commit | Line | Data |
---|---|---|
52256637 AE |
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 | */ | |
833c9545 JB |
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 | ||
52256637 AE |
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 | ||
833c9545 | 69 | #ifdef CONFIG_DEV_COREDUMP |
52256637 | 70 | void dev_coredumpv(struct device *dev, void *data, size_t datalen, |
833c9545 JB |
71 | gfp_t gfp); |
72 | ||
73 | void dev_coredumpm(struct device *dev, struct module *owner, | |
52256637 | 74 | void *data, size_t datalen, gfp_t gfp, |
833c9545 | 75 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
52256637 AE |
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); | |
833c9545 | 81 | #else |
52256637 | 82 | static inline void dev_coredumpv(struct device *dev, void *data, |
833c9545 JB |
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, | |
52256637 | 90 | void *data, size_t datalen, gfp_t gfp, |
833c9545 | 91 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
52256637 AE |
92 | void *data, size_t datalen), |
93 | void (*free)(void *data)) | |
833c9545 JB |
94 | { |
95 | free(data); | |
96 | } | |
52256637 AE |
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 | } | |
833c9545 JB |
103 | #endif /* CONFIG_DEV_COREDUMP */ |
104 | ||
105 | #endif /* __DEVCOREDUMP_H */ |