xref: /linux/drivers/ntb/test/ntb_tool.c (revision c5ec8b451a02674882c75f51073a4f0323b37550)
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_VERSION			"1.0"
113 #define DRIVER_RELDATE			"22 April 2015"
114 #define DRIVER_AUTHOR			"Allen Hubbe <Allen.Hubbe@emc.com>"
115 
116 MODULE_LICENSE("Dual BSD/GPL");
117 MODULE_VERSION(DRIVER_VERSION);
118 MODULE_AUTHOR(DRIVER_AUTHOR);
119 MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
120 
121 /* It is rare to have hadrware with greater than six MWs */
122 #define MAX_MWS	6
123 /* Only two-ports devices are supported */
124 #define PIDX	NTB_DEF_PEER_IDX
125 
126 static struct dentry *tool_dbgfs;
127 
128 struct tool_mw {
129 	int idx;
130 	struct tool_ctx *tc;
131 	resource_size_t win_size;
132 	resource_size_t size;
133 	u8 __iomem *local;
134 	u8 *peer;
135 	dma_addr_t peer_dma;
136 	struct dentry *peer_dbg_file;
137 };
138 
139 struct tool_ctx {
140 	struct ntb_dev *ntb;
141 	struct dentry *dbgfs;
142 	wait_queue_head_t link_wq;
143 	int mw_count;
144 	struct tool_mw mws[MAX_MWS];
145 };
146 
147 #define SPAD_FNAME_SIZE 0x10
148 #define INT_PTR(x) ((void *)(unsigned long)x)
149 #define PTR_INT(x) ((int)(unsigned long)x)
150 
151 #define TOOL_FOPS_RDWR(__name, __read, __write) \
152 	const struct file_operations __name = {	\
153 		.owner = THIS_MODULE,		\
154 		.open = simple_open,		\
155 		.read = __read,			\
156 		.write = __write,		\
157 	}
158 
159 static void tool_link_event(void *ctx)
160 {
161 	struct tool_ctx *tc = ctx;
162 	enum ntb_speed speed;
163 	enum ntb_width width;
164 	int up;
165 
166 	up = ntb_link_is_up(tc->ntb, &speed, &width);
167 
168 	dev_dbg(&tc->ntb->dev, "link is %s speed %d width %d\n",
169 		up ? "up" : "down", speed, width);
170 
171 	wake_up(&tc->link_wq);
172 }
173 
174 static void tool_db_event(void *ctx, int vec)
175 {
176 	struct tool_ctx *tc = ctx;
177 	u64 db_bits, db_mask;
178 
179 	db_mask = ntb_db_vector_mask(tc->ntb, vec);
180 	db_bits = ntb_db_read(tc->ntb);
181 
182 	dev_dbg(&tc->ntb->dev, "doorbell vec %d mask %#llx bits %#llx\n",
183 		vec, db_mask, db_bits);
184 }
185 
186 static const struct ntb_ctx_ops tool_ops = {
187 	.link_event = tool_link_event,
188 	.db_event = tool_db_event,
189 };
190 
191 static ssize_t tool_dbfn_read(struct tool_ctx *tc, char __user *ubuf,
192 			      size_t size, loff_t *offp,
193 			      u64 (*db_read_fn)(struct ntb_dev *))
194 {
195 	size_t buf_size;
196 	char *buf;
197 	ssize_t pos, rc;
198 
199 	if (!db_read_fn)
200 		return -EINVAL;
201 
202 	buf_size = min_t(size_t, size, 0x20);
203 
204 	buf = kmalloc(buf_size, GFP_KERNEL);
205 	if (!buf)
206 		return -ENOMEM;
207 
208 	pos = scnprintf(buf, buf_size, "%#llx\n",
209 			db_read_fn(tc->ntb));
210 
211 	rc = simple_read_from_buffer(ubuf, size, offp, buf, pos);
212 
213 	kfree(buf);
214 
215 	return rc;
216 }
217 
218 static ssize_t tool_dbfn_write(struct tool_ctx *tc,
219 			       const char __user *ubuf,
220 			       size_t size, loff_t *offp,
221 			       int (*db_set_fn)(struct ntb_dev *, u64),
222 			       int (*db_clear_fn)(struct ntb_dev *, u64))
223 {
224 	u64 db_bits;
225 	char *buf, cmd;
226 	ssize_t rc;
227 	int n;
228 
229 	buf = kmalloc(size + 1, GFP_KERNEL);
230 	if (!buf)
231 		return -ENOMEM;
232 
233 	rc = simple_write_to_buffer(buf, size, offp, ubuf, size);
234 	if (rc < 0) {
235 		kfree(buf);
236 		return rc;
237 	}
238 
239 	buf[size] = 0;
240 
241 	n = sscanf(buf, "%c %lli", &cmd, &db_bits);
242 
243 	kfree(buf);
244 
245 	if (n != 2) {
246 		rc = -EINVAL;
247 	} else if (cmd == 's') {
248 		if (!db_set_fn)
249 			rc = -EINVAL;
250 		else
251 			rc = db_set_fn(tc->ntb, db_bits);
252 	} else if (cmd == 'c') {
253 		if (!db_clear_fn)
254 			rc = -EINVAL;
255 		else
256 			rc = db_clear_fn(tc->ntb, db_bits);
257 	} else {
258 		rc = -EINVAL;
259 	}
260 
261 	return rc ? : size;
262 }
263 
264 static ssize_t tool_spadfn_read(struct tool_ctx *tc, char __user *ubuf,
265 				size_t size, loff_t *offp,
266 				u32 (*spad_read_fn)(struct ntb_dev *, int))
267 {
268 	size_t buf_size;
269 	char *buf;
270 	ssize_t pos, rc;
271 	int i, spad_count;
272 
273 	if (!spad_read_fn)
274 		return -EINVAL;
275 
276 	spad_count = ntb_spad_count(tc->ntb);
277 
278 	/*
279 	 * We multiply the number of spads by 15 to get the buffer size
280 	 * this is from 3 for the %d, 10 for the largest hex value
281 	 * (0x00000000) and 2 for the tab and line feed.
282 	 */
283 	buf_size = min_t(size_t, size, spad_count * 15);
284 
285 	buf = kmalloc(buf_size, GFP_KERNEL);
286 	if (!buf)
287 		return -ENOMEM;
288 
289 	pos = 0;
290 
291 	for (i = 0; i < spad_count; ++i) {
292 		pos += scnprintf(buf + pos, buf_size - pos, "%d\t%#x\n",
293 				 i, spad_read_fn(tc->ntb, i));
294 	}
295 
296 	rc = simple_read_from_buffer(ubuf, size, offp, buf, pos);
297 
298 	kfree(buf);
299 
300 	return rc;
301 }
302 
303 static ssize_t tool_spadfn_write(struct tool_ctx *tc,
304 				 const char __user *ubuf,
305 				 size_t size, loff_t *offp,
306 				 int (*spad_write_fn)(struct ntb_dev *,
307 						      int, u32))
308 {
309 	int spad_idx;
310 	u32 spad_val;
311 	char *buf, *buf_ptr;
312 	int pos, n;
313 	ssize_t rc;
314 
315 	if (!spad_write_fn) {
316 		dev_dbg(&tc->ntb->dev, "no spad write fn\n");
317 		return -EINVAL;
318 	}
319 
320 	buf = kmalloc(size + 1, GFP_KERNEL);
321 	if (!buf)
322 		return -ENOMEM;
323 
324 	rc = simple_write_to_buffer(buf, size, offp, ubuf, size);
325 	if (rc < 0) {
326 		kfree(buf);
327 		return rc;
328 	}
329 
330 	buf[size] = 0;
331 	buf_ptr = buf;
332 	n = sscanf(buf_ptr, "%d %i%n", &spad_idx, &spad_val, &pos);
333 	while (n == 2) {
334 		buf_ptr += pos;
335 		rc = spad_write_fn(tc->ntb, spad_idx, spad_val);
336 		if (rc)
337 			break;
338 
339 		n = sscanf(buf_ptr, "%d %i%n", &spad_idx, &spad_val, &pos);
340 	}
341 
342 	if (n < 0)
343 		rc = n;
344 
345 	kfree(buf);
346 
347 	return rc ? : size;
348 }
349 
350 static ssize_t tool_db_read(struct file *filep, char __user *ubuf,
351 			    size_t size, loff_t *offp)
352 {
353 	struct tool_ctx *tc = filep->private_data;
354 
355 	return tool_dbfn_read(tc, ubuf, size, offp,
356 			      tc->ntb->ops->db_read);
357 }
358 
359 static ssize_t tool_db_write(struct file *filep, const char __user *ubuf,
360 			     size_t size, loff_t *offp)
361 {
362 	struct tool_ctx *tc = filep->private_data;
363 
364 	return tool_dbfn_write(tc, ubuf, size, offp,
365 			       tc->ntb->ops->db_set,
366 			       tc->ntb->ops->db_clear);
367 }
368 
369 static TOOL_FOPS_RDWR(tool_db_fops,
370 		      tool_db_read,
371 		      tool_db_write);
372 
373 static ssize_t tool_mask_read(struct file *filep, char __user *ubuf,
374 			      size_t size, loff_t *offp)
375 {
376 	struct tool_ctx *tc = filep->private_data;
377 
378 	return tool_dbfn_read(tc, ubuf, size, offp,
379 			      tc->ntb->ops->db_read_mask);
380 }
381 
382 static ssize_t tool_mask_write(struct file *filep, const char __user *ubuf,
383 			       size_t size, loff_t *offp)
384 {
385 	struct tool_ctx *tc = filep->private_data;
386 
387 	return tool_dbfn_write(tc, ubuf, size, offp,
388 			       tc->ntb->ops->db_set_mask,
389 			       tc->ntb->ops->db_clear_mask);
390 }
391 
392 static TOOL_FOPS_RDWR(tool_mask_fops,
393 		      tool_mask_read,
394 		      tool_mask_write);
395 
396 static ssize_t tool_peer_db_read(struct file *filep, char __user *ubuf,
397 				 size_t size, loff_t *offp)
398 {
399 	struct tool_ctx *tc = filep->private_data;
400 
401 	return tool_dbfn_read(tc, ubuf, size, offp,
402 			      tc->ntb->ops->peer_db_read);
403 }
404 
405 static ssize_t tool_peer_db_write(struct file *filep, const char __user *ubuf,
406 				  size_t size, loff_t *offp)
407 {
408 	struct tool_ctx *tc = filep->private_data;
409 
410 	return tool_dbfn_write(tc, ubuf, size, offp,
411 			       tc->ntb->ops->peer_db_set,
412 			       tc->ntb->ops->peer_db_clear);
413 }
414 
415 static TOOL_FOPS_RDWR(tool_peer_db_fops,
416 		      tool_peer_db_read,
417 		      tool_peer_db_write);
418 
419 static ssize_t tool_peer_mask_read(struct file *filep, char __user *ubuf,
420 				   size_t size, loff_t *offp)
421 {
422 	struct tool_ctx *tc = filep->private_data;
423 
424 	return tool_dbfn_read(tc, ubuf, size, offp,
425 			      tc->ntb->ops->peer_db_read_mask);
426 }
427 
428 static ssize_t tool_peer_mask_write(struct file *filep, const char __user *ubuf,
429 				    size_t size, loff_t *offp)
430 {
431 	struct tool_ctx *tc = filep->private_data;
432 
433 	return tool_dbfn_write(tc, ubuf, size, offp,
434 			       tc->ntb->ops->peer_db_set_mask,
435 			       tc->ntb->ops->peer_db_clear_mask);
436 }
437 
438 static TOOL_FOPS_RDWR(tool_peer_mask_fops,
439 		      tool_peer_mask_read,
440 		      tool_peer_mask_write);
441 
442 static ssize_t tool_spad_read(struct file *filep, char __user *ubuf,
443 			      size_t size, loff_t *offp)
444 {
445 	struct tool_ctx *tc = filep->private_data;
446 
447 	return tool_spadfn_read(tc, ubuf, size, offp,
448 				tc->ntb->ops->spad_read);
449 }
450 
451 static ssize_t tool_spad_write(struct file *filep, const char __user *ubuf,
452 			       size_t size, loff_t *offp)
453 {
454 	struct tool_ctx *tc = filep->private_data;
455 
456 	return tool_spadfn_write(tc, ubuf, size, offp,
457 				 tc->ntb->ops->spad_write);
458 }
459 
460 static TOOL_FOPS_RDWR(tool_spad_fops,
461 		      tool_spad_read,
462 		      tool_spad_write);
463 
464 static u32 ntb_tool_peer_spad_read(struct ntb_dev *ntb, int sidx)
465 {
466 	return ntb_peer_spad_read(ntb, PIDX, sidx);
467 }
468 
469 static ssize_t tool_peer_spad_read(struct file *filep, char __user *ubuf,
470 				   size_t size, loff_t *offp)
471 {
472 	struct tool_ctx *tc = filep->private_data;
473 
474 	return tool_spadfn_read(tc, ubuf, size, offp, ntb_tool_peer_spad_read);
475 }
476 
477 static int ntb_tool_peer_spad_write(struct ntb_dev *ntb, int sidx, u32 val)
478 {
479 	return ntb_peer_spad_write(ntb, PIDX, sidx, val);
480 }
481 
482 static ssize_t tool_peer_spad_write(struct file *filep, const char __user *ubuf,
483 				    size_t size, loff_t *offp)
484 {
485 	struct tool_ctx *tc = filep->private_data;
486 
487 	return tool_spadfn_write(tc, ubuf, size, offp,
488 				 ntb_tool_peer_spad_write);
489 }
490 
491 static TOOL_FOPS_RDWR(tool_peer_spad_fops,
492 		      tool_peer_spad_read,
493 		      tool_peer_spad_write);
494 
495 static ssize_t tool_link_read(struct file *filep, char __user *ubuf,
496 			      size_t size, loff_t *offp)
497 {
498 	struct tool_ctx *tc = filep->private_data;
499 	char buf[3];
500 
501 	buf[0] = ntb_link_is_up(tc->ntb, NULL, NULL) ? 'Y' : 'N';
502 	buf[1] = '\n';
503 	buf[2] = '\0';
504 
505 	return simple_read_from_buffer(ubuf, size, offp, buf, 2);
506 }
507 
508 static ssize_t tool_link_write(struct file *filep, const char __user *ubuf,
509 			       size_t size, loff_t *offp)
510 {
511 	struct tool_ctx *tc = filep->private_data;
512 	char buf[32];
513 	size_t buf_size;
514 	bool val;
515 	int rc;
516 
517 	buf_size = min(size, (sizeof(buf) - 1));
518 	if (copy_from_user(buf, ubuf, buf_size))
519 		return -EFAULT;
520 
521 	buf[buf_size] = '\0';
522 
523 	rc = strtobool(buf, &val);
524 	if (rc)
525 		return rc;
526 
527 	if (val)
528 		rc = ntb_link_enable(tc->ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
529 	else
530 		rc = ntb_link_disable(tc->ntb);
531 
532 	if (rc)
533 		return rc;
534 
535 	return size;
536 }
537 
538 static TOOL_FOPS_RDWR(tool_link_fops,
539 		      tool_link_read,
540 		      tool_link_write);
541 
542 static ssize_t tool_link_event_write(struct file *filep,
543 				     const char __user *ubuf,
544 				     size_t size, loff_t *offp)
545 {
546 	struct tool_ctx *tc = filep->private_data;
547 	char buf[32];
548 	size_t buf_size;
549 	bool val;
550 	int rc;
551 
552 	buf_size = min(size, (sizeof(buf) - 1));
553 	if (copy_from_user(buf, ubuf, buf_size))
554 		return -EFAULT;
555 
556 	buf[buf_size] = '\0';
557 
558 	rc = strtobool(buf, &val);
559 	if (rc)
560 		return rc;
561 
562 	if (wait_event_interruptible(tc->link_wq,
563 		ntb_link_is_up(tc->ntb, NULL, NULL) == val))
564 		return -ERESTART;
565 
566 	return size;
567 }
568 
569 static TOOL_FOPS_RDWR(tool_link_event_fops,
570 		      NULL,
571 		      tool_link_event_write);
572 
573 static ssize_t tool_mw_read(struct file *filep, char __user *ubuf,
574 			    size_t size, loff_t *offp)
575 {
576 	struct tool_mw *mw = filep->private_data;
577 	ssize_t rc;
578 	loff_t pos = *offp;
579 	void *buf;
580 
581 	if (mw->local == NULL)
582 		return -EIO;
583 	if (pos < 0)
584 		return -EINVAL;
585 	if (pos >= mw->win_size || !size)
586 		return 0;
587 	if (size > mw->win_size - pos)
588 		size = mw->win_size - pos;
589 
590 	buf = kmalloc(size, GFP_KERNEL);
591 	if (!buf)
592 		return -ENOMEM;
593 
594 	memcpy_fromio(buf, mw->local + pos, size);
595 	rc = copy_to_user(ubuf, buf, size);
596 	if (rc == size) {
597 		rc = -EFAULT;
598 		goto err_free;
599 	}
600 
601 	size -= rc;
602 	*offp = pos + size;
603 	rc = size;
604 
605 err_free:
606 	kfree(buf);
607 
608 	return rc;
609 }
610 
611 static ssize_t tool_mw_write(struct file *filep, const char __user *ubuf,
612 			     size_t size, loff_t *offp)
613 {
614 	struct tool_mw *mw = filep->private_data;
615 	ssize_t rc;
616 	loff_t pos = *offp;
617 	void *buf;
618 
619 	if (pos < 0)
620 		return -EINVAL;
621 	if (pos >= mw->win_size || !size)
622 		return 0;
623 	if (size > mw->win_size - pos)
624 		size = mw->win_size - pos;
625 
626 	buf = kmalloc(size, GFP_KERNEL);
627 	if (!buf)
628 		return -ENOMEM;
629 
630 	rc = copy_from_user(buf, ubuf, size);
631 	if (rc == size) {
632 		rc = -EFAULT;
633 		goto err_free;
634 	}
635 
636 	size -= rc;
637 	*offp = pos + size;
638 	rc = size;
639 
640 	memcpy_toio(mw->local + pos, buf, size);
641 
642 err_free:
643 	kfree(buf);
644 
645 	return rc;
646 }
647 
648 static TOOL_FOPS_RDWR(tool_mw_fops,
649 		      tool_mw_read,
650 		      tool_mw_write);
651 
652 static ssize_t tool_peer_mw_read(struct file *filep, 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_read_from_buffer(ubuf, size, offp, mw->peer, mw->size);
661 }
662 
663 static ssize_t tool_peer_mw_write(struct file *filep, const char __user *ubuf,
664 				  size_t size, loff_t *offp)
665 {
666 	struct tool_mw *mw = filep->private_data;
667 
668 	if (!mw->peer)
669 		return -ENXIO;
670 
671 	return simple_write_to_buffer(mw->peer, mw->size, offp, ubuf, size);
672 }
673 
674 static TOOL_FOPS_RDWR(tool_peer_mw_fops,
675 		      tool_peer_mw_read,
676 		      tool_peer_mw_write);
677 
678 static int tool_setup_mw(struct tool_ctx *tc, int idx, size_t req_size)
679 {
680 	int rc;
681 	struct tool_mw *mw = &tc->mws[idx];
682 	resource_size_t size, align_addr, align_size;
683 	char buf[16];
684 
685 	if (mw->peer)
686 		return 0;
687 
688 	rc = ntb_mw_get_align(tc->ntb, PIDX, idx, &align_addr,
689 				&align_size, &size);
690 	if (rc)
691 		return rc;
692 
693 	mw->size = min_t(resource_size_t, req_size, size);
694 	mw->size = round_up(mw->size, align_addr);
695 	mw->size = round_up(mw->size, align_size);
696 	mw->peer = dma_alloc_coherent(&tc->ntb->pdev->dev, mw->size,
697 				      &mw->peer_dma, GFP_KERNEL);
698 
699 	if (!mw->peer || !IS_ALIGNED(mw->peer_dma, align_addr))
700 		return -ENOMEM;
701 
702 	rc = ntb_mw_set_trans(tc->ntb, PIDX, idx, mw->peer_dma, mw->size);
703 	if (rc)
704 		goto err_free_dma;
705 
706 	snprintf(buf, sizeof(buf), "peer_mw%d", idx);
707 	mw->peer_dbg_file = debugfs_create_file(buf, S_IRUSR | S_IWUSR,
708 						mw->tc->dbgfs, mw,
709 						&tool_peer_mw_fops);
710 
711 	return 0;
712 
713 err_free_dma:
714 	dma_free_coherent(&tc->ntb->pdev->dev, mw->size,
715 			  mw->peer,
716 			  mw->peer_dma);
717 	mw->peer = NULL;
718 	mw->peer_dma = 0;
719 	mw->size = 0;
720 
721 	return rc;
722 }
723 
724 static void tool_free_mw(struct tool_ctx *tc, int idx)
725 {
726 	struct tool_mw *mw = &tc->mws[idx];
727 
728 	if (mw->peer) {
729 		ntb_mw_clear_trans(tc->ntb, PIDX, idx);
730 		dma_free_coherent(&tc->ntb->pdev->dev, mw->size,
731 				  mw->peer,
732 				  mw->peer_dma);
733 	}
734 
735 	mw->peer = NULL;
736 	mw->peer_dma = 0;
737 
738 	debugfs_remove(mw->peer_dbg_file);
739 
740 	mw->peer_dbg_file = NULL;
741 }
742 
743 static ssize_t tool_peer_mw_trans_read(struct file *filep,
744 				       char __user *ubuf,
745 				       size_t size, loff_t *offp)
746 {
747 	struct tool_mw *mw = filep->private_data;
748 
749 	char *buf;
750 	size_t buf_size;
751 	ssize_t ret, off = 0;
752 
753 	phys_addr_t base;
754 	resource_size_t mw_size;
755 	resource_size_t align_addr = 0;
756 	resource_size_t align_size = 0;
757 	resource_size_t max_size = 0;
758 
759 	buf_size = min_t(size_t, size, 512);
760 
761 	buf = kmalloc(buf_size, GFP_KERNEL);
762 	if (!buf)
763 		return -ENOMEM;
764 
765 	ntb_mw_get_align(mw->tc->ntb, PIDX, mw->idx,
766 			 &align_addr, &align_size, &max_size);
767 	ntb_peer_mw_get_addr(mw->tc->ntb, mw->idx, &base, &mw_size);
768 
769 	off += scnprintf(buf + off, buf_size - off,
770 			 "Peer MW %d Information:\n", mw->idx);
771 
772 	off += scnprintf(buf + off, buf_size - off,
773 			 "Physical Address      \t%pa[p]\n",
774 			 &base);
775 
776 	off += scnprintf(buf + off, buf_size - off,
777 			 "Window Size           \t%lld\n",
778 			 (unsigned long long)mw_size);
779 
780 	off += scnprintf(buf + off, buf_size - off,
781 			 "Alignment             \t%lld\n",
782 			 (unsigned long long)align_addr);
783 
784 	off += scnprintf(buf + off, buf_size - off,
785 			 "Size Alignment        \t%lld\n",
786 			 (unsigned long long)align_size);
787 
788 	off += scnprintf(buf + off, buf_size - off,
789 			 "Size Max              \t%lld\n",
790 			 (unsigned long long)max_size);
791 
792 	off += scnprintf(buf + off, buf_size - off,
793 			 "Ready                 \t%c\n",
794 			 (mw->peer) ? 'Y' : 'N');
795 
796 	off += scnprintf(buf + off, buf_size - off,
797 			 "Allocated Size       \t%zd\n",
798 			 (mw->peer) ? (size_t)mw->size : 0);
799 
800 	ret = simple_read_from_buffer(ubuf, size, offp, buf, off);
801 	kfree(buf);
802 	return ret;
803 }
804 
805 static ssize_t tool_peer_mw_trans_write(struct file *filep,
806 					const char __user *ubuf,
807 					size_t size, loff_t *offp)
808 {
809 	struct tool_mw *mw = filep->private_data;
810 
811 	char buf[32];
812 	size_t buf_size;
813 	unsigned long long val;
814 	int rc;
815 
816 	buf_size = min(size, (sizeof(buf) - 1));
817 	if (copy_from_user(buf, ubuf, buf_size))
818 		return -EFAULT;
819 
820 	buf[buf_size] = '\0';
821 
822 	rc = kstrtoull(buf, 0, &val);
823 	if (rc)
824 		return rc;
825 
826 	tool_free_mw(mw->tc, mw->idx);
827 	if (val)
828 		rc = tool_setup_mw(mw->tc, mw->idx, val);
829 
830 	if (rc)
831 		return rc;
832 
833 	return size;
834 }
835 
836 static TOOL_FOPS_RDWR(tool_peer_mw_trans_fops,
837 		      tool_peer_mw_trans_read,
838 		      tool_peer_mw_trans_write);
839 
840 static int tool_init_mw(struct tool_ctx *tc, int idx)
841 {
842 	struct tool_mw *mw = &tc->mws[idx];
843 	phys_addr_t base;
844 	int rc;
845 
846 	rc = ntb_peer_mw_get_addr(tc->ntb, idx, &base, &mw->win_size);
847 	if (rc)
848 		return rc;
849 
850 	mw->tc = tc;
851 	mw->idx = idx;
852 	mw->local = ioremap_wc(base, mw->win_size);
853 	if (!mw->local)
854 		return -EFAULT;
855 
856 	return 0;
857 }
858 
859 static void tool_free_mws(struct tool_ctx *tc)
860 {
861 	int i;
862 
863 	for (i = 0; i < tc->mw_count; i++) {
864 		tool_free_mw(tc, i);
865 
866 		if (tc->mws[i].local)
867 			iounmap(tc->mws[i].local);
868 
869 		tc->mws[i].local = NULL;
870 	}
871 }
872 
873 static void tool_setup_dbgfs(struct tool_ctx *tc)
874 {
875 	int i;
876 
877 	/* This modules is useless without dbgfs... */
878 	if (!tool_dbgfs) {
879 		tc->dbgfs = NULL;
880 		return;
881 	}
882 
883 	tc->dbgfs = debugfs_create_dir(dev_name(&tc->ntb->dev),
884 				       tool_dbgfs);
885 	if (!tc->dbgfs)
886 		return;
887 
888 	debugfs_create_file("db", S_IRUSR | S_IWUSR, tc->dbgfs,
889 			    tc, &tool_db_fops);
890 
891 	debugfs_create_file("mask", S_IRUSR | S_IWUSR, tc->dbgfs,
892 			    tc, &tool_mask_fops);
893 
894 	debugfs_create_file("peer_db", S_IRUSR | S_IWUSR, tc->dbgfs,
895 			    tc, &tool_peer_db_fops);
896 
897 	debugfs_create_file("peer_mask", S_IRUSR | S_IWUSR, tc->dbgfs,
898 			    tc, &tool_peer_mask_fops);
899 
900 	debugfs_create_file("spad", S_IRUSR | S_IWUSR, tc->dbgfs,
901 			    tc, &tool_spad_fops);
902 
903 	debugfs_create_file("peer_spad", S_IRUSR | S_IWUSR, tc->dbgfs,
904 			    tc, &tool_peer_spad_fops);
905 
906 	debugfs_create_file("link", S_IRUSR | S_IWUSR, tc->dbgfs,
907 			    tc, &tool_link_fops);
908 
909 	debugfs_create_file("link_event", S_IWUSR, tc->dbgfs,
910 			    tc, &tool_link_event_fops);
911 
912 	for (i = 0; i < tc->mw_count; i++) {
913 		char buf[30];
914 
915 		snprintf(buf, sizeof(buf), "mw%d", i);
916 		debugfs_create_file(buf, S_IRUSR | S_IWUSR, tc->dbgfs,
917 				    &tc->mws[i], &tool_mw_fops);
918 
919 		snprintf(buf, sizeof(buf), "peer_trans%d", i);
920 		debugfs_create_file(buf, S_IRUSR | S_IWUSR, tc->dbgfs,
921 				    &tc->mws[i], &tool_peer_mw_trans_fops);
922 	}
923 }
924 
925 static int tool_probe(struct ntb_client *self, struct ntb_dev *ntb)
926 {
927 	struct tool_ctx *tc;
928 	int rc;
929 	int i;
930 
931 	if (!ntb->ops->mw_set_trans) {
932 		dev_dbg(&ntb->dev, "need inbound MW based NTB API\n");
933 		rc = -EINVAL;
934 		goto err_tc;
935 	}
936 
937 	if (ntb_spad_count(ntb) < 1) {
938 		dev_dbg(&ntb->dev, "no enough scratchpads\n");
939 		rc = -EINVAL;
940 		goto err_tc;
941 	}
942 
943 	if (ntb_db_is_unsafe(ntb))
944 		dev_dbg(&ntb->dev, "doorbell is unsafe\n");
945 
946 	if (ntb_spad_is_unsafe(ntb))
947 		dev_dbg(&ntb->dev, "scratchpad is unsafe\n");
948 
949 	if (ntb_peer_port_count(ntb) != NTB_DEF_PEER_CNT)
950 		dev_warn(&ntb->dev, "multi-port NTB is unsupported\n");
951 
952 	tc = kzalloc(sizeof(*tc), GFP_KERNEL);
953 	if (!tc) {
954 		rc = -ENOMEM;
955 		goto err_tc;
956 	}
957 
958 	tc->ntb = ntb;
959 	init_waitqueue_head(&tc->link_wq);
960 
961 	tc->mw_count = min(ntb_peer_mw_count(tc->ntb), MAX_MWS);
962 	for (i = 0; i < tc->mw_count; i++) {
963 		rc = tool_init_mw(tc, i);
964 		if (rc)
965 			goto err_ctx;
966 	}
967 
968 	tool_setup_dbgfs(tc);
969 
970 	rc = ntb_set_ctx(ntb, tc, &tool_ops);
971 	if (rc)
972 		goto err_ctx;
973 
974 	ntb_link_enable(ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
975 	ntb_link_event(ntb);
976 
977 	return 0;
978 
979 err_ctx:
980 	tool_free_mws(tc);
981 	debugfs_remove_recursive(tc->dbgfs);
982 	kfree(tc);
983 err_tc:
984 	return rc;
985 }
986 
987 static void tool_remove(struct ntb_client *self, struct ntb_dev *ntb)
988 {
989 	struct tool_ctx *tc = ntb->ctx;
990 
991 	tool_free_mws(tc);
992 
993 	ntb_clear_ctx(ntb);
994 	ntb_link_disable(ntb);
995 
996 	debugfs_remove_recursive(tc->dbgfs);
997 	kfree(tc);
998 }
999 
1000 static struct ntb_client tool_client = {
1001 	.ops = {
1002 		.probe = tool_probe,
1003 		.remove = tool_remove,
1004 	},
1005 };
1006 
1007 static int __init tool_init(void)
1008 {
1009 	int rc;
1010 
1011 	if (debugfs_initialized())
1012 		tool_dbgfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
1013 
1014 	rc = ntb_register_client(&tool_client);
1015 	if (rc)
1016 		goto err_client;
1017 
1018 	return 0;
1019 
1020 err_client:
1021 	debugfs_remove_recursive(tool_dbgfs);
1022 	return rc;
1023 }
1024 module_init(tool_init);
1025 
1026 static void __exit tool_exit(void)
1027 {
1028 	ntb_unregister_client(&tool_client);
1029 	debugfs_remove_recursive(tool_dbgfs);
1030 }
1031 module_exit(tool_exit);
1032