mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
90 lines
2.2 KiB
90 lines
2.2 KiB
/* SPDX-License-Identifier: GPL-2.0-only */ |
|
/* |
|
* Copyright(c) 2015 Intel Deutschland GmbH |
|
*/ |
|
#ifndef __DEVCOREDUMP_H |
|
#define __DEVCOREDUMP_H |
|
|
|
#include <linux/device.h> |
|
#include <linux/module.h> |
|
#include <linux/vmalloc.h> |
|
|
|
#include <linux/scatterlist.h> |
|
#include <linux/slab.h> |
|
|
|
/* |
|
* _devcd_free_sgtable - free all the memory of the given scatterlist table |
|
* (i.e. both pages and scatterlist instances) |
|
* NOTE: if two tables allocated and chained using the sg_chain function then |
|
* this function should be called only once on the first table |
|
* @table: pointer to sg_table to free |
|
*/ |
|
static inline void _devcd_free_sgtable(struct scatterlist *table) |
|
{ |
|
int i; |
|
struct page *page; |
|
struct scatterlist *iter; |
|
struct scatterlist *delete_iter; |
|
|
|
/* free pages */ |
|
iter = table; |
|
for_each_sg(table, iter, sg_nents(table), i) { |
|
page = sg_page(iter); |
|
if (page) |
|
__free_page(page); |
|
} |
|
|
|
/* then free all chained tables */ |
|
iter = table; |
|
delete_iter = table; /* always points on a head of a table */ |
|
while (!sg_is_last(iter)) { |
|
iter++; |
|
if (sg_is_chain(iter)) { |
|
iter = sg_chain_ptr(iter); |
|
kfree(delete_iter); |
|
delete_iter = iter; |
|
} |
|
} |
|
|
|
/* free the last table */ |
|
kfree(delete_iter); |
|
} |
|
|
|
|
|
#ifdef CONFIG_DEV_COREDUMP |
|
void dev_coredumpv(struct device *dev, void *data, size_t datalen, |
|
gfp_t gfp); |
|
|
|
void dev_coredumpm(struct device *dev, struct module *owner, |
|
void *data, size_t datalen, gfp_t gfp, |
|
ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
|
void *data, size_t datalen), |
|
void (*free)(void *data)); |
|
|
|
void dev_coredumpsg(struct device *dev, struct scatterlist *table, |
|
size_t datalen, gfp_t gfp); |
|
#else |
|
static inline void dev_coredumpv(struct device *dev, void *data, |
|
size_t datalen, gfp_t gfp) |
|
{ |
|
vfree(data); |
|
} |
|
|
|
static inline void |
|
dev_coredumpm(struct device *dev, struct module *owner, |
|
void *data, size_t datalen, gfp_t gfp, |
|
ssize_t (*read)(char *buffer, loff_t offset, size_t count, |
|
void *data, size_t datalen), |
|
void (*free)(void *data)) |
|
{ |
|
free(data); |
|
} |
|
|
|
static inline void dev_coredumpsg(struct device *dev, struct scatterlist *table, |
|
size_t datalen, gfp_t gfp) |
|
{ |
|
_devcd_free_sgtable(table); |
|
} |
|
#endif /* CONFIG_DEV_COREDUMP */ |
|
|
|
#endif /* __DEVCOREDUMP_H */
|
|
|