1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (C) 2021, Intel Corporation. */
3 
4 #ifndef _ICE_PTP_H_
5 #define _ICE_PTP_H_
6 
7 #include <linux/ptp_clock_kernel.h>
8 #include <linux/kthread.h>
9 
10 #include "ice_ptp_hw.h"
11 
12 /* The ice hardware captures Tx hardware timestamps in the PHY. The timestamp
13  * is stored in a buffer of registers. Depending on the specific hardware,
14  * this buffer might be shared across multiple PHY ports.
15  *
16  * On transmit of a packet to be timestamped, software is responsible for
17  * selecting an open index. Hardware makes no attempt to lock or prevent
18  * re-use of an index for multiple packets.
19  *
20  * To handle this, timestamp indexes must be tracked by software to ensure
21  * that an index is not re-used for multiple transmitted packets. The
22  * structures and functions declared in this file track the available Tx
23  * register indexes, as well as provide storage for the SKB pointers.
24  *
25  * To allow multiple ports to access the shared register block independently,
26  * the blocks are split up so that indexes are assigned to each port based on
27  * hardware logical port number.
28  */
29 
30 /**
31  * struct ice_tx_tstamp - Tracking for a single Tx timestamp
32  * @skb: pointer to the SKB for this timestamp request
33  * @start: jiffies when the timestamp was first requested
34  *
35  * This structure tracks a single timestamp request. The SKB pointer is
36  * provided when initiating a request. The start time is used to ensure that
37  * we discard old requests that were not fulfilled within a 2 second time
38  * window.
39  */
40 struct ice_tx_tstamp {
41 	struct sk_buff *skb;
42 	unsigned long start;
43 };
44 
45 /**
46  * struct ice_ptp_tx - Tracking structure for all Tx timestamp requests on a port
47  * @work: work function to handle processing of Tx timestamps
48  * @lock: lock to prevent concurrent write to in_use bitmap
49  * @tstamps: array of len to store outstanding requests
50  * @in_use: bitmap of len to indicate which slots are in use
51  * @quad: which quad the timestamps are captured in
52  * @quad_offset: offset into timestamp block of the quad to get the real index
53  * @len: length of the tstamps and in_use fields.
54  * @init: if true, the tracker is initialized;
55  */
56 struct ice_ptp_tx {
57 	struct kthread_work work;
58 	spinlock_t lock; /* lock protecting in_use bitmap */
59 	struct ice_tx_tstamp *tstamps;
60 	unsigned long *in_use;
61 	u8 quad;
62 	u8 quad_offset;
63 	u8 len;
64 	u8 init;
65 };
66 
67 /* Quad and port information for initializing timestamp blocks */
68 #define INDEX_PER_QUAD			64
69 #define INDEX_PER_PORT			(INDEX_PER_QUAD / ICE_PORTS_PER_QUAD)
70 
71 /**
72  * struct ice_ptp_port - data used to initialize an external port for PTP
73  *
74  * This structure contains PTP data related to the external ports. Currently
75  * it is used for tracking the Tx timestamps of a port. In the future this
76  * structure will also hold information for the E822 port initialization
77  * logic.
78  *
79  * @tx: Tx timestamp tracking for this port
80  */
81 struct ice_ptp_port {
82 	struct ice_ptp_tx tx;
83 };
84 
85 /**
86  * struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK
87  * @port: data for the PHY port initialization procedure
88  * @work: delayed work function for periodic tasks
89  * @cached_phc_time: a cached copy of the PHC time for timestamp extension
90  * @kworker: kwork thread for handling periodic work
91  * @info: structure defining PTP hardware capabilities
92  * @clock: pointer to registered PTP clock device
93  * @tstamp_config: hardware timestamping configuration
94  */
95 struct ice_ptp {
96 	struct ice_ptp_port port;
97 	struct kthread_delayed_work work;
98 	u64 cached_phc_time;
99 	struct kthread_worker *kworker;
100 	struct ptp_clock_info info;
101 	struct ptp_clock *clock;
102 	struct hwtstamp_config tstamp_config;
103 };
104 
105 #define __ptp_port_to_ptp(p) \
106 	container_of((p), struct ice_ptp, port)
107 #define ptp_port_to_pf(p) \
108 	container_of(__ptp_port_to_ptp((p)), struct ice_pf, ptp)
109 
110 #define __ptp_info_to_ptp(i) \
111 	container_of((i), struct ice_ptp, info)
112 #define ptp_info_to_pf(i) \
113 	container_of(__ptp_info_to_ptp((i)), struct ice_pf, ptp)
114 
115 #define PTP_SHARED_CLK_IDX_VALID	BIT(31)
116 #define ICE_PTP_TS_VALID		BIT(0)
117 
118 #if IS_ENABLED(CONFIG_PTP_1588_CLOCK)
119 struct ice_pf;
120 int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr);
121 int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr);
122 int ice_get_ptp_clock_index(struct ice_pf *pf);
123 
124 s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb);
125 void ice_ptp_process_ts(struct ice_pf *pf);
126 
127 void
128 ice_ptp_rx_hwtstamp(struct ice_ring *rx_ring,
129 		    union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb);
130 void ice_ptp_init(struct ice_pf *pf);
131 void ice_ptp_release(struct ice_pf *pf);
132 #else /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */
133 static inline int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr)
134 {
135 	return -EOPNOTSUPP;
136 }
137 
138 static inline int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr)
139 {
140 	return -EOPNOTSUPP;
141 }
142 
143 static inline int ice_get_ptp_clock_index(struct ice_pf *pf)
144 {
145 	return -1;
146 }
147 
148 static inline
149 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb)
150 {
151 	return -1;
152 }
153 
154 static inline void ice_ptp_process_ts(struct ice_pf *pf) { }
155 static inline void
156 ice_ptp_rx_hwtstamp(struct ice_ring *rx_ring,
157 		    union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb) { }
158 static inline void ice_ptp_init(struct ice_pf *pf) { }
159 static inline void ice_ptp_release(struct ice_pf *pf) { }
160 #endif /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */
161 #endif /* _ICE_PTP_H_ */
162