Commit 49a5fdc0 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-msm-fixes-2025-06-16' of https://gitlab.freedesktop.org/drm/msm into drm-fixes



Fixes for v6.16-rc3

Display:
- Fixed DP output on SDM845
- Fixed 10nm DSI PLL init

GPU:
- SUBMIT ioctl error path leak fixes
- drm half of stall-on-fault fixes.  Note there is a soft dependency,
  to get correct mmu fault devcoredumps, on arm-smmu changes which
  are not in this branch, but have already been merged by Linus.  So
  by the time Linus merges this, everything should be peachy.
- a7xx: Missing CP_RESET_CONTEXT_STATE
- Skip GPU component bind if GPU is not in the device table.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Rob Clark <rob.clark@oss.qualcomm.com>
Link: https://lore.kernel.org/r/CACSVV03=OH74ip8O1xqb8RJWGyM4HFuUnWuR=p3zJR+-ko_AJA@mail.gmail.com
parents e04c78d8 d3deabe4
Loading
Loading
Loading
Loading
+0 −5
Original line number Diff line number Diff line
@@ -71,10 +71,6 @@ static int a2xx_gpummu_unmap(struct msm_mmu *mmu, uint64_t iova, size_t len)
	return 0;
}

static void a2xx_gpummu_resume_translation(struct msm_mmu *mmu)
{
}

static void a2xx_gpummu_destroy(struct msm_mmu *mmu)
{
	struct a2xx_gpummu *gpummu = to_a2xx_gpummu(mmu);
@@ -90,7 +86,6 @@ static const struct msm_mmu_funcs funcs = {
		.map = a2xx_gpummu_map,
		.unmap = a2xx_gpummu_unmap,
		.destroy = a2xx_gpummu_destroy,
		.resume_translation = a2xx_gpummu_resume_translation,
};

struct msm_mmu *a2xx_gpummu_new(struct device *dev, struct msm_gpu *gpu)
+2 −0
Original line number Diff line number Diff line
@@ -131,6 +131,8 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
	struct msm_ringbuffer *ring = submit->ring;
	unsigned int i, ibs = 0;

	adreno_check_and_reenable_stall(adreno_gpu);

	if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) {
		ring->cur_ctx_seqno = 0;
		a5xx_submit_in_rb(gpu, submit);
+18 −0
Original line number Diff line number Diff line
@@ -130,6 +130,20 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
		OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence)));
		OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence)));
		OUT_RING(ring, submit->seqno - 1);

		OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
		OUT_RING(ring, CP_SET_THREAD_BOTH);

		/* Reset state used to synchronize BR and BV */
		OUT_PKT7(ring, CP_RESET_CONTEXT_STATE, 1);
		OUT_RING(ring,
			 CP_RESET_CONTEXT_STATE_0_CLEAR_ON_CHIP_TS |
			 CP_RESET_CONTEXT_STATE_0_CLEAR_RESOURCE_TABLE |
			 CP_RESET_CONTEXT_STATE_0_CLEAR_BV_BR_COUNTER |
			 CP_RESET_CONTEXT_STATE_0_RESET_GLOBAL_LOCAL_TS);

		OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
		OUT_RING(ring, CP_SET_THREAD_BR);
	}

	if (!sysprof) {
@@ -212,6 +226,8 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
	struct msm_ringbuffer *ring = submit->ring;
	unsigned int i, ibs = 0;

	adreno_check_and_reenable_stall(adreno_gpu);

	a6xx_set_pagetable(a6xx_gpu, ring, submit);

	get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0),
@@ -335,6 +351,8 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
	struct msm_ringbuffer *ring = submit->ring;
	unsigned int i, ibs = 0;

	adreno_check_and_reenable_stall(adreno_gpu);

	/*
	 * Toggle concurrent binning for pagetable switch and set the thread to
	 * BR since only it can execute the pagetable switch packets.
+29 −10
Original line number Diff line number Diff line
@@ -137,9 +137,8 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
	return NULL;
}

static int find_chipid(struct device *dev, uint32_t *chipid)
static int find_chipid(struct device_node *node, uint32_t *chipid)
{
	struct device_node *node = dev->of_node;
	const char *compat;
	int ret;

@@ -173,15 +172,36 @@ static int find_chipid(struct device *dev, uint32_t *chipid)
	/* and if that fails, fall back to legacy "qcom,chipid" property: */
	ret = of_property_read_u32(node, "qcom,chipid", chipid);
	if (ret) {
		DRM_DEV_ERROR(dev, "could not parse qcom,chipid: %d\n", ret);
		DRM_ERROR("%pOF: could not parse qcom,chipid: %d\n",
			  node, ret);
		return ret;
	}

	dev_warn(dev, "Using legacy qcom,chipid binding!\n");
	pr_warn("%pOF: Using legacy qcom,chipid binding!\n", node);

	return 0;
}

