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 : 0 : int i;
25 : 0 : struct page *page;
26 : 0 : struct scatterlist *iter;
27 : 0 : struct scatterlist *delete_iter;
28 : :
29 : : /* free pages */
30 : 0 : iter = table;
31 [ # # ]: 0 : for_each_sg(table, iter, sg_nents(table), i) {
32 [ # # ]: 0 : 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 : 0 : 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 */
|