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

Commit 02a3be4c authored by Rakesh Naidu Bhaviripudi's avatar Rakesh Naidu Bhaviripudi Committed by Sumangala P
Browse files

msm: kgsl: Fix error handling during drawctxt switch



Currently, separate submissions are made for page table
switch and context switch to the ring buffer. However, if
the page table switch succeeds but the context switch fails,
it can lead to use of wrong page table for drawctxt.

To address this issue, submit page table switch and context
switch commands as a single submission to ring buffer.

Also, remove the unnecessary ADRENO_DEVICE_FAULT check and
correctly put the refcount of adreno context during error
cleanup.

Change-Id: I1bb4ee3ebb0ce6ea32f0b6799cfb7fa89c0d09c7
Signed-off-by: default avatarRakesh Naidu Bhaviripudi <quic_rakeshb@quicinc.com>
(cherry picked from commit fe4cb13a)
parent db38212f
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2002,2007-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#include <linux/debugfs.h>
@@ -615,8 +616,6 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,
	if (drawctxt != NULL && kgsl_context_detached(&drawctxt->base))
		return -ENOENT;

	trace_adreno_drawctxt_switch(rb, drawctxt);

	/* Get a refcount to the new instance */
	if (drawctxt) {
		if (!_kgsl_context_get(&drawctxt->base))
@@ -630,7 +629,7 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,

	ret = adreno_iommu_set_pt_ctx(rb, new_pt, drawctxt);
	if (ret)
		return ret;
		goto err;

	if (rb->drawctxt_active) {
		/* Wait for the timestamp to expire */
@@ -640,7 +639,12 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev,
			kgsl_context_put(&rb->drawctxt_active->base);
		}
	}
	trace_adreno_drawctxt_switch(rb, drawctxt);

	rb->drawctxt_active = drawctxt;
	return 0;
err:
	if (drawctxt)
		kgsl_context_put(&drawctxt->base);
	return ret;
}
+21 −65
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) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
 * Copyright (c) 2022,2024 Qualcomm Innovation Center, Inc. All rights reserved.
 */

#include <linux/slab.h>
@@ -400,63 +400,6 @@ static unsigned int __add_curr_ctxt_cmds(struct adreno_ringbuffer *rb,
	return cmds - cmds_orig;
}

/**
 * _set_ctxt_gpu() - Add commands to set the current context in memstore
 * @rb: The ringbuffer in which commands to set memstore are added
 * @drawctxt: The context whose id is being set in memstore
 */
static int _set_ctxt_gpu(struct adreno_ringbuffer *rb,
			struct adreno_context *drawctxt)
{
	unsigned int link[15], *cmds;
	int result;

	cmds = &link[0];
	cmds += __add_curr_ctxt_cmds(rb, cmds, drawctxt);
	result = adreno_ringbuffer_issue_internal_cmds(rb, 0, link,
			(unsigned int)(cmds - link));
	return result;
}

/**
 * _set_pagetable_gpu() - Use GPU to switch the pagetable
 * @rb: The rb in which commands to switch pagetable are to be
 *    submitted
 * @new_pt: The pagetable to switch to
 */
static int _set_pagetable_gpu(struct adreno_ringbuffer *rb,
			struct kgsl_pagetable *new_pt)
{
	struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
	unsigned int *link = NULL, count;
	int result;

	link = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (link == NULL)
		return -ENOMEM;

	/* If we are in a fault the MMU will be reset soon */
	if (test_bit(ADRENO_DEVICE_FAULT, &adreno_dev->priv)) {
		kfree(link);
		return 0;
	}

	count = adreno_iommu_set_pt_generate_cmds(rb, link, new_pt);

	WARN(count > (PAGE_SIZE / sizeof(unsigned int)),
		"Temp command buffer overflow\n");

	/*
	 * This returns the per context timestamp but we need to
	 * use the global timestamp for iommu clock disablement
	 */
	result = adreno_ringbuffer_issue_internal_cmds(rb,
			KGSL_CMD_FLAGS_PMODE, link, count);

	kfree(link);
	return result;
}

/**
 * adreno_iommu_init() - Adreno iommu init
 * @adreno_dev: Adreno device
@@ -485,7 +428,6 @@ void adreno_iommu_init(struct adreno_device *adreno_dev)

/**
 * adreno_iommu_set_pt_ctx() - Change the pagetable of the current RB
 * @device: Pointer to device to which the rb belongs
 * @rb: The RB pointer on which pagetable is to be changed
 * @new_pt: The new pt the device will change to
 * @drawctxt: The context whose pagetable the ringbuffer is switching to,
@@ -500,21 +442,35 @@ int adreno_iommu_set_pt_ctx(struct adreno_ringbuffer *rb,
	struct adreno_device *adreno_dev = ADRENO_RB_DEVICE(rb);
	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
	struct kgsl_pagetable *cur_pt = device->mmu.defaultpagetable;
	unsigned int *cmds = NULL, count = 0;
	int result = 0;

	cmds = kmalloc(PAGE_SIZE, GFP_KERNEL);
	if (cmds == NULL)
		return -ENOMEM;

	/* Switch the page table if a MMU is attached */
	if (kgsl_mmu_get_mmutype(device) != KGSL_MMU_TYPE_NONE) {
		if (rb->drawctxt_active)
			cur_pt = rb->drawctxt_active->base.proc_priv->pagetable;

		/* Pagetable switch */
		/* Add commands for pagetable switch */
		if (new_pt != cur_pt)
			result = _set_pagetable_gpu(rb, new_pt);
			count += adreno_iommu_set_pt_generate_cmds(rb,
					cmds, new_pt);

		if (result)
			return result;
	}

	/* Context switch */
	return _set_ctxt_gpu(rb, drawctxt);
	/* Add commands to set the current context in memstore */
	count += __add_curr_ctxt_cmds(rb, cmds + count, drawctxt);

	WARN(count > (PAGE_SIZE / sizeof(unsigned int)),
			"Temp command buffer overflow\n");

	result = adreno_ringbuffer_issue_internal_cmds(rb, KGSL_CMD_FLAGS_PMODE,
			cmds, count);

	kfree(cmds);
	return result;

}