1 /*
2   This file is provided under a dual BSD/GPLv2 license.  When using or
3   redistributing this file, you may do so under either license.
4 
5   GPL LICENSE SUMMARY
6   Copyright(c) 2014 Intel Corporation.
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of version 2 of the GNU General Public License as
9   published by the Free Software Foundation.
10 
11   This program is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   General Public License for more details.
15 
16   Contact Information:
17   qat-linux@intel.com
18 
19   BSD LICENSE
20   Copyright(c) 2014 Intel Corporation.
21   Redistribution and use in source and binary forms, with or without
22   modification, are permitted provided that the following conditions
23   are met:
24 
25     * Redistributions of source code must retain the above copyright
26       notice, this list of conditions and the following disclaimer.
27     * Redistributions in binary form must reproduce the above copyright
28       notice, this list of conditions and the following disclaimer in
29       the documentation and/or other materials provided with the
30       distribution.
31     * Neither the name of Intel Corporation nor the names of its
32       contributors may be used to endorse or promote products derived
33       from this software without specific prior written permission.
34 
35   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 */
47 #include <linux/mutex.h>
48 #include <linux/slab.h>
49 #include <linux/seq_file.h>
50 #include "adf_accel_devices.h"
51 #include "adf_transport_internal.h"
52 #include "adf_transport_access_macros.h"
53 
54 static DEFINE_MUTEX(ring_read_lock);
55 static DEFINE_MUTEX(bank_read_lock);
56 
adf_ring_start(struct seq_file * sfile,loff_t * pos)57 static void *adf_ring_start(struct seq_file *sfile, loff_t *pos)
58 {
59 	struct adf_etr_ring_data *ring = sfile->private;
60 
61 	mutex_lock(&ring_read_lock);
62 	if (*pos == 0)
63 		return SEQ_START_TOKEN;
64 
65 	if (*pos >= (ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size) /
66 		     ADF_MSG_SIZE_TO_BYTES(ring->msg_size)))
67 		return NULL;
68 
69 	return ring->base_addr +
70 		(ADF_MSG_SIZE_TO_BYTES(ring->msg_size) * (*pos)++);
71 }
72 
adf_ring_next(struct seq_file * sfile,void * v,loff_t * pos)73 static void *adf_ring_next(struct seq_file *sfile, void *v, loff_t *pos)
74 {
75 	struct adf_etr_ring_data *ring = sfile->private;
76 
77 	if (*pos >= (ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size) /
78 		     ADF_MSG_SIZE_TO_BYTES(ring->msg_size)))
79 		return NULL;
80 
81 	return ring->base_addr +
82 		(ADF_MSG_SIZE_TO_BYTES(ring->msg_size) * (*pos)++);
83 }
84 
adf_ring_show(struct seq_file * sfile,void * v)85 static int adf_ring_show(struct seq_file *sfile, void *v)
86 {
87 	struct adf_etr_ring_data *ring = sfile->private;
88 	struct adf_etr_bank_data *bank = ring->bank;
89 	uint32_t *msg = v;
90 	void __iomem *csr = ring->bank->csr_addr;
91 	int i, x;
92 
93 	if (v == SEQ_START_TOKEN) {
94 		int head, tail, empty;
95 
96 		head = READ_CSR_RING_HEAD(csr, bank->bank_number,
97 					  ring->ring_number);
98 		tail = READ_CSR_RING_TAIL(csr, bank->bank_number,
99 					  ring->ring_number);
100 		empty = READ_CSR_E_STAT(csr, bank->bank_number);
101 
102 		seq_puts(sfile, "------- Ring configuration -------\n");
103 		seq_printf(sfile, "ring name: %s\n",
104 			   ring->ring_debug->ring_name);
105 		seq_printf(sfile, "ring num %d, bank num %d\n",
106 			   ring->ring_number, ring->bank->bank_number);
107 		seq_printf(sfile, "head %x, tail %x, empty: %d\n",
108 			   head, tail, (empty & 1 << ring->ring_number)
109 			   >> ring->ring_number);
110 		seq_printf(sfile, "ring size %d, msg size %d\n",
111 			   ADF_SIZE_TO_RING_SIZE_IN_BYTES(ring->ring_size),
112 			   ADF_MSG_SIZE_TO_BYTES(ring->msg_size));
113 		seq_puts(sfile, "----------- Ring data ------------\n");
114 		return 0;
115 	}
116 	seq_printf(sfile, "%p:", msg);
117 	x = 0;
118 	i = 0;
119 	for (; i < (ADF_MSG_SIZE_TO_BYTES(ring->msg_size) >> 2); i++) {
120 		seq_printf(sfile, " %08X", *(msg + i));
121 		if ((ADF_MSG_SIZE_TO_BYTES(ring->msg_size) >> 2) != i + 1 &&
122 		    (++x == 8)) {
123 			seq_printf(sfile, "\n%p:", msg + i + 1);
124 			x = 0;
125 		}
126 	}
127 	seq_puts(sfile, "\n");
128 	return 0;
129 }
130 
adf_ring_stop(struct seq_file * sfile,void * v)131 static void adf_ring_stop(struct seq_file *sfile, void *v)
132 {
133 	mutex_unlock(&ring_read_lock);
134 }
135 
136 static const struct seq_operations adf_ring_sops = {
137 	.start = adf_ring_start,
138 	.next = adf_ring_next,
139 	.stop = adf_ring_stop,
140 	.show = adf_ring_show
141 };
142 
adf_ring_open(struct inode * inode,struct file * file)143 static int adf_ring_open(struct inode *inode, struct file *file)
144 {
145 	int ret = seq_open(file, &adf_ring_sops);
146 
147 	if (!ret) {
148 		struct seq_file *seq_f = file->private_data;
149 
150 		seq_f->private = inode->i_private;
151 	}
152 	return ret;
153 }
154 
155 static const struct file_operations adf_ring_debug_fops = {
156 	.open = adf_ring_open,
157 	.read = seq_read,
158 	.llseek = seq_lseek,
159 	.release = seq_release
160 };
161 
adf_ring_debugfs_add(struct adf_etr_ring_data * ring,const char * name)162 int adf_ring_debugfs_add(struct adf_etr_ring_data *ring, const char *name)
163 {
164 	struct adf_etr_ring_debug_entry *ring_debug;
165 	char entry_name[8];
166 
167 	ring_debug = kzalloc(sizeof(*ring_debug), GFP_KERNEL);
168 	if (!ring_debug)
169 		return -ENOMEM;
170 
171 	strlcpy(ring_debug->ring_name, name, sizeof(ring_debug->ring_name));
172 	snprintf(entry_name, sizeof(entry_name), "ring_%02d",
173 		 ring->ring_number);
174 
175 	ring_debug->debug = debugfs_create_file(entry_name, S_IRUSR,
176 						ring->bank->bank_debug_dir,
177 						ring, &adf_ring_debug_fops);
178 	if (!ring_debug->debug) {
179 		pr_err("QAT: Failed to create ring debug entry.\n");
180 		kfree(ring_debug);
181 		return -EFAULT;
182 	}
183 	ring->ring_debug = ring_debug;
184 	return 0;
185 }
186 
adf_ring_debugfs_rm(struct adf_etr_ring_data * ring)187 void adf_ring_debugfs_rm(struct adf_etr_ring_data *ring)
188 {
189 	if (ring->ring_debug) {
190 		debugfs_remove(ring->ring_debug->debug);
191 		kfree(ring->ring_debug);
192 		ring->ring_debug = NULL;
193 	}
194 }
195 
adf_bank_start(struct seq_file * sfile,loff_t * pos)196 static void *adf_bank_start(struct seq_file *sfile, loff_t *pos)
197 {
198 	mutex_lock(&bank_read_lock);
199 	if (*pos == 0)
200 		return SEQ_START_TOKEN;
201 
202 	if (*pos >= ADF_ETR_MAX_RINGS_PER_BANK)
203 		return NULL;
204 
205 	return pos;
206 }
207 
adf_bank_next(struct seq_file * sfile,void * v,loff_t * pos)208 static void *adf_bank_next(struct seq_file *sfile, void *v, loff_t *pos)
209 {
210 	if (++(*pos) >= ADF_ETR_MAX_RINGS_PER_BANK)
211 		return NULL;
212 
213 	return pos;
214 }
215 
adf_bank_show(struct seq_file * sfile,void * v)216 static int adf_bank_show(struct seq_file *sfile, void *v)
217 {
218 	struct adf_etr_bank_data *bank = sfile->private;
219 
220 	if (v == SEQ_START_TOKEN) {
221 		seq_printf(sfile, "------- Bank %d configuration -------\n",
222 			   bank->bank_number);
223 	} else {
224 		int ring_id = *((int *)v) - 1;
225 		struct adf_etr_ring_data *ring = &bank->rings[ring_id];
226 		void __iomem *csr = bank->csr_addr;
227 		int head, tail, empty;
228 
229 		if (!(bank->ring_mask & 1 << ring_id))
230 			return 0;
231 
232 		head = READ_CSR_RING_HEAD(csr, bank->bank_number,
233 					  ring->ring_number);
234 		tail = READ_CSR_RING_TAIL(csr, bank->bank_number,
235 					  ring->ring_number);
236 		empty = READ_CSR_E_STAT(csr, bank->bank_number);
237 
238 		seq_printf(sfile,
239 			   "ring num %02d, head %04x, tail %04x, empty: %d\n",
240 			   ring->ring_number, head, tail,
241 			   (empty & 1 << ring->ring_number) >>
242 			   ring->ring_number);
243 	}
244 	return 0;
245 }
246 
adf_bank_stop(struct seq_file * sfile,void * v)247 static void adf_bank_stop(struct seq_file *sfile, void *v)
248 {
249 	mutex_unlock(&bank_read_lock);
250 }
251 
252 static const struct seq_operations adf_bank_sops = {
253 	.start = adf_bank_start,
254 	.next = adf_bank_next,
255 	.stop = adf_bank_stop,
256 	.show = adf_bank_show
257 };
258 
adf_bank_open(struct inode * inode,struct file * file)259 static int adf_bank_open(struct inode *inode, struct file *file)
260 {
261 	int ret = seq_open(file, &adf_bank_sops);
262 
263 	if (!ret) {
264 		struct seq_file *seq_f = file->private_data;
265 
266 		seq_f->private = inode->i_private;
267 	}
268 	return ret;
269 }
270 
271 static const struct file_operations adf_bank_debug_fops = {
272 	.open = adf_bank_open,
273 	.read = seq_read,
274 	.llseek = seq_lseek,
275 	.release = seq_release
276 };
277 
adf_bank_debugfs_add(struct adf_etr_bank_data * bank)278 int adf_bank_debugfs_add(struct adf_etr_bank_data *bank)
279 {
280 	struct adf_accel_dev *accel_dev = bank->accel_dev;
281 	struct dentry *parent = accel_dev->transport->debug;
282 	char name[8];
283 
284 	snprintf(name, sizeof(name), "bank_%02d", bank->bank_number);
285 	bank->bank_debug_dir = debugfs_create_dir(name, parent);
286 	if (!bank->bank_debug_dir) {
287 		pr_err("QAT: Failed to create bank debug dir.\n");
288 		return -EFAULT;
289 	}
290 
291 	bank->bank_debug_cfg = debugfs_create_file("config", S_IRUSR,
292 						   bank->bank_debug_dir, bank,
293 						   &adf_bank_debug_fops);
294 	if (!bank->bank_debug_cfg) {
295 		pr_err("QAT: Failed to create bank debug entry.\n");
296 		debugfs_remove(bank->bank_debug_dir);
297 		return -EFAULT;
298 	}
299 	return 0;
300 }
301 
adf_bank_debugfs_rm(struct adf_etr_bank_data * bank)302 void adf_bank_debugfs_rm(struct adf_etr_bank_data *bank)
303 {
304 	debugfs_remove(bank->bank_debug_cfg);
305 	debugfs_remove(bank->bank_debug_dir);
306 }
307