1*78ee8d1cSJulian Grajkowski /* SPDX-License-Identifier: BSD-3-Clause */
2*78ee8d1cSJulian Grajkowski /* Copyright(c) 2007-2022 Intel Corporation */
3*78ee8d1cSJulian Grajkowski #include "adf_accel_devices.h"
4*78ee8d1cSJulian Grajkowski #include "adf_common_drv.h"
5*78ee8d1cSJulian Grajkowski
6*78ee8d1cSJulian Grajkowski #include <linux/delay.h>
7*78ee8d1cSJulian Grajkowski
8*78ee8d1cSJulian Grajkowski #define MEASURE_CLOCK_RETRIES 10
9*78ee8d1cSJulian Grajkowski #define MEASURE_CLOCK_DELTA_THRESHOLD 100
10*78ee8d1cSJulian Grajkowski #define MEASURE_CLOCK_DELAY 10000
11*78ee8d1cSJulian Grajkowski #define ME_CLK_DIVIDER 16
12*78ee8d1cSJulian Grajkowski
13*78ee8d1cSJulian Grajkowski #define CLK_DBGFS_FILE "frequency"
14*78ee8d1cSJulian Grajkowski #define HB_SYSCTL_ERR(RC) \
15*78ee8d1cSJulian Grajkowski do { \
16*78ee8d1cSJulian Grajkowski if (!RC) { \
17*78ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev), \
18*78ee8d1cSJulian Grajkowski "Memory allocation failed in \
19*78ee8d1cSJulian Grajkowski adf_heartbeat_dbg_add\n"); \
20*78ee8d1cSJulian Grajkowski return ENOMEM; \
21*78ee8d1cSJulian Grajkowski } \
22*78ee8d1cSJulian Grajkowski } while (0)
23*78ee8d1cSJulian Grajkowski
24*78ee8d1cSJulian Grajkowski int
adf_clock_debugfs_add(struct adf_accel_dev * accel_dev)25*78ee8d1cSJulian Grajkowski adf_clock_debugfs_add(struct adf_accel_dev *accel_dev)
26*78ee8d1cSJulian Grajkowski {
27*78ee8d1cSJulian Grajkowski struct adf_hw_device_data *hw_data = accel_dev->hw_device;
28*78ee8d1cSJulian Grajkowski
29*78ee8d1cSJulian Grajkowski struct sysctl_ctx_list *qat_sysctl_ctx;
30*78ee8d1cSJulian Grajkowski struct sysctl_oid *qat_sysctl_tree;
31*78ee8d1cSJulian Grajkowski struct sysctl_oid *rc = 0;
32*78ee8d1cSJulian Grajkowski
33*78ee8d1cSJulian Grajkowski qat_sysctl_ctx =
34*78ee8d1cSJulian Grajkowski device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev);
35*78ee8d1cSJulian Grajkowski qat_sysctl_tree =
36*78ee8d1cSJulian Grajkowski device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev);
37*78ee8d1cSJulian Grajkowski
38*78ee8d1cSJulian Grajkowski rc = SYSCTL_ADD_UINT(qat_sysctl_ctx,
39*78ee8d1cSJulian Grajkowski SYSCTL_CHILDREN(qat_sysctl_tree),
40*78ee8d1cSJulian Grajkowski OID_AUTO,
41*78ee8d1cSJulian Grajkowski CLK_DBGFS_FILE,
42*78ee8d1cSJulian Grajkowski CTLFLAG_RD,
43*78ee8d1cSJulian Grajkowski &hw_data->clock_frequency,
44*78ee8d1cSJulian Grajkowski 0,
45*78ee8d1cSJulian Grajkowski "clock frequency");
46*78ee8d1cSJulian Grajkowski HB_SYSCTL_ERR(rc);
47*78ee8d1cSJulian Grajkowski return 0;
48*78ee8d1cSJulian Grajkowski }
49*78ee8d1cSJulian Grajkowski
50*78ee8d1cSJulian Grajkowski /**
51*78ee8d1cSJulian Grajkowski * adf_dev_measure_clock() -- Measure the CPM clock frequency
52*78ee8d1cSJulian Grajkowski * @accel_dev: Pointer to acceleration device.
53*78ee8d1cSJulian Grajkowski * @frequency: Pointer to returned frequency in Hz.
54*78ee8d1cSJulian Grajkowski *
55*78ee8d1cSJulian Grajkowski * Return: 0 on success, error code otherwise.
56*78ee8d1cSJulian Grajkowski */
57*78ee8d1cSJulian Grajkowski static int
measure_clock(struct adf_accel_dev * accel_dev,u32 * frequency)58*78ee8d1cSJulian Grajkowski measure_clock(struct adf_accel_dev *accel_dev, u32 *frequency)
59*78ee8d1cSJulian Grajkowski {
60*78ee8d1cSJulian Grajkowski struct timespec ts1;
61*78ee8d1cSJulian Grajkowski struct timespec ts2;
62*78ee8d1cSJulian Grajkowski struct timespec ts3;
63*78ee8d1cSJulian Grajkowski struct timespec ts4;
64*78ee8d1cSJulian Grajkowski struct timespec delta;
65*78ee8d1cSJulian Grajkowski u64 delta_us = 0;
66*78ee8d1cSJulian Grajkowski u64 timestamp1 = 0;
67*78ee8d1cSJulian Grajkowski u64 timestamp2 = 0;
68*78ee8d1cSJulian Grajkowski u64 temp = 0;
69*78ee8d1cSJulian Grajkowski int tries = 0;
70*78ee8d1cSJulian Grajkowski
71*78ee8d1cSJulian Grajkowski if (!accel_dev || !frequency)
72*78ee8d1cSJulian Grajkowski return EIO;
73*78ee8d1cSJulian Grajkowski do {
74*78ee8d1cSJulian Grajkowski nanotime(&ts1);
75*78ee8d1cSJulian Grajkowski if (adf_get_fw_timestamp(accel_dev, ×tamp1)) {
76*78ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
77*78ee8d1cSJulian Grajkowski "Failed to get fw timestamp\n");
78*78ee8d1cSJulian Grajkowski return EIO;
79*78ee8d1cSJulian Grajkowski }
80*78ee8d1cSJulian Grajkowski nanotime(&ts2);
81*78ee8d1cSJulian Grajkowski
82*78ee8d1cSJulian Grajkowski delta = timespec_sub(ts2, ts1);
83*78ee8d1cSJulian Grajkowski temp = delta.tv_nsec;
84*78ee8d1cSJulian Grajkowski do_div(temp, NSEC_PER_USEC);
85*78ee8d1cSJulian Grajkowski
86*78ee8d1cSJulian Grajkowski delta_us = delta.tv_sec * USEC_PER_SEC + temp;
87*78ee8d1cSJulian Grajkowski } while (delta_us > MEASURE_CLOCK_DELTA_THRESHOLD &&
88*78ee8d1cSJulian Grajkowski ++tries < MEASURE_CLOCK_RETRIES);
89*78ee8d1cSJulian Grajkowski
90*78ee8d1cSJulian Grajkowski if (tries >= MEASURE_CLOCK_RETRIES) {
91*78ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
92*78ee8d1cSJulian Grajkowski "Excessive clock measure delay\n");
93*78ee8d1cSJulian Grajkowski return EIO;
94*78ee8d1cSJulian Grajkowski }
95*78ee8d1cSJulian Grajkowski
96*78ee8d1cSJulian Grajkowski usleep_range(MEASURE_CLOCK_DELAY, MEASURE_CLOCK_DELAY * 2);
97*78ee8d1cSJulian Grajkowski tries = 0;
98*78ee8d1cSJulian Grajkowski do {
99*78ee8d1cSJulian Grajkowski nanotime(&ts3);
100*78ee8d1cSJulian Grajkowski if (adf_get_fw_timestamp(accel_dev, ×tamp2)) {
101*78ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
102*78ee8d1cSJulian Grajkowski "Failed to get fw timestamp\n");
103*78ee8d1cSJulian Grajkowski return EIO;
104*78ee8d1cSJulian Grajkowski }
105*78ee8d1cSJulian Grajkowski nanotime(&ts4);
106*78ee8d1cSJulian Grajkowski
107*78ee8d1cSJulian Grajkowski delta = timespec_sub(ts4, ts3);
108*78ee8d1cSJulian Grajkowski temp = delta.tv_nsec;
109*78ee8d1cSJulian Grajkowski do_div(temp, NSEC_PER_USEC);
110*78ee8d1cSJulian Grajkowski
111*78ee8d1cSJulian Grajkowski delta_us = delta.tv_sec * USEC_PER_SEC + temp;
112*78ee8d1cSJulian Grajkowski } while (delta_us > MEASURE_CLOCK_DELTA_THRESHOLD &&
113*78ee8d1cSJulian Grajkowski ++tries < MEASURE_CLOCK_RETRIES);
114*78ee8d1cSJulian Grajkowski
115*78ee8d1cSJulian Grajkowski if (tries >= MEASURE_CLOCK_RETRIES) {
116*78ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
117*78ee8d1cSJulian Grajkowski "Excessive clock measure delay\n");
118*78ee8d1cSJulian Grajkowski return EIO;
119*78ee8d1cSJulian Grajkowski }
120*78ee8d1cSJulian Grajkowski
121*78ee8d1cSJulian Grajkowski delta = timespec_sub(ts3, ts1);
122*78ee8d1cSJulian Grajkowski temp =
123*78ee8d1cSJulian Grajkowski delta.tv_sec * NSEC_PER_SEC + delta.tv_nsec + (NSEC_PER_USEC / 2);
124*78ee8d1cSJulian Grajkowski do_div(temp, NSEC_PER_USEC);
125*78ee8d1cSJulian Grajkowski delta_us = temp;
126*78ee8d1cSJulian Grajkowski /* Don't pretend that this gives better than 100KHz resolution */
127*78ee8d1cSJulian Grajkowski temp = (timestamp2 - timestamp1) * ME_CLK_DIVIDER * 10 + (delta_us / 2);
128*78ee8d1cSJulian Grajkowski do_div(temp, delta_us);
129*78ee8d1cSJulian Grajkowski *frequency = temp * 100000;
130*78ee8d1cSJulian Grajkowski
131*78ee8d1cSJulian Grajkowski return 0;
132*78ee8d1cSJulian Grajkowski }
133*78ee8d1cSJulian Grajkowski
134*78ee8d1cSJulian Grajkowski /**
135*78ee8d1cSJulian Grajkowski * adf_dev_measure_clock() -- Measure the CPM clock frequency
136*78ee8d1cSJulian Grajkowski * @accel_dev: Pointer to acceleration device.
137*78ee8d1cSJulian Grajkowski * @frequency: Pointer to returned frequency in Hz.
138*78ee8d1cSJulian Grajkowski * @min: Minimum expected frequency
139*78ee8d1cSJulian Grajkowski * @max: Maximum expected frequency
140*78ee8d1cSJulian Grajkowski *
141*78ee8d1cSJulian Grajkowski * Return: 0 on success, error code otherwise.
142*78ee8d1cSJulian Grajkowski */
143*78ee8d1cSJulian Grajkowski int
adf_dev_measure_clock(struct adf_accel_dev * accel_dev,u32 * frequency,u32 min,u32 max)144*78ee8d1cSJulian Grajkowski adf_dev_measure_clock(struct adf_accel_dev *accel_dev,
145*78ee8d1cSJulian Grajkowski u32 *frequency,
146*78ee8d1cSJulian Grajkowski u32 min,
147*78ee8d1cSJulian Grajkowski u32 max)
148*78ee8d1cSJulian Grajkowski {
149*78ee8d1cSJulian Grajkowski int ret;
150*78ee8d1cSJulian Grajkowski u32 freq;
151*78ee8d1cSJulian Grajkowski
152*78ee8d1cSJulian Grajkowski ret = measure_clock(accel_dev, &freq);
153*78ee8d1cSJulian Grajkowski if (ret)
154*78ee8d1cSJulian Grajkowski return ret;
155*78ee8d1cSJulian Grajkowski
156*78ee8d1cSJulian Grajkowski if (freq < min) {
157*78ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
158*78ee8d1cSJulian Grajkowski "Slow clock %d MHz measured, assuming %d\n",
159*78ee8d1cSJulian Grajkowski freq,
160*78ee8d1cSJulian Grajkowski min);
161*78ee8d1cSJulian Grajkowski freq = min;
162*78ee8d1cSJulian Grajkowski } else if (freq > max) {
163*78ee8d1cSJulian Grajkowski device_printf(GET_DEV(accel_dev),
164*78ee8d1cSJulian Grajkowski "Fast clock %d MHz measured, assuming %d\n",
165*78ee8d1cSJulian Grajkowski freq,
166*78ee8d1cSJulian Grajkowski max);
167*78ee8d1cSJulian Grajkowski freq = max;
168*78ee8d1cSJulian Grajkowski }
169*78ee8d1cSJulian Grajkowski *frequency = freq;
170*78ee8d1cSJulian Grajkowski return 0;
171*78ee8d1cSJulian Grajkowski }
172*78ee8d1cSJulian Grajkowski
173*78ee8d1cSJulian Grajkowski static inline u64
timespec_to_ms(const struct timespec * ts)174*78ee8d1cSJulian Grajkowski timespec_to_ms(const struct timespec *ts)
175*78ee8d1cSJulian Grajkowski {
176*78ee8d1cSJulian Grajkowski return (uint64_t)(ts->tv_sec * (1000)) + (ts->tv_nsec / NSEC_PER_MSEC);
177*78ee8d1cSJulian Grajkowski }
178*78ee8d1cSJulian Grajkowski
179*78ee8d1cSJulian Grajkowski u64
adf_clock_get_current_time(void)180*78ee8d1cSJulian Grajkowski adf_clock_get_current_time(void)
181*78ee8d1cSJulian Grajkowski {
182*78ee8d1cSJulian Grajkowski struct timespec ts;
183*78ee8d1cSJulian Grajkowski
184*78ee8d1cSJulian Grajkowski getnanotime(&ts);
185*78ee8d1cSJulian Grajkowski return timespec_to_ms(&ts);
186*78ee8d1cSJulian Grajkowski }
187