brintos

brintos / linux-shallow public Read only

0
0
Text · 6.1 KiB · cccdff2 Raw
249 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* 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 018#define HB_ERROR -119#define HB_STATUS_MAX_STRLEN 420#define HB_STATS_MAX_STRLEN 1621 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 and128		 * its period is fixed to 200ms129		 */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_INJECTION220		hb->dbgfs.inject_error = inject_error;221#endif222	}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_INJECTION242	debugfs_remove(hb->dbgfs.inject_error);243	hb->dbgfs.inject_error = NULL;244#endif245	debugfs_remove(hb->dbgfs.base_dir);246	hb->dbgfs.base_dir = NULL;247}248EXPORT_SYMBOL_GPL(adf_heartbeat_dbgfs_rm);249