Skip to content

Commit d5dba8f

Browse files
mwolechanguy11
authored andcommitted
idpf: add PTP clock configuration
PTP clock configuration operations - set time, adjust time and adjust frequency are required to control the clock and maintain synchronization process. Extend get PTP capabilities function to request for the clock adjustments and add functions to enable these actions using dedicated virtchnl messages. Reviewed-by: Alexander Lobakin <aleksander.lobakin@intel.com> 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>
1 parent 5a27503 commit d5dba8f

File tree

4 files changed

+386
-3
lines changed

4 files changed

+386
-3
lines changed

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

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,20 @@ void idpf_ptp_get_features_access(const struct idpf_adapter *adapter)
4141
ptp->get_dev_clk_time_access = idpf_ptp_get_access(adapter,
4242
direct,
4343
mailbox);
44+
45+
/* Set the device clock time */
46+
direct = VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME;
47+
mailbox = VIRTCHNL2_CAP_PTP_SET_DEVICE_CLK_TIME;
48+
ptp->set_dev_clk_time_access = idpf_ptp_get_access(adapter,
49+
direct,
50+
mailbox);
51+
52+
/* Adjust the device clock time */
53+
direct = VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK;
54+
mailbox = VIRTCHNL2_CAP_PTP_ADJ_DEVICE_CLK_MB;
55+
ptp->adj_dev_clk_time_access = idpf_ptp_get_access(adapter,
56+
direct,
57+
mailbox);
4458
}
4559

