2019-05-20 15:19:02 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
2011-04-22 18:03:08 +08:00
|
|
|
/*
|
|
|
|
* PTP 1588 clock support
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010 OMICRON electronics GmbH
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _PTP_CLOCK_KERNEL_H_
|
|
|
|
#define _PTP_CLOCK_KERNEL_H_
|
|
|
|
|
2012-09-22 15:02:03 +08:00
|
|
|
#include <linux/device.h>
|
2012-09-03 18:34:58 +08:00
|
|
|
#include <linux/pps_kernel.h>
|
2011-04-22 18:03:08 +08:00
|
|
|
#include <linux/ptp_clock.h>
|
2021-06-30 16:11:52 +08:00
|
|
|
#include <linux/timecounter.h>
|
2021-06-30 16:11:57 +08:00
|
|
|
#include <linux/skbuff.h>
|
2011-04-22 18:03:08 +08:00
|
|
|
|
2021-06-30 16:11:52 +08:00
|
|
|
#define PTP_CLOCK_NAME_LEN 32
|
2020-11-18 05:38:26 +08:00
|
|
|
/**
|
|
|
|
* struct ptp_clock_request - request PTP clock event
|
|
|
|
*
|
|
|
|
* @type: The type of the request.
|
|
|
|
* EXTTS: Configure external trigger timestamping
|
|
|
|
* PEROUT: Configure periodic output signal (e.g. PPS)
|
|
|
|
* PPS: trigger internal PPS event for input
|
|
|
|
* into kernel PPS subsystem
|
|
|
|
* @extts: describes configuration for external trigger timestamping.
|
|
|
|
* This is only valid when event == PTP_CLK_REQ_EXTTS.
|
|
|
|
* @perout: describes configuration for periodic output.
|
|
|
|
* This is only valid when event == PTP_CLK_REQ_PEROUT.
|
|
|
|
*/
|
2011-04-22 18:03:08 +08:00
|
|
|
|
|
|
|
struct ptp_clock_request {
|
|
|
|
enum {
|
|
|
|
PTP_CLK_REQ_EXTTS,
|
|
|
|
PTP_CLK_REQ_PEROUT,
|
|
|
|
PTP_CLK_REQ_PPS,
|
|
|
|
} type;
|
|
|
|
union {
|
|
|
|
struct ptp_extts_request extts;
|
|
|
|
struct ptp_perout_request perout;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2016-02-22 19:15:25 +08:00
|
|
|
struct system_device_crosststamp;
|
2018-11-09 18:14:44 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ptp_system_timestamp - system time corresponding to a PHC timestamp
|
2022-10-28 19:04:12 +08:00
|
|
|
* @pre_ts: system timestamp before capturing PHC
|
|
|
|
* @post_ts: system timestamp after capturing PHC
|
2018-11-09 18:14:44 +08:00
|
|
|
*/
|
|
|
|
struct ptp_system_timestamp {
|
|
|
|
struct timespec64 pre_ts;
|
|
|
|
struct timespec64 post_ts;
|
|
|
|
};
|
|
|
|
|
2011-04-22 18:03:08 +08:00
|
|
|
/**
|
2020-05-02 11:35:36 +08:00
|
|
|
* struct ptp_clock_info - describes a PTP hardware clock
|
2011-04-22 18:03:08 +08:00
|
|
|
*
|
|
|
|
* @owner: The clock driver should set to THIS_MODULE.
|
2012-09-22 15:02:04 +08:00
|
|
|
* @name: A short "friendly name" to identify the clock and to
|
|
|
|
* help distinguish PHY based devices from MAC based ones.
|
|
|
|
* The string is not meant to be a unique id.
|
2011-04-22 18:03:08 +08:00
|
|
|
* @max_adj: The maximum possible frequency adjustment, in parts per billon.
|
|
|
|
* @n_alarm: The number of programmable alarms.
|
|
|
|
* @n_ext_ts: The number of external time stamp channels.
|
|
|
|
* @n_per_out: The number of programmable periodic signals.
|
2014-03-21 05:21:52 +08:00
|
|
|
* @n_pins: The number of programmable pins.
|
2011-04-22 18:03:08 +08:00
|
|
|
* @pps: Indicates whether the clock supports a PPS callback.
|
2014-03-21 05:21:52 +08:00
|
|
|
* @pin_config: Array of length 'n_pins'. If the number of
|
|
|
|
* programmable pins is nonzero, then drivers must
|
|
|
|
* allocate and initialize this array.
|
2011-04-22 18:03:08 +08:00
|
|
|
*
|
|
|
|
* clock operations
|
|
|
|
*
|
2016-11-09 05:49:16 +08:00
|
|
|
* @adjfine: Adjusts the frequency of the hardware clock.
|
|
|
|
* parameter scaled_ppm: Desired frequency offset from
|
|
|
|
* nominal frequency in parts per million, but with a
|
|
|
|
* 16 bit binary fractional field.
|
|
|
|
*
|
2023-06-13 05:14:52 +08:00
|
|
|
* @adjphase: Indicates that the PHC should use an internal servo
|
|
|
|
* algorithm to correct the provided phase offset.
|
|
|
|
* parameter delta: PHC servo phase adjustment target
|
|
|
|
* in nanoseconds.
|
2020-05-02 11:35:36 +08:00
|
|
|
*
|
2023-06-13 05:14:56 +08:00
|
|
|
* @getmaxphase: Advertises maximum offset that can be provided
|
|
|
|
* to the hardware clock's phase control functionality
|
|
|
|
* through adjphase.
|
|
|
|
*
|
2011-04-22 18:03:08 +08:00
|
|
|
* @adjtime: Shifts the time of the hardware clock.
|
|
|
|
* parameter delta: Desired change in nanoseconds.
|
|
|
|
*
|
2015-03-30 05:11:51 +08:00
|
|
|
* @gettime64: Reads the current time from the hardware clock.
|
2018-11-09 18:14:45 +08:00
|
|
|
* This method is deprecated. New drivers should implement
|
|
|
|
* the @gettimex64 method instead.
|
2015-03-30 05:11:51 +08:00
|
|
|
* parameter ts: Holds the result.
|
|
|
|
*
|
2018-11-09 18:14:44 +08:00
|
|
|
* @gettimex64: Reads the current time from the hardware clock and optionally
|
|
|
|
* also the system clock.
|
|
|
|
* parameter ts: Holds the PHC timestamp.
|
|
|
|
* parameter sts: If not NULL, it holds a pair of timestamps from
|
|
|
|
* the system clock. The first reading is made right before
|
|
|
|
* reading the lowest bits of the PHC timestamp and the second
|
|
|
|
* reading immediately follows that.
|
|
|
|
*
|
2016-02-22 19:15:25 +08:00
|
|
|
* @getcrosststamp: Reads the current time from the hardware clock and
|
|
|
|
* system clock simultaneously.
|
|
|
|
* parameter cts: Contains timestamp (device,system) pair,
|
|
|
|
* where system time is realtime and monotonic.
|
|
|
|
*
|
2015-03-30 05:11:51 +08:00
|
|
|
* @settime64: Set the current time on the hardware clock.
|
|
|
|
* parameter ts: Time value to set.
|
|
|
|
*
|
2022-05-07 04:01:37 +08:00
|
|
|
* @getcycles64: Reads the current free running cycle counter from the hardware
|
|
|
|
* clock.
|
|
|
|
* If @getcycles64 and @getcyclesx64 are not supported, then
|
|
|
|
* @gettime64 or @gettimex64 will be used as default
|
|
|
|
* implementation.
|
|
|
|
* parameter ts: Holds the result.
|
|
|
|
*
|
|
|
|
* @getcyclesx64: Reads the current free running cycle counter from the
|
|
|
|
* hardware clock and optionally also the system clock.
|
|
|
|
* If @getcycles64 and @getcyclesx64 are not supported, then
|
|
|
|
* @gettimex64 will be used as default implementation if
|
|
|
|
* available.
|
|
|
|
* parameter ts: Holds the PHC timestamp.
|
|
|
|
* parameter sts: If not NULL, it holds a pair of timestamps
|
|
|
|
* from the system clock. The first reading is made right before
|
|
|
|
* reading the lowest bits of the PHC timestamp and the second
|
|
|
|
* reading immediately follows that.
|
|
|
|
*
|
|
|
|
* @getcrosscycles: Reads the current free running cycle counter from the
|
|
|
|
* hardware clock and system clock simultaneously.
|
|
|
|
* If @getcycles64 and @getcyclesx64 are not supported, then
|
|
|
|
* @getcrosststamp will be used as default implementation if
|
|
|
|
* available.
|
|
|
|
* parameter cts: Contains timestamp (device,system) pair,
|
|
|
|
* where system time is realtime and monotonic.
|
|
|
|
*
|
2011-04-22 18:03:08 +08:00
|
|
|
* @enable: Request driver to enable or disable an ancillary feature.
|
|
|
|
* parameter request: Desired resource to enable or disable.
|
|
|
|
* parameter on: Caller passes one to enable or zero to disable.
|
|
|
|
*
|
2014-03-21 05:21:52 +08:00
|
|
|
* @verify: Confirm that a pin can perform a given function. The PTP
|
|
|
|
* Hardware Clock subsystem maintains the 'pin_config'
|
|
|
|
* array on behalf of the drivers, but the PHC subsystem
|
|
|
|
* assumes that every pin can perform every function. This
|
|
|
|
* hook gives drivers a way of telling the core about
|
|
|
|
* limitations on specific pins. This function must return
|
|
|
|
* zero if the function can be assigned to this pin, and
|
|
|
|
* nonzero otherwise.
|
|
|
|
* parameter pin: index of the pin in question.
|
|
|
|
* parameter func: the desired function to use.
|
|
|
|
* parameter chan: the function channel index to use.
|
|
|
|
*
|
2020-05-12 05:02:15 +08:00
|
|
|
* @do_aux_work: Request driver to perform auxiliary (periodic) operations
|
|
|
|
* Driver should return delay of the next auxiliary work
|
|
|
|
* scheduling time (>=0) or negative value in case further
|
|
|
|
* scheduling is not required.
|
ptp: introduce ptp auxiliary worker
Many PTP drivers required to perform some asynchronous or periodic work,
like periodically handling PHC counter overflow or handle delayed timestamp
for RX/TX network packets. In most of the cases, such work is implemented
using workqueues. Unfortunately, Kernel workqueues might introduce
significant delay in work scheduling under high system load and on -RT,
which could cause misbehavior of PTP drivers due to internal counter
overflow, for example, and there is no way to tune its execution policy and
priority manuallly.
Hence, The kthread_worker can be used insted of workqueues, as it create
separte named kthread for each worker and its its execution policy and
priority can be configured using chrt tool.
This prblem was reported for two drivers TI CPSW CPTS and dp83640, so
instead of modifying each of these driver it was proposed to add PTP
auxiliary worker to the PHC subsystem.
The patch adds PTP auxiliary worker in PHC subsystem using kthread_worker
and kthread_delayed_work and introduces two new PHC subsystem APIs:
- long (*do_aux_work)(struct ptp_clock_info *ptp) callback in
ptp_clock_info structure, which driver should assign if it require to
perform asynchronous or periodic work. Driver should return the delay of
the PTP next auxiliary work scheduling time (>=0) or negative value in case
further scheduling is not required.
- int ptp_schedule_worker(struct ptp_clock *ptp, unsigned long delay) which
allows schedule PTP auxiliary work.
The name of kthread_worker thread corresponds PTP PHC device name "ptp%d".
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-07-29 06:30:02 +08:00
|
|
|
*
|
2011-04-22 18:03:08 +08:00
|
|
|
* Drivers should embed their ptp_clock_info within a private
|
|
|
|
* structure, obtaining a reference to it using container_of().
|
|
|
|
*
|
|
|
|
* The callbacks must all return zero on success, non-zero otherwise.
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct ptp_clock_info {
|
|
|
|
struct module *owner;
|
2021-06-30 16:11:52 +08:00
|
|
|
char name[PTP_CLOCK_NAME_LEN];
|
2011-04-22 18:03:08 +08:00
|
|
|
s32 max_adj;
|
|
|
|
int n_alarm;
|
|
|
|
int n_ext_ts;
|
|
|
|
int n_per_out;
|
2014-03-21 05:21:52 +08:00
|
|
|
int n_pins;
|
2011-04-22 18:03:08 +08:00
|
|
|
int pps;
|
2014-03-21 05:21:52 +08:00
|
|
|
struct ptp_pin_desc *pin_config;
|
2016-11-09 05:49:16 +08:00
|
|
|
int (*adjfine)(struct ptp_clock_info *ptp, long scaled_ppm);
|
2020-05-02 11:35:36 +08:00
|
|
|
int (*adjphase)(struct ptp_clock_info *ptp, s32 phase);
|
2023-06-13 05:14:56 +08:00
|
|
|
s32 (*getmaxphase)(struct ptp_clock_info *ptp);
|
2011-04-22 18:03:08 +08:00
|
|
|
int (*adjtime)(struct ptp_clock_info *ptp, s64 delta);
|
2015-03-30 05:11:51 +08:00
|
|
|
int (*gettime64)(struct ptp_clock_info *ptp, struct timespec64 *ts);
|
2018-11-09 18:14:44 +08:00
|
|
|
int (*gettimex64)(struct ptp_clock_info *ptp, struct timespec64 *ts,
|
|
|
|
struct ptp_system_timestamp *sts);
|
2016-02-22 19:15:25 +08:00
|
|
|
int (*getcrosststamp)(struct ptp_clock_info *ptp,
|
|
|
|
struct system_device_crosststamp *cts);
|
2015-03-30 05:11:51 +08:00
|
|
|
int (*settime64)(struct ptp_clock_info *p, const struct timespec64 *ts);
|
2022-05-07 04:01:37 +08:00
|
|
|
int (*getcycles64)(struct ptp_clock_info *ptp, struct timespec64 *ts);
|
|
|
|
int (*getcyclesx64)(struct ptp_clock_info *ptp, struct timespec64 *ts,
|
|
|
|
struct ptp_system_timestamp *sts);
|
|
|
|
int (*getcrosscycles)(struct ptp_clock_info *ptp,
|
|
|
|
struct system_device_crosststamp *cts);
|
2011-04-22 18:03:08 +08:00
|
|
|
int (*enable)(struct ptp_clock_info *ptp,
|
|
|
|
struct ptp_clock_request *request, int on);
|
2014-03-21 05:21:52 +08:00
|
|
|
int (*verify)(struct ptp_clock_info *ptp, unsigned int pin,
|
|
|
|
enum ptp_pin_function func, unsigned int chan);
|
ptp: introduce ptp auxiliary worker
Many PTP drivers required to perform some asynchronous or periodic work,
like periodically handling PHC counter overflow or handle delayed timestamp
for RX/TX network packets. In most of the cases, such work is implemented
using workqueues. Unfortunately, Kernel workqueues might introduce
significant delay in work scheduling under high system load and on -RT,
which could cause misbehavior of PTP drivers due to internal counter
overflow, for example, and there is no way to tune its execution policy and
priority manuallly.
Hence, The kthread_worker can be used insted of workqueues, as it create
separte named kthread for each worker and its its execution policy and
priority can be configured using chrt tool.
This prblem was reported for two drivers TI CPSW CPTS and dp83640, so
instead of modifying each of these driver it was proposed to add PTP
auxiliary worker to the PHC subsystem.
The patch adds PTP auxiliary worker in PHC subsystem using kthread_worker
and kthread_delayed_work and introduces two new PHC subsystem APIs:
- long (*do_aux_work)(struct ptp_clock_info *ptp) callback in
ptp_clock_info structure, which driver should assign if it require to
perform asynchronous or periodic work. Driver should return the delay of
the PTP next auxiliary work scheduling time (>=0) or negative value in case
further scheduling is not required.
- int ptp_schedule_worker(struct ptp_clock *ptp, unsigned long delay) which
allows schedule PTP auxiliary work.
The name of kthread_worker thread corresponds PTP PHC device name "ptp%d".
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-07-29 06:30:02 +08:00
|
|
|
long (*do_aux_work)(struct ptp_clock_info *ptp);
|
2011-04-22 18:03:08 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct ptp_clock;
|
|
|
|
|
|
|
|
enum ptp_clock_events {
|
|
|
|
PTP_CLOCK_ALARM,
|
|
|
|
PTP_CLOCK_EXTTS,
|
|
|
|
PTP_CLOCK_PPS,
|
2012-09-03 18:34:58 +08:00
|
|
|
PTP_CLOCK_PPSUSR,
|
2011-04-22 18:03:08 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct ptp_clock_event - decribes a PTP hardware clock event
|
|
|
|
*
|
|
|
|
* @type: One of the ptp_clock_events enumeration values.
|
|
|
|
* @index: Identifies the source of the event.
|
2012-09-03 18:34:58 +08:00
|
|
|
* @timestamp: When the event occurred (%PTP_CLOCK_EXTTS only).
|
|
|
|
* @pps_times: When the event occurred (%PTP_CLOCK_PPSUSR only).
|
2011-04-22 18:03:08 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
struct ptp_clock_event {
|
|
|
|
int type;
|
|
|
|
int index;
|
2012-09-03 18:34:58 +08:00
|
|
|
union {
|
|
|
|
u64 timestamp;
|
|
|
|
struct pps_event_time pps_times;
|
|
|
|
};
|
2011-04-22 18:03:08 +08:00
|
|
|
};
|
|
|
|
|
2021-05-10 23:34:32 +08:00
|
|
|
/**
|
|
|
|
* scaled_ppm_to_ppb() - convert scaled ppm to ppb
|
|
|
|
*
|
|
|
|
* @ppm: Parts per million, but with a 16 bit binary fractional field
|
|
|
|
*/
|
2021-06-19 10:47:02 +08:00
|
|
|
static inline long scaled_ppm_to_ppb(long ppm)
|
2021-05-10 23:34:32 +08:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* The 'freq' field in the 'struct timex' is in parts per
|
|
|
|
* million, but with a 16 bit binary fractional field.
|
|
|
|
*
|
|
|
|
* We want to calculate
|
|
|
|
*
|
|
|
|
* ppb = scaled_ppm * 1000 / 2^16
|
|
|
|
*
|
|
|
|
* which simplifies to
|
|
|
|
*
|
|
|
|
* ppb = scaled_ppm * 125 / 2^13
|
|
|
|
*/
|
|
|
|
s64 ppb = 1 + ppm;
|
|
|
|
|
|
|
|
ppb *= 125;
|
|
|
|
ppb >>= 13;
|
2021-06-19 10:47:02 +08:00
|
|
|
return (long)ppb;
|
2021-05-10 23:34:32 +08:00
|
|
|
}
|
|
|
|
|
2022-10-28 19:04:13 +08:00
|
|
|
/**
|
|
|
|
* diff_by_scaled_ppm - Calculate difference using scaled ppm
|
|
|
|
* @base: the base increment value to adjust
|
|
|
|
* @scaled_ppm: scaled parts per million to adjust by
|
|
|
|
* @diff: on return, the absolute value of calculated diff
|
|
|
|
*
|
|
|
|
* Calculate the difference to adjust the base increment using scaled parts
|
|
|
|
* per million.
|
|
|
|
*
|
|
|
|
* Use mul_u64_u64_div_u64 to perform the difference calculation in avoid
|
|
|
|
* possible overflow.
|
|
|
|
*
|
|
|
|
* Returns: true if scaled_ppm is negative, false otherwise
|
|
|
|
*/
|
|
|
|
static inline bool diff_by_scaled_ppm(u64 base, long scaled_ppm, u64 *diff)
|
|
|
|
{
|
|
|
|
bool negative = false;
|
|
|
|
|
|
|
|
if (scaled_ppm < 0) {
|
|
|
|
negative = true;
|
|
|
|
scaled_ppm = -scaled_ppm;
|
|
|
|
}
|
|
|
|
|
|
|
|
*diff = mul_u64_u64_div_u64(base, (u64)scaled_ppm, 1000000ULL << 16);
|
|
|
|
|
|
|
|
return negative;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* adjust_by_scaled_ppm - Adjust a base increment by scaled parts per million
|
|
|
|
* @base: the base increment value to adjust
|
|
|
|
* @scaled_ppm: scaled parts per million frequency adjustment
|
|
|
|
*
|
|
|
|
* Helper function which calculates a new increment value based on the
|
|
|
|
* requested scaled parts per million adjustment.
|
|
|
|
*/
|
|
|
|
static inline u64 adjust_by_scaled_ppm(u64 base, long scaled_ppm)
|
|
|
|
{
|
|
|
|
u64 diff;
|
|
|
|
|
|
|
|
if (diff_by_scaled_ppm(base, scaled_ppm, &diff))
|
|
|
|
return base - diff;
|
|
|
|
|
|
|
|
return base + diff;
|
|
|
|
}
|
|
|
|
|
ethernet: fix PTP_1588_CLOCK dependencies
The 'imply' keyword does not do what most people think it does, it only
politely asks Kconfig to turn on another symbol, but does not prevent
it from being disabled manually or built as a loadable module when the
user is built-in. In the ICE driver, the latter now causes a link failure:
aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_eth_ioctl':
ice_main.c:(.text+0x13b0): undefined reference to `ice_ptp_get_ts_config'
ice_main.c:(.text+0x13b0): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_get_ts_config'
aarch64-linux-ld: ice_main.c:(.text+0x13bc): undefined reference to `ice_ptp_set_ts_config'
ice_main.c:(.text+0x13bc): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_set_ts_config'
aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_prepare_for_reset':
ice_main.c:(.text+0x31fc): undefined reference to `ice_ptp_release'
ice_main.c:(.text+0x31fc): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_release'
aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_rebuild':
This is a recurring problem in many drivers, and we have discussed
it several times befores, without reaching a consensus. I'm providing
a link to the previous email thread for reference, which discusses
some related problems.
To solve the dependency issue better than the 'imply' keyword, introduce a
separate Kconfig symbol "CONFIG_PTP_1588_CLOCK_OPTIONAL" that any driver
can depend on if it is able to use PTP support when available, but works
fine without it. Whenever CONFIG_PTP_1588_CLOCK=m, those drivers are
then prevented from being built-in, the same way as with a 'depends on
PTP_1588_CLOCK || !PTP_1588_CLOCK' dependency that does the same trick,
but that can be rather confusing when you first see it.
Since this should cover the dependencies correctly, the IS_REACHABLE()
hack in the header is no longer needed now, and can be turned back
into a normal IS_ENABLED() check. Any driver that gets the dependency
wrong will now cause a link time failure rather than being unable to use
PTP support when that is in a loadable module.
However, the two recently added ptp_get_vclocks_index() and
ptp_convert_timestamp() interfaces are only called from builtin code with
ethtool and socket timestamps, so keep the current behavior by stubbing
those out completely when PTP is in a loadable module. This should be
addressed properly in a follow-up.
As Richard suggested, we may want to actually turn PTP support into a
'bool' option later on, preventing it from being a loadable module
altogether, which would be one way to solve the problem with the ethtool
interface.
Fixes: 06c16d89d2cb ("ice: register 1588 PTP clock device object for E810 devices")
Link: https://lore.kernel.org/netdev/20210804121318.337276-1-arnd@kernel.org/
Link: https://lore.kernel.org/netdev/CAK8P3a06enZOf=XyZ+zcAwBczv41UuCTz+=0FMf2gBz1_cOnZQ@mail.gmail.com/
Link: https://lore.kernel.org/netdev/CAK8P3a3=eOxE-K25754+fB_-i_0BZzf9a9RfPTX3ppSwu9WZXw@mail.gmail.com/
Link: https://lore.kernel.org/netdev/20210726084540.3282344-1-arnd@kernel.org/
Acked-by: Shannon Nelson <snelson@pensando.io>
Acked-by: Jacob Keller <jacob.e.keller@intel.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20210812183509.1362782-1-arnd@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-08-13 02:33:58 +08:00
|
|
|
#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
|
2016-11-11 13:10:07 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* ptp_clock_register() - register a PTP hardware clock driver
|
|
|
|
*
|
|
|
|
* @info: Structure describing the new clock.
|
|
|
|
* @parent: Pointer to the parent device of the new clock.
|
|
|
|
*
|
|
|
|
* Returns a valid pointer on success or PTR_ERR on failure. If PHC
|
|
|
|
* support is missing at the configuration level, this function
|
|
|
|
* returns NULL, and drivers are expected to gracefully handle that
|
|
|
|
* case separately.
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
|
|
|
|
struct device *parent);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ptp_clock_unregister() - unregister a PTP hardware clock driver
|
|
|
|
*
|
|
|
|
* @ptp: The clock to remove from service.
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern int ptp_clock_unregister(struct ptp_clock *ptp);
|
|
|
|
|
2011-04-22 18:03:08 +08:00
|
|
|
/**
|
|
|
|
* ptp_clock_event() - notify the PTP layer about an event
|
|
|
|
*
|
|
|
|
* @ptp: The clock obtained from ptp_clock_register().
|
|
|
|
* @event: Message structure describing the event.
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern void ptp_clock_event(struct ptp_clock *ptp,
|
|
|
|
struct ptp_clock_event *event);
|
|
|
|
|
2012-04-04 06:59:16 +08:00
|
|
|
/**
|
|
|
|
* ptp_clock_index() - obtain the device index of a PTP clock
|
|
|
|
*
|
|
|
|
* @ptp: The clock obtained from ptp_clock_register().
|
|
|
|
*/
|
|
|
|
|
|
|
|
extern int ptp_clock_index(struct ptp_clock *ptp);
|
|
|
|
|
2014-03-21 05:21:52 +08:00
|
|
|
/**
|
|
|
|
* ptp_find_pin() - obtain the pin index of a given auxiliary function
|
|
|
|
*
|
2020-03-29 22:55:10 +08:00
|
|
|
* The caller must hold ptp_clock::pincfg_mux. Drivers do not have
|
|
|
|
* access to that mutex as ptp_clock is an opaque type. However, the
|
|
|
|
* core code acquires the mutex before invoking the driver's
|
|
|
|
* ptp_clock_info::enable() callback, and so drivers may call this
|
|
|
|
* function from that context.
|
|
|
|
*
|
2014-03-21 05:21:52 +08:00
|
|
|
* @ptp: The clock obtained from ptp_clock_register().
|
|
|
|
* @func: One of the ptp_pin_function enumerated values.
|
|
|
|
* @chan: The particular functional channel to find.
|
|
|
|
* Return: Pin index in the range of zero to ptp_clock_caps.n_pins - 1,
|
|
|
|
* or -1 if the auxiliary function cannot be found.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int ptp_find_pin(struct ptp_clock *ptp,
|
|
|
|
enum ptp_pin_function func, unsigned int chan);
|
|
|
|
|
2020-03-29 22:55:10 +08:00
|
|
|
/**
|
|
|
|
* ptp_find_pin_unlocked() - wrapper for ptp_find_pin()
|
|
|
|
*
|
|
|
|
* This function acquires the ptp_clock::pincfg_mux mutex before
|
|
|
|
* invoking ptp_find_pin(). Instead of using this function, drivers
|
|
|
|
* should most likely call ptp_find_pin() directly from their
|
|
|
|
* ptp_clock_info::enable() method.
|
|
|
|
*
|
2022-10-28 19:04:12 +08:00
|
|
|
* @ptp: The clock obtained from ptp_clock_register().
|
|
|
|
* @func: One of the ptp_pin_function enumerated values.
|
|
|
|
* @chan: The particular functional channel to find.
|
|
|
|
* Return: Pin index in the range of zero to ptp_clock_caps.n_pins - 1,
|
|
|
|
* or -1 if the auxiliary function cannot be found.
|
2020-03-29 22:55:10 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
int ptp_find_pin_unlocked(struct ptp_clock *ptp,
|
|
|
|
enum ptp_pin_function func, unsigned int chan);
|
|
|
|
|
ptp: introduce ptp auxiliary worker
Many PTP drivers required to perform some asynchronous or periodic work,
like periodically handling PHC counter overflow or handle delayed timestamp
for RX/TX network packets. In most of the cases, such work is implemented
using workqueues. Unfortunately, Kernel workqueues might introduce
significant delay in work scheduling under high system load and on -RT,
which could cause misbehavior of PTP drivers due to internal counter
overflow, for example, and there is no way to tune its execution policy and
priority manuallly.
Hence, The kthread_worker can be used insted of workqueues, as it create
separte named kthread for each worker and its its execution policy and
priority can be configured using chrt tool.
This prblem was reported for two drivers TI CPSW CPTS and dp83640, so
instead of modifying each of these driver it was proposed to add PTP
auxiliary worker to the PHC subsystem.
The patch adds PTP auxiliary worker in PHC subsystem using kthread_worker
and kthread_delayed_work and introduces two new PHC subsystem APIs:
- long (*do_aux_work)(struct ptp_clock_info *ptp) callback in
ptp_clock_info structure, which driver should assign if it require to
perform asynchronous or periodic work. Driver should return the delay of
the PTP next auxiliary work scheduling time (>=0) or negative value in case
further scheduling is not required.
- int ptp_schedule_worker(struct ptp_clock *ptp, unsigned long delay) which
allows schedule PTP auxiliary work.
The name of kthread_worker thread corresponds PTP PHC device name "ptp%d".
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-07-29 06:30:02 +08:00
|
|
|
/**
|
|
|
|
* ptp_schedule_worker() - schedule ptp auxiliary work
|
|
|
|
*
|
|
|
|
* @ptp: The clock obtained from ptp_clock_register().
|
|
|
|
* @delay: number of jiffies to wait before queuing
|
|
|
|
* See kthread_queue_delayed_work() for more info.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int ptp_schedule_worker(struct ptp_clock *ptp, unsigned long delay);
|
|
|
|
|
2019-12-27 21:02:28 +08:00
|
|
|
/**
|
|
|
|
* ptp_cancel_worker_sync() - cancel ptp auxiliary clock
|
|
|
|
*
|
|
|
|
* @ptp: The clock obtained from ptp_clock_register().
|
|
|
|
*/
|
|
|
|
void ptp_cancel_worker_sync(struct ptp_clock *ptp);
|
|
|
|
|
ethernet: fix PTP_1588_CLOCK dependencies
The 'imply' keyword does not do what most people think it does, it only
politely asks Kconfig to turn on another symbol, but does not prevent
it from being disabled manually or built as a loadable module when the
user is built-in. In the ICE driver, the latter now causes a link failure:
aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_eth_ioctl':
ice_main.c:(.text+0x13b0): undefined reference to `ice_ptp_get_ts_config'
ice_main.c:(.text+0x13b0): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_get_ts_config'
aarch64-linux-ld: ice_main.c:(.text+0x13bc): undefined reference to `ice_ptp_set_ts_config'
ice_main.c:(.text+0x13bc): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_set_ts_config'
aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_prepare_for_reset':
ice_main.c:(.text+0x31fc): undefined reference to `ice_ptp_release'
ice_main.c:(.text+0x31fc): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_release'
aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_rebuild':
This is a recurring problem in many drivers, and we have discussed
it several times befores, without reaching a consensus. I'm providing
a link to the previous email thread for reference, which discusses
some related problems.
To solve the dependency issue better than the 'imply' keyword, introduce a
separate Kconfig symbol "CONFIG_PTP_1588_CLOCK_OPTIONAL" that any driver
can depend on if it is able to use PTP support when available, but works
fine without it. Whenever CONFIG_PTP_1588_CLOCK=m, those drivers are
then prevented from being built-in, the same way as with a 'depends on
PTP_1588_CLOCK || !PTP_1588_CLOCK' dependency that does the same trick,
but that can be rather confusing when you first see it.
Since this should cover the dependencies correctly, the IS_REACHABLE()
hack in the header is no longer needed now, and can be turned back
into a normal IS_ENABLED() check. Any driver that gets the dependency
wrong will now cause a link time failure rather than being unable to use
PTP support when that is in a loadable module.
However, the two recently added ptp_get_vclocks_index() and
ptp_convert_timestamp() interfaces are only called from builtin code with
ethtool and socket timestamps, so keep the current behavior by stubbing
those out completely when PTP is in a loadable module. This should be
addressed properly in a follow-up.
As Richard suggested, we may want to actually turn PTP support into a
'bool' option later on, preventing it from being a loadable module
altogether, which would be one way to solve the problem with the ethtool
interface.
Fixes: 06c16d89d2cb ("ice: register 1588 PTP clock device object for E810 devices")
Link: https://lore.kernel.org/netdev/20210804121318.337276-1-arnd@kernel.org/
Link: https://lore.kernel.org/netdev/CAK8P3a06enZOf=XyZ+zcAwBczv41UuCTz+=0FMf2gBz1_cOnZQ@mail.gmail.com/
Link: https://lore.kernel.org/netdev/CAK8P3a3=eOxE-K25754+fB_-i_0BZzf9a9RfPTX3ppSwu9WZXw@mail.gmail.com/
Link: https://lore.kernel.org/netdev/20210726084540.3282344-1-arnd@kernel.org/
Acked-by: Shannon Nelson <snelson@pensando.io>
Acked-by: Jacob Keller <jacob.e.keller@intel.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20210812183509.1362782-1-arnd@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-08-13 02:33:58 +08:00
|
|
|
#else
|
|
|
|
static inline struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
|
|
|
|
struct device *parent)
|
|
|
|
{ return NULL; }
|
|
|
|
static inline int ptp_clock_unregister(struct ptp_clock *ptp)
|
|
|
|
{ return 0; }
|
|
|
|
static inline void ptp_clock_event(struct ptp_clock *ptp,
|
|
|
|
struct ptp_clock_event *event)
|
|
|
|
{ }
|
|
|
|
static inline int ptp_clock_index(struct ptp_clock *ptp)
|
|
|
|
{ return -1; }
|
|
|
|
static inline int ptp_find_pin(struct ptp_clock *ptp,
|
|
|
|
enum ptp_pin_function func, unsigned int chan)
|
|
|
|
{ return -1; }
|
2022-04-29 15:19:53 +08:00
|
|
|
static inline int ptp_find_pin_unlocked(struct ptp_clock *ptp,
|
|
|
|
enum ptp_pin_function func,
|
|
|
|
unsigned int chan)
|
|
|
|
{ return -1; }
|
ethernet: fix PTP_1588_CLOCK dependencies
The 'imply' keyword does not do what most people think it does, it only
politely asks Kconfig to turn on another symbol, but does not prevent
it from being disabled manually or built as a loadable module when the
user is built-in. In the ICE driver, the latter now causes a link failure:
aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_eth_ioctl':
ice_main.c:(.text+0x13b0): undefined reference to `ice_ptp_get_ts_config'
ice_main.c:(.text+0x13b0): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_get_ts_config'
aarch64-linux-ld: ice_main.c:(.text+0x13bc): undefined reference to `ice_ptp_set_ts_config'
ice_main.c:(.text+0x13bc): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_set_ts_config'
aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_prepare_for_reset':
ice_main.c:(.text+0x31fc): undefined reference to `ice_ptp_release'
ice_main.c:(.text+0x31fc): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `ice_ptp_release'
aarch64-linux-ld: drivers/net/ethernet/intel/ice/ice_main.o: in function `ice_rebuild':
This is a recurring problem in many drivers, and we have discussed
it several times befores, without reaching a consensus. I'm providing
a link to the previous email thread for reference, which discusses
some related problems.
To solve the dependency issue better than the 'imply' keyword, introduce a
separate Kconfig symbol "CONFIG_PTP_1588_CLOCK_OPTIONAL" that any driver
can depend on if it is able to use PTP support when available, but works
fine without it. Whenever CONFIG_PTP_1588_CLOCK=m, those drivers are
then prevented from being built-in, the same way as with a 'depends on
PTP_1588_CLOCK || !PTP_1588_CLOCK' dependency that does the same trick,
but that can be rather confusing when you first see it.
Since this should cover the dependencies correctly, the IS_REACHABLE()
hack in the header is no longer needed now, and can be turned back
into a normal IS_ENABLED() check. Any driver that gets the dependency
wrong will now cause a link time failure rather than being unable to use
PTP support when that is in a loadable module.
However, the two recently added ptp_get_vclocks_index() and
ptp_convert_timestamp() interfaces are only called from builtin code with
ethtool and socket timestamps, so keep the current behavior by stubbing
those out completely when PTP is in a loadable module. This should be
addressed properly in a follow-up.
As Richard suggested, we may want to actually turn PTP support into a
'bool' option later on, preventing it from being a loadable module
altogether, which would be one way to solve the problem with the ethtool
interface.
Fixes: 06c16d89d2cb ("ice: register 1588 PTP clock device object for E810 devices")
Link: https://lore.kernel.org/netdev/20210804121318.337276-1-arnd@kernel.org/
Link: https://lore.kernel.org/netdev/CAK8P3a06enZOf=XyZ+zcAwBczv41UuCTz+=0FMf2gBz1_cOnZQ@mail.gmail.com/
Link: https://lore.kernel.org/netdev/CAK8P3a3=eOxE-K25754+fB_-i_0BZzf9a9RfPTX3ppSwu9WZXw@mail.gmail.com/
Link: https://lore.kernel.org/netdev/20210726084540.3282344-1-arnd@kernel.org/
Acked-by: Shannon Nelson <snelson@pensando.io>
Acked-by: Jacob Keller <jacob.e.keller@intel.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Link: https://lore.kernel.org/r/20210812183509.1362782-1-arnd@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-08-13 02:33:58 +08:00
|
|
|
static inline int ptp_schedule_worker(struct ptp_clock *ptp,
|
|
|
|
unsigned long delay)
|
|
|
|
{ return -EOPNOTSUPP; }
|
|
|
|
static inline void ptp_cancel_worker_sync(struct ptp_clock *ptp)
|
|
|
|
{ }
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if IS_BUILTIN(CONFIG_PTP_1588_CLOCK)
|
|
|
|
/*
|
|
|
|
* These are called by the network core, and don't work if PTP is in
|
|
|
|
* a loadable module.
|
|
|
|
*/
|
|
|
|
|
2021-06-30 16:11:55 +08:00
|
|
|
/**
|
|
|
|
* ptp_get_vclocks_index() - get all vclocks index on pclock, and
|
|
|
|
* caller is responsible to free memory
|
|
|
|
* of vclock_index
|
|
|
|
*
|
|
|
|
* @pclock_index: phc index of ptp pclock.
|
|
|
|
* @vclock_index: pointer to pointer of vclock index.
|
|
|
|
*
|
|
|
|
* return number of vclocks.
|
|
|
|
*/
|
|
|
|
int ptp_get_vclocks_index(int pclock_index, int **vclock_index);
|
|
|
|
|
2021-06-30 16:11:57 +08:00
|
|
|
/**
|
|
|
|
* ptp_convert_timestamp() - convert timestamp to a ptp vclock time
|
|
|
|
*
|
2022-05-07 04:01:39 +08:00
|
|
|
* @hwtstamp: timestamp
|
2021-06-30 16:11:57 +08:00
|
|
|
* @vclock_index: phc index of ptp vclock.
|
2022-01-05 18:33:26 +08:00
|
|
|
*
|
|
|
|
* Returns converted timestamp, or 0 on error.
|
2021-06-30 16:11:57 +08:00
|
|
|
*/
|
2022-05-07 04:01:39 +08:00
|
|
|
ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index);
|
2016-11-11 13:10:07 +08:00
|
|
|
#else
|
2021-06-30 16:11:55 +08:00
|
|
|
static inline int ptp_get_vclocks_index(int pclock_index, int **vclock_index)
|
|
|
|
{ return 0; }
|
2022-05-07 04:01:39 +08:00
|
|
|
static inline ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp,
|
2022-01-05 18:33:26 +08:00
|
|
|
int vclock_index)
|
|
|
|
{ return 0; }
|
ptp: introduce ptp auxiliary worker
Many PTP drivers required to perform some asynchronous or periodic work,
like periodically handling PHC counter overflow or handle delayed timestamp
for RX/TX network packets. In most of the cases, such work is implemented
using workqueues. Unfortunately, Kernel workqueues might introduce
significant delay in work scheduling under high system load and on -RT,
which could cause misbehavior of PTP drivers due to internal counter
overflow, for example, and there is no way to tune its execution policy and
priority manuallly.
Hence, The kthread_worker can be used insted of workqueues, as it create
separte named kthread for each worker and its its execution policy and
priority can be configured using chrt tool.
This prblem was reported for two drivers TI CPSW CPTS and dp83640, so
instead of modifying each of these driver it was proposed to add PTP
auxiliary worker to the PHC subsystem.
The patch adds PTP auxiliary worker in PHC subsystem using kthread_worker
and kthread_delayed_work and introduces two new PHC subsystem APIs:
- long (*do_aux_work)(struct ptp_clock_info *ptp) callback in
ptp_clock_info structure, which driver should assign if it require to
perform asynchronous or periodic work. Driver should return the delay of
the PTP next auxiliary work scheduling time (>=0) or negative value in case
further scheduling is not required.
- int ptp_schedule_worker(struct ptp_clock *ptp, unsigned long delay) which
allows schedule PTP auxiliary work.
The name of kthread_worker thread corresponds PTP PHC device name "ptp%d".
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-07-29 06:30:02 +08:00
|
|
|
|
2016-11-11 13:10:07 +08:00
|
|
|
#endif
|
|
|
|
|
2018-11-09 18:14:44 +08:00
|
|
|
static inline void ptp_read_system_prets(struct ptp_system_timestamp *sts)
|
|
|
|
{
|
|
|
|
if (sts)
|
|
|
|
ktime_get_real_ts64(&sts->pre_ts);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void ptp_read_system_postts(struct ptp_system_timestamp *sts)
|
|
|
|
{
|
|
|
|
if (sts)
|
|
|
|
ktime_get_real_ts64(&sts->post_ts);
|
|
|
|
}
|
|
|
|
|
2011-04-22 18:03:08 +08:00
|
|
|
#endif
|