Skip to content

Commit 0e23d4b

Browse files
MeghanaMalladiTIopsiff
authored andcommitted
net: ti: icss-iep: Fix possible NULL pointer dereference for perout request
[ Upstream commit 7349c9e ] 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: 9b11536 ("net: ti: icssg-prueth: Fix clearing of IEP_CMP_CFG registers during iep_init") Reported-by: Dan Carpenter <dan.carpenter@linaro.org> Closes: https://lore.kernel.org/all/7b1c7c36-363a-4085-b26c-4f210bee1df6@stanley.mountain/ Signed-off-by: Meghana Malladi <m-malladi@ti.com> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Link: https://patch.msgid.link/20250415090543.717991-4-m-malladi@ti.com Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org> (cherry picked from commit 7891619)
1 parent 4097197 commit 0e23d4b

1 file changed

Lines changed: 58 additions & 63 deletions

File tree

drivers/net/ethernet/ti/icssg/icss_iep.c

Lines changed: 58 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,22 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
482482
int ret;
483483
u64 cmp;
484484

485+
if (!on) {
486+
/* Disable CMP 1 */
487+
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
488+
IEP_CMP_CFG_CMP_EN(1), 0);
489+
490+
/* clear CMP regs */
491+
regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0);
492+
if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
493+
regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0);
494+
495+
/* Disable sync */
496+
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0);
497+
498+
return 0;
499+
}
500+
485501
/* Calculate width of the signal for PPS/PEROUT handling */
486502
ts.tv_sec = req->on.sec;
487503
ts.tv_nsec = req->on.nsec;
@@ -500,64 +516,39 @@ static int icss_iep_perout_enable_hw(struct icss_iep *iep,
500516
if (ret)
501517
return ret;
502518

503-
if (on) {
504-
/* Configure CMP */
505-
regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp));
506-
if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
507-
regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp));
508-
/* Configure SYNC, based on req on width */
509-
regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
510-
div_u64(ns_width, iep->def_inc));
511-
regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
512-
regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
513-
div_u64(ns_start, iep->def_inc));
514-
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */
515-
/* Enable CMP 1 */
516-
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
517-
IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
518-
} else {
519-
/* Disable CMP 1 */
520-
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
521-
IEP_CMP_CFG_CMP_EN(1), 0);
522-
523-
/* clear regs */
524-
regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0);
525-
if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
526-
regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0);
527-
}
519+
/* Configure CMP */
520+
regmap_write(iep->map, ICSS_IEP_CMP1_REG0, lower_32_bits(cmp));
521+
if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
522+
regmap_write(iep->map, ICSS_IEP_CMP1_REG1, upper_32_bits(cmp));
523+
/* Configure SYNC, based on req on width */
524+
regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
525+
div_u64(ns_width, iep->def_inc));
526+
regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
527+
regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
528+
div_u64(ns_start, iep->def_inc));
529+
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0); /* one-shot mode */
530+
/* Enable CMP 1 */
531+
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
532+
IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
528533
} else {
529-
if (on) {
530-
u64 start_ns;
531-
532-
iep->period = ((u64)req->period.sec * NSEC_PER_SEC) +
533-
req->period.nsec;
534-
start_ns = ((u64)req->period.sec * NSEC_PER_SEC)
535-
+ req->period.nsec;
536-
icss_iep_update_to_next_boundary(iep, start_ns);
537-
538-
regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
539-
div_u64(ns_width, iep->def_inc));
540-
regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
541-
div_u64(ns_start, iep->def_inc));
542-
/* Enable Sync in single shot mode */
543-
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG,
544-
IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN);
545-
/* Enable CMP 1 */
546-
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
547-
IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
548-
} else {
549-
/* Disable CMP 1 */
550-
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
551-
IEP_CMP_CFG_CMP_EN(1), 0);
552-
553-
/* clear CMP regs */
554-
regmap_write(iep->map, ICSS_IEP_CMP1_REG0, 0);
555-
if (iep->plat_data->flags & ICSS_IEP_64BIT_COUNTER_SUPPORT)
556-
regmap_write(iep->map, ICSS_IEP_CMP1_REG1, 0);
557-
558-
/* Disable sync */
559-
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG, 0);
560-
}
534+
u64 start_ns;
535+
536+
iep->period = ((u64)req->period.sec * NSEC_PER_SEC) +
537+
req->period.nsec;
538+
start_ns = ((u64)req->period.sec * NSEC_PER_SEC)
539+
+ req->period.nsec;
540+
icss_iep_update_to_next_boundary(iep, start_ns);
541+
542+
regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG,
543+
div_u64(ns_width, iep->def_inc));
544+
regmap_write(iep->map, ICSS_IEP_SYNC_START_REG,
545+
div_u64(ns_start, iep->def_inc));
546+
/* Enable Sync in single shot mode */
547+
regmap_write(iep->map, ICSS_IEP_SYNC_CTRL_REG,
548+
IEP_SYNC_CTRL_SYNC_N_EN(0) | IEP_SYNC_CTRL_SYNC_EN);
549+
/* Enable CMP 1 */
550+
regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
551+
IEP_CMP_CFG_CMP_EN(1), IEP_CMP_CFG_CMP_EN(1));
561552
}
562553

563554
return 0;
@@ -568,11 +559,21 @@ static int icss_iep_perout_enable(struct icss_iep *iep,
568559
{
569560
int ret = 0;
570561

562+
if (!on)
563+
goto disable;
564+
571565
/* Reject requests with unsupported flags */
572566
if (req->flags & ~(PTP_PEROUT_DUTY_CYCLE |
573567
PTP_PEROUT_PHASE))
574568
return -EOPNOTSUPP;
575569

570+
/* Set default "on" time (1ms) for the signal if not passed by the app */
571+
if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) {
572+
req->on.sec = 0;
573+
req->on.nsec = NSEC_PER_MSEC;
574+
}
575+
576+
disable:
576577
mutex_lock(&iep->ptp_clk_mutex);
577578

578579
if (iep->pps_enabled) {
@@ -583,12 +584,6 @@ static int icss_iep_perout_enable(struct icss_iep *iep,
583584
if (iep->perout_enabled == !!on)
584585
goto exit;
585586

586-
/* Set default "on" time (1ms) for the signal if not passed by the app */
587-
if (!(req->flags & PTP_PEROUT_DUTY_CYCLE)) {
588-
req->on.sec = 0;
589-
req->on.nsec = NSEC_PER_MSEC;
590-
}
591-
592587
ret = icss_iep_perout_enable_hw(iep, req, on);
593588
if (!ret)
594589
iep->perout_enabled = !!on;

0 commit comments

Comments
 (0)