Commit 09d78dde authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-msm-fixes-2021-02-25' of https://gitlab.freedesktop.org/drm/msm into drm-fixes



- pll fixes
- shutdown hook fix
- runtime resume fix
- clear_oob fix
- kms locking fix
- display aux retry fix

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
From: Rob Clark <robdclark@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGvmiMKRms_NVavD=NA_jbuexZUcqqL35ke7umqpp-TxMw@mail.gmail.com
parents 4e8d123f 627dc55c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -304,7 +304,7 @@ int a5xx_power_init(struct msm_gpu *gpu)
	/* Set up the limits management */
	if (adreno_is_a530(adreno_gpu))
		a530_lm_setup(gpu);
	else
	else if (adreno_is_a540(adreno_gpu))
		a540_lm_setup(gpu);

	/* Set up SP/TP power collpase */
+1 −1
Original line number Diff line number Diff line
@@ -339,7 +339,7 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state)
	else
		bit = a6xx_gmu_oob_bits[state].ack_new;

	gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, bit);
	gmu_write(gmu, REG_A6XX_GMU_HOST2GMU_INTR_SET, 1 << bit);
}

/* Enable CPU control of SPTP power power collapse */
+72 −36
Original line number Diff line number Diff line
@@ -522,28 +522,73 @@ static int a6xx_cp_init(struct msm_gpu *gpu)
	return a6xx_idle(gpu, ring) ? 0 : -EINVAL;
}

static void a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
/*
 * Check that the microcode version is new enough to include several key
 * security fixes. Return true if the ucode is safe.
 */
static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu,
		struct drm_gem_object *obj)
{
	struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
	struct msm_gpu *gpu = &adreno_gpu->base;
	u32 *buf = msm_gem_get_vaddr(obj);
	bool ret = false;

	if (IS_ERR(buf))
		return;
		return false;

	/*
	 * If the lowest nibble is 0xa that is an indication that this microcode
	 * has been patched. The actual version is in dword [3] but we only care
	 * about the patchlevel which is the lowest nibble of dword [3]
	 * Targets up to a640 (a618, a630 and a640) need to check for a
	 * microcode version that is patched to support the whereami opcode or
	 * one that is new enough to include it by default.
	 */
	if (adreno_is_a618(adreno_gpu) || adreno_is_a630(adreno_gpu) ||
		adreno_is_a640(adreno_gpu)) {
		/*
		 * If the lowest nibble is 0xa that is an indication that this
		 * microcode has been patched. The actual version is in dword
		 * [3] but we only care about the patchlevel which is the lowest
		 * nibble of dword [3]
		 *
	 * Otherwise check that the firmware is greater than or equal to 1.90
	 * which was the first version that had this fix built in
		 * Otherwise check that the firmware is greater than or equal
		 * to 1.90 which was the first version that had this fix built
		 * in
		 */
	if (((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1)
		a6xx_gpu->has_whereami = true;
	else if ((buf[0] & 0xfff) > 0x190)
		if ((((buf[0] & 0xf) == 0xa) && (buf[2] & 0xf) >= 1) ||
			(buf[0] & 0xfff) >= 0x190) {
			a6xx_gpu->has_whereami = true;
			ret = true;
			goto out;
		}

		DRM_DEV_ERROR(&gpu->pdev->dev,
			"a630 SQE ucode is too old. Have version %x need at least %x\n",
			buf[0] & 0xfff, 0x190);
	}  else {
		/*
		 * a650 tier targets don't need whereami but still need to be
		 * equal to or newer than 1.95 for other security fixes
		 */
		if (adreno_is_a650(adreno_gpu)) {
			if ((buf[0] & 0xfff) >= 0x195) {
				ret = true;
				goto out;
			}

			DRM_DEV_ERROR(&gpu->pdev->dev,
				"a650 SQE ucode is too old. Have version %x need at least %x\n",
				buf[0] & 0xfff, 0x195);
		}

		/*
		 * When a660 is added those targets should return true here
		 * since those have all the critical security fixes built in
		 * from the start
		 */
	}
out:
	msm_gem_put_vaddr(obj);
	return ret;
}

static int a6xx_ucode_init(struct msm_gpu *gpu)
@@ -566,7 +611,13 @@ static int a6xx_ucode_init(struct msm_gpu *gpu)
		}

