xref: /linux-6.15/include/linux/devcoredump.h (revision 77515eba)
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 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 
54 #ifdef CONFIG_DEV_COREDUMP
55 void dev_coredumpv(struct device *dev, void *data, size_t datalen);
56 
57 void dev_coredumpm(struct device *dev, struct module *owner,
58 		   void *data, size_t datalen,
59 		   ssize_t (*read)(char *buffer, loff_t offset, size_t count,
60 				   void *data, size_t datalen),
61 		   void (*free)(void *data));
62 
63 void dev_coredumpsg(struct device *dev, struct scatterlist *table,
64 		    size_t datalen);
65 #else
66 static inline void dev_coredumpv(struct device *dev, void *data,
67 				 size_t datalen)
68 {
69 	vfree(data);
70 }
71 
72 static inline void
73 dev_coredumpm(struct device *dev, struct module *owner,
74 	      void *data, size_t datalen,
75 	      ssize_t (*read)(char *buffer, loff_t offset, size_t count,
76 			      void *data, size_t datalen),
77 	      void (*free)(void *data))
78 {
79 	free(data);
80 }
81 
82 static inline void dev_coredumpsg(struct device *dev, struct scatterlist *table,
83 				  size_t datalen)
84 {
85 	_devcd_free_sgtable(table);
86 }
87 #endif /* CONFIG_DEV_COREDUMP */
88 
89 #endif /* __DEVCOREDUMP_H */
90