Skip to content

Commit 67569a7

Browse files
jacob-kelleranguy11
authored andcommitted
ice: report the PTP clock index in ethtool .get_ts_info
Now that the driver registers a PTP clock device that represents the clock hardware, it is important that the clock index is reported via the ethtool .get_ts_info callback. The underlying hardware resource is shared between multiple PF functions. Only one function owns the hardware resources associated with a timer, but multiple functions may be associated with it for the purposes of timestamping. To support this, the owning PF will store the clock index into the driver shared parameters buffer in firmware. Other PFs will look up the clock index by reading the driver shared parameter on demand when requested via the .get_ts_info ethtool function. In this way, all functions which are tied to the same timer are able to report the clock index. Userspace software such as ptp4l performs a look up on the netdev to determine the associated clock, and all commands to control or configure the clock will be handled through the controlling PF. Signed-off-by: Jacob Keller <[email protected]> Tested-by: Tony Brelinski <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent 06c16d8 commit 67569a7

File tree

3 files changed

+155
-1
lines changed

3 files changed

+155
-1
lines changed

drivers/net/ethernet/intel/ice/ice_ethtool.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3195,6 +3195,26 @@ ice_set_rxfh(struct net_device *netdev, const u32 *indir, const u8 *key,
31953195
return 0;
31963196
}
31973197

