summaryrefslogtreecommitdiffstats
path: root/drivers/ntb/test
diff options
context:
space:
mode:
authorAllen Hubbe <Allen.Hubbe@emc.com>2015-04-15 11:12:41 -0400
committerJon Mason <jdmason@kudzu.us>2015-07-04 14:07:42 -0400
commit963de4739fb4f8fa8d5cd87969109a7d3282ed13 (patch)
treeb64de66fb1eb3eec2b9dfb63a8006b036944ff0a /drivers/ntb/test
parent42fefc86a680f975e2816cd86c4ba50069766ef6 (diff)
NTB: Add ping pong test client
This is a simple ping pong driver that exercises the scratch pads and doorbells of the ntb hardware. This driver may be used to test that your ntb hardware and drivers are functioning at a basic level. Signed-off-by: Allen Hubbe <Allen.Hubbe@emc.com> Signed-off-by: Jon Mason <jdmason@kudzu.us>
Diffstat (limited to 'drivers/ntb/test')
-rw-r--r--drivers/ntb/test/Kconfig8
-rw-r--r--drivers/ntb/test/Makefile1
-rw-r--r--drivers/ntb/test/ntb_pingpong.c250
3 files changed, 259 insertions, 0 deletions
diff --git a/drivers/ntb/test/Kconfig b/drivers/ntb/test/Kconfig
new file mode 100644
index 000000000000..72d255d220c8
--- /dev/null
+++ b/drivers/ntb/test/Kconfig
@@ -0,0 +1,8 @@
1config NTB_PINGPONG
2 tristate "NTB Ping Pong Test Client"
3 help
4 This is a simple ping pong driver that exercises the scratchpads and
5 doorbells of the ntb hardware. This driver may be used to test that
6 your ntb hardware and drivers are functioning at a basic level.
7
8 If unsure, say N.
diff --git a/drivers/ntb/test/Makefile b/drivers/ntb/test/Makefile
new file mode 100644
index 000000000000..b32309307771
--- /dev/null
+++ b/drivers/ntb/test/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_NTB_PINGPONG) += ntb_pingpong.o
diff --git a/drivers/ntb/test/ntb_pingpong.c b/drivers/ntb/test/ntb_pingpong.c
new file mode 100644
index 000000000000..fe1600566981
--- /dev/null
+++ b/drivers/ntb/test/ntb_pingpong.c
@@ -0,0 +1,250 @@
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 Pingpong Linux driver
49 *
50 * Contact Information:
51 * Allen Hubbe <Allen.Hubbe@emc.com>
52 */
53
54/* Note: load this module with option 'dyndbg=+p' */
55
56#include <linux/init.h>
57#include <linux/kernel.h>
58#include <linux/module.h>
59
60#include <linux/dma-mapping.h>
61#include <linux/pci.h>
62#include <linux/slab.h>
63#include <linux/spinlock.h>
64
65#include <linux/ntb.h>
66
67#define DRIVER_NAME "ntb_pingpong"
68#define DRIVER_DESCRIPTION "PCIe NTB Simple Pingpong Client"
69
70#define DRIVER_LICENSE "Dual BSD/GPL"
71#define DRIVER_VERSION "1.0"
72#define DRIVER_RELDATE "24 March 2015"
73#define DRIVER_AUTHOR "Allen Hubbe <Allen.Hubbe@emc.com>"
74
75MODULE_LICENSE(DRIVER_LICENSE);
76MODULE_VERSION(DRIVER_VERSION);
77MODULE_AUTHOR(DRIVER_AUTHOR);
78MODULE_DESCRIPTION(DRIVER_DESCRIPTION);
79
80static unsigned int unsafe;
81module_param(unsafe, uint, 0644);
82MODULE_PARM_DESC(unsafe, "Run even though ntb operations may be unsafe");
83
84static unsigned int delay_ms = 1000;
85module_param(delay_ms, uint, 0644);
86MODULE_PARM_DESC(delay_ms, "Milliseconds to delay the response to peer");
87
88static unsigned long db_init = 0x7;
89module_param(db_init, ulong, 0644);
90MODULE_PARM_DESC(delay_ms, "Initial doorbell bits to ring on the peer");
91
92struct pp_ctx {
93 struct ntb_dev *ntb;
94 u64 db_bits;
95 /* synchronize access to db_bits by ping and pong */
96 spinlock_t db_lock;
97 struct timer_list db_timer;
98 unsigned long db_delay;
99};
100
101static void pp_ping(unsigned long ctx)
102{
103 struct pp_ctx *pp = (void *)ctx;
104 unsigned long irqflags;
105 u64 db_bits, db_mask;
106 u32 spad_rd, spad_wr;
107
108 spin_lock_irqsave(&pp->db_lock, irqflags);
109 {
110 db_mask = ntb_db_valid_mask(pp->ntb);
111 db_bits = ntb_db_read(pp->ntb);
112
113 if (db_bits) {
114 dev_dbg(&pp->ntb->dev,
115 "Masked pongs %#llx\n",
116 db_bits);
117 ntb_db_clear(pp->ntb, db_bits);
118 }
119
120 db_bits = ((pp->db_bits | db_bits) << 1) & db_mask;
121
122 if (!db_bits)
123 db_bits = db_init;
124
125 spad_rd = ntb_spad_read(pp->ntb, 0);
126 spad_wr = spad_rd + 1;
127
128 dev_dbg(&pp->ntb->dev,
129 "Ping bits %#llx read %#x write %#x\n",
130 db_bits, spad_rd, spad_wr);
131
132 ntb_peer_spad_write(pp->ntb, 0, spad_wr);
133 ntb_peer_db_set(pp->ntb, db_bits);
134 ntb_db_clear_mask(pp->ntb, db_mask);
135
136 pp->db_bits = 0;
137 }
138 spin_unlock_irqrestore(&pp->db_lock, irqflags);
139}
140
141static void pp_link_event(void *ctx)
142{
143 struct pp_ctx *pp = ctx;
144
145 if (ntb_link_is_up(pp->ntb, NULL, NULL) == 1) {
146 dev_dbg(&pp->ntb->dev, "link is up\n");
147 pp_ping((unsigned long)pp);
148 } else {
149 dev_dbg(&pp->ntb->dev, "link is down\n");
150 del_timer(&pp->db_timer);
151 }
152}
153
154static void pp_db_event(void *ctx, int vec)
155{
156 struct pp_ctx *pp = ctx;
157 u64 db_bits, db_mask;
158 unsigned long irqflags;
159
160 spin_lock_irqsave(&pp->db_lock, irqflags);
161 {
162 db_mask = ntb_db_vector_mask(pp->ntb, vec);
163 db_bits = db_mask & ntb_db_read(pp->ntb);
164 ntb_db_set_mask(pp->ntb, db_mask);
165 ntb_db_clear(pp->ntb, db_bits);
166
167 pp->db_bits |= db_bits;
168
169 mod_timer(&pp->db_timer, jiffies + pp->db_delay);
170
171 dev_dbg(&pp->ntb->dev,
172 "Pong vec %d bits %#llx\n",
173 vec, db_bits);
174 }
175 spin_unlock_irqrestore(&pp->db_lock, irqflags);
176}
177
178static const struct ntb_ctx_ops pp_ops = {
179 .link_event = pp_link_event,
180 .db_event = pp_db_event,
181};
182
183static int pp_probe(struct ntb_client *client,
184 struct ntb_dev *ntb)
185{
186 struct pp_ctx *pp;
187 int rc;
188
189 if (ntb_db_is_unsafe(ntb)) {
190 dev_dbg(&ntb->dev, "doorbell is unsafe\n");
191 if (!unsafe) {
192 rc = -EINVAL;
193 goto err_pp;
194 }
195 }
196
197 if (ntb_spad_is_unsafe(ntb)) {
198 dev_dbg(&ntb->dev, "scratchpad is unsafe\n");
199 if (!unsafe) {
200 rc = -EINVAL;
201 goto err_pp;
202 }
203 }
204
205 pp = kmalloc(sizeof(*pp), GFP_KERNEL);
206 if (!pp) {
207 rc = -ENOMEM;
208 goto err_pp;
209 }
210
211 pp->ntb = ntb;
212 pp->db_bits = 0;
213 spin_lock_init(&pp->db_lock);
214 setup_timer(&pp->db_timer, pp_ping, (unsigned long)pp);
215 pp->db_delay = msecs_to_jiffies(delay_ms);
216
217 rc = ntb_set_ctx(ntb, pp, &pp_ops);
218 if (rc)
219 goto err_ctx;
220
221 ntb_link_enable(ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
222 ntb_link_event(ntb);
223
224 return 0;
225
226err_ctx:
227 kfree(pp);
228err_pp:
229 return rc;
230}
231
232static void pp_remove(struct ntb_client *client,
233 struct ntb_dev *ntb)
234{
235 struct pp_ctx *pp = ntb->ctx;
236
237 ntb_clear_ctx(ntb);
238 del_timer_sync(&pp->db_timer);
239 ntb_link_disable(ntb);
240
241 kfree(pp);
242}
243
244static struct ntb_client pp_client = {
245 .ops = {
246 .probe = pp_probe,
247 .remove = pp_remove,
248 },
249};
250module_ntb_client(pp_client);