Skip to content

Commit

Permalink
net: fec: Restart PPS after link state change
Browse files Browse the repository at this point in the history
On link state change, the controller gets reset,
causing PPS to drop out. Re-enable PPS if it was
enabled before the controller reset.

Fixes: 6605b73 ("FEC: Add time stamping code and a PTP hardware clock")
Signed-off-by: Csókás, Bence <csokas.bence@prolan.hu>
Link: https://patch.msgid.link/20240924093705.2897329-1-csokas.bence@prolan.hu
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Csókás, Bence authored and Paolo Abeni committed Oct 1, 2024
1 parent 93ef6ee commit a1477dc
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 1 deletion.
6 changes: 6 additions & 0 deletions drivers/net/ethernet/freescale/fec.h
Original file line number Diff line number Diff line change
Expand Up @@ -691,10 +691,16 @@ struct fec_enet_private {
/* XDP BPF Program */
struct bpf_prog *xdp_prog;

struct {
int pps_enable;
} ptp_saved_state;

u64 ethtool_stats[];
};

void fec_ptp_init(struct platform_device *pdev, int irq_idx);
void fec_ptp_restore_state(struct fec_enet_private *fep);
void fec_ptp_save_state(struct fec_enet_private *fep);
void fec_ptp_stop(struct platform_device *pdev);
void fec_ptp_start_cyclecounter(struct net_device *ndev);
int fec_ptp_set(struct net_device *ndev, struct kernel_hwtstamp_config *config,
Expand Down
11 changes: 10 additions & 1 deletion drivers/net/ethernet/freescale/fec_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,8 @@ fec_restart(struct net_device *ndev)
u32 rcntl = OPT_FRAME_SIZE | 0x04;
u32 ecntl = FEC_ECR_ETHEREN;

fec_ptp_save_state(fep);

/* Whack a reset. We should wait for this.
* For i.MX6SX SOC, enet use AXI bus, we use disable MAC
* instead of reset MAC itself.
Expand Down Expand Up @@ -1244,8 +1246,10 @@ fec_restart(struct net_device *ndev)
writel(ecntl, fep->hwp + FEC_ECNTRL);
fec_enet_active_rxring(ndev);

if (fep->bufdesc_ex)
if (fep->bufdesc_ex) {
fec_ptp_start_cyclecounter(ndev);
fec_ptp_restore_state(fep);
}

/* Enable interrupts we wish to service */
if (fep->link)
Expand Down Expand Up @@ -1336,6 +1340,8 @@ fec_stop(struct net_device *ndev)
netdev_err(ndev, "Graceful transmit stop did not complete!\n");
}

fec_ptp_save_state(fep);

/* Whack a reset. We should wait for this.
* For i.MX6SX SOC, enet use AXI bus, we use disable MAC
* instead of reset MAC itself.
Expand Down Expand Up @@ -1366,6 +1372,9 @@ fec_stop(struct net_device *ndev)
val = readl(fep->hwp + FEC_ECNTRL);
val |= FEC_ECR_EN1588;
writel(val, fep->hwp + FEC_ECNTRL);

fec_ptp_start_cyclecounter(ndev);
fec_ptp_restore_state(fep);
}
}

Expand Down
30 changes: 30 additions & 0 deletions drivers/net/ethernet/freescale/fec_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -764,6 +764,36 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx)
schedule_delayed_work(&fep->time_keep, HZ);
}

void fec_ptp_save_state(struct fec_enet_private *fep)
{
unsigned long flags;

spin_lock_irqsave(&fep->tmreg_lock, flags);

fep->ptp_saved_state.pps_enable = fep->pps_enable;

spin_unlock_irqrestore(&fep->tmreg_lock, flags);
}

/* Restore PTP functionality after a reset */
void fec_ptp_restore_state(struct fec_enet_private *fep)
{
unsigned long flags;

spin_lock_irqsave(&fep->tmreg_lock, flags);

/* Reset turned it off, so adjust our status flag */
fep->pps_enable = 0;

spin_unlock_irqrestore(&fep->tmreg_lock, flags);

/* Restart PPS if needed */
if (fep->ptp_saved_state.pps_enable) {
/* Re-enable PPS */
fec_ptp_enable_pps(fep, 1);
}
}

void fec_ptp_stop(struct platform_device *pdev)
{
struct net_device *ndev = platform_get_drvdata(pdev);
Expand Down

0 comments on commit a1477dc

Please sign in to comment.