idpf: add initial PTP support

PTP feature is supported if the VIRTCHNL2_CAP_PTP is negotiated during the
capabilities recognition. Initial PTP support includes PTP initialization
and registration of the clock.

Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Milena Olech <milena.olech@intel.com>
Tested-by: Mina Almasry <almasrymina@google.com>
Tested-by: Samuel Salin <Samuel.salin@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
Milena Olech 2025-04-16 14:19:02 +02:00 committed by Tony Nguyen
parent 9525a12d6b
commit 8d5e12c592
7 changed files with 140 additions and 1 deletions

View File

@ -4,6 +4,7 @@
config IDPF
tristate "Intel(R) Infrastructure Data Path Function Support"
depends on PCI_MSI
depends on PTP_1588_CLOCK_OPTIONAL
select DIMLIB
select LIBETH
help

View File

@ -17,3 +17,4 @@ idpf-y := \
idpf_vf_dev.o
idpf-$(CONFIG_IDPF_SINGLEQ) += idpf_singleq_txrx.o
idpf-$(CONFIG_PTP_1588_CLOCK) += idpf_ptp.o

View File

@ -530,6 +530,7 @@ struct idpf_vc_xn_manager;
* @vector_lock: Lock to protect vector distribution
* @queue_lock: Lock to protect queue distribution
* @vc_buf_lock: Lock to protect virtchnl buffer
* @ptp: Storage for PTP-related data
*/
struct idpf_adapter {
struct pci_dev *pdev;
@ -587,6 +588,8 @@ struct idpf_adapter {
struct mutex vector_lock;
struct mutex queue_lock;
struct mutex vc_buf_lock;
struct idpf_ptp *ptp;
};
/**

View File

@ -168,6 +168,10 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_free;
}
err = pci_enable_ptm(pdev, NULL);
if (err)
pci_dbg(pdev, "PCIe PTM is not supported by PCIe bus/controller\n");
/* set up for high or low dma */
err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
if (err) {

View File

@ -0,0 +1,90 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2024 Intel Corporation */
#include "idpf.h"
#include "idpf_ptp.h"
/**
* idpf_ptp_create_clock - Create PTP clock device for userspace
* @adapter: Driver specific private structure
*
* This function creates a new PTP clock device.
*
* Return: 0 on success, -errno otherwise.
*/
static int idpf_ptp_create_clock(const struct idpf_adapter *adapter)
{
struct ptp_clock *clock;
/* Attempt to register the clock before enabling the hardware. */
clock = ptp_clock_register(&adapter->ptp->info,
&adapter->pdev->dev);
if (IS_ERR(clock)) {
pci_err(adapter->pdev, "PTP clock creation failed: %pe\n",
clock);
return PTR_ERR(clock);
}
adapter->ptp->clock = clock;
return 0;
}
/**
* idpf_ptp_init - Initialize PTP hardware clock support
* @adapter: Driver specific private structure
*
* Set up the device for interacting with the PTP hardware clock for all
* functions. Function will allocate and register a ptp_clock with the
* PTP_1588_CLOCK infrastructure.
*
* Return: 0 on success, -errno otherwise.
*/
int idpf_ptp_init(struct idpf_adapter *adapter)
{
int err;
if (!idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_PTP)) {
pci_dbg(adapter->pdev, "PTP capability is not detected\n");
return -EOPNOTSUPP;
}
adapter->ptp = kzalloc(sizeof(*adapter->ptp), GFP_KERNEL);
if (!adapter->ptp)
return -ENOMEM;
/* add a back pointer to adapter */
adapter->ptp->adapter = adapter;
err = idpf_ptp_create_clock(adapter);
if (err)
goto free_ptp;
pci_dbg(adapter->pdev, "PTP init successful\n");
return 0;
free_ptp:
kfree(adapter->ptp);
adapter->ptp = NULL;
return err;
}
/**
* idpf_ptp_release - Clear PTP hardware clock support
* @adapter: Driver specific private structure
*/
void idpf_ptp_release(struct idpf_adapter *adapter)
{
struct idpf_ptp *ptp = adapter->ptp;
if (!ptp)
return;
if (ptp->clock)
ptp_clock_unregister(ptp->clock);
kfree(ptp);
adapter->ptp = NULL;
}

View File

@ -0,0 +1,32 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (C) 2024 Intel Corporation */
#ifndef _IDPF_PTP_H
#define _IDPF_PTP_H
#include <linux/ptp_clock_kernel.h>
/**
* struct idpf_ptp - PTP parameters
* @info: structure defining PTP hardware capabilities
* @clock: pointer to registered PTP clock device
* @adapter: back pointer to the adapter
*/
struct idpf_ptp {
struct ptp_clock_info info;
struct ptp_clock *clock;
struct idpf_adapter *adapter;
};
#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
int idpf_ptp_init(struct idpf_adapter *adapter);
void idpf_ptp_release(struct idpf_adapter *adapter);
#else /* CONFIG_PTP_1588_CLOCK */
static inline int idpf_ptp_init(struct idpf_adapter *adapter)
{
return 0;
}
static inline void idpf_ptp_release(struct idpf_adapter *adapter) { }
#endif /* CONFIG_PTP_1588_CLOCK */
#endif /* _IDPF_PTP_H */

View File

@ -5,6 +5,7 @@
#include "idpf.h"
#include "idpf_virtchnl.h"
#include "idpf_ptp.h"
#define IDPF_VC_XN_MIN_TIMEOUT_MSEC 2000
#define IDPF_VC_XN_DEFAULT_TIMEOUT_MSEC (60 * 1000)
@ -900,7 +901,8 @@ static int idpf_send_get_caps_msg(struct idpf_adapter *adapter)
VIRTCHNL2_CAP_MACFILTER |
VIRTCHNL2_CAP_SPLITQ_QSCHED |
VIRTCHNL2_CAP_PROMISC |
VIRTCHNL2_CAP_LOOPBACK);
VIRTCHNL2_CAP_LOOPBACK |
VIRTCHNL2_CAP_PTP);
xn_params.vc_op = VIRTCHNL2_OP_GET_CAPS;
xn_params.send_buf.iov_base = &caps;
@ -3029,6 +3031,11 @@ int idpf_vc_core_init(struct idpf_adapter *adapter)
goto err_intr_req;
}
err = idpf_ptp_init(adapter);
if (err)
pci_err(adapter->pdev, "PTP init failed, err=%pe\n",
ERR_PTR(err));
idpf_init_avail_queues(adapter);
/* Skew the delay for init tasks for each function based on fn number
@ -3091,6 +3098,7 @@ void idpf_vc_core_deinit(struct idpf_adapter *adapter)
if (!remove_in_prog)
idpf_vc_xn_shutdown(adapter->vcxn_mngr);
idpf_ptp_release(adapter);
idpf_deinit_task(adapter);
idpf_intr_rel(adapter);