File Index
Files and directories
Sign in
FILE

adf_heartbeat_dbgfs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/crypto/intel/qat/qat_common/adf_heartbeat_dbgfs.c C
  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
 22static 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
 38static const struct file_operations adf_hb_stats_fops = {
 39	.owner = THIS_MODULE,
 40	.open = simple_open,
 41	.read = adf_hb_stats_read,
 42};
 43
 44static 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
 69static const struct file_operations adf_hb_status_fops = {
 70	.owner = THIS_MODULE,
 71	.open = simple_open,
 72	.read = adf_hb_status_read,
 73};
 74
 75static 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
 94static 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
151static 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
158static ssize_t adf_hb_error_inject_write(struct file *file,
159					 const char __user *user_buf,
160					 size_t count, loff_t *ppos)
161{
162	struct adf_accel_dev *accel_dev = file->private_data;
163	char buf[3];
164	int ret;
165
166	/* last byte left as string termination */
167	if (*ppos != 0 || count != 2)
168		return -EINVAL;
169
170	if (copy_from_user(buf, user_buf, count))
171		return -EFAULT;
172	buf[count] = '\0';
173
174	if (buf[0] != '1')
175		return -EINVAL;
176
177	ret = adf_heartbeat_inject_error(accel_dev);
178	if (ret) {
179		dev_err(&GET_DEV(accel_dev),
180			"Heartbeat error injection failed with status %d\n",
181			ret);
182		return ret;
183	}
184
185	dev_info(&GET_DEV(accel_dev), "Heartbeat error injection enabled\n");
186
187	return count;
188}
189
190static const struct file_operations adf_hb_error_inject_fops = {
191	.owner = THIS_MODULE,
192	.open = simple_open,
193	.write = adf_hb_error_inject_write,
194};
195
196void adf_heartbeat_dbgfs_add(struct adf_accel_dev *accel_dev)
197{
198	struct adf_heartbeat *hb = accel_dev->heartbeat;
199
200	if (!hb)
201		return;
202
203	hb->dbgfs.base_dir = debugfs_create_dir("heartbeat", accel_dev->debugfs_dir);
204	hb->dbgfs.status = debugfs_create_file("status", 0400, hb->dbgfs.base_dir,
205					       accel_dev, &adf_hb_status_fops);
206	hb->dbgfs.sent = debugfs_create_file("queries_sent", 0400, hb->dbgfs.base_dir,
207					     &hb->hb_sent_counter, &adf_hb_stats_fops);
208	hb->dbgfs.failed = debugfs_create_file("queries_failed", 0400, hb->dbgfs.base_dir,
209					       &hb->hb_failed_counter, &adf_hb_stats_fops);
210	hb->dbgfs.cfg = debugfs_create_file("config", 0600, hb->dbgfs.base_dir,
211					    accel_dev, &adf_hb_cfg_fops);
212
213	if (IS_ENABLED(CONFIG_CRYPTO_DEV_QAT_ERROR_INJECTION)) {
214		struct dentry *inject_error __maybe_unused;
215
216		inject_error = debugfs_create_file("inject_error", 0200,
217						   hb->dbgfs.base_dir, accel_dev,
218						   &adf_hb_error_inject_fops);
219#ifdef CONFIG_CRYPTO_DEV_QAT_ERROR_INJECTION
220		hb->dbgfs.inject_error = inject_error;
221#endif
222	}
223}
224EXPORT_SYMBOL_GPL(adf_heartbeat_dbgfs_add);
225
226void adf_heartbeat_dbgfs_rm(struct adf_accel_dev *accel_dev)
227{
228	struct adf_heartbeat *hb = accel_dev->heartbeat;
229
230	if (!hb)
231		return;
232
233	debugfs_remove(hb->dbgfs.status);
234	hb->dbgfs.status = NULL;
235	debugfs_remove(hb->dbgfs.sent);
236	hb->dbgfs.sent = NULL;
237	debugfs_remove(hb->dbgfs.failed);
238	hb->dbgfs.failed = NULL;
239	debugfs_remove(hb->dbgfs.cfg);
240	hb->dbgfs.cfg = NULL;
241#ifdef CONFIG_CRYPTO_DEV_QAT_ERROR_INJECTION
242	debugfs_remove(hb->dbgfs.inject_error);
243	hb->dbgfs.inject_error = NULL;
244#endif
245	debugfs_remove(hb->dbgfs.base_dir);
246	hb->dbgfs.base_dir = NULL;
247}
248EXPORT_SYMBOL_GPL(adf_heartbeat_dbgfs_rm);
~/ Read-only file preview.