bool adreno_has_gpu(struct device_node *node)
{
	const struct adreno_info *info;
	uint32_t chip_id;
	int ret;

	ret = find_chipid(node, &chip_id);
	if (ret)
		return false;

	info = adreno_info(chip_id);
	if (!info) {
		pr_warn("%pOF: Unknown GPU revision: %"ADRENO_CHIPID_FMT"\n",
			node, ADRENO_CHIPID_ARGS(chip_id));
		return false;
	}

	return true;
}

static int adreno_bind(struct device *dev, struct device *master, void *data)
{
	static struct adreno_platform_config config = {};
@@ -191,19 +211,18 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
	struct msm_gpu *gpu;
	int ret;

	ret = find_chipid(dev, &config.chip_id);
	if (ret)
	ret = find_chipid(dev->of_node, &config.chip_id);
	/* We shouldn't have gotten this far if we can't parse the chip_id */
	if (WARN_ON(ret))
		return ret;

	dev->platform_data = &config;
	priv->gpu_pdev = to_platform_device(dev);

	info = adreno_info(config.chip_id);
	if (!info) {
		dev_warn(drm->dev, "Unknown GPU revision: %"ADRENO_CHIPID_FMT"\n",
			ADRENO_CHIPID_ARGS(config.chip_id));
	/* We shouldn't have gotten this far if we don't recognize the GPU: */
	if (WARN_ON(!info))
		return -ENXIO;
	}

	config.info = info;

+43 −11
Original line number Diff line number Diff line
@@ -259,24 +259,54 @@ u64 adreno_private_address_space_size(struct msm_gpu *gpu)
	return BIT(ttbr1_cfg->ias) - ADRENO_VM_START;
}

void adreno_check_and_reenable_stall(struct adreno_gpu *adreno_gpu)
{
	struct msm_gpu *gpu = &adreno_gpu->base;
	struct msm_drm_private *priv = gpu->dev->dev_private;
	unsigned long flags;

	/*
	 * Wait until the cooldown period has passed and we would actually
	 * collect a crashdump to re-enable stall-on-fault.
	 */
	spin_lock_irqsave(&priv->fault_stall_lock, flags);
	if (!priv->stall_enabled &&
			ktime_after(ktime_get(), priv->stall_reenable_time) &&
			!READ_ONCE(gpu->crashstate)) {
		priv->stall_enabled = true;

		gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, true);
	}
	spin_unlock_irqrestore(&priv->fault_stall_lock, flags);
}

#define ARM_SMMU_FSR_TF                 BIT(1)
#define ARM_SMMU_FSR_PF			BIT(3)
#define ARM_SMMU_FSR_EF			BIT(4)
#define ARM_SMMU_FSR_SS			BIT(30)

int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
			 struct adreno_smmu_fault_info *info, const char *block,
			 u32 scratch[4])
{
	struct msm_drm_private *priv = gpu->dev->dev_private;
	const char *type = "UNKNOWN";
	bool do_devcoredump = info && !READ_ONCE(gpu->crashstate);
	bool do_devcoredump = info && (info->fsr & ARM_SMMU_FSR_SS) &&
		!READ_ONCE(gpu->crashstate);
	unsigned long irq_flags;

	/*
	 * If we aren't going to be resuming later from fault_worker, then do
	 * it now.
	 * In case there is a subsequent storm of pagefaults, disable
	 * stall-on-fault for at least half a second.
	 */
	if (!do_devcoredump) {
		gpu->aspace->mmu->funcs->resume_translation(gpu->aspace->mmu);
	spin_lock_irqsave(&priv->fault_stall_lock, irq_flags);
	if (priv->stall_enabled) {
		priv->stall_enabled = false;

		gpu->aspace->mmu->funcs->set_stall(gpu->aspace->mmu, false);
	}
	priv->stall_reenable_time = ktime_add_ms(ktime_get(), 500);
	spin_unlock_irqrestore(&priv->fault_stall_lock, irq_flags);

	/*
	 * Print a default message if we couldn't get the data from the
@@ -304,16 +334,18 @@ int adreno_fault_handler(struct msm_gpu *gpu, unsigned long iova, int flags,
			scratch[0], scratch[1], scratch[2], scratch[3]);

	if (do_devcoredump) {
		struct msm_gpu_fault_info fault_info = {};

		/* Turn off the hangcheck timer to keep it from bothering us */
		timer_delete(&gpu->hangcheck_timer);

		gpu->fault_info.ttbr0 = info->ttbr0;
		gpu->fault_info.iova  = iova;
		gpu->fault_info.flags = flags;
		gpu->fault_info.type  = type;
		gpu->fault_info.block = block;
		fault_info.ttbr0 = info->ttbr0;
		fault_info.iova  = iova;
		fault_info.flags = flags;
		fault_info.type  = type;
		fault_info.block = block;

		kthread_queue_work(gpu->worker, &gpu->fault_work);
		msm_gpu_fault_crashstate_capture(gpu, &fault_info);
	}

	return 0;
Loading