[RFC 5/8] lib: add small API for handling register snapshots
Dmitry Baryshkov
dmitry.baryshkov at linaro.org
Sat May 29 00:25:05 UTC 2021
Add small API covering lists of register dumps. Currently this is a part
of MSM DRM driver, but is extracted as it might be usefull to other
drivers too.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov at linaro.org>
---
include/linux/dump_state.h | 78 ++++++++++++++++++++++++++++++++++++++
lib/Kconfig | 3 ++
lib/Makefile | 1 +
lib/dump_state.c | 51 +++++++++++++++++++++++++
4 files changed, 133 insertions(+)
create mode 100644 include/linux/dump_state.h
create mode 100644 lib/dump_state.c
diff --git a/include/linux/dump_state.h b/include/linux/dump_state.h
new file mode 100644
index 000000000000..9cf2cd2e99a6
--- /dev/null
+++ b/include/linux/dump_state.h
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021, Linaro Ltd
+ */
+
+#ifndef LINUX_DUMP_STATE_H
+#define LINUX_DUMP_STATE_H
+
+#include <linux/list.h>
+#include <linux/sizes.h>
+
+/**
+ * struct dump_state_block - structure to store each hardware block state
+ * @name: name of the block
+ * @drm_dev: handle to the linked list head
+ * @size: size of the register space of this hardware block
+ * @state: array holding the register dump of this hardware block
+ * @base_addr: starting address of this hardware block's register space
+ */
+struct dump_state_block {
+ char name[SZ_128];
+ struct list_head node;
+ void __iomem *base_addr;
+ size_t size;
+ u8 state[0] __aligned(8);
+};
+
+/**
+ * struct dump_state - structure to store reg dump state
+ * @blocks: hardware blocks info related to this dump state
+ */
+struct dump_state {
+ struct list_head blocks;
+};
+
+static inline void dump_state_init(struct dump_state *state)
+{
+ INIT_LIST_HEAD(&state->blocks);
+}
+
+#define dump_state_for_each_block(state, block) \
+ list_for_each_entry(block, &(state)->blocks, node)
+
+/**
+ * dump_state_free_blocks - free allocated blocks
+ * @state: handle to struct dump_state
+ */
+void dump_state_free_blocks(struct dump_state *state);
+
+/**
+ * dump_state_allocate_block - allocate data block for register dumps
+ * @len: size of the register space of the hardware block
+ * @base_addr: starting address of the register space of the hardware block
+ * @gfp: type of memory allocation
+ * @fmt: format in which the block names need to be printed
+ *
+ * Returns: new block
+ */
+extern __printf(4, 5)
+struct dump_state_block *dump_state_allocate_block(void __iomem *base_addr, size_t len, gfp_t gfp, const char *fmt, ...);
+
+/**
+ * dump_state_allocate_block_va - allocate data block for register dumps
+ * @len: size of the register space of the hardware block
+ * @base_addr: starting address of the register space of the hardware block
+ * @gfp: type of memory allocation
+ * @fmt: format in which the block names need to be printed
+ *
+ * Returns: new block
+ */
+extern __printf(4, 0)
+struct dump_state_block *dump_state_allocate_block_va(void __iomem *base_addr, size_t len, gfp_t gfp, const char *fmt, va_list args);
+
+#define dump_state_add_block(state, block) \
+ list_add_tail(&(state)->blocks, &(block)->node)
+
+#endif
diff --git a/lib/Kconfig b/lib/Kconfig
index ac3b30697b2b..ab654232ecb6 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -704,3 +704,6 @@ config PLDMFW
config ASN1_ENCODER
tristate
+
+config DUMP_STATE
+ tristate
diff --git a/lib/Makefile b/lib/Makefile
index 2cc359ec1fdd..4836a0e3aef2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -356,3 +356,4 @@ obj-$(CONFIG_BITS_TEST) += test_bits.o
obj-$(CONFIG_CMDLINE_KUNIT_TEST) += cmdline_kunit.o
obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o
+obj-$(CONFIG_DUMP_STATE) += dump_state.o
diff --git a/lib/dump_state.c b/lib/dump_state.c
new file mode 100644
index 000000000000..58d88be65c0a
--- /dev/null
+++ b/lib/dump_state.c
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021, Linaro Ltd
+ */
+
+#include <linux/dump_state.h>
+#include <linux/slab.h>
+
+void dump_state_free_blocks(struct dump_state *state)
+{
+ struct dump_state_block *block, *tmp;
+
+ list_for_each_entry_safe(block, tmp, &state->blocks, node) {
+ list_del(&block->node);
+ kfree(block);
+ }
+}
+EXPORT_SYMBOL(dump_state_free_blocks);
+
+struct dump_state_block *dump_state_allocate_block_va(void __iomem *base_addr, size_t len, gfp_t gfp, const char *fmt, va_list args)
+{
+ struct dump_state_block *block = kzalloc(sizeof(*block) + len, gfp);
+
+ if (!block)
+ return ERR_PTR(-ENOMEM);
+
+ vsnprintf(block->name, sizeof(block->name), fmt, args);
+
+ INIT_LIST_HEAD(&block->node);
+ block->size = len;
+ block->base_addr = base_addr;
+
+ return block;
+}
+EXPORT_SYMBOL(dump_state_allocate_block);
+
+struct dump_state_block *dump_state_allocate_block(void __iomem *base_addr, size_t len, gfp_t gfp, const char *fmt, ...)
+{
+ struct dump_state_block *block;
+ va_list va;
+
+ va_start(va, fmt);
+
+ block = dump_state_allocate_block_va(base_addr, len, gfp, fmt, va);
+
+ va_end(va);
+
+ return block;
+}
+EXPORT_SYMBOL(dump_state_allocate_block_va);
--
2.30.2
More information about the dri-devel
mailing list