]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ioat/ioat_test.c
Update from svn-1.8.14 to 1.9.2.
[FreeBSD/FreeBSD.git] / sys / dev / ioat / ioat_test.c
1 /*-
2  * Copyright (C) 2012 Intel Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/conf.h>
34 #include <sys/ioccom.h>
35 #include <sys/kernel.h>
36 #include <sys/lock.h>
37 #include <sys/malloc.h>
38 #include <sys/module.h>
39 #include <sys/mutex.h>
40 #include <sys/rman.h>
41 #include <sys/sysctl.h>
42 #include <dev/pci/pcireg.h>
43 #include <dev/pci/pcivar.h>
44 #include <machine/bus.h>
45 #include <machine/resource.h>
46 #include <vm/vm.h>
47 #include <vm/pmap.h>
48
49 #include "ioat.h"
50 #include "ioat_hw.h"
51 #include "ioat_internal.h"
52 #include "ioat_test.h"
53
54 MALLOC_DEFINE(M_IOAT_TEST, "ioat_test", "ioat test allocations");
55
56 #define IOAT_TEST_SIZE  0x40000
57 #define IOAT_MAX_BUFS   8
58
59 struct test_transaction {
60         uint8_t                 num_buffers;
61         void                    *buf[IOAT_MAX_BUFS];
62         uint32_t                length;
63         struct ioat_test        *test;
64 };
65
66 static int g_thread_index = 1;
67 static struct cdev *g_ioat_cdev = NULL;
68
69 static void
70 ioat_test_transaction_destroy(struct test_transaction *tx)
71 {
72         int i;
73
74         for (i = 0; i < IOAT_MAX_BUFS; i++) {
75                 if (tx->buf[i] != NULL) {
76                         contigfree(tx->buf[i], IOAT_TEST_SIZE, M_IOAT_TEST);
77                         tx->buf[i] = NULL;
78                 }
79         }
80
81         free(tx, M_IOAT_TEST);
82 }
83
84 static struct
85 test_transaction *ioat_test_transaction_create(uint8_t num_buffers,
86     uint32_t buffer_size)
87 {
88         struct test_transaction *tx;
89         int i;
90
91         tx = malloc(sizeof(struct test_transaction), M_IOAT_TEST, M_NOWAIT | M_ZERO);
92         if (tx == NULL)
93                 return (NULL);
94
95         tx->num_buffers = num_buffers;
96         tx->length = buffer_size;
97
98         for (i = 0; i < num_buffers; i++) {
99                 tx->buf[i] = contigmalloc(buffer_size, M_IOAT_TEST, M_NOWAIT,
100                     0, BUS_SPACE_MAXADDR, PAGE_SIZE, 0);
101
102                 if (tx->buf[i] == NULL) {
103                         ioat_test_transaction_destroy(tx);
104                         return (NULL);
105                 }
106         }
107         return (tx);
108 }
109
110 static void
111 ioat_dma_test_callback(void *arg)
112 {
113         struct test_transaction *tx;
114         struct ioat_test *test;
115
116         tx = arg;
117         test = tx->test;
118
119         if (memcmp(tx->buf[0], tx->buf[1], tx->length) != 0) {
120                 ioat_log_message(0, "miscompare found\n");
121                 test->status = IOAT_TEST_MISCOMPARE;
122         }
123         atomic_add_32(&test->num_completions, 1);
124         ioat_test_transaction_destroy(tx);
125         if (test->num_completions == test->num_loops)
126                 wakeup(test);
127 }
128
129 static void
130 ioat_dma_test(void *arg)
131 {
132         struct test_transaction *tx;
133         struct ioat_test *test;
134         bus_dmaengine_t dmaengine;
135         uint32_t loops;
136         int index, i;
137
138         test = arg;
139         loops = test->num_loops;
140
141         test->status = IOAT_TEST_OK;
142         test->num_completions = 0;
143
144         index = g_thread_index++;
145         dmaengine = ioat_get_dmaengine(test->channel_index);
146
147         if (dmaengine == NULL) {
148                 ioat_log_message(0, "Couldn't acquire dmaengine\n");
149                 test->status = IOAT_TEST_NO_DMA_ENGINE;
150                 return;
151         }
152
153         ioat_log_message(0, "Thread %d: num_loops remaining: 0x%07x\n", index,
154             test->num_loops);
155
156         for (loops = 0; loops < test->num_loops; loops++) {
157                 bus_addr_t src, dest;
158
159                 if (loops % 0x10000 == 0) {
160                         ioat_log_message(0, "Thread %d: "
161                             "num_loops remaining: 0x%07x\n", index,
162                             test->num_loops - loops);
163                 }
164
165                 tx = ioat_test_transaction_create(2, IOAT_TEST_SIZE);
166                 if (tx == NULL) {
167                         ioat_log_message(0, "tx == NULL - memory exhausted\n");
168                         atomic_add_32(&test->num_completions, 1);
169                         test->status = IOAT_TEST_NO_MEMORY;
170                         continue;
171                 }
172
173                 tx->test = test;
174                 wmb();
175
176                 /* fill in source buffer */
177                 for (i = 0; i < (IOAT_TEST_SIZE / sizeof(uint32_t)); i++) {
178                         uint32_t val = i + (loops << 16) + (index << 28);
179                         ((uint32_t *)tx->buf[0])[i] = ~val;
180                         ((uint32_t *)tx->buf[1])[i] = val;
181                 }
182
183                 src = pmap_kextract((vm_offset_t)tx->buf[0]);
184                 dest = pmap_kextract((vm_offset_t)tx->buf[1]);
185
186                 ioat_acquire(dmaengine);
187                 ioat_copy(dmaengine, src, dest, IOAT_TEST_SIZE,
188                     ioat_dma_test_callback, tx, DMA_INT_EN);
189                 ioat_release(dmaengine);
190         }
191
192         while (test->num_completions < test->num_loops)
193                 tsleep(test, 0, "compl", 5 * hz);
194
195 }
196
197 static int
198 ioat_test_open(struct cdev *dev, int flags, int fmt, struct thread *td)
199 {
200
201         return (0);
202 }
203
204 static int
205 ioat_test_close(struct cdev *dev, int flags, int fmt, struct thread *td)
206 {
207
208         return (0);
209 }
210
211 static int
212 ioat_test_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg, int flag,
213     struct thread *td)
214 {
215
216         switch (cmd) {
217         case IOAT_DMATEST:
218                 ioat_dma_test(arg);
219                 break;
220         default:
221                 return (EINVAL);
222         }
223         return (0);
224 }
225
226 static struct cdevsw ioat_cdevsw = {
227         .d_version =    D_VERSION,
228         .d_flags =      0,
229         .d_open =       ioat_test_open,
230         .d_close =      ioat_test_close,
231         .d_ioctl =      ioat_test_ioctl,
232         .d_name =       "ioat_test",
233 };
234
235 static int
236 sysctl_enable_ioat_test(SYSCTL_HANDLER_ARGS)
237 {
238         int error, enabled;
239
240         enabled = (g_ioat_cdev != NULL);
241         error = sysctl_handle_int(oidp, &enabled, 0, req);
242         if (error != 0 || req->newptr == NULL)
243                 return (error);
244
245         if (enabled != 0 && g_ioat_cdev == NULL) {
246                 g_ioat_cdev = make_dev(&ioat_cdevsw, 0, UID_ROOT, GID_WHEEL,
247                     0600, "ioat_test");
248         } else if (enabled == 0 && g_ioat_cdev != NULL) {
249                 destroy_dev(g_ioat_cdev);
250                 g_ioat_cdev = NULL;
251         }
252         return (0);
253 }
254 SYSCTL_PROC(_hw_ioat, OID_AUTO, enable_ioat_test, CTLTYPE_INT | CTLFLAG_RW,
255     0, 0, sysctl_enable_ioat_test, "I",
256     "Non-zero: Enable the /dev/ioat_test device");