3198+
static int
3199+
ice_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
3200+
{
3201+
struct ice_pf *pf = ice_netdev_to_pf(dev);
3202+
3203+
/* only report timestamping if PTP is enabled */
3204+
if (!test_bit(ICE_FLAG_PTP, pf->flags))
3205+
return ethtool_op_get_ts_info(dev, info);
3206+
3207+
info->so_timestamping = SOF_TIMESTAMPING_SOFTWARE;
3208+
3209+
info->phc_index = ice_get_ptp_clock_index(pf);
3210+
3211+
info->tx_types = BIT(HWTSTAMP_TX_OFF);
3212+
3213+
info->rx_filters = BIT(HWTSTAMP_FILTER_NONE);
3214+
3215+
return 0;
3216+
}
3217+
31983218
/**
31993219
* ice_get_max_txq - return the maximum number of Tx queues for in a PF
32003220
* @pf: PF structure
@@ -3986,7 +4006,7 @@ static const struct ethtool_ops ice_ethtool_ops = {
39864006
.set_rxfh = ice_set_rxfh,
39874007
.get_channels = ice_get_channels,
39884008
.set_channels = ice_set_channels,
3989-
.get_ts_info = ethtool_op_get_ts_info,
4009+
.get_ts_info = ice_get_ts_info,
39904010
.get_per_queue_coalesce = ice_get_per_q_coalesce,
39914011
.set_per_queue_coalesce = ice_set_per_q_coalesce,
39924012
.get_fecparam = ice_get_fecparam,

drivers/net/ethernet/intel/ice/ice_ptp.c

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,131 @@
44
#include "ice.h"
55
#include "ice_lib.h"
66

7+
/**
8+
* ice_get_ptp_clock_index - Get the PTP clock index
9+
* @pf: the PF pointer
10+
*
11+
* Determine the clock index of the PTP clock associated with this device. If
12+
* this is the PF controlling the clock, just use the local access to the
13+
* clock device pointer.
14+
*
15+
* Otherwise, read from the driver shared parameters to determine the clock
16+
* index value.
17+
*
18+
* Returns: the index of the PTP clock associated with this device, or -1 if
19+
* there is no associated clock.
20+
*/
21+
int ice_get_ptp_clock_index(struct ice_pf *pf)
22+
{
23+
struct device *dev = ice_pf_to_dev(pf);
24+
enum ice_aqc_driver_params param_idx;
25+
struct ice_hw *hw = &pf->hw;
26+
u8 tmr_idx;
27+
u32 value;
28+
int err;
29+
30+
/* Use the ptp_clock structure if we're the main PF */
31+
if (pf->ptp.clock)
32+
return ptp_clock_index(pf->ptp.clock);
33+
34+
tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc;
35+
if (!tmr_idx)
36+
param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0;
37+
else
38+
param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1;
39+
40+
err = ice_aq_get_driver_param(hw, param_idx, &value, NULL);
41+
if (err) {
42+
dev_err(dev, "Failed to read PTP clock index parameter, err %d aq_err %s\n",
43+
err, ice_aq_str(hw->adminq.sq_last_status));
44+
return -1;
45+
}
46+
47+
/* The PTP clock index is an integer, and will be between 0 and
48+
* INT_MAX. The highest bit of the driver shared parameter is used to
49+
* indicate whether or not the currently stored clock index is valid.
50+
*/
51+
if (!(value & PTP_SHARED_CLK_IDX_VALID))
52+
return -1;
53+
54+
return value & ~PTP_SHARED_CLK_IDX_VALID;
55+
}
56+
57+
/**
58+
* ice_set_ptp_clock_index - Set the PTP clock index
59+
* @pf: the PF pointer
60+
*
61+
* Set the PTP clock index for this device into the shared driver parameters,
62+
* so that other PFs associated with this device can read it.
63+
*
64+
* If the PF is unable to store the clock index, it will log an error, but
65+
* will continue operating PTP.
66+
*/
67+
static void ice_set_ptp_clock_index(struct ice_pf *pf)
68+
{
69+
struct device *dev = ice_pf_to_dev(pf);
70+
enum ice_aqc_driver_params param_idx;
71+
struct ice_hw *hw = &pf->hw;
72+
u8 tmr_idx;
73+
u32 value;
74+
int err;
75+
76+
if (!pf->ptp.clock)
77+
return;
78+
79+
tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc;
80+
if (!tmr_idx)
81+
param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0;
82+
else
83+
param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1;
84+
85+
value = (u32)ptp_clock_index(pf->ptp.clock);
86+
if (value > INT_MAX) {
87+
dev_err(dev, "PTP Clock index is too large to store\n");
88+
return;
89+
}
90+
value |= PTP_SHARED_CLK_IDX_VALID;
91+
92+
err = ice_aq_set_driver_param(hw, param_idx, value, NULL);
93+
if (err) {
94+
dev_err(dev, "Failed to set PTP clock index parameter, err %d aq_err %s\n",
95+
err, ice_aq_str(hw->adminq.sq_last_status));
96+
}
97+
}
98+
99+
/**
100+
* ice_clear_ptp_clock_index - Clear the PTP clock index
101+
* @pf: the PF pointer
102+
*
103+
* Clear the PTP clock index for this device. Must be called when
104+
* unregistering the PTP clock, in order to ensure other PFs stop reporting
105+
* a clock object that no longer exists.
106+
*/
107+
static void ice_clear_ptp_clock_index(struct ice_pf *pf)
108+
{
109+
struct device *dev = ice_pf_to_dev(pf);
110+
enum ice_aqc_driver_params param_idx;
111+
struct ice_hw *hw = &pf->hw;
112+
u8 tmr_idx;
113+
int err;
114+
115+
/* Do not clear the index if we don't own the timer */
116+
if (!hw->func_caps.ts_func_info.src_tmr_owned)
117+
return;
118+
119+
tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc;
120+
if (!tmr_idx)
121+
param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR0;
122+
else
123+
param_idx = ICE_AQC_DRIVER_PARAM_CLK_IDX_TMR1;
124+
125+
err = ice_aq_set_driver_param(hw, param_idx, 0, NULL);
126+
if (err) {
127+
dev_dbg(dev, "Failed to clear PTP clock index parameter, err %d aq_err %s\n",
128+
err, ice_aq_str(hw->adminq.sq_last_status));
129+
}
130+
}
131+
7132
/**
8133
* ice_ptp_read_src_clk_reg - Read the source clock register
9134
* @pf: Board private structure
@@ -377,6 +502,9 @@ static int ice_ptp_init_owner(struct ice_pf *pf)
377502
if (err)
378503
goto err_clk;
379504

505+
/* Store the PTP clock index for other PFs */
506+
ice_set_ptp_clock_index(pf);
507+
380508
return 0;
381509

382510
err_clk:
@@ -431,6 +559,7 @@ void ice_ptp_release(struct ice_pf *pf)
431559
if (!pf->ptp.clock)
432560
return;
433561

562+
ice_clear_ptp_clock_index(pf);
434563
ptp_clock_unregister(pf->ptp.clock);
435564
pf->ptp.clock = NULL;
436565

drivers/net/ethernet/intel/ice/ice_ptp.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,14 @@ struct ice_ptp {
2727

2828
#if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
2929
struct ice_pf;
30+
int ice_get_ptp_clock_index(struct ice_pf *pf);
3031
void ice_ptp_init(struct ice_pf *pf);
3132
void ice_ptp_release(struct ice_pf *pf);
3233
#else /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */
34+
static inline int ice_get_ptp_clock_index(struct ice_pf *pf)
35+
{
36+
return -1;
37+
}
3338
static inline void ice_ptp_init(struct ice_pf *pf) { }
3439
static inline void ice_ptp_release(struct ice_pf *pf) { }
3540
#endif /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */

0 commit comments

Comments
 (0)