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

Commit 423b064d authored by Jordan Crouse's avatar Jordan Crouse
Browse files

msm: kgsl: Add a function to map global buffers



Currently all global buffers are mapped when pagetables are created which
means that all global buffers need to be in place before the default
pagetable is created otherwise they will not be available in that context.
Add a new MMU function to map each global buffer. If the default pagetable
has been created then the new buffer can be mapped immediately, otherwise
all the buffers on the list will be mapped when the pagetable finally comes
along. Per-process pagetables will map everything from the list at create
time as they do now.

As a caveat this function only applies to the default pagetable. We will
not go back and retroactively map buffers into existing per-process
pagetables. Previously if somebody mapped a global buffer late it
wouldn't be available in the default pagetable either so it was easier to
debug. Now that this function will always successfully map buffers in the
default pagetable "late" buffers that got missed in a per-process table
will be harder to debug. In recognition of this the new map function will
trigger a warning if a buffer is mapped after the first per-process
pagetable is created. It won't stop breakage from happening but at least
it will be more easily debuggable.

Change-Id: Ic0dedbad2ed20769ea96bfdac3b707a30c6f9737
Signed-off-by: default avatarJordan Crouse <jcrouse@codeaurora.org>
parent f7a35f03
Loading
Loading
Loading
Loading
+27 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2011-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/compat.h>
@@ -88,6 +88,29 @@ static void kgsl_iommu_map_globals(struct kgsl_mmu *mmu,
		kgsl_mmu_map(pagetable, &md->memdesc);
}

static void kgsl_iommu_map_global(struct kgsl_mmu *mmu,
		struct kgsl_memdesc *memdesc)
{
	struct kgsl_iommu *iommu = _IOMMU_PRIV(mmu);

	/*
	 * If the global pagetable hasn't been created yet, do nothing. We'll
	 * get them all in one big swoop at create time
	 */
	if (!mmu->defaultpagetable)
		return;

	/*
	 * Warn if a global is added after first per-process pagetables have
	 * been created since we do not go back and retroactively add the
	 * globals to existing pages
	 */
	WARN_ON(iommu->ppt_active);

	/* Map the buffer in the default pagetable */
	kgsl_mmu_map(mmu->defaultpagetable, memdesc);
}

static u64 kgsl_iommu_get_global_base(struct kgsl_mmu *mmu)
{
	return KGSL_IOMMU_GLOBAL_MEM_BASE(mmu);
@@ -1108,6 +1131,8 @@ static int _init_per_process_pt(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt)
		goto done;
	}

	iommu->ppt_active = true;

	kgsl_iommu_map_globals(mmu, pt);

done:
@@ -2383,6 +2408,7 @@ struct kgsl_mmu_ops kgsl_iommu_ops = {
	.mmu_init_pt = kgsl_iommu_init_pt,
	.mmu_getpagetable = kgsl_iommu_getpagetable,
	.mmu_get_global_base = kgsl_iommu_get_global_base,
	.mmu_map_global = kgsl_iommu_map_global,
	.probe = kgsl_iommu_probe,
};

+7 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
 */
#ifndef __KGSL_IOMMU_H
#define __KGSL_IOMMU_H
@@ -124,6 +124,12 @@ struct kgsl_iommu {
	struct kgsl_memdesc *smmu_info;
	/** @pdev: Pointer to the platform device for the IOMMU device */
	struct platform_device *pdev;
	/**
	 * @ppt_active: Set when the first per process pagetable is created.
	 * This is used to warn when global buffers are created that might not
	 * be mapped in all contexts
	 */
	bool ppt_active;
};

/*
+10 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/slab.h>
@@ -537,6 +537,15 @@ u64 kgsl_mmu_get_global_base(struct kgsl_device *device)
	return 0;
}

void kgsl_mmu_map_global(struct kgsl_device *device,
		struct kgsl_memdesc *memdesc)
{
	struct kgsl_mmu *mmu = &(device->mmu);

	if (MMU_OP_VALID(mmu, mmu_map_global))
		mmu->mmu_ops->mmu_map_global(mmu, memdesc);
}

void kgsl_mmu_close(struct kgsl_device *device)
{
	struct kgsl_mmu *mmu = &(device->mmu);
+13 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
 */
#ifndef __KGSL_MMU_H
#define __KGSL_MMU_H
@@ -71,6 +71,8 @@ struct kgsl_mmu_ops {
	struct kgsl_pagetable * (*mmu_getpagetable)(struct kgsl_mmu *mmu,
			unsigned long name);
	u64 (*mmu_get_global_base)(struct kgsl_mmu *mmu);
	void (*mmu_map_global)(struct kgsl_mmu *mmu,
		struct kgsl_memdesc *memdesc);
};

struct kgsl_mmu_pt_ops {
@@ -344,4 +346,14 @@ kgsl_mmu_pagetable_get_contextidr(struct kgsl_pagetable *pagetable)
 */
u64 kgsl_mmu_get_global_base(struct kgsl_device *device);

/**
 * kgsl_mmu_map_global - Map a memdesc as a global buffer
 * @device: A KGSL GPU device handle
 * @memdesc: Pointer to a GPU memory descriptor
 *
 * Map a buffer as globally accessible in all pagetable contexts
 */
void kgsl_mmu_map_global(struct kgsl_device *device,
		struct kgsl_memdesc *memdesc);

#endif /* __KGSL_MMU_H */
+5 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2002,2007-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
 */

#include <asm/cacheflush.h>
@@ -1325,6 +1325,8 @@ struct kgsl_memdesc *kgsl_allocate_global_fixed(struct kgsl_device *device,
	 */
	list_add_tail(&md->node, &device->globals);

	kgsl_mmu_map_global(device, &md->memdesc);

	return &md->memdesc;
}

@@ -1374,6 +1376,8 @@ struct kgsl_memdesc *kgsl_allocate_global(struct kgsl_device *device,
	 */
	list_add_tail(&md->node, &device->globals);

	kgsl_mmu_map_global(device, &md->memdesc);

	return &md->memdesc;
}