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

Commit 1615787f authored by Raghu Ananya Arabolu's avatar Raghu Ananya Arabolu
Browse files

msm: kgsl: Do not suppress page faults due to UCHE overfetch



Do not suppress read pagefaults where the faulting address lies within the
first 64 bytes of a page (UCHE line size is 64 bytes) and the fault page is
preceded by a valid allocation. This page fault is likely due to UCHE
overfetch. The page fault logs print the faulting address, faulting block
and nearby memory. From the logs it can be inferred that the page fault is
due to UCHE overfetch.

Change-Id: Ic7d3ad114620f9233e7e51859c1ce56418ca2b9b
Signed-off-by: default avatarRaghu Ananya Arabolu <rarabolu@codeaurora.org>
parent af96f07f
Loading
Loading
Loading
Loading
+0 −48
Original line number Diff line number Diff line
@@ -694,48 +694,6 @@ static void _check_if_freed(struct kgsl_iommu_context *ctx,
	}
}

static bool
kgsl_iommu_uche_overfetch(struct kgsl_process_private *private,
		uint64_t faultaddr)
{
	int id;
	struct kgsl_mem_entry *entry = NULL;

	spin_lock(&private->mem_lock);
	idr_for_each_entry(&private->mem_idr, entry, id) {
		struct kgsl_memdesc *m = &entry->memdesc;

		if ((faultaddr >= (m->gpuaddr + m->size))
				&& (faultaddr < (m->gpuaddr + m->size + 64))) {
			spin_unlock(&private->mem_lock);
			return true;
		}
	}
	spin_unlock(&private->mem_lock);
	return false;
}

/*
 * Read pagefaults where the faulting address lies within the first 64 bytes
 * of a page (UCHE line size is 64 bytes) and the fault page is preceded by a
 * valid allocation are considered likely due to UCHE overfetch and suppressed.
 */

static bool kgsl_iommu_suppress_pagefault(uint64_t faultaddr, int write,
					struct kgsl_context *context)
{
	/*
	 * If there is no context associated with the pagefault then this
	 * could be a fault on a global buffer. We do not suppress faults
	 * on global buffers as they are mainly accessed by the CP bypassing
	 * the UCHE. Also, write pagefaults are never suppressed.
	 */
	if (!context || write)
		return false;

	return kgsl_iommu_uche_overfetch(context->proc_priv, faultaddr);
}

static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
	struct device *dev, unsigned long addr, int flags, void *token)
{
@@ -796,12 +754,6 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
	else if (flags & IOMMU_FAULT_TRANSACTION_STALLED)
		fault_type = "transaction stalled";

	if (kgsl_iommu_suppress_pagefault(addr, write, context)) {
		iommu->pagefault_suppression_count++;
		kgsl_context_put(context);
		return ret;
	}

	if (context != NULL) {
		/* save pagefault timestamp for GFT */
		set_bit(KGSL_CONTEXT_PRIV_PAGEFAULT, &context->priv);
+0 −3
Original line number Diff line number Diff line
@@ -111,8 +111,6 @@ struct kgsl_iommu_context {
 * @clks: Array of pointers to IOMMU clocks
 * @smmu_info: smmu info used in a5xx preemption
 * @protect: register protection settings for the iommu.
 * @pagefault_suppression_count: Total number of pagefaults
 *				 suppressed since boot.
 */
struct kgsl_iommu {
	struct kgsl_iommu_context ctx[KGSL_IOMMU_CONTEXT_MAX];
@@ -124,7 +122,6 @@ struct kgsl_iommu {
	struct clk *clks[KGSL_IOMMU_MAX_CLKS];
	struct kgsl_memdesc smmu_info;
	struct kgsl_protected_registers protect;
	u32 pagefault_suppression_count;
};

/*