xref: /linux/drivers/crypto/intel/qat/qat_common/adf_telemetry.c (revision 6093a688a07da07808f0122f9aa2a3eed250d853)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2023 Intel Corporation. */
3 #define dev_fmt(fmt) "Telemetry: " fmt
4 
5 #include <asm/errno.h>
6 #include <linux/atomic.h>
7 #include <linux/device.h>
8 #include <linux/dev_printk.h>
9 #include <linux/dma-mapping.h>
10 #include <linux/jiffies.h>
11 #include <linux/kernel.h>
12 #include <linux/mutex.h>
13 #include <linux/slab.h>
14 #include <linux/string.h>
15 #include <linux/workqueue.h>
16 
17 #include "adf_admin.h"
18 #include "adf_accel_devices.h"
19 #include "adf_common_drv.h"
20 #include "adf_telemetry.h"
21 
22 #define TL_IS_ZERO(input)	((input) == 0)
23 
24 static bool is_tl_supported(struct adf_accel_dev *accel_dev)
25 {
26 	u16 fw_caps =  GET_HW_DATA(accel_dev)->fw_capabilities;
27 
28 	return fw_caps & TL_CAPABILITY_BIT;
29 }
30 
31 static int validate_tl_data(struct adf_tl_hw_data *tl_data)
32 {
33 	if (!tl_data->dev_counters ||
34 	    TL_IS_ZERO(tl_data->num_dev_counters) ||
35 	    !tl_data->sl_util_counters ||
36 	    !tl_data->sl_exec_counters ||
37 	    !tl_data->rp_counters ||
38 	    TL_IS_ZERO(tl_data->num_rp_counters))
39 		return -EOPNOTSUPP;
40 
41 	return 0;
42 }
43 
44 static int validate_tl_slice_counters(struct icp_qat_fw_init_admin_slice_cnt *slice_count,
45 				      u8 max_slices_per_type)
46 {
47 	u8 *sl_counter = (u8 *)slice_count;
48 	int i;
49 
50 	for (i = 0; i < ADF_TL_SL_CNT_COUNT; i++) {
51 		if (sl_counter[i] > max_slices_per_type)
52 			return -EINVAL;
53 	}
54 
55 	return 0;
56 }
57 
58 static int adf_tl_alloc_mem(struct adf_accel_dev *accel_dev)
59 {
60 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(accel_dev);
61 	struct device *dev = &GET_DEV(accel_dev);
62 	size_t regs_sz = tl_data->layout_sz;
63 	struct adf_telemetry *telemetry;
64 	int node = dev_to_node(dev);
65 	void *tl_data_regs;
66 	unsigned int i;
67 
68 	telemetry = kzalloc_node(sizeof(*telemetry), GFP_KERNEL, node);
69 	if (!telemetry)
70 		return -ENOMEM;
71 
72 	telemetry->rp_num_indexes = kmalloc_array(tl_data->max_rp,
73 						  sizeof(*telemetry->rp_num_indexes),
74 						  GFP_KERNEL);
75 	if (!telemetry->rp_num_indexes)
76 		goto err_free_tl;
77 
78 	telemetry->regs_hist_buff = kmalloc_array(tl_data->num_hbuff,
79 						  sizeof(*telemetry->regs_hist_buff),
80 						  GFP_KERNEL);
81 	if (!telemetry->regs_hist_buff)
82 		goto err_free_rp_indexes;
83 
84 	telemetry->regs_data = dma_alloc_coherent(dev, regs_sz,
85 						  &telemetry->regs_data_p,
86 						  GFP_KERNEL);
87 	if (!telemetry->regs_data)
88 		goto err_free_regs_hist_buff;
89 
90 	for (i = 0; i < tl_data->num_hbuff; i++) {
91 		tl_data_regs = kzalloc_node(regs_sz, GFP_KERNEL, node);
92 		if (!tl_data_regs)
93 			goto err_free_dma;
94 
95 		telemetry->regs_hist_buff[i] = tl_data_regs;
96 	}
97 
98 	accel_dev->telemetry = telemetry;
99 
100 	return 0;
101 
102 err_free_dma:
103 	dma_free_coherent(dev, regs_sz, telemetry->regs_data,
104 			  telemetry->regs_data_p);
105 
106 	while (i--)
107 		kfree(telemetry->regs_hist_buff[i]);
108 
109 err_free_regs_hist_buff:
110 	kfree(telemetry->regs_hist_buff);
111 err_free_rp_indexes:
112 	kfree(telemetry->rp_num_indexes);
113 err_free_tl:
114 	kfree(telemetry);
115 
116 	return -ENOMEM;
117 }
118 
119 static void adf_tl_free_mem(struct adf_accel_dev *accel_dev)
120 {
121 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(accel_dev);
122 	struct adf_telemetry *telemetry = accel_dev->telemetry;
123 	struct device *dev = &GET_DEV(accel_dev);
124 	size_t regs_sz = tl_data->layout_sz;
125 	unsigned int i;
126 
127 	for (i = 0; i < tl_data->num_hbuff; i++)
128 		kfree(telemetry->regs_hist_buff[i]);
129 
130 	dma_free_coherent(dev, regs_sz, telemetry->regs_data,
131 			  telemetry->regs_data_p);
132 
133 	kfree(telemetry->regs_hist_buff);
134 	kfree(telemetry->rp_num_indexes);
135 	kfree(telemetry);
136 	accel_dev->telemetry = NULL;
137 }
138 
139 static unsigned long get_next_timeout(void)
140 {
141 	return msecs_to_jiffies(ADF_TL_TIMER_INT_MS);
142 }
143 
144 static void snapshot_regs(struct adf_telemetry *telemetry, size_t size)
145 {
146 	void *dst = telemetry->regs_hist_buff[telemetry->hb_num];
147 	void *src = telemetry->regs_data;
148 
149 	memcpy(dst, src, size);
150 }
151 
152 static void tl_work_handler(struct work_struct *work)
153 {
154 	struct delayed_work *delayed_work;
155 	struct adf_telemetry *telemetry;
156 	struct adf_tl_hw_data *tl_data;
157 	u32 msg_cnt, old_msg_cnt;
158 	size_t layout_sz;
159 	u32 *regs_data;
160 	size_t id;
161 
162 	delayed_work = to_delayed_work(work);
163 	telemetry = container_of(delayed_work, struct adf_telemetry, work_ctx);
164 	tl_data = &GET_TL_DATA(telemetry->accel_dev);
165 	regs_data = telemetry->regs_data;
166 
167 	id = tl_data->msg_cnt_off / sizeof(*regs_data);
168 	layout_sz = tl_data->layout_sz;
169 
170 	if (!atomic_read(&telemetry->state)) {
171 		cancel_delayed_work_sync(&telemetry->work_ctx);
172 		return;
173 	}
174 
175 	msg_cnt = regs_data[id];
176 	old_msg_cnt = msg_cnt;
177 	if (msg_cnt == telemetry->msg_cnt)
178 		goto out;
179 
180 	mutex_lock(&telemetry->regs_hist_lock);
181 
182 	snapshot_regs(telemetry, layout_sz);
183 
184 	/* Check if data changed while updating it */
185 	msg_cnt = regs_data[id];
186 	if (old_msg_cnt != msg_cnt)
187 		snapshot_regs(telemetry, layout_sz);
188 
189 	telemetry->msg_cnt = msg_cnt;
190 	telemetry->hb_num++;
191 	telemetry->hb_num %= telemetry->hbuffs;
192 
193 	mutex_unlock(&telemetry->regs_hist_lock);
194 
195 out:
196 	adf_misc_wq_queue_delayed_work(&telemetry->work_ctx, get_next_timeout());
197 }
198 
199 int adf_tl_halt(struct adf_accel_dev *accel_dev)
200 {
201 	struct adf_telemetry *telemetry = accel_dev->telemetry;
202 	struct device *dev = &GET_DEV(accel_dev);
203 	int ret;
204 
205 	cancel_delayed_work_sync(&telemetry->work_ctx);
206 	atomic_set(&telemetry->state, 0);
207 
208 	ret = adf_send_admin_tl_stop(accel_dev);
209 	if (ret)
210 		dev_err(dev, "failed to stop telemetry\n");
211 
212 	return ret;
213 }
214 
215 static void adf_set_cmdq_cnt(struct adf_accel_dev *accel_dev,
216 			     struct adf_tl_hw_data *tl_data)
217 {
218 	struct icp_qat_fw_init_admin_slice_cnt *slice_cnt, *cmdq_cnt;
219 
220 	slice_cnt = &accel_dev->telemetry->slice_cnt;
221 	cmdq_cnt = &accel_dev->telemetry->cmdq_cnt;
222 
223 	cmdq_cnt->cpr_cnt = slice_cnt->cpr_cnt * tl_data->multiplier.cpr_cnt;
224 	cmdq_cnt->dcpr_cnt = slice_cnt->dcpr_cnt * tl_data->multiplier.dcpr_cnt;
225 	cmdq_cnt->pke_cnt = slice_cnt->pke_cnt * tl_data->multiplier.pke_cnt;
226 	cmdq_cnt->wat_cnt = slice_cnt->wat_cnt * tl_data->multiplier.wat_cnt;
227 	cmdq_cnt->wcp_cnt = slice_cnt->wcp_cnt * tl_data->multiplier.wcp_cnt;
228 	cmdq_cnt->ucs_cnt = slice_cnt->ucs_cnt * tl_data->multiplier.ucs_cnt;
229 	cmdq_cnt->ath_cnt = slice_cnt->ath_cnt * tl_data->multiplier.ath_cnt;
230 }
231 
232 int adf_tl_run(struct adf_accel_dev *accel_dev, int state)
233 {
234 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(accel_dev);
235 	struct adf_telemetry *telemetry = accel_dev->telemetry;
236 	struct device *dev = &GET_DEV(accel_dev);
237 	size_t layout_sz = tl_data->layout_sz;
238 	int ret;
239 
240 	ret = adf_send_admin_tl_start(accel_dev, telemetry->regs_data_p,
241 				      layout_sz, telemetry->rp_num_indexes,
242 				      &telemetry->slice_cnt);
243 	if (ret) {
244 		dev_err(dev, "failed to start telemetry\n");
245 		return ret;
246 	}
247 
248 	ret = validate_tl_slice_counters(&telemetry->slice_cnt, tl_data->max_sl_cnt);
249 	if (ret) {
250 		dev_err(dev, "invalid value returned by FW\n");
251 		adf_send_admin_tl_stop(accel_dev);
252 		return ret;
253 	}
254 
255 	adf_set_cmdq_cnt(accel_dev, tl_data);
256 
257 	telemetry->hbuffs = state;
258 	atomic_set(&telemetry->state, state);
259 
260 	adf_misc_wq_queue_delayed_work(&telemetry->work_ctx, get_next_timeout());
261 
262 	return 0;
263 }
264 
265 int adf_tl_init(struct adf_accel_dev *accel_dev)
266 {
267 	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(accel_dev);
268 	u8 max_rp = GET_TL_DATA(accel_dev).max_rp;
269 	struct device *dev = &GET_DEV(accel_dev);
270 	struct adf_telemetry *telemetry;
271 	unsigned int i;
272 	int ret;
273 
274 	ret = validate_tl_data(tl_data);
275 	if (ret)
276 		return ret;
277 
278 	ret = adf_tl_alloc_mem(accel_dev);
279 	if (ret) {
280 		dev_err(dev, "failed to initialize: %d\n", ret);
281 		return ret;
282 	}
283 
284 	telemetry = accel_dev->telemetry;
285 	telemetry->accel_dev = accel_dev;
286 
287 	mutex_init(&telemetry->wr_lock);
288 	mutex_init(&telemetry->regs_hist_lock);
289 	INIT_DELAYED_WORK(&telemetry->work_ctx, tl_work_handler);
290 
291 	for (i = 0; i < max_rp; i++)
292 		telemetry->rp_num_indexes[i] = ADF_TL_RP_REGS_DISABLED;
293 
294 	return 0;
295 }
296 
297 int adf_tl_start(struct adf_accel_dev *accel_dev)
298 {
299 	struct device *dev = &GET_DEV(accel_dev);
300 
301 	if (!accel_dev->telemetry)
302 		return -EOPNOTSUPP;
303 
304 	if (!is_tl_supported(accel_dev)) {
305 		dev_info(dev, "feature not supported by FW\n");
306 		adf_tl_free_mem(accel_dev);
307 		return -EOPNOTSUPP;
308 	}
309 
310 	return 0;
311 }
312 
313 void adf_tl_stop(struct adf_accel_dev *accel_dev)
314 {
315 	if (!accel_dev->telemetry)
316 		return;
317 
318 	if (atomic_read(&accel_dev->telemetry->state))
319 		adf_tl_halt(accel_dev);
320 }
321 
322 void adf_tl_shutdown(struct adf_accel_dev *accel_dev)
323 {
324 	if (!accel_dev->telemetry)
325 		return;
326 
327 	adf_tl_free_mem(accel_dev);
328 }
329