xref: /freebsd/sys/dev/qat/qat_common/adf_fw_counters.c (revision 71625ec9ad2a9bc8c09784fbd23b759830e0ee5f)
1*78ee8d1cSJulian Grajkowski /* SPDX-License-Identifier: BSD-3-Clause */
2*78ee8d1cSJulian Grajkowski /* Copyright(c) 2007-2022 Intel Corporation */
3*78ee8d1cSJulian Grajkowski #include <sys/types.h>
4*78ee8d1cSJulian Grajkowski #include <sys/sysctl.h>
5*78ee8d1cSJulian Grajkowski #include <sys/systm.h>
6*78ee8d1cSJulian Grajkowski #include "adf_accel_devices.h"
7*78ee8d1cSJulian Grajkowski #include "adf_fw_counters.h"
8*78ee8d1cSJulian Grajkowski #include "adf_common_drv.h"
9*78ee8d1cSJulian Grajkowski #include "icp_qat_fw_init_admin.h"
10*78ee8d1cSJulian Grajkowski #include <sys/mutex.h>
11*78ee8d1cSJulian Grajkowski #include <sys/sbuf.h>
12*78ee8d1cSJulian Grajkowski #define ADF_FW_COUNTERS_BUF_SZ 4096
13*78ee8d1cSJulian Grajkowski 
14*78ee8d1cSJulian Grajkowski #define ADF_RAS_EVENT_STR "RAS events"
15*78ee8d1cSJulian Grajkowski #define ADF_FW_REQ_STR "Firmware Requests"
16*78ee8d1cSJulian Grajkowski #define ADF_FW_RESP_STR "Firmware Responses"
17*78ee8d1cSJulian Grajkowski 
18*78ee8d1cSJulian Grajkowski static void adf_fw_counters_section_del_all(struct list_head *head);
19*78ee8d1cSJulian Grajkowski static void adf_fw_counters_del_all(struct adf_accel_dev *accel_dev);
20*78ee8d1cSJulian Grajkowski static int
21*78ee8d1cSJulian Grajkowski adf_fw_counters_add_key_value_param(struct adf_accel_dev *accel_dev,
22*78ee8d1cSJulian Grajkowski 				    const char *section_name,
23*78ee8d1cSJulian Grajkowski 				    const unsigned long sec_name_max_size,
24*78ee8d1cSJulian Grajkowski 				    const char *key,
25*78ee8d1cSJulian Grajkowski 				    const void *val);
26*78ee8d1cSJulian Grajkowski static int adf_fw_counters_section_add(struct adf_accel_dev *accel_dev,
27*78ee8d1cSJulian Grajkowski 				       const char *name,
28*78ee8d1cSJulian Grajkowski 				       const unsigned long name_max_size);
29*78ee8d1cSJulian Grajkowski int adf_get_fw_counters(struct adf_accel_dev *accel_dev);
30*78ee8d1cSJulian Grajkowski int adf_read_fw_counters(SYSCTL_HANDLER_ARGS);
31*78ee8d1cSJulian Grajkowski 
32*78ee8d1cSJulian Grajkowski int
adf_get_fw_counters(struct adf_accel_dev * accel_dev)33*78ee8d1cSJulian Grajkowski adf_get_fw_counters(struct adf_accel_dev *accel_dev)
34*78ee8d1cSJulian Grajkowski {
35*78ee8d1cSJulian Grajkowski 	struct icp_qat_fw_init_admin_req req;
36*78ee8d1cSJulian Grajkowski 	struct icp_qat_fw_init_admin_resp resp;
37*78ee8d1cSJulian Grajkowski 	unsigned long ae_mask;
38*78ee8d1cSJulian Grajkowski 	int i;
39*78ee8d1cSJulian Grajkowski 	int ret = 0;
40*78ee8d1cSJulian Grajkowski 	char aeidstr[16] = { 0 };
41*78ee8d1cSJulian Grajkowski 	struct adf_hw_device_data *hw_device;
42*78ee8d1cSJulian Grajkowski 
43*78ee8d1cSJulian Grajkowski 	if (!accel_dev) {
44*78ee8d1cSJulian Grajkowski 		ret = EFAULT;
45*78ee8d1cSJulian Grajkowski 		goto fail_clean;
46*78ee8d1cSJulian Grajkowski 	}
47*78ee8d1cSJulian Grajkowski 	if (!adf_dev_started(accel_dev)) {
48*78ee8d1cSJulian Grajkowski 		device_printf(GET_DEV(accel_dev), "Qat Device not started\n");
49*78ee8d1cSJulian Grajkowski 		ret = EFAULT;
50*78ee8d1cSJulian Grajkowski 		goto fail_clean;
51*78ee8d1cSJulian Grajkowski 	}
52*78ee8d1cSJulian Grajkowski 
53*78ee8d1cSJulian Grajkowski 	hw_device = accel_dev->hw_device;
54*78ee8d1cSJulian Grajkowski 	if (!hw_device) {
55*78ee8d1cSJulian Grajkowski 		ret = EFAULT;
56*78ee8d1cSJulian Grajkowski 		goto fail_clean;
57*78ee8d1cSJulian Grajkowski 	}
58*78ee8d1cSJulian Grajkowski 
59*78ee8d1cSJulian Grajkowski 	adf_fw_counters_del_all(accel_dev);
60*78ee8d1cSJulian Grajkowski 	explicit_bzero(&req, sizeof(struct icp_qat_fw_init_admin_req));
61*78ee8d1cSJulian Grajkowski 	req.cmd_id = ICP_QAT_FW_COUNTERS_GET;
62*78ee8d1cSJulian Grajkowski 	ae_mask = hw_device->ae_mask;
63*78ee8d1cSJulian Grajkowski 	for_each_set_bit(i, &ae_mask, GET_MAX_ACCELENGINES(accel_dev))
64*78ee8d1cSJulian Grajkowski 	{
65*78ee8d1cSJulian Grajkowski 		explicit_bzero(&resp,
66*78ee8d1cSJulian Grajkowski 			       sizeof(struct icp_qat_fw_init_admin_resp));
67*78ee8d1cSJulian Grajkowski 		if (adf_put_admin_msg_sync(accel_dev, i, &req, &resp) ||
68*78ee8d1cSJulian Grajkowski 		    resp.status) {
69*78ee8d1cSJulian Grajkowski 			resp.req_rec_count = ADF_FW_COUNTERS_NO_RESPONSE;
70*78ee8d1cSJulian Grajkowski 			resp.resp_sent_count = ADF_FW_COUNTERS_NO_RESPONSE;
71*78ee8d1cSJulian Grajkowski 			resp.ras_event_count = ADF_FW_COUNTERS_NO_RESPONSE;
72*78ee8d1cSJulian Grajkowski 		}
73*78ee8d1cSJulian Grajkowski 		explicit_bzero(aeidstr, sizeof(aeidstr));
74*78ee8d1cSJulian Grajkowski 		snprintf(aeidstr, sizeof(aeidstr), "AE %2d", i);
75*78ee8d1cSJulian Grajkowski 
76*78ee8d1cSJulian Grajkowski 		if (adf_fw_counters_section_add(accel_dev,
77*78ee8d1cSJulian Grajkowski 						aeidstr,
78*78ee8d1cSJulian Grajkowski 						sizeof(aeidstr))) {
79*78ee8d1cSJulian Grajkowski 			ret = ENOMEM;
80*78ee8d1cSJulian Grajkowski 			goto fail_clean;
81*78ee8d1cSJulian Grajkowski 		}
82*78ee8d1cSJulian Grajkowski 
83*78ee8d1cSJulian Grajkowski 		if (adf_fw_counters_add_key_value_param(
84*78ee8d1cSJulian Grajkowski 			accel_dev,
85*78ee8d1cSJulian Grajkowski 			aeidstr,
86*78ee8d1cSJulian Grajkowski 			sizeof(aeidstr),
87*78ee8d1cSJulian Grajkowski 			ADF_FW_REQ_STR,
88*78ee8d1cSJulian Grajkowski 			(void *)&resp.req_rec_count)) {
89*78ee8d1cSJulian Grajkowski 			adf_fw_counters_del_all(accel_dev);
90*78ee8d1cSJulian Grajkowski 			ret = ENOMEM;
91*78ee8d1cSJulian Grajkowski 			goto fail_clean;
92*78ee8d1cSJulian Grajkowski 		}
93*78ee8d1cSJulian Grajkowski 
94*78ee8d1cSJulian Grajkowski 		if (adf_fw_counters_add_key_value_param(
95*78ee8d1cSJulian Grajkowski 			accel_dev,
96*78ee8d1cSJulian Grajkowski 			aeidstr,
97*78ee8d1cSJulian Grajkowski 			sizeof(aeidstr),
98*78ee8d1cSJulian Grajkowski 			ADF_FW_RESP_STR,
99*78ee8d1cSJulian Grajkowski 			(void *)&resp.resp_sent_count)) {
100*78ee8d1cSJulian Grajkowski 			adf_fw_counters_del_all(accel_dev);
101*78ee8d1cSJulian Grajkowski 			ret = ENOMEM;
102*78ee8d1cSJulian Grajkowski 			goto fail_clean;
103*78ee8d1cSJulian Grajkowski 		}
104*78ee8d1cSJulian Grajkowski 
105*78ee8d1cSJulian Grajkowski 		if (hw_device->count_ras_event &&
106*78ee8d1cSJulian Grajkowski 		    hw_device->count_ras_event(accel_dev,
107*78ee8d1cSJulian Grajkowski 					       (void *)&resp.ras_event_count,
108*78ee8d1cSJulian Grajkowski 					       aeidstr)) {
109*78ee8d1cSJulian Grajkowski 			adf_fw_counters_del_all(accel_dev);
110*78ee8d1cSJulian Grajkowski 			ret = ENOMEM;
111*78ee8d1cSJulian Grajkowski 			goto fail_clean;
112*78ee8d1cSJulian Grajkowski 		}
113*78ee8d1cSJulian Grajkowski 	}
114*78ee8d1cSJulian Grajkowski 
115*78ee8d1cSJulian Grajkowski fail_clean:
116*78ee8d1cSJulian Grajkowski 	return ret;
117*78ee8d1cSJulian Grajkowski }
118*78ee8d1cSJulian Grajkowski 
adf_read_fw_counters(SYSCTL_HANDLER_ARGS)119*78ee8d1cSJulian Grajkowski int adf_read_fw_counters(SYSCTL_HANDLER_ARGS)
120*78ee8d1cSJulian Grajkowski {
121*78ee8d1cSJulian Grajkowski 	struct adf_accel_dev *accel_dev = arg1;
122*78ee8d1cSJulian Grajkowski 	struct adf_fw_counters_section *ptr = NULL;
123*78ee8d1cSJulian Grajkowski 	struct list_head *list = NULL, *list_ptr = NULL;
124*78ee8d1cSJulian Grajkowski 	struct list_head *tmp = NULL, *tmp_val = NULL;
125*78ee8d1cSJulian Grajkowski 	int ret = 0;
126*78ee8d1cSJulian Grajkowski 	struct sbuf *sbuf = NULL;
127*78ee8d1cSJulian Grajkowski 	char *cbuf = NULL;
128*78ee8d1cSJulian Grajkowski 
129*78ee8d1cSJulian Grajkowski 	if (accel_dev == NULL) {
130*78ee8d1cSJulian Grajkowski 		return EINVAL;
131*78ee8d1cSJulian Grajkowski 	}
132*78ee8d1cSJulian Grajkowski 	cbuf = malloc(ADF_FW_COUNTERS_BUF_SZ, M_QAT, M_WAITOK | M_ZERO);
133*78ee8d1cSJulian Grajkowski 
134*78ee8d1cSJulian Grajkowski 	sbuf = sbuf_new(NULL, cbuf, ADF_FW_COUNTERS_BUF_SZ, SBUF_FIXEDLEN);
135*78ee8d1cSJulian Grajkowski 	if (sbuf == NULL) {
136*78ee8d1cSJulian Grajkowski 		free(cbuf, M_QAT);
137*78ee8d1cSJulian Grajkowski 		return ENOMEM;
138*78ee8d1cSJulian Grajkowski 	}
139*78ee8d1cSJulian Grajkowski 	ret = adf_get_fw_counters(accel_dev);
140*78ee8d1cSJulian Grajkowski 
141*78ee8d1cSJulian Grajkowski 	if (ret) {
142*78ee8d1cSJulian Grajkowski 		sbuf_delete(sbuf);
143*78ee8d1cSJulian Grajkowski 		free(cbuf, M_QAT);
144*78ee8d1cSJulian Grajkowski 		return ret;
145*78ee8d1cSJulian Grajkowski 	}
146*78ee8d1cSJulian Grajkowski 
147*78ee8d1cSJulian Grajkowski 	sbuf_printf(sbuf,
148*78ee8d1cSJulian Grajkowski 		    "\n+------------------------------------------------+\n");
149*78ee8d1cSJulian Grajkowski 	sbuf_printf(
150*78ee8d1cSJulian Grajkowski 	    sbuf,
151*78ee8d1cSJulian Grajkowski 	    "| FW Statistics for Qat Device					   |\n");
152*78ee8d1cSJulian Grajkowski 	sbuf_printf(sbuf,
153*78ee8d1cSJulian Grajkowski 		    "+------------------------------------------------+\n");
154*78ee8d1cSJulian Grajkowski 
155*78ee8d1cSJulian Grajkowski 	list_for_each_prev_safe(list,
156*78ee8d1cSJulian Grajkowski 				tmp,
157*78ee8d1cSJulian Grajkowski 				&accel_dev->fw_counters_data->ae_sec_list)
158*78ee8d1cSJulian Grajkowski 	{
159*78ee8d1cSJulian Grajkowski 		ptr = list_entry(list, struct adf_fw_counters_section, list);
160*78ee8d1cSJulian Grajkowski 		sbuf_printf(sbuf, "%s\n", ptr->name);
161*78ee8d1cSJulian Grajkowski 		list_for_each_prev_safe(list_ptr, tmp_val, &ptr->param_head)
162*78ee8d1cSJulian Grajkowski 		{
163*78ee8d1cSJulian Grajkowski 			struct adf_fw_counters_val *count =
164*78ee8d1cSJulian Grajkowski 			    list_entry(list_ptr,
165*78ee8d1cSJulian Grajkowski 				       struct adf_fw_counters_val,
166*78ee8d1cSJulian Grajkowski 				       list);
167*78ee8d1cSJulian Grajkowski 			sbuf_printf(sbuf, "%s:%s\n", count->key, count->val);
168*78ee8d1cSJulian Grajkowski 		}
169*78ee8d1cSJulian Grajkowski 	}
170*78ee8d1cSJulian Grajkowski 
171*78ee8d1cSJulian Grajkowski 	sbuf_finish(sbuf);
172*78ee8d1cSJulian Grajkowski 	ret = SYSCTL_OUT(req, sbuf_data(sbuf), sbuf_len(sbuf));
173*78ee8d1cSJulian Grajkowski 	sbuf_delete(sbuf);
174*78ee8d1cSJulian Grajkowski 	free(cbuf, M_QAT);
175*78ee8d1cSJulian Grajkowski 	return ret;
176*78ee8d1cSJulian Grajkowski }
177*78ee8d1cSJulian Grajkowski 
178*78ee8d1cSJulian Grajkowski int
adf_fw_count_ras_event(struct adf_accel_dev * accel_dev,u32 * ras_event,char * aeidstr)179*78ee8d1cSJulian Grajkowski adf_fw_count_ras_event(struct adf_accel_dev *accel_dev,
180*78ee8d1cSJulian Grajkowski 		       u32 *ras_event,
181*78ee8d1cSJulian Grajkowski 		       char *aeidstr)
182*78ee8d1cSJulian Grajkowski {
183*78ee8d1cSJulian Grajkowski 	unsigned long count = 0;
184*78ee8d1cSJulian Grajkowski 
185*78ee8d1cSJulian Grajkowski 	if (!accel_dev || !ras_event || !aeidstr)
186*78ee8d1cSJulian Grajkowski 		return EINVAL;
187*78ee8d1cSJulian Grajkowski 
188*78ee8d1cSJulian Grajkowski 	count = (*ras_event == ADF_FW_COUNTERS_NO_RESPONSE ?
189*78ee8d1cSJulian Grajkowski 		     ADF_FW_COUNTERS_NO_RESPONSE :
190*78ee8d1cSJulian Grajkowski 		     (unsigned long)*ras_event);
191*78ee8d1cSJulian Grajkowski 
192*78ee8d1cSJulian Grajkowski 	return adf_fw_counters_add_key_value_param(
193*78ee8d1cSJulian Grajkowski 	    accel_dev, aeidstr, 16, ADF_RAS_EVENT_STR, (void *)&count);
194*78ee8d1cSJulian Grajkowski }
195*78ee8d1cSJulian Grajkowski 
196*78ee8d1cSJulian Grajkowski /**
197*78ee8d1cSJulian Grajkowski  * adf_fw_counters_add() - Create an acceleration device FW counters table.
198*78ee8d1cSJulian Grajkowski  * @accel_dev:	Pointer to acceleration device.
199*78ee8d1cSJulian Grajkowski  *
200*78ee8d1cSJulian Grajkowski  * Function creates a FW counters statistics table for the given
201*78ee8d1cSJulian Grajkowski  * acceleration device.
202*78ee8d1cSJulian Grajkowski  * The table stores device specific values of FW Requests sent to the FW and
203*78ee8d1cSJulian Grajkowski  * FW Responses received from the FW.
204*78ee8d1cSJulian Grajkowski  * To be used by QAT device specific drivers.
205*78ee8d1cSJulian Grajkowski  *
206*78ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
207*78ee8d1cSJulian Grajkowski  */
208*78ee8d1cSJulian Grajkowski int
adf_fw_counters_add(struct adf_accel_dev * accel_dev)209*78ee8d1cSJulian Grajkowski adf_fw_counters_add(struct adf_accel_dev *accel_dev)
210*78ee8d1cSJulian Grajkowski {
211*78ee8d1cSJulian Grajkowski 	struct adf_fw_counters_data *fw_counters_data;
212*78ee8d1cSJulian Grajkowski 	struct sysctl_ctx_list *qat_sysctl_ctx;
213*78ee8d1cSJulian Grajkowski 	struct sysctl_oid *qat_sysctl_tree;
214*78ee8d1cSJulian Grajkowski 	struct sysctl_oid *rc = 0;
215*78ee8d1cSJulian Grajkowski 
216*78ee8d1cSJulian Grajkowski 	fw_counters_data =
217*78ee8d1cSJulian Grajkowski 	    malloc(sizeof(*fw_counters_data), M_QAT, M_WAITOK | M_ZERO);
218*78ee8d1cSJulian Grajkowski 
219*78ee8d1cSJulian Grajkowski 	INIT_LIST_HEAD(&fw_counters_data->ae_sec_list);
220*78ee8d1cSJulian Grajkowski 
221*78ee8d1cSJulian Grajkowski 	init_rwsem(&fw_counters_data->lock);
222*78ee8d1cSJulian Grajkowski 	accel_dev->fw_counters_data = fw_counters_data;
223*78ee8d1cSJulian Grajkowski 
224*78ee8d1cSJulian Grajkowski 	qat_sysctl_ctx =
225*78ee8d1cSJulian Grajkowski 	    device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev);
226*78ee8d1cSJulian Grajkowski 	qat_sysctl_tree =
227*78ee8d1cSJulian Grajkowski 	    device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev);
228*78ee8d1cSJulian Grajkowski 	rc = SYSCTL_ADD_OID(qat_sysctl_ctx,
229*78ee8d1cSJulian Grajkowski 			    SYSCTL_CHILDREN(qat_sysctl_tree),
230*78ee8d1cSJulian Grajkowski 			    OID_AUTO,
231*78ee8d1cSJulian Grajkowski 			    "fw_counters",
232*78ee8d1cSJulian Grajkowski 			    CTLTYPE_STRING | CTLFLAG_RD,
233*78ee8d1cSJulian Grajkowski 			    accel_dev,
234*78ee8d1cSJulian Grajkowski 			    0,
235*78ee8d1cSJulian Grajkowski 			    adf_read_fw_counters,
236*78ee8d1cSJulian Grajkowski 			    "A",
237*78ee8d1cSJulian Grajkowski 			    "QAT FW counters");
238*78ee8d1cSJulian Grajkowski 	if (!rc)
239*78ee8d1cSJulian Grajkowski 		return ENOMEM;
240*78ee8d1cSJulian Grajkowski 	else
241*78ee8d1cSJulian Grajkowski 		return 0;
242*78ee8d1cSJulian Grajkowski }
243*78ee8d1cSJulian Grajkowski 
244*78ee8d1cSJulian Grajkowski static void
adf_fw_counters_del_all(struct adf_accel_dev * accel_dev)245*78ee8d1cSJulian Grajkowski adf_fw_counters_del_all(struct adf_accel_dev *accel_dev)
246*78ee8d1cSJulian Grajkowski {
247*78ee8d1cSJulian Grajkowski 	struct adf_fw_counters_data *fw_counters_data =
248*78ee8d1cSJulian Grajkowski 	    accel_dev->fw_counters_data;
249*78ee8d1cSJulian Grajkowski 
250*78ee8d1cSJulian Grajkowski 	down_write(&fw_counters_data->lock);
251*78ee8d1cSJulian Grajkowski 	adf_fw_counters_section_del_all(&fw_counters_data->ae_sec_list);
252*78ee8d1cSJulian Grajkowski 	up_write(&fw_counters_data->lock);
253*78ee8d1cSJulian Grajkowski }
254*78ee8d1cSJulian Grajkowski 
255*78ee8d1cSJulian Grajkowski static void
adf_fw_counters_keyval_add(struct adf_fw_counters_val * new,struct adf_fw_counters_section * sec)256*78ee8d1cSJulian Grajkowski adf_fw_counters_keyval_add(struct adf_fw_counters_val *new,
257*78ee8d1cSJulian Grajkowski 			   struct adf_fw_counters_section *sec)
258*78ee8d1cSJulian Grajkowski {
259*78ee8d1cSJulian Grajkowski 	list_add_tail(&new->list, &sec->param_head);
260*78ee8d1cSJulian Grajkowski }
261*78ee8d1cSJulian Grajkowski 
262*78ee8d1cSJulian Grajkowski static void
adf_fw_counters_keyval_del_all(struct list_head * head)263*78ee8d1cSJulian Grajkowski adf_fw_counters_keyval_del_all(struct list_head *head)
264*78ee8d1cSJulian Grajkowski {
265*78ee8d1cSJulian Grajkowski 	struct list_head *list_ptr = NULL, *tmp = NULL;
266*78ee8d1cSJulian Grajkowski 
267*78ee8d1cSJulian Grajkowski 	list_for_each_prev_safe(list_ptr, tmp, head)
268*78ee8d1cSJulian Grajkowski 	{
269*78ee8d1cSJulian Grajkowski 		struct adf_fw_counters_val *ptr =
270*78ee8d1cSJulian Grajkowski 		    list_entry(list_ptr, struct adf_fw_counters_val, list);
271*78ee8d1cSJulian Grajkowski 		list_del(list_ptr);
272*78ee8d1cSJulian Grajkowski 		free(ptr, M_QAT);
273*78ee8d1cSJulian Grajkowski 	}
274*78ee8d1cSJulian Grajkowski }
275*78ee8d1cSJulian Grajkowski 
276*78ee8d1cSJulian Grajkowski static void
adf_fw_counters_section_del_all(struct list_head * head)277*78ee8d1cSJulian Grajkowski adf_fw_counters_section_del_all(struct list_head *head)
278*78ee8d1cSJulian Grajkowski {
279*78ee8d1cSJulian Grajkowski 	struct adf_fw_counters_section *ptr = NULL;
280*78ee8d1cSJulian Grajkowski 	struct list_head *list = NULL, *tmp = NULL;
281*78ee8d1cSJulian Grajkowski 
282*78ee8d1cSJulian Grajkowski 	list_for_each_prev_safe(list, tmp, head)
283*78ee8d1cSJulian Grajkowski 	{
284*78ee8d1cSJulian Grajkowski 		ptr = list_entry(list, struct adf_fw_counters_section, list);
285*78ee8d1cSJulian Grajkowski 		adf_fw_counters_keyval_del_all(&ptr->param_head);
286*78ee8d1cSJulian Grajkowski 		list_del(list);
287*78ee8d1cSJulian Grajkowski 		free(ptr, M_QAT);
288*78ee8d1cSJulian Grajkowski 	}
289*78ee8d1cSJulian Grajkowski }
290*78ee8d1cSJulian Grajkowski 
291*78ee8d1cSJulian Grajkowski static struct adf_fw_counters_section *
adf_fw_counters_sec_find(struct adf_accel_dev * accel_dev,const char * sec_name,const unsigned long sec_name_max_size)292*78ee8d1cSJulian Grajkowski adf_fw_counters_sec_find(struct adf_accel_dev *accel_dev,
293*78ee8d1cSJulian Grajkowski 			 const char *sec_name,
294*78ee8d1cSJulian Grajkowski 			 const unsigned long sec_name_max_size)
295*78ee8d1cSJulian Grajkowski {
296*78ee8d1cSJulian Grajkowski 	struct adf_fw_counters_data *fw_counters_data =
297*78ee8d1cSJulian Grajkowski 	    accel_dev->fw_counters_data;
298*78ee8d1cSJulian Grajkowski 	struct list_head *list = NULL;
299*78ee8d1cSJulian Grajkowski 
300*78ee8d1cSJulian Grajkowski 	list_for_each(list, &fw_counters_data->ae_sec_list)
301*78ee8d1cSJulian Grajkowski 	{
302*78ee8d1cSJulian Grajkowski 		struct adf_fw_counters_section *ptr =
303*78ee8d1cSJulian Grajkowski 		    list_entry(list, struct adf_fw_counters_section, list);
304*78ee8d1cSJulian Grajkowski 		if (!strncmp(ptr->name, sec_name, sec_name_max_size))
305*78ee8d1cSJulian Grajkowski 			return ptr;
306*78ee8d1cSJulian Grajkowski 	}
307*78ee8d1cSJulian Grajkowski 	return NULL;
308*78ee8d1cSJulian Grajkowski }
309*78ee8d1cSJulian Grajkowski 
310*78ee8d1cSJulian Grajkowski static int
adf_fw_counters_add_key_value_param(struct adf_accel_dev * accel_dev,const char * section_name,const unsigned long sec_name_max_size,const char * key,const void * val)311*78ee8d1cSJulian Grajkowski adf_fw_counters_add_key_value_param(struct adf_accel_dev *accel_dev,
312*78ee8d1cSJulian Grajkowski 				    const char *section_name,
313*78ee8d1cSJulian Grajkowski 				    const unsigned long sec_name_max_size,
314*78ee8d1cSJulian Grajkowski 				    const char *key,
315*78ee8d1cSJulian Grajkowski 				    const void *val)
316*78ee8d1cSJulian Grajkowski {
317*78ee8d1cSJulian Grajkowski 	struct adf_fw_counters_data *fw_counters_data =
318*78ee8d1cSJulian Grajkowski 	    accel_dev->fw_counters_data;
319*78ee8d1cSJulian Grajkowski 	struct adf_fw_counters_val *key_val;
320*78ee8d1cSJulian Grajkowski 	struct adf_fw_counters_section *section =
321*78ee8d1cSJulian Grajkowski 	    adf_fw_counters_sec_find(accel_dev,
322*78ee8d1cSJulian Grajkowski 				     section_name,
323*78ee8d1cSJulian Grajkowski 				     sec_name_max_size);
324*78ee8d1cSJulian Grajkowski 	long tmp = *((const long *)val);
325*78ee8d1cSJulian Grajkowski 
326*78ee8d1cSJulian Grajkowski 	if (!section)
327*78ee8d1cSJulian Grajkowski 		return EFAULT;
328*78ee8d1cSJulian Grajkowski 	key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO);
329*78ee8d1cSJulian Grajkowski 
330*78ee8d1cSJulian Grajkowski 	INIT_LIST_HEAD(&key_val->list);
331*78ee8d1cSJulian Grajkowski 
332*78ee8d1cSJulian Grajkowski 	if (tmp == ADF_FW_COUNTERS_NO_RESPONSE) {
333*78ee8d1cSJulian Grajkowski 		snprintf(key_val->val,
334*78ee8d1cSJulian Grajkowski 			 FW_COUNTERS_MAX_VAL_LEN_IN_BYTES,
335*78ee8d1cSJulian Grajkowski 			 "No Response");
336*78ee8d1cSJulian Grajkowski 	} else {
337*78ee8d1cSJulian Grajkowski 		snprintf(key_val->val,
338*78ee8d1cSJulian Grajkowski 			 FW_COUNTERS_MAX_VAL_LEN_IN_BYTES,
339*78ee8d1cSJulian Grajkowski 			 "%ld",
340*78ee8d1cSJulian Grajkowski 			 tmp);
341*78ee8d1cSJulian Grajkowski 	}
342*78ee8d1cSJulian Grajkowski 
343*78ee8d1cSJulian Grajkowski 	strlcpy(key_val->key, key, sizeof(key_val->key));
344*78ee8d1cSJulian Grajkowski 	down_write(&fw_counters_data->lock);
345*78ee8d1cSJulian Grajkowski 	adf_fw_counters_keyval_add(key_val, section);
346*78ee8d1cSJulian Grajkowski 	up_write(&fw_counters_data->lock);
347*78ee8d1cSJulian Grajkowski 	return 0;
348*78ee8d1cSJulian Grajkowski }
349*78ee8d1cSJulian Grajkowski 
350*78ee8d1cSJulian Grajkowski /**
351*78ee8d1cSJulian Grajkowski  * adf_fw_counters_section_add() - Add AE section entry to FW counters table.
352*78ee8d1cSJulian Grajkowski  * @accel_dev:	Pointer to acceleration device.
353*78ee8d1cSJulian Grajkowski  * @name: Name of the section
354*78ee8d1cSJulian Grajkowski  *
355*78ee8d1cSJulian Grajkowski  * Function adds a section for each AE where FW Requests/Responses and their
356*78ee8d1cSJulian Grajkowski  * values will be stored.
357*78ee8d1cSJulian Grajkowski  * To be used by QAT device specific drivers.
358*78ee8d1cSJulian Grajkowski  *
359*78ee8d1cSJulian Grajkowski  * Return: 0 on success, error code otherwise.
360*78ee8d1cSJulian Grajkowski  */
361*78ee8d1cSJulian Grajkowski static int
adf_fw_counters_section_add(struct adf_accel_dev * accel_dev,const char * name,const unsigned long name_max_size)362*78ee8d1cSJulian Grajkowski adf_fw_counters_section_add(struct adf_accel_dev *accel_dev,
363*78ee8d1cSJulian Grajkowski 			    const char *name,
364*78ee8d1cSJulian Grajkowski 			    const unsigned long name_max_size)
365*78ee8d1cSJulian Grajkowski {
366*78ee8d1cSJulian Grajkowski 	struct adf_fw_counters_data *fw_counters_data =
367*78ee8d1cSJulian Grajkowski 	    accel_dev->fw_counters_data;
368*78ee8d1cSJulian Grajkowski 	struct adf_fw_counters_section *sec =
369*78ee8d1cSJulian Grajkowski 	    adf_fw_counters_sec_find(accel_dev, name, name_max_size);
370*78ee8d1cSJulian Grajkowski 
371*78ee8d1cSJulian Grajkowski 	if (sec)
372*78ee8d1cSJulian Grajkowski 		return 0;
373*78ee8d1cSJulian Grajkowski 
374*78ee8d1cSJulian Grajkowski 	sec = malloc(sizeof(*sec), M_QAT, M_WAITOK | M_ZERO);
375*78ee8d1cSJulian Grajkowski 
376*78ee8d1cSJulian Grajkowski 	strlcpy(sec->name, name, sizeof(sec->name));
377*78ee8d1cSJulian Grajkowski 	INIT_LIST_HEAD(&sec->param_head);
378*78ee8d1cSJulian Grajkowski 
379*78ee8d1cSJulian Grajkowski 	down_write(&fw_counters_data->lock);
380*78ee8d1cSJulian Grajkowski 
381*78ee8d1cSJulian Grajkowski 	list_add_tail(&sec->list, &fw_counters_data->ae_sec_list);
382*78ee8d1cSJulian Grajkowski 	up_write(&fw_counters_data->lock);
383*78ee8d1cSJulian Grajkowski 	return 0;
384*78ee8d1cSJulian Grajkowski }
385*78ee8d1cSJulian Grajkowski 
386*78ee8d1cSJulian Grajkowski /**
387*78ee8d1cSJulian Grajkowski  * adf_fw_counters_remove() - Clears acceleration device FW counters table.
388*78ee8d1cSJulian Grajkowski  * @accel_dev:	Pointer to acceleration device.
389*78ee8d1cSJulian Grajkowski  *
390*78ee8d1cSJulian Grajkowski  * Function removes FW counters table from the given acceleration device
391*78ee8d1cSJulian Grajkowski  * and frees all allocated memory.
392*78ee8d1cSJulian Grajkowski  * To be used by QAT device specific drivers.
393*78ee8d1cSJulian Grajkowski  *
394*78ee8d1cSJulian Grajkowski  * Return: void
395*78ee8d1cSJulian Grajkowski  */
396*78ee8d1cSJulian Grajkowski void
adf_fw_counters_remove(struct adf_accel_dev * accel_dev)397*78ee8d1cSJulian Grajkowski adf_fw_counters_remove(struct adf_accel_dev *accel_dev)
398*78ee8d1cSJulian Grajkowski {
399*78ee8d1cSJulian Grajkowski 	struct adf_fw_counters_data *fw_counters_data =
400*78ee8d1cSJulian Grajkowski 	    accel_dev->fw_counters_data;
401*78ee8d1cSJulian Grajkowski 
402*78ee8d1cSJulian Grajkowski 	if (!fw_counters_data)
403*78ee8d1cSJulian Grajkowski 		return;
404*78ee8d1cSJulian Grajkowski 
405*78ee8d1cSJulian Grajkowski 	down_write(&fw_counters_data->lock);
406*78ee8d1cSJulian Grajkowski 	adf_fw_counters_section_del_all(&fw_counters_data->ae_sec_list);
407*78ee8d1cSJulian Grajkowski 	up_write(&fw_counters_data->lock);
408*78ee8d1cSJulian Grajkowski 	free(fw_counters_data, M_QAT);
409*78ee8d1cSJulian Grajkowski 	accel_dev->fw_counters_data = NULL;
410*78ee8d1cSJulian Grajkowski }
411