Skip to content

Commit 5cb8805

Browse files
mwolechanguy11
authored andcommitted
idpf: negotiate PTP capabilities and get PTP clock
PTP capabilities are negotiated using virtchnl command. Add get capabilities function, direct access to read the PTP clock. Set initial PTP capabilities exposed to the stack. Reviewed-by: Jacob Keller <jacob.e.keller@intel.com> Signed-off-by: Milena Olech <milena.olech@intel.com> Tested-by: Willem de Bruijn <willemb@google.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>
1 parent c5d0607 commit 5cb8805

File tree

7 files changed

+354
-0
lines changed

7 files changed

+354
-0
lines changed

drivers/net/ethernet/intel/idpf/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,6 @@ idpf-y := \
1717
idpf_vf_dev.o
1818

1919
idpf-$(CONFIG_IDPF_SINGLEQ) += idpf_singleq_txrx.o
20+
2021
idpf-$(CONFIG_PTP_1588_CLOCK) += idpf_ptp.o
22+
idpf-$(CONFIG_PTP_1588_CLOCK) += idpf_virtchnl_ptp.o

drivers/net/ethernet/intel/idpf/idpf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ struct idpf_vport_max_q {
189189
* @mb_intr_reg_init: Mailbox interrupt register initialization
190190
* @reset_reg_init: Reset register initialization
191191
* @trigger_reset: Trigger a reset to occur
192+
* @ptp_reg_init: PTP register initialization
192193
*/
193194
struct idpf_reg_ops {
194195
void (*ctlq_reg_init)(struct idpf_ctlq_create_info *cq);
@@ -197,6 +198,7 @@ struct idpf_reg_ops {
197198
void (*reset_reg_init)(struct idpf_adapter *adapter);
198199
void (*trigger_reset)(struct idpf_adapter *adapter,
199200
enum idpf_flags trig_cause);
201+
void (*ptp_reg_init)(const struct idpf_adapter *adapter);
200202
};
201203

202204
/**

drivers/net/ethernet/intel/idpf/idpf_dev.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "idpf.h"
55
#include "idpf_lan_pf_regs.h"
66
#include "idpf_virtchnl.h"
7+
#include "idpf_ptp.h"
78

89
#define IDPF_PF_ITR_IDX_SPACING 0x4
910

@@ -148,6 +149,18 @@ static void idpf_trigger_reset(struct idpf_adapter *adapter,
148149
idpf_get_reg_addr(adapter, PFGEN_CTRL));
149150
}
150151

152+
/**
153+
* idpf_ptp_reg_init - Initialize required registers
154+
* @adapter: Driver specific private structure
155+
*
156+
* Set the bits required for enabling shtime and cmd execution
157+
*/
158+
static void idpf_ptp_reg_init(const struct idpf_adapter *adapter)
159+
{
160+
adapter->ptp->cmd.shtime_enable_mask = PF_GLTSYN_CMD_SYNC_SHTIME_EN_M;
161+
adapter->ptp->cmd.exec_cmd_mask = PF_GLTSYN_CMD_SYNC_EXEC_CMD_M;
162+
}
163+
151164
/**
152165
* idpf_reg_ops_init - Initialize register API function pointers
153166
* @adapter: Driver specific private structure
@@ -159,6 +172,7 @@ static void idpf_reg_ops_init(struct idpf_adapter *adapter)
159172
adapter->dev_ops.reg_ops.mb_intr_reg_init = idpf_mb_intr_reg_init;
160173
adapter->dev_ops.reg_ops.reset_reg_init = idpf_reset_reg_init;
161174
adapter->dev_ops.reg_ops.trigger_reset = idpf_trigger_reset;
175+
adapter->dev_ops.reg_ops.ptp_reg_init = idpf_ptp_reg_init;
162176
}
163177

164178
/**

drivers/net/ethernet/intel/idpf/idpf_lan_pf_regs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
#define PF_FW_ATQH_ATQH_M GENMASK(9, 0)
5454
#define PF_FW_ATQT (PF_FW_BASE + 0x24)
5555

56+
/* Timesync registers */
57+
#define PF_GLTSYN_CMD_SYNC_EXEC_CMD_M GENMASK(1, 0)
58+
#define PF_GLTSYN_CMD_SYNC_SHTIME_EN_M BIT(2)
59+
5660
/* Interrupts */
5761
#define PF_GLINT_BASE 0x08900000
5862
#define PF_GLINT_DYN_CTL(_INT) (PF_GLINT_BASE + ((_INT) * 0x1000))

drivers/net/ethernet/intel/idpf/idpf_ptp.c

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,163 @@
44
#include "idpf.h"
55
#include "idpf_ptp.h"
66

7+
/**
8+
* idpf_ptp_get_access - Determine the access type of the PTP features
9+
* @adapter: Driver specific private structure
10+
* @direct: Capability that indicates the direct access
11+
* @mailbox: Capability that indicates the mailbox access
12+
*
13+
* Return: the type of supported access for the PTP feature.
14+
*/
15+
static enum idpf_ptp_access
16+
idpf_ptp_get_access(const struct idpf_adapter *adapter, u32 direct, u32 mailbox)
17+
{
18+
if (adapter->ptp->caps & direct)
19+
return IDPF_PTP_DIRECT;
20+
else if (adapter->ptp->caps & mailbox)
21+
return IDPF_PTP_MAILBOX;
22+
else
23+
return IDPF_PTP_NONE;
24+
}
25+
26+
/**
27+
* idpf_ptp_get_features_access - Determine the access type of PTP features
28+
* @adapter: Driver specific private structure
29+
*
30+
* Fulfill the adapter structure with type of the supported PTP features
31+
* access.
32+
*/
33+
void idpf_ptp_get_features_access(const struct idpf_adapter *adapter)
34+
{
35+
struct idpf_ptp *ptp = adapter->ptp;
36+
u32 direct, mailbox;
37+
38+
/* Get the device clock time */
39+
direct = VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME;
40+
mailbox = VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME_MB;
41+
ptp->get_dev_clk_time_access = idpf_ptp_get_access(adapter,
42+
direct,
43+
mailbox);
44+
}
45+
46+
/**
47+
* idpf_ptp_enable_shtime - Enable shadow time and execute a command
48+
* @adapter: Driver specific private structure
49+
*/
50+
static void idpf_ptp_enable_shtime(struct idpf_adapter *adapter)
51+
{
52+
u32 shtime_enable, exec_cmd;
53+
54+
/* Get offsets */
55+
shtime_enable = adapter->ptp->cmd.shtime_enable_mask;
56+
exec_cmd = adapter->ptp->cmd.exec_cmd_mask;
57+
58+
/* Set the shtime en and the sync field */
59+
writel(shtime_enable, adapter->ptp->dev_clk_regs.cmd_sync);
60+
writel(exec_cmd | shtime_enable, adapter->ptp->dev_clk_regs.cmd_sync);
61+
}
62+
63+
/**
64+
* idpf_ptp_read_src_clk_reg_direct - Read directly the main timer value
65+
* @adapter: Driver specific private structure
66+
* @sts: Optional parameter for holding a pair of system timestamps from
67+
* the system clock. Will be ignored when NULL is given.
68+
*
69+
* Return: the device clock time.
70+
*/
71+
static u64 idpf_ptp_read_src_clk_reg_direct(struct idpf_adapter *adapter,
72+
struct ptp_system_timestamp *sts)
73+
{
74+
struct idpf_ptp *ptp = adapter->ptp;
75+
u32 hi, lo;
76+
77+
spin_lock(&ptp->read_dev_clk_lock);
78+
79+
/* Read the system timestamp pre PHC read */
80+
ptp_read_system_prets(sts);
81+
82+
idpf_ptp_enable_shtime(adapter);
83+
84+
/* Read the system timestamp post PHC read */
85+
ptp_read_system_postts(sts);
86+
87+
lo = readl(ptp->dev_clk_regs.dev_clk_ns_l);
88+
hi = readl(ptp->dev_clk_regs.dev_clk_ns_h);
89+
90+
spin_unlock(&ptp->read_dev_clk_lock);
91+
92+
return ((u64)hi << 32) | lo;
93+
}
94+
95+
/**
96+
* idpf_ptp_read_src_clk_reg - Read the main timer value
97+
* @adapter: Driver specific private structure
98+
* @src_clk: Returned main timer value in nanoseconds unit
99+
* @sts: Optional parameter for holding a pair of system timestamps from
100+
* the system clock. Will be ignored if NULL is given.
101+
*
102+
* Return: the device clock time on success, -errno otherwise.
103+
*/
104+
static int idpf_ptp_read_src_clk_reg(struct idpf_adapter *adapter, u64 *src_clk,
105+
struct ptp_system_timestamp *sts)
106+
{
107+
switch (adapter->ptp->get_dev_clk_time_access) {
108+
case IDPF_PTP_NONE:
109+
return -EOPNOTSUPP;
110+
case IDPF_PTP_DIRECT:
111+
*src_clk = idpf_ptp_read_src_clk_reg_direct(adapter, sts);
112+
break;
113+
default:
114+
return -EOPNOTSUPP;
115+
}
116+
117+
return 0;
118+
}
119+
120+
/**
121+
* idpf_ptp_gettimex64 - Get the time of the clock
122+
* @info: the driver's PTP info structure
123+
* @ts: timespec64 structure to hold the current time value
124+
* @sts: Optional parameter for holding a pair of system timestamps from
125+
* the system clock. Will be ignored if NULL is given.
126+
*
127+
* Return: the device clock value in ns, after converting it into a timespec
128+
* struct on success, -errno otherwise.
129+
*/
130+
static int idpf_ptp_gettimex64(struct ptp_clock_info *info,
131+
struct timespec64 *ts,
132+
struct ptp_system_timestamp *sts)
133+
{
134+
struct idpf_adapter *adapter = idpf_ptp_info_to_adapter(info);
135+
u64 time_ns;
136+
int err;
137+
138+
err = idpf_ptp_read_src_clk_reg(adapter, &time_ns, sts);
139+
if (err)
140+
return -EACCES;
141+
142+
*ts = ns_to_timespec64(time_ns);
143+
144+
return 0;
145+
}
146+
147+
/**
148+
* idpf_ptp_set_caps - Set PTP capabilities
149+
* @adapter: Driver specific private structure
150+
*
151+
* This function sets the PTP functions.
152+
*/
153+
static void idpf_ptp_set_caps(const struct idpf_adapter *adapter)
154+
{
155+
struct ptp_clock_info *info = &adapter->ptp->info;
156+
157+
snprintf(info->name, sizeof(info->name), "%s-%s-clk",
158+
KBUILD_MODNAME, pci_name(adapter->pdev));
159+
160+
info->owner = THIS_MODULE;
161+
info->gettimex64 = idpf_ptp_gettimex64;
162+
}
163+
7164
/**
8165
* idpf_ptp_create_clock - Create PTP clock device for userspace
9166
* @adapter: Driver specific private structure
@@ -16,6 +173,8 @@ static int idpf_ptp_create_clock(const struct idpf_adapter *adapter)
16173
{
17174
struct ptp_clock *clock;
18175

176+
idpf_ptp_set_caps(adapter);
177+
19178
/* Attempt to register the clock before enabling the hardware. */
20179
clock = ptp_clock_register(&adapter->ptp->info,
21180
&adapter->pdev->dev);
@@ -56,10 +215,21 @@ int idpf_ptp_init(struct idpf_adapter *adapter)
56215
/* add a back pointer to adapter */
57216
adapter->ptp->adapter = adapter;
58217

218+
if (adapter->dev_ops.reg_ops.ptp_reg_init)
219+
adapter->dev_ops.reg_ops.ptp_reg_init(adapter);
220+
221+
err = idpf_ptp_get_caps(adapter);
222+
if (err) {
223+
pci_err(adapter->pdev, "Failed to get PTP caps err %d\n", err);
224+
goto free_ptp;
225+
}
226+
59227
err = idpf_ptp_create_clock(adapter);
60228
if (err)
61229
goto free_ptp;
62230

231+
spin_lock_init(&adapter->ptp->read_dev_clk_lock);
232+
63233
pci_dbg(adapter->pdev, "PTP init successful\n");
64234

65235
return 0;

drivers/net/ethernet/intel/idpf/idpf_ptp.h

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,111 @@
66

77
#include <linux/ptp_clock_kernel.h>
88

9+
/**
10+
* struct idpf_ptp_cmd - PTP command masks
11+
* @exec_cmd_mask: mask to trigger command execution
12+
* @shtime_enable_mask: mask to enable shadow time
13+
*/
14+
struct idpf_ptp_cmd {
15+
u32 exec_cmd_mask;
16+
u32 shtime_enable_mask;
17+
};
18+
19+
/* struct idpf_ptp_dev_clk_regs - PTP device registers
20+
* @dev_clk_ns_l: low part of the device clock register
21+
* @dev_clk_ns_h: high part of the device clock register
22+
* @phy_clk_ns_l: low part of the PHY clock register
23+
* @phy_clk_ns_h: high part of the PHY clock register
24+
* @cmd: PTP command register
25+
* @phy_cmd: PHY command register
26+
* @cmd_sync: PTP command synchronization register
27+
*/
28+
struct idpf_ptp_dev_clk_regs {
29+
/* Main clock */
30+
void __iomem *dev_clk_ns_l;
31+
void __iomem *dev_clk_ns_h;
32+
33+
/* PHY timer */
34+
void __iomem *phy_clk_ns_l;
35+
void __iomem *phy_clk_ns_h;
36+
37+
/* Command */
38+
void __iomem *cmd;
39+
void __iomem *phy_cmd;
40+
void __iomem *cmd_sync;
41+
};
42+
43+
/**
44+
* enum idpf_ptp_access - the type of access to PTP operations
45+
* @IDPF_PTP_NONE: no access
46+
* @IDPF_PTP_DIRECT: direct access through BAR registers
47+
* @IDPF_PTP_MAILBOX: access through mailbox messages
48+
*/
49+
enum idpf_ptp_access {
50+
IDPF_PTP_NONE = 0,
51+
IDPF_PTP_DIRECT,
52+
IDPF_PTP_MAILBOX,
53+
};
54+
955
/**
1056
* struct idpf_ptp - PTP parameters
1157
* @info: structure defining PTP hardware capabilities
1258
* @clock: pointer to registered PTP clock device
1359
* @adapter: back pointer to the adapter
60+
* @cmd: HW specific command masks
61+
* @dev_clk_regs: the set of registers to access the device clock
62+
* @caps: PTP capabilities negotiated with the Control Plane
63+
* @get_dev_clk_time_access: access type for getting the device clock time
64+
* @rsv: reserved bits
65+
* @read_dev_clk_lock: spinlock protecting access to the device clock read
66+
* operation executed by the HW latch
1467
*/
1568
struct idpf_ptp {
1669
struct ptp_clock_info info;
1770
struct ptp_clock *clock;
1871
struct idpf_adapter *adapter;
72+
struct idpf_ptp_cmd cmd;
73+
struct idpf_ptp_dev_clk_regs dev_clk_regs;
74+
u32 caps;
75+
enum idpf_ptp_access get_dev_clk_time_access:2;
76+
u32 rsv:30;
77+
spinlock_t read_dev_clk_lock;
1978
};
2079

80+
/**
81+
* idpf_ptp_info_to_adapter - get driver adapter struct from ptp_clock_info
82+
* @info: pointer to ptp_clock_info struct
83+
*
84+
* Return: pointer to the corresponding adapter struct
85+
*/
86+
static inline struct idpf_adapter *
87+
idpf_ptp_info_to_adapter(const struct ptp_clock_info *info)
88+
{
89+
const struct idpf_ptp *ptp = container_of_const(info, struct idpf_ptp,
90+
info);
91+
return ptp->adapter;
92+
}
93+
2194
#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
2295
int idpf_ptp_init(struct idpf_adapter *adapter);
2396
void idpf_ptp_release(struct idpf_adapter *adapter);
97+
int idpf_ptp_get_caps(struct idpf_adapter *adapter);
98+
void idpf_ptp_get_features_access(const struct idpf_adapter *adapter);
2499
#else /* CONFIG_PTP_1588_CLOCK */
25100
static inline int idpf_ptp_init(struct idpf_adapter *adapter)
26101
{
27102
return 0;
28103
}
29104

30105
static inline void idpf_ptp_release(struct idpf_adapter *adapter) { }
106+
107+
static inline int idpf_ptp_get_caps(struct idpf_adapter *adapter)
108+
{
109+
return -EOPNOTSUPP;
110+
}
111+
112+
static inline void
113+
idpf_ptp_get_features_access(const struct idpf_adapter *adapter) { }
114+
31115
#endif /* CONFIG_PTP_1588_CLOCK */
32116
#endif /* _IDPF_PTP_H */

0 commit comments

Comments
 (0)