diff --git a/drivers/soc/rockchip/Kconfig b/drivers/soc/rockchip/Kconfig index 4410c67928df..968a3edafef4 100644 --- a/drivers/soc/rockchip/Kconfig +++ b/drivers/soc/rockchip/Kconfig @@ -220,6 +220,16 @@ config RK_CMA_PROCFS Turns on the ProcFS interface for CMA, shows the bitmap in hex format. +config RK_DMABUF_PROCFS + tristate "DMABUF procfs support" + depends on DMA_SHARED_BUFFER + depends on PROC_FS + help + Turns on this to create a procfs debug interface for dma-buf, support + get information from db_list by get_each_dmabuf. + + If unsure, say "N". + config RK_MEMBLOCK_PROCFS bool "Memblock procfs for reserved memory" depends on PROC_FS && ARCH_KEEP_MEMBLOCK diff --git a/drivers/soc/rockchip/Makefile b/drivers/soc/rockchip/Makefile index 3c44a79eeb48..20f4fe6fedaf 100644 --- a/drivers/soc/rockchip/Makefile +++ b/drivers/soc/rockchip/Makefile @@ -25,4 +25,5 @@ obj-$(CONFIG_ROCKCHIP_THUNDER_BOOT_SFC) += rockchip_thunderboot_sfc.o obj-$(CONFIG_ROCKCHIP_DEBUG) += rockchip_debug.o obj-$(CONFIG_ROCKCHIP_NPOR_POWERGOOD) += rockchip_npor_powergood.o obj-$(CONFIG_RK_CMA_PROCFS) += rk_cma_procfs.o +obj-$(CONFIG_RK_DMABUF_PROCFS) += rk_dmabuf_procfs.o obj-$(CONFIG_RK_MEMBLOCK_PROCFS) += rk_memblock_procfs.o diff --git a/drivers/soc/rockchip/rk_dmabuf_procfs.c b/drivers/soc/rockchip/rk_dmabuf_procfs.c new file mode 100644 index 000000000000..d65d68ea749d --- /dev/null +++ b/drivers/soc/rockchip/rk_dmabuf_procfs.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 Rockchip Electronics Co. Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define K(size) ((unsigned long)((size) >> 10)) +static struct device *dmabuf_dev; + +static void rk_dmabuf_dump_empty_sgt(struct dma_buf *dmabuf, void *private) +{ + struct dma_buf *db = (struct dma_buf *)dmabuf; + struct dma_buf_attachment *a; + struct seq_file *s = private; + struct scatterlist *sg; + struct sg_table *sgt; + phys_addr_t end, len; + int i; + + a = dma_buf_attach(db, dmabuf_dev); + if (IS_ERR(a)) + return; + + sgt = dma_buf_map_attachment(a, DMA_BIDIRECTIONAL); + if (IS_ERR(sgt)) { + dma_buf_detach(db, a); + return; + } + + for_each_sgtable_sg(sgt, sg, i) { + end = sg->dma_address + sg->length - 1; + len = sg->length; + if (i) + seq_printf(s, "%48s", " "); + else + seq_printf(s, "%-16.16s %-16.16s %10lu KiB", + dmabuf->name, + dmabuf->exp_name, K(dmabuf->size)); + seq_printf(s, "%4d: %pa..%pa (%10lu %s)\n", i, + &sg->dma_address, &end, + (len >> 10) ? (K(len)) : (unsigned long)len, + (len >> 10) ? "KiB" : "Bytes"); + } + dma_buf_unmap_attachment(a, sgt, DMA_BIDIRECTIONAL); + dma_buf_detach(db, a); +} + +static void rk_dmabuf_dump_sgt(struct dma_buf *dmabuf, void *private) +{ + struct seq_file *s = private; + struct scatterlist *sg; + struct dma_buf_attachment *a, *t; + phys_addr_t end, len; + int i; + + if (list_empty(&dmabuf->attachments)) + return rk_dmabuf_dump_empty_sgt(dmabuf, s); + + list_for_each_entry_safe(a, t, &dmabuf->attachments, node) { + if (!a->sgt) + continue; + for_each_sgtable_sg(a->sgt, sg, i) { + end = sg->dma_address + sg->length - 1; + len = sg->length; + if (i) + seq_printf(s, "%48s", " "); + else + seq_printf(s, "%-16.16s %-16.16s %10lu KiB", + dmabuf->name, + dmabuf->exp_name, K(dmabuf->size)); + seq_printf(s, "%4d: %pa..%pa (%10lu %s)\n", i, + &sg->dma_address, &end, + (len >> 10) ? (K(len)) : (unsigned long)len, + (len >> 10) ? "KiB" : "Bytes"); + } + break; + } +} + +static int rk_dmabuf_cb(const struct dma_buf *dmabuf, void *private) +{ + struct seq_file *s = private; + struct dma_buf *db = (struct dma_buf *)dmabuf; + + rk_dmabuf_dump_sgt(db, s); + + return 0; +} + +static int rk_dmabuf_cb2(const struct dma_buf *dmabuf, void *private) +{ + *((unsigned long *)private) += dmabuf->size; + + return 0; +} + +static int rk_dmabuf_show(struct seq_file *s, void *v) +{ + int ret; + unsigned long total_size = 0; + + seq_printf(s, "%-16s %-16s %14s %8s\n\n", + "NAME", "EXPORT", "SIZE:KiB", "SGLIST"); + + ret = get_each_dmabuf(rk_dmabuf_cb, s); + if (ret) + return ret; + + ret = get_each_dmabuf(rk_dmabuf_cb2, &total_size); + if (ret) + return ret; + + seq_printf(s, "Total: %lu KiB\n", K(total_size)); + + return 0; +} + +static int __init rk_dmabuf_init(void) +{ + struct platform_device *pdev; + struct platform_device_info dev_info = { + .name = "dmabuf", + .id = PLATFORM_DEVID_NONE, + .dma_mask = DMA_BIT_MASK(64), + }; + + pdev = platform_device_register_full(&dev_info); + dmabuf_dev = pdev ? &pdev->dev : NULL; + + proc_create_single("rk_dmabuf", 0, NULL, rk_dmabuf_show); + + return 0; +} +late_initcall_sync(rk_dmabuf_init); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Jianqun Xu "); +MODULE_DESCRIPTION("ROCKCHIP DMABUF Driver"); +MODULE_ALIAS("platform:rk-dmabuf");