xref: /linux/drivers/net/ethernet/amazon/ena/ena_phc.c (revision 8be4d31cb8aaeea27bde4b7ddb26e28a89062ebf)
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /*
3  * Copyright 2015-2022 Amazon.com, Inc. or its affiliates. All rights reserved.
4  */
5 
6 #include <linux/pci.h>
7 #include "ena_netdev.h"
8 #include "ena_phc.h"
9 #include "ena_devlink.h"
10 
ena_phc_adjtime(struct ptp_clock_info * clock_info,s64 delta)11 static int ena_phc_adjtime(struct ptp_clock_info *clock_info, s64 delta)
12 {
13 	return -EOPNOTSUPP;
14 }
15 
ena_phc_adjfine(struct ptp_clock_info * clock_info,long scaled_ppm)16 static int ena_phc_adjfine(struct ptp_clock_info *clock_info, long scaled_ppm)
17 {
18 	return -EOPNOTSUPP;
19 }
20 
ena_phc_feature_enable(struct ptp_clock_info * clock_info,struct ptp_clock_request * rq,int on)21 static int ena_phc_feature_enable(struct ptp_clock_info *clock_info,
22 				  struct ptp_clock_request *rq,
23 				  int on)
24 {
25 	return -EOPNOTSUPP;
26 }
27 
ena_phc_gettimex64(struct ptp_clock_info * clock_info,struct timespec64 * ts,struct ptp_system_timestamp * sts)28 static int ena_phc_gettimex64(struct ptp_clock_info *clock_info,
29 			      struct timespec64 *ts,
30 			      struct ptp_system_timestamp *sts)
31 {
32 	struct ena_phc_info *phc_info =
33 		container_of(clock_info, struct ena_phc_info, clock_info);
34 	unsigned long flags;
35 	u64 timestamp_nsec;
36 	int rc;
37 
38 	spin_lock_irqsave(&phc_info->lock, flags);
39 
40 	ptp_read_system_prets(sts);
41 
42 	rc = ena_com_phc_get_timestamp(phc_info->adapter->ena_dev,
43 				       &timestamp_nsec);
44 
45 	ptp_read_system_postts(sts);
46 
47 	spin_unlock_irqrestore(&phc_info->lock, flags);
48 
49 	*ts = ns_to_timespec64(timestamp_nsec);
50 
51 	return rc;
52 }
53 
ena_phc_settime64(struct ptp_clock_info * clock_info,const struct timespec64 * ts)54 static int ena_phc_settime64(struct ptp_clock_info *clock_info,
55 			     const struct timespec64 *ts)
56 {
57 	return -EOPNOTSUPP;
58 }
59 
60 static struct ptp_clock_info ena_ptp_clock_info = {
61 	.owner		= THIS_MODULE,
62 	.n_alarm	= 0,
63 	.n_ext_ts	= 0,
64 	.n_per_out	= 0,
65 	.pps		= 0,
66 	.adjtime	= ena_phc_adjtime,
67 	.adjfine	= ena_phc_adjfine,
68 	.gettimex64	= ena_phc_gettimex64,
69 	.settime64	= ena_phc_settime64,
70 	.enable		= ena_phc_feature_enable,
71 };
72 
73 /* Enable/Disable PHC by the kernel, affects on the next init flow */
ena_phc_enable(struct ena_adapter * adapter,bool enable)74 void ena_phc_enable(struct ena_adapter *adapter, bool enable)
75 {
76 	struct ena_phc_info *phc_info = adapter->phc_info;
77 
78 	if (!phc_info) {
79 		netdev_err(adapter->netdev, "phc_info is not allocated\n");
80 		return;
81 	}
82 
83 	phc_info->enabled = enable;
84 }
85 
86 /* Check if PHC is enabled by the kernel */
ena_phc_is_enabled(struct ena_adapter * adapter)87 bool ena_phc_is_enabled(struct ena_adapter *adapter)
88 {
89 	struct ena_phc_info *phc_info = adapter->phc_info;
90 
91 	return (phc_info && phc_info->enabled);
92 }
93 
94 /* PHC is activated if ptp clock is registered in the kernel */
ena_phc_is_active(struct ena_adapter * adapter)95 bool ena_phc_is_active(struct ena_adapter *adapter)
96 {
97 	struct ena_phc_info *phc_info = adapter->phc_info;
98 
99 	return (phc_info && phc_info->clock);
100 }
101 
ena_phc_register(struct ena_adapter * adapter)102 static int ena_phc_register(struct ena_adapter *adapter)
103 {
104 	struct pci_dev *pdev = adapter->pdev;
105 	struct ptp_clock_info *clock_info;
106 	struct ena_phc_info *phc_info;
107 	int rc = 0;
108 
109 	phc_info = adapter->phc_info;
110 	clock_info = &phc_info->clock_info;
111 
112 	/* PHC may already be registered in case of a reset */
113 	if (ena_phc_is_active(adapter))
114 		return 0;
115 
116 	phc_info->adapter = adapter;
117 
118 	spin_lock_init(&phc_info->lock);
119 
120 	/* Fill the ptp_clock_info struct and register PTP clock */
121 	*clock_info = ena_ptp_clock_info;
122 	snprintf(clock_info->name,
123 		 sizeof(clock_info->name),
124 		 "ena-ptp-%02x",
125 		 PCI_SLOT(pdev->devfn));
126 
127 	phc_info->clock = ptp_clock_register(clock_info, &pdev->dev);
128 	if (IS_ERR(phc_info->clock)) {
129 		rc = PTR_ERR(phc_info->clock);
130 		netdev_err(adapter->netdev, "Failed registering ptp clock, error: %d\n",
131 			   rc);
132 		phc_info->clock = NULL;
133 	}
134 
135 	return rc;
136 }
137 
ena_phc_unregister(struct ena_adapter * adapter)138 static void ena_phc_unregister(struct ena_adapter *adapter)
139 {
140 	struct ena_phc_info *phc_info = adapter->phc_info;
141 
142 	/* During reset flow, PHC must stay registered
143 	 * to keep kernel's PHC index
144 	 */
145 	if (ena_phc_is_active(adapter) &&
146 	    !test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags)) {
147 		ptp_clock_unregister(phc_info->clock);
148 		phc_info->clock = NULL;
149 	}
150 }
151 
ena_phc_alloc(struct ena_adapter * adapter)152 int ena_phc_alloc(struct ena_adapter *adapter)
153 {
154 	/* Allocate driver specific PHC info */
155 	adapter->phc_info = vzalloc(sizeof(*adapter->phc_info));
156 	if (unlikely(!adapter->phc_info)) {
157 		netdev_err(adapter->netdev, "Failed to alloc phc_info\n");
158 		return -ENOMEM;
159 	}
160 
161 	return 0;
162 }
163 
ena_phc_free(struct ena_adapter * adapter)164 void ena_phc_free(struct ena_adapter *adapter)
165 {
166 	if (adapter->phc_info) {
167 		vfree(adapter->phc_info);
168 		adapter->phc_info = NULL;
169 	}
170 }
171 
ena_phc_init(struct ena_adapter * adapter)172 int ena_phc_init(struct ena_adapter *adapter)
173 {
174 	struct ena_com_dev *ena_dev = adapter->ena_dev;
175 	struct net_device *netdev = adapter->netdev;
176 	int rc = -EOPNOTSUPP;
177 
178 	/* Validate PHC feature is supported in the device */
179 	if (!ena_com_phc_supported(ena_dev)) {
180 		netdev_dbg(netdev, "PHC feature is not supported by the device\n");
181 		goto err_ena_com_phc_init;
182 	}
183 
184 	/* Validate PHC feature is enabled by the kernel */
185 	if (!ena_phc_is_enabled(adapter)) {
186 		netdev_dbg(netdev, "PHC feature is not enabled by the kernel\n");
187 		goto err_ena_com_phc_init;
188 	}
189 
190 	/* Initialize device specific PHC info */
191 	rc = ena_com_phc_init(ena_dev);
192 	if (unlikely(rc)) {
193 		netdev_err(netdev, "Failed to init phc, error: %d\n", rc);
194 		goto err_ena_com_phc_init;
195 	}
196 
197 	/* Configure PHC feature in driver and device */
198 	rc = ena_com_phc_config(ena_dev);
199 	if (unlikely(rc)) {
200 		netdev_err(netdev, "Failed to config phc, error: %d\n", rc);
201 		goto err_ena_com_phc_config;
202 	}
203 
204 	/* Register to PTP class driver */
205 	rc = ena_phc_register(adapter);
206 	if (unlikely(rc)) {
207 		netdev_err(netdev, "Failed to register phc, error: %d\n", rc);
208 		goto err_ena_com_phc_config;
209 	}
210 
211 	return 0;
212 
213 err_ena_com_phc_config:
214 	ena_com_phc_destroy(ena_dev);
215 err_ena_com_phc_init:
216 	ena_phc_enable(adapter, false);
217 	ena_devlink_disable_phc_param(adapter->devlink);
218 	return rc;
219 }
220 
ena_phc_destroy(struct ena_adapter * adapter)221 void ena_phc_destroy(struct ena_adapter *adapter)
222 {
223 	ena_phc_unregister(adapter);
224 	ena_com_phc_destroy(adapter->ena_dev);
225 }
226 
ena_phc_get_index(struct ena_adapter * adapter)227 int ena_phc_get_index(struct ena_adapter *adapter)
228 {
229 	if (ena_phc_is_active(adapter))
230 		return ptp_clock_index(adapter->phc_info->clock);
231 
232 	return -1;
233 }
234