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