Add a drm printer suitable for use with the read callback for
devcoredump or any other file operation read() function that
isn't otherwise covered by seq_file.

Signed-off-by: Jordan Crouse <jcro...@codeaurora.org>
---
 drivers/gpu/drm/drm_print.c | 54 +++++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_print.h     | 27 +++++++++++++++++++++++
 2 files changed, 81 insertions(+)

diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c
index 781518f..f6efde4 100644
--- a/drivers/gpu/drm/drm_print.c
+++ b/drivers/gpu/drm/drm_print.c
@@ -30,6 +30,60 @@
 #include <drm/drmP.h>
 #include <drm/drm_print.h>
 
+void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf)
+{
+       struct drm_print_iterator *iterator = p->arg;
+
+       ssize_t len;
+
+       if (!iterator->remain)
+               return;
+
+       if (iterator->offset < iterator->start) {
+               char *buf;
+               ssize_t copy;
+
+               /* Figure out how big the string will be */
+               len = snprintf(NULL, 0, "%pV", vaf);
+
+               if (iterator->offset + len <= iterator->start) {
+                       iterator->offset += len;
+                       return;
+               }
+
+               /* Print the string into a temporary buffer */
+               buf = kmalloc(len + 1,
+                       GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
+               if (!buf)
+                       return;
+
+               snprintf(buf, len + 1, "%pV", vaf);
+
+               copy = len - (iterator->start - iterator->offset);
+
+               if (copy > iterator->remain)
+                       copy = iterator->remain;
+
+               /* Copy out the bit of the string that we need */
+               memcpy(iterator->data,
+                       buf + (iterator->start - iterator->offset), copy);
+
+               iterator->offset = iterator->start + copy;
+               iterator->remain -= copy;
+
+               kfree(buf);
+       } else {
+               ssize_t pos = iterator->offset - iterator->start;
+
+               len = scnprintf(((char *) iterator->data) + pos,
+                       iterator->remain, "%pV", vaf);
+
+               iterator->offset += len;
+               iterator->remain -= len;
+       }
+}
+EXPORT_SYMBOL(__drm_printfn_coredump);
+
 void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf)
 {
        seq_printf(p->arg, "%pV", vaf);
diff --git a/include/drm/drm_print.h b/include/drm/drm_print.h
index 2a4a42e..29eee51 100644
--- a/include/drm/drm_print.h
+++ b/include/drm/drm_print.h
@@ -73,6 +73,7 @@ struct drm_printer {
        const char *prefix;
 };
 
+void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf);
 void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf);
 void __drm_printfn_info(struct drm_printer *p, struct va_format *vaf);
 void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf);
@@ -104,6 +105,32 @@ struct drm_printer {
 #define drm_printf_indent(printer, indent, fmt, ...) \
        drm_printf((printer), "%.*s" fmt, (indent), "\t\t\t\t\tX", 
##__VA_ARGS__)
 
+struct drm_print_iterator {
+       void *data;
+
+       ssize_t start;
+       ssize_t offset;
+       ssize_t remain;
+};
+
+/**
+ * drm_coredump_printer - construct a &drm_printer that can output to a buffer
+ * from the read function for devcoredump
+ * @iter: A pointer to a struct drm_print_iterator for the read instance
+ *
+ * RETURNS:
+ * The &drm_printer object
+ */
+static inline struct drm_printer
+drm_coredump_printer(struct drm_print_iterator *iter)
+{
+       struct drm_printer p = {
+               .printfn = __drm_printfn_coredump,
+               .arg = iter,
+       };
+       return p;
+}
+
 /**
  * drm_seq_file_printer - construct a &drm_printer that outputs to &seq_file
  * @f:  the &struct seq_file to output to
-- 
1.9.1

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to