devcoredump.h 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  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. #include <linux/device.h>
  8. #include <linux/module.h>
  9. #include <linux/vmalloc.h>
  10. #include <linux/scatterlist.h>
  11. #include <linux/slab.h>
  12. /*
  13. * _devcd_free_sgtable - free all the memory of the given scatterlist table
  14. * (i.e. both pages and scatterlist instances)
  15. * NOTE: if two tables allocated and chained using the sg_chain function then
  16. * this function should be called only once on the first table
  17. * @table: pointer to sg_table to free
  18. */
  19. static inline void _devcd_free_sgtable(struct scatterlist *table)
  20. {
  21. int i;
  22. struct page *page;
  23. struct scatterlist *iter;
  24. struct scatterlist *delete_iter;
  25. /* free pages */
  26. iter = table;
  27. for_each_sg(table, iter, sg_nents(table), i) {
  28. page = sg_page(iter);
  29. if (page)
  30. __free_page(page);
  31. }
  32. /* then free all chained tables */
  33. iter = table;
  34. delete_iter = table; /* always points on a head of a table */
  35. while (!sg_is_last(iter)) {
  36. iter++;
  37. if (sg_is_chain(iter)) {
  38. iter = sg_chain_ptr(iter);
  39. kfree(delete_iter);
  40. delete_iter = iter;
  41. }
  42. }
  43. /* free the last table */
  44. kfree(delete_iter);
  45. }
  46. #ifdef CONFIG_DEV_COREDUMP
  47. void dev_coredumpv(struct device *dev, void *data, size_t datalen,
  48. gfp_t gfp);
  49. void dev_coredumpm(struct device *dev, struct module *owner,
  50. void *data, size_t datalen, gfp_t gfp,
  51. ssize_t (*read)(char *buffer, loff_t offset, size_t count,
  52. void *data, size_t datalen),
  53. void (*free)(void *data));
  54. void dev_coredumpsg(struct device *dev, struct scatterlist *table,
  55. size_t datalen, gfp_t gfp);
  56. #else
  57. static inline void dev_coredumpv(struct device *dev, void *data,
  58. size_t datalen, gfp_t gfp)
  59. {
  60. vfree(data);
  61. }
  62. static inline void
  63. dev_coredumpm(struct device *dev, struct module *owner,
  64. void *data, size_t datalen, gfp_t gfp,
  65. ssize_t (*read)(char *buffer, loff_t offset, size_t count,
  66. void *data, size_t datalen),
  67. void (*free)(void *data))
  68. {
  69. free(data);
  70. }
  71. static inline void dev_coredumpsg(struct device *dev, struct scatterlist *table,
  72. size_t datalen, gfp_t gfp)
  73. {
  74. _devcd_free_sgtable(table);
  75. }
  76. #endif /* CONFIG_DEV_COREDUMP */
  77. #endif /* __DEVCOREDUMP_H */