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