| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: swdmover.c,v 1.13 2015/08/20 14:40:17 christos Exp $ */ | | 1 | /* $NetBSD: swdmover.c,v 1.14 2017/01/07 21:11:14 christos Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2002, 2003 Wasabi Systems, Inc. | | 4 | * Copyright (c) 2002, 2003 Wasabi Systems, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. | | 7 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| @@ -39,27 +39,27 @@ | | | @@ -39,27 +39,27 @@ |
39 | * swdmover.c: Software back-end providing the dmover functions | | 39 | * swdmover.c: Software back-end providing the dmover functions |
40 | * mentioned in dmover(9). | | 40 | * mentioned in dmover(9). |
41 | * | | 41 | * |
42 | * This module provides a fallback for cases where no hardware | | 42 | * This module provides a fallback for cases where no hardware |
43 | * data movers are present in a system, and also serves an an | | 43 | * data movers are present in a system, and also serves an an |
44 | * example of how to write a dmover back-end. | | 44 | * example of how to write a dmover back-end. |
45 | * | | 45 | * |
46 | * Note that even through the software dmover doesn't require | | 46 | * Note that even through the software dmover doesn't require |
47 | * interrupts to be blocked, we block them anyway to demonstrate | | 47 | * interrupts to be blocked, we block them anyway to demonstrate |
48 | * the locking protocol. | | 48 | * the locking protocol. |
49 | */ | | 49 | */ |
50 | | | 50 | |
51 | #include <sys/cdefs.h> | | 51 | #include <sys/cdefs.h> |
52 | __KERNEL_RCSID(0, "$NetBSD: swdmover.c,v 1.13 2015/08/20 14:40:17 christos Exp $"); | | 52 | __KERNEL_RCSID(0, "$NetBSD: swdmover.c,v 1.14 2017/01/07 21:11:14 christos Exp $"); |
53 | | | 53 | |
54 | #include <sys/param.h> | | 54 | #include <sys/param.h> |
55 | #include <sys/kthread.h> | | 55 | #include <sys/kthread.h> |
56 | #include <sys/systm.h> | | 56 | #include <sys/systm.h> |
57 | #include <sys/uio.h> | | 57 | #include <sys/uio.h> |
58 | | | 58 | |
59 | #include <dev/dmover/dmovervar.h> | | 59 | #include <dev/dmover/dmovervar.h> |
60 | | | 60 | |
61 | #include "ioconf.h" | | 61 | #include "ioconf.h" |
62 | | | 62 | |
63 | struct swdmover_function { | | 63 | struct swdmover_function { |
64 | void (*sdf_process)(struct dmover_request *); | | 64 | void (*sdf_process)(struct dmover_request *); |
65 | }; | | 65 | }; |
| @@ -137,42 +137,41 @@ swdmover_thread(void *arg) | | | @@ -137,42 +137,41 @@ swdmover_thread(void *arg) |
137 | static void | | 137 | static void |
138 | swdmover_func_zero_process(struct dmover_request *dreq) | | 138 | swdmover_func_zero_process(struct dmover_request *dreq) |
139 | { | | 139 | { |
140 | | | 140 | |
141 | switch (dreq->dreq_outbuf_type) { | | 141 | switch (dreq->dreq_outbuf_type) { |
142 | case DMOVER_BUF_LINEAR: | | 142 | case DMOVER_BUF_LINEAR: |
143 | memset(dreq->dreq_outbuf.dmbuf_linear.l_addr, 0, | | 143 | memset(dreq->dreq_outbuf.dmbuf_linear.l_addr, 0, |
144 | dreq->dreq_outbuf.dmbuf_linear.l_len); | | 144 | dreq->dreq_outbuf.dmbuf_linear.l_len); |
145 | break; | | 145 | break; |
146 | | | 146 | |
147 | case DMOVER_BUF_UIO: | | 147 | case DMOVER_BUF_UIO: |
148 | { | | 148 | { |
149 | struct uio *uio = dreq->dreq_outbuf.dmbuf_uio; | | 149 | struct uio *uio = dreq->dreq_outbuf.dmbuf_uio; |
150 | char *cp; | | 150 | char cp[1024]; |
151 | size_t count, buflen; | | 151 | size_t count, buflen; |
152 | int error; | | 152 | int error; |
153 | | | 153 | |
154 | if (uio->uio_rw != UIO_READ) { | | 154 | if (uio->uio_rw != UIO_READ) { |
155 | /* XXXLOCK */ | | 155 | /* XXXLOCK */ |
156 | dreq->dreq_error = EINVAL; | | 156 | dreq->dreq_error = EINVAL; |
157 | dreq->dreq_flags |= DMOVER_REQ_ERROR; | | 157 | dreq->dreq_flags |= DMOVER_REQ_ERROR; |
158 | /* XXXUNLOCK */ | | 158 | /* XXXUNLOCK */ |
159 | break; | | 159 | break; |
160 | } | | 160 | } |
161 | | | 161 | |
162 | buflen = uio->uio_resid; | | 162 | buflen = uio->uio_resid; |
163 | if (buflen > 1024) | | 163 | if (buflen > sizeof(cp)) |
164 | buflen = 1024; | | 164 | buflen = sizeof(cp); |
165 | cp = alloca(buflen); | | | |
166 | memset(cp, 0, buflen); | | 165 | memset(cp, 0, buflen); |
167 | | | 166 | |
168 | while ((count = uio->uio_resid) != 0) { | | 167 | while ((count = uio->uio_resid) != 0) { |
169 | if (count > buflen) | | 168 | if (count > buflen) |
170 | count = buflen; | | 169 | count = buflen; |
171 | error = uiomove(cp, count, uio); | | 170 | error = uiomove(cp, count, uio); |
172 | if (error) { | | 171 | if (error) { |
173 | /* XXXLOCK */ | | 172 | /* XXXLOCK */ |
174 | dreq->dreq_error = error; | | 173 | dreq->dreq_error = error; |
175 | dreq->dreq_flags |= DMOVER_REQ_ERROR; | | 174 | dreq->dreq_flags |= DMOVER_REQ_ERROR; |
176 | /* XXXUNLOCK */ | | 175 | /* XXXUNLOCK */ |
177 | break; | | 176 | break; |
178 | } | | 177 | } |
| @@ -199,42 +198,41 @@ static void | | | @@ -199,42 +198,41 @@ static void |
199 | swdmover_func_fill8_process(struct dmover_request *dreq) | | 198 | swdmover_func_fill8_process(struct dmover_request *dreq) |
200 | { | | 199 | { |
201 | | | 200 | |
202 | switch (dreq->dreq_outbuf_type) { | | 201 | switch (dreq->dreq_outbuf_type) { |
203 | case DMOVER_BUF_LINEAR: | | 202 | case DMOVER_BUF_LINEAR: |
204 | memset(dreq->dreq_outbuf.dmbuf_linear.l_addr, | | 203 | memset(dreq->dreq_outbuf.dmbuf_linear.l_addr, |
205 | dreq->dreq_immediate[0], | | 204 | dreq->dreq_immediate[0], |
206 | dreq->dreq_outbuf.dmbuf_linear.l_len); | | 205 | dreq->dreq_outbuf.dmbuf_linear.l_len); |
207 | break; | | 206 | break; |
208 | | | 207 | |
209 | case DMOVER_BUF_UIO: | | 208 | case DMOVER_BUF_UIO: |
210 | { | | 209 | { |
211 | struct uio *uio = dreq->dreq_outbuf.dmbuf_uio; | | 210 | struct uio *uio = dreq->dreq_outbuf.dmbuf_uio; |
212 | char *cp; | | 211 | char cp[1024]; |
213 | size_t count, buflen; | | 212 | size_t count, buflen; |
214 | int error; | | 213 | int error; |
215 | | | 214 | |
216 | if (uio->uio_rw != UIO_READ) { | | 215 | if (uio->uio_rw != UIO_READ) { |
217 | /* XXXLOCK */ | | 216 | /* XXXLOCK */ |
218 | dreq->dreq_error = EINVAL; | | 217 | dreq->dreq_error = EINVAL; |
219 | dreq->dreq_flags |= DMOVER_REQ_ERROR; | | 218 | dreq->dreq_flags |= DMOVER_REQ_ERROR; |
220 | /* XXXUNLOCK */ | | 219 | /* XXXUNLOCK */ |
221 | break; | | 220 | break; |
222 | } | | 221 | } |
223 | | | 222 | |
224 | buflen = uio->uio_resid; | | 223 | buflen = uio->uio_resid; |
225 | if (buflen > 1024) | | 224 | if (buflen > sizeof(cp)) |
226 | buflen = 1024; | | 225 | buflen = sizeof(cp); |
227 | cp = alloca(buflen); | | | |
228 | memset(cp, dreq->dreq_immediate[0], buflen); | | 226 | memset(cp, dreq->dreq_immediate[0], buflen); |
229 | | | 227 | |
230 | while ((count = uio->uio_resid) != 0) { | | 228 | while ((count = uio->uio_resid) != 0) { |
231 | if (count > buflen) | | 229 | if (count > buflen) |
232 | count = buflen; | | 230 | count = buflen; |
233 | error = uiomove(cp, count, uio); | | 231 | error = uiomove(cp, count, uio); |
234 | if (error) { | | 232 | if (error) { |
235 | /* XXXLOCK */ | | 233 | /* XXXLOCK */ |
236 | dreq->dreq_error = error; | | 234 | dreq->dreq_error = error; |
237 | dreq->dreq_flags |= DMOVER_REQ_ERROR; | | 235 | dreq->dreq_flags |= DMOVER_REQ_ERROR; |
238 | /* XXXUNLOCK */ | | 236 | /* XXXUNLOCK */ |
239 | break; | | 237 | break; |
240 | } | | 238 | } |
| @@ -324,45 +322,43 @@ swdmover_func_xor_process(struct dmover_ | | | @@ -324,45 +322,43 @@ swdmover_func_xor_process(struct dmover_ |
324 | *dst8 ^= *src8; | | 322 | *dst8 ^= *src8; |
325 | } | | 323 | } |
326 | dst8++; | | 324 | dst8++; |
327 | } | | 325 | } |
328 | } | | 326 | } |
329 | | | 327 | |
330 | break; | | 328 | break; |
331 | | | 329 | |
332 | case DMOVER_BUF_UIO: | | 330 | case DMOVER_BUF_UIO: |
333 | { | | 331 | { |
334 | struct uio *uio_out = dreq->dreq_outbuf.dmbuf_uio; | | 332 | struct uio *uio_out = dreq->dreq_outbuf.dmbuf_uio; |
335 | struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio; | | 333 | struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio; |
336 | struct uio *uio; | | 334 | struct uio *uio; |
337 | char *cp, *dst; | | 335 | char cp[1024], dst[1024]; |
338 | size_t count, buflen; | | 336 | size_t count, buflen; |
339 | int error; | | 337 | int error; |
340 | | | 338 | |
341 | if (uio_in->uio_rw != UIO_WRITE || | | 339 | if (uio_in->uio_rw != UIO_WRITE || |
342 | uio_out->uio_rw != UIO_READ || | | 340 | uio_out->uio_rw != UIO_READ || |
343 | uio_in->uio_resid != uio_out->uio_resid) { | | 341 | uio_in->uio_resid != uio_out->uio_resid) { |
344 | /* XXXLOCK */ | | 342 | /* XXXLOCK */ |
345 | dreq->dreq_error = EINVAL; | | 343 | dreq->dreq_error = EINVAL; |
346 | dreq->dreq_flags |= DMOVER_REQ_ERROR; | | 344 | dreq->dreq_flags |= DMOVER_REQ_ERROR; |
347 | /* XXXUNLOCK */ | | 345 | /* XXXUNLOCK */ |
348 | break; | | 346 | break; |
349 | } | | 347 | } |
350 | | | 348 | |
351 | buflen = uio_in->uio_resid; | | 349 | buflen = uio_in->uio_resid; |
352 | if (buflen > 1024) | | 350 | if (buflen > sizeof(cp)) |
353 | buflen = 1024; | | 351 | buflen = sizeof(cp); |
354 | cp = alloca(buflen); | | | |
355 | dst = alloca(buflen); | | | |
356 | | | 352 | |
357 | /* | | 353 | /* |
358 | * For each block, copy first input buffer into the destination | | 354 | * For each block, copy first input buffer into the destination |
359 | * buffer and then read the rest, one by one, into a temporary | | 355 | * buffer and then read the rest, one by one, into a temporary |
360 | * buffer and xor into the destination buffer. After all of | | 356 | * buffer and xor into the destination buffer. After all of |
361 | * the inputs have been xor'd in, move the destination buffer | | 357 | * the inputs have been xor'd in, move the destination buffer |
362 | * out and loop. | | 358 | * out and loop. |
363 | */ | | 359 | */ |
364 | while ((count = uio_in->uio_resid) != 0) { | | 360 | while ((count = uio_in->uio_resid) != 0) { |
365 | if (count > buflen) | | 361 | if (count > buflen) |
366 | count = buflen; | | 362 | count = buflen; |
367 | error = uiomove(dst, count, uio_in); | | 363 | error = uiomove(dst, count, uio_in); |
368 | if (error) { | | 364 | if (error) { |
| @@ -430,44 +426,43 @@ swdmover_func_copy_process(struct dmover | | | @@ -430,44 +426,43 @@ swdmover_func_copy_process(struct dmover |
430 | dreq->dreq_flags |= DMOVER_REQ_ERROR; | | 426 | dreq->dreq_flags |= DMOVER_REQ_ERROR; |
431 | /* XXXUNLOCK */ | | 427 | /* XXXUNLOCK */ |
432 | break; | | 428 | break; |
433 | } | | 429 | } |
434 | memcpy(dreq->dreq_outbuf.dmbuf_linear.l_addr, | | 430 | memcpy(dreq->dreq_outbuf.dmbuf_linear.l_addr, |
435 | dreq->dreq_inbuf[0].dmbuf_linear.l_addr, | | 431 | dreq->dreq_inbuf[0].dmbuf_linear.l_addr, |
436 | dreq->dreq_outbuf.dmbuf_linear.l_len); | | 432 | dreq->dreq_outbuf.dmbuf_linear.l_len); |
437 | break; | | 433 | break; |
438 | | | 434 | |
439 | case DMOVER_BUF_UIO: | | 435 | case DMOVER_BUF_UIO: |
440 | { | | 436 | { |
441 | struct uio *uio_out = dreq->dreq_outbuf.dmbuf_uio; | | 437 | struct uio *uio_out = dreq->dreq_outbuf.dmbuf_uio; |
442 | struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio; | | 438 | struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio; |
443 | char *cp; | | 439 | char cp[1024]; |
444 | size_t count, buflen; | | 440 | size_t count, buflen; |
445 | int error; | | 441 | int error; |
446 | | | 442 | |
447 | if (uio_in->uio_rw != UIO_WRITE || | | 443 | if (uio_in->uio_rw != UIO_WRITE || |
448 | uio_out->uio_rw != UIO_READ || | | 444 | uio_out->uio_rw != UIO_READ || |
449 | uio_in->uio_resid != uio_out->uio_resid) { | | 445 | uio_in->uio_resid != uio_out->uio_resid) { |
450 | /* XXXLOCK */ | | 446 | /* XXXLOCK */ |
451 | dreq->dreq_error = EINVAL; | | 447 | dreq->dreq_error = EINVAL; |
452 | dreq->dreq_flags |= DMOVER_REQ_ERROR; | | 448 | dreq->dreq_flags |= DMOVER_REQ_ERROR; |
453 | /* XXXUNLOCK */ | | 449 | /* XXXUNLOCK */ |
454 | break; | | 450 | break; |
455 | } | | 451 | } |
456 | | | 452 | |
457 | buflen = uio_in->uio_resid; | | 453 | buflen = uio_in->uio_resid; |
458 | if (buflen > 1024) | | 454 | if (buflen > sizeof(cp)) |
459 | buflen = 1024; | | 455 | buflen = sizeof(cp); |
460 | cp = alloca(buflen); | | | |
461 | | | 456 | |
462 | while ((count = uio_in->uio_resid) != 0) { | | 457 | while ((count = uio_in->uio_resid) != 0) { |
463 | if (count > buflen) | | 458 | if (count > buflen) |
464 | count = buflen; | | 459 | count = buflen; |
465 | error = uiomove(cp, count, uio_in); | | 460 | error = uiomove(cp, count, uio_in); |
466 | if (error == 0) | | 461 | if (error == 0) |
467 | error = uiomove(cp, count, uio_out); | | 462 | error = uiomove(cp, count, uio_out); |
468 | if (error) { | | 463 | if (error) { |
469 | /* XXXLOCK */ | | 464 | /* XXXLOCK */ |
470 | dreq->dreq_error = error; | | 465 | dreq->dreq_error = error; |
471 | dreq->dreq_flags |= DMOVER_REQ_ERROR; | | 466 | dreq->dreq_flags |= DMOVER_REQ_ERROR; |
472 | /* XXXUNLOCK */ | | 467 | /* XXXUNLOCK */ |
473 | break; | | 468 | break; |
| @@ -585,42 +580,41 @@ swdmover_func_iscsi_crc32c_process(struc | | | @@ -585,42 +580,41 @@ swdmover_func_iscsi_crc32c_process(struc |
585 | } | | 580 | } |
586 | | | 581 | |
587 | memcpy(&result, dreq->dreq_immediate, sizeof(result)); | | 582 | memcpy(&result, dreq->dreq_immediate, sizeof(result)); |
588 | | | 583 | |
589 | switch (dreq->dreq_inbuf_type) { | | 584 | switch (dreq->dreq_inbuf_type) { |
590 | case DMOVER_BUF_LINEAR: | | 585 | case DMOVER_BUF_LINEAR: |
591 | result = iscsi_crc32c(dreq->dreq_inbuf[0].dmbuf_linear.l_addr, | | 586 | result = iscsi_crc32c(dreq->dreq_inbuf[0].dmbuf_linear.l_addr, |
592 | dreq->dreq_inbuf[0].dmbuf_linear.l_len, result); | | 587 | dreq->dreq_inbuf[0].dmbuf_linear.l_len, result); |
593 | break; | | 588 | break; |
594 | | | 589 | |
595 | case DMOVER_BUF_UIO: | | 590 | case DMOVER_BUF_UIO: |
596 | { | | 591 | { |
597 | struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio; | | 592 | struct uio *uio_in = dreq->dreq_inbuf[0].dmbuf_uio; |
598 | uint8_t *cp; | | 593 | uint8_t cp[1024]; |
599 | size_t count, buflen; | | 594 | size_t count, buflen; |
600 | int error; | | 595 | int error; |
601 | | | 596 | |
602 | if (uio_in->uio_rw != UIO_WRITE) { | | 597 | if (uio_in->uio_rw != UIO_WRITE) { |
603 | /* XXXLOCK */ | | 598 | /* XXXLOCK */ |
604 | dreq->dreq_error = EINVAL; | | 599 | dreq->dreq_error = EINVAL; |
605 | dreq->dreq_flags |= DMOVER_REQ_ERROR; | | 600 | dreq->dreq_flags |= DMOVER_REQ_ERROR; |
606 | /* XXXUNLOCK */ | | 601 | /* XXXUNLOCK */ |
607 | goto done; | | 602 | goto done; |
608 | } | | 603 | } |
609 | | | 604 | |
610 | buflen = uio_in->uio_resid; | | 605 | buflen = uio_in->uio_resid; |
611 | if (buflen > 1024) | | 606 | if (buflen > sizeof(cp)) |
612 | buflen = 1024; | | 607 | buflen = sizeof(cp); |
613 | cp = alloca(buflen); | | | |
614 | | | 608 | |
615 | while ((count = uio_in->uio_resid) != 0) { | | 609 | while ((count = uio_in->uio_resid) != 0) { |
616 | if (count > buflen) | | 610 | if (count > buflen) |
617 | count = buflen; | | 611 | count = buflen; |
618 | error = uiomove(cp, count, uio_in); | | 612 | error = uiomove(cp, count, uio_in); |
619 | if (error) { | | 613 | if (error) { |
620 | /* XXXLOCK */ | | 614 | /* XXXLOCK */ |
621 | dreq->dreq_error = error; | | 615 | dreq->dreq_error = error; |
622 | dreq->dreq_flags |= DMOVER_REQ_ERROR; | | 616 | dreq->dreq_flags |= DMOVER_REQ_ERROR; |
623 | /* XXXUNLOCK */ | | 617 | /* XXXUNLOCK */ |
624 | goto done; | | 618 | goto done; |
625 | } else | | 619 | } else |
626 | result = iscsi_crc32c(cp, count, result); | | 620 | result = iscsi_crc32c(cp, count, result); |