Commit 7349c9e9 authored by Meghana Malladi's avatar Meghana Malladi Committed by Paolo Abeni
Browse files

net: ti: icss-iep: Fix possible NULL pointer dereference for perout request



The ICSS IEP driver tracks perout and pps enable state with flags.
Currently when disabling pps and perout signals during icss_iep_exit(),
results in NULL pointer dereference for perout.

To fix the null pointer dereference issue, the icss_iep_perout_enable_hw
function can be modified to directly clear the IEP CMP registers when
disabling PPS or PEROUT, without referencing the ptp_perout_request
structure, as its contents are irrelevant in this case.

Fixes: 9b115361 ("net: ti: icssg-prueth: Fix clearing of IEP_CMP_CFG registers during iep_init")
Reported-by: default avatarDan Carpenter <dan.carpenter@linaro.org>
Closes: https://lore.kernel.org/all/7b1c7c36-363a-4085-b26c-4f210bee1df6@stanley.mountain/


Signed-off-by: default avatarMeghana Malladi <m-malladi@ti.com>
Reviewed-by: default avatarJacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20250415090543.717991-4-m-malladi@ti.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 8ed2fa66
Loading
Loading
Loading
Loading
+58 −63
Original line number Diff line number Diff line
@@ -412,6 +412,22 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
	int ret;
	u64 cmp;

	if (!on) {
		/* Disable CMP 1 */
		regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
				   IEP_CMP_CFG_CMP_EN(1), 0);

		/* clear CMP regs */
		regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0);
		if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
			regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0);

		/* Disable sync */
		regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0);

		return 0;
	}

	/* Calculate width of the signal for PPS/PEROUT handling */
	ts.tv_sec = req->on.sec;
	ts.tv_nsec = req->on.nsec;
@@ -430,7 +446,6 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
		if (ret)
			return ret;

		if (on) {
		/* Configure CMP */
		regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp));
		if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
@@ -446,17 +461,6 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
		regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
				   IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
	} else {
			/* Disable CMP 1 */
			regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
					   IEP_CMP_CFG_CMP_EN(1), 0);

			/* clear regs */
			regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0);
			if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
				regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0);
		}
	} else {
		if (on) {
		u64 start_ns;

		iep->period = ((u64)req->period.sec * NSEC_PER_SEC) +
@@ -475,19 +479,6 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
		/* Enable CMP 1 */
		regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
				   IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
		} else {
			/* Disable CMP 1 */
			regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
					   IEP_CMP_CFG_CMP_EN(1), 0);

			/* clear CMP regs */
			regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0);
			if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
				regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0);

			/* Disable sync */
			regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0);
		}
	}

	return 0;
@@ -498,11 +489,21 @@ static int icss_iep_perout_enable(struct icss_iep *iep,
{
	int ret = 0;

	if (!on)
		goto disable;

	/* Reject requests with unsupported flags */
	if (req->flags & ~(PTP_PEROUT_DUTY_CYCLE |
			  PTP_PEROUT_PHASE))
		return -EOPNOTSUPP;

	/* Set default "on" time (1ms) for the signal if not passed by the app */
	if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) {
		req->on.sec = 0;
		req->on.nsec = NSEC_PER_MSEC;
	}

disable:
	mutex_lock(&iep->ptp_clk_mutex);

	if (iep->pps_enabled) {
@@ -513,12 +514,6 @@ static int icss_iep_perout_enable(struct icss_iep *iep,
	if (iep->perout_enabled == !!on)
		goto exit;

	/* Set default "on" time (1ms) for the signal if not passed by the app */
	if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) {
		req->on.sec = 0;
		req->on.nsec = NSEC_PER_MSEC;
	}

	ret = icss_iep_perout_enable_hw(iep, req, on);
	if (!ret)
		iep->perout_enabled = !!on;