xref: /openbmc/linux/drivers/ntb/test/ntb_tool.c (revision 4f6cce39)
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  *
7  *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
8  *
9  *   This program is free software; you can redistribute it and/or modify
10  *   it under the terms of version 2 of the GNU General Public License as
11  *   published by the Free Software Foundation.
12  *
13  *   This program is distributed in the hope that it will be useful, but
14  *   WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *   General Public License for more details.
17  *
18  *   BSD LICENSE
19  *
20  *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
21  *
22  *   Redistribution and use in source and binary forms, with or without
23  *   modification, are permitted provided that the following conditions
24  *   are met:
25  *
26  *     * Redistributions of source code must retain the above copyright
27  *       notice, this list of conditions and the following disclaimer.
28  *     * Redistributions in binary form must reproduce the above copy
29  *       notice, this list of conditions and the following disclaimer in
30  *       the documentation and/or other materials provided with the
31  *       distribution.
32  *     * Neither the name of Intel Corporation nor the names of its
33  *       contributors may be used to endorse or promote products derived
34  *       from this software without specific prior written permission.
35  *
36  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  *
48  * PCIe NTB Debugging Tool Linux driver
49  *
50  * Contact Information:
51  * Allen Hubbe <Allen.Hubbe@emc.com>
52  */
53 
54 /*
55  * How to use this tool, by example.
56  *
57  * Assuming $DBG_DIR is something like:
58  * '/sys/kernel/debug/ntb_tool/0000:00:03.0'
59  *
60  * Eg: check if clearing the doorbell mask generates an interrupt.
61  *
62  * # Check the link status
63  * root@self# cat $DBG_DIR/link
64  *
65  * # Block until the link is up
66  * root@self# echo Y > $DBG_DIR/link_event
67  *
68  * # Set the doorbell mask
69  * root@self# echo 's 1' > $DBG_DIR/mask
70  *
71  * # Ring the doorbell from the peer
72  * root@peer# echo 's 1' > $DBG_DIR/peer_db
73  *
74  * # Clear the doorbell mask
75  * root@self# echo 'c 1' > $DBG_DIR/mask
76  *
77  * Observe debugging output in dmesg or your console.  You should see a
78  * doorbell event triggered by clearing the mask.  If not, this may indicate an
79  * issue with the hardware that needs to be worked around in the driver.
80  *
81  * Eg: read and write scratchpad registers
82  *
83  * root@peer# echo '0 0x01010101 1 0x7f7f7f7f' > $DBG_DIR/peer_spad
84  *
85  * root@self# cat $DBG_DIR/spad
86  *
87  * Observe that spad 0 and 1 have the values set by the peer.
88  *
89  * # Check the memory window translation info
90  * cat $DBG_DIR/peer_trans0
91  *
92  * # Setup a 16k memory window buffer
93  * echo 16384 > $DBG_DIR/peer_trans0
94  *
95  */
96 
97 #include <linux/init.h>
98 #include <linux/kernel.h>
99 #include <linux/module.h>
100 
101 #include <linux/debugfs.h>
102 #include <linux/dma-mapping.h>
103 #include <linux/pci.h>
104 #include <linux/slab.h>
105 #include <linux/uaccess.h>
106 
107 #include <linux/ntb.h>
108 
109 #define DRIVER_NAME			"ntb_tool"
110 #define DRIVER_DESCRIPTION		"PCIe NTB Debugging Tool"
111 
112 #define DRIVER_LICENSE			"Dual BSD/GPL"
113 #define DRIVER_VERSION			"1.0"
114 #define DRIVER_RELDATE			"22 April 2015"
115 #define DRIVER_AUTHOR			"Allen Hubbe <Allen.Hubbe@emc.com>"
116 
117 MODULE_LICENSE(DRIVER_LICENSE);
118 MODULE_VERSION(DRIVER_VERSION);
119 MODULE_AUTHOR(DRIVER_AUTHOR);
120 MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
121 
122 #define MAX_MWS 16
123 
124 static struct dentry *tool_dbgfs;
125 
126 struct tool_mw {
127 	int idx;
128 	struct tool_ctx *tc;
129 	resource_size_t win_size;
130 	resource_size_t size;
131 	u8 __iomem *local;
132 	u8 *peer;
133 	dma_addr_t peer_dma;
134 	struct dentry *peer_dbg_file;
135 };
136 
137 struct tool_ctx {
138 	struct ntb_dev *ntb;
139 	struct dentry *dbgfs;
140 	wait_queue_head_t link_wq;
141 	int mw_count;
142 	struct tool_mw mws[MAX_MWS];
143 };
144 
145 #define SPAD_FNAME_SIZE 0x10
146 #define INT_PTR(x) ((void *)(unsigned long)x)
147 #define PTR_INT(x) ((int)(unsigned long)x)
148 
149 #define TOOL_FOPS_RDWR(__name, __read, __write) \
150 	const struct file_operations __name = {	\
151 		.owner = THIS_MODULE,		\
152 		.open = simple_open,		\
153 		.read = __read,			\
154 		.write = __write,		\
155 	}
156 
157 static void tool_link_event(void *ctx)
158 {
159 	struct tool_ctx *tc = ctx;
160 	enum ntb_speed speed;
161 	enum ntb_width width;
162 	int up;
163 
164 	up = ntb_link_is_up(tc->ntb, &speed, &width);
165 
166 	dev_dbg(&tc->ntb->dev, "link is %s speed %d width %d\n",
167 		up ? "up" : "down", speed, width);
168 
169 	wake_up(&tc->link_wq);
170 }
171 
172 static void tool_db_event(void *ctx, int vec)
173 {
174 	struct tool_ctx *tc = ctx;
175 	u64 db_bits, db_mask;
176 
177 	db_mask = ntb_db_vector_mask(tc->ntb, vec);
178 	db_bits = ntb_db_read(tc->ntb);
179 
180 	dev_dbg(&tc->ntb->dev, "doorbell vec %d mask %#llx bits %#llx\n",
181 		vec, db_mask, db_bits);
182 }
183 
184 static const struct ntb_ctx_ops tool_ops = {
185 	.link_event = tool_link_event,
186 	.db_event = tool_db_event,
187 };
188 
189 static ssize_t tool_dbfn_read(struct tool_ctx *tc, char __user *ubuf,
190 			      size_t size, loff_t *offp,
191 			      u64 (*db_read_fn)(struct ntb_dev *))
192 {
193 	size_t buf_size;
194 	char *buf;
195 	ssize_t pos, rc;
196 
197 	if (!db_read_fn)
198 		return -EINVAL;
199 
200 	buf_size = min_t(size_t, size, 0x20);
201 
202 	buf = kmalloc(buf_size, GFP_KERNEL);
203 	if (!buf)
204 		return -ENOMEM;
205 
206 	pos = scnprintf(buf, buf_size, "%#llx\n",
207 			db_read_fn(tc->ntb));
208 
209 	rc = simple_read_from_buffer(ubuf, size, offp, buf, pos);
210 
211 	kfree(buf);
212 
213 	return rc;
214 }
215 
216 static ssize_t tool_dbfn_write(struct tool_ctx *tc,
217 			       const char __user *ubuf,
218 			       size_t size, loff_t *offp,
219 			       int (*db_set_fn)(struct ntb_dev *, u64),
220 			       int (*db_clear_fn)(struct ntb_dev *, u64))
221 {
222 	u64 db_bits;
223 	char *buf, cmd;
224 	ssize_t rc;
225 	int n;
226 
227 	buf = kmalloc(size + 1, GFP_KERNEL);
228 	if (!buf)
229 		return -ENOMEM;
230 
231 	rc = simple_write_to_buffer(buf, size, offp, ubuf, size);
232 	if (rc < 0) {
233 		kfree(buf);
234 		return rc;
235 	}
236 
237 	buf[size] = 0;
238 
239 	n = sscanf(buf, "%c %lli", &cmd, &db_bits);
240 
241 	kfree(buf);
242 
243 	if (n != 2) {
244 		rc = -EINVAL;
245 	} else if (cmd == 's') {
246 		if (!db_set_fn)
247 			rc = -EINVAL;
248 		else
249 			rc = db_set_fn(tc->ntb, db_bits);
250 	} else if (cmd == 'c') {
251 		if (!db_clear_fn)
252 			rc = -EINVAL;
253 		else
254 			rc = db_clear_fn(tc->ntb, db_bits);
255 	} else {
256 		rc = -EINVAL;
257 	}
258 
259 	return rc ? : size;
260 }
261 
262 static ssize_t tool_spadfn_read(struct tool_ctx *tc, char __user *ubuf,
263 				size_t size, loff_t *offp,
264 				u32 (*spad_read_fn)(struct ntb_dev *, int))
265 {
266 	size_t buf_size;
267 	char *buf;
268 	ssize_t pos, rc;
269 	int i, spad_count;
270 
271 	if (!spad_read_fn)
272 		return -EINVAL;
273 
274 	spad_count = ntb_spad_count(tc->ntb);
275 
276 	/*
277 	 * We multiply the number of spads by 15 to get the buffer size
278 	 * this is from 3 for the %d, 10 for the largest hex value
279 	 * (0x00000000) and 2 for the tab and line feed.
280 	 */
281 	buf_size = min_t(size_t, size, spad_count * 15);
282 
283 	buf = kmalloc(buf_size, GFP_KERNEL);
284 	if (!buf)
285 		return -ENOMEM;
286 
287 	pos = 0;
288 
289 	for (i = 0; i < spad_count; ++i) {
290 		pos += scnprintf(buf + pos, buf_size - pos, "%d\t%#x\n",
291 				 i, spad_read_fn(tc->ntb, i));
292 	}
293 
294 	rc = simple_read_from_buffer(ubuf, size, offp, buf, pos);
295 
296 	kfree(buf);
297 
298 	return rc;
299 }
300 
301 static ssize_t tool_spadfn_write(struct tool_ctx *tc,
302 				 const char __user *ubuf,
303 				 size_t size, loff_t *offp,
304 				 int (*spad_write_fn)(struct ntb_dev *,
305 						      int, u32))
306 {
307 	int spad_idx;
308 	u32 spad_val;
309 	char *buf, *buf_ptr;
310 	int pos, n;
311 	ssize_t rc;
312 
313 	if (!spad_write_fn) {
314 		dev_dbg(&tc->ntb->dev, "no spad write fn\n");
315 		return -EINVAL;
316 	}
317 
318 	buf = kmalloc(size + 1, GFP_KERNEL);
319 	if (!buf)
320 		return -ENOMEM;
321 
322 	rc = simple_write_to_buffer(buf, size, offp, ubuf, size);
323 	if (rc < 0) {
324 		kfree(buf);
325 		return rc;
326 	}
327 
328 	buf[size] = 0;
329 	buf_ptr = buf;
330 	n = sscanf(buf_ptr, "%d %i%n", &spad_idx, &spad_val, &pos);
331 	while (n == 2) {
332 		buf_ptr += pos;
333 		rc = spad_write_fn(tc->ntb, spad_idx, spad_val);
334 		if (rc)
335 			break;
336 
337 		n = sscanf(buf_ptr, "%d %i%n", &spad_idx, &spad_val, &pos);
338 	}
339 
340 	if (n < 0)
341 		rc = n;
342 
343 	kfree(buf);
344 
345 	return rc ? : size;
346 }
347 
348 static ssize_t tool_db_read(struct file *filep, char __user *ubuf,
349 			    size_t size, loff_t *offp)
350 {
351 	struct tool_ctx *tc = filep->private_data;
352 
353 	return tool_dbfn_read(tc, ubuf, size, offp,
354 			      tc->ntb->ops->db_read);
355 }
356 
357 static ssize_t tool_db_write(struct file *filep, const char __user *ubuf,
358 			     size_t size, loff_t *offp)
359 {
360 	struct tool_ctx *tc = filep->private_data;
361 
362 	return tool_dbfn_write(tc, ubuf, size, offp,
363 			       tc->ntb->ops->db_set,
364 			       tc->ntb->ops->db_clear);
365 }
366 
367 static TOOL_FOPS_RDWR(tool_db_fops,
368 		      tool_db_read,
369 		      tool_db_write);
370 
371 static ssize_t tool_mask_read(struct file *filep, char __user *ubuf,
372 			      size_t size, loff_t *offp)
373 {
374 	struct tool_ctx *tc = filep->private_data;
375 
376 	return tool_dbfn_read(tc, ubuf, size, offp,
377 			      tc->ntb->ops->db_read_mask);
378 }
379 
380 static ssize_t tool_mask_write(struct file *filep, const char __user *ubuf,
381 			       size_t size, loff_t *offp)
382 {
383 	struct tool_ctx *tc = filep->private_data;
384 
385 	return tool_dbfn_write(tc, ubuf, size, offp,
386 			       tc->ntb->ops->db_set_mask,
387 			       tc->ntb->ops->db_clear_mask);
388 }
389 
390 static TOOL_FOPS_RDWR(tool_mask_fops,
391 		      tool_mask_read,
392 		      tool_mask_write);
393 
394 static ssize_t tool_peer_db_read(struct file *filep, char __user *ubuf,
395 				 size_t size, loff_t *offp)
396 {
397 	struct tool_ctx *tc = filep->private_data;
398 
399 	return tool_dbfn_read(tc, ubuf, size, offp,
400 			      tc->ntb->ops->peer_db_read);
401 }
402 
403 static ssize_t tool_peer_db_write(struct file *filep, const char __user *ubuf,
404 				  size_t size, loff_t *offp)
405 {
406 	struct tool_ctx *tc = filep->private_data;
407 
408 	return tool_dbfn_write(tc, ubuf, size, offp,
409 			       tc->ntb->ops->peer_db_set,
410 			       tc->ntb->ops->peer_db_clear);
411 }
412 
413 static TOOL_FOPS_RDWR(tool_peer_db_fops,
414 		      tool_peer_db_read,
415 		      tool_peer_db_write);
416 
417 static ssize_t tool_peer_mask_read(struct file *filep, char __user *ubuf,
418 				   size_t size, loff_t *offp)
419 {
420 	struct tool_ctx *tc = filep->private_data;
421 
422 	return tool_dbfn_read(tc, ubuf, size, offp,
423 			      tc->ntb->ops->peer_db_read_mask);
424 }
425 
426 static ssize_t tool_peer_mask_write(struct file *filep, const char __user *ubuf,
427 				    size_t size, loff_t *offp)
428 {
429 	struct tool_ctx *tc = filep->private_data;
430 
431 	return tool_dbfn_write(tc, ubuf, size, offp,
432 			       tc->ntb->ops->peer_db_set_mask,
433 			       tc->ntb->ops->peer_db_clear_mask);
434 }
435 
436 static TOOL_FOPS_RDWR(tool_peer_mask_fops,
437 		      tool_peer_mask_read,
438 		      tool_peer_mask_write);
439 
440 static ssize_t tool_spad_read(struct file *filep, char __user *ubuf,
441 			      size_t size, loff_t *offp)
442 {
443 	struct tool_ctx *tc = filep->private_data;
444 
445 	return tool_spadfn_read(tc, ubuf, size, offp,
446 				tc->ntb->ops->spad_read);
447 }
448 
449 static ssize_t tool_spad_write(struct file *filep, const char __user *ubuf,
450 			       size_t size, loff_t *offp)
451 {
452 	struct tool_ctx *tc = filep->private_data;
453 
454 	return tool_spadfn_write(tc, ubuf, size, offp,
455 				 tc->ntb->ops->spad_write);
456 }
457 
458 static TOOL_FOPS_RDWR(tool_spad_fops,
459 		      tool_spad_read,
460 		      tool_spad_write);
461 
462 static ssize_t tool_peer_spad_read(struct file *filep, char __user *ubuf,
463 				   size_t size, loff_t *offp)
464 {
465 	struct tool_ctx *tc = filep->private_data;
466 
467 	return tool_spadfn_read(tc, ubuf, size, offp,
468 				tc->ntb->ops->peer_spad_read);
469 }
470 
471 static ssize_t tool_peer_spad_write(struct file *filep, const char __user *ubuf,
472 				    size_t size, loff_t *offp)
473 {
474 	struct tool_ctx *tc = filep->private_data;
475 
476 	return tool_spadfn_write(tc, ubuf, size, offp,
477 				 tc->ntb->ops->peer_spad_write);
478 }
479 
480 static TOOL_FOPS_RDWR(tool_peer_spad_fops,
481 		      tool_peer_spad_read,
482 		      tool_peer_spad_write);
483 
484 static ssize_t tool_link_read(struct file *filep, char __user *ubuf,
485 			      size_t size, loff_t *offp)
486 {
487 	struct tool_ctx *tc = filep->private_data;
488 	char buf[3];
489 
490 	buf[0] = ntb_link_is_up(tc->ntb, NULL, NULL) ? 'Y' : 'N';
491 	buf[1] = '\n';
492 	buf[2] = '\0';
493 
494 	return simple_read_from_buffer(ubuf, size, offp, buf, 2);
495 }
496 
497 static ssize_t tool_link_write(struct file *filep, const char __user *ubuf,
498 			       size_t size, loff_t *offp)
499 {
500 	struct tool_ctx *tc = filep->private_data;
501 	char buf[32];
502 	size_t buf_size;
503 	bool val;
504 	int rc;
505 
506 	buf_size = min(size, (sizeof(buf) - 1));
507 	if (copy_from_user(buf, ubuf, buf_size))
508 		return -EFAULT;
509 
510 	buf[buf_size] = '\0';
511 
512 	rc = strtobool(buf, &val);
513 	if (rc)
514 		return rc;
515 
516 	if (val)
517 		rc = ntb_link_enable(tc->ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
518 	else
519 		rc = ntb_link_disable(tc->ntb);
520 
521 	if (rc)
522 		return rc;
523 
524 	return size;
525 }
526 
527 static TOOL_FOPS_RDWR(tool_link_fops,
528 		      tool_link_read,
529 		      tool_link_write);
530 
531 static ssize_t tool_link_event_write(struct file *filep,
532 				     const char __user *ubuf,
533 				     size_t size, loff_t *offp)
534 {
535 	struct tool_ctx *tc = filep->private_data;
536 	char buf[32];
537 	size_t buf_size;
538 	bool val;
539 	int rc;
540 
541 	buf_size = min(size, (sizeof(buf) - 1));
542 	if (copy_from_user(buf, ubuf, buf_size))
543 		return -EFAULT;
544 
545 	buf[buf_size] = '\0';
546 
547 	rc = strtobool(buf, &val);
548 	if (rc)
549 		return rc;
550 
551 	if (wait_event_interruptible(tc->link_wq,
552 		ntb_link_is_up(tc->ntb, NULL, NULL) == val))
553 		return -ERESTART;
554 
555 	return size;
556 }
557 
558 static TOOL_FOPS_RDWR(tool_link_event_fops,
559 		      NULL,
560 		      tool_link_event_write);
561 
562 static ssize_t tool_mw_read(struct file *filep, char __user *ubuf,
563 			    size_t size, loff_t *offp)
564 {
565 	struct tool_mw *mw = filep->private_data;
566 	ssize_t rc;
567 	loff_t pos = *offp;
568 	void *buf;
569 
570 	if (mw->local == NULL)
571 		return -EIO;
572 	if (pos < 0)
573 		return -EINVAL;
574 	if (pos >= mw->win_size || !size)
575 		return 0;
576 	if (size > mw->win_size - pos)
577 		size = mw->win_size - pos;
578 
579 	buf = kmalloc(size, GFP_KERNEL);
580 	if (!buf)
581 		return -ENOMEM;
582 
583 	memcpy_fromio(buf, mw->local + pos, size);
584 	rc = copy_to_user(ubuf, buf, size);
585 	if (rc == size) {
586 		rc = -EFAULT;
587 		goto err_free;
588 	}
589 
590 	size -= rc;
591 	*offp = pos + size;
592 	rc = size;
593 
594 err_free:
595 	kfree(buf);
596 
597 	return rc;
598 }
599 
600 static ssize_t tool_mw_write(struct file *filep, const char __user *ubuf,
601 			     size_t size, loff_t *offp)
602 {
603 	struct tool_mw *mw = filep->private_data;
604 	ssize_t rc;
605 	loff_t pos = *offp;
606 	void *buf;
607 
608 	if (pos < 0)
609 		return -EINVAL;
610 	if (pos >= mw->win_size || !size)
611 		return 0;
612 	if (size > mw->win_size - pos)
613 		size = mw->win_size - pos;
614 
615 	buf = kmalloc(size, GFP_KERNEL);
616 	if (!buf)
617 		return -ENOMEM;
618 
619 	rc = copy_from_user(buf, ubuf, size);
620 	if (rc == size) {
621 		rc = -EFAULT;
622 		goto err_free;
623 	}
624 
625 	size -= rc;
626 	*offp = pos + size;
627 	rc = size;
628 
629 	memcpy_toio(mw->local + pos, buf, size);
630 
631 err_free:
632 	kfree(buf);
633 
634 	return rc;
635 }
636 
637 static TOOL_FOPS_RDWR(tool_mw_fops,
638 		      tool_mw_read,
639 		      tool_mw_write);
640 
641 static ssize_t tool_peer_mw_read(struct file *filep, char __user *ubuf,
642 				 size_t size, loff_t *offp)
643 {
644 	struct tool_mw *mw = filep->private_data;
645 
646 	if (!mw->peer)
647 		return -ENXIO;
648 
649 	return simple_read_from_buffer(ubuf, size, offp, mw->peer, mw->size);
650 }
651 
652 static ssize_t tool_peer_mw_write(struct file *filep, const char __user *ubuf,
653 				  size_t size, loff_t *offp)
654 {
655 	struct tool_mw *mw = filep->private_data;
656 
657 	if (!mw->peer)
658 		return -ENXIO;
659 
660 	return simple_write_to_buffer(mw->peer, mw->size, offp, ubuf, size);
661 }
662 
663 static TOOL_FOPS_RDWR(tool_peer_mw_fops,
664 		      tool_peer_mw_read,
665 		      tool_peer_mw_write);
666 
667 static int tool_setup_mw(struct tool_ctx *tc, int idx, size_t req_size)
668 {
669 	int rc;
670 	struct tool_mw *mw = &tc->mws[idx];
671 	phys_addr_t base;
672 	resource_size_t size, align, align_size;
673 	char buf[16];
674 
675 	if (mw->peer)
676 		return 0;
677 
678 	rc = ntb_mw_get_range(tc->ntb, idx, &base, &size, &align,
679 			      &align_size);
680 	if (rc)
681 		return rc;
682 
683 	mw->size = min_t(resource_size_t, req_size, size);
684 	mw->size = round_up(mw->size, align);
685 	mw->size = round_up(mw->size, align_size);
686 	mw->peer = dma_alloc_coherent(&tc->ntb->pdev->dev, mw->size,
687 				      &mw->peer_dma, GFP_KERNEL);
688 
689 	if (!mw->peer)
690 		return -ENOMEM;
691 
692 	rc = ntb_mw_set_trans(tc->ntb, idx, mw->peer_dma, mw->size);
693 	if (rc)
694 		goto err_free_dma;
695 
696 	snprintf(buf, sizeof(buf), "peer_mw%d", idx);
697 	mw->peer_dbg_file = debugfs_create_file(buf, S_IRUSR | S_IWUSR,
698 						mw->tc->dbgfs, mw,
699 						&tool_peer_mw_fops);
700 
701 	return 0;
702 
703 err_free_dma:
704 	dma_free_coherent(&tc->ntb->pdev->dev, mw->size,
705 			  mw->peer,
706 			  mw->peer_dma);
707 	mw->peer = NULL;
708 	mw->peer_dma = 0;
709 	mw->size = 0;
710 
711 	return rc;
712 }
713 
714 static void tool_free_mw(struct tool_ctx *tc, int idx)
715 {
716 	struct tool_mw *mw = &tc->mws[idx];
717 
718 	if (mw->peer) {
719 		ntb_mw_clear_trans(tc->ntb, idx);
720 		dma_free_coherent(&tc->ntb->pdev->dev, mw->size,
721 				  mw->peer,
722 				  mw->peer_dma);
723 	}
724 
725 	mw->peer = NULL;
726 	mw->peer_dma = 0;
727 
728 	debugfs_remove(mw->peer_dbg_file);
729 
730 	mw->peer_dbg_file = NULL;
731 }
732 
733 static ssize_t tool_peer_mw_trans_read(struct file *filep,
734 				       char __user *ubuf,
735 				       size_t size, loff_t *offp)
736 {
737 	struct tool_mw *mw = filep->private_data;
738 
739 	char *buf;
740 	size_t buf_size;
741 	ssize_t ret, off = 0;
742 
743 	phys_addr_t base;
744 	resource_size_t mw_size;
745 	resource_size_t align;
746 	resource_size_t align_size;
747 
748 	buf_size = min_t(size_t, size, 512);
749 
750 	buf = kmalloc(buf_size, GFP_KERNEL);
751 	if (!buf)
752 		return -ENOMEM;
753 
754 	ntb_mw_get_range(mw->tc->ntb, mw->idx,
755 			 &base, &mw_size, &align, &align_size);
756 
757 	off += scnprintf(buf + off, buf_size - off,
758 			 "Peer MW %d Information:\n", mw->idx);
759 
760 	off += scnprintf(buf + off, buf_size - off,
761 			 "Physical Address      \t%pa[p]\n",
762 			 &base);
763 
764 	off += scnprintf(buf + off, buf_size - off,
765 			 "Window Size           \t%lld\n",
766 			 (unsigned long long)mw_size);
767 
768 	off += scnprintf(buf + off, buf_size - off,
769 			 "Alignment             \t%lld\n",
770 			 (unsigned long long)align);
771 
772 	off += scnprintf(buf + off, buf_size - off,
773 			 "Size Alignment        \t%lld\n",
774 			 (unsigned long long)align_size);
775 
776 	off += scnprintf(buf + off, buf_size - off,
777 			 "Ready                 \t%c\n",
778 			 (mw->peer) ? 'Y' : 'N');
779 
780 	off += scnprintf(buf + off, buf_size - off,
781 			 "Allocated Size       \t%zd\n",
782 			 (mw->peer) ? (size_t)mw->size : 0);
783 
784 	ret = simple_read_from_buffer(ubuf, size, offp, buf, off);
785 	kfree(buf);
786 	return ret;
787 }
788 
789 static ssize_t tool_peer_mw_trans_write(struct file *filep,
790 					const char __user *ubuf,
791 					size_t size, loff_t *offp)
792 {
793 	struct tool_mw *mw = filep->private_data;
794 
795 	char buf[32];
796 	size_t buf_size;
797 	unsigned long long val;
798 	int rc;
799 
800 	buf_size = min(size, (sizeof(buf) - 1));
801 	if (copy_from_user(buf, ubuf, buf_size))
802 		return -EFAULT;
803 
804 	buf[buf_size] = '\0';
805 
806 	rc = kstrtoull(buf, 0, &val);
807 	if (rc)
808 		return rc;
809 
810 	tool_free_mw(mw->tc, mw->idx);
811 	if (val)
812 		rc = tool_setup_mw(mw->tc, mw->idx, val);
813 
814 	if (rc)
815 		return rc;
816 
817 	return size;
818 }
819 
820 static TOOL_FOPS_RDWR(tool_peer_mw_trans_fops,
821 		      tool_peer_mw_trans_read,
822 		      tool_peer_mw_trans_write);
823 
824 static int tool_init_mw(struct tool_ctx *tc, int idx)
825 {
826 	struct tool_mw *mw = &tc->mws[idx];
827 	phys_addr_t base;
828 	int rc;
829 
830 	rc = ntb_mw_get_range(tc->ntb, idx, &base, &mw->win_size,
831 			      NULL, NULL);
832 	if (rc)
833 		return rc;
834 
835 	mw->tc = tc;
836 	mw->idx = idx;
837 	mw->local = ioremap_wc(base, mw->win_size);
838 	if (!mw->local)
839 		return -EFAULT;
840 
841 	return 0;
842 }
843 
844 static void tool_free_mws(struct tool_ctx *tc)
845 {
846 	int i;
847 
848 	for (i = 0; i < tc->mw_count; i++) {
849 		tool_free_mw(tc, i);
850 
851 		if (tc->mws[i].local)
852 			iounmap(tc->mws[i].local);
853 
854 		tc->mws[i].local = NULL;
855 	}
856 }
857 
858 static void tool_setup_dbgfs(struct tool_ctx *tc)
859 {
860 	int i;
861 
862 	/* This modules is useless without dbgfs... */
863 	if (!tool_dbgfs) {
864 		tc->dbgfs = NULL;
865 		return;
866 	}
867 
868 	tc->dbgfs = debugfs_create_dir(dev_name(&tc->ntb->dev),
869 				       tool_dbgfs);
870 	if (!tc->dbgfs)
871 		return;
872 
873 	debugfs_create_file("db", S_IRUSR | S_IWUSR, tc->dbgfs,
874 			    tc, &tool_db_fops);
875 
876 	debugfs_create_file("mask", S_IRUSR | S_IWUSR, tc->dbgfs,
877 			    tc, &tool_mask_fops);
878 
879 	debugfs_create_file("peer_db", S_IRUSR | S_IWUSR, tc->dbgfs,
880 			    tc, &tool_peer_db_fops);
881 
882 	debugfs_create_file("peer_mask", S_IRUSR | S_IWUSR, tc->dbgfs,
883 			    tc, &tool_peer_mask_fops);
884 
885 	debugfs_create_file("spad", S_IRUSR | S_IWUSR, tc->dbgfs,
886 			    tc, &tool_spad_fops);
887 
888 	debugfs_create_file("peer_spad", S_IRUSR | S_IWUSR, tc->dbgfs,
889 			    tc, &tool_peer_spad_fops);
890 
891 	debugfs_create_file("link", S_IRUSR | S_IWUSR, tc->dbgfs,
892 			    tc, &tool_link_fops);
893 
894 	debugfs_create_file("link_event", S_IWUSR, tc->dbgfs,
895 			    tc, &tool_link_event_fops);
896 
897 	for (i = 0; i < tc->mw_count; i++) {
898 		char buf[30];
899 
900 		snprintf(buf, sizeof(buf), "mw%d", i);
901 		debugfs_create_file(buf, S_IRUSR | S_IWUSR, tc->dbgfs,
902 				    &tc->mws[i], &tool_mw_fops);
903 
904 		snprintf(buf, sizeof(buf), "peer_trans%d", i);
905 		debugfs_create_file(buf, S_IRUSR | S_IWUSR, tc->dbgfs,
906 				    &tc->mws[i], &tool_peer_mw_trans_fops);
907 	}
908 }
909 
910 static int tool_probe(struct ntb_client *self, struct ntb_dev *ntb)
911 {
912 	struct tool_ctx *tc;
913 	int rc;
914 	int i;
915 
916 	if (ntb_db_is_unsafe(ntb))
917 		dev_dbg(&ntb->dev, "doorbell is unsafe\n");
918 
919 	if (ntb_spad_is_unsafe(ntb))
920 		dev_dbg(&ntb->dev, "scratchpad is unsafe\n");
921 
922 	tc = kzalloc(sizeof(*tc), GFP_KERNEL);
923 	if (!tc) {
924 		rc = -ENOMEM;
925 		goto err_tc;
926 	}
927 
928 	tc->ntb = ntb;
929 	init_waitqueue_head(&tc->link_wq);
930 
931 	tc->mw_count = min(ntb_mw_count(tc->ntb), MAX_MWS);
932 	for (i = 0; i < tc->mw_count; i++) {
933 		rc = tool_init_mw(tc, i);
934 		if (rc)
935 			goto err_ctx;
936 	}
937 
938 	tool_setup_dbgfs(tc);
939 
940 	rc = ntb_set_ctx(ntb, tc, &tool_ops);
941 	if (rc)
942 		goto err_ctx;
943 
944 	ntb_link_enable(ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
945 	ntb_link_event(ntb);
946 
947 	return 0;
948 
949 err_ctx:
950 	tool_free_mws(tc);
951 	debugfs_remove_recursive(tc->dbgfs);
952 	kfree(tc);
953 err_tc:
954 	return rc;
955 }
956 
957 static void tool_remove(struct ntb_client *self, struct ntb_dev *ntb)
958 {
959 	struct tool_ctx *tc = ntb->ctx;
960 
961 	tool_free_mws(tc);
962 
963 	ntb_clear_ctx(ntb);
964 	ntb_link_disable(ntb);
965 
966 	debugfs_remove_recursive(tc->dbgfs);
967 	kfree(tc);
968 }
969 
970 static struct ntb_client tool_client = {
971 	.ops = {
972 		.probe = tool_probe,
973 		.remove = tool_remove,
974 	},
975 };
976 
977 static int __init tool_init(void)
978 {
979 	int rc;
980 
981 	if (debugfs_initialized())
982 		tool_dbgfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
983 
984 	rc = ntb_register_client(&tool_client);
985 	if (rc)
986 		goto err_client;
987 
988 	return 0;
989 
990 err_client:
991 	debugfs_remove_recursive(tool_dbgfs);
992 	return rc;
993 }
994 module_init(tool_init);
995 
996 static void __exit tool_exit(void)
997 {
998 	ntb_unregister_client(&tool_client);
999 	debugfs_remove_recursive(tool_dbgfs);
1000 }
1001 module_exit(tool_exit);
1002