/* 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_cmd - PTP command masks
* @ exec_cmd_mask : mask to trigger command execution
* @ shtime_enable_mask : mask to enable shadow time
*/
struct idpf_ptp_cmd {
u32 exec_cmd_mask;
u32 shtime_enable_mask;
};
/* struct idpf_ptp_dev_clk_regs - PTP device registers
* @ dev_clk_ns_l : low part of the device clock register
* @ dev_clk_ns_h : high part of the device clock register
* @ phy_clk_ns_l : low part of the PHY clock register
* @ phy_clk_ns_h : high part of the PHY clock register
* @ sys_time_ns_l : low part of the system time register
* @ sys_time_ns_h : high part of the system time register
* @ incval_l : low part of the increment value register
* @ incval_h : high part of the increment value register
* @ shadj_l : low part of the shadow adjust register
* @ shadj_h : high part of the shadow adjust register
* @ phy_incval_l : low part of the PHY increment value register
* @ phy_incval_h : high part of the PHY increment value register
* @ phy_shadj_l : low part of the PHY shadow adjust register
* @ phy_shadj_h : high part of the PHY shadow adjust register
* @ cmd : PTP command register
* @ phy_cmd : PHY command register
* @ cmd_sync : PTP command synchronization register
*/
struct idpf_ptp_dev_clk_regs {
/* Main clock */
void __iomem *dev_clk_ns_l;
void __iomem *dev_clk_ns_h;
/* PHY timer */
void __iomem *phy_clk_ns_l;
void __iomem *phy_clk_ns_h;
/* System time */
void __iomem *sys_time_ns_l;
void __iomem *sys_time_ns_h;
/* Main timer adjustments */
void __iomem *incval_l;
void __iomem *incval_h;
void __iomem *shadj_l;
void __iomem *shadj_h;
/* PHY timer adjustments */
void __iomem *phy_incval_l;
void __iomem *phy_incval_h;
void __iomem *phy_shadj_l;
void __iomem *phy_shadj_h;
/* Command */
void __iomem *cmd;
void __iomem *phy_cmd;
void __iomem *cmd_sync;
};
/**
* enum idpf_ptp_access - the type of access to PTP operations
* @ IDPF_PTP_NONE : no access
* @ IDPF_PTP_DIRECT : direct access through BAR registers
* @ IDPF_PTP_MAILBOX : access through mailbox messages
*/
enum idpf_ptp_access {
IDPF_PTP_NONE = 0 ,
IDPF_PTP_DIRECT,
IDPF_PTP_MAILBOX,
};
/**
* struct idpf_ptp_secondary_mbx - PTP secondary mailbox
* @ peer_mbx_q_id : PTP mailbox queue ID
* @ peer_id : Peer ID for PTP Device Control daemon
* @ valid : indicates whether secondary mailblox is supported by the Control
* Plane
*/
struct idpf_ptp_secondary_mbx {
u16 peer_mbx_q_id;
u16 peer_id;
bool valid:1 ;
};
/**
* enum idpf_ptp_tx_tstamp_state - Tx timestamp states
* @ IDPF_PTP_FREE : Tx timestamp index free to use
* @ IDPF_PTP_REQUEST : Tx timestamp index set to the Tx descriptor
* @ IDPF_PTP_READ_VALUE : Tx timestamp value ready to be read
*/
enum idpf_ptp_tx_tstamp_state {
IDPF_PTP_FREE,
IDPF_PTP_REQUEST,
IDPF_PTP_READ_VALUE,
};
/**
* struct idpf_ptp_tx_tstamp_status - Parameters to track Tx timestamp
* @ skb : the pointer to the SKB that received the completion tag
* @ state : the state of the Tx timestamp
*/
struct idpf_ptp_tx_tstamp_status {
struct sk_buff *skb;
enum idpf_ptp_tx_tstamp_state state;
};
/**
* struct idpf_ptp_tx_tstamp - Parameters for Tx timestamping
* @ list_member : the list member structure
* @ tx_latch_reg_offset_l : Tx tstamp latch low register offset
* @ tx_latch_reg_offset_h : Tx tstamp latch high register offset
* @ skb : the pointer to the SKB for this timestamp request
* @ tstamp : the Tx tstamp value
* @ idx : the index of the Tx tstamp
*/
struct idpf_ptp_tx_tstamp {
struct list_head list_member;
u32 tx_latch_reg_offset_l;
u32 tx_latch_reg_offset_h;
struct sk_buff *skb;
u64 tstamp;
u32 idx;
};
/**
* struct idpf_ptp_vport_tx_tstamp_caps - Tx timestamp capabilities
* @ vport_id : the vport id
* @ num_entries : the number of negotiated Tx timestamp entries
* @ tstamp_ns_lo_bit : first bit for nanosecond part of the timestamp
* @ latches_lock : the lock to the lists of free / used timestamp indexes
* @ status_lock : the lock to the status tracker
* @ access : indicates an access to Tx timestamp
* @ latches_free : the list of the free Tx timestamps latches
* @ latches_in_use : the list of the used Tx timestamps latches
* @ tx_tstamp_status : Tx tstamp status tracker
*/
struct idpf_ptp_vport_tx_tstamp_caps {
u32 vport_id;
u16 num_entries;
u16 tstamp_ns_lo_bit;
spinlock_t latches_lock;
spinlock_t status_lock;
bool access:1 ;
struct list_head latches_free;
struct list_head latches_in_use;
struct idpf_ptp_tx_tstamp_status tx_tstamp_status[];
};
/**
* struct idpf_ptp - PTP parameters
* @ info : structure defining PTP hardware capabilities
* @ clock : pointer to registered PTP clock device
* @ adapter : back pointer to the adapter
* @ base_incval : base increment value of the PTP clock
* @ max_adj : maximum adjustment of the PTP clock
* @ cmd : HW specific command masks
* @ cached_phc_time : a cached copy of the PHC time for timestamp extension
* @ cached_phc_jiffies : jiffies when cached_phc_time was last updated
* @ dev_clk_regs : the set of registers to access the device clock
* @ caps : PTP capabilities negotiated with the Control Plane
* @ get_dev_clk_time_access : access type for getting the device clock time
* @ get_cross_tstamp_access : access type for the cross timestamping
* @ set_dev_clk_time_access : access type for setting the device clock time
* @ adj_dev_clk_time_access : access type for the adjusting the device clock
* @ tx_tstamp_access : access type for the Tx timestamp value read
* @ rsv : reserved bits
* @ secondary_mbx : parameters for using dedicated PTP mailbox
* @ read_dev_clk_lock : spinlock protecting access to the device clock read
* operation executed by the HW latch
*/
struct idpf_ptp {
struct ptp_clock_info info;
struct ptp_clock *clock;
struct idpf_adapter *adapter;
u64 base_incval;
u64 max_adj;
struct idpf_ptp_cmd cmd;
u64 cached_phc_time;
unsigned long cached_phc_jiffies;
struct idpf_ptp_dev_clk_regs dev_clk_regs;
u32 caps;
enum idpf_ptp_access get_dev_clk_time_access:2 ;
enum idpf_ptp_access get_cross_tstamp_access:2 ;
enum idpf_ptp_access set_dev_clk_time_access:2 ;
enum idpf_ptp_access adj_dev_clk_time_access:2 ;
enum idpf_ptp_access tx_tstamp_access:2 ;
u8 rsv;
struct idpf_ptp_secondary_mbx secondary_mbx;
spinlock_t read_dev_clk_lock;
};
/**
* idpf_ptp_info_to_adapter - get driver adapter struct from ptp_clock_info
* @ info : pointer to ptp_clock_info struct
*
* Return : pointer to the corresponding adapter struct
*/
static inline struct idpf_adapter *
idpf_ptp_info_to_adapter(const struct ptp_clock_info *info)
{
const struct idpf_ptp *ptp = container_of_const(info, struct idpf_ptp,
info);
return ptp->adapter;
}
/**
* struct idpf_ptp_dev_timers - System time and device time values
* @ sys_time_ns : system time value expressed in nanoseconds
* @ dev_clk_time_ns : device clock time value expressed in nanoseconds
*/
struct idpf_ptp_dev_timers {
u64 sys_time_ns;
u64 dev_clk_time_ns;
};
/**
* idpf_ptp_is_vport_tx_tstamp_ena - Verify the Tx timestamping enablement for
* a given vport .
* @ vport : Virtual port structure
*
* Tx timestamp capabilities are negotiated with the Control Plane only if the
* device clock value can be read , Tx timestamp access type is different than
* NONE , and the PTP clock for the adapter is created . When all those conditions
* are satisfied , Tx timestamp feature is enabled and tx_tstamp_caps is
* allocated and fulfilled .
*
* Return : true if the Tx timestamping is enabled , false otherwise .
*/
static inline bool idpf_ptp_is_vport_tx_tstamp_ena(struct idpf_vport *vport)
{
if (!vport->tx_tstamp_caps)
return false ;
else
return true ;
}
/**
* idpf_ptp_is_vport_rx_tstamp_ena - Verify the Rx timestamping enablement for
* a given vport .
* @ vport : Virtual port structure
*
* Rx timestamp feature is enabled if the PTP clock for the adapter is created
* and it is possible to read the value of the device clock . The second
* assumption comes from the need to extend the Rx timestamp value to 64 bit
* based on the current device clock time .
*
* Return : true if the Rx timestamping is enabled , false otherwise .
*/
static inline bool idpf_ptp_is_vport_rx_tstamp_ena(struct idpf_vport *vport)
{
if (!vport->adapter->ptp ||
vport->adapter->ptp->get_dev_clk_time_access == IDPF_PTP_NONE)
return false ;
else
return true ;
}
#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
int idpf_ptp_init(struct idpf_adapter *adapter);
void idpf_ptp_release(struct idpf_adapter *adapter);
int idpf_ptp_get_caps(struct idpf_adapter *adapter);
void idpf_ptp_get_features_access(const struct idpf_adapter *adapter);
bool idpf_ptp_get_txq_tstamp_capability(struct idpf_tx_queue *txq);
int idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,
struct idpf_ptp_dev_timers *dev_clk_time);
int idpf_ptp_get_cross_time(struct idpf_adapter *adapter,
struct idpf_ptp_dev_timers *cross_time);
int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, u64 time);
int idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter, u64 incval);
int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter, s64 delta);
int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport);
int idpf_ptp_get_tx_tstamp(struct idpf_vport *vport);
int idpf_ptp_set_timestamp_mode(struct idpf_vport *vport,
struct kernel_hwtstamp_config *config);
u64 idpf_ptp_extend_ts(struct idpf_vport *vport, u64 in_tstamp);
u64 idpf_ptp_tstamp_extend_32b_to_64b(u64 cached_phc_time, u32 in_timestamp);
int idpf_ptp_request_ts(struct idpf_tx_queue *tx_q, struct sk_buff *skb,
u32 *idx);
void idpf_tstamp_task(struct work_struct *work);
#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) { }
static inline int idpf_ptp_get_caps(struct idpf_adapter *adapter)
{
return -EOPNOTSUPP;
}
static inline void
idpf_ptp_get_features_access(const struct idpf_adapter *adapter) { }
static inline bool
idpf_ptp_get_txq_tstamp_capability(struct idpf_tx_queue *txq)
{
return false ;
}
static inline int
idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,
struct idpf_ptp_dev_timers *dev_clk_time)
{
return -EOPNOTSUPP;
}
static inline int
idpf_ptp_get_cross_time(struct idpf_adapter *adapter,
struct idpf_ptp_dev_timers *cross_time)
{
return -EOPNOTSUPP;
}
static inline int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter,
u64 time)
{
return -EOPNOTSUPP;
}
static inline int idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter,
u64 incval)
{
return -EOPNOTSUPP;
}
static inline int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter,
s64 delta)
{
return -EOPNOTSUPP;
}
static inline int idpf_ptp_get_vport_tstamps_caps(struct idpf_vport *vport)
{
return -EOPNOTSUPP;
}
static inline int idpf_ptp_get_tx_tstamp(struct idpf_vport *vport)
{
return -EOPNOTSUPP;
}
static inline int
idpf_ptp_set_timestamp_mode(struct idpf_vport *vport,
struct kernel_hwtstamp_config *config)
{
return -EOPNOTSUPP;
}
static inline u64 idpf_ptp_extend_ts(struct idpf_vport *vport, u32 in_tstamp)
{
return 0 ;
}
static inline u64 idpf_ptp_tstamp_extend_32b_to_64b(u64 cached_phc_time,
u32 in_timestamp)
{
return 0 ;
}
static inline int idpf_ptp_request_ts(struct idpf_tx_queue *tx_q,
struct sk_buff *skb, u32 *idx)
{
return -EOPNOTSUPP;
}
static inline void idpf_tstamp_task(struct work_struct *work) { }
#endif /* CONFIG_PTP_1588_CLOCK */
#endif /* _IDPF_PTP_H */
Messung V0.5 in Prozent C=94 H=100 G=96
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-10-03)
¤
*© Formatika GbR, Deutschland