4660
/**
@@ -177,6 +191,157 @@ static int idpf_ptp_gettimex64(struct ptp_clock_info *info,
177191
return 0;
178192
}
179193

194+
/**
195+
* idpf_ptp_settime64 - Set the time of the clock
196+
* @info: the driver's PTP info structure
197+
* @ts: timespec64 structure that holds the new time value
198+
*
199+
* Set the device clock to the user input value. The conversion from timespec
200+
* to ns happens in the write function.
201+
*
202+
* Return: 0 on success, -errno otherwise.
203+
*/
204+
static int idpf_ptp_settime64(struct ptp_clock_info *info,
205+
const struct timespec64 *ts)
206+
{
207+
struct idpf_adapter *adapter = idpf_ptp_info_to_adapter(info);
208+
enum idpf_ptp_access access;
209+
int err;
210+
u64 ns;
211+
212+
access = adapter->ptp->set_dev_clk_time_access;
213+
if (access != IDPF_PTP_MAILBOX)
214+
return -EOPNOTSUPP;
215+
216+
ns = timespec64_to_ns(ts);
217+
218+
err = idpf_ptp_set_dev_clk_time(adapter, ns);
219+
if (err) {
220+
pci_err(adapter->pdev, "Failed to set the time, err: %pe\n",
221+
ERR_PTR(err));
222+
return err;
223+
}
224+
225+
return 0;
226+
}
227+
228+
/**
229+
* idpf_ptp_adjtime_nonatomic - Do a non-atomic clock adjustment
230+
* @info: the driver's PTP info structure
231+
* @delta: Offset in nanoseconds to adjust the time by
232+
*
233+
* Return: 0 on success, -errno otherwise.
234+
*/
235+
static int idpf_ptp_adjtime_nonatomic(struct ptp_clock_info *info, s64 delta)
236+
{
237+
struct timespec64 now, then;
238+
int err;
239+
240+
err = idpf_ptp_gettimex64(info, &now, NULL);
241+
if (err)
242+
return err;
243+
244+
then = ns_to_timespec64(delta);
245+
now = timespec64_add(now, then);
246+
247+
return idpf_ptp_settime64(info, &now);
248+
}
249+
250+
/**
251+
* idpf_ptp_adjtime - Adjust the time of the clock by the indicated delta
252+
* @info: the driver's PTP info structure
253+
* @delta: Offset in nanoseconds to adjust the time by
254+
*
255+
* Return: 0 on success, -errno otherwise.
256+
*/
257+
static int idpf_ptp_adjtime(struct ptp_clock_info *info, s64 delta)
258+
{
259+
struct idpf_adapter *adapter = idpf_ptp_info_to_adapter(info);
260+
enum idpf_ptp_access access;
261+
int err;
262+
263+
access = adapter->ptp->adj_dev_clk_time_access;
264+
if (access != IDPF_PTP_MAILBOX)
265+
return -EOPNOTSUPP;
266+
267+
/* Hardware only supports atomic adjustments using signed 32-bit
268+
* integers. For any adjustment outside this range, perform
269+
* a non-atomic get->adjust->set flow.
270+
*/
271+
if (delta > S32_MAX || delta < S32_MIN)
272+
return idpf_ptp_adjtime_nonatomic(info, delta);
273+
274+
err = idpf_ptp_adj_dev_clk_time(adapter, delta);
275+
if (err) {
276+
pci_err(adapter->pdev, "Failed to adjust the clock with delta %lld err: %pe\n",
277+
delta, ERR_PTR(err));
278+
return err;
279+
}
280+
281+
return 0;
282+
}
283+
284+
/**
285+
* idpf_ptp_adjfine - Adjust clock increment rate
286+
* @info: the driver's PTP info structure
287+
* @scaled_ppm: Parts per million with 16-bit fractional field
288+
*
289+
* Adjust the frequency of the clock by the indicated scaled ppm from the
290+
* base frequency.
291+
*
292+
* Return: 0 on success, -errno otherwise.
293+
*/
294+
static int idpf_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm)
295+
{
296+
struct idpf_adapter *adapter = idpf_ptp_info_to_adapter(info);
297+
enum idpf_ptp_access access;
298+
u64 incval, diff;
299+
int err;
300+
301+
access = adapter->ptp->adj_dev_clk_time_access;
302+
if (access != IDPF_PTP_MAILBOX)
303+
return -EOPNOTSUPP;
304+
305+
incval = adapter->ptp->base_incval;
306+
307+
diff = adjust_by_scaled_ppm(incval, scaled_ppm);
308+
err = idpf_ptp_adj_dev_clk_fine(adapter, diff);
309+
if (err)
310+
pci_err(adapter->pdev, "Failed to adjust clock increment rate for scaled ppm %ld %pe\n",
311+
scaled_ppm, ERR_PTR(err));
312+
313+
return 0;
314+
}
315+
316+
/**
317+
* idpf_ptp_verify_pin - Verify if pin supports requested pin function
318+
* @info: the driver's PTP info structure
319+
* @pin: Pin index
320+
* @func: Assigned function
321+
* @chan: Assigned channel
322+
*
323+
* Return: EOPNOTSUPP as not supported yet.
324+
*/
325+
static int idpf_ptp_verify_pin(struct ptp_clock_info *info, unsigned int pin,
326+
enum ptp_pin_function func, unsigned int chan)
327+
{
328+
return -EOPNOTSUPP;
329+
}
330+
331+
/**
332+
* idpf_ptp_gpio_enable - Enable/disable ancillary features of PHC
333+
* @info: the driver's PTP info structure
334+
* @rq: The requested feature to change
335+
* @on: Enable/disable flag
336+
*
337+
* Return: EOPNOTSUPP as not supported yet.
338+
*/
339+
static int idpf_ptp_gpio_enable(struct ptp_clock_info *info,
340+
struct ptp_clock_request *rq, int on)
341+
{
342+
return -EOPNOTSUPP;
343+
}
344+
180345
/**
181346
* idpf_ptp_set_caps - Set PTP capabilities
182347
* @adapter: Driver specific private structure
@@ -191,7 +356,13 @@ static void idpf_ptp_set_caps(const struct idpf_adapter *adapter)
191356
KBUILD_MODNAME, pci_name(adapter->pdev));
192357

193358
info->owner = THIS_MODULE;
359+
info->max_adj = adapter->ptp->max_adj;
194360
info->gettimex64 = idpf_ptp_gettimex64;
361+
info->settime64 = idpf_ptp_settime64;
362+
info->adjfine = idpf_ptp_adjfine;
363+
info->adjtime = idpf_ptp_adjtime;
364+
info->verify = idpf_ptp_verify_pin;
365+
info->enable = idpf_ptp_gpio_enable;
195366
}
196367

197368
/**
@@ -234,6 +405,7 @@ static int idpf_ptp_create_clock(const struct idpf_adapter *adapter)
234405
*/
235406
int idpf_ptp_init(struct idpf_adapter *adapter)
236407
{
408+
struct timespec64 ts;
237409
int err;
238410

239411
if (!idpf_is_cap_ena(adapter, IDPF_OTHER_CAPS, VIRTCHNL2_CAP_PTP)) {
@@ -261,12 +433,34 @@ int idpf_ptp_init(struct idpf_adapter *adapter)
261433
if (err)
262434
goto free_ptp;
263435

436+
/* Write the default increment time value if the clock adjustments
437+
* are enabled.
438+
*/
439+
if (adapter->ptp->adj_dev_clk_time_access != IDPF_PTP_NONE) {
440+
err = idpf_ptp_adj_dev_clk_fine(adapter,
441+
adapter->ptp->base_incval);
442+
if (err)
443+
goto remove_clock;
444+
}
445+
446+
/* Write the initial time value if the set time operation is enabled */
447+
if (adapter->ptp->set_dev_clk_time_access != IDPF_PTP_NONE) {
448+
ts = ktime_to_timespec64(ktime_get_real());
449+
err = idpf_ptp_settime64(&adapter->ptp->info, &ts);
450+
if (err)
451+
goto remove_clock;
452+
}
453+
264454
spin_lock_init(&adapter->ptp->read_dev_clk_lock);
265455

266456
pci_dbg(adapter->pdev, "PTP init successful\n");
267457

268458
return 0;
269459

460+
remove_clock:
461+
ptp_clock_unregister(adapter->ptp->clock);
462+
adapter->ptp->clock = NULL;
463+
270464
free_ptp:
271465
kfree(adapter->ptp);
272466
adapter->ptp = NULL;

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

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@ struct idpf_ptp_cmd {
2121
* @dev_clk_ns_h: high part of the device clock register
2222
* @phy_clk_ns_l: low part of the PHY clock register
2323
* @phy_clk_ns_h: high part of the PHY clock register
24+
* @incval_l: low part of the increment value register
25+
* @incval_h: high part of the increment value register
26+
* @shadj_l: low part of the shadow adjust register
27+
* @shadj_h: high part of the shadow adjust register
28+
* @phy_incval_l: low part of the PHY increment value register
29+
* @phy_incval_h: high part of the PHY increment value register
30+
* @phy_shadj_l: low part of the PHY shadow adjust register
31+
* @phy_shadj_h: high part of the PHY shadow adjust register
2432
* @cmd: PTP command register
2533
* @phy_cmd: PHY command register
2634
* @cmd_sync: PTP command synchronization register
@@ -34,6 +42,18 @@ struct idpf_ptp_dev_clk_regs {
3442
void __iomem *phy_clk_ns_l;
3543
void __iomem *phy_clk_ns_h;
3644

45+
/* Main timer adjustments */
46+
void __iomem *incval_l;
47+
void __iomem *incval_h;
48+
void __iomem *shadj_l;
49+
void __iomem *shadj_h;
50+
51+
/* PHY timer adjustments */
52+
void __iomem *phy_incval_l;
53+
void __iomem *phy_incval_h;
54+
void __iomem *phy_shadj_l;
55+
void __iomem *phy_shadj_h;
56+
3757
/* Command */
3858
void __iomem *cmd;
3959
void __iomem *phy_cmd;
@@ -70,10 +90,14 @@ struct idpf_ptp_secondary_mbx {
7090
* @info: structure defining PTP hardware capabilities
7191
* @clock: pointer to registered PTP clock device
7292
* @adapter: back pointer to the adapter
93+
* @base_incval: base increment value of the PTP clock
94+
* @max_adj: maximum adjustment of the PTP clock
7395
* @cmd: HW specific command masks
7496
* @dev_clk_regs: the set of registers to access the device clock
7597
* @caps: PTP capabilities negotiated with the Control Plane
7698
* @get_dev_clk_time_access: access type for getting the device clock time
99+
* @set_dev_clk_time_access: access type for setting the device clock time
100+
* @adj_dev_clk_time_access: access type for the adjusting the device clock
77101
* @rsv: reserved bits
78102
* @secondary_mbx: parameters for using dedicated PTP mailbox
79103
* @read_dev_clk_lock: spinlock protecting access to the device clock read
@@ -83,11 +107,15 @@ struct idpf_ptp {
83107
struct ptp_clock_info info;
84108
struct ptp_clock *clock;
85109
struct idpf_adapter *adapter;
110+
u64 base_incval;
111+
u64 max_adj;
86112
struct idpf_ptp_cmd cmd;
87113
struct idpf_ptp_dev_clk_regs dev_clk_regs;
88114
u32 caps;
89115
enum idpf_ptp_access get_dev_clk_time_access:2;
90-
u32 rsv:30;
116+
enum idpf_ptp_access set_dev_clk_time_access:2;
117+
enum idpf_ptp_access adj_dev_clk_time_access:2;
118+
u32 rsv:10;
91119
struct idpf_ptp_secondary_mbx secondary_mbx;
92120
spinlock_t read_dev_clk_lock;
93121
};
@@ -123,6 +151,9 @@ int idpf_ptp_get_caps(struct idpf_adapter *adapter);
123151
void idpf_ptp_get_features_access(const struct idpf_adapter *adapter);
124152
int idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,
125153
struct idpf_ptp_dev_timers *dev_clk_time);
154+
int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter, u64 time);
155+
int idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter, u64 incval);
156+
int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter, s64 delta);
126157
#else /* CONFIG_PTP_1588_CLOCK */
127158
static inline int idpf_ptp_init(struct idpf_adapter *adapter)
128159
{
@@ -146,5 +177,23 @@ idpf_ptp_get_dev_clk_time(struct idpf_adapter *adapter,
146177
return -EOPNOTSUPP;
147178
}
148179

180+
static inline int idpf_ptp_set_dev_clk_time(struct idpf_adapter *adapter,
181+
u64 time)
182+
{
183+
return -EOPNOTSUPP;
184+
}
185+
186+
static inline int idpf_ptp_adj_dev_clk_fine(struct idpf_adapter *adapter,
187+
u64 incval)
188+
{
189+
return -EOPNOTSUPP;
190+
}
191+
192+
static inline int idpf_ptp_adj_dev_clk_time(struct idpf_adapter *adapter,
193+
s64 delta)
194+
{
195+
return -EOPNOTSUPP;
196+
}
197+
149198
#endif /* CONFIG_PTP_1588_CLOCK */
150199
#endif /* _IDPF_PTP_H */

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ static bool idpf_ptp_is_mb_msg(u32 op)
166166
switch (op) {
167167
case VIRTCHNL2_OP_PTP_GET_DEV_CLK_TIME:
168168
case VIRTCHNL2_OP_PTP_GET_CROSS_TIME:
169+
case VIRTCHNL2_OP_PTP_SET_DEV_CLK_TIME:
170+
case VIRTCHNL2_OP_PTP_ADJ_DEV_CLK_FINE:
171+
case VIRTCHNL2_OP_PTP_ADJ_DEV_CLK_TIME:
169172
return true;
170173
default:
171174
return false;

0 commit comments

Comments
 (0)