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 ×tamp_nsec);
44
45 ptp_read_system_postts(sts);
46
47 spin_unlock_irqrestore(&phc_info->lock, flags);
48
49 if (rc)
50 return rc;
51
52 *ts = ns_to_timespec64(timestamp_nsec);
53
54 return 0;
55 }
56
ena_phc_settime64(struct ptp_clock_info * clock_info,const struct timespec64 * ts)57 static int ena_phc_settime64(struct ptp_clock_info *clock_info,
58 const struct timespec64 *ts)
59 {
60 return -EOPNOTSUPP;
61 }
62
63 static struct ptp_clock_info ena_ptp_clock_info = {
64 .owner = THIS_MODULE,
65 .n_alarm = 0,
66 .n_ext_ts = 0,
67 .n_per_out = 0,
68 .pps = 0,
69 .adjtime = ena_phc_adjtime,
70 .adjfine = ena_phc_adjfine,
71 .gettimex64 = ena_phc_gettimex64,
72 .settime64 = ena_phc_settime64,
73 .enable = ena_phc_feature_enable,
74 };
75
76 /* Enable/Disable PHC by the kernel, affects on the next init flow */
ena_phc_enable(struct ena_adapter * adapter,bool enable)77 void ena_phc_enable(struct ena_adapter *adapter, bool enable)
78 {
79 struct ena_phc_info *phc_info = adapter->phc_info;
80
81 if (!phc_info) {
82 netdev_err(adapter->netdev, "phc_info is not allocated\n");
83 return;
84 }
85
86 phc_info->enabled = enable;
87 }
88
89 /* Check if PHC is enabled by the kernel */
ena_phc_is_enabled(struct ena_adapter * adapter)90 bool ena_phc_is_enabled(struct ena_adapter *adapter)
91 {
92 struct ena_phc_info *phc_info = adapter->phc_info;
93
94 return (phc_info && phc_info->enabled);
95 }
96
97 /* PHC is activated if ptp clock is registered in the kernel */
ena_phc_is_active(struct ena_adapter * adapter)98 bool ena_phc_is_active(struct ena_adapter *adapter)
99 {
100 struct ena_phc_info *phc_info = adapter->phc_info;
101
102 return (phc_info && phc_info->clock);
103 }
104
ena_phc_register(struct ena_adapter * adapter)105 static int ena_phc_register(struct ena_adapter *adapter)
106 {
107 struct pci_dev *pdev = adapter->pdev;
108 struct ptp_clock_info *clock_info;
109 struct ena_phc_info *phc_info;
110 int rc = 0;
111
112 phc_info = adapter->phc_info;
113 clock_info = &phc_info->clock_info;
114
115 /* PHC may already be registered in case of a reset */
116 if (ena_phc_is_active(adapter))
117 return 0;
118
119 phc_info->adapter = adapter;
120
121 spin_lock_init(&phc_info->lock);
122
123 /* Fill the ptp_clock_info struct and register PTP clock */
124 *clock_info = ena_ptp_clock_info;
125 snprintf(clock_info->name,
126 sizeof(clock_info->name),
127 "ena-ptp-%02x",
128 PCI_SLOT(pdev->devfn));
129
130 phc_info->clock = ptp_clock_register(clock_info, &pdev->dev);
131 if (IS_ERR(phc_info->clock)) {
132 rc = PTR_ERR(phc_info->clock);
133 netdev_err(adapter->netdev, "Failed registering ptp clock, error: %d\n",
134 rc);
135 phc_info->clock = NULL;
136 }
137
138 return rc;
139 }
140
ena_phc_unregister(struct ena_adapter * adapter)141 static void ena_phc_unregister(struct ena_adapter *adapter)
142 {
143 struct ena_phc_info *phc_info = adapter->phc_info;
144
145 /* During reset flow, PHC must stay registered
146 * to keep kernel's PHC index
147 */
148 if (ena_phc_is_active(adapter) &&
149 !test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags)) {
150 ptp_clock_unregister(phc_info->clock);
151 phc_info->clock = NULL;
152 }
153 }
154
ena_phc_alloc(struct ena_adapter * adapter)155 int ena_phc_alloc(struct ena_adapter *adapter)
156 {
157 /* Allocate driver specific PHC info */
158 adapter->phc_info = vzalloc(sizeof(*adapter->phc_info));
159 if (unlikely(!adapter->phc_info)) {
160 netdev_err(adapter->netdev, "Failed to alloc phc_info\n");
161 return -ENOMEM;
162 }
163
164 return 0;
165 }
166
ena_phc_free(struct ena_adapter * adapter)167 void ena_phc_free(struct ena_adapter *adapter)
168 {
169 if (adapter->phc_info) {
170 vfree(adapter->phc_info);
171 adapter->phc_info = NULL;
172 }
173 }
174
ena_phc_init(struct ena_adapter * adapter)175 int ena_phc_init(struct ena_adapter *adapter)
176 {
177 struct ena_com_dev *ena_dev = adapter->ena_dev;
178 struct net_device *netdev = adapter->netdev;
179 int rc = -EOPNOTSUPP;
180
181 /* Validate PHC feature is supported in the device */
182 if (!ena_com_phc_supported(ena_dev)) {
183 netdev_dbg(netdev, "PHC feature is not supported by the device\n");
184 goto err_ena_com_phc_init;
185 }
186
187 /* Validate PHC feature is enabled by the kernel */
188 if (!ena_phc_is_enabled(adapter)) {
189 netdev_dbg(netdev, "PHC feature is not enabled by the kernel\n");
190 goto err_ena_com_phc_init;
191 }
192
193 /* Initialize device specific PHC info */
194 rc = ena_com_phc_init(ena_dev);
195 if (unlikely(rc)) {
196 netdev_err(netdev, "Failed to init phc, error: %d\n", rc);
197 goto err_ena_com_phc_init;
198 }
199
200 /* Configure PHC feature in driver and device */
201 rc = ena_com_phc_config(ena_dev);
202 if (unlikely(rc)) {
203 netdev_err(netdev, "Failed to config phc, error: %d\n", rc);
204 goto err_ena_com_phc_config;
205 }
206
207 /* Register to PTP class driver */
208 rc = ena_phc_register(adapter);
209 if (unlikely(rc)) {
210 netdev_err(netdev, "Failed to register phc, error: %d\n", rc);
211 goto err_ena_com_phc_config;
212 }
213
214 return 0;
215
216 err_ena_com_phc_config:
217 ena_com_phc_destroy(ena_dev);
218 err_ena_com_phc_init:
219 ena_phc_enable(adapter, false);
220 ena_devlink_disable_phc_param(adapter->devlink);
221 return rc;
222 }
223
ena_phc_destroy(struct ena_adapter * adapter)224 void ena_phc_destroy(struct ena_adapter *adapter)
225 {
226 ena_phc_unregister(adapter);
227 ena_com_phc_destroy(adapter->ena_dev);
228 }
229
ena_phc_get_index(struct ena_adapter * adapter)230 int ena_phc_get_index(struct ena_adapter *adapter)
231 {
232 if (ena_phc_is_active(adapter))
233 return ptp_clock_index(adapter->phc_info->clock);
234
235 return -1;
236 }
237