]>
Commit | Line | Data |
---|---|---|
0b156947 | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
52256637 | 2 | /* |
52256637 | 3 | * Copyright(c) 2015 Intel Deutschland GmbH |
52256637 | 4 | */ |
833c9545 JB |
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 | ||
52256637 AE |
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 | 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 | for_each_sg(table, iter, sg_nents(table), i) { | |
32 | page = sg_page(iter); | |
33 | if (page) | |
34 | __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 | while (!sg_is_last(iter)) { | |
41 | iter++; | |
42 | if (sg_is_chain(iter)) { | |
43 | iter = sg_chain_ptr(iter); | |
44 | kfree(delete_iter); | |
45 | delete_iter = iter; | |
46 | } | |
47 | } | |
48 | ||
49 | /* free the last table */ | |
50 | kfree(delete_iter); | |
51 | } | |
52 | ||
53 | ||
833c9545 | 54 | #ifdef CONFIG_DEV_COREDUMP |
52256637 | 55 | void dev_coredumpv(struct device *dev, void *data, size_t datalen, |
833c9545 JB |
56 | gfp_t gfp); |
57 | ||
58 | void dev_coredumpm(struct device *dev, struct module *owner, | |
52256637 | 59 | void *data, size_t datalen, gfp_t gfp, |
833c9545 | 60 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
52256637 AE |
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); | |
a28380f1 JRS |
66 | |
67 | void dev_coredump_put(struct device *dev); | |
833c9545 | 68 | #else |
52256637 | 69 | static inline void dev_coredumpv(struct device *dev, void *data, |
833c9545 JB |
70 | size_t datalen, gfp_t gfp) |
71 | { | |
72 | vfree(data); | |
73 | } | |
74 | ||
75 | static inline void | |
76 | dev_coredumpm(struct device *dev, struct module *owner, | |
52256637 | 77 | void *data, size_t datalen, gfp_t gfp, |
833c9545 | 78 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
52256637 AE |
79 | void *data, size_t datalen), |
80 | void (*free)(void *data)) | |
833c9545 JB |
81 | { |
82 | free(data); | |
83 | } | |
52256637 AE |
84 | |
85 | static inline void dev_coredumpsg(struct device *dev, struct scatterlist *table, | |
86 | size_t datalen, gfp_t gfp) | |
87 | { | |
88 | _devcd_free_sgtable(table); | |
89 | } | |
a28380f1 JRS |
90 | static inline void dev_coredump_put(struct device *dev) |
91 | { | |
92 | } | |
833c9545 JB |
93 | #endif /* CONFIG_DEV_COREDUMP */ |
94 | ||
95 | #endif /* __DEVCOREDUMP_H */ |