Skip to content

Commit fbd5e2d

Browse files
jacob-kellerJeff Kirsher
authored andcommitted
i40e: only create PTP device node once
Currently every time we run through the i40e_ptp_init routine, we create a new device node. This function is called by i40e_reset_and_rebuild which is used to handle reset of the device. Even though the 1588 registers only get cleared on a GLOBAL reset, this function is still called to handle a CORE reset. This causes a leak of PTP device nodes at every reset. To fix this, break PTP device clock node creation out of i40e_ptp_init, and only call this if we don't already have a device created. Further invocation of i40e_ptp_init will not generate new PTP devices. Instead, only the necessary work required to reconfigure 1588 will be done. This change also fixes an issue where a reset can cause the device to forget it's timestamp configuration, and revert to the default mode. Change-ID: I741d01c61d9fe1d24887859d1316e1a8a892909e Signed-off-by: Jacob Keller <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent d19af2a commit fbd5e2d

File tree

1 file changed

+46
-12
lines changed

1 file changed

+46
-12
lines changed

drivers/net/ethernet/intel/i40e/i40e_ptp.c

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -567,18 +567,22 @@ int i40e_ptp_set_ts_config(struct i40e_pf *pf, struct ifreq *ifr)
567567
}
568568

569569
/**
570-
* i40e_ptp_init - Initialize the 1588 support and register the PHC
570+
* i40e_ptp_create_clock - Create PTP clock device for userspace
571571
* @pf: Board private structure
572572
*
573-
* This function registers the device clock as a PHC. If it is successful, it
574-
* starts the clock in the hardware.
573+
* This function creates a new PTP clock device. It only creates one if we
574+
* don't already have one, so it is safe to call. Will return error if it
575+
* can't create one, but success if we already have a device. Should be used
576+
* by i40e_ptp_init to create clock initially, and prevent global resets from
577+
* creating new clock devices.
575578
**/
576-
void i40e_ptp_init(struct i40e_pf *pf)
579+
static long i40e_ptp_create_clock(struct i40e_pf *pf)
577580
{
578-
struct i40e_hw *hw = &pf->hw;
579-
struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev;
581+
/* no need to create a clock device if we already have one */
582+
if (!IS_ERR_OR_NULL(pf->ptp_clock))
583+
return 0;
580584

581-
strncpy(pf->ptp_caps.name, "i40e", sizeof(pf->ptp_caps.name));
585+
strncpy(pf->ptp_caps.name, i40e_driver_name, sizeof(pf->ptp_caps.name));
582586
pf->ptp_caps.owner = THIS_MODULE;
583587
pf->ptp_caps.max_adj = 999999999;
584588
pf->ptp_caps.n_ext_ts = 0;
@@ -592,22 +596,52 @@ void i40e_ptp_init(struct i40e_pf *pf)
592596
/* Attempt to register the clock before enabling the hardware. */
593597
pf->ptp_clock = ptp_clock_register(&pf->ptp_caps, &pf->pdev->dev);
594598
if (IS_ERR(pf->ptp_clock)) {
599+
return PTR_ERR(pf->ptp_clock);
600+
}
601+
602+
/* clear the hwtstamp settings here during clock create, instead of
603+
* during regular init, so that we can maintain settings across a
604+
* reset or suspend.
605+
*/
606+
pf->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
607+
pf->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
608+
609+
return 0;
610+
}
611+
612+
/**
613+
* i40e_ptp_init - Initialize the 1588 support after device probe or reset
614+
* @pf: Board private structure
615+
*
616+
* This function sets device up for 1588 support. The first time it is run, it
617+
* will create a PHC clock device. It does not create a clock device if one
618+
* already exists. It also reconfigures the device after a reset.
619+
**/
620+
void i40e_ptp_init(struct i40e_pf *pf)
621+
{
622+
struct net_device *netdev = pf->vsi[pf->lan_vsi]->netdev;
623+
struct i40e_hw *hw = &pf->hw;
624+
long err;
625+
626+
/* we have to initialize the lock first, since we can't control
627+
* when the user will enter the PHC device entry points
628+
*/
629+
spin_lock_init(&pf->tmreg_lock);
630+
631+
/* ensure we have a clock device */
632+
err = i40e_ptp_create_clock(pf);
633+
if (err) {
595634
pf->ptp_clock = NULL;
596635
dev_err(&pf->pdev->dev, "%s: ptp_clock_register failed\n",
597636
__func__);
598637
} else {
599638
struct timespec ts;
600639
u32 regval;
601640

602-
spin_lock_init(&pf->tmreg_lock);
603-
604641
dev_info(&pf->pdev->dev, "%s: added PHC on %s\n", __func__,
605642
netdev->name);
606643
pf->flags |= I40E_FLAG_PTP;
607644

608-
pf->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
609-
pf->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
610-
611645
/* Ensure the clocks are running. */
612646
regval = rd32(hw, I40E_PRTTSYN_CTL0);
613647
regval |= I40E_PRTTSYN_CTL0_TSYNENA_MASK;

0 commit comments

Comments
 (0)