xref: /linux/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.c (revision 8e07e0e3964ca4e23ce7b68e2096fe660a888942)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2023 Intel Corporation */
3 
4 #include <linux/debugfs.h>
5 #include <linux/errno.h>
6 #include <linux/export.h>
7 #include <linux/fs.h>
8 #include <linux/kernel.h>
9 #include <linux/kstrtox.h>
10 #include <linux/types.h>
11 #include "adf_admin.h"
12 #include "adf_cfg.h"
13 #include "adf_common_drv.h"
14 #include "adf_heartbeat.h"
15 #include "adf_heartbeat_dbgfs.h"
16 
17 #define HB_OK 0
18 #define HB_ERROR -1
19 #define HB_STATUS_MAX_STRLEN 4
20 #define HB_STATS_MAX_STRLEN 16
21 
22 static ssize_t adf_hb_stats_read(struct file *file, char __user *user_buffer,
23 				 size_t count, loff_t *ppos)
24 {
25 	char buf[HB_STATS_MAX_STRLEN];
26 	unsigned int *value;
27 	int len;
28 
29 	if (*ppos > 0)
30 		return 0;
31 
32 	value = file->private_data;
33 	len = scnprintf(buf, sizeof(buf), "%u\n", *value);
34 
35 	return simple_read_from_buffer(user_buffer, count, ppos, buf, len + 1);
36 }
37 
38 static const struct file_operations adf_hb_stats_fops = {
39 	.owner = THIS_MODULE,
40 	.open = simple_open,
41 	.read = adf_hb_stats_read,
42 };
43 
44 static ssize_t adf_hb_status_read(struct file *file, char __user *user_buf,
45 				  size_t count, loff_t *ppos)
46 {
47 	enum adf_device_heartbeat_status hb_status;
48 	char ret_str[HB_STATUS_MAX_STRLEN];
49 	struct adf_accel_dev *accel_dev;
50 	int ret_code;
51 	size_t len;
52 
53 	if (*ppos > 0)
54 		return 0;
55 
56 	accel_dev = file->private_data;
57 	ret_code = HB_OK;
58 
59 	adf_heartbeat_status(accel_dev, &hb_status);
60 
61 	if (hb_status != HB_DEV_ALIVE)
62 		ret_code = HB_ERROR;
63 
64 	len = scnprintf(ret_str, sizeof(ret_str), "%d\n", ret_code);
65 
66 	return simple_read_from_buffer(user_buf, count, ppos, ret_str, len + 1);
67 }
68 
69 static const struct file_operations adf_hb_status_fops = {
70 	.owner = THIS_MODULE,
71 	.open = simple_open,
72 	.read = adf_hb_status_read,
73 };
74 
75 static ssize_t adf_hb_cfg_read(struct file *file, char __user *user_buf,
76 			       size_t count, loff_t *ppos)
77 {
78 	char timer_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
79 	struct adf_accel_dev *accel_dev;
80 	unsigned int timer_ms;
81 	int len;
82 
83 	if (*ppos > 0)
84 		return 0;
85 
86 	accel_dev = file->private_data;
87 	timer_ms = accel_dev->heartbeat->hb_timer;
88 	len = scnprintf(timer_str, sizeof(timer_str), "%u\n", timer_ms);
89 
90 	return simple_read_from_buffer(user_buf, count, ppos, timer_str,
91 				       len + 1);
92 }
93 
94 static ssize_t adf_hb_cfg_write(struct file *file, const char __user *user_buf,
95 				size_t count, loff_t *ppos)
96 {
97 	char input_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { };
98 	struct adf_accel_dev *accel_dev;
99 	int ret, written_chars;
100 	unsigned int timer_ms;
101 	u32 ticks;
102 
103 	accel_dev = file->private_data;
104 	timer_ms = ADF_CFG_HB_TIMER_DEFAULT_MS;
105 
106 	/* last byte left as string termination */
107 	if (count > sizeof(input_str) - 1)
108 		return -EINVAL;
109 
110 	written_chars = simple_write_to_buffer(input_str, sizeof(input_str) - 1,
111 					       ppos, user_buf, count);
112 	if (written_chars > 0) {
113 		ret = kstrtouint(input_str, 10, &timer_ms);
114 		if (ret) {
115 			dev_err(&GET_DEV(accel_dev),
116 				"heartbeat_cfg: Invalid value\n");
117 			return ret;
118 		}
119 
120 		if (timer_ms < ADF_CFG_HB_TIMER_MIN_MS) {
121 			dev_err(&GET_DEV(accel_dev),
122 				"heartbeat_cfg: Invalid value\n");
123 			return -EINVAL;
124 		}
125 
126 		/*
127 		 * On 4xxx devices adf_timer is responsible for HB updates and
128 		 * its period is fixed to 200ms
129 		 */
130 		if (accel_dev->timer)
131 			timer_ms = ADF_CFG_HB_TIMER_MIN_MS;
132 
133 		ret = adf_heartbeat_save_cfg_param(accel_dev, timer_ms);
134 		if (ret)
135 			return ret;
136 
137 		ret = adf_heartbeat_ms_to_ticks(accel_dev, timer_ms, &ticks);
138 		if (ret)
139 			return ret;
140 
141 		ret = adf_send_admin_hb_timer(accel_dev, ticks);
142 		if (ret)
143 			return ret;
144 
145 		accel_dev->heartbeat->hb_timer = timer_ms;
146 	}
147 
148 	return written_chars;
149 }
150 
151 static const struct file_operations adf_hb_cfg_fops = {
152 	.owner = THIS_MODULE,
153 	.open = simple_open,
154 	.read = adf_hb_cfg_read,
155 	.write = adf_hb_cfg_write,
156 };
157 
158 void adf_heartbeat_dbgfs_add(struct adf_accel_dev *accel_dev)
159 {
160 	struct adf_heartbeat *hb = accel_dev->heartbeat;
161 
162 	if (!hb)
163 		return;
164 
165 	hb->dbgfs.base_dir = debugfs_create_dir("heartbeat", accel_dev->debugfs_dir);
166 	hb->dbgfs.status = debugfs_create_file("status", 0400, hb->dbgfs.base_dir,
167 					       accel_dev, &adf_hb_status_fops);
168 	hb->dbgfs.sent = debugfs_create_file("queries_sent", 0400, hb->dbgfs.base_dir,
169 					     &hb->hb_sent_counter, &adf_hb_stats_fops);
170 	hb->dbgfs.failed = debugfs_create_file("queries_failed", 0400, hb->dbgfs.base_dir,
171 					       &hb->hb_failed_counter, &adf_hb_stats_fops);
172 	hb->dbgfs.cfg = debugfs_create_file("config", 0600, hb->dbgfs.base_dir,
173 					    accel_dev, &adf_hb_cfg_fops);
174 }
175 EXPORT_SYMBOL_GPL(adf_heartbeat_dbgfs_add);
176 
177 void adf_heartbeat_dbgfs_rm(struct adf_accel_dev *accel_dev)
178 {
179 	struct adf_heartbeat *hb = accel_dev->heartbeat;
180 
181 	if (!hb)
182 		return;
183 
184 	debugfs_remove(hb->dbgfs.status);
185 	hb->dbgfs.status = NULL;
186 	debugfs_remove(hb->dbgfs.sent);
187 	hb->dbgfs.sent = NULL;
188 	debugfs_remove(hb->dbgfs.failed);
189 	hb->dbgfs.failed = NULL;
190 	debugfs_remove(hb->dbgfs.cfg);
191 	hb->dbgfs.cfg = NULL;
192 	debugfs_remove(hb->dbgfs.base_dir);
193 	hb->dbgfs.base_dir = NULL;
194 }
195 EXPORT_SYMBOL_GPL(adf_heartbeat_dbgfs_rm);
196