]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - include/linux/devcoredump.h
ptr_ring: array based FIFO for pointers
[karo-tx-linux.git] / include / linux / devcoredump.h
index c0a360e99f6486fdb1a4e6554e8538260bedbc9e..269521f143ac254240ac6510f8fbdcb5412fd809 100644 (file)
@@ -1,3 +1,22 @@
+/*
+ * This file is provided under the GPLv2 license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2015 Intel Deutschland GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ */
 #ifndef __DEVCOREDUMP_H
 #define __DEVCOREDUMP_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, const void *data, size_t datalen,
+void dev_coredumpv(struct device *dev, void *data, size_t datalen,
                   gfp_t gfp);
 
 void dev_coredumpm(struct device *dev, struct module *owner,
-                  const void *data, size_t datalen, gfp_t gfp,
+                  void *data, size_t datalen, gfp_t gfp,
                   ssize_t (*read)(char *buffer, loff_t offset, size_t count,
-                                  const void *data, size_t datalen),
-                  void (*free)(const void *data));
+                                  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, const void *data,
+static inline void dev_coredumpv(struct device *dev, void *data,
                                 size_t datalen, gfp_t gfp)
 {
        vfree(data);
@@ -23,13 +87,19 @@ static inline void dev_coredumpv(struct device *dev, const void *data,
 
 static inline void
 dev_coredumpm(struct device *dev, struct module *owner,
-             const void *data, size_t datalen, gfp_t gfp,
+             void *data, size_t datalen, gfp_t gfp,
              ssize_t (*read)(char *buffer, loff_t offset, size_t count,
-                             const void *data, size_t datalen),
-             void (*free)(const void *data))
+                             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 */