Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f01d6e38 authored by Mitchel Humpherys's avatar Mitchel Humpherys Committed by Patrick Daly
Browse files

iommu/io-pgtable: Add memory stats debugfs file



It can be useful for debugging to know how much memory is being used for
IOMMU page tables.  Add some dedicated allocation functions and a
debugfs file for this.

Change-Id: Id69b4b1b5df5dcc6c604eec3a12a894b8eab0eb6
Signed-off-by: default avatarMitchel Humpherys <mitchelh@codeaurora.org>
Signed-off-by: default avatarPatrick Daly <pdaly@codeaurora.org>
parent c75ae496
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -286,7 +286,7 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
{
	struct device *dev = cfg->iommu_dev;
	dma_addr_t dma;
	void *pages = alloc_pages_exact(size, gfp | __GFP_ZERO);
	void *pages = io_pgtable_alloc_pages_exact(size, gfp | __GFP_ZERO);

	if (!pages)
		return NULL;
@@ -310,7 +310,7 @@ static void *__arm_lpae_alloc_pages(size_t size, gfp_t gfp,
	dev_err(dev, "Cannot accommodate DMA translation for IOMMU page tables\n");
	dma_unmap_single(dev, dma, size, DMA_TO_DEVICE);
out_free:
	free_pages_exact(pages, size);
	io_pgtable_free_pages_exact(pages, size);
	return NULL;
}

@@ -320,7 +320,7 @@ static void __arm_lpae_free_pages(void *pages, size_t size,
	if (!selftest_running)
		dma_unmap_single(cfg->iommu_dev, __arm_lpae_dma_addr(pages),
				 size, DMA_TO_DEVICE);
	free_pages_exact(pages, size);
	io_pgtable_free_pages_exact(pages, size);
}

static void __arm_lpae_set_pte(arm_lpae_iopte *ptep, arm_lpae_iopte pte,
+49 −0
Original line number Diff line number Diff line
@@ -18,9 +18,15 @@
 * Author: Will Deacon <will.deacon@arm.com>
 */

#define pr_fmt(fmt)	"io-pgtable: " fmt

#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/iommu.h>
#include <linux/debugfs.h>
#include <linux/atomic.h>
#include <linux/module.h>

#include "io-pgtable.h"

@@ -37,6 +43,8 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
#endif
};

static struct dentry *io_pgtable_top;

struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
					    struct io_pgtable_cfg *cfg,
					    void *cookie)
@@ -77,3 +85,44 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops)
	io_pgtable_tlb_flush_all(iop);
	io_pgtable_init_table[iop->fmt]->free(iop);
}

static atomic_t pages_allocated;

void *io_pgtable_alloc_pages_exact(size_t size, gfp_t gfp_mask)
{
	void *ret = alloc_pages_exact(size, gfp_mask);

	if (likely(ret))
		atomic_add(1 << get_order(size), &pages_allocated);
	return ret;
}

void io_pgtable_free_pages_exact(void *virt, size_t size)
{
	free_pages_exact(virt, size);
	atomic_sub(1 << get_order(size), &pages_allocated);
}

static int io_pgtable_init(void)
{
	io_pgtable_top = debugfs_create_dir("io-pgtable", iommu_debugfs_top);

	if (!io_pgtable_top)
		return -ENODEV;

	if (!debugfs_create_atomic_t("pages", 0600,
				     io_pgtable_top, &pages_allocated)) {
		debugfs_remove_recursive(io_pgtable_top);
		return -ENODEV;
	}

	return 0;
}

static void io_pgtable_exit(void)
{
	debugfs_remove_recursive(io_pgtable_top);
}

module_init(io_pgtable_init);
module_exit(io_pgtable_exit);
+22 −0
Original line number Diff line number Diff line
@@ -213,4 +213,26 @@ extern struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s1_init_fns;
extern struct io_pgtable_init_fns io_pgtable_arm_64_lpae_s2_init_fns;
extern struct io_pgtable_init_fns io_pgtable_arm_v7s_init_fns;

/**
 * io_pgtable_alloc_pages_exact:
 *	allocate an exact number of physically-contiguous pages.
 * @size: the number of bytes to allocate
 * @gfp_mask: GFP flags for the allocation
 *
 * Like alloc_pages_exact(), but with some additional accounting for debug
 * purposes.
 */
void *io_pgtable_alloc_pages_exact(size_t size, gfp_t gfp_mask);

/**
 * io_pgtable_free_pages_exact:
 *	release memory allocated via io_pgtable_alloc_pages_exact()
 * @virt: the value returned by alloc_pages_exact.
 * @size: size of allocation, same value as passed to alloc_pages_exact().
 *
 * Like free_pages_exact(), but with some additional accounting for debug
 * purposes.
 */
void io_pgtable_free_pages_exact(void *virt, size_t size);

#endif /* __IO_PGTABLE_H */