xref: /OK3568_Linux_fs/kernel/drivers/crypto/rockchip/procfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) Rockchip Electronics Co., Ltd. */
3 #include <linux/clk.h>
4 #include <linux/proc_fs.h>
5 #include <linux/sem.h>
6 #include <linux/seq_file.h>
7 
8 #include "procfs.h"
9 
10 #ifdef CONFIG_PROC_FS
11 
12 static const char *alg_type2name[ALG_TYPE_MAX] = {
13 	[ALG_TYPE_HASH]   = "HASH",
14 	[ALG_TYPE_HMAC]   = "HMAC",
15 	[ALG_TYPE_CIPHER] = "CIPHER",
16 	[ALG_TYPE_ASYM]   = "ASYM",
17 	[ALG_TYPE_AEAD]   = "AEAD",
18 };
19 
crypto_show_clock(struct seq_file * p,struct clk_bulk_data * clk_bulks,int clks_num)20 static void crypto_show_clock(struct seq_file *p, struct clk_bulk_data *clk_bulks, int clks_num)
21 {
22 	int i;
23 
24 	seq_puts(p, "clock info:\n");
25 
26 	for (i = 0; i < clks_num; i++)
27 		seq_printf(p, "\t%-10s %ld\n", clk_bulks[i].id, clk_get_rate(clk_bulks[i].clk));
28 
29 	seq_puts(p, "\n");
30 }
31 
crypto_show_stat(struct seq_file * p,struct rk_crypto_stat * stat)32 static void crypto_show_stat(struct seq_file *p, struct rk_crypto_stat *stat)
33 {
34 	/* show statistic info */
35 	seq_puts(p, "Statistic info:\n");
36 	seq_printf(p, "\tbusy_cnt      : %llu\n", stat->busy_cnt);
37 	seq_printf(p, "\tequeue_cnt    : %llu\n", stat->equeue_cnt);
38 	seq_printf(p, "\tdequeue_cnt   : %llu\n", stat->dequeue_cnt);
39 	seq_printf(p, "\tdone_cnt      : %llu\n", stat->done_cnt);
40 	seq_printf(p, "\tcomplete_cnt  : %llu\n", stat->complete_cnt);
41 	seq_printf(p, "\tfake_cnt      : %llu\n", stat->fake_cnt);
42 	seq_printf(p, "\tirq_cnt       : %llu\n", stat->irq_cnt);
43 	seq_printf(p, "\ttimeout_cnt   : %llu\n", stat->timeout_cnt);
44 	seq_printf(p, "\terror_cnt     : %llu\n", stat->error_cnt);
45 	seq_printf(p, "\tlast_error    : %d\n",   stat->last_error);
46 	seq_puts(p, "\n");
47 }
48 
crypto_show_queue_info(struct seq_file * p,struct rk_crypto_dev * rk_dev)49 static void crypto_show_queue_info(struct seq_file *p, struct rk_crypto_dev *rk_dev)
50 {
51 	bool busy;
52 	unsigned long flags;
53 	u32 qlen, max_qlen;
54 
55 	spin_lock_irqsave(&rk_dev->lock, flags);
56 
57 	qlen     = rk_dev->queue.qlen;
58 	max_qlen = rk_dev->queue.max_qlen;
59 	busy     = rk_dev->busy;
60 
61 	spin_unlock_irqrestore(&rk_dev->lock, flags);
62 
63 	seq_printf(p, "Crypto queue usage [%u/%u], ever_max = %llu, status: %s\n",
64 		   qlen, max_qlen, rk_dev->stat.ever_queue_max, busy ? "busy" : "idle");
65 
66 	seq_puts(p, "\n");
67 }
68 
crypto_show_valid_algo_single(struct seq_file * p,enum alg_type type,struct rk_crypto_algt ** algs,u32 algs_num)69 static void crypto_show_valid_algo_single(struct seq_file *p, enum alg_type type,
70 					  struct rk_crypto_algt **algs, u32 algs_num)
71 {
72 	u32 i;
73 	struct rk_crypto_algt *tmp_algs;
74 
75 	seq_printf(p, "\t%s:\n", alg_type2name[type]);
76 
77 	for (i = 0; i < algs_num; i++, algs++) {
78 		tmp_algs = *algs;
79 
80 		if (!(tmp_algs->valid_flag) || tmp_algs->type != type)
81 			continue;
82 
83 		seq_printf(p, "\t\t%s\n", tmp_algs->name);
84 	}
85 
86 	seq_puts(p, "\n");
87 }
88 
crypto_show_valid_algos(struct seq_file * p,struct rk_crypto_soc_data * soc_data)89 static void crypto_show_valid_algos(struct seq_file *p, struct rk_crypto_soc_data *soc_data)
90 {
91 	u32 algs_num = 0;
92 	struct rk_crypto_algt **algs;
93 
94 	seq_puts(p, "Valid algorithms:\n");
95 
96 	algs = soc_data->hw_get_algts(&algs_num);
97 	if (!algs || algs_num == 0)
98 		return;
99 
100 	crypto_show_valid_algo_single(p, ALG_TYPE_CIPHER, algs, algs_num);
101 	crypto_show_valid_algo_single(p, ALG_TYPE_AEAD,   algs, algs_num);
102 	crypto_show_valid_algo_single(p, ALG_TYPE_HASH,   algs, algs_num);
103 	crypto_show_valid_algo_single(p, ALG_TYPE_HMAC,   algs, algs_num);
104 	crypto_show_valid_algo_single(p, ALG_TYPE_ASYM,   algs, algs_num);
105 }
106 
crypto_show_all(struct seq_file * p,void * v)107 static int crypto_show_all(struct seq_file *p, void *v)
108 {
109 	struct rk_crypto_dev *rk_dev = p->private;
110 	struct rk_crypto_soc_data *soc_data = rk_dev->soc_data;
111 	struct rk_crypto_stat *stat = &rk_dev->stat;
112 
113 	seq_printf(p, "Rockchip Crypto Version: %s\n\n",
114 		   soc_data->crypto_ver);
115 
116 	seq_printf(p, "use_soft_aes192 : %s\n\n", soc_data->use_soft_aes192 ? "true" : "false");
117 
118 	crypto_show_clock(p, rk_dev->clk_bulks, rk_dev->clks_num);
119 
120 	crypto_show_valid_algos(p, soc_data);
121 
122 	crypto_show_stat(p, stat);
123 
124 	crypto_show_queue_info(p, rk_dev);
125 
126 	return 0;
127 }
128 
crypto_open(struct inode * inode,struct file * file)129 static int crypto_open(struct inode *inode, struct file *file)
130 {
131 	struct rk_crypto_dev *data = PDE_DATA(inode);
132 
133 	return single_open(file, crypto_show_all, data);
134 }
135 
136 static const struct proc_ops ops = {
137 	.proc_open    = crypto_open,
138 	.proc_read    = seq_read,
139 	.proc_lseek   = seq_lseek,
140 	.proc_release = single_release,
141 };
142 
rkcrypto_proc_init(struct rk_crypto_dev * rk_dev)143 int rkcrypto_proc_init(struct rk_crypto_dev *rk_dev)
144 {
145 	rk_dev->procfs = proc_create_data(rk_dev->name, 0, NULL, &ops, rk_dev);
146 	if (!rk_dev->procfs)
147 		return -EINVAL;
148 
149 	return 0;
150 }
151 
rkcrypto_proc_cleanup(struct rk_crypto_dev * rk_dev)152 void rkcrypto_proc_cleanup(struct rk_crypto_dev *rk_dev)
153 {
154 	if (rk_dev->procfs)
155 		remove_proc_entry(rk_dev->name, NULL);
156 
157 	rk_dev->procfs = NULL;
158 }
159 
160 #endif /* CONFIG_PROC_FS */
161