]>
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); | |
833c9545 | 66 | #else |
52256637 | 67 | static inline void dev_coredumpv(struct device *dev, void *data, |
833c9545 JB |
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, | |
52256637 | 75 | void *data, size_t datalen, gfp_t gfp, |
833c9545 | 76 | ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
52256637 AE |
77 | void *data, size_t datalen), |
78 | void (*free)(void *data)) | |
833c9545 JB |
79 | { |
80 | free(data); | |
81 | } | |
52256637 AE |
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 | } | |
833c9545 JB |
88 | #endif /* CONFIG_DEV_COREDUMP */ |
89 | ||
90 | #endif /* __DEVCOREDUMP_H */ |