Commit a1477dc8 authored by Bence Csókás's avatar Bence Csókás Committed by Paolo Abeni
Browse files

net: fec: Restart PPS after link state change



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: 6605b730 ("FEC: Add time stamping code and a PTP hardware clock")
Signed-off-by: default avatarCsókás, Bence <csokas.bence@prolan.hu>
Link: https://patch.msgid.link/20240924093705.2897329-1-csokas.bence@prolan.hu


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 93ef6ee5
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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,
+10 −1
Original line number Diff line number Diff line
@@ -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.
@@ -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)
@@ -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.
@@ -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);
	}
}

+30 −0
Original line number Diff line number Diff line
@@ -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);