		msm_gem_object_set_name(a6xx_gpu->sqe_bo, "sqefw");
		a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo);
		if (!a6xx_ucode_check_version(a6xx_gpu, a6xx_gpu->sqe_bo)) {
			msm_gem_unpin_iova(a6xx_gpu->sqe_bo, gpu->aspace);
			drm_gem_object_put(a6xx_gpu->sqe_bo);

			a6xx_gpu->sqe_bo = NULL;
			return -EPERM;
		}
	}

	gpu_write64(gpu, REG_A6XX_CP_SQE_INSTR_BASE_LO,
@@ -1350,35 +1401,20 @@ static int a6xx_set_supported_hw(struct device *dev, struct a6xx_gpu *a6xx_gpu,
		u32 revn)
{
	struct opp_table *opp_table;
	struct nvmem_cell *cell;
	u32 supp_hw = UINT_MAX;
	void *buf;

	cell = nvmem_cell_get(dev, "speed_bin");
	/*
	 * -ENOENT means that the platform doesn't support speedbin which is
	 * fine
	 */
	if (PTR_ERR(cell) == -ENOENT)
		return 0;
	else if (IS_ERR(cell)) {
		DRM_DEV_ERROR(dev,
				"failed to read speed-bin. Some OPPs may not be supported by hardware");
		goto done;
	}
	u16 speedbin;
	int ret;

	buf = nvmem_cell_read(cell, NULL);
	if (IS_ERR(buf)) {
		nvmem_cell_put(cell);
	ret = nvmem_cell_read_u16(dev, "speed_bin", &speedbin);
	if (ret) {
		DRM_DEV_ERROR(dev,
				"failed to read speed-bin. Some OPPs may not be supported by hardware");
			      "failed to read speed-bin (%d). Some OPPs may not be supported by hardware",
			      ret);
		goto done;
	}
	speedbin = le16_to_cpu(speedbin);

	supp_hw = fuse_to_supp_hw(dev, revn, *((u32 *) buf));

	kfree(buf);
	nvmem_cell_put(cell);
	supp_hw = fuse_to_supp_hw(dev, revn, speedbin);

done:
	opp_table = dev_pm_opp_set_supported_hw(dev, &supp_hw, 1);
+7 −5
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@
#define DPU_DEBUGFS_DIR "msm_dpu"
#define DPU_DEBUGFS_HWMASKNAME "hw_log_mask"

#define MIN_IB_BW	400000000ULL /* Min ib vote 400MB */

static int dpu_kms_hw_init(struct msm_kms *kms);
static void _dpu_kms_mmu_destroy(struct dpu_kms *dpu_kms);

@@ -931,6 +933,9 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
		DPU_DEBUG("REG_DMA is not defined");
	}

	if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss"))
		dpu_kms_parse_data_bus_icc_path(dpu_kms);

	pm_runtime_get_sync(&dpu_kms->pdev->dev);

	dpu_kms->core_rev = readl_relaxed(dpu_kms->mmio + 0x0);
@@ -1032,9 +1037,6 @@ static int dpu_kms_hw_init(struct msm_kms *kms)

	dpu_vbif_init_memtypes(dpu_kms);

	if (of_device_is_compatible(dev->dev->of_node, "qcom,sc7180-mdss"))
		dpu_kms_parse_data_bus_icc_path(dpu_kms);

	pm_runtime_put_sync(&dpu_kms->pdev->dev);

	return 0;
@@ -1191,10 +1193,10 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev)

	ddev = dpu_kms->dev;

	WARN_ON(!(dpu_kms->num_paths));
	/* Min vote of BW is required before turning on AXI clk */
	for (i = 0; i < dpu_kms->num_paths; i++)
		icc_set_bw(dpu_kms->path[i], 0,
			dpu_kms->catalog->perf.min_dram_ib);
		icc_set_bw(dpu_kms->path[i], 0, Bps_to_icc(MIN_IB_BW));

	rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
	if (rc) {
+7 −0
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ struct dp_aux_private {
	struct drm_dp_aux dp_aux;
};

#define MAX_AUX_RETRIES			5

static const char *dp_aux_get_error(u32 aux_error)
{
	switch (aux_error) {
@@ -377,6 +379,11 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
	ret = dp_aux_cmd_fifo_tx(aux, msg);

	if (ret < 0) {
		if (aux->native) {
			aux->retry_cnt++;
			if (!(aux->retry_cnt % MAX_AUX_RETRIES))
				dp_catalog_aux_update_cfg(aux->catalog);
		}
		usleep_range(400, 500); /* at least 400us to next try */
		goto unlock_exit;
	}
Loading