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

Commit 9bd358e6 authored by Animesh Kishore's avatar Animesh Kishore Committed by Sachin Bhayare
Browse files

msm: mdss: Fix scalar LUT handling



Add lock to serialize access between userspace
and kernel. Fix error handling for LUT allocation.

Change-Id: Ie86a8eb3e2a11852ae16d87ebc851afb6566732f
Signed-off-by: default avatarAnimesh Kishore <animeshk@codeaurora.org>
parent 14681b57
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -232,6 +232,13 @@ struct mdss_scaler_block {
	u32 *dest_scaler_off;
	u32 *dest_scaler_lut_off;
	struct mdss_mdp_qseed3_lut_tbl lut_tbl;

	/*
	 * Lock is mainly to serialize access to LUT.
	 * LUT values come asynchronously from userspace
	 * via ioctl.
	 */
	struct mutex scaler_lock;
};

struct mdss_data_type;
+1 −0
Original line number Diff line number Diff line
@@ -2124,6 +2124,7 @@ static u32 mdss_mdp_scaler_init(struct mdss_data_type *mdata,
			return -EINVAL;
	}

	mutex_init(&mdata->scaler_off->scaler_lock);
	return 0;
}

+24 −12
Original line number Diff line number Diff line
@@ -6792,14 +6792,18 @@ static int mdss_mdp_scaler_lut_init(struct mdss_data_type *mdata,
	if (!mdata->scaler_off)
		return -EFAULT;

	mutex_lock(&mdata->scaler_off->scaler_lock);

	qseed3_lut_tbl = &mdata->scaler_off->lut_tbl;
	if ((lut_tbl->dir_lut_size !=
		DIR_LUT_IDX * DIR_LUT_COEFFS * sizeof(uint32_t)) ||
		(lut_tbl->cir_lut_size !=
		 CIR_LUT_IDX * CIR_LUT_COEFFS * sizeof(uint32_t)) ||
		(lut_tbl->sep_lut_size !=
		 SEP_LUT_IDX * SEP_LUT_COEFFS * sizeof(uint32_t)))
		 SEP_LUT_IDX * SEP_LUT_COEFFS * sizeof(uint32_t))) {
		mutex_unlock(&mdata->scaler_off->scaler_lock);
		return -EINVAL;
	}

	if (!qseed3_lut_tbl->dir_lut) {
		qseed3_lut_tbl->dir_lut = devm_kzalloc(&mdata->pdev->dev,
@@ -6807,7 +6811,7 @@ static int mdss_mdp_scaler_lut_init(struct mdss_data_type *mdata,
				GFP_KERNEL);
		if (!qseed3_lut_tbl->dir_lut) {
			ret = -ENOMEM;
			goto fail;
			goto err;
		}
	}

@@ -6817,7 +6821,7 @@ static int mdss_mdp_scaler_lut_init(struct mdss_data_type *mdata,
				GFP_KERNEL);
		if (!qseed3_lut_tbl->cir_lut) {
			ret = -ENOMEM;
			goto fail;
			goto fail_free_dir_lut;
		}
	}

@@ -6827,44 +6831,52 @@ static int mdss_mdp_scaler_lut_init(struct mdss_data_type *mdata,
				GFP_KERNEL);
		if (!qseed3_lut_tbl->sep_lut) {
			ret = -ENOMEM;
			goto fail;
			goto fail_free_cir_lut;
		}
	}

	/* Invalidate before updating */
	qseed3_lut_tbl->valid = false;


	if (copy_from_user(qseed3_lut_tbl->dir_lut,
				(void *)(unsigned long)lut_tbl->dir_lut,
				lut_tbl->dir_lut_size)) {
		ret = -EINVAL;
		goto err;
		goto fail_free_sep_lut;
	}

	if (copy_from_user(qseed3_lut_tbl->cir_lut,
				(void *)(unsigned long)lut_tbl->cir_lut,
				lut_tbl->cir_lut_size)) {
		ret = -EINVAL;
		goto err;
		goto fail_free_sep_lut;
	}

	if (copy_from_user(qseed3_lut_tbl->sep_lut,
				(void *)(unsigned long)lut_tbl->sep_lut,
				lut_tbl->sep_lut_size)) {
		ret = -EINVAL;
		goto err;
		goto fail_free_sep_lut;
	}

	qseed3_lut_tbl->valid = true;
	mutex_unlock(&mdata->scaler_off->scaler_lock);

	return ret;

fail:
	kfree(qseed3_lut_tbl->dir_lut);
	kfree(qseed3_lut_tbl->cir_lut);
	kfree(qseed3_lut_tbl->sep_lut);
fail_free_sep_lut:
	devm_kfree(&mdata->pdev->dev, qseed3_lut_tbl->sep_lut);
fail_free_cir_lut:
	devm_kfree(&mdata->pdev->dev, qseed3_lut_tbl->cir_lut);
fail_free_dir_lut:
	devm_kfree(&mdata->pdev->dev, qseed3_lut_tbl->dir_lut);
err:
	qseed3_lut_tbl->dir_lut = NULL;
	qseed3_lut_tbl->cir_lut = NULL;
	qseed3_lut_tbl->sep_lut = NULL;
	qseed3_lut_tbl->valid = false;
	mutex_unlock(&mdata->scaler_off->scaler_lock);

	return ret;
}

+6 −0
Original line number Diff line number Diff line
@@ -1578,11 +1578,16 @@ int mdss_mdp_scaler_lut_cfg(struct mdp_scale_data_v2 *scaler,
	};

	mdata = mdss_mdp_get_mdata();

	mutex_lock(&mdata->scaler_off->scaler_lock);

	lut_tbl = &mdata->scaler_off->lut_tbl;
	if ((!lut_tbl) || (!lut_tbl->valid)) {
		mutex_unlock(&mdata->scaler_off->scaler_lock);
		pr_err("%s:Invalid QSEED3 LUT TABLE\n", __func__);
		return -EINVAL;
	}

	if ((scaler->lut_flag & SCALER_LUT_DIR_WR) ||
		(scaler->lut_flag & SCALER_LUT_Y_CIR_WR) ||
		(scaler->lut_flag & SCALER_LUT_UV_CIR_WR) ||
@@ -1632,6 +1637,7 @@ int mdss_mdp_scaler_lut_cfg(struct mdp_scale_data_v2 *scaler,
	if (scaler->lut_flag & SCALER_LUT_SWAP)
		writel_relaxed(BIT(0), MDSS_MDP_REG_SCALER_COEF_LUT_CTRL +
				offset);
	mutex_unlock(&mdata->scaler_off->scaler_lock);

	return 0;
}