Skip to content

Commit e97faa0

Browse files
WeiFang-NXPPaolo Abeni
authored andcommitted
net: fec: do not update PEROUT if it is enabled
If the previously set PEROUT is already active, updating it will cause the new PEROUT to start immediately instead of at the specified time. This is because fep->reload_period is updated whithout check whether the PEROUT is enabled, and the old PEROUT is not disabled. Therefore, the pulse period will be updated immediately in the pulse interrupt handler fec_pps_interrupt(). Currently, the driver does not support directly updating PEROUT and it will make the logic be more complicated. To fix the current issue, add a check before enabling the PEROUT, the driver will return an error if PEROUT is enabled. If users wants to update a new PEROUT, they should disable the old PEROUT first. Fixes: 350749b ("net: fec: Add support for periodic output signal of PPS") Signed-off-by: Wei Fang <wei.fang@nxp.com> Link: https://patch.msgid.link/20251125085210.1094306-3-wei.fang@nxp.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent 50caa74 commit e97faa0

2 files changed

Lines changed: 34 additions & 10 deletions

File tree

drivers/net/ethernet/freescale/fec.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,7 @@ struct fec_enet_private {
687687
unsigned int reload_period;
688688
int pps_enable;
689689
unsigned int next_counter;
690+
bool perout_enable;
690691
struct hrtimer perout_timer;
691692
u64 perout_stime;
692693

drivers/net/ethernet/freescale/fec_ptp.c

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ static int fec_ptp_pps_perout(struct fec_enet_private *fep)
243243
* the FEC_TCCR register in time and missed the start time.
244244
*/
245245
if (fep->perout_stime < curr_time + 100 * NSEC_PER_MSEC) {
246+
fep->perout_enable = false;
246247
dev_err(&fep->pdev->dev, "Current time is too close to the start time!\n");
247248
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
248249
return -1;
@@ -500,6 +501,7 @@ static int fec_ptp_pps_disable(struct fec_enet_private *fep, uint channel)
500501
hrtimer_cancel(&fep->perout_timer);
501502

502503
spin_lock_irqsave(&fep->tmreg_lock, flags);
504+
fep->perout_enable = false;
503505
writel(0, fep->hwp + FEC_TCSR(channel));
504506
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
505507

@@ -531,6 +533,8 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
531533

532534
return ret;
533535
} else if (rq->type == PTP_CLK_REQ_PEROUT) {
536+
u32 reload_period;
537+
534538
/* Reject requests with unsupported flags */
535539
if (rq->perout.flags)
536540
return -EOPNOTSUPP;
@@ -550,12 +554,14 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
550554
return -EOPNOTSUPP;
551555
}
552556

553-
fep->reload_period = div_u64(period_ns, 2);
554-
if (on && fep->reload_period) {
557+
reload_period = div_u64(period_ns, 2);
558+
if (on && reload_period) {
559+
u64 perout_stime;
560+
555561
/* Convert 1588 timestamp to ns*/
556562
start_time.tv_sec = rq->perout.start.sec;
557563
start_time.tv_nsec = rq->perout.start.nsec;
558-
fep->perout_stime = timespec64_to_ns(&start_time);
564+
perout_stime = timespec64_to_ns(&start_time);
559565

560566
mutex_lock(&fep->ptp_clk_mutex);
561567
if (!fep->ptp_clk_on) {
@@ -564,18 +570,35 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp,
564570
return -EOPNOTSUPP;
565571
}
566572
spin_lock_irqsave(&fep->tmreg_lock, flags);
573+
574+
if (fep->perout_enable) {
575+
dev_err(&fep->pdev->dev,
576+
"PEROUT has been enabled\n");
577+
ret = -EBUSY;
578+
goto unlock;
579+
}
580+
567581
/* Read current timestamp */
568582
curr_time = timecounter_read(&fep->tc);
569-
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
570-
mutex_unlock(&fep->ptp_clk_mutex);
583+
if (perout_stime <= curr_time) {
584+
dev_err(&fep->pdev->dev,
585+
"Start time must be greater than current time\n");
586+
ret = -EINVAL;
587+
goto unlock;
588+
}
571589

572590
/* Calculate time difference */
573-
delta = fep->perout_stime - curr_time;
591+
delta = perout_stime - curr_time;
592+
fep->reload_period = reload_period;
593+
fep->perout_stime = perout_stime;
594+
fep->perout_enable = true;
574595

575-
if (fep->perout_stime <= curr_time) {
576-
dev_err(&fep->pdev->dev, "Start time must larger than current time!\n");
577-
return -EINVAL;
578-
}
596+
unlock:
597+
spin_unlock_irqrestore(&fep->tmreg_lock, flags);
598+
mutex_unlock(&fep->ptp_clk_mutex);
599+
600+
if (ret)
601+
return ret;
579602

580603
/* Because the timer counter of FEC only has 31-bits, correspondingly,
581604
* the time comparison register FEC_TCCR also only low 31 bits can be

0 commit comments

Comments
